st/vega: Remove.
[mesa.git] / src / gallium / state_trackers / vega / renderer.c
diff --git a/src/gallium/state_trackers/vega/renderer.c b/src/gallium/state_trackers/vega/renderer.c
deleted file mode 100644 (file)
index d369c32..0000000
+++ /dev/null
@@ -1,1558 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2009 VMware, Inc.  All Rights Reserved.
- * Copyright 2010 LunarG, Inc.  All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-#include "renderer.h"
-
-#include "vg_context.h"
-
-#include "pipe/p_context.h"
-#include "pipe/p_state.h"
-#include "util/u_inlines.h"
-#include "pipe/p_screen.h"
-#include "pipe/p_shader_tokens.h"
-
-#include "util/u_draw_quad.h"
-#include "util/u_simple_shaders.h"
-#include "util/u_memory.h"
-#include "util/u_sampler.h"
-#include "util/u_surface.h"
-#include "util/u_math.h"
-#include "util/u_format.h"
-
-#include "cso_cache/cso_context.h"
-#include "tgsi/tgsi_ureg.h"
-
-typedef enum {
-   RENDERER_STATE_INIT,
-   RENDERER_STATE_COPY,
-   RENDERER_STATE_DRAWTEX,
-   RENDERER_STATE_SCISSOR,
-   RENDERER_STATE_CLEAR,
-   RENDERER_STATE_FILTER,
-   RENDERER_STATE_POLYGON_STENCIL,
-   RENDERER_STATE_POLYGON_FILL,
-   NUM_RENDERER_STATES
-} RendererState;
-
-typedef enum {
-   RENDERER_VS_PLAIN,
-   RENDERER_VS_COLOR,
-   RENDERER_VS_TEXTURE,
-   NUM_RENDERER_VS
-} RendererVs;
-
-typedef enum {
-   RENDERER_FS_COLOR,
-   RENDERER_FS_TEXTURE,
-   RENDERER_FS_SCISSOR,
-   RENDERER_FS_WHITE,
-   NUM_RENDERER_FS
-} RendererFs;
-
-struct renderer {
-   struct pipe_context *pipe;
-   struct cso_context *cso;
-
-   VGbitfield dirty;
-   struct {
-      struct pipe_rasterizer_state rasterizer;
-      struct pipe_depth_stencil_alpha_state dsa;
-      struct pipe_framebuffer_state fb;
-   } g3d;
-   struct matrix projection;
-
-   struct matrix mvp;
-   struct pipe_resource *vs_cbuf;
-
-   struct pipe_resource *fs_cbuf;
-   VGfloat fs_cbuf_data[32];
-   VGint fs_cbuf_len;
-
-   struct pipe_vertex_element velems[2];
-   VGfloat vertices[4][2][4];
-
-   void *cached_vs[NUM_RENDERER_VS];
-   void *cached_fs[NUM_RENDERER_FS];
-
-   RendererState state;
-
-   /* state data */
-   union {
-      struct {
-         VGint tex_width;
-         VGint tex_height;
-      } copy;
-
-      struct {
-         VGint tex_width;
-         VGint tex_height;
-      } drawtex;
-
-      struct {
-         VGboolean restore_dsa;
-      } scissor;
-
-      struct {
-         VGboolean use_sampler;
-         VGint tex_width, tex_height;
-      } filter;
-
-      struct {
-         struct pipe_depth_stencil_alpha_state dsa;
-         VGboolean manual_two_sides;
-         VGboolean restore_dsa;
-      } polygon_stencil;
-   } u;
-};
-
-/**
- * Return VG_TRUE if the renderer can use the resource as the asked bindings.
- */
-static VGboolean renderer_can_support(struct renderer *renderer,
-                                      struct pipe_resource *res,
-                                      unsigned bindings)
-{
-   struct pipe_screen *screen = renderer->pipe->screen;
-
-   return screen->is_format_supported(screen,
-         res->format, res->target, 0, bindings);
-}
-
-/**
- * Set the model-view-projection matrix used by vertex shaders.
- */
-static void renderer_set_mvp(struct renderer *renderer,
-                             const struct matrix *mvp)
-{
-   struct matrix *cur = &renderer->mvp;
-   struct pipe_resource *cbuf;
-   VGfloat consts[3][4];
-   VGint i;
-
-   /* projection only */
-   if (!mvp)
-      mvp = &renderer->projection;
-
-   /* re-upload only if necessary */
-   if (memcmp(cur, mvp, sizeof(*mvp)) == 0)
-      return;
-
-   /* 3x3 matrix to 3 constant vectors (no Z) */
-   for (i = 0; i < 3; i++) {
-      consts[i][0] = mvp->m[i + 0];
-      consts[i][1] = mvp->m[i + 3];
-      consts[i][2] = 0.0f;
-      consts[i][3] = mvp->m[i + 6];
-   }
-
-   cbuf = renderer->vs_cbuf;
-   pipe_resource_reference(&cbuf, NULL);
-   cbuf = pipe_buffer_create(renderer->pipe->screen,
-                             PIPE_BIND_CONSTANT_BUFFER,
-                             PIPE_USAGE_DEFAULT,
-                             sizeof(consts));
-   if (cbuf) {
-      pipe_buffer_write(renderer->pipe, cbuf,
-            0, sizeof(consts), consts);
-   }
-   pipe_set_constant_buffer(renderer->pipe,
-         PIPE_SHADER_VERTEX, 0, cbuf);
-
-   memcpy(cur, mvp, sizeof(*mvp));
-   renderer->vs_cbuf = cbuf;
-}
-
-/**
- * Create a simple vertex shader that passes through position and the given
- * attribute.
- */
-static void *create_passthrough_vs(struct pipe_context *pipe, int semantic_name)
-{
-   struct ureg_program *ureg;
-   struct ureg_src src[2], constants[3];
-   struct ureg_dst dst[2], tmp;
-   int i;
-
-   ureg = ureg_create(TGSI_PROCESSOR_VERTEX);
-   if (!ureg)
-      return NULL;
-
-   /* position is in user coordinates */
-   src[0] = ureg_DECL_vs_input(ureg, 0);
-   dst[0] = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
-   tmp = ureg_DECL_temporary(ureg);
-   for (i = 0; i < Elements(constants); i++)
-      constants[i] = ureg_DECL_constant(ureg, i);
-
-   /* transform to clipped coordinates */
-   ureg_DP4(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), src[0], constants[0]);
-   ureg_DP4(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Y), src[0], constants[1]);
-   ureg_MOV(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Z), src[0]);
-   ureg_DP4(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_W), src[0], constants[2]);
-   ureg_MOV(ureg, dst[0], ureg_src(tmp));
-
-   if (semantic_name >= 0) {
-      src[1] = ureg_DECL_vs_input(ureg, 1);
-      dst[1] = ureg_DECL_output(ureg, semantic_name, 0);
-      ureg_MOV(ureg, dst[1], src[1]);
-   }
-
-   ureg_END(ureg);
-
-   return ureg_create_shader_and_destroy(ureg, pipe);
-}
-
-/**
- * Set renderer vertex shader.
- *
- * This function modifies vertex_shader state.
- */
-static void renderer_set_vs(struct renderer *r, RendererVs id)
-{
-   /* create as needed */
-   if (!r->cached_vs[id]) {
-      int semantic_name = -1;
-
-      switch (id) {
-      case RENDERER_VS_PLAIN:
-         break;
-      case RENDERER_VS_COLOR:
-         semantic_name = TGSI_SEMANTIC_COLOR;
-         break;
-      case RENDERER_VS_TEXTURE:
-         semantic_name = TGSI_SEMANTIC_GENERIC;
-         break;
-      default:
-         assert(!"Unknown renderer vs id");
-         break;
-      }
-
-      r->cached_vs[id] = create_passthrough_vs(r->pipe, semantic_name);
-   }
-
-   cso_set_vertex_shader_handle(r->cso, r->cached_vs[id]);
-}
-
-/**
- * Create a simple fragment shader that sets the depth to 0.0f.
- */
-static void *create_scissor_fs(struct pipe_context *pipe)
-{
-   struct ureg_program *ureg;
-   struct ureg_dst out;
-   struct ureg_src imm;
-
-   ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
-   out = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
-   imm = ureg_imm4f(ureg, 0.0f, 0.0f, 0.0f, 0.0f);
-
-   ureg_MOV(ureg, ureg_writemask(out, TGSI_WRITEMASK_Z), imm);
-   ureg_END(ureg);
-
-   return ureg_create_shader_and_destroy(ureg, pipe);
-}
-
-/**
- * Create a simple fragment shader that sets the color to white.
- */
-static void *create_white_fs(struct pipe_context *pipe)
-{
-   struct ureg_program *ureg;
-   struct ureg_dst out;
-   struct ureg_src imm;
-
-   ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
-   out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
-   imm = ureg_imm4f(ureg, 1.0f, 1.0f, 1.0f, 1.0f);
-
-   ureg_MOV(ureg, out, imm);
-   ureg_END(ureg);
-
-   return ureg_create_shader_and_destroy(ureg, pipe);
-}
-
-/**
- * Set renderer fragment shader.
- *
- * This function modifies fragment_shader state.
- */
-static void renderer_set_fs(struct renderer *r, RendererFs id)
-{
-   /* create as needed */
-   if (!r->cached_fs[id]) {
-      void *fs = NULL;
-
-      switch (id) {
-      case RENDERER_FS_COLOR:
-         fs = util_make_fragment_passthrough_shader(r->pipe,
-                          TGSI_SEMANTIC_COLOR, TGSI_INTERPOLATE_PERSPECTIVE,
-                          TRUE);
-         break;
-      case RENDERER_FS_TEXTURE:
-         fs = util_make_fragment_tex_shader(r->pipe,
-               TGSI_TEXTURE_2D, TGSI_INTERPOLATE_LINEAR);
-         break;
-      case RENDERER_FS_SCISSOR:
-         fs = create_scissor_fs(r->pipe);
-         break;
-      case RENDERER_FS_WHITE:
-         fs = create_white_fs(r->pipe);
-         break;
-      default:
-         assert(!"Unknown renderer fs id");
-         break;
-      }
-
-      r->cached_fs[id] = fs;
-   }
-
-   cso_set_fragment_shader_handle(r->cso, r->cached_fs[id]);
-}
-
-typedef enum {
-   VEGA_Y0_TOP,
-   VEGA_Y0_BOTTOM
-} VegaOrientation;
-
-static void vg_set_viewport(struct renderer *r,
-                            VegaOrientation orientation)
-{
-   const struct pipe_framebuffer_state *fb = &r->g3d.fb;
-   struct pipe_viewport_state viewport;
-   VGfloat y_scale = (orientation == VEGA_Y0_BOTTOM) ? -2.f : 2.f;
-
-   viewport.scale[0] =  fb->width / 2.f;
-   viewport.scale[1] =  fb->height / y_scale;
-   viewport.scale[2] =  1.0;
-   viewport.translate[0] = fb->width / 2.f;
-   viewport.translate[1] = fb->height / 2.f;
-   viewport.translate[2] = 0.0;
-
-   cso_set_viewport(r->cso, &viewport);
-}
-
-/**
- * Set renderer target.
- *
- * This function modifies framebuffer and viewport states.
- */
-static void renderer_set_target(struct renderer *r,
-                                struct pipe_surface *cbuf,
-                                struct pipe_surface *zsbuf,
-                                VGboolean y0_top)
-{
-   struct pipe_framebuffer_state fb;
-
-   memset(&fb, 0, sizeof(fb));
-   fb.width = cbuf->width;
-   fb.height = cbuf->height;
-   fb.cbufs[0] = cbuf;
-   fb.nr_cbufs = 1;
-   fb.zsbuf = zsbuf;
-   cso_set_framebuffer(r->cso, &fb);
-
-   vg_set_viewport(r, (y0_top) ? VEGA_Y0_TOP : VEGA_Y0_BOTTOM);
-}
-
-/**
- * Set renderer blend state.  Blending is disabled.
- *
- * This function modifies blend state.
- */
-static void renderer_set_blend(struct renderer *r,
-                               VGbitfield channel_mask)
-{
-   struct pipe_blend_state blend;
-
-   memset(&blend, 0, sizeof(blend));
-
-   blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
-   blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
-   blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
-   blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
-
-   if (channel_mask & VG_RED)
-      blend.rt[0].colormask |= PIPE_MASK_R;
-   if (channel_mask & VG_GREEN)
-      blend.rt[0].colormask |= PIPE_MASK_G;
-   if (channel_mask & VG_BLUE)
-      blend.rt[0].colormask |= PIPE_MASK_B;
-   if (channel_mask & VG_ALPHA)
-      blend.rt[0].colormask |= PIPE_MASK_A;
-
-   cso_set_blend(r->cso, &blend);
-}
-
-/**
- * Set renderer sampler and view states.
- *
- * This function modifies samplers and fragment_sampler_views states.
- */
-static void renderer_set_samplers(struct renderer *r,
-                                  uint num_views,
-                                  struct pipe_sampler_view **views)
-{
-   struct pipe_sampler_state sampler;
-   unsigned tex_filter = PIPE_TEX_FILTER_NEAREST;
-   unsigned tex_wrap = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
-   uint i;
-
-   memset(&sampler, 0, sizeof(sampler));
-
-   sampler.min_img_filter = tex_filter;
-   sampler.mag_img_filter = tex_filter;
-   sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
-
-   sampler.wrap_s = tex_wrap;
-   sampler.wrap_t = tex_wrap;
-   sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
-
-   sampler.normalized_coords = 1;
-
-   /* set samplers */
-   for (i = 0; i < num_views; i++)
-      cso_single_sampler(r->cso, PIPE_SHADER_FRAGMENT, i, &sampler);
-   cso_single_sampler_done(r->cso, PIPE_SHADER_FRAGMENT);
-
-   /* set views */
-   cso_set_sampler_views(r->cso, PIPE_SHADER_FRAGMENT, num_views, views);
-}
-
-/**
- * Set custom renderer fragment shader, and optionally set samplers and views
- * and upload the fragment constant buffer.
- *
- * This function modifies fragment_shader, samplers and fragment_sampler_views
- * states.
- */
-static void renderer_set_custom_fs(struct renderer *renderer,
-                                   void *fs,
-                                   const struct pipe_sampler_state **samplers,
-                                   struct pipe_sampler_view **views,
-                                   VGint num_samplers,
-                                   const void *const_buffer,
-                                   VGint const_buffer_len)
-{
-   cso_set_fragment_shader_handle(renderer->cso, fs);
-
-   /* set samplers and views */
-   if (num_samplers) {
-      cso_set_samplers(renderer->cso, PIPE_SHADER_FRAGMENT, num_samplers, samplers);
-      cso_set_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT, num_samplers, views);
-   }
-
-   /* upload fs constant buffer */
-   if (const_buffer_len) {
-      struct pipe_resource *cbuf = renderer->fs_cbuf;
-
-      if (!cbuf || renderer->fs_cbuf_len != const_buffer_len ||
-          memcmp(renderer->fs_cbuf_data, const_buffer, const_buffer_len)) {
-         pipe_resource_reference(&cbuf, NULL);
-
-         cbuf = pipe_buffer_create(renderer->pipe->screen,
-               PIPE_BIND_CONSTANT_BUFFER, PIPE_USAGE_DEFAULT,
-               const_buffer_len);
-         pipe_buffer_write(renderer->pipe, cbuf, 0,
-               const_buffer_len, const_buffer);
-         pipe_set_constant_buffer(renderer->pipe,
-               PIPE_SHADER_FRAGMENT, 0, cbuf);
-
-         renderer->fs_cbuf = cbuf;
-         if (const_buffer_len <= sizeof(renderer->fs_cbuf_data)) {
-            memcpy(renderer->fs_cbuf_data, const_buffer, const_buffer_len);
-            renderer->fs_cbuf_len = const_buffer_len;
-         }
-         else {
-            renderer->fs_cbuf_len = 0;
-         }
-      }
-   }
-}
-
-/**
- * Setup renderer quad position.
- */
-static void renderer_quad_pos(struct renderer *r,
-                              VGfloat x0, VGfloat y0,
-                              VGfloat x1, VGfloat y1,
-                              VGboolean scissor)
-{
-   VGfloat z;
-
-   /* the depth test is used for scissoring */
-   z = (scissor) ? 0.0f : 1.0f;
-
-   /* positions */
-   r->vertices[0][0][0] = x0;
-   r->vertices[0][0][1] = y0;
-   r->vertices[0][0][2] = z;
-
-   r->vertices[1][0][0] = x1;
-   r->vertices[1][0][1] = y0;
-   r->vertices[1][0][2] = z;
-
-   r->vertices[2][0][0] = x1;
-   r->vertices[2][0][1] = y1;
-   r->vertices[2][0][2] = z;
-
-   r->vertices[3][0][0] = x0;
-   r->vertices[3][0][1] = y1;
-   r->vertices[3][0][2] = z;
-}
-
-/**
- * Setup renderer quad texture coordinates.
- */
-static void renderer_quad_texcoord(struct renderer *r,
-                                   VGfloat x0, VGfloat y0,
-                                   VGfloat x1, VGfloat y1,
-                                   VGint tex_width, VGint tex_height)
-{
-   VGfloat s0, t0, s1, t1, r0, q0;
-   VGint i;
-
-   s0 = x0 / tex_width;
-   s1 = x1 / tex_width;
-   t0 = y0 / tex_height;
-   t1 = y1 / tex_height;
-   r0 = 0.0f;
-   q0 = 1.0f;
-
-   /* texcoords */
-   r->vertices[0][1][0] = s0;
-   r->vertices[0][1][1] = t0;
-
-   r->vertices[1][1][0] = s1;
-   r->vertices[1][1][1] = t0;
-
-   r->vertices[2][1][0] = s1;
-   r->vertices[2][1][1] = t1;
-
-   r->vertices[3][1][0] = s0;
-   r->vertices[3][1][1] = t1;
-
-   for (i = 0; i < 4; i++) {
-      r->vertices[i][1][2] = r0;
-      r->vertices[i][1][3] = q0;
-   }
-}
-
-/**
- * Draw renderer quad.
- */
-static void renderer_quad_draw(struct renderer *r)
-{
-   util_draw_user_vertex_buffer(r->cso, r->vertices, PIPE_PRIM_TRIANGLE_FAN,
-                                Elements(r->vertices),     /* verts */
-                                Elements(r->vertices[0])); /* attribs/vert */
-}
-
-/**
- * Prepare the renderer for copying.
- */
-VGboolean renderer_copy_begin(struct renderer *renderer,
-                              struct pipe_surface *dst,
-                              VGboolean y0_top,
-                              struct pipe_sampler_view *src)
-{
-   assert(renderer->state == RENDERER_STATE_INIT);
-
-   /* sanity check */
-   if (!renderer_can_support(renderer,
-            dst->texture, PIPE_BIND_RENDER_TARGET) ||
-       !renderer_can_support(renderer,
-          src->texture, PIPE_BIND_SAMPLER_VIEW))
-      return VG_FALSE;
-
-   cso_save_framebuffer(renderer->cso);
-   cso_save_viewport(renderer->cso);
-   cso_save_blend(renderer->cso);
-   cso_save_samplers(renderer->cso, PIPE_SHADER_FRAGMENT);
-   cso_save_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT);
-   cso_save_fragment_shader(renderer->cso);
-   cso_save_vertex_shader(renderer->cso);
-
-   renderer_set_target(renderer, dst, NULL, y0_top);
-
-   renderer_set_blend(renderer, ~0);
-   renderer_set_samplers(renderer, 1, &src);
-
-   renderer_set_fs(renderer, RENDERER_FS_TEXTURE);
-   renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
-
-   renderer_set_mvp(renderer, NULL);
-
-   /* remember the texture size */
-   renderer->u.copy.tex_width = src->texture->width0;
-   renderer->u.copy.tex_height = src->texture->height0;
-   renderer->state = RENDERER_STATE_COPY;
-
-   return VG_TRUE;
-}
-
-/**
- * Draw into the destination rectangle given by (x, y, w, h).  The texture is
- * sampled from within the rectangle given by (sx, sy, sw, sh).
- *
- * The coordinates are in surface coordinates.
- */
-void renderer_copy(struct renderer *renderer,
-                   VGint x, VGint y, VGint w, VGint h,
-                   VGint sx, VGint sy, VGint sw, VGint sh)
-{
-   assert(renderer->state == RENDERER_STATE_COPY);
-
-   /* there is no depth buffer for scissoring anyway */
-   renderer_quad_pos(renderer, x, y, x + w, y + h, VG_FALSE);
-   renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
-         renderer->u.copy.tex_width,
-         renderer->u.copy.tex_height);
-
-   renderer_quad_draw(renderer);
-}
-
-/**
- * End copying and restore the states.
- */
-void renderer_copy_end(struct renderer *renderer)
-{
-   assert(renderer->state == RENDERER_STATE_COPY);
-
-   cso_restore_framebuffer(renderer->cso);
-   cso_restore_viewport(renderer->cso);
-   cso_restore_blend(renderer->cso);
-   cso_restore_samplers(renderer->cso, PIPE_SHADER_FRAGMENT);
-   cso_restore_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT);
-   cso_restore_fragment_shader(renderer->cso);
-   cso_restore_vertex_shader(renderer->cso);
-
-   renderer->state = RENDERER_STATE_INIT;
-}
-
-/**
- * Prepare the renderer for textured drawing.
- */
-VGboolean renderer_drawtex_begin(struct renderer *renderer,
-                                 struct pipe_sampler_view *src)
-{
-   assert(renderer->state == RENDERER_STATE_INIT);
-
-   if (!renderer_can_support(renderer, src->texture, PIPE_BIND_SAMPLER_VIEW))
-      return VG_FALSE;
-
-   cso_save_blend(renderer->cso);
-   cso_save_samplers(renderer->cso, PIPE_SHADER_FRAGMENT);
-   cso_save_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT);
-   cso_save_fragment_shader(renderer->cso);
-   cso_save_vertex_shader(renderer->cso);
-
-   renderer_set_blend(renderer, ~0);
-
-   renderer_set_samplers(renderer, 1, &src);
-
-   renderer_set_fs(renderer, RENDERER_FS_TEXTURE);
-   renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
-
-   renderer_set_mvp(renderer, NULL);
-
-   /* remember the texture size */
-   renderer->u.drawtex.tex_width = src->texture->width0;
-   renderer->u.drawtex.tex_height = src->texture->height0;
-   renderer->state = RENDERER_STATE_DRAWTEX;
-
-   return VG_TRUE;
-}
-
-/**
- * Draw into the destination rectangle given by (x, y, w, h).  The texture is
- * sampled from within the rectangle given by (sx, sy, sw, sh).
- *
- * The coordinates are in surface coordinates.
- */
-void renderer_drawtex(struct renderer *renderer,
-                      VGint x, VGint y, VGint w, VGint h,
-                      VGint sx, VGint sy, VGint sw, VGint sh)
-{
-   assert(renderer->state == RENDERER_STATE_DRAWTEX);
-
-   /* with scissoring */
-   renderer_quad_pos(renderer, x, y, x + w, y + h, VG_TRUE);
-   renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
-         renderer->u.drawtex.tex_width,
-         renderer->u.drawtex.tex_height);
-
-   renderer_quad_draw(renderer);
-}
-
-/**
- * End textured drawing and restore the states.
- */
-void renderer_drawtex_end(struct renderer *renderer)
-{
-   assert(renderer->state == RENDERER_STATE_DRAWTEX);
-
-   cso_restore_blend(renderer->cso);
-   cso_restore_samplers(renderer->cso, PIPE_SHADER_FRAGMENT);
-   cso_restore_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT);
-   cso_restore_fragment_shader(renderer->cso);
-   cso_restore_vertex_shader(renderer->cso);
-
-   renderer->state = RENDERER_STATE_INIT;
-}
-
-/**
- * Prepare the renderer for scissor update.  This will reset the depth buffer
- * to 1.0f.
- */
-VGboolean renderer_scissor_begin(struct renderer *renderer,
-                                 VGboolean restore_dsa)
-{
-   struct pipe_depth_stencil_alpha_state dsa;
-
-   assert(renderer->state == RENDERER_STATE_INIT);
-
-   if (restore_dsa)
-      cso_save_depth_stencil_alpha(renderer->cso);
-   cso_save_blend(renderer->cso);
-   cso_save_fragment_shader(renderer->cso);
-
-   /* enable depth writes */
-   memset(&dsa, 0, sizeof(dsa));
-   dsa.depth.enabled = 1;
-   dsa.depth.writemask = 1;
-   dsa.depth.func = PIPE_FUNC_ALWAYS;
-   cso_set_depth_stencil_alpha(renderer->cso, &dsa);
-
-   /* disable color writes */
-   renderer_set_blend(renderer, 0);
-   renderer_set_fs(renderer, RENDERER_FS_SCISSOR);
-
-   renderer_set_mvp(renderer, NULL);
-
-   renderer->u.scissor.restore_dsa = restore_dsa;
-   renderer->state = RENDERER_STATE_SCISSOR;
-
-   /* clear the depth buffer to 1.0f */
-   renderer->pipe->clear(renderer->pipe,
-         PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0f, 0);
-
-   return VG_TRUE;
-}
-
-/**
- * Add a scissor rectangle.  Depth values inside the rectangle will be set to
- * 0.0f.
- */
-void renderer_scissor(struct renderer *renderer,
-                      VGint x, VGint y, VGint width, VGint height)
-{
-   assert(renderer->state == RENDERER_STATE_SCISSOR);
-
-   renderer_quad_pos(renderer, x, y, x + width, y + height, VG_FALSE);
-   renderer_quad_draw(renderer);
-}
-
-/**
- * End scissor update and restore the states.
- */
-void renderer_scissor_end(struct renderer *renderer)
-{
-   assert(renderer->state == RENDERER_STATE_SCISSOR);
-
-   if (renderer->u.scissor.restore_dsa)
-      cso_restore_depth_stencil_alpha(renderer->cso);
-   cso_restore_blend(renderer->cso);
-   cso_restore_fragment_shader(renderer->cso);
-
-   renderer->state = RENDERER_STATE_INIT;
-}
-
-/**
- * Prepare the renderer for clearing.
- */
-VGboolean renderer_clear_begin(struct renderer *renderer)
-{
-   assert(renderer->state == RENDERER_STATE_INIT);
-
-   cso_save_blend(renderer->cso);
-   cso_save_fragment_shader(renderer->cso);
-   cso_save_vertex_shader(renderer->cso);
-
-   renderer_set_blend(renderer, ~0);
-   renderer_set_fs(renderer, RENDERER_FS_COLOR);
-   renderer_set_vs(renderer, RENDERER_VS_COLOR);
-
-   renderer_set_mvp(renderer, NULL);
-
-   renderer->state = RENDERER_STATE_CLEAR;
-
-   return VG_TRUE;
-}
-
-/**
- * Clear the framebuffer with the specified region and color.
- *
- * The coordinates are in surface coordinates.
- */
-void renderer_clear(struct renderer *renderer,
-                    VGint x, VGint y, VGint width, VGint height,
-                    const VGfloat color[4])
-{
-   VGuint i;
-
-   assert(renderer->state == RENDERER_STATE_CLEAR);
-
-   renderer_quad_pos(renderer, x, y, x + width, y + height, VG_TRUE);
-   for (i = 0; i < 4; i++)
-      memcpy(renderer->vertices[i][1], color, sizeof(VGfloat) * 4);
-
-   renderer_quad_draw(renderer);
-}
-
-/**
- * End clearing and retore the states.
- */
-void renderer_clear_end(struct renderer *renderer)
-{
-   assert(renderer->state == RENDERER_STATE_CLEAR);
-
-   cso_restore_blend(renderer->cso);
-   cso_restore_fragment_shader(renderer->cso);
-   cso_restore_vertex_shader(renderer->cso);
-
-   renderer->state = RENDERER_STATE_INIT;
-}
-
-/**
- * Prepare the renderer for image filtering.
- */
-VGboolean renderer_filter_begin(struct renderer *renderer,
-                                struct pipe_resource *dst,
-                                VGboolean y0_top,
-                                VGbitfield channel_mask,
-                                const struct pipe_sampler_state **samplers,
-                                struct pipe_sampler_view **views,
-                                VGint num_samplers,
-                                void *fs,
-                                const void *const_buffer,
-                                VGint const_buffer_len)
-{
-   struct pipe_surface *surf, surf_tmpl;
-
-   assert(renderer->state == RENDERER_STATE_INIT);
-
-   if (!fs)
-      return VG_FALSE;
-   if (!renderer_can_support(renderer, dst, PIPE_BIND_RENDER_TARGET))
-      return VG_FALSE;
-
-   u_surface_default_template(&surf_tmpl, dst);
-   surf = renderer->pipe->create_surface(renderer->pipe, dst, &surf_tmpl);
-   if (!surf)
-      return VG_FALSE;
-
-   cso_save_framebuffer(renderer->cso);
-   cso_save_viewport(renderer->cso);
-   cso_save_blend(renderer->cso);
-
-   /* set the image as the target */
-   renderer_set_target(renderer, surf, NULL, y0_top);
-   pipe_surface_reference(&surf, NULL);
-
-   renderer_set_blend(renderer, channel_mask);
-
-   if (num_samplers) {
-      struct pipe_resource *tex;
-
-      cso_save_samplers(renderer->cso, PIPE_SHADER_FRAGMENT);
-      cso_save_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT);
-      cso_save_fragment_shader(renderer->cso);
-      cso_save_vertex_shader(renderer->cso);
-
-      renderer_set_custom_fs(renderer, fs,
-                             samplers, views, num_samplers,
-                             const_buffer, const_buffer_len);
-      renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
-
-      tex = views[0]->texture;
-      renderer->u.filter.tex_width = tex->width0;
-      renderer->u.filter.tex_height = tex->height0;
-      renderer->u.filter.use_sampler = VG_TRUE;
-   }
-   else {
-      cso_save_fragment_shader(renderer->cso);
-
-      renderer_set_custom_fs(renderer, fs, NULL, NULL, 0,
-                             const_buffer, const_buffer_len);
-
-      renderer->u.filter.use_sampler = VG_FALSE;
-   }
-
-   renderer_set_mvp(renderer, NULL);
-
-   renderer->state = RENDERER_STATE_FILTER;
-
-   return VG_TRUE;
-}
-
-/**
- * Draw into a rectangle of the destination with the specified region of the
- * texture(s).
- *
- * The coordinates are in surface coordinates.
- */
-void renderer_filter(struct renderer *renderer,
-                    VGint x, VGint y, VGint w, VGint h,
-                    VGint sx, VGint sy, VGint sw, VGint sh)
-{
-   assert(renderer->state == RENDERER_STATE_FILTER);
-
-   renderer_quad_pos(renderer, x, y, x + w, y + h, VG_FALSE);
-   if (renderer->u.filter.use_sampler) {
-      renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
-            renderer->u.filter.tex_width,
-            renderer->u.filter.tex_height);
-   }
-
-   renderer_quad_draw(renderer);
-}
-
-/**
- * End image filtering and restore the states.
- */
-void renderer_filter_end(struct renderer *renderer)
-{
-   assert(renderer->state == RENDERER_STATE_FILTER);
-
-   if (renderer->u.filter.use_sampler) {
-      cso_restore_samplers(renderer->cso, PIPE_SHADER_FRAGMENT);
-      cso_restore_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT);
-      cso_restore_vertex_shader(renderer->cso);
-   }
-
-   cso_restore_framebuffer(renderer->cso);
-   cso_restore_viewport(renderer->cso);
-   cso_restore_blend(renderer->cso);
-   cso_restore_fragment_shader(renderer->cso);
-
-   renderer->state = RENDERER_STATE_INIT;
-}
-
-/**
- * Prepare the renderer for polygon silhouette rendering.
- */
-VGboolean renderer_polygon_stencil_begin(struct renderer *renderer,
-                                         struct pipe_vertex_element *velem,
-                                         VGFillRule rule,
-                                         VGboolean restore_dsa)
-{
-   struct pipe_depth_stencil_alpha_state *dsa;
-   VGboolean manual_two_sides;
-
-   assert(renderer->state == RENDERER_STATE_INIT);
-
-   cso_save_vertex_elements(renderer->cso);
-   cso_save_blend(renderer->cso);
-   cso_save_depth_stencil_alpha(renderer->cso);
-
-   cso_set_vertex_elements(renderer->cso, 1, velem);
-
-   /* disable color writes */
-   renderer_set_blend(renderer, 0);
-
-   manual_two_sides = VG_FALSE;
-   dsa = &renderer->u.polygon_stencil.dsa;
-   memset(dsa, 0, sizeof(*dsa));
-   if (rule == VG_EVEN_ODD) {
-      dsa->stencil[0].enabled = 1;
-      dsa->stencil[0].writemask = 1;
-      dsa->stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
-      dsa->stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
-      dsa->stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT;
-      dsa->stencil[0].func = PIPE_FUNC_ALWAYS;
-      dsa->stencil[0].valuemask = ~0;
-   }
-   else {
-      assert(rule == VG_NON_ZERO);
-
-      /* front face */
-      dsa->stencil[0].enabled = 1;
-      dsa->stencil[0].writemask = ~0;
-      dsa->stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
-      dsa->stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
-      dsa->stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
-      dsa->stencil[0].func = PIPE_FUNC_ALWAYS;
-      dsa->stencil[0].valuemask = ~0;
-
-      if (renderer->pipe->screen->get_param(renderer->pipe->screen,
-                                            PIPE_CAP_TWO_SIDED_STENCIL)) {
-         /* back face */
-         dsa->stencil[1] = dsa->stencil[0];
-         dsa->stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
-      }
-      else {
-         manual_two_sides = VG_TRUE;
-      }
-   }
-   cso_set_depth_stencil_alpha(renderer->cso, dsa);
-
-   if (manual_two_sides)
-      cso_save_rasterizer(renderer->cso);
-
-   renderer->u.polygon_stencil.manual_two_sides = manual_two_sides;
-   renderer->u.polygon_stencil.restore_dsa = restore_dsa;
-   renderer->state = RENDERER_STATE_POLYGON_STENCIL;
-
-   return VG_TRUE;
-}
-
-/**
- * Render a polygon silhouette to stencil buffer.
- */
-void renderer_polygon_stencil(struct renderer *renderer,
-                              struct pipe_vertex_buffer *vbuf,
-                              VGuint mode, VGuint start, VGuint count)
-{
-   assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL);
-
-   cso_set_vertex_buffers(renderer->cso, 0, 1, vbuf);
-
-   if (!renderer->u.polygon_stencil.manual_two_sides) {
-      cso_draw_arrays(renderer->cso, mode, start, count);
-   }
-   else {
-      struct pipe_rasterizer_state raster;
-      struct pipe_depth_stencil_alpha_state dsa;
-
-      raster = renderer->g3d.rasterizer;
-      dsa = renderer->u.polygon_stencil.dsa;
-
-      /* front */
-      raster.cull_face = PIPE_FACE_BACK;
-      dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
-
-      cso_set_rasterizer(renderer->cso, &raster);
-      cso_set_depth_stencil_alpha(renderer->cso, &dsa);
-      cso_draw_arrays(renderer->cso, mode, start, count);
-
-      /* back */
-      raster.cull_face = PIPE_FACE_FRONT;
-      dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
-
-      cso_set_rasterizer(renderer->cso, &raster);
-      cso_set_depth_stencil_alpha(renderer->cso, &dsa);
-      cso_draw_arrays(renderer->cso, mode, start, count);
-   }
-}
-
-/**
- * End polygon silhouette rendering.
- */
-void renderer_polygon_stencil_end(struct renderer *renderer)
-{
-   assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL);
-
-   if (renderer->u.polygon_stencil.manual_two_sides)
-      cso_restore_rasterizer(renderer->cso);
-
-   cso_restore_vertex_elements(renderer->cso);
-
-   /* restore color writes */
-   cso_restore_blend(renderer->cso);
-
-   if (renderer->u.polygon_stencil.restore_dsa)
-      cso_restore_depth_stencil_alpha(renderer->cso);
-
-   renderer->state = RENDERER_STATE_INIT;
-}
-
-/**
- * Prepare the renderer for polygon filling.
- */
-VGboolean renderer_polygon_fill_begin(struct renderer *renderer,
-                                      VGboolean save_dsa)
-{
-   struct pipe_depth_stencil_alpha_state dsa;
-
-   assert(renderer->state == RENDERER_STATE_INIT);
-
-   if (save_dsa)
-      cso_save_depth_stencil_alpha(renderer->cso);
-
-   /* setup stencil ops */
-   memset(&dsa, 0, sizeof(dsa));
-   dsa.stencil[0].enabled = 1;
-   dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL;
-   dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
-   dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
-   dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
-   dsa.stencil[0].valuemask = ~0;
-   dsa.stencil[0].writemask = ~0;
-   dsa.depth = renderer->g3d.dsa.depth;
-   cso_set_depth_stencil_alpha(renderer->cso, &dsa);
-
-   renderer->state = RENDERER_STATE_POLYGON_FILL;
-
-   return VG_TRUE;
-}
-
-/**
- * Fill a polygon.
- */
-void renderer_polygon_fill(struct renderer *renderer,
-                           VGfloat min_x, VGfloat min_y,
-                           VGfloat max_x, VGfloat max_y)
-{
-   assert(renderer->state == RENDERER_STATE_POLYGON_FILL);
-
-   renderer_quad_pos(renderer, min_x, min_y, max_x, max_y, VG_TRUE);
-   renderer_quad_draw(renderer);
-}
-
-/**
- * End polygon filling.
- */
-void renderer_polygon_fill_end(struct renderer *renderer)
-{
-   assert(renderer->state == RENDERER_STATE_POLYGON_FILL);
-
-   cso_restore_depth_stencil_alpha(renderer->cso);
-
-   renderer->state = RENDERER_STATE_INIT;
-}
-
-struct renderer * renderer_create(struct vg_context *owner)
-{
-   struct renderer *renderer;
-   struct pipe_rasterizer_state *raster;
-   struct pipe_stencil_ref sr;
-   VGint i;
-
-   renderer = CALLOC_STRUCT(renderer);
-   if (!renderer)
-      return NULL;
-
-   renderer->pipe = owner->pipe;
-   renderer->cso = owner->cso_context;
-
-   /* init vertex data that doesn't change */
-   for (i = 0; i < 4; i++)
-      renderer->vertices[i][0][3] = 1.0f; /* w */
-
-   for (i = 0; i < 2; i++) {
-      renderer->velems[i].src_offset = i * 4 * sizeof(float);
-      renderer->velems[i].instance_divisor = 0;
-      renderer->velems[i].vertex_buffer_index = 0;
-      renderer->velems[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
-   }
-   cso_set_vertex_elements(renderer->cso, 2, renderer->velems);
-
-   /* GL rasterization rules */
-   raster = &renderer->g3d.rasterizer;
-   memset(raster, 0, sizeof(*raster));
-   raster->half_pixel_center = 1;
-   raster->bottom_edge_rule = 1;
-   raster->depth_clip = 1;
-   cso_set_rasterizer(renderer->cso, raster);
-
-   /* fixed at 0 */
-   memset(&sr, 0, sizeof(sr));
-   cso_set_stencil_ref(renderer->cso, &sr);
-
-   renderer_set_vs(renderer, RENDERER_VS_PLAIN);
-
-   renderer->state = RENDERER_STATE_INIT;
-
-   return renderer;
-}
-
-void renderer_destroy(struct renderer *ctx)
-{
-   int i;
-
-   for (i = 0; i < NUM_RENDERER_VS; i++) {
-      if (ctx->cached_vs[i])
-         cso_delete_vertex_shader(ctx->cso, ctx->cached_vs[i]);
-   }
-   for (i = 0; i < NUM_RENDERER_FS; i++) {
-      if (ctx->cached_fs[i])
-         cso_delete_fragment_shader(ctx->cso, ctx->cached_fs[i]);
-   }
-
-   pipe_resource_reference(&ctx->vs_cbuf, NULL);
-   pipe_resource_reference(&ctx->fs_cbuf, NULL);
-
-   FREE(ctx);
-}
-
-static void update_clip_state(struct renderer *renderer,
-                              const struct vg_state *state)
-{
-   struct pipe_depth_stencil_alpha_state *dsa = &renderer->g3d.dsa;
-
-   memset(dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
-
-   if (state->scissoring) {
-      struct pipe_framebuffer_state *fb = &renderer->g3d.fb;
-      int i;
-
-      renderer_scissor_begin(renderer, VG_FALSE);
-
-      for (i = 0; i < state->scissor_rects_num; ++i) {
-         const float x      = state->scissor_rects[i * 4 + 0].f;
-         const float y      = state->scissor_rects[i * 4 + 1].f;
-         const float width  = state->scissor_rects[i * 4 + 2].f;
-         const float height = state->scissor_rects[i * 4 + 3].f;
-         VGint x0, y0, x1, y1, iw, ih;
-
-         x0 = (VGint) x;
-         y0 = (VGint) y;
-         if (x0 < 0)
-            x0 = 0;
-         if (y0 < 0)
-            y0 = 0;
-
-         /* note that x1 and y1 are exclusive */
-         x1 = (VGint) ceilf(x + width);
-         y1 = (VGint) ceilf(y + height);
-         if (x1 > fb->width)
-            x1 = fb->width;
-         if (y1 > fb->height)
-            y1 = fb->height;
-
-         iw = x1 - x0;
-         ih = y1 - y0;
-         if (iw > 0 && ih> 0 )
-            renderer_scissor(renderer, x0, y0, iw, ih);
-      }
-
-      renderer_scissor_end(renderer);
-
-      dsa->depth.enabled = 1; /* glEnable(GL_DEPTH_TEST); */
-      dsa->depth.writemask = 0;/*glDepthMask(FALSE);*/
-      dsa->depth.func = PIPE_FUNC_GEQUAL;
-   }
-}
-
-static void renderer_validate_blend(struct renderer *renderer,
-                                     const struct vg_state *state,
-                                     enum pipe_format fb_format)
-{
-   struct pipe_blend_state blend;
-
-   memset(&blend, 0, sizeof(blend));
-   blend.rt[0].colormask = PIPE_MASK_RGBA;
-   blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ONE;
-   blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
-   blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ZERO;
-   blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
-
-   /* TODO alpha masking happens after blending? */
-
-   switch (state->blend_mode) {
-   case VG_BLEND_SRC:
-      blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ONE;
-      blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
-      blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ZERO;
-      blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
-      break;
-   case VG_BLEND_SRC_OVER:
-      /* use the blend state only when there is no alpha channel */
-      if (!util_format_has_alpha(fb_format)) {
-         blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_SRC_ALPHA;
-         blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
-         blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
-         blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
-         blend.rt[0].blend_enable = 1;
-      }
-      break;
-   case VG_BLEND_SRC_IN:
-      blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ONE;
-      blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_DST_ALPHA;
-      blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ZERO;
-      blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
-      blend.rt[0].blend_enable = 1;
-      break;
-   case VG_BLEND_DST_IN:
-      blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ZERO;
-      blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO;
-      blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ONE;
-      blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
-      blend.rt[0].blend_enable = 1;
-      break;
-   case VG_BLEND_DST_OVER:
-   case VG_BLEND_MULTIPLY:
-   case VG_BLEND_SCREEN:
-   case VG_BLEND_DARKEN:
-   case VG_BLEND_LIGHTEN:
-   case VG_BLEND_ADDITIVE:
-      /* need a shader */
-      break;
-   default:
-      assert(!"not implemented blend mode");
-      break;
-   }
-
-   cso_set_blend(renderer->cso, &blend);
-}
-
-/**
- * Propogate OpenVG state changes to the renderer.  Only framebuffer, blending
- * and scissoring states are relevant here.
- */
-void renderer_validate(struct renderer *renderer,
-                       VGbitfield dirty,
-                       const struct st_framebuffer *stfb,
-                       const struct vg_state *state)
-{
-   assert(renderer->state == RENDERER_STATE_INIT);
-
-   dirty |= renderer->dirty;
-   renderer->dirty = 0;
-
-   if (dirty & FRAMEBUFFER_DIRTY) {
-      struct pipe_framebuffer_state *fb = &renderer->g3d.fb;
-      struct matrix *proj = &renderer->projection;
-
-      memset(fb, 0, sizeof(struct pipe_framebuffer_state));
-      fb->width  = stfb->width;
-      fb->height = stfb->height;
-      fb->nr_cbufs = 1;
-      fb->cbufs[0] = stfb->strb->surface;
-      fb->zsbuf = stfb->dsrb->surface;
-
-      cso_set_framebuffer(renderer->cso, fb);
-      vg_set_viewport(renderer, VEGA_Y0_BOTTOM);
-
-      matrix_load_identity(proj);
-      matrix_translate(proj, -1.0f, -1.0f);
-      matrix_scale(proj, 2.0f / fb->width, 2.0f / fb->height);
-
-      /* we also got a new depth buffer */
-      if (dirty & DEPTH_STENCIL_DIRTY) {
-         renderer->pipe->clear(renderer->pipe,
-               PIPE_CLEAR_DEPTHSTENCIL, NULL, 0.0, 0);
-      }
-   }
-
-   /* must be last because it renders to the depth buffer*/
-   if (dirty & DEPTH_STENCIL_DIRTY) {
-      update_clip_state(renderer, state);
-      cso_set_depth_stencil_alpha(renderer->cso, &renderer->g3d.dsa);
-   }
-
-   if (dirty & BLEND_DIRTY)
-      renderer_validate_blend(renderer, state, stfb->strb->format);
-}
-
-/**
- * Prepare the renderer for OpenVG pipeline.
- */
-void renderer_validate_for_shader(struct renderer *renderer,
-                                  const struct pipe_sampler_state **samplers,
-                                  struct pipe_sampler_view **views,
-                                  VGint num_samplers,
-                                  const struct matrix *modelview,
-                                  void *fs,
-                                  const void *const_buffer,
-                                  VGint const_buffer_len)
-{
-   struct matrix mvp = renderer->projection;
-
-   /* will be used in POLYGON_STENCIL and POLYGON_FILL */
-   matrix_mult(&mvp, modelview);
-   renderer_set_mvp(renderer, &mvp);
-
-   renderer_set_custom_fs(renderer, fs,
-                          samplers, views, num_samplers,
-                          const_buffer, const_buffer_len);
-}
-
-void renderer_validate_for_mask_rendering(struct renderer *renderer,
-                                          struct pipe_surface *dst,
-                                          const struct matrix *modelview)
-{
-   struct matrix mvp = renderer->projection;
-
-   /* will be used in POLYGON_STENCIL and POLYGON_FILL */
-   matrix_mult(&mvp, modelview);
-   renderer_set_mvp(renderer, &mvp);
-
-   renderer_set_target(renderer, dst, renderer->g3d.fb.zsbuf, VG_FALSE);
-   renderer_set_blend(renderer, ~0);
-   renderer_set_fs(renderer, RENDERER_FS_WHITE);
-
-   /* set internal dirty flags (hacky!) */
-   renderer->dirty = FRAMEBUFFER_DIRTY | BLEND_DIRTY;
-}
-
-void renderer_copy_surface(struct renderer *ctx,
-                           struct pipe_surface *src,
-                           int srcX0, int srcY0,
-                           int srcX1, int srcY1,
-                           struct pipe_surface *dst,
-                           int dstX0, int dstY0,
-                           int dstX1, int dstY1,
-                           float z, unsigned filter)
-{
-   struct pipe_context *pipe = ctx->pipe;
-   struct pipe_screen *screen = pipe->screen;
-   struct pipe_sampler_view view_templ;
-   struct pipe_sampler_view *view;
-   struct pipe_box src_box;
-   struct pipe_resource texTemp, *tex;
-   const struct pipe_framebuffer_state *fb = &ctx->g3d.fb;
-   const int srcW = abs(srcX1 - srcX0);
-   const int srcH = abs(srcY1 - srcY0);
-   const int srcLeft = MIN2(srcX0, srcX1);
-   const int srcTop = MIN2(srcY0, srcY1);
-
-   assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
-          filter == PIPE_TEX_MIPFILTER_LINEAR);
-
-   if (srcLeft != srcX0) {
-      /* left-right flip */
-      int tmp = dstX0;
-      dstX0 = dstX1;
-      dstX1 = tmp;
-   }
-
-   if (srcTop != srcY0) {
-      /* up-down flip */
-      int tmp = dstY0;
-      dstY0 = dstY1;
-      dstY1 = tmp;
-   }
-
-   assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D,
-                                      0, PIPE_BIND_SAMPLER_VIEW));
-   assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
-                                      0, PIPE_BIND_SAMPLER_VIEW));
-   assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
-                                      0, PIPE_BIND_RENDER_TARGET));
-
-   /*
-    * XXX for now we're always creating a temporary texture.
-    * Strictly speaking that's not always needed.
-    */
-
-   /* create temp texture */
-   memset(&texTemp, 0, sizeof(texTemp));
-   texTemp.target = PIPE_TEXTURE_2D;
-   texTemp.format = src->format;
-   texTemp.last_level = 0;
-   texTemp.width0 = srcW;
-   texTemp.height0 = srcH;
-   texTemp.depth0 = 1;
-   texTemp.array_size = 1;
-   texTemp.bind = PIPE_BIND_SAMPLER_VIEW;
-
-   tex = screen->resource_create(screen, &texTemp);
-   if (!tex)
-      return;
-
-   u_sampler_view_default_template(&view_templ, tex, tex->format);
-   view = pipe->create_sampler_view(pipe, tex, &view_templ);
-
-   if (!view)
-      return;
-
-   u_box_2d_zslice(srcLeft, srcTop, src->u.tex.first_layer, srcW, srcH, &src_box);
-
-   pipe->resource_copy_region(pipe,
-                              tex, 0, 0, 0, 0,  /* dest */
-                              src->texture, 0, &src_box);
-
-   assert(floatsEqual(z, 0.0f));
-
-   /* draw */
-   if (fb->cbufs[0] == dst) {
-      /* transform back to surface coordinates */
-      dstY0 = dst->height - dstY0;
-      dstY1 = dst->height - dstY1;
-
-      if (renderer_drawtex_begin(ctx, view)) {
-         renderer_drawtex(ctx,
-               dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0,
-               0, 0, view->texture->width0, view->texture->height0);
-         renderer_drawtex_end(ctx);
-      }
-   }
-   else {
-      if (renderer_copy_begin(ctx, dst, VG_TRUE, view)) {
-         renderer_copy(ctx,
-               dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0,
-               0, 0, view->texture->width0, view->texture->height0);
-         renderer_copy_end(ctx);
-      }
-   }
-}
-
-void renderer_texture_quad(struct renderer *r,
-                           struct pipe_resource *tex,
-                           VGfloat x1offset, VGfloat y1offset,
-                           VGfloat x2offset, VGfloat y2offset,
-                           VGfloat x1, VGfloat y1,
-                           VGfloat x2, VGfloat y2,
-                           VGfloat x3, VGfloat y3,
-                           VGfloat x4, VGfloat y4)
-{
-   const VGfloat z = 0.0f;
-
-   assert(r->state == RENDERER_STATE_INIT);
-   assert(tex->width0 != 0);
-   assert(tex->height0 != 0);
-
-   cso_save_vertex_shader(r->cso);
-
-   renderer_set_vs(r, RENDERER_VS_TEXTURE);
-
-   /* manually set up positions */
-   r->vertices[0][0][0] = x1;
-   r->vertices[0][0][1] = y1;
-   r->vertices[0][0][2] = z;
-
-   r->vertices[1][0][0] = x2;
-   r->vertices[1][0][1] = y2;
-   r->vertices[1][0][2] = z;
-
-   r->vertices[2][0][0] = x3;
-   r->vertices[2][0][1] = y3;
-   r->vertices[2][0][2] = z;
-
-   r->vertices[3][0][0] = x4;
-   r->vertices[3][0][1] = y4;
-   r->vertices[3][0][2] = z;
-
-   /* texcoords */
-   renderer_quad_texcoord(r, x1offset, y1offset,
-         x2offset, y2offset, tex->width0, tex->height0);
-
-   renderer_quad_draw(r);
-
-   cso_restore_vertex_shader(r->cso);
-}