renderer.c revision 859106f196ade77f59f8787b071739901cd1a843
1/**************************************************************************
2 *
3 * Copyright 2009 VMware, Inc.  All Rights Reserved.
4 * Copyright 2010 LunarG, Inc.  All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28#include "renderer.h"
29
30#include "vg_context.h"
31#include "image.h"
32
33#include "pipe/p_context.h"
34#include "pipe/p_state.h"
35#include "util/u_inlines.h"
36#include "pipe/p_screen.h"
37#include "pipe/p_shader_tokens.h"
38
39#include "util/u_draw_quad.h"
40#include "util/u_simple_shaders.h"
41#include "util/u_memory.h"
42#include "util/u_sampler.h"
43#include "util/u_surface.h"
44#include "util/u_math.h"
45#include "util/u_format.h"
46
47#include "cso_cache/cso_context.h"
48#include "tgsi/tgsi_ureg.h"
49
50typedef enum {
51   RENDERER_STATE_INIT,
52   RENDERER_STATE_COPY,
53   RENDERER_STATE_DRAWTEX,
54   RENDERER_STATE_SCISSOR,
55   RENDERER_STATE_CLEAR,
56   RENDERER_STATE_FILTER,
57   RENDERER_STATE_POLYGON_STENCIL,
58   RENDERER_STATE_POLYGON_FILL,
59   NUM_RENDERER_STATES
60} RendererState;
61
62typedef enum {
63   RENDERER_VS_PLAIN,
64   RENDERER_VS_COLOR,
65   RENDERER_VS_TEXTURE,
66   NUM_RENDERER_VS
67} RendererVs;
68
69typedef enum {
70   RENDERER_FS_COLOR,
71   RENDERER_FS_TEXTURE,
72   RENDERER_FS_SCISSOR,
73   RENDERER_FS_WHITE,
74   NUM_RENDERER_FS
75} RendererFs;
76
77struct renderer {
78   struct pipe_context *pipe;
79   struct cso_context *cso;
80
81   VGbitfield dirty;
82   struct {
83      struct pipe_rasterizer_state rasterizer;
84      struct pipe_depth_stencil_alpha_state dsa;
85      struct pipe_framebuffer_state fb;
86   } g3d;
87   struct matrix projection;
88
89   struct matrix mvp;
90   struct pipe_resource *vs_cbuf;
91
92   struct pipe_resource *fs_cbuf;
93   VGfloat fs_cbuf_data[32];
94   VGint fs_cbuf_len;
95
96   struct pipe_vertex_element velems[2];
97   VGfloat vertices[4][2][4];
98
99   void *cached_vs[NUM_RENDERER_VS];
100   void *cached_fs[NUM_RENDERER_FS];
101
102   RendererState state;
103
104   /* state data */
105   union {
106      struct {
107         VGint tex_width;
108         VGint tex_height;
109      } copy;
110
111      struct {
112         VGint tex_width;
113         VGint tex_height;
114      } drawtex;
115
116      struct {
117         VGboolean restore_dsa;
118      } scissor;
119
120      struct {
121         VGboolean use_sampler;
122         VGint tex_width, tex_height;
123      } filter;
124
125      struct {
126         struct pipe_depth_stencil_alpha_state dsa;
127         VGboolean manual_two_sides;
128         VGboolean restore_dsa;
129      } polygon_stencil;
130   } u;
131};
132
133/**
134 * Return VG_TRUE if the renderer can use the resource as the asked bindings.
135 */
136static VGboolean renderer_can_support(struct renderer *renderer,
137                                      struct pipe_resource *res,
138                                      unsigned bindings)
139{
140   struct pipe_screen *screen = renderer->pipe->screen;
141
142   return screen->is_format_supported(screen,
143         res->format, res->target, 0, bindings, 0);
144}
145
146/**
147 * Set the model-view-projection matrix used by vertex shaders.
148 */
149static void renderer_set_mvp(struct renderer *renderer,
150                             const struct matrix *mvp)
151{
152   struct matrix *cur = &renderer->mvp;
153   struct pipe_resource *cbuf;
154   VGfloat consts[3][4];
155   VGint i;
156
157   /* projection only */
158   if (!mvp)
159      mvp = &renderer->projection;
160
161   /* re-upload only if necessary */
162   if (memcmp(cur, mvp, sizeof(*mvp)) == 0)
163      return;
164
165   /* 3x3 matrix to 3 constant vectors (no Z) */
166   for (i = 0; i < 3; i++) {
167      consts[i][0] = mvp->m[i + 0];
168      consts[i][1] = mvp->m[i + 3];
169      consts[i][2] = 0.0f;
170      consts[i][3] = mvp->m[i + 6];
171   }
172
173   cbuf = renderer->vs_cbuf;
174   pipe_resource_reference(&cbuf, NULL);
175   cbuf = pipe_buffer_create(renderer->pipe->screen,
176                             PIPE_BIND_CONSTANT_BUFFER,
177                             sizeof(consts));
178   if (cbuf) {
179      pipe_buffer_write(renderer->pipe, cbuf,
180            0, sizeof(consts), consts);
181   }
182   renderer->pipe->set_constant_buffer(renderer->pipe,
183         PIPE_SHADER_VERTEX, 0, cbuf);
184
185   memcpy(cur, mvp, sizeof(*mvp));
186   renderer->vs_cbuf = cbuf;
187}
188
189/**
190 * Create a simple vertex shader that passes through position and the given
191 * attribute.
192 */
193static void *create_passthrough_vs(struct pipe_context *pipe, int semantic_name)
194{
195   struct ureg_program *ureg;
196   struct ureg_src src[2], constants[3];
197   struct ureg_dst dst[2], tmp;
198   int i;
199
200   ureg = ureg_create(TGSI_PROCESSOR_VERTEX);
201   if (!ureg)
202      return NULL;
203
204   /* position is in user coordinates */
205   src[0] = ureg_DECL_vs_input(ureg, 0);
206   dst[0] = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
207   tmp = ureg_DECL_temporary(ureg);
208   for (i = 0; i < Elements(constants); i++)
209      constants[i] = ureg_DECL_constant(ureg, i);
210
211   /* transform to clipped coordinates */
212   ureg_DP4(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), src[0], constants[0]);
213   ureg_DP4(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Y), src[0], constants[1]);
214   ureg_MOV(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Z), src[0]);
215   ureg_DP4(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_W), src[0], constants[2]);
216   ureg_MOV(ureg, dst[0], ureg_src(tmp));
217
218   if (semantic_name >= 0) {
219      src[1] = ureg_DECL_vs_input(ureg, 1);
220      dst[1] = ureg_DECL_output(ureg, semantic_name, 0);
221      ureg_MOV(ureg, dst[1], src[1]);
222   }
223
224   ureg_END(ureg);
225
226   return ureg_create_shader_and_destroy(ureg, pipe);
227}
228
229/**
230 * Set renderer vertex shader.
231 *
232 * This function modifies vertex_shader state.
233 */
234static void renderer_set_vs(struct renderer *r, RendererVs id)
235{
236   /* create as needed */
237   if (!r->cached_vs[id]) {
238      int semantic_name = -1;
239
240      switch (id) {
241      case RENDERER_VS_PLAIN:
242         break;
243      case RENDERER_VS_COLOR:
244         semantic_name = TGSI_SEMANTIC_COLOR;
245         break;
246      case RENDERER_VS_TEXTURE:
247         semantic_name = TGSI_SEMANTIC_GENERIC;
248         break;
249      default:
250         assert(!"Unknown renderer vs id");
251         break;
252      }
253
254      r->cached_vs[id] = create_passthrough_vs(r->pipe, semantic_name);
255   }
256
257   cso_set_vertex_shader_handle(r->cso, r->cached_vs[id]);
258}
259
260/**
261 * Create a simple fragment shader that sets the depth to 0.0f.
262 */
263static void *create_scissor_fs(struct pipe_context *pipe)
264{
265   struct ureg_program *ureg;
266   struct ureg_dst out;
267   struct ureg_src imm;
268
269   ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
270   out = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
271   imm = ureg_imm4f(ureg, 0.0f, 0.0f, 0.0f, 0.0f);
272
273   ureg_MOV(ureg, ureg_writemask(out, TGSI_WRITEMASK_Z), imm);
274   ureg_END(ureg);
275
276   return ureg_create_shader_and_destroy(ureg, pipe);
277}
278
279/**
280 * Create a simple fragment shader that sets the color to white.
281 */
282static void *create_white_fs(struct pipe_context *pipe)
283{
284   struct ureg_program *ureg;
285   struct ureg_dst out;
286   struct ureg_src imm;
287
288   ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
289   out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
290   imm = ureg_imm4f(ureg, 1.0f, 1.0f, 1.0f, 1.0f);
291
292   ureg_MOV(ureg, out, imm);
293   ureg_END(ureg);
294
295   return ureg_create_shader_and_destroy(ureg, pipe);
296}
297
298/**
299 * Set renderer fragment shader.
300 *
301 * This function modifies fragment_shader state.
302 */
303static void renderer_set_fs(struct renderer *r, RendererFs id)
304{
305   /* create as needed */
306   if (!r->cached_fs[id]) {
307      void *fs = NULL;
308
309      switch (id) {
310      case RENDERER_FS_COLOR:
311         fs = util_make_fragment_passthrough_shader(r->pipe);
312         break;
313      case RENDERER_FS_TEXTURE:
314         fs = util_make_fragment_tex_shader(r->pipe,
315               TGSI_TEXTURE_2D, TGSI_INTERPOLATE_LINEAR);
316         break;
317      case RENDERER_FS_SCISSOR:
318         fs = create_scissor_fs(r->pipe);
319         break;
320      case RENDERER_FS_WHITE:
321         fs = create_white_fs(r->pipe);
322         break;
323      default:
324         assert(!"Unknown renderer fs id");
325         break;
326      }
327
328      r->cached_fs[id] = fs;
329   }
330
331   cso_set_fragment_shader_handle(r->cso, r->cached_fs[id]);
332}
333
334typedef enum {
335   VEGA_Y0_TOP,
336   VEGA_Y0_BOTTOM
337} VegaOrientation;
338
339static void vg_set_viewport(struct renderer *r,
340                            VegaOrientation orientation)
341{
342   const struct pipe_framebuffer_state *fb = &r->g3d.fb;
343   struct pipe_viewport_state viewport;
344   VGfloat y_scale = (orientation == VEGA_Y0_BOTTOM) ? -2.f : 2.f;
345
346   viewport.scale[0] =  fb->width / 2.f;
347   viewport.scale[1] =  fb->height / y_scale;
348   viewport.scale[2] =  1.0;
349   viewport.scale[3] =  1.0;
350   viewport.translate[0] = fb->width / 2.f;
351   viewport.translate[1] = fb->height / 2.f;
352   viewport.translate[2] = 0.0;
353   viewport.translate[3] = 0.0;
354
355   cso_set_viewport(r->cso, &viewport);
356}
357
358/**
359 * Set renderer target.
360 *
361 * This function modifies framebuffer and viewport states.
362 */
363static void renderer_set_target(struct renderer *r,
364                                struct pipe_surface *cbuf,
365                                struct pipe_surface *zsbuf,
366                                VGboolean y0_top)
367{
368   struct pipe_framebuffer_state fb;
369
370   memset(&fb, 0, sizeof(fb));
371   fb.width = cbuf->width;
372   fb.height = cbuf->height;
373   fb.cbufs[0] = cbuf;
374   fb.nr_cbufs = 1;
375   fb.zsbuf = zsbuf;
376   cso_set_framebuffer(r->cso, &fb);
377
378   vg_set_viewport(r, (y0_top) ? VEGA_Y0_TOP : VEGA_Y0_BOTTOM);
379}
380
381/**
382 * Set renderer blend state.  Blending is disabled.
383 *
384 * This function modifies blend state.
385 */
386static void renderer_set_blend(struct renderer *r,
387                               VGbitfield channel_mask)
388{
389   struct pipe_blend_state blend;
390
391   memset(&blend, 0, sizeof(blend));
392
393   blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
394   blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
395   blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
396   blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
397
398   if (channel_mask & VG_RED)
399      blend.rt[0].colormask |= PIPE_MASK_R;
400   if (channel_mask & VG_GREEN)
401      blend.rt[0].colormask |= PIPE_MASK_G;
402   if (channel_mask & VG_BLUE)
403      blend.rt[0].colormask |= PIPE_MASK_B;
404   if (channel_mask & VG_ALPHA)
405      blend.rt[0].colormask |= PIPE_MASK_A;
406
407   cso_set_blend(r->cso, &blend);
408}
409
410/**
411 * Set renderer sampler and view states.
412 *
413 * This function modifies samplers and fragment_sampler_views states.
414 */
415static void renderer_set_samplers(struct renderer *r,
416                                  uint num_views,
417                                  struct pipe_sampler_view **views)
418{
419   struct pipe_sampler_state sampler;
420   unsigned tex_filter = PIPE_TEX_FILTER_NEAREST;
421   unsigned tex_wrap = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
422   uint i;
423
424   memset(&sampler, 0, sizeof(sampler));
425
426   sampler.min_img_filter = tex_filter;
427   sampler.mag_img_filter = tex_filter;
428   sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
429
430   sampler.wrap_s = tex_wrap;
431   sampler.wrap_t = tex_wrap;
432   sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
433
434   sampler.normalized_coords = 1;
435
436   /* set samplers */
437   for (i = 0; i < num_views; i++)
438      cso_single_sampler(r->cso, i, &sampler);
439   cso_single_sampler_done(r->cso);
440
441   /* set views */
442   cso_set_fragment_sampler_views(r->cso, num_views, views);
443}
444
445/**
446 * Set custom renderer fragment shader, and optionally set samplers and views
447 * and upload the fragment constant buffer.
448 *
449 * This function modifies fragment_shader, samplers and fragment_sampler_views
450 * states.
451 */
452static void renderer_set_custom_fs(struct renderer *renderer,
453                                   void *fs,
454                                   const struct pipe_sampler_state **samplers,
455                                   struct pipe_sampler_view **views,
456                                   VGint num_samplers,
457                                   const void *const_buffer,
458                                   VGint const_buffer_len)
459{
460   cso_set_fragment_shader_handle(renderer->cso, fs);
461
462   /* set samplers and views */
463   if (num_samplers) {
464      cso_set_samplers(renderer->cso, num_samplers, samplers);
465      cso_set_fragment_sampler_views(renderer->cso, num_samplers, views);
466   }
467
468   /* upload fs constant buffer */
469   if (const_buffer_len) {
470      struct pipe_resource *cbuf = renderer->fs_cbuf;
471
472      if (!cbuf || renderer->fs_cbuf_len != const_buffer_len ||
473          memcmp(renderer->fs_cbuf_data, const_buffer, const_buffer_len)) {
474         pipe_resource_reference(&cbuf, NULL);
475
476         cbuf = pipe_buffer_create(renderer->pipe->screen,
477               PIPE_BIND_CONSTANT_BUFFER, const_buffer_len);
478         pipe_buffer_write(renderer->pipe, cbuf, 0,
479               const_buffer_len, const_buffer);
480         renderer->pipe->set_constant_buffer(renderer->pipe,
481               PIPE_SHADER_FRAGMENT, 0, cbuf);
482
483         renderer->fs_cbuf = cbuf;
484         if (const_buffer_len <= sizeof(renderer->fs_cbuf_data)) {
485            memcpy(renderer->fs_cbuf_data, const_buffer, const_buffer_len);
486            renderer->fs_cbuf_len = const_buffer_len;
487         }
488         else {
489            renderer->fs_cbuf_len = 0;
490         }
491      }
492   }
493}
494
495/**
496 * Setup renderer quad position.
497 */
498static void renderer_quad_pos(struct renderer *r,
499                              VGfloat x0, VGfloat y0,
500                              VGfloat x1, VGfloat y1,
501                              VGboolean scissor)
502{
503   VGfloat z;
504
505   /* the depth test is used for scissoring */
506   z = (scissor) ? 0.0f : 1.0f;
507
508   /* positions */
509   r->vertices[0][0][0] = x0;
510   r->vertices[0][0][1] = y0;
511   r->vertices[0][0][2] = z;
512
513   r->vertices[1][0][0] = x1;
514   r->vertices[1][0][1] = y0;
515   r->vertices[1][0][2] = z;
516
517   r->vertices[2][0][0] = x1;
518   r->vertices[2][0][1] = y1;
519   r->vertices[2][0][2] = z;
520
521   r->vertices[3][0][0] = x0;
522   r->vertices[3][0][1] = y1;
523   r->vertices[3][0][2] = z;
524}
525
526/**
527 * Setup renderer quad texture coordinates.
528 */
529static void renderer_quad_texcoord(struct renderer *r,
530                                   VGfloat x0, VGfloat y0,
531                                   VGfloat x1, VGfloat y1,
532                                   VGint tex_width, VGint tex_height)
533{
534   VGfloat s0, t0, s1, t1, r0, q0;
535   VGint i;
536
537   s0 = x0 / tex_width;
538   s1 = x1 / tex_width;
539   t0 = y0 / tex_height;
540   t1 = y1 / tex_height;
541   r0 = 0.0f;
542   q0 = 1.0f;
543
544   /* texcoords */
545   r->vertices[0][1][0] = s0;
546   r->vertices[0][1][1] = t0;
547
548   r->vertices[1][1][0] = s1;
549   r->vertices[1][1][1] = t0;
550
551   r->vertices[2][1][0] = s1;
552   r->vertices[2][1][1] = t1;
553
554   r->vertices[3][1][0] = s0;
555   r->vertices[3][1][1] = t1;
556
557   for (i = 0; i < 4; i++) {
558      r->vertices[i][1][2] = r0;
559      r->vertices[i][1][3] = q0;
560   }
561}
562
563/**
564 * Draw renderer quad.
565 */
566static void renderer_quad_draw(struct renderer *r)
567{
568   struct pipe_resource *buf;
569
570   buf = pipe_user_buffer_create(r->pipe->screen,
571                                 r->vertices,
572                                 sizeof(r->vertices),
573                                 PIPE_BIND_VERTEX_BUFFER);
574   if (buf) {
575      util_draw_vertex_buffer(r->pipe, buf, 0,
576                              PIPE_PRIM_TRIANGLE_FAN,
577                              Elements(r->vertices),     /* verts */
578                              Elements(r->vertices[0])); /* attribs/vert */
579
580      pipe_resource_reference(&buf, NULL);
581   }
582}
583
584/**
585 * Prepare the renderer for copying.
586 */
587VGboolean renderer_copy_begin(struct renderer *renderer,
588                              struct pipe_surface *dst,
589                              VGboolean y0_top,
590                              struct pipe_sampler_view *src)
591{
592   assert(renderer->state == RENDERER_STATE_INIT);
593
594   /* sanity check */
595   if (!renderer_can_support(renderer,
596            dst->texture, PIPE_BIND_RENDER_TARGET) ||
597       !renderer_can_support(renderer,
598          src->texture, PIPE_BIND_SAMPLER_VIEW))
599      return VG_FALSE;
600
601   cso_save_framebuffer(renderer->cso);
602   cso_save_viewport(renderer->cso);
603   cso_save_blend(renderer->cso);
604   cso_save_samplers(renderer->cso);
605   cso_save_fragment_sampler_views(renderer->cso);
606   cso_save_fragment_shader(renderer->cso);
607   cso_save_vertex_shader(renderer->cso);
608
609   renderer_set_target(renderer, dst, NULL, y0_top);
610
611   renderer_set_blend(renderer, ~0);
612   renderer_set_samplers(renderer, 1, &src);
613
614   renderer_set_fs(renderer, RENDERER_FS_TEXTURE);
615   renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
616
617   renderer_set_mvp(renderer, NULL);
618
619   /* remember the texture size */
620   renderer->u.copy.tex_width = src->texture->width0;
621   renderer->u.copy.tex_height = src->texture->height0;
622   renderer->state = RENDERER_STATE_COPY;
623
624   return VG_TRUE;
625}
626
627/**
628 * Draw into the destination rectangle given by (x, y, w, h).  The texture is
629 * sampled from within the rectangle given by (sx, sy, sw, sh).
630 *
631 * The coordinates are in surface coordinates.
632 */
633void renderer_copy(struct renderer *renderer,
634                   VGint x, VGint y, VGint w, VGint h,
635                   VGint sx, VGint sy, VGint sw, VGint sh)
636{
637   assert(renderer->state == RENDERER_STATE_COPY);
638
639   /* there is no depth buffer for scissoring anyway */
640   renderer_quad_pos(renderer, x, y, x + w, y + h, VG_FALSE);
641   renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
642         renderer->u.copy.tex_width,
643         renderer->u.copy.tex_height);
644
645   renderer_quad_draw(renderer);
646}
647
648/**
649 * End copying and restore the states.
650 */
651void renderer_copy_end(struct renderer *renderer)
652{
653   assert(renderer->state == RENDERER_STATE_COPY);
654
655   cso_restore_framebuffer(renderer->cso);
656   cso_restore_viewport(renderer->cso);
657   cso_restore_blend(renderer->cso);
658   cso_restore_samplers(renderer->cso);
659   cso_restore_fragment_sampler_views(renderer->cso);
660   cso_restore_fragment_shader(renderer->cso);
661   cso_restore_vertex_shader(renderer->cso);
662
663   renderer->state = RENDERER_STATE_INIT;
664}
665
666/**
667 * Prepare the renderer for textured drawing.
668 */
669VGboolean renderer_drawtex_begin(struct renderer *renderer,
670                                 struct pipe_sampler_view *src)
671{
672   assert(renderer->state == RENDERER_STATE_INIT);
673
674   if (!renderer_can_support(renderer, src->texture, PIPE_BIND_SAMPLER_VIEW))
675      return VG_FALSE;
676
677   cso_save_blend(renderer->cso);
678   cso_save_samplers(renderer->cso);
679   cso_save_fragment_sampler_views(renderer->cso);
680   cso_save_fragment_shader(renderer->cso);
681   cso_save_vertex_shader(renderer->cso);
682
683   renderer_set_blend(renderer, ~0);
684
685   renderer_set_samplers(renderer, 1, &src);
686
687   renderer_set_fs(renderer, RENDERER_FS_TEXTURE);
688   renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
689
690   renderer_set_mvp(renderer, NULL);
691
692   /* remember the texture size */
693   renderer->u.drawtex.tex_width = src->texture->width0;
694   renderer->u.drawtex.tex_height = src->texture->height0;
695   renderer->state = RENDERER_STATE_DRAWTEX;
696
697   return VG_TRUE;
698}
699
700/**
701 * Draw into the destination rectangle given by (x, y, w, h).  The texture is
702 * sampled from within the rectangle given by (sx, sy, sw, sh).
703 *
704 * The coordinates are in surface coordinates.
705 */
706void renderer_drawtex(struct renderer *renderer,
707                      VGint x, VGint y, VGint w, VGint h,
708                      VGint sx, VGint sy, VGint sw, VGint sh)
709{
710   assert(renderer->state == RENDERER_STATE_DRAWTEX);
711
712   /* with scissoring */
713   renderer_quad_pos(renderer, x, y, x + w, y + h, VG_TRUE);
714   renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
715         renderer->u.drawtex.tex_width,
716         renderer->u.drawtex.tex_height);
717
718   renderer_quad_draw(renderer);
719}
720
721/**
722 * End textured drawing and restore the states.
723 */
724void renderer_drawtex_end(struct renderer *renderer)
725{
726   assert(renderer->state == RENDERER_STATE_DRAWTEX);
727
728   cso_restore_blend(renderer->cso);
729   cso_restore_samplers(renderer->cso);
730   cso_restore_fragment_sampler_views(renderer->cso);
731   cso_restore_fragment_shader(renderer->cso);
732   cso_restore_vertex_shader(renderer->cso);
733
734   renderer->state = RENDERER_STATE_INIT;
735}
736
737/**
738 * Prepare the renderer for scissor update.  This will reset the depth buffer
739 * to 1.0f.
740 */
741VGboolean renderer_scissor_begin(struct renderer *renderer,
742                                 VGboolean restore_dsa)
743{
744   struct pipe_depth_stencil_alpha_state dsa;
745
746   assert(renderer->state == RENDERER_STATE_INIT);
747
748   if (restore_dsa)
749      cso_save_depth_stencil_alpha(renderer->cso);
750   cso_save_blend(renderer->cso);
751   cso_save_fragment_shader(renderer->cso);
752
753   /* enable depth writes */
754   memset(&dsa, 0, sizeof(dsa));
755   dsa.depth.enabled = 1;
756   dsa.depth.writemask = 1;
757   dsa.depth.func = PIPE_FUNC_ALWAYS;
758   cso_set_depth_stencil_alpha(renderer->cso, &dsa);
759
760   /* disable color writes */
761   renderer_set_blend(renderer, 0);
762   renderer_set_fs(renderer, RENDERER_FS_SCISSOR);
763
764   renderer_set_mvp(renderer, NULL);
765
766   renderer->u.scissor.restore_dsa = restore_dsa;
767   renderer->state = RENDERER_STATE_SCISSOR;
768
769   /* clear the depth buffer to 1.0f */
770   renderer->pipe->clear(renderer->pipe,
771         PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0f, 0);
772
773   return VG_TRUE;
774}
775
776/**
777 * Add a scissor rectangle.  Depth values inside the rectangle will be set to
778 * 0.0f.
779 */
780void renderer_scissor(struct renderer *renderer,
781                      VGint x, VGint y, VGint width, VGint height)
782{
783   assert(renderer->state == RENDERER_STATE_SCISSOR);
784
785   renderer_quad_pos(renderer, x, y, x + width, y + height, VG_FALSE);
786   renderer_quad_draw(renderer);
787}
788
789/**
790 * End scissor update and restore the states.
791 */
792void renderer_scissor_end(struct renderer *renderer)
793{
794   assert(renderer->state == RENDERER_STATE_SCISSOR);
795
796   if (renderer->u.scissor.restore_dsa)
797      cso_restore_depth_stencil_alpha(renderer->cso);
798   cso_restore_blend(renderer->cso);
799   cso_restore_fragment_shader(renderer->cso);
800
801   renderer->state = RENDERER_STATE_INIT;
802}
803
804/**
805 * Prepare the renderer for clearing.
806 */
807VGboolean renderer_clear_begin(struct renderer *renderer)
808{
809   assert(renderer->state == RENDERER_STATE_INIT);
810
811   cso_save_blend(renderer->cso);
812   cso_save_fragment_shader(renderer->cso);
813   cso_save_vertex_shader(renderer->cso);
814
815   renderer_set_blend(renderer, ~0);
816   renderer_set_fs(renderer, RENDERER_FS_COLOR);
817   renderer_set_vs(renderer, RENDERER_VS_COLOR);
818
819   renderer_set_mvp(renderer, NULL);
820
821   renderer->state = RENDERER_STATE_CLEAR;
822
823   return VG_TRUE;
824}
825
826/**
827 * Clear the framebuffer with the specified region and color.
828 *
829 * The coordinates are in surface coordinates.
830 */
831void renderer_clear(struct renderer *renderer,
832                    VGint x, VGint y, VGint width, VGint height,
833                    const VGfloat color[4])
834{
835   VGuint i;
836
837   assert(renderer->state == RENDERER_STATE_CLEAR);
838
839   renderer_quad_pos(renderer, x, y, x + width, y + height, VG_TRUE);
840   for (i = 0; i < 4; i++)
841      memcpy(renderer->vertices[i][1], color, sizeof(VGfloat) * 4);
842
843   renderer_quad_draw(renderer);
844}
845
846/**
847 * End clearing and retore the states.
848 */
849void renderer_clear_end(struct renderer *renderer)
850{
851   assert(renderer->state == RENDERER_STATE_CLEAR);
852
853   cso_restore_blend(renderer->cso);
854   cso_restore_fragment_shader(renderer->cso);
855   cso_restore_vertex_shader(renderer->cso);
856
857   renderer->state = RENDERER_STATE_INIT;
858}
859
860/**
861 * Prepare the renderer for image filtering.
862 */
863VGboolean renderer_filter_begin(struct renderer *renderer,
864                                struct pipe_resource *dst,
865                                VGboolean y0_top,
866                                VGbitfield channel_mask,
867                                const struct pipe_sampler_state **samplers,
868                                struct pipe_sampler_view **views,
869                                VGint num_samplers,
870                                void *fs,
871                                const void *const_buffer,
872                                VGint const_buffer_len)
873{
874   struct pipe_surface *surf, surf_tmpl;
875
876   assert(renderer->state == RENDERER_STATE_INIT);
877
878   if (!fs)
879      return VG_FALSE;
880   if (!renderer_can_support(renderer, dst, PIPE_BIND_RENDER_TARGET))
881      return VG_FALSE;
882
883   u_surface_default_template(&surf_tmpl, dst,
884                              PIPE_BIND_RENDER_TARGET);
885   surf = renderer->pipe->create_surface(renderer->pipe, dst, &surf_tmpl);
886   if (!surf)
887      return VG_FALSE;
888
889   cso_save_framebuffer(renderer->cso);
890   cso_save_viewport(renderer->cso);
891   cso_save_blend(renderer->cso);
892
893   /* set the image as the target */
894   renderer_set_target(renderer, surf, NULL, y0_top);
895   pipe_surface_reference(&surf, NULL);
896
897   renderer_set_blend(renderer, channel_mask);
898
899   if (num_samplers) {
900      struct pipe_resource *tex;
901
902      cso_save_samplers(renderer->cso);
903      cso_save_fragment_sampler_views(renderer->cso);
904      cso_save_fragment_shader(renderer->cso);
905      cso_save_vertex_shader(renderer->cso);
906
907      renderer_set_custom_fs(renderer, fs,
908                             samplers, views, num_samplers,
909                             const_buffer, const_buffer_len);
910      renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
911
912      tex = views[0]->texture;
913      renderer->u.filter.tex_width = tex->width0;
914      renderer->u.filter.tex_height = tex->height0;
915      renderer->u.filter.use_sampler = VG_TRUE;
916   }
917   else {
918      cso_save_fragment_shader(renderer->cso);
919
920      renderer_set_custom_fs(renderer, fs, NULL, NULL, 0,
921                             const_buffer, const_buffer_len);
922
923      renderer->u.filter.use_sampler = VG_FALSE;
924   }
925
926   renderer_set_mvp(renderer, NULL);
927
928   renderer->state = RENDERER_STATE_FILTER;
929
930   return VG_TRUE;
931}
932
933/**
934 * Draw into a rectangle of the destination with the specified region of the
935 * texture(s).
936 *
937 * The coordinates are in surface coordinates.
938 */
939void renderer_filter(struct renderer *renderer,
940                    VGint x, VGint y, VGint w, VGint h,
941                    VGint sx, VGint sy, VGint sw, VGint sh)
942{
943   assert(renderer->state == RENDERER_STATE_FILTER);
944
945   renderer_quad_pos(renderer, x, y, x + w, y + h, VG_FALSE);
946   if (renderer->u.filter.use_sampler) {
947      renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
948            renderer->u.filter.tex_width,
949            renderer->u.filter.tex_height);
950   }
951
952   renderer_quad_draw(renderer);
953}
954
955/**
956 * End image filtering and restore the states.
957 */
958void renderer_filter_end(struct renderer *renderer)
959{
960   assert(renderer->state == RENDERER_STATE_FILTER);
961
962   if (renderer->u.filter.use_sampler) {
963      cso_restore_samplers(renderer->cso);
964      cso_restore_fragment_sampler_views(renderer->cso);
965      cso_restore_vertex_shader(renderer->cso);
966   }
967
968   cso_restore_framebuffer(renderer->cso);
969   cso_restore_viewport(renderer->cso);
970   cso_restore_blend(renderer->cso);
971   cso_restore_fragment_shader(renderer->cso);
972
973   renderer->state = RENDERER_STATE_INIT;
974}
975
976/**
977 * Prepare the renderer for polygon silhouette rendering.
978 */
979VGboolean renderer_polygon_stencil_begin(struct renderer *renderer,
980                                         struct pipe_vertex_element *velem,
981                                         VGFillRule rule,
982                                         VGboolean restore_dsa)
983{
984   struct pipe_depth_stencil_alpha_state *dsa;
985   VGboolean manual_two_sides;
986
987   assert(renderer->state == RENDERER_STATE_INIT);
988
989   cso_save_vertex_elements(renderer->cso);
990   cso_save_blend(renderer->cso);
991   cso_save_depth_stencil_alpha(renderer->cso);
992
993   cso_set_vertex_elements(renderer->cso, 1, velem);
994
995   /* disable color writes */
996   renderer_set_blend(renderer, 0);
997
998   manual_two_sides = VG_FALSE;
999   dsa = &renderer->u.polygon_stencil.dsa;
1000   memset(dsa, 0, sizeof(*dsa));
1001   if (rule == VG_EVEN_ODD) {
1002      dsa->stencil[0].enabled = 1;
1003      dsa->stencil[0].writemask = 1;
1004      dsa->stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
1005      dsa->stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
1006      dsa->stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT;
1007      dsa->stencil[0].func = PIPE_FUNC_ALWAYS;
1008      dsa->stencil[0].valuemask = ~0;
1009   }
1010   else {
1011      assert(rule == VG_NON_ZERO);
1012
1013      /* front face */
1014      dsa->stencil[0].enabled = 1;
1015      dsa->stencil[0].writemask = ~0;
1016      dsa->stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
1017      dsa->stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
1018      dsa->stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
1019      dsa->stencil[0].func = PIPE_FUNC_ALWAYS;
1020      dsa->stencil[0].valuemask = ~0;
1021
1022      if (renderer->pipe->screen->get_param(renderer->pipe->screen,
1023                                            PIPE_CAP_TWO_SIDED_STENCIL)) {
1024         /* back face */
1025         dsa->stencil[1] = dsa->stencil[0];
1026         dsa->stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
1027      }
1028      else {
1029         manual_two_sides = VG_TRUE;
1030      }
1031   }
1032   cso_set_depth_stencil_alpha(renderer->cso, dsa);
1033
1034   if (manual_two_sides)
1035      cso_save_rasterizer(renderer->cso);
1036
1037   renderer->u.polygon_stencil.manual_two_sides = manual_two_sides;
1038   renderer->u.polygon_stencil.restore_dsa = restore_dsa;
1039   renderer->state = RENDERER_STATE_POLYGON_STENCIL;
1040
1041   return VG_TRUE;
1042}
1043
1044/**
1045 * Render a polygon silhouette to stencil buffer.
1046 */
1047void renderer_polygon_stencil(struct renderer *renderer,
1048                              struct pipe_vertex_buffer *vbuf,
1049                              VGuint mode, VGuint start, VGuint count)
1050{
1051   assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL);
1052
1053   renderer->pipe->set_vertex_buffers(renderer->pipe, 1, vbuf);
1054
1055   if (!renderer->u.polygon_stencil.manual_two_sides) {
1056      util_draw_arrays(renderer->pipe, mode, start, count);
1057   }
1058   else {
1059      struct pipe_rasterizer_state raster;
1060      struct pipe_depth_stencil_alpha_state dsa;
1061
1062      raster = renderer->g3d.rasterizer;
1063      dsa = renderer->u.polygon_stencil.dsa;
1064
1065      /* front */
1066      raster.cull_face = PIPE_FACE_BACK;
1067      dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
1068
1069      cso_set_rasterizer(renderer->cso, &raster);
1070      cso_set_depth_stencil_alpha(renderer->cso, &dsa);
1071      util_draw_arrays(renderer->pipe, mode, start, count);
1072
1073      /* back */
1074      raster.cull_face = PIPE_FACE_FRONT;
1075      dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
1076
1077      cso_set_rasterizer(renderer->cso, &raster);
1078      cso_set_depth_stencil_alpha(renderer->cso, &dsa);
1079      util_draw_arrays(renderer->pipe, mode, start, count);
1080   }
1081}
1082
1083/**
1084 * End polygon silhouette rendering.
1085 */
1086void renderer_polygon_stencil_end(struct renderer *renderer)
1087{
1088   assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL);
1089
1090   if (renderer->u.polygon_stencil.manual_two_sides)
1091      cso_restore_rasterizer(renderer->cso);
1092
1093   cso_restore_vertex_elements(renderer->cso);
1094
1095   /* restore color writes */
1096   cso_restore_blend(renderer->cso);
1097
1098   if (renderer->u.polygon_stencil.restore_dsa)
1099      cso_restore_depth_stencil_alpha(renderer->cso);
1100
1101   renderer->state = RENDERER_STATE_INIT;
1102}
1103
1104/**
1105 * Prepare the renderer for polygon filling.
1106 */
1107VGboolean renderer_polygon_fill_begin(struct renderer *renderer,
1108                                      VGboolean save_dsa)
1109{
1110   struct pipe_depth_stencil_alpha_state dsa;
1111
1112   assert(renderer->state == RENDERER_STATE_INIT);
1113
1114   if (save_dsa)
1115      cso_save_depth_stencil_alpha(renderer->cso);
1116
1117   /* setup stencil ops */
1118   memset(&dsa, 0, sizeof(dsa));
1119   dsa.stencil[0].enabled = 1;
1120   dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL;
1121   dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
1122   dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
1123   dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
1124   dsa.stencil[0].valuemask = ~0;
1125   dsa.stencil[0].writemask = ~0;
1126   dsa.depth = renderer->g3d.dsa.depth;
1127   cso_set_depth_stencil_alpha(renderer->cso, &dsa);
1128
1129   renderer->state = RENDERER_STATE_POLYGON_FILL;
1130
1131   return VG_TRUE;
1132}
1133
1134/**
1135 * Fill a polygon.
1136 */
1137void renderer_polygon_fill(struct renderer *renderer,
1138                           VGfloat min_x, VGfloat min_y,
1139                           VGfloat max_x, VGfloat max_y)
1140{
1141   assert(renderer->state == RENDERER_STATE_POLYGON_FILL);
1142
1143   renderer_quad_pos(renderer, min_x, min_y, max_x, max_y, VG_TRUE);
1144   renderer_quad_draw(renderer);
1145}
1146
1147/**
1148 * End polygon filling.
1149 */
1150void renderer_polygon_fill_end(struct renderer *renderer)
1151{
1152   assert(renderer->state == RENDERER_STATE_POLYGON_FILL);
1153
1154   cso_restore_depth_stencil_alpha(renderer->cso);
1155
1156   renderer->state = RENDERER_STATE_INIT;
1157}
1158
1159struct renderer * renderer_create(struct vg_context *owner)
1160{
1161   struct renderer *renderer;
1162   struct pipe_rasterizer_state *raster;
1163   struct pipe_stencil_ref sr;
1164   VGint i;
1165
1166   renderer = CALLOC_STRUCT(renderer);
1167   if (!renderer)
1168      return NULL;
1169
1170   renderer->pipe = owner->pipe;
1171   renderer->cso = owner->cso_context;
1172
1173   /* init vertex data that doesn't change */
1174   for (i = 0; i < 4; i++)
1175      renderer->vertices[i][0][3] = 1.0f; /* w */
1176
1177   for (i = 0; i < 2; i++) {
1178      renderer->velems[i].src_offset = i * 4 * sizeof(float);
1179      renderer->velems[i].instance_divisor = 0;
1180      renderer->velems[i].vertex_buffer_index = 0;
1181      renderer->velems[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
1182   }
1183   cso_set_vertex_elements(renderer->cso, 2, renderer->velems);
1184
1185   /* GL rasterization rules */
1186   raster = &renderer->g3d.rasterizer;
1187   memset(raster, 0, sizeof(*raster));
1188   raster->gl_rasterization_rules = 1;
1189   cso_set_rasterizer(renderer->cso, raster);
1190
1191   /* fixed at 0 */
1192   memset(&sr, 0, sizeof(sr));
1193   cso_set_stencil_ref(renderer->cso, &sr);
1194
1195   renderer_set_vs(renderer, RENDERER_VS_PLAIN);
1196
1197   renderer->state = RENDERER_STATE_INIT;
1198
1199   return renderer;
1200}
1201
1202void renderer_destroy(struct renderer *ctx)
1203{
1204   int i;
1205
1206   for (i = 0; i < NUM_RENDERER_VS; i++) {
1207      if (ctx->cached_vs[i])
1208         cso_delete_vertex_shader(ctx->cso, ctx->cached_vs[i]);
1209   }
1210   for (i = 0; i < NUM_RENDERER_FS; i++) {
1211      if (ctx->cached_fs[i])
1212         cso_delete_fragment_shader(ctx->cso, ctx->cached_fs[i]);
1213   }
1214
1215   pipe_resource_reference(&ctx->vs_cbuf, NULL);
1216   pipe_resource_reference(&ctx->fs_cbuf, NULL);
1217
1218   FREE(ctx);
1219}
1220
1221static void update_clip_state(struct renderer *renderer,
1222                              const struct vg_state *state)
1223{
1224   struct pipe_depth_stencil_alpha_state *dsa = &renderer->g3d.dsa;
1225
1226   memset(dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
1227
1228   if (state->scissoring) {
1229      struct pipe_framebuffer_state *fb = &renderer->g3d.fb;
1230      int i;
1231
1232      renderer_scissor_begin(renderer, VG_FALSE);
1233
1234      for (i = 0; i < state->scissor_rects_num; ++i) {
1235         const float x      = state->scissor_rects[i * 4 + 0].f;
1236         const float y      = state->scissor_rects[i * 4 + 1].f;
1237         const float width  = state->scissor_rects[i * 4 + 2].f;
1238         const float height = state->scissor_rects[i * 4 + 3].f;
1239         VGint x0, y0, x1, y1, iw, ih;
1240
1241         x0 = (VGint) x;
1242         y0 = (VGint) y;
1243         if (x0 < 0)
1244            x0 = 0;
1245         if (y0 < 0)
1246            y0 = 0;
1247
1248         /* note that x1 and y1 are exclusive */
1249         x1 = (VGint) ceilf(x + width);
1250         y1 = (VGint) ceilf(y + height);
1251         if (x1 > fb->width)
1252            x1 = fb->width;
1253         if (y1 > fb->height)
1254            y1 = fb->height;
1255
1256         iw = x1 - x0;
1257         ih = y1 - y0;
1258         if (iw > 0 && ih> 0 )
1259            renderer_scissor(renderer, x0, y0, iw, ih);
1260      }
1261
1262      renderer_scissor_end(renderer);
1263
1264      dsa->depth.enabled = 1; /* glEnable(GL_DEPTH_TEST); */
1265      dsa->depth.writemask = 0;/*glDepthMask(FALSE);*/
1266      dsa->depth.func = PIPE_FUNC_GEQUAL;
1267   }
1268}
1269
1270static void renderer_validate_blend(struct renderer *renderer,
1271                                     const struct vg_state *state,
1272                                     enum pipe_format fb_format)
1273{
1274   struct pipe_blend_state blend;
1275
1276   memset(&blend, 0, sizeof(blend));
1277   blend.rt[0].colormask = PIPE_MASK_RGBA;
1278   blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ONE;
1279   blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
1280   blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ZERO;
1281   blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
1282
1283   /* TODO alpha masking happens after blending? */
1284
1285   switch (state->blend_mode) {
1286   case VG_BLEND_SRC:
1287      blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ONE;
1288      blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
1289      blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ZERO;
1290      blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
1291      break;
1292   case VG_BLEND_SRC_OVER:
1293      if (!util_format_has_alpha(fb_format)) {
1294         blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_SRC_ALPHA;
1295         blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
1296         blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
1297         blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
1298         blend.rt[0].blend_enable = 1;
1299      }
1300      break;
1301   case VG_BLEND_SRC_IN:
1302      blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ONE;
1303      blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_DST_ALPHA;
1304      blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ZERO;
1305      blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
1306      blend.rt[0].blend_enable = 1;
1307      break;
1308   case VG_BLEND_DST_IN:
1309      blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ZERO;
1310      blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO;
1311      blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ONE;
1312      blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
1313      blend.rt[0].blend_enable = 1;
1314      break;
1315   case VG_BLEND_DST_OVER:
1316   case VG_BLEND_MULTIPLY:
1317   case VG_BLEND_SCREEN:
1318   case VG_BLEND_DARKEN:
1319   case VG_BLEND_LIGHTEN:
1320   case VG_BLEND_ADDITIVE:
1321      /* need a shader */
1322      break;
1323   default:
1324      assert(!"not implemented blend mode");
1325      break;
1326   }
1327
1328   cso_set_blend(renderer->cso, &blend);
1329}
1330
1331/**
1332 * Propogate OpenVG state changes to the renderer.  Only framebuffer, blending
1333 * and scissoring states are relevant here.
1334 */
1335void renderer_validate(struct renderer *renderer,
1336                       VGbitfield dirty,
1337                       const struct st_framebuffer *stfb,
1338                       const struct vg_state *state)
1339{
1340   assert(renderer->state == RENDERER_STATE_INIT);
1341
1342   dirty |= renderer->dirty;
1343   renderer->dirty = 0;
1344
1345   if (dirty & FRAMEBUFFER_DIRTY) {
1346      struct pipe_framebuffer_state *fb = &renderer->g3d.fb;
1347      struct matrix *proj = &renderer->projection;
1348
1349      memset(fb, 0, sizeof(struct pipe_framebuffer_state));
1350      fb->width  = stfb->width;
1351      fb->height = stfb->height;
1352      fb->nr_cbufs = 1;
1353      fb->cbufs[0] = stfb->strb->surface;
1354      fb->zsbuf = stfb->dsrb->surface;
1355
1356      cso_set_framebuffer(renderer->cso, fb);
1357      vg_set_viewport(renderer, VEGA_Y0_BOTTOM);
1358
1359      matrix_load_identity(proj);
1360      matrix_translate(proj, -1.0f, -1.0f);
1361      matrix_scale(proj, 2.0f / fb->width, 2.0f / fb->height);
1362
1363      /* we also got a new depth buffer */
1364      if (dirty & DEPTH_STENCIL_DIRTY) {
1365         renderer->pipe->clear(renderer->pipe,
1366               PIPE_CLEAR_DEPTHSTENCIL, NULL, 0.0, 0);
1367      }
1368   }
1369
1370   /* must be last because it renders to the depth buffer*/
1371   if (dirty & DEPTH_STENCIL_DIRTY) {
1372      update_clip_state(renderer, state);
1373      cso_set_depth_stencil_alpha(renderer->cso, &renderer->g3d.dsa);
1374   }
1375
1376   if (dirty & BLEND_DIRTY)
1377      renderer_validate_blend(renderer, state, stfb->strb->format);
1378}
1379
1380/**
1381 * Prepare the renderer for OpenVG pipeline.
1382 */
1383void renderer_validate_for_shader(struct renderer *renderer,
1384                                  const struct pipe_sampler_state **samplers,
1385                                  struct pipe_sampler_view **views,
1386                                  VGint num_samplers,
1387                                  const struct matrix *modelview,
1388                                  void *fs,
1389                                  const void *const_buffer,
1390                                  VGint const_buffer_len)
1391{
1392   struct matrix mvp = renderer->projection;
1393
1394   /* will be used in POLYGON_STENCIL and POLYGON_FILL */
1395   matrix_mult(&mvp, modelview);
1396   renderer_set_mvp(renderer, &mvp);
1397
1398   renderer_set_custom_fs(renderer, fs,
1399                          samplers, views, num_samplers,
1400                          const_buffer, const_buffer_len);
1401}
1402
1403void renderer_validate_for_mask_rendering(struct renderer *renderer,
1404                                          struct pipe_surface *dst,
1405                                          const struct matrix *modelview)
1406{
1407   struct matrix mvp = renderer->projection;
1408
1409   /* will be used in POLYGON_STENCIL and POLYGON_FILL */
1410   matrix_mult(&mvp, modelview);
1411   renderer_set_mvp(renderer, &mvp);
1412
1413   renderer_set_target(renderer, dst, renderer->g3d.fb.zsbuf, VG_FALSE);
1414   renderer_set_blend(renderer, ~0);
1415   renderer_set_fs(renderer, RENDERER_FS_WHITE);
1416
1417   /* set internal dirty flags (hacky!) */
1418   renderer->dirty = FRAMEBUFFER_DIRTY | BLEND_DIRTY;
1419}
1420
1421void renderer_copy_surface(struct renderer *ctx,
1422                           struct pipe_surface *src,
1423                           int srcX0, int srcY0,
1424                           int srcX1, int srcY1,
1425                           struct pipe_surface *dst,
1426                           int dstX0, int dstY0,
1427                           int dstX1, int dstY1,
1428                           float z, unsigned filter)
1429{
1430   struct pipe_context *pipe = ctx->pipe;
1431   struct pipe_screen *screen = pipe->screen;
1432   struct pipe_sampler_view view_templ;
1433   struct pipe_sampler_view *view;
1434   struct pipe_box src_box;
1435   struct pipe_resource texTemp, *tex;
1436   const struct pipe_framebuffer_state *fb = &ctx->g3d.fb;
1437   const int srcW = abs(srcX1 - srcX0);
1438   const int srcH = abs(srcY1 - srcY0);
1439   const int srcLeft = MIN2(srcX0, srcX1);
1440   const int srcTop = MIN2(srcY0, srcY1);
1441
1442   assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
1443          filter == PIPE_TEX_MIPFILTER_LINEAR);
1444
1445   if (srcLeft != srcX0) {
1446      /* left-right flip */
1447      int tmp = dstX0;
1448      dstX0 = dstX1;
1449      dstX1 = tmp;
1450   }
1451
1452   if (srcTop != srcY0) {
1453      /* up-down flip */
1454      int tmp = dstY0;
1455      dstY0 = dstY1;
1456      dstY1 = tmp;
1457   }
1458
1459   assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D,
1460                                      0, PIPE_BIND_SAMPLER_VIEW, 0));
1461   assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
1462                                      0, PIPE_BIND_SAMPLER_VIEW, 0));
1463   assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
1464                                      0, PIPE_BIND_RENDER_TARGET, 0));
1465
1466   /*
1467    * XXX for now we're always creating a temporary texture.
1468    * Strictly speaking that's not always needed.
1469    */
1470
1471   /* create temp texture */
1472   memset(&texTemp, 0, sizeof(texTemp));
1473   texTemp.target = PIPE_TEXTURE_2D;
1474   texTemp.format = src->format;
1475   texTemp.last_level = 0;
1476   texTemp.width0 = srcW;
1477   texTemp.height0 = srcH;
1478   texTemp.depth0 = 1;
1479   texTemp.array_size = 1;
1480   texTemp.bind = PIPE_BIND_SAMPLER_VIEW;
1481
1482   tex = screen->resource_create(screen, &texTemp);
1483   if (!tex)
1484      return;
1485
1486   u_sampler_view_default_template(&view_templ, tex, tex->format);
1487   view = pipe->create_sampler_view(pipe, tex, &view_templ);
1488
1489   if (!view)
1490      return;
1491
1492   u_box_2d_zslice(srcLeft, srcTop, src->u.tex.first_layer, srcW, srcH, &src_box);
1493
1494   pipe->resource_copy_region(pipe,
1495                              tex, 0, 0, 0, 0,  /* dest */
1496                              src->texture, 0, &src_box);
1497
1498   assert(floatsEqual(z, 0.0f));
1499
1500   /* draw */
1501   if (fb->cbufs[0] == dst) {
1502      /* transform back to surface coordinates */
1503      dstY0 = dst->height - dstY0;
1504      dstY1 = dst->height - dstY1;
1505
1506      if (renderer_drawtex_begin(ctx, view)) {
1507         renderer_drawtex(ctx,
1508               dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0,
1509               0, 0, view->texture->width0, view->texture->height0);
1510         renderer_drawtex_end(ctx);
1511      }
1512   }
1513   else {
1514      if (renderer_copy_begin(ctx, dst, VG_TRUE, view)) {
1515         renderer_copy(ctx,
1516               dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0,
1517               0, 0, view->texture->width0, view->texture->height0);
1518         renderer_copy_end(ctx);
1519      }
1520   }
1521}
1522
1523void renderer_texture_quad(struct renderer *r,
1524                           struct pipe_resource *tex,
1525                           VGfloat x1offset, VGfloat y1offset,
1526                           VGfloat x2offset, VGfloat y2offset,
1527                           VGfloat x1, VGfloat y1,
1528                           VGfloat x2, VGfloat y2,
1529                           VGfloat x3, VGfloat y3,
1530                           VGfloat x4, VGfloat y4)
1531{
1532   const VGfloat z = 0.0f;
1533
1534   assert(r->state == RENDERER_STATE_INIT);
1535   assert(tex->width0 != 0);
1536   assert(tex->height0 != 0);
1537
1538   cso_save_vertex_shader(r->cso);
1539
1540   renderer_set_vs(r, RENDERER_VS_TEXTURE);
1541
1542   /* manually set up positions */
1543   r->vertices[0][0][0] = x1;
1544   r->vertices[0][0][1] = y1;
1545   r->vertices[0][0][2] = z;
1546
1547   r->vertices[1][0][0] = x2;
1548   r->vertices[1][0][1] = y2;
1549   r->vertices[1][0][2] = z;
1550
1551   r->vertices[2][0][0] = x3;
1552   r->vertices[2][0][1] = y3;
1553   r->vertices[2][0][2] = z;
1554
1555   r->vertices[3][0][0] = x4;
1556   r->vertices[3][0][1] = y4;
1557   r->vertices[3][0][2] = z;
1558
1559   /* texcoords */
1560   renderer_quad_texcoord(r, x1offset, y1offset,
1561         x2offset, y2offset, tex->width0, tex->height0);
1562
1563   renderer_quad_draw(r);
1564
1565   cso_restore_vertex_shader(r->cso);
1566}
1567