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