gallium: Replace gl_rasterization_rules with lower_left_origin and half_pixel_center.
[mesa.git] / src / gallium / state_trackers / vega / renderer.c
index 169526bf7bb896156ba9df422fccce242032c1e0..b8232787eba7064a729eeb3234b044a484049f12 100644 (file)
@@ -28,7 +28,6 @@
 #include "renderer.h"
 
 #include "vg_context.h"
-#include "image.h"
 
 #include "pipe/p_context.h"
 #include "pipe/p_state.h"
@@ -40,7 +39,9 @@
 #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"
@@ -82,9 +83,10 @@ struct renderer {
       struct pipe_depth_stencil_alpha_state dsa;
       struct pipe_framebuffer_state fb;
    } g3d;
+   struct matrix projection;
 
+   struct matrix mvp;
    struct pipe_resource *vs_cbuf;
-   VGfloat vs_cbuf_data[8];
 
    struct pipe_resource *fs_cbuf;
    VGfloat fs_cbuf_data[32];
@@ -137,7 +139,51 @@ static VGboolean renderer_can_support(struct renderer *renderer,
    struct pipe_screen *screen = renderer->pipe->screen;
 
    return screen->is_format_supported(screen,
-         res->format, res->target, 0, bindings, 0);
+         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_STATIC,
+                             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;
 }
 
 /**
@@ -147,7 +193,7 @@ static VGboolean renderer_can_support(struct renderer *renderer,
 static void *create_passthrough_vs(struct pipe_context *pipe, int semantic_name)
 {
    struct ureg_program *ureg;
-   struct ureg_src src[2], constants[2];
+   struct ureg_src src[2], constants[3];
    struct ureg_dst dst[2], tmp;
    int i;
 
@@ -155,16 +201,18 @@ static void *create_passthrough_vs(struct pipe_context *pipe, int semantic_name)
    if (!ureg)
       return NULL;
 
-   /* position in surface coordinates */
+   /* 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 < 2; i++)
+   for (i = 0; i < Elements(constants); i++)
       constants[i] = ureg_DECL_constant(ureg, i);
 
    /* transform to clipped coordinates */
