renderer.c revision 4a96a02de7c1b8c136ffc0cd278401c85faab233
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
32#include "pipe/p_context.h"
33#include "pipe/p_state.h"
34#include "util/u_inlines.h"
35#include "pipe/p_screen.h"
36#include "pipe/p_shader_tokens.h"
37
38#include "util/u_draw_quad.h"
39#include "util/u_simple_shaders.h"
40#include "util/u_memory.h"
41#include "util/u_sampler.h"
42#include "util/u_surface.h"
43#include "util/u_math.h"
44#include "util/u_format.h"
45
46#include "cso_cache/cso_context.h"
47#include "tgsi/tgsi_ureg.h"
48
49typedef enum {
50   RENDERER_STATE_INIT,
51   RENDERER_STATE_COPY,
52   RENDERER_STATE_DRAWTEX,
53   RENDERER_STATE_SCISSOR,
54   RENDERER_STATE_CLEAR,
55   RENDERER_STATE_FILTER,
56   RENDERER_STATE_POLYGON_STENCIL,
57   RENDERER_STATE_POLYGON_FILL,
58   NUM_RENDERER_STATES
59} RendererState;
60
61typedef enum {
62   RENDERER_VS_PLAIN,
63   RENDERER_VS_COLOR,
64   RENDERER_VS_TEXTURE,
65   NUM_RENDERER_VS
66} RendererVs;
67
68typedef enum {
69   RENDERER_FS_COLOR,
70   RENDERER_FS_TEXTURE,
71   RENDERER_FS_SCISSOR,
72   RENDERER_FS_WHITE,
73   NUM_RENDERER_FS
74} RendererFs;
75
76struct renderer {
77   struct pipe_context *pipe;
78   struct cso_context *cso;
79
80   VGbitfield dirty;
81   struct {
82      struct pipe_rasterizer_state rasterizer;
83      struct pipe_depth_stencil_alpha_state dsa;
84      struct pipe_framebuffer_state fb;
85   } g3d;
86   struct matrix projection;
87
88   struct matrix mvp;
89   struct pipe_resource *vs_cbuf;
90
91   struct pipe_resource *fs_cbuf;
92   VGfloat fs_cbuf_data[32];
93   VGint fs_cbuf_len;
94
95   struct pipe_vertex_element velems[2];
96   VGfloat vertices[4][2][4];
97
98   void *cached_vs[NUM_RENDERER_VS];
99   void *cached_fs[NUM_RENDERER_FS];
100
101   RendererState state;
102
103   /* state data */
104   union {
105      struct {
106         VGint tex_width;
107         VGint tex_height;
108      } copy;
109
110      struct {
111         VGint tex_width;
112         VGint tex_height;
113      } drawtex;
114
115      struct {
116         VGboolean restore_dsa;
117      } scissor;
118
119      struct {
120         VGboolean use_sampler;
121         VGint tex_width, tex_height;
122      } filter;
123
124      struct {
125         struct pipe_depth_stencil_alpha_state dsa;
126         VGboolean manual_two_sides;
127         VGboolean restore_dsa;
128      } polygon_stencil;
129   } u;
130};
131
132/**
133 * Return VG_TRUE if the renderer can use the resource as the asked bindings.
134 */
135static VGboolean renderer_can_support(struct renderer *renderer,
136                                      struct pipe_resource *res,
137                                      unsigned bindings)
138{
139   struct pipe_screen *screen = renderer->pipe->screen;
140
141   return screen->is_format_supported(screen,
142         res->format, res->target, 0, bindings);
143}
144
145/**
146 * Set the model-view-projection matrix used by vertex shaders.
147 */
148static void renderer_set_mvp(struct renderer *renderer,
149                             const struct matrix *mvp)
150{
151   struct matrix *cur = &renderer->mvp;
152   struct pipe_resource *cbuf;
153   VGfloat consts[3][4];
154   VGint i;
155
156   /* projection only */
157   if (!mvp)
158      mvp = &renderer->projection;
159
160   /* re-upload only if necessary */
161   if (memcmp(cur, mvp, sizeof(*mvp)) == 0)
162      return;
163
164   /* 3x3 matrix to 3 constant vectors (no Z) */
165   for (i = 0; i < 3; i++) {
166      consts[i][0] = mvp->m[i + 0];
167      consts[i][1] = mvp->m[i + 3];
168      consts[i][2] = 0.0f;
169      consts[i][3] = mvp->m[i + 6];
170   }
171
172   cbuf = renderer->vs_cbuf;
173   pipe_resource_reference(&cbuf, NULL);
174   cbuf = pipe_buffer_create(renderer->pipe->screen,
175                             PIPE_BIND_CONSTANT_BUFFER,
176                             PIPE_USAGE_STATIC,
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, PIPE_USAGE_STATIC,
478               const_buffer_len);
479         pipe_buffer_write(renderer->pipe, cbuf, 0,
480               const_buffer_len, const_buffer);
481         renderer->pipe->set_constant_buffer(renderer->pipe,
482               PIPE_SHADER_FRAGMENT, 0, cbuf);
483
484         renderer->fs_cbuf = cbuf;
485         if (const_buffer_len <= sizeof(renderer->fs_cbuf_data)) {
486            memcpy(renderer->fs_cbuf_data, const_buffer, const_buffer_len);
487            renderer->fs_cbuf_len = const_buffer_len;
488         }
489         else {
490            renderer->fs_cbuf_len = 0;
491         }
492      }
493   }
494}
495
496/**
497 * Setup renderer quad position.
498 */
499static void renderer_quad_pos(struct renderer *r,
500                              VGfloat x0, VGfloat y0,
501                              VGfloat x1, VGfloat y1,
502                              VGboolean scissor)
503{
504   VGfloat z;
505
506   /* the depth test is used for scissoring */
507   z = (scissor) ? 0.0f : 1.0f;
508
509   /* positions */
510   r->vertices[0][0][0] = x0;
511   r->vertices[0][0][1] = y0;
512   r->vertices[0][0][2] = z;
513
514   r->vertices[1][0][0] = x1;
515   r->vertices[1][0][1] = y0;
516   r->vertices[1][0][2] = z;
517
518   r->vertices[2][0][0] = x1;
519   r->vertices[2][0][1] = y1;
520   r->vertices[2][0][2] = z;
521
522   r->vertices[3][0][0] = x0;
523   r->vertices[3][0][1] = y1;
524   r->vertices[3][0][2] = z;
525}
526
527/**
528 * Setup renderer quad texture coordinates.
529 */
530static void renderer_quad_texcoord(struct renderer *r,
531                                   VGfloat x0, VGfloat y0,
532                                   VGfloat x1, VGfloat y1,
533                                   VGint tex_width, VGint tex_height)
534{
535   VGfloat s0, t0, s1, t1, r0, q0;
536   VGint i;
537
538   s0 = x0 / tex_width;
539   s1 = x1 / tex_width;
540   t0 = y0 / tex_height;
541   t1 = y1 / tex_height;
542   r0 = 0.0f;
543   q0 = 1.0f;
544
545   /* texcoords */
546   r->vertices[0][1][0] = s0;
547   r->vertices[0][1][1] = t0;
548
549   r->vertices[1][1][0] = s1;
550   r->vertices[1][1][1] = t0;
551
552   r->vertices[2][1][0] = s1;
553   r->vertices[2][1][1] = t1;
554
555   r->vertices[3][1][0] = s0;
556   r->vertices[3][1][1] = t1;
557
558   for (i = 0; i < 4; i++) {
559      r->vertices[i][1][2] = r0;
560      r->vertices[i][1][3] = q0;
561   }
562}
563
564/**
565 * Draw renderer quad.
566 */
567static void renderer_quad_draw(struct renderer *r)
568{
569   struct pipe_resource *buf;
570
571   buf = pipe_user_buffer_create(r->pipe->screen,
572                                 r->vertices,
573                                 sizeof(r->vertices),
574                                 PIPE_BIND_VERTEX_BUFFER);
575   if (buf) {
576      util_draw_vertex_buffer(r->pipe, r->cso, buf, 0,
577                              PIPE_PRIM_TRIANGLE_FAN,
578                              Elements(r->vertices),     /* verts */
579                              Elements(r->vertices[0])); /* attribs/vert */
580
581      pipe_resource_reference(&buf, NULL);
582   }
583}
584
585/**
586 * Prepare the renderer for copying.
587 */
588VGboolean renderer_copy_begin(struct renderer *renderer,
589                              struct pipe_surface *dst,
590                              VGboolean y0_top,
591                              struct pipe_sampler_view *src)
592{
593   assert(renderer->state == RENDERER_STATE_INIT);
594
595   /* sanity check */
596   if (!renderer_can_support(renderer,
597            dst->texture, PIPE_BIND_RENDER_TARGET) ||
598       !renderer_can_support(renderer,
599          src->texture, PIPE_BIND_SAMPLER_VIEW))
600      return VG_FALSE;
601
602   cso_save_framebuffer(renderer->cso);
603   cso_save_viewport(renderer->cso);
604   cso_save_blend(renderer->cso);
605   cso_save_samplers(renderer->cso);
606   cso_save_fragment_sampler_views(renderer->cso);
607   cso_save_fragment_shader(renderer->cso);
608   cso_save_vertex_shader(renderer->cso);
609
610   renderer_set_target(renderer, dst, NULL, y0_top);
611
612   renderer_set_blend(renderer, ~0);
613   renderer_set_samplers(renderer, 1, &src);
614
615   renderer_set_fs(renderer, RENDERER_FS_TEXTURE);
616   renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
617
618   renderer_set_mvp(renderer, NULL);
619
620   /* remember the texture size */
621   renderer->u.copy.tex_width = src->texture->width0;
622   renderer->u.copy.tex_height = src->texture->height0;
623   renderer->state = RENDERER_STATE_COPY;
624
625   return VG_TRUE;
626}
627
628/**
629 * Draw into the destination rectangle given by (x, y, w, h).  The texture is
630 * sampled from within the rectangle given by (sx, sy, sw, sh).
631 *
632 * The coordinates are in surface coordinates.
633 */
634void renderer_copy(struct renderer *renderer,
635                   VGint x, VGint y, VGint w, VGint h,
636                   VGint sx, VGint sy, VGint sw, VGint sh)
637{
638   assert(renderer->state == RENDERER_STATE_COPY);
639
640   /* there is no depth buffer for scissoring anyway */
641   renderer_quad_pos(renderer, x, y, x + w, y + h, VG_FALSE);
642   renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
643         renderer->u.copy.tex_width,
644         renderer->u.copy.tex_height);
645
646   renderer_quad_draw(renderer);
647}
648
649/**
650 * End copying and restore the states.
651 */
652void renderer_copy_end(struct renderer *renderer)
653{
654   assert(renderer->state == RENDERER_STATE_COPY);
655
656   cso_restore_framebuffer(renderer->cso);
657   cso_restore_viewport(renderer->cso);
658   cso_restore_blend(renderer->cso);
659   cso_restore_samplers(renderer->cso);
660   cso_restore_fragment_sampler_views(renderer->cso);
661   cso_restore_fragment_shader(renderer->cso);
662   cso_restore_vertex_shader(renderer->cso);
663
664   renderer->state = RENDERER_STATE_INIT;
665}
666
667/**
668 * Prepare the renderer for textured drawing.
669 */
670VGboolean renderer_drawtex_begin(struct renderer *renderer,
671                                 struct pipe_sampler_view *src)
672{
673   assert(renderer->state == RENDERER_STATE_INIT);
674
675   if (!renderer_can_support(renderer, src->texture, PIPE_BIND_SAMPLER_VIEW))
676      return VG_FALSE;
677
678   cso_save_blend(renderer->cso);
679   cso_save_samplers(renderer->cso);
680   cso_save_fragment_sampler_views(renderer->cso);
681   cso_save_fragment_shader(renderer->cso);
682   cso_save_vertex_shader(renderer->cso);
683
684   renderer_set_blend(renderer, ~0);
685
686   renderer_set_samplers(renderer, 1, &src);
687
688   renderer_set_fs(renderer, RENDERER_FS_TEXTURE);
689   renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
690
691   renderer_set_mvp(renderer, NULL);
692
693   /* remember the texture size */
694   renderer->u.drawtex.tex_width = src->texture->width0;
695   renderer->u.drawtex.tex_height = src->texture->height0;
696   renderer->state = RENDERER_STATE_DRAWTEX;
697
698   return VG_TRUE;
699}
700
701/**
702 * Draw into the destination rectangle given by (x, y, w, h).  The texture is
703 * sampled from within the rectangle given by (sx, sy, sw, sh).
704 *
705 * The coordinates are in surface coordinates.
706 */
707void renderer_drawtex(struct renderer *renderer,
708                      VGint x, VGint y, VGint w, VGint h,
709                      VGint sx, VGint sy, VGint sw, VGint sh)
710{
711   assert(renderer->state == RENDERER_STATE_DRAWTEX);
712
713   /* with scissoring */
714   renderer_quad_pos(renderer, x, y, x + w, y + h, VG_TRUE);
715   renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
716         renderer->u.drawtex.tex_width,
717         renderer->u.drawtex.tex_height);
718
719   renderer_quad_draw(renderer);
720}
721
722/**
723 * End textured drawing and restore the states.
724 */
725void renderer_drawtex_end(struct renderer *renderer)
726{
727   assert(renderer->state == RENDERER_STATE_DRAWTEX);
728
729   cso_restore_blend(renderer->cso);
730   cso_restore_samplers(renderer->cso);
731   cso_restore_fragment_sampler_views(renderer->cso);
732   cso_restore_fragment_shader(renderer->cso);
733   cso_restore_vertex_shader(renderer->cso);
734
735   renderer->state = RENDERER_STATE_INIT;
736}
737
738/**
739 * Prepare the renderer for scissor update.  This will reset the depth buffer
740 * to 1.0f.
741 */
742VGboolean renderer_scissor_begin(struct renderer *renderer,
743                                 VGboolean restore_dsa)
744{
745   struct pipe_depth_stencil_alpha_state dsa;
746
747   assert(renderer->state == RENDERER_STATE_INIT);
748
749   if (restore_dsa)
750      cso_save_depth_stencil_alpha(renderer->cso);
751   cso_save_blend(renderer->cso);
752   cso_save_fragment_shader(renderer->cso);
753
754   /* enable depth writes */
755   memset(&dsa, 0, sizeof(dsa));
756   dsa.depth.enabled = 1;
757   dsa.depth.writemask = 1;
758   dsa.depth.func = PIPE_FUNC_ALWAYS;
759   cso_set_depth_stencil_alpha(renderer->cso, &dsa);
760
761   /* disable color writes */
762   renderer_set_blend(renderer, 0);
763   renderer_set_fs(renderer, RENDERER_FS_SCISSOR);
764
765   renderer_set_mvp(renderer, NULL);
766
767   renderer->u.scissor.restore_dsa = restore_dsa;
768   renderer->state = RENDERER_STATE_SCISSOR;
769
770   /* clear the depth buffer to 1.0f */
771   renderer->pipe->clear(renderer->pipe,
772         PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0f, 0);
773
774   return VG_TRUE;
775}
776
777/**
778 * Add a scissor rectangle.  Depth values inside the rectangle will be set to
779 * 0.0f.
780 */
781void renderer_scissor(struct renderer *renderer,
782                      VGint x, VGint y, VGint width, VGint height)
783{
784   assert(renderer->state == RENDERER_STATE_SCISSOR);
785
786   renderer_quad_pos(renderer, x, y, x + width, y + height, VG_FALSE);
787   renderer_quad_draw(renderer);
788}
789
790/**
791 * End scissor update and restore the states.
792 */
793void renderer_scissor_end(struct renderer *renderer)
794{
795   assert(renderer->state == RENDERER_STATE_SCISSOR);
796
797   if (renderer->u.scissor.restore_dsa)
798      cso_restore_depth_stencil_alpha(renderer->cso);
799   cso_restore_blend(renderer->cso);
800   cso_restore_fragment_shader(renderer->cso);
801
802   renderer->state = RENDERER_STATE_INIT;
803}
804
805/**
806 * Prepare the renderer for clearing.
807 */
808VGboolean renderer_clear_begin(struct renderer *renderer)
809{
810   assert(renderer->state == RENDERER_STATE_INIT);
811
812   cso_save_blend(renderer->cso);
813   cso_save_fragment_shader(renderer->cso);
814   cso_save_vertex_shader(renderer->cso);
815
816   renderer_set_blend(renderer, ~0);
817   renderer_set_fs(renderer, RENDERER_FS_COLOR);
818   renderer_set_vs(renderer, RENDERER_VS_COLOR);
819
820   renderer_set_mvp(renderer, NULL);
821
822   renderer->state = RENDERER_STATE_CLEAR;
823
824   return VG_TRUE;
825}
826
827/**
828 * Clear the framebuffer with the specified region and color.
829 *
830 * The coordinates are in surface coordinates.
831 */
832void renderer_clear(struct renderer *renderer,
833                    VGint x, VGint y, VGint width, VGint height,
834                    const VGfloat color[4])
835{
836   VGuint i;
837
838   assert(renderer->state == RENDERER_STATE_CLEAR);
839
840   renderer_quad_pos(renderer, x, y, x + width, y + height, VG_TRUE);
841   for (i = 0; i < 4; i++)
842      memcpy(renderer->vertices[i][1], color, sizeof(VGfloat) * 4);
843
844   renderer_quad_draw(renderer);
845}
846
847/**
848 * End clearing and retore the states.
849 */
850void renderer_clear_end(struct renderer *renderer)
851{
852   assert(renderer->state == RENDERER_STATE_CLEAR);
853
854   cso_restore_blend(renderer->cso);
855   cso_restore_fragment_shader(renderer->cso);
856   cso_restore_vertex_shader(renderer->cso);
857
858   renderer->state = RENDERER_STATE_INIT;
859}
860
861/**
862 * Prepare the renderer for image filtering.
863 */
864VGboolean renderer_filter_begin(struct renderer *renderer,
865                                struct pipe_resource *dst,
866                                VGboolean y0_top,
867                                VGbitfield channel_mask,
868                                const struct pipe_sampler_state **samplers,
869                                struct pipe_sampler_view **views,
870                                VGint num_samplers,
871                                void *fs,
872                                const void *const_buffer,
873                                VGint const_buffer_len)
874{
875   struct pipe_surface *surf, surf_tmpl;
876
877   assert(renderer->state == RENDERER_STATE_INIT);
878
879   if (!fs)
880      return VG_FALSE;
881   if (!renderer_can_support(renderer, dst, PIPE_BIND_RENDER_TARGET))
882      return VG_FALSE;
883
884   u_surface_default_template(&surf_tmpl, dst,
885                              PIPE_BIND_RENDER_TARGET);
886   surf = renderer->pipe->create_surface(renderer->pipe, dst, &surf_tmpl);
887   if (!surf)
888      return VG_FALSE;
889
890   cso_save_framebuffer(renderer->cso);
891   cso_save_viewport(renderer->cso);
892   cso_save_blend(renderer->cso);
893
894   /* set the image as the target */
895   renderer_set_target(renderer, surf, NULL, y0_top);
896   pipe_surface_reference(&surf, NULL);
897
898   renderer_set_blend(renderer, channel_mask);
899
900   if (num_samplers) {
901      struct pipe_resource *tex;
902
903      cso_save_samplers(renderer->cso);
904      cso_save_fragment_sampler_views(renderer->cso);
905      cso_save_fragment_shader(renderer->cso);
906      cso_save_vertex_shader(renderer->cso);
907
908      renderer_set_custom_fs(renderer, fs,
909                             samplers, views, num_samplers,
910                             const_buffer, const_buffer_len);
911      renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
912
913      tex = views[0]->texture;
914      renderer->u.filter.tex_width = tex->width0;
915      renderer->u.filter.tex_height = tex->height0;
916      renderer->u.filter.use_sampler = VG_TRUE;
917   }
918   else {
919      cso_save_fragment_shader(renderer->cso);
920
921      renderer_set_custom_fs(renderer, fs, NULL, NULL, 0,
922                             const_buffer, const_buffer_len);
923
924      renderer->u.filter.use_sampler = VG_FALSE;
925   }
926
927   renderer_set_mvp(renderer, NULL);
928
929   renderer->state = RENDERER_STATE_FILTER;
930
931   return VG_TRUE;
932}
933
934/**
935 * Draw into a rectangle of the destination with the specified region of the
936 * texture(s).
937 *
938 * The coordinates are in surface coordinates.
939 */
940void renderer_filter(struct renderer *renderer,
941                    VGint x, VGint y, VGint w, VGint h,
942                    VGint sx, VGint sy, VGint sw, VGint sh)
943{
944   assert(renderer->state == RENDERER_STATE_FILTER);
945
946   renderer_quad_pos(renderer, x, y, x + w, y + h, VG_FALSE);
947   if (renderer->u.filter.use_sampler) {
948      renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
949            renderer->u.filter.tex_width,
950            renderer->u.filter.tex_height);
951   }
952
953   renderer_quad_draw(renderer);
954}
955
956/**
957 * End image filtering and restore the states.
958 */
959void renderer_filter_end(struct renderer *renderer)
960{
961   assert(renderer->state == RENDERER_STATE_FILTER);
962
963   if (renderer->u.filter.use_sampler) {
964      cso_restore_samplers(renderer->cso);
965      cso_restore_fragment_sampler_views(renderer->cso);
966      cso_restore_vertex_shader(renderer->cso);
967   }
968
969   cso_restore_framebuffer(renderer->cso);
970   cso_restore_viewport(renderer->cso);
971   cso_restore_blend(renderer->cso);
972   cso_restore_fragment_shader(renderer->cso);
973
974   renderer->state = RENDERER_STATE_INIT;
975}
976
977/**
978 * Prepare the renderer for polygon silhouette rendering.
979 */
980VGboolean renderer_polygon_stencil_begin(struct renderer *renderer,
981                                         struct pipe_vertex_element *velem,
982                                         VGFillRule rule,
983                                         VGboolean restore_dsa)
984{
985   struct pipe_depth_stencil_alpha_state *dsa;
986   VGboolean manual_two_sides;
987
988   assert(renderer->state == RENDERER_STATE_INIT);
989
990   cso_save_vertex_elements(renderer->cso);
991   cso_save_blend(renderer->cso);
992   cso_save_depth_stencil_alpha(renderer->cso);
993
994   cso_set_vertex_elements(renderer->cso, 1, velem);
995
996   /* disable color writes */
997   renderer_set_blend(renderer, 0);
998
999   manual_two_sides = VG_FALSE;
1000   dsa = &renderer->u.polygon_stencil.dsa;
1001   memset(dsa, 0, sizeof(*dsa));
1002   if (rule == VG_EVEN_ODD) {
1003      dsa->stencil[0].enabled = 1;
1004      dsa->stencil[0].writemask = 1;
1005      dsa->stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
1006      dsa->stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
1007      dsa->stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT;
1008      dsa->stencil[0].func = PIPE_FUNC_ALWAYS;
1009      dsa->stencil[0].valuemask = ~0;
1010   }
1011   else {
1012      assert(rule == VG_NON_ZERO);
1013
1014      /* front face */
1015      dsa->stencil[0].enabled = 1;
1016      dsa->stencil[0].writemask = ~0;
1017      dsa->stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
1018      dsa->stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
1019      dsa->stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
1020      dsa->stencil[0].func = PIPE_FUNC_ALWAYS;
1021      dsa->stencil[0].valuemask = ~0;
1022
1023      if (renderer->pipe->screen->get_param(renderer->pipe->screen,
1024                                            PIPE_CAP_TWO_SIDED_STENCIL)) {
1025         /* back face */
1026         dsa->stencil[1] = dsa->stencil[0];
1027         dsa->stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
1028      }
1029      else {
1030         manual_two_sides = VG_TRUE;
1031      }
1032   }
1033   cso_set_depth_stencil_alpha(renderer->cso, dsa);
1034
1035   if (manual_two_sides)
1036      cso_save_rasterizer(renderer->cso);
1037
1038   renderer->u.polygon_stencil.manual_two_sides = manual_two_sides;
1039   renderer->u.polygon_stencil.restore_dsa = restore_dsa;
1040   renderer->state = RENDERER_STATE_POLYGON_STENCIL;
1041
1042   return VG_TRUE;
1043}
1044
1045/**
1046 * Render a polygon silhouette to stencil buffer.
1047 */
1048void renderer_polygon_stencil(struct renderer *renderer,
1049                              struct pipe_vertex_buffer *vbuf,
1050                              VGuint mode, VGuint start, VGuint count)
1051{
1052   assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL);
1053
1054   cso_set_vertex_buffers(renderer->cso, 1, vbuf);
1055
1056   if (!renderer->u.polygon_stencil.manual_two_sides) {
1057      util_draw_arrays(renderer->pipe, mode, start, count);
1058   }
1059   else {
1060      struct pipe_rasterizer_state raster;
1061      struct pipe_depth_stencil_alpha_state dsa;
1062
1063      raster = renderer->g3d.rasterizer;
1064      dsa = renderer->u.polygon_stencil.dsa;
1065
1066      /* front */
1067      raster.cull_face = PIPE_FACE_BACK;
1068      dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
1069
1070      cso_set_rasterizer(renderer->cso, &raster);
1071      cso_set_depth_stencil_alpha(renderer->cso, &dsa);
1072      util_draw_arrays(renderer->pipe, mode, start, count);
1073
1074      /* back */
1075      raster.cull_face = PIPE_FACE_FRONT;
1076      dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
1077
1078      cso_set_rasterizer(renderer->cso, &raster);
1079      cso_set_depth_stencil_alpha(renderer->cso, &dsa);
1080      util_draw_arrays(renderer->pipe, mode, start, count);
1081   }
1082}
1083
1084/**
1085 * End polygon silhouette rendering.
1086 */
1087void renderer_polygon_stencil_end(struct renderer *renderer)
1088{
1089   assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL);
1090
1091   if (renderer->u.polygon_stencil.manual_two_sides)
1092      cso_restore_rasterizer(renderer->cso);
1093
1094   cso_restore_vertex_elements(renderer->cso);
1095
1096   /* restore color writes */
1097   cso_restore_blend(renderer->cso);
1098
1099   if (renderer->u.polygon_stencil.restore_dsa)
1100      cso_restore_depth_stencil_alpha(renderer->cso);
1101
1102   renderer->state = RENDERER_STATE_INIT;
1103}
1104
1105/**
1106 * Prepare the renderer for polygon filling.
1107 */
1108VGboolean renderer_polygon_fill_begin(struct renderer *renderer,
1109                                      VGboolean save_dsa)
1110{
1111   struct pipe_depth_stencil_alpha_state dsa;
1112
1113   assert(renderer->state == RENDERER_STATE_INIT);
1114
1115   if (save_dsa)
1116      cso_save_depth_stencil_alpha(renderer->cso);
1117
1118   /* setup stencil ops */
1119   memset(&dsa, 0, sizeof(dsa));
1120   dsa.stencil[0].enabled = 1;
1121   dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL;
1122   dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
1123   dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
1124   dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
1125   dsa.stencil[0].valuemask = ~0;
1126   dsa.stencil[0].writemask = ~0;
1127   dsa.depth = renderer->g3d.dsa.depth;
1128   cso_set_depth_stencil_alpha(renderer->cso, &dsa);
1129
1130   renderer->state = RENDERER_STATE_POLYGON_FILL;
1131
1132   return VG_TRUE;
1133}
1134
1135/**
1136 * Fill a polygon.
1137 */
1138void renderer_polygon_fill(struct renderer *renderer,
1139                           VGfloat min_x, VGfloat min_y,
1140                           VGfloat max_x, VGfloat max_y)
1141{
1142   assert(renderer->state == RENDERER_STATE_POLYGON_FILL);
1143
1144   renderer_quad_pos(renderer, min_x, min_y, max_x, max_y, VG_TRUE);
1145   renderer_quad_draw(renderer);
1146}
1147
1148/**
1149 * End polygon filling.
1150 */
1151void renderer_polygon_fill_end(struct renderer *renderer)
1152{
1153   assert(renderer->state == RENDERER_STATE_POLYGON_FILL);
1154
1155   cso_restore_depth_stencil_alpha(renderer->cso);
1156
1157   renderer->state = RENDERER_STATE_INIT;
1158}
1159
1160struct renderer * renderer_create(struct vg_context *owner)
1161{
1162   struct renderer *renderer;
1163   struct pipe_rasterizer_state *raster;
1164   struct pipe_stencil_ref sr;
1165   VGint i;
1166
1167   renderer = CALLOC_STRUCT(renderer);
1168   if (!renderer)
1169      return NULL;
1170
1171   renderer->pipe = owner->pipe;
1172   renderer->cso = owner->cso_context;
1173
1174   /* init vertex data that doesn't change */
1175   for (i = 0; i < 4; i++)
1176      renderer->vertices[i][0][3] = 1.0f; /* w */
1177
1178   for (i = 0; i < 2; i++) {
1179      renderer->velems[i].src_offset = i * 4 * sizeof(float);
1180      renderer->velems[i].instance_divisor = 0;
1181      renderer->velems[i].vertex_buffer_index = 0;
1182      renderer->velems[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
1183   }
1184   cso_set_vertex_elements(renderer->cso, 2, renderer->velems);
1185
1186   /* GL rasterization rules */
1187   raster = &renderer->g3d.rasterizer;
1188   memset(raster, 0, sizeof(*raster));
1189   raster->gl_rasterization_rules = 1;
1190   cso_set_rasterizer(renderer->cso, raster);
1191
1192   /* fixed at 0 */
1193   memset(&sr, 0, sizeof(sr));
1194   cso_set_stencil_ref(renderer->cso, &sr);
1195
1196   renderer_set_vs(renderer, RENDERER_VS_PLAIN);
1197
1198   renderer->state = RENDERER_STATE_INIT;
1199
1200   return renderer;
1201}
1202
1203void renderer_destroy(struct renderer *ctx)
1204{
1205   int i;
1206
1207   for (i = 0; i < NUM_RENDERER_VS; i++) {
1208      if (ctx->cached_vs[i])
1209         cso_delete_vertex_shader(ctx->cso, ctx->cached_vs[i]);
1210   }
1211   for (i = 0; i < NUM_RENDERER_FS; i++) {
1212      if (ctx->cached_fs[i])
1213         cso_delete_fragment_shader(ctx->cso, ctx->cached_fs[i]);
1214   }
1215
1216   pipe_resource_reference(&ctx->vs_cbuf, NULL);
1217   pipe_resource_reference(&ctx->fs_cbuf, NULL);
1218
1219   FREE(ctx);
1220}
1221
1222static void update_clip_state(struct renderer *renderer,
1223                              const struct vg_state *state)
1224{
1225   struct pipe_depth_stencil_alpha_state *dsa = &renderer->g3d.dsa;
1226
1227   memset(dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
1228
1229   if (state->scissoring) {
1230      struct pipe_framebuffer_state *fb = &renderer->g3d.fb;
1231      int i;
1232
1233      renderer_scissor_begin(renderer, VG_FALSE);
1234
1235      for (i = 0; i < state->scissor_rects_num; ++i) {
1236         const float x      = state->scissor_rects[i * 4 + 0].f;
1237         const float y      = state->scissor_rects[i * 4 + 1].f;
1238         const float width  = state->scissor_rects[i * 4 + 2].f;
1239         const float height = state->scissor_rects[i * 4 + 3].f;
1240         VGint x0, y0, x1, y1, iw, ih;
1241
1242         x0 = (VGint) x;
1243         y0 = (VGint) y;
1244         if (x0 < 0)
1245            x0 = 0;
1246         if (y0 < 0)
1247            y0 = 0;
1248
1249         /* note that x1 and y1 are exclusive */
1250         x1 = (VGint) ceilf(x + width);
1251         y1 = (VGint) ceilf(y + height);
1252         if (x1 > fb->width)
1253            x1 = fb->width;
1254         if (y1 > fb->height)
1255            y1 = fb->height;
1256
1257         iw = x1 - x0;
1258         ih = y1 - y0;
1259         if (iw > 0 && ih> 0 )
1260            renderer_scissor(renderer, x0, y0, iw, ih);
1261      }
1262
1263      renderer_scissor_end(renderer);
1264
1265      dsa->depth.enabled = 1; /* glEnable(GL_DEPTH_TEST); */
1266      dsa->depth.writemask = 0;/*glDepthMask(FALSE);*/
1267      dsa->depth.func = PIPE_FUNC_GEQUAL;
1268   }
1269}
1270
1271static void renderer_validate_blend(struct renderer *renderer,
1272                                     const struct vg_state *state,
1273                                     enum pipe_format fb_format)
1274{
1275   struct pipe_blend_state blend;
1276
1277   memset(&blend, 0, sizeof(blend));
1278   blend.rt[0].colormask = PIPE_MASK_RGBA;
1279   blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ONE;
1280   blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
1281   blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ZERO;
1282   blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
1283
1284   /* TODO alpha masking happens after blending? */
1285
1286   switch (state->blend_mode) {
1287   case VG_BLEND_SRC:
1288      blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ONE;
1289      blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
1290      blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ZERO;
1291      blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
1292      break;
1293   case VG_BLEND_SRC_OVER:
1294      /* use the blend state only when there is no alpha channel */
1295      if (!util_format_has_alpha(fb_format)) {
1296         blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_SRC_ALPHA;
1297         blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
1298         blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
1299         blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
1300         blend.rt[0].blend_enable = 1;
1301      }
1302      break;
1303   case VG_BLEND_SRC_IN:
1304      blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ONE;
1305      blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_DST_ALPHA;
1306      blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ZERO;
1307      blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
1308      blend.rt[0].blend_enable = 1;
1309      break;
1310   case VG_BLEND_DST_IN:
1311      blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ZERO;
1312      blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO;
1313      blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ONE;
1314      blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
1315      blend.rt[0].blend_enable = 1;
1316      break;
1317   case VG_BLEND_DST_OVER:
1318   case VG_BLEND_MULTIPLY:
1319   case VG_BLEND_SCREEN:
1320   case VG_BLEND_DARKEN:
1321   case VG_BLEND_LIGHTEN:
1322   case VG_BLEND_ADDITIVE:
1323      /* need a shader */
1324      break;
1325   default:
1326      assert(!"not implemented blend mode");
1327      break;
1328   }
1329
1330   cso_set_blend(renderer->cso, &blend);
1331}
1332
1333/**
1334 * Propogate OpenVG state changes to the renderer.  Only framebuffer, blending
1335 * and scissoring states are relevant here.
1336 */
1337void renderer_validate(struct renderer *renderer,
1338                       VGbitfield dirty,
1339                       const struct st_framebuffer *stfb,
1340                       const struct vg_state *state)
1341{
1342   assert(renderer->state == RENDERER_STATE_INIT);
1343
1344   dirty |= renderer->dirty;
1345   renderer->dirty = 0;
1346
1347   if (dirty & FRAMEBUFFER_DIRTY) {
1348      struct pipe_framebuffer_state *fb = &renderer->g3d.fb;
1349      struct matrix *proj = &renderer->projection;
1350
1351      memset(fb, 0, sizeof(struct pipe_framebuffer_state));
1352      fb->width  = stfb->width;
1353      fb->height = stfb->height;
1354      fb->nr_cbufs = 1;
1355      fb->cbufs[0] = stfb->strb->surface;
1356      fb->zsbuf = stfb->dsrb->surface;
1357
1358      cso_set_framebuffer(renderer->cso, fb);
1359      vg_set_viewport(renderer, VEGA_Y0_BOTTOM);
1360
1361      matrix_load_identity(proj);
1362      matrix_translate(proj, -1.0f, -1.0f);
1363      matrix_scale(proj, 2.0f / fb->width, 2.0f / fb->height);
1364
1365      /* we also got a new depth buffer */
1366      if (dirty & DEPTH_STENCIL_DIRTY) {
1367         renderer->pipe->clear(renderer->pipe,
1368               PIPE_CLEAR_DEPTHSTENCIL, NULL, 0.0, 0);
1369      }
1370   }
1371
1372   /* must be last because it renders to the depth buffer*/
1373   if (dirty & DEPTH_STENCIL_DIRTY) {
1374      update_clip_state(renderer, state);
1375      cso_set_depth_stencil_alpha(renderer->cso, &renderer->g3d.dsa);
1376   }
1377
1378   if (dirty & BLEND_DIRTY)
1379      renderer_validate_blend(renderer, state, stfb->strb->format);
1380}
1381
1382/**
1383 * Prepare the renderer for OpenVG pipeline.
1384 */
1385void renderer_validate_for_shader(struct renderer *renderer,
1386                                  const struct pipe_sampler_state **samplers,
1387                                  struct pipe_sampler_view **views,
1388                                  VGint num_samplers,
1389                                  const struct matrix *modelview,
1390                                  void *fs,
1391                                  const void *const_buffer,
1392                                  VGint const_buffer_len)
1393{
1394   struct matrix mvp = renderer->projection;
1395
1396   /* will be used in POLYGON_STENCIL and POLYGON_FILL */
1397   matrix_mult(&mvp, modelview);
1398   renderer_set_mvp(renderer, &mvp);
1399
1400   renderer_set_custom_fs(renderer, fs,
1401                          samplers, views, num_samplers,
1402                          const_buffer, const_buffer_len);
1403}
1404
1405void renderer_validate_for_mask_rendering(struct renderer *renderer,
1406                                          struct pipe_surface *dst,
1407                                          const struct matrix *modelview)
1408{
1409   struct matrix mvp = renderer->projection;
1410
1411   /* will be used in POLYGON_STENCIL and POLYGON_FILL */
1412   matrix_mult(&mvp, modelview);
1413   renderer_set_mvp(renderer, &mvp);
1414
1415   renderer_set_target(renderer, dst, renderer->g3d.fb.zsbuf, VG_FALSE);
1416   renderer_set_blend(renderer, ~0);
1417   renderer_set_fs(renderer, RENDERER_FS_WHITE);
1418
1419   /* set internal dirty flags (hacky!) */
1420   renderer->dirty = FRAMEBUFFER_DIRTY | BLEND_DIRTY;
1421}
1422
1423void renderer_copy_surface(struct renderer *ctx,
1424                           struct pipe_surface *src,
1425                           int srcX0, int srcY0,
1426                           int srcX1, int srcY1,
1427                           struct pipe_surface *dst,
1428                           int dstX0, int dstY0,
1429                           int dstX1, int dstY1,
1430                           float z, unsigned filter)
1431{
1432   struct pipe_context *pipe = ctx->pipe;
1433   struct pipe_screen *screen = pipe->screen;
1434   struct pipe_sampler_view view_templ;
1435   struct pipe_sampler_view *view;
1436   struct pipe_box src_box;
1437   struct pipe_resource texTemp, *tex;
1438   const struct pipe_framebuffer_state *fb = &ctx->g3d.fb;
1439   const int srcW = abs(srcX1 - srcX0);
1440   const int srcH = abs(srcY1 - srcY0);
1441   const int srcLeft = MIN2(srcX0, srcX1);
1442   const int srcTop = MIN2(srcY0, srcY1);
1443
1444   assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
1445          filter == PIPE_TEX_MIPFILTER_LINEAR);
1446
1447   if (srcLeft != srcX0) {
1448      /* left-right flip */
1449      int tmp = dstX0;
1450      dstX0 = dstX1;
1451      dstX1 = tmp;
1452   }
1453
1454   if (srcTop != srcY0) {
1455      /* up-down flip */
1456      int tmp = dstY0;
1457      dstY0 = dstY1;
1458      dstY1 = tmp;
1459   }
1460
1461   assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D,
1462                                      0, PIPE_BIND_SAMPLER_VIEW));
1463   assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
1464                                      0, PIPE_BIND_SAMPLER_VIEW));
1465   assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
1466                                      0, PIPE_BIND_RENDER_TARGET));
1467
1468   /*
1469    * XXX for now we're always creating a temporary texture.
1470    * Strictly speaking that's not always needed.
1471    */
1472
1473   /* create temp texture */
1474   memset(&texTemp, 0, sizeof(texTemp));
1475   texTemp.target = PIPE_TEXTURE_2D;
1476   texTemp.format = src->format;
1477   texTemp.last_level = 0;
1478   texTemp.width0 = srcW;
1479   texTemp.height0 = srcH;
1480   texTemp.depth0 = 1;
1481   texTemp.array_size = 1;
1482   texTemp.bind = PIPE_BIND_SAMPLER_VIEW;
1483
1484   tex = screen->resource_create(screen, &texTemp);
1485   if (!tex)
1486      return;
1487
1488   u_sampler_view_default_template(&view_templ, tex, tex->format);
1489   view = pipe->create_sampler_view(pipe, tex, &view_templ);
1490
1491   if (!view)
1492      return;
1493
1494   u_box_2d_zslice(srcLeft, srcTop, src->u.tex.first_layer, srcW, srcH, &src_box);
1495
1496   pipe->resource_copy_region(pipe,
1497                              tex, 0, 0, 0, 0,  /* dest */
1498                              src->texture, 0, &src_box);
1499
1500   assert(floatsEqual(z, 0.0f));
1501
1502   /* draw */
1503   if (fb->cbufs[0] == dst) {
1504      /* transform back to surface coordinates */
1505      dstY0 = dst->height - dstY0;
1506      dstY1 = dst->height - dstY1;
1507
1508      if (renderer_drawtex_begin(ctx, view)) {
1509         renderer_drawtex(ctx,
1510               dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0,
1511               0, 0, view->texture->width0, view->texture->height0);
1512         renderer_drawtex_end(ctx);
1513      }
1514   }
1515   else {
1516      if (renderer_copy_begin(ctx, dst, VG_TRUE, view)) {
1517         renderer_copy(ctx,
1518               dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0,
1519               0, 0, view->texture->width0, view->texture->height0);
1520         renderer_copy_end(ctx);
1521      }
1522   }
1523}
1524
1525void renderer_texture_quad(struct renderer *r,
1526                           struct pipe_resource *tex,
1527                           VGfloat x1offset, VGfloat y1offset,
1528                           VGfloat x2offset, VGfloat y2offset,
1529                           VGfloat x1, VGfloat y1,
1530                           VGfloat x2, VGfloat y2,
1531                           VGfloat x3, VGfloat y3,
1532                           VGfloat x4, VGfloat y4)
1533{
1534   const VGfloat z = 0.0f;
1535
1536   assert(r->state == RENDERER_STATE_INIT);
1537   assert(tex->width0 != 0);
1538   assert(tex->height0 != 0);
1539
1540   cso_save_vertex_shader(r->cso);
1541
1542   renderer_set_vs(r, RENDERER_VS_TEXTURE);
1543
1544   /* manually set up positions */
1545   r->vertices[0][0][0] = x1;
1546   r->vertices[0][0][1] = y1;
1547   r->vertices[0][0][2] = z;
1548
1549   r->vertices[1][0][0] = x2;
1550   r->vertices[1][0][1] = y2;
1551   r->vertices[1][0][2] = z;
1552
1553   r->vertices[2][0][0] = x3;
1554   r->vertices[2][0][1] = y3;
1555   r->vertices[2][0][2] = z;
1556
1557   r->vertices[3][0][0] = x4;
1558   r->vertices[3][0][1] = y4;
1559   r->vertices[3][0][2] = z;
1560
1561   /* texcoords */
1562   renderer_quad_texcoord(r, x1offset, y1offset,
1563         x2offset, y2offset, tex->width0, tex->height0);
1564
1565   renderer_quad_draw(r);
1566
1567   cso_restore_vertex_shader(r->cso);
1568}
1569