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