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