renderer.c revision a84a1e344f544ec4da61809d4f09853a94d93e07
1/**************************************************************************
2 *
3 * Copyright 2009 VMware, Inc.  All Rights Reserved.
4 * Copyright 2010 LunarG, Inc.  All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28#include "renderer.h"
29
30#include "vg_context.h"
31#include "image.h"
32
33#include "pipe/p_context.h"
34#include "pipe/p_state.h"
35#include "util/u_inlines.h"
36#include "pipe/p_screen.h"
37#include "pipe/p_shader_tokens.h"
38
39#include "util/u_draw_quad.h"
40#include "util/u_simple_shaders.h"
41#include "util/u_memory.h"
42#include "util/u_sampler.h"
43#include "util/u_surface.h"
44#include "util/u_math.h"
45
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
1269/**
1270 * Propogate OpenVG state changes to the renderer.  Only framebuffer, blending
1271 * and scissoring states are relevant here.
1272 */
1273void renderer_validate(struct renderer *renderer,
1274                       VGbitfield dirty,
1275                       const struct st_framebuffer *stfb,
1276                       const struct vg_state *state)
1277{
1278   assert(renderer->state == RENDERER_STATE_INIT);
1279
1280   dirty |= renderer->dirty;
1281   renderer->dirty = 0;
1282
1283   if (dirty & BLEND_DIRTY) {
1284      struct pipe_blend_state blend;
1285      memset(&blend, 0, sizeof(blend));
1286      blend.rt[0].blend_enable = 1;
1287      blend.rt[0].colormask = PIPE_MASK_RGBA;
1288
1289      switch (state->blend_mode) {
1290      case VG_BLEND_SRC:
1291         blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ONE;
1292         blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
1293         blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ZERO;
1294         blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
1295         blend.rt[0].blend_enable = 0;
1296         break;
1297      case VG_BLEND_SRC_OVER:
1298         blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_SRC_ALPHA;
1299         blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
1300         blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
1301         blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
1302         break;
1303      case VG_BLEND_DST_OVER:
1304         blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_INV_DST_ALPHA;
1305         blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_INV_DST_ALPHA;
1306         blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_DST_ALPHA;
1307         blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_DST_ALPHA;
1308         break;
1309      case VG_BLEND_SRC_IN:
1310         blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_DST_ALPHA;
1311         blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_DST_ALPHA;
1312         blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ZERO;
1313         blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
1314         break;
1315      case VG_BLEND_DST_IN:
1316         blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ZERO;
1317         blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO;
1318         blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_SRC_ALPHA;
1319         blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
1320         break;
1321      case VG_BLEND_MULTIPLY:
1322      case VG_BLEND_SCREEN:
1323      case VG_BLEND_DARKEN:
1324      case VG_BLEND_LIGHTEN:
1325         blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ONE;
1326         blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
1327         blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ZERO;
1328         blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
1329         blend.rt[0].blend_enable = 0;
1330         break;
1331      case VG_BLEND_ADDITIVE:
1332         blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ONE;
1333         blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
1334         blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ONE;
1335         blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
1336         break;
1337      default:
1338         assert(!"not implemented blend mode");
1339      }
1340      cso_set_blend(renderer->cso, &blend);
1341   }
1342
1343   if (dirty & FRAMEBUFFER_DIRTY) {
1344      struct pipe_framebuffer_state *fb = &renderer->g3d.fb;
1345      struct matrix *proj = &renderer->projection;
1346
1347      memset(fb, 0, sizeof(struct pipe_framebuffer_state));
1348      fb->width  = stfb->width;
1349      fb->height = stfb->height;
1350      fb->nr_cbufs = 1;
1351      fb->cbufs[0] = stfb->strb->surface;
1352      fb->zsbuf = stfb->dsrb->surface;
1353
1354      cso_set_framebuffer(renderer->cso, fb);
1355      vg_set_viewport(renderer, VEGA_Y0_BOTTOM);
1356
1357      matrix_load_identity(proj);
1358      matrix_translate(proj, -1.0f, -1.0f);
1359      matrix_scale(proj, 2.0f / fb->width, 2.0f / fb->height);
1360
1361      /* we also got a new depth buffer */
1362      if (dirty & DEPTH_STENCIL_DIRTY) {
1363         renderer->pipe->clear(renderer->pipe,
1364               PIPE_CLEAR_DEPTHSTENCIL, NULL, 0.0, 0);
1365      }
1366   }
1367
1368   /* must be last because it renders to the depth buffer*/
1369   if (dirty & DEPTH_STENCIL_DIRTY) {
1370      update_clip_state(renderer, state);
1371      cso_set_depth_stencil_alpha(renderer->cso, &renderer->g3d.dsa);
1372   }
1373}
1374
1375/**
1376 * Prepare the renderer for OpenVG pipeline.
1377 */
1378void renderer_validate_for_shader(struct renderer *renderer,
1379                                  const struct pipe_sampler_state **samplers,
1380                                  struct pipe_sampler_view **views,
1381                                  VGint num_samplers,
1382                                  const struct matrix *modelview,
1383                                  void *fs,
1384                                  const void *const_buffer,
1385                                  VGint const_buffer_len)
1386{
1387   struct matrix mvp = renderer->projection;
1388
1389   /* will be used in POLYGON_STENCIL and POLYGON_FILL */
1390   matrix_mult(&mvp, modelview);
1391   renderer_set_mvp(renderer, &mvp);
1392
1393   renderer_set_custom_fs(renderer, fs,
1394                          samplers, views, num_samplers,
1395                          const_buffer, const_buffer_len);
1396}
1397
1398void renderer_validate_for_mask_rendering(struct renderer *renderer,
1399                                          struct pipe_surface *dst,
1400                                          const struct matrix *modelview)
1401{
1402   struct matrix mvp = renderer->projection;
1403
1404   /* will be used in POLYGON_STENCIL and POLYGON_FILL */
1405   matrix_mult(&mvp, modelview);
1406   renderer_set_mvp(renderer, &mvp);
1407
1408   renderer_set_target(renderer, dst, renderer->g3d.fb.zsbuf, VG_FALSE);
1409   renderer_set_blend(renderer, ~0);
1410   renderer_set_fs(renderer, RENDERER_FS_WHITE);
1411
1412   /* set internal dirty flags (hacky!) */
1413   renderer->dirty = FRAMEBUFFER_DIRTY | BLEND_DIRTY;
1414}
1415
1416void renderer_copy_surface(struct renderer *ctx,
1417                           struct pipe_surface *src,
1418                           int srcX0, int srcY0,
1419                           int srcX1, int srcY1,
1420                           struct pipe_surface *dst,
1421                           int dstX0, int dstY0,
1422                           int dstX1, int dstY1,
1423                           float z, unsigned filter)
1424{
1425   struct pipe_context *pipe = ctx->pipe;
1426   struct pipe_screen *screen = pipe->screen;
1427   struct pipe_sampler_view view_templ;
1428   struct pipe_sampler_view *view;
1429   struct pipe_box src_box;
1430   struct pipe_resource texTemp, *tex;
1431   const struct pipe_framebuffer_state *fb = &ctx->g3d.fb;
1432   const int srcW = abs(srcX1 - srcX0);
1433   const int srcH = abs(srcY1 - srcY0);
1434   const int srcLeft = MIN2(srcX0, srcX1);
1435   const int srcTop = MIN2(srcY0, srcY1);
1436
1437   assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
1438          filter == PIPE_TEX_MIPFILTER_LINEAR);
1439
1440   if (srcLeft != srcX0) {
1441      /* left-right flip */
1442      int tmp = dstX0;
1443      dstX0 = dstX1;
1444      dstX1 = tmp;
1445   }
1446
1447   if (srcTop != srcY0) {
1448      /* up-down flip */
1449      int tmp = dstY0;
1450      dstY0 = dstY1;
1451      dstY1 = tmp;
1452   }
1453
1454   assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D,
1455                                      0, PIPE_BIND_SAMPLER_VIEW, 0));
1456   assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
1457                                      0, PIPE_BIND_SAMPLER_VIEW, 0));
1458   assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
1459                                      0, PIPE_BIND_RENDER_TARGET, 0));
1460
1461   /*
1462    * XXX for now we're always creating a temporary texture.
1463    * Strictly speaking that's not always needed.
1464    */
1465
1466   /* create temp texture */
1467   memset(&texTemp, 0, sizeof(texTemp));
1468   texTemp.target = PIPE_TEXTURE_2D;
1469   texTemp.format = src->format;
1470   texTemp.last_level = 0;
1471   texTemp.width0 = srcW;
1472   texTemp.height0 = srcH;
1473   texTemp.depth0 = 1;
1474   texTemp.array_size = 1;
1475   texTemp.bind = PIPE_BIND_SAMPLER_VIEW;
1476
1477   tex = screen->resource_create(screen, &texTemp);
1478   if (!tex)
1479      return;
1480
1481   u_sampler_view_default_template(&view_templ, tex, tex->format);
1482   view = pipe->create_sampler_view(pipe, tex, &view_templ);
1483
1484   if (!view)
1485      return;
1486
1487   u_box_2d_zslice(srcLeft, srcTop, src->u.tex.first_layer, srcW, srcH, &src_box);
1488
1489   pipe->resource_copy_region(pipe,
1490                              tex, 0, 0, 0, 0,  /* dest */
1491                              src->texture, 0, &src_box);
1492
1493   assert(floatsEqual(z, 0.0f));
1494
1495   /* draw */
1496   if (fb->cbufs[0] == dst) {
1497      /* transform back to surface coordinates */
1498      dstY0 = dst->height - dstY0;
1499      dstY1 = dst->height - dstY1;
1500
1501      if (renderer_drawtex_begin(ctx, view)) {
1502         renderer_drawtex(ctx,
1503               dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0,
1504               0, 0, view->texture->width0, view->texture->height0);
1505         renderer_drawtex_end(ctx);
1506      }
1507   }
1508   else {
1509      if (renderer_copy_begin(ctx, dst, VG_TRUE, view)) {
1510         renderer_copy(ctx,
1511               dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0,
1512               0, 0, view->texture->width0, view->texture->height0);
1513         renderer_copy_end(ctx);
1514      }
1515   }
1516}
1517
1518void renderer_texture_quad(struct renderer *r,
1519                           struct pipe_resource *tex,
1520                           VGfloat x1offset, VGfloat y1offset,
1521                           VGfloat x2offset, VGfloat y2offset,
1522                           VGfloat x1, VGfloat y1,
1523                           VGfloat x2, VGfloat y2,
1524                           VGfloat x3, VGfloat y3,
1525                           VGfloat x4, VGfloat y4)
1526{
1527   const VGfloat z = 0.0f;
1528
1529   assert(r->state == RENDERER_STATE_INIT);
1530   assert(tex->width0 != 0);
1531   assert(tex->height0 != 0);
1532
1533   cso_save_vertex_shader(r->cso);
1534
1535   renderer_set_vs(r, RENDERER_VS_TEXTURE);
1536
1537   /* manually set up positions */
1538   r->vertices[0][0][0] = x1;
1539   r->vertices[0][0][1] = y1;
1540   r->vertices[0][0][2] = z;
1541
1542   r->vertices[1][0][0] = x2;
1543   r->vertices[1][0][1] = y2;
1544   r->vertices[1][0][2] = z;
1545
1546   r->vertices[2][0][0] = x3;
1547   r->vertices[2][0][1] = y3;
1548   r->vertices[2][0][2] = z;
1549
1550   r->vertices[3][0][0] = x4;
1551   r->vertices[3][0][1] = y4;
1552   r->vertices[3][0][2] = z;
1553
1554   /* texcoords */
1555   renderer_quad_texcoord(r, x1offset, y1offset,
1556         x2offset, y2offset, tex->width0, tex->height0);
1557
1558   renderer_quad_draw(r);
1559
1560   cso_restore_vertex_shader(r->cso);
1561}
1562