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