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