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