python: Fix up state tracker for sw api.
[mesa.git] / src / gallium / state_trackers / xorg / xorg_renderer.c
index 32b056a362e5b423de327ab2c184a6af2e8d8f48..1eb926360b9d0182bca36b4787f004bfb8de0913 100644 (file)
@@ -9,15 +9,10 @@
 #include "util/u_memory.h"
 #include "util/u_rect.h"
 
-#include "pipe/p_inlines.h"
+#include "util/u_inlines.h"
 
 #include <math.h>
 
-enum AxisOrientation {
-   Y0_BOTTOM,
-   Y0_TOP
-};
-
 #define floatsEqual(x, y) (fabs(x - y) <= 0.00001f * MIN2(fabs(x), fabs(y)))
 #define floatIsZero(x) (floatsEqual((x) + 1, 1))
 
@@ -73,13 +68,14 @@ renderer_draw(struct xorg_renderer *r)
 
 
    if (buf) {
+      cso_set_vertex_elements(r->cso, r->attrs_per_vertex, r->velems);
+
       util_draw_vertex_buffer(pipe, buf, 0,
                               PIPE_PRIM_QUADS,
                               num_verts,  /* verts */
                               r->attrs_per_vertex); /* attribs/vert */
 
       pipe_buffer_reference(&buf, NULL);
-      pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
    }
 }
 
@@ -98,6 +94,7 @@ renderer_init_state(struct xorg_renderer *r)
 {
    struct pipe_depth_stencil_alpha_state dsa;
    struct pipe_rasterizer_state raster;
+   unsigned i;
 
    /* set common initial clip state */
    memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
@@ -109,6 +106,14 @@ renderer_init_state(struct xorg_renderer *r)
    raster.gl_rasterization_rules = 1;
    cso_set_rasterizer(r->cso, &raster);
 
+   /* vertex elements state */
+   memset(&r->velems[0], 0, sizeof(r->velems[0]) * 3);
+   for (i = 0; i < 3; i++) {
+      r->velems[i].src_offset = i * 4 * sizeof(float);
+      r->velems[i].instance_divisor = 0;
+      r->velems[i].vertex_buffer_index = 0;
+      r->velems[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+   }
 }
 
 
@@ -176,14 +181,14 @@ add_vertex_data1(struct xorg_renderer *r,
       map_point(src_matrix, pt3[0], pt3[1], &pt3[0], &pt3[1]);
    }
 
-   s0 =  pt0[0] / src->width[0];
-   s1 =  pt1[0] / src->width[0];
-   s2 =  pt2[0] / src->width[0];
-   s3 =  pt3[0] / src->width[0];
-   t0 =  pt0[1] / src->height[0];
-   t1 =  pt1[1] / src->height[0];
-   t2 =  pt2[1] / src->height[0];
-   t3 =  pt3[1] / src->height[0];
+   s0 =  pt0[0] / src->width0;
+   s1 =  pt1[0] / src->width0;
+   s2 =  pt2[0] / src->width0;
+   s3 =  pt3[0] / src->width0;
+   t0 =  pt0[1] / src->height0;
+   t1 =  pt1[1] / src->height0;
+   t2 =  pt2[1] / src->height0;
+   t3 =  pt3[1] / src->height0;
 
    /* 1st vertex */
    add_vertex_1tex(r, dstX, dstY, s0, t0);
@@ -195,23 +200,6 @@ add_vertex_data1(struct xorg_renderer *r,
    add_vertex_1tex(r, dstX, dstY + height, s3, t3);
 }
 
-static struct pipe_buffer *
-setup_vertex_data_tex(struct xorg_renderer *r,
-                      float x0, float y0, float x1, float y1,
-                      float s0, float t0, float s1, float t1,
-                      float z)
-{
-   /* 1st vertex */
-   add_vertex_1tex(r, x0, y0, s0, t0);
-   /* 2nd vertex */
-   add_vertex_1tex(r, x1, y0, s1, t0);
-   /* 3rd vertex */
-   add_vertex_1tex(r, x1, y1, s1, t1);
-   /* 4th vertex */
-   add_vertex_1tex(r, x0, y1, s0, t1);
-
-   return renderer_buffer_create(r);
-}
 
 static INLINE void
 add_vertex_2tex(struct xorg_renderer *r,
@@ -271,15 +259,15 @@ add_vertex_data2(struct xorg_renderer *r,
       map_point(mask_matrix, mpt1[0], mpt1[1], &mpt1[0], &mpt1[1]);
    }
 
-   src_s0 = spt0[0] / src->width[0];
-   src_t0 = spt0[1] / src->height[0];
-   src_s1 = spt1[0] / src->width[0];
-   src_t1 = spt1[1] / src->height[0];
+   src_s0 = spt0[0] / src->width0;
+   src_t0 = spt0[1] / src->height0;
+   src_s1 = spt1[0] / src->width0;
+   src_t1 = spt1[1] / src->height0;
 
-   mask_s0 = mpt0[0] / mask->width[0];
-   mask_t0 = mpt0[1] / mask->height[0];
-   mask_s1 = mpt1[0] / mask->width[0];
-   mask_t1 = mpt1[1] / mask->height[0];
+   mask_s0 = mpt0[0] / mask->width0;
+   mask_t0 = mpt0[1] / mask->height0;
+   mask_s1 = mpt1[0] / mask->width0;
+   mask_t1 = mpt1[1] / mask->height0;
 
    /* 1st vertex */
    add_vertex_2tex(r, dstX, dstY,
@@ -309,10 +297,10 @@ setup_vertex_data_yuv(struct xorg_renderer *r,
    spt1[0] = srcX + srcW;
    spt1[1] = srcY + srcH;
 
-   s0 = spt0[0] / tex[0]->width[0];
-   t0 = spt0[1] / tex[0]->height[0];
-   s1 = spt1[0] / tex[0]->width[0];
-   t1 = spt1[1] / tex[0]->height[0];
+   s0 = spt0[0] / tex[0]->width0;
+   t0 = spt0[1] / tex[0]->height0;
+   s1 = spt1[0] / tex[0]->width0;
+   t1 = spt1[1] / tex[0]->height0;
 
    /* 1st vertex */
    add_vertex_1tex(r, dstX, dstY, s0, t0);
@@ -336,21 +324,25 @@ setup_vertex_data_yuv(struct xorg_renderer *r,
  * these concepts are linked.
  */
 void renderer_bind_destination(struct xorg_renderer *r,
-                               struct pipe_surface *surface )
+                               struct pipe_surface *surface,
+                               int width,
+                               int height )
 {
 
    struct pipe_framebuffer_state fb;
    struct pipe_viewport_state viewport;
-   int width = surface->width;
-   int height = surface->height;
 
+   /* Framebuffer uses actual surface width/height
+    */
    memset(&fb, 0, sizeof fb);
-   fb.width  = width;
-   fb.height = height;
+   fb.width  = surface->width;
+   fb.height = surface->height;
    fb.nr_cbufs = 1;
    fb.cbufs[0] = surface;
    fb.zsbuf = 0;
 
+   /* Viewport just touches the bit we're interested in:
+    */
    viewport.scale[0] =  width / 2.f;
    viewport.scale[1] =  height / 2.f;
    viewport.scale[2] =  1.0;
@@ -360,6 +352,8 @@ void renderer_bind_destination(struct xorg_renderer *r,
    viewport.translate[2] = 0.0;
    viewport.translate[3] = 0.0;
 
+   /* Constant buffer set up to match viewport dimensions:
+    */
    if (r->fb_width != width ||
        r->fb_height != height) 
    {
@@ -395,14 +389,14 @@ struct xorg_renderer * renderer_create(struct pipe_context *pipe)
 
 void renderer_destroy(struct xorg_renderer *r)
 {
-   struct pipe_constant_buffer *vsbuf = &r->vs_const_buffer;
-   struct pipe_constant_buffer *fsbuf = &r->fs_const_buffer;
+   struct pipe_buffer **vsbuf = &r->vs_const_buffer;
+   struct pipe_buffer **fsbuf = &r->fs_const_buffer;
 
-   if (vsbuf && vsbuf->buffer)
-      pipe_buffer_reference(&vsbuf->buffer, NULL);
+   if (*vsbuf)
+      pipe_buffer_reference(vsbuf, NULL);
 
-   if (fsbuf && fsbuf->buffer)
-      pipe_buffer_reference(&fsbuf->buffer, NULL);
+   if (*fsbuf)
+      pipe_buffer_reference(fsbuf, NULL);
 
    if (r->shaders) {
       xorg_shaders_destroy(r->shaders);
@@ -425,89 +419,47 @@ void renderer_set_constants(struct xorg_renderer *r,
                             const float *params,
                             int param_bytes)
 {
-   struct pipe_constant_buffer *cbuf =
+   struct pipe_buffer **cbuf =
       (shader_type == PIPE_SHADER_VERTEX) ? &r->vs_const_buffer :
       &r->fs_const_buffer;
 
-   pipe_buffer_reference(&cbuf->buffer, NULL);
-   cbuf->buffer = pipe_buffer_create(r->pipe->screen, 16,
-                                     PIPE_BUFFER_USAGE_CONSTANT,
-                                     param_bytes);
+   pipe_buffer_reference(cbuf, NULL);
+   *cbuf = pipe_buffer_create(r->pipe->screen, 16,
+                              PIPE_BUFFER_USAGE_CONSTANT,
+                              param_bytes);
 
-   if (cbuf->buffer) {
-      pipe_buffer_write(r->pipe->screen, cbuf->buffer,
+   if (*cbuf) {
+      pipe_buffer_write(r->pipe->screen, *cbuf,
                         0, param_bytes, params);
    }
-   r->pipe->set_constant_buffer(r->pipe, shader_type, 0, cbuf);
-}
-
-static void
-setup_fs_constant_buffer(struct xorg_renderer *r)
-{
-   const int param_bytes = 4 * sizeof(float);
-   const float fs_consts[8] = {
-      0, 0, 0, 1,
-   };
-   renderer_set_constants(r, PIPE_SHADER_FRAGMENT,
-                          fs_consts, param_bytes);
+   r->pipe->set_constant_buffer(r->pipe, shader_type, 0, *cbuf);
 }
 
 
-static void renderer_copy_texture(struct xorg_renderer *r,
-                                  struct pipe_texture *src,
-                                  float sx1, float sy1,
-                                  float sx2, float sy2,
-                                  struct pipe_texture *dst,
-                                  float dx1, float dy1,
-                                  float dx2, float dy2)
+void renderer_copy_prepare(struct xorg_renderer *r,
+                           struct pipe_surface *dst_surface,
+                           struct pipe_texture *src_texture)
 {
    struct pipe_context *pipe = r->pipe;
    struct pipe_screen *screen = pipe->screen;
-   struct pipe_buffer *buf;
-   struct pipe_surface *dst_surf = screen->get_tex_surface(
-      screen, dst, 0, 0, 0,
-      PIPE_BUFFER_USAGE_GPU_WRITE);
-   float s0, t0, s1, t1;
    struct xorg_shader shader;
 
-   assert(src->width[0] != 0);
-   assert(src->height[0] != 0);
-   assert(dst->width[0] != 0);
-   assert(dst->height[0] != 0);
-
-#if 1
-   s0 = sx1 / src->width[0];
-   s1 = sx2 / src->width[0];
-   t0 = sy1 / src->height[0];
-   t1 = sy2 / src->height[0];
-#else
-   s0 = 0;
-   s1 = 1;
-   t0 = 0;
-   t1 = 1;
-#endif
-
-#if 0
-   debug_printf("copy texture src=[%f, %f, %f, %f], dst=[%f, %f, %f, %f], tex=[%f, %f, %f, %f]\n",
-                sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2,
-                s0, t0, s1, t1);
-#endif
-
-   assert(screen->is_format_supported(screen, dst_surf->format,
+   assert(screen->is_format_supported(screen, dst_surface->format,
                                       PIPE_TEXTURE_2D,
                                       PIPE_TEXTURE_USAGE_RENDER_TARGET,
                                       0));
+   (void) screen;
 
 
    /* set misc state we care about */
    {
       struct pipe_blend_state blend;
       memset(&blend, 0, sizeof(blend));
-      blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
-      blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
-      blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
-      blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
-      blend.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;
+      blend.rt[0].colormask = PIPE_MASK_RGBA;
       cso_set_blend(r->cso, &blend);
    }
 
@@ -526,10 +478,12 @@ static void renderer_copy_texture(struct xorg_renderer *r,
       cso_single_sampler_done(r->cso);
    }
 
-   renderer_bind_destination(r, dst_surf);
+   renderer_bind_destination(r, dst_surface, 
+                             dst_surface->width,
+                             dst_surface->height);
 
    /* texture */
-   cso_set_sampler_textures(r->cso, 1, &src);
+   cso_set_sampler_textures(r->cso, 1, &src_texture);
 
    /* shaders */
    shader = xorg_shaders_get(r->shaders,
@@ -538,29 +492,12 @@ static void renderer_copy_texture(struct xorg_renderer *r,
    cso_set_vertex_shader_handle(r->cso, shader.vs);
    cso_set_fragment_shader_handle(r->cso, shader.fs);
 
-   setup_fs_constant_buffer(r);
-
-   /* draw quad */
-   buf = setup_vertex_data_tex(r,
-                               dx1, dy1,
-                               dx2, dy2,
-                               s0, t0, s1, t1,
-                               0.0f);
-
-   if (buf) {
-      util_draw_vertex_buffer(r->pipe, buf, 0,
-                              PIPE_PRIM_QUADS,
-                              4,  /* verts */
-                              2); /* attribs/vert */
-
-      pipe_buffer_reference(&buf, NULL);
-   }
-
-   pipe_surface_reference(&dst_surf, NULL);
+   r->buffer_size = 0;
+   r->attrs_per_vertex = 2;
 }
 
-static struct pipe_texture *
-create_sampler_texture(struct xorg_renderer *r,
+struct pipe_texture *
+renderer_clone_texture(struct xorg_renderer *r,
                        struct pipe_texture *src)
 {
    enum pipe_format format;
@@ -569,7 +506,9 @@ create_sampler_texture(struct xorg_renderer *r,
    struct pipe_texture *pt;
    struct pipe_texture templ;
 
-   pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
+   if (pipe->is_texture_referenced(pipe, src, 0, 0) &
+       PIPE_REFERENCED_FOR_WRITE)
+      pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
 
    /* the coming in texture should already have that invariance */
    debug_assert(screen->is_format_supported(screen, src->format,
@@ -582,10 +521,9 @@ create_sampler_texture(struct xorg_renderer *r,
    templ.target = PIPE_TEXTURE_2D;
    templ.format = format;
    templ.last_level = 0;
-   templ.width[0] = src->width[0];
-   templ.height[0] = src->height[0];
-   templ.depth[0] = 1;
-   pf_get_block(format, &templ.block);
+   templ.width0 = src->width0;
+   templ.height0 = src->height0;
+   templ.depth0 = 1;
    templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER;
 
    pt = screen->texture_create(screen, &templ);
@@ -606,13 +544,13 @@ create_sampler_texture(struct xorg_renderer *r,
                 ps_tex, /* dest */
                 0, 0, /* destx/y */
                 ps_read,
-                0, 0, src->width[0], src->height[0]);
+                0, 0, src->width0, src->height0);
       } else {
           util_surface_copy(pipe, FALSE,
                 ps_tex, /* dest */
                 0, 0, /* destx/y */
                 ps_read,
-                0, 0, src->width[0], src->height[0]);
+                0, 0, src->width0, src->height0);
       }
       pipe_surface_reference(&ps_read, NULL);
       pipe_surface_reference(&ps_tex, NULL);
@@ -623,52 +561,40 @@ create_sampler_texture(struct xorg_renderer *r,
 
 
 void renderer_copy_pixmap(struct xorg_renderer *r,
-                          struct exa_pixmap_priv *dst_priv, int dx, int dy,
-                          struct exa_pixmap_priv *src_priv, int sx, int sy,
-                          int width, int height)
+                          int dx, int dy,
+                          int sx, int sy,
+                          int width, int height,
+                          float src_width,
+                          float src_height)
 {
-   float dst_loc[4], src_loc[4];
-   struct pipe_texture *dst = dst_priv->tex;
-   struct pipe_texture *src = src_priv->tex;
+   float s0, t0, s1, t1;
+   float x0, y0, x1, y1;
 
-   if (r->pipe->is_texture_referenced(r->pipe, src, 0, 0) &
-       PIPE_REFERENCED_FOR_WRITE)
-      r->pipe->flush(r->pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
-
-   dst_loc[0] = dx;
-   dst_loc[1] = dy;
-   dst_loc[2] = width;
-   dst_loc[3] = height;
-
-   src_loc[0] = sx;
-   src_loc[1] = sy;
-   src_loc[2] = width;
-   src_loc[3] = height;
-
-   if (src_loc[2] >= 0 && src_loc[3] >= 0 &&
-       dst_loc[2] >= 0 && dst_loc[3] >= 0) {
-      struct pipe_texture *temp_src = src;
-
-      if (src == dst)
-         temp_src = create_sampler_texture(r, src);
-
-      renderer_copy_texture(r,
-                            temp_src,
-                            src_loc[0],
-                            src_loc[1],
-                            src_loc[0] + src_loc[2],
-                            src_loc[1] + src_loc[3],
-                            dst,
-                            dst_loc[0],
-                            dst_loc[1],
-                            dst_loc[0] + dst_loc[2],
-                            dst_loc[1] + dst_loc[3]);
-
-      if (src == dst)
-         pipe_texture_reference(&temp_src, NULL);
-   }
+
+   /* XXX: could put the texcoord scaling calculation into the vertex
+    * shader.
+    */
+   s0 = sx            / src_width;
+   s1 = (sx + width)  / src_width;
+   t0 = sy            / src_height;
+   t1 = (sy + height) / src_height;
+
+   x0 = dx;
+   x1 = dx + width;
+   y0 = dy;
+   y1 = dy + height;
+
+   /* draw quad */
+   renderer_draw_conditional(r, 4*8);
+   add_vertex_1tex(r, x0, y0, s0, t0);
+   add_vertex_1tex(r, x1, y0, s1, t0);
+   add_vertex_1tex(r, x1, y1, s1, t1);
+   add_vertex_1tex(r, x0, y1, s0, t1);
 }
 
+
+
+
 void renderer_draw_yuv(struct xorg_renderer *r,
                        int src_x, int src_y, int src_w, int src_h,
                        int dst_x, int dst_y, int dst_w, int dst_h,
@@ -685,6 +611,8 @@ void renderer_draw_yuv(struct xorg_renderer *r,
    if (buf) {
       const int num_attribs = 2; /*pos + tex coord*/
 
+      cso_set_vertex_elements(r->cso, num_attribs, r->velems);
+
       util_draw_vertex_buffer(pipe, buf, 0,
                               PIPE_PRIM_QUADS,
                               4,  /* verts */