st/xorg: start rendering and compositing pictures
authorZack Rusin <zackr@vmware.com>
Tue, 1 Sep 2009 18:43:04 +0000 (14:43 -0400)
committerZack Rusin <zackr@vmware.com>
Tue, 1 Sep 2009 18:44:55 +0000 (14:44 -0400)
src/gallium/state_trackers/xorg/xorg_composite.c
src/gallium/state_trackers/xorg/xorg_exa.c
src/gallium/state_trackers/xorg/xorg_exa.h

index 86402a0d1303e54e6ce11b1e95f7e2d4c623631d..8a12c03267ac1f2f169d738272a7cb03779a40b7 100644 (file)
@@ -77,79 +77,189 @@ blend_for_op(int op)
 }
 
 
+static INLINE void
+setup_vertex0(float vertex[2][4], float x, float y,
+              float color[4])
+{
+   vertex[0][0] = x;
+   vertex[0][1] = y;
+   vertex[0][2] = 0.f; /*z*/
+   vertex[0][3] = 1.f; /*w*/
+
+   vertex[1][0] = color[0]; /*r*/
+   vertex[1][1] = color[1]; /*g*/
+   vertex[1][2] = color[2]; /*b*/
+   vertex[1][3] = color[3]; /*a*/
+}
+
 static struct pipe_buffer *
-setup_vertex_data_tex(struct exa_context *ctx,
-                      float x0, float y0, float x1, float y1,
-                      float x2, float y2, float x3, float y3,
-                      float s0, float t0, float s1, float t1,
-                      float z)
+setup_vertex_data0(struct exa_context *ctx,
+                   int srcX, int srcY, int maskX, int maskY,
+                   int dstX, int dstY, int width, int height)
 {
-   ctx->vertices[0][0][0] = x0;
-   ctx->vertices[0][0][1] = y0;
-   ctx->vertices[0][0][2] = z;
-   ctx->vertices[0][1][0] = s0; /*s*/
-   ctx->vertices[0][1][1] = t0; /*t*/
-
-   ctx->vertices[1][0][0] = x1;
-   ctx->vertices[1][0][1] = y1;
-   ctx->vertices[1][0][2] = z;
-   ctx->vertices[1][1][0] = s1; /*s*/
-   ctx->vertices[1][1][1] = t0; /*t*/
-
-   ctx->vertices[2][0][0] = x2;
-   ctx->vertices[2][0][1] = y2;
-   ctx->vertices[2][0][2] = z;
-   ctx->vertices[2][1][0] = s1;
-   ctx->vertices[2][1][1] = t1;
-
-   ctx->vertices[3][0][0] = x3;
-   ctx->vertices[3][0][1] = y3;
-   ctx->vertices[3][0][2] = z;
-   ctx->vertices[3][1][0] = s0;
-   ctx->vertices[3][1][1] = t1;
+   float vertices[4][2][4];
+
+   /* 1st vertex */
+   setup_vertex0(vertices[0], dstX, dstY,
+                 ctx->solid_color);
+   /* 2nd vertex */
+   setup_vertex0(vertices[1], dstX + width, dstY,
+                 ctx->solid_color);
+   /* 3rd vertex */
+   setup_vertex0(vertices[2], dstX + width, dstY + height,
+                 ctx->solid_color);
+   /* 4th vertex */
+   setup_vertex0(vertices[3], dstX, dstY + height,
+                 ctx->solid_color);
 
    return pipe_user_buffer_create(ctx->ctx->screen,
-                                  ctx->vertices,
-                                  sizeof(ctx->vertices));
+                                  vertices,
+                                  sizeof(vertices));
 }
 
-static void
-draw_texture(struct exa_context *exa,
-             struct pipe_texture *tex,
-             float x1offset, float y1offset,
-             float x2offset, float y2offset,
-             float x1, float y1,
-             float x2, float y2,
-             float x3, float y3,
-             float x4, float y4)
+static INLINE void
+setup_vertex1(float vertex[2][4], float x, float y, float s, float t)
 {
-   struct pipe_context *pipe = exa->ctx;
-   struct pipe_buffer *buf;
+   vertex[0][0] = x;
+   vertex[0][1] = y;
+   vertex[0][2] = 0.f; /*z*/
+   vertex[0][3] = 1.f; /*w*/
+
+   vertex[1][0] = s;   /*s*/
+   vertex[1][1] = t;   /*t*/
+   vertex[1][2] = 0.f; /*r*/
+   vertex[1][3] = 1.f; /*q*/
+}
+
+static struct pipe_buffer *
+setup_vertex_data1(struct exa_context *ctx,
+                   int srcX, int srcY, int maskX, int maskY,
+                   int dstX, int dstY, int width, int height)
+{
+   float vertices[4][2][4];
    float s0, t0, s1, t1;
+   struct pipe_texture *src = ctx->bound_textures[0];
+
+   s0 = srcX / src->width[0];
+   s1 = srcX + width / src->width[0];
+   t0 = srcY / src->height[0];
+   t1 = srcY + height / src->height[0];
+
+   /* 1st vertex */
+   setup_vertex1(vertices[0], dstX, dstY,
+                 s0, t0);
+   /* 2nd vertex */
+   setup_vertex1(vertices[1], dstX + width, dstY,
+                 s1, t0);
+   /* 3rd vertex */
+   setup_vertex1(vertices[2], dstX + width, dstY + height,
+                 s1, t1);
+   /* 4th vertex */
+   setup_vertex1(vertices[3], dstX, dstY + height,
+                 s0, t1);
 
-   assert(tex->width[0] != 0);
-   assert(tex->height[0] != 0);
+   return pipe_user_buffer_create(ctx->ctx->screen,
+                                  vertices,
+                                  sizeof(vertices));
+}
 