-   ureg_MUL(ureg, tmp, src[0], constants[0]);
-   ureg_ADD(ureg, tmp, ureg_src(tmp), constants[1]);
+   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) {
@@ -260,7 +308,8 @@ static void renderer_set_fs(struct renderer *r, RendererFs id)
 
       switch (id) {
       case RENDERER_FS_COLOR:
-         fs = util_make_fragment_passthrough_shader(r->pipe);
+         fs = util_make_fragment_passthrough_shader(r->pipe,
+                          TGSI_SEMANTIC_COLOR, TGSI_INTERPOLATE_PERSPECTIVE);
          break;
       case RENDERER_FS_TEXTURE:
          fs = util_make_fragment_tex_shader(r->pipe,
@@ -387,11 +436,11 @@ static void renderer_set_samplers(struct renderer *r,
 
    /* set samplers */
    for (i = 0; i < num_views; i++)
-      cso_single_sampler(r->cso, i, &sampler);
-   cso_single_sampler_done(r->cso);
+      cso_single_sampler(r->cso, PIPE_SHADER_FRAGMENT, i, &sampler);
+   cso_single_sampler_done(r->cso, PIPE_SHADER_FRAGMENT);
 
    /* set views */
-   cso_set_fragment_sampler_views(r->cso, num_views, views);
+   cso_set_sampler_views(r->cso, PIPE_SHADER_FRAGMENT, num_views, views);
 }
 
 /**
@@ -413,8 +462,8 @@ static void renderer_set_custom_fs(struct renderer *renderer,
 
    /* set samplers and views */
    if (num_samplers) {
-      cso_set_samplers(renderer->cso, num_samplers, samplers);
-      cso_set_fragment_sampler_views(renderer->cso, num_samplers, views);
+      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 */
@@ -426,10 +475,11 @@ static void renderer_set_custom_fs(struct renderer *renderer,
          pipe_resource_reference(&cbuf, NULL);
 
          cbuf = pipe_buffer_create(renderer->pipe->screen,
-               PIPE_BIND_CONSTANT_BUFFER, const_buffer_len);
+               PIPE_BIND_CONSTANT_BUFFER, PIPE_USAGE_STATIC,
+               const_buffer_len);
          pipe_buffer_write(renderer->pipe, cbuf, 0,
                const_buffer_len, const_buffer);
-         renderer->pipe->set_constant_buffer(renderer->pipe,
+         pipe_set_constant_buffer(renderer->pipe,
                PIPE_SHADER_FRAGMENT, 0, cbuf);
 
          renderer->fs_cbuf = cbuf;
@@ -517,20 +567,9 @@ static void renderer_quad_texcoord(struct renderer *r,
  */
 static void renderer_quad_draw(struct renderer *r)
 {
-   struct pipe_resource *buf;
-
-   buf = pipe_user_buffer_create(r->pipe->screen,
-                                 r->vertices,
-                                 sizeof(r->vertices),
-                                 PIPE_BIND_VERTEX_BUFFER);
-   if (buf) {
-      util_draw_vertex_buffer(r->pipe, buf, 0,
-                              PIPE_PRIM_TRIANGLE_FAN,
-                              Elements(r->vertices),     /* verts */
-                              Elements(r->vertices[0])); /* attribs/vert */
-
-      pipe_resource_reference(&buf, NULL);
-   }
+   util_draw_user_vertex_buffer(r->cso, r->vertices, PIPE_PRIM_TRIANGLE_FAN,
+                                Elements(r->vertices),     /* verts */
+                                Elements(r->vertices[0])); /* attribs/vert */
 }
 
 /**
@@ -553,8 +592,8 @@ VGboolean renderer_copy_begin(struct renderer *renderer,
    cso_save_framebuffer(renderer->cso);
    cso_save_viewport(renderer->cso);
    cso_save_blend(renderer->cso);
-   cso_save_samplers(renderer->cso);
-   cso_save_fragment_sampler_views(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);
 
@@ -566,6 +605,8 @@ VGboolean renderer_copy_begin(struct renderer *renderer,
    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;
@@ -605,8 +646,8 @@ void renderer_copy_end(struct renderer *renderer)
    cso_restore_framebuffer(renderer->cso);
    cso_restore_viewport(renderer->cso);
    cso_restore_blend(renderer->cso);
-   cso_restore_samplers(renderer->cso);
-   cso_restore_fragment_sampler_views(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);
 
@@ -625,8 +666,8 @@ VGboolean renderer_drawtex_begin(struct renderer *renderer,
       return VG_FALSE;
 
    cso_save_blend(renderer->cso);
-   cso_save_samplers(renderer->cso);
-   cso_save_fragment_sampler_views(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);
 
@@ -637,6 +678,8 @@ VGboolean renderer_drawtex_begin(struct renderer *renderer,
    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;
@@ -674,8 +717,8 @@ void renderer_drawtex_end(struct renderer *renderer)
    assert(renderer->state == RENDERER_STATE_DRAWTEX);
 
    cso_restore_blend(renderer->cso);
-   cso_restore_samplers(renderer->cso);
-   cso_restore_fragment_sampler_views(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);
 
@@ -709,6 +752,8 @@ VGboolean renderer_scissor_begin(struct renderer *renderer,
    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;
 
@@ -762,6 +807,8 @@ VGboolean renderer_clear_begin(struct renderer *renderer)
    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;
@@ -815,7 +862,7 @@ VGboolean renderer_filter_begin(struct renderer *renderer,
                                 const void *const_buffer,
                                 VGint const_buffer_len)
 {
-   struct pipe_surface *surf;
+   struct pipe_surface *surf, surf_tmpl;
 
    assert(renderer->state == RENDERER_STATE_INIT);
 
@@ -824,8 +871,8 @@ VGboolean renderer_filter_begin(struct renderer *renderer,
    if (!renderer_can_support(renderer, dst, PIPE_BIND_RENDER_TARGET))
       return VG_FALSE;
 
-   surf = renderer->pipe->screen->get_tex_surface(renderer->pipe->screen,
-         dst, 0, 0, 0, PIPE_BIND_RENDER_TARGET);
+   u_surface_default_template(&surf_tmpl, dst);
+   surf = renderer->pipe->create_surface(renderer->pipe, dst, &surf_tmpl);
    if (!surf)
       return VG_FALSE;
 
@@ -842,8 +889,8 @@ VGboolean renderer_filter_begin(struct renderer *renderer,
    if (num_samplers) {
       struct pipe_resource *tex;
 
-      cso_save_samplers(renderer->cso);
-      cso_save_fragment_sampler_views(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);
 
@@ -866,6 +913,8 @@ VGboolean renderer_filter_begin(struct renderer *renderer,
       renderer->u.filter.use_sampler = VG_FALSE;
    }
 
+   renderer_set_mvp(renderer, NULL);
+
    renderer->state = RENDERER_STATE_FILTER;
 
    return VG_TRUE;
@@ -901,8 +950,8 @@ void renderer_filter_end(struct renderer *renderer)
    assert(renderer->state == RENDERER_STATE_FILTER);
 
    if (renderer->u.filter.use_sampler) {
-      cso_restore_samplers(renderer->cso);
-      cso_restore_fragment_sampler_views(renderer->cso);
+      cso_restore_samplers(renderer->cso, PIPE_SHADER_FRAGMENT);
+      cso_restore_sampler_views(renderer->cso, PIPE_SHADER_FRAGMENT);
       cso_restore_vertex_shader(renderer->cso);
    }
 
@@ -991,10 +1040,10 @@ void renderer_polygon_stencil(struct renderer *renderer,
 {
    assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL);
 
-   renderer->pipe->set_vertex_buffers(renderer->pipe, 1, vbuf);
+   cso_set_vertex_buffers(renderer->cso, 0, 1, vbuf);
 
    if (!renderer->u.polygon_stencil.manual_two_sides) {
-      util_draw_arrays(renderer->pipe, mode, start, count);
+      cso_draw_arrays(renderer->cso, mode, start, count);
    }
    else {
       struct pipe_rasterizer_state raster;
@@ -1009,7 +1058,7 @@ void renderer_polygon_stencil(struct renderer *renderer,
 
       cso_set_rasterizer(renderer->cso, &raster);
       cso_set_depth_stencil_alpha(renderer->cso, &dsa);
-      util_draw_arrays(renderer->pipe, mode, start, count);
+      cso_draw_arrays(renderer->cso, mode, start, count);
 
       /* back */
       raster.cull_face = PIPE_FACE_FRONT;
@@ -1017,7 +1066,7 @@ void renderer_polygon_stencil(struct renderer *renderer,
 
       cso_set_rasterizer(renderer->cso, &raster);
       cso_set_depth_stencil_alpha(renderer->cso, &dsa);
-      util_draw_arrays(renderer->pipe, mode, start, count);
+      cso_draw_arrays(renderer->cso, mode, start, count);
    }
 }
 
@@ -1126,7 +1175,9 @@ struct renderer * renderer_create(struct vg_context *owner)
    /* GL rasterization rules */
    raster = &renderer->g3d.rasterizer;
    memset(raster, 0, sizeof(*raster));
-   raster->gl_rasterization_rules = 1;
+   raster->half_pixel_center = 1;
+   raster->bottom_edge_rule = 1;
+   raster->depth_clip = 1;
    cso_set_rasterizer(renderer->cso, raster);
 
    /* fixed at 0 */
@@ -1208,6 +1259,68 @@ static void update_clip_state(struct renderer *renderer,
    }
 }
 
+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.
@@ -1222,70 +1335,9 @@ void renderer_validate(struct renderer *renderer,
    dirty |= renderer->dirty;
    renderer->dirty = 0;
 
-   if (dirty & BLEND_DIRTY) {
-      struct pipe_blend_state blend;
-      memset(&blend, 0, sizeof(blend));
-      blend.rt[0].blend_enable = 1;
-      blend.rt[0].colormask = PIPE_MASK_RGBA;
-
-      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;
-         blend.rt[0].blend_enable = 0;
-         break;
-      case VG_BLEND_SRC_OVER:
-         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;
-         break;
-      case VG_BLEND_DST_OVER:
-         blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_INV_DST_ALPHA;
-         blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_INV_DST_ALPHA;
-         blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_DST_ALPHA;
-         blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_DST_ALPHA;
-         break;
-      case VG_BLEND_SRC_IN:
-         blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_DST_ALPHA;
-         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;
-         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_SRC_ALPHA;
-         blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
-         break;
-      case VG_BLEND_MULTIPLY:
-      case VG_BLEND_SCREEN:
-      case VG_BLEND_DARKEN:
-      case VG_BLEND_LIGHTEN:
-         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;
-         blend.rt[0].blend_enable = 0;
-         break;
-      case VG_BLEND_ADDITIVE:
-         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_ONE;
-         blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
-         break;
-      default:
-         assert(!"not implemented blend mode");
-      }
-      cso_set_blend(renderer->cso, &blend);
-   }
-
    if (dirty & FRAMEBUFFER_DIRTY) {
       struct pipe_framebuffer_state *fb = &renderer->g3d.fb;
-      struct pipe_resource *cbuf;
-      VGfloat vs_consts[8];
+      struct matrix *proj = &renderer->projection;
 
       memset(fb, 0, sizeof(struct pipe_framebuffer_state));
       fb->width  = stfb->width;
@@ -1297,34 +1349,9 @@ void renderer_validate(struct renderer *renderer,
       cso_set_framebuffer(renderer->cso, fb);
       vg_set_viewport(renderer, VEGA_Y0_BOTTOM);
 
-      /* surface coordinates to clipped coordinates */
-      vs_consts[0] = 2.0f / fb->width;
-      vs_consts[1] = 2.0f / fb->height;
-      vs_consts[2] = 1.0f;
-      vs_consts[3] = 1.0f;
-      vs_consts[4] = -1.0f;
-      vs_consts[5] = -1.0f;
-      vs_consts[6] = 0.0f;
-      vs_consts[7] = 0.0f;
-
-      /* upload if needed */
-      cbuf = renderer->vs_cbuf;
-      if (!cbuf ||
-          memcmp(renderer->vs_cbuf_data, vs_consts, sizeof(vs_consts)) != 0) {
-         pipe_resource_reference(&cbuf, NULL);
-         cbuf = pipe_buffer_create(renderer->pipe->screen,
-                                   PIPE_BIND_CONSTANT_BUFFER,
-                                   sizeof(vs_consts));
-         if (cbuf) {
-            pipe_buffer_write(renderer->pipe, cbuf, 0,
-                  sizeof(vs_consts), vs_consts);
-         }
-         renderer->pipe->set_constant_buffer(renderer->pipe,
-               PIPE_SHADER_VERTEX, 0, cbuf);
-
-         renderer->vs_cbuf = cbuf;
-         memcpy(renderer->vs_cbuf_data, vs_consts, sizeof(vs_consts));
-      }
+      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) {
@@ -1338,6 +1365,9 @@ void renderer_validate(struct renderer *renderer,
       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);
 }
 
 /**
@@ -1347,18 +1377,32 @@ 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)
+                                          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);
@@ -1380,8 +1424,8 @@ void renderer_copy_surface(struct renderer *ctx,
    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;
-   struct pipe_subresource subsrc, subdst;
    const struct pipe_framebuffer_state *fb = &ctx->g3d.fb;
    const int srcW = abs(srcX1 - srcX0);
    const int srcH = abs(srcY1 - srcY0);
@@ -1406,11 +1450,11 @@ void renderer_copy_surface(struct renderer *ctx,
    }
 
    assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D,
-                                      0, PIPE_BIND_SAMPLER_VIEW, 0));
+                                      0, PIPE_BIND_SAMPLER_VIEW));
    assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
-                                      0, PIPE_BIND_SAMPLER_VIEW, 0));
+                                      0, PIPE_BIND_SAMPLER_VIEW));
    assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
-                                      0, PIPE_BIND_RENDER_TARGET, 0));
+                                      0, PIPE_BIND_RENDER_TARGET));
 
    /*
     * XXX for now we're always creating a temporary texture.
@@ -1425,6 +1469,7 @@ void renderer_copy_surface(struct renderer *ctx,
    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);
@@ -1437,15 +1482,11 @@ void renderer_copy_surface(struct renderer *ctx,
    if (!view)
       return;
 
-   subdst.face = 0;
-   subdst.level = 0;
-   subsrc.face = src->face;
-   subsrc.level = src->level;
+   u_box_2d_zslice(srcLeft, srcTop, src->u.tex.first_layer, srcW, srcH, &src_box);
 
    pipe->resource_copy_region(pipe,
-                              tex, subdst, 0, 0, 0,  /* dest */
-                              src->texture, subsrc, srcLeft, srcTop, src->zslice, /* src */
-                              srcW, srcH);     /* size */
+                              tex, 0, 0, 0, 0,  /* dest */
+                              src->texture, 0, &src_box);
 
    assert(floatsEqual(z, 0.0f));