-   s0 = x1offset / tex->width[0];
-   s1 = x2offset / tex->width[0];
-   t0 = y1offset / tex->height[0];
-   t1 = y2offset / tex->height[0];
 
-   /* draw quad */
-   buf = setup_vertex_data_tex(exa, x1, y1, x2, y2, x3, y3, x4, y4,
-                               s0, t0, s1, t1, 0.0f);
+static INLINE void
+setup_vertex2(float vertex[3][4], float x, float y,
+              float s0, float t0, float s1, float t1)
+{
+   vertex[0][0] = x;
+   vertex[0][1] = y;
+   vertex[0][2] = 0.f; /*z*/
+   vertex[0][3] = 1.f; /*w*/
+
+   vertex[1][0] = s0;  /*s*/
+   vertex[1][1] = t0;  /*t*/
+   vertex[1][2] = 0.f; /*r*/
+   vertex[1][3] = 1.f; /*q*/
+
+   vertex[2][0] = s1;  /*s*/
+   vertex[2][1] = t1;  /*t*/
+   vertex[2][2] = 0.f; /*r*/
+   vertex[2][3] = 1.f; /*q*/
+}
+
+static struct pipe_buffer *
+setup_vertex_data2(struct exa_context *ctx,
+                   int srcX, int srcY, int maskX, int maskY,
+                   int dstX, int dstY, int width, int height)
+{
+   float vertices[4][3][4];
+   float st0[4], st1[4];
+   struct pipe_texture *src = ctx->bound_textures[0];
+   struct pipe_texture *mask = ctx->bound_textures[0];
+
+   st0[0] = srcX / src->width[0];
+   st0[1] = srcY / src->height[0];
+   st0[2] = srcX + width / src->width[0];
+   st0[3] = srcY + height / src->height[0];
+
+   st1[0] = maskX / mask->width[0];
+   st1[1] = maskY / mask->height[0];
+   st1[2] = maskX + width / mask->width[0];
+   st1[3] = maskY + height / mask->height[0];
+
+   /* 1st vertex */
+   setup_vertex2(vertices[0], dstX, dstY,
+                 st0[0], st0[1], st1[0], st1[1]);
+   /* 2nd vertex */
+   setup_vertex2(vertices[1], dstX + width, dstY,
+                 st0[2], st0[1], st1[2], st1[1]);
+   /* 3rd vertex */
+   setup_vertex2(vertices[2], dstX + width, dstY + height,
+                 st0[2], st0[3], st1[2], st1[3]);
+   /* 4th vertex */
+   setup_vertex2(vertices[3], dstX, dstY + height,
+                 st0[0], st0[3], st1[0], st1[3]);
+
+   return pipe_user_buffer_create(ctx->ctx->screen,
+                                  vertices,
+                                  sizeof(vertices));
+}
+
+
+static void
+draw_pictures(struct exa_context *exa,
+              int srcX, int srcY, int maskX, int maskY,
+              int dstX, int dstY, int width, int height)
+{
+   struct pipe_context *pipe = exa->ctx;
+   struct pipe_buffer *buf = 0;
+
+   if (exa->num_bound_samplers == 0 ) { /* solid fill */
+      buf = setup_vertex_data0(exa,
+                               srcX, srcY, maskX, maskY,
+                               dstX, dstY, width, height);
+   } else if (exa->num_bound_samplers == 1 ) /* src */
+      buf = setup_vertex_data1(exa,
+                               srcX, srcY, maskX, maskY,
+                               dstX, dstY, width, height);
+   else if (exa->num_bound_samplers == 2) /* src + mask */
+      buf = setup_vertex_data2(exa,
+                               srcX, srcY, maskX, maskY,
+                               dstX, dstY, width, height);
+   else if (exa->num_bound_samplers == 3) { /* src + mask + dst */
+      debug_assert(!"src/mask/dst not handled right now");
+#if 0
+      buf = setup_vertex_data2(exa,
+                               srcX, srcY, maskX, maskY,
+                               dstX, dstY, width, height);
+#endif
+   }
 
    if (buf) {
       util_draw_vertex_buffer(pipe, buf, 0,
                               PIPE_PRIM_TRIANGLE_FAN,
                               4,  /* verts */
-                              2); /* attribs/vert */
+                              1 + exa->num_bound_samplers); /* attribs/vert */
 
-      pipe_buffer_reference(&buf,
-                            NULL);
+      pipe_buffer_reference(&buf, NULL);
    }
-
-   cso_restore_vertex_shader(exa->cso);
 }
 
 boolean xorg_composite_accelerated(int op,
@@ -309,9 +419,10 @@ bind_samplers(struct exa_context *exa, int op,
               struct exa_pixmap_priv *pDst)
 {
    struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
-   struct pipe_texture *textures[PIPE_MAX_SAMPLERS];
    struct pipe_sampler_state src_sampler, mask_sampler;
 
+   exa->num_bound_samplers = 0;
+
    memset(&src_sampler, 0, sizeof(struct pipe_sampler_state));
    memset(&mask_sampler, 0, sizeof(struct pipe_sampler_state));
 
@@ -322,7 +433,8 @@ bind_samplers(struct exa_context *exa, int op,
       src_sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
       src_sampler.normalized_coords = 1;
       samplers[0] = &src_sampler;
-      textures[0] = pSrc->tex;
+      exa->bound_textures[0] = pSrc->tex;
+      ++exa->num_bound_samplers;
    }
 
    if (pMaskPicture && pMask) {
@@ -332,12 +444,14 @@ bind_samplers(struct exa_context *exa, int op,
       mask_sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
       mask_sampler.normalized_coords = 1;
       samplers[1] = &mask_sampler;
-      textures[1] = pMask->tex;
+      exa->bound_textures[1] = pMask->tex;
+      ++exa->num_bound_samplers;
    }
 
-   cso_set_samplers(exa->cso, 3,
+   cso_set_samplers(exa->cso, exa->num_bound_samplers,
                     (const struct pipe_sampler_state **)samplers);
-   cso_set_sampler_textures(exa->cso, 3, textures);
+   cso_set_sampler_textures(exa->cso, exa->num_bound_samplers,
+                            exa->bound_textures);
 }
 
 static void
@@ -409,8 +523,8 @@ boolean xorg_composite_bind_state(struct exa_context *exa,
    bind_blend_state(exa, op, pSrcPicture, pMaskPicture);
    bind_rasterizer_state(exa);
    bind_shaders(exa, op, pSrcPicture, pMaskPicture);
-   bind_samplers(exa, op, pSrcPicture, pMaskPicture, pDstPicture,
-                 pSrc, pMask, pDst);
+   bind_samplers(exa, op, pSrcPicture, pMaskPicture,
+                 pDstPicture, pSrc, pMask, pDst);
 
    setup_constant_buffers(exa, pDstPicture);
 
@@ -422,5 +536,7 @@ void xorg_composite(struct exa_context *exa,
                     int srcX, int srcY, int maskX, int maskY,
                     int dstX, int dstY, int width, int height)
 {
+   draw_pictures(exa, srcX, srcY, maskX, maskY,
+                 dstX, dstY, width, height);
 }
 
index 3697d26363e4aaaab1136fb90a7fdc51201bb7e7..1ed807de93d1251b3b8f2f9f783b19febf4d7b64 100644 (file)
@@ -563,7 +563,6 @@ xorg_exa_init(ScrnInfoPtr pScrn)
    modesettingPtr ms = modesettingPTR(pScrn);
    struct exa_context *exa;
    ExaDriverPtr pExa;
-   int i;
 
    exa = xcalloc(1, sizeof(struct exa_context));
    if (!exa)
@@ -615,13 +614,6 @@ xorg_exa_init(ScrnInfoPtr pScrn)
    /* Share context with DRI */
    ms->ctx = exa->ctx;
 
-   /* common vertex data setup */
-   for (i = 0; i < 4; ++i) {
-      exa->vertices[i][0][3] = 1.0f; /* w */
-      exa->vertices[i][1][2] = 0.0f; /* r */
-      exa->vertices[i][1][3] = 1.0f; /* q */
-   }
-
    exa->cso = cso_create_context(exa->ctx);
    exa->shaders = xorg_shaders_create(exa);
 
index 90ad8400ffd2a139882dbf2e657f6aeabac0f6dd..d4ffe5ce2e86388bff936e85449e4cd915a371b9 100644 (file)
@@ -8,6 +8,9 @@
 struct cso_context;
 struct xorg_shaders;
 
+/* src + mask + dst */
+#define MAX_EXA_SAMPLERS 3
+
 struct exa_context
 {
    ExaDriverPtr pExa;
@@ -19,7 +22,10 @@ struct exa_context
    struct pipe_constant_buffer vs_const_buffer;
    struct pipe_constant_buffer fs_const_buffer;
 
-   float vertices[4][2][4];
+   struct pipe_texture *bound_textures[MAX_EXA_SAMPLERS];
+   int num_bound_samplers;
+
+   float solid_color[4];
 };