r600g: implement draw_rectangle callback
authorMarek Olšák <maraeo@gmail.com>
Fri, 24 Aug 2012 03:57:22 +0000 (05:57 +0200)
committerMarek Olšák <maraeo@gmail.com>
Thu, 30 Aug 2012 17:43:55 +0000 (19:43 +0200)
The color resolve on r6xx needs PT_RECTLIST. Using conventional primitive
types (triangles and quads) produces an ugly line between two diagonally
opposite corners. I guess a rectangular point sprite would work too.

src/gallium/auxiliary/util/u_blitter.c
src/gallium/auxiliary/util/u_blitter.h
src/gallium/drivers/r600/r600_pipe.c
src/gallium/drivers/r600/r600_pipe.h
src/gallium/drivers/r600/r600_state_common.c

index ad4ccd9eb46bb40f898482d4575cb0d4a0e62f35..03ed91fa0b50ac40c8f41b87c84c99941d513fef 100644 (file)
@@ -123,13 +123,6 @@ struct blitter_context_priv
    boolean has_stencil_export;
 };
 
-static void blitter_draw_rectangle(struct blitter_context *blitter,
-                                   unsigned x, unsigned y,
-                                   unsigned width, unsigned height,
-                                   float depth,
-                                   enum blitter_attrib_type type,
-                                   const union pipe_color_union *attrib);
-
 
 struct blitter_context *util_blitter_create(struct pipe_context *pipe)
 {
@@ -146,7 +139,7 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
       return NULL;
 
    ctx->base.pipe = pipe;
-   ctx->base.draw_rectangle = blitter_draw_rectangle;
+   ctx->base.draw_rectangle = util_blitter_draw_rectangle;
 
    /* init state objects for them to be considered invalid */
    ctx->base.saved_blend_state = INVALID_PTR;
@@ -862,12 +855,12 @@ static void blitter_draw(struct blitter_context_priv *ctx,
    pipe_resource_reference(&buf, NULL);
 }
 
-static void blitter_draw_rectangle(struct blitter_context *blitter,
-                                   unsigned x1, unsigned y1,
-                                   unsigned x2, unsigned y2,
-                                   float depth,
-                                   enum blitter_attrib_type type,
-                                   const union pipe_color_union *attrib)
+void util_blitter_draw_rectangle(struct blitter_context *blitter,
+                                 unsigned x1, unsigned y1,
+                                 unsigned x2, unsigned y2,
+                                 float depth,
+                                 enum blitter_attrib_type type,
+                                 const union pipe_color_union *attrib)
 {
    struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
 
index e06e8b12d53bc6bd48e4e9c07d884656ca3c4d09..2055fd64f4004902d810d2778023d9dc8145f261 100644 (file)
@@ -129,6 +129,15 @@ struct pipe_context *util_blitter_get_pipe(struct blitter_context *blitter)
    return blitter->pipe;
 }
 
+/* The default function to draw a rectangle. This can only be used
+ * inside of the draw_rectangle callback if the driver overrides it. */
+void util_blitter_draw_rectangle(struct blitter_context *blitter,
+                                 unsigned x1, unsigned y1,
+                                 unsigned x2, unsigned y2,
+                                 float depth,
+                                 enum blitter_attrib_type type,
+                                 const union pipe_color_union *attrib);
+
 /*
  * These states must be saved before any of the following functions are called:
  * - vertex buffers
index 34ba80b244f421853ff831ea0418d37d6de1b033..77adeaef8bc9b671c79dd13be980f76b7e167817 100644 (file)
@@ -294,6 +294,7 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void
        rctx->blitter = util_blitter_create(&rctx->context);
        if (rctx->blitter == NULL)
                goto fail;
+       rctx->blitter->draw_rectangle = r600_draw_rectangle;
 
        r600_get_backend_mask(rctx); /* this emits commands and must be last */
 
index 074eed432dcf0a704690e11c2071ec43839f728a..9cbf0c88e64bec527d230db0733ad71f7a477e8f 100644 (file)
@@ -26,6 +26,7 @@
 #ifndef R600_PIPE_H
 #define R600_PIPE_H
 
+#include "util/u_blitter.h"
 #include "util/u_slab.h"
 #include "r600.h"
 #include "r600_llvm.h"
@@ -638,6 +639,9 @@ void r600_set_sample_mask(struct pipe_context *pipe, unsigned sample_mask);
 void r600_set_pipe_stencil_ref(struct pipe_context *ctx,
                               const struct pipe_stencil_ref *state);
 void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info);
+void r600_draw_rectangle(struct blitter_context *blitter,
+                        unsigned x1, unsigned y1, unsigned x2, unsigned y2, float depth,
+                        enum blitter_attrib_type type, const union pipe_color_union *attrib);
 uint32_t r600_translate_stencil_op(int s_op);
 uint32_t r600_translate_fill(uint32_t func);
 unsigned r600_tex_wrap(unsigned wrap);
index 77c3e20599e3fa9b2f5553ed1bda43d43c2dc7f2..e8801329d3fb78c4a831e9a90ad246a72b85fecc 100644 (file)
 #include "r600_formats.h"
 #include "r600d.h"
 
-#include "util/u_blitter.h"
+#include "util/u_draw_quad.h"
 #include "util/u_upload_mgr.h"
 #include "tgsi/tgsi_parse.h"
 #include <byteswap.h>
 
+#define R600_PRIM_RECTANGLE_LIST PIPE_PRIM_MAX
+
 static void r600_emit_command_buffer(struct r600_context *rctx, struct r600_atom *atom)
 {
        struct radeon_winsys_cs *cs = rctx->cs;
@@ -153,7 +155,8 @@ static bool r600_conv_pipe_prim(unsigned pprim, unsigned *prim)
                -1,
                -1,
                -1,
-               -1
+               -1,
+               V_008958_DI_PT_RECTLIST
        };
 
        *prim = prim_conv[pprim];
@@ -1110,6 +1113,7 @@ static unsigned r600_conv_prim_to_gs_out(unsigned mode)
                V_028A6C_OUTPRIM_TYPE_LINESTRIP,
                V_028A6C_OUTPRIM_TYPE_LINESTRIP,
                V_028A6C_OUTPRIM_TYPE_TRISTRIP,
+               V_028A6C_OUTPRIM_TYPE_TRISTRIP,
                V_028A6C_OUTPRIM_TYPE_TRISTRIP
        };
        assert(mode < Elements(prim_conv));
@@ -1293,6 +1297,67 @@ void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *dinfo)
        pipe_resource_reference(&ib.buffer, NULL);
 }
 
+void r600_draw_rectangle(struct blitter_context *blitter,
+                        unsigned x1, unsigned y1, unsigned x2, unsigned y2, float depth,
+                        enum blitter_attrib_type type, const union pipe_color_union *attrib)
+{
+       struct r600_context *rctx = (struct r600_context*)util_blitter_get_pipe(blitter);
+       struct pipe_viewport_state viewport;
+       struct pipe_resource *buf = NULL;
+       unsigned offset = 0;
+       float *vb;
+
+       if (type == UTIL_BLITTER_ATTRIB_TEXCOORD) {
+               util_blitter_draw_rectangle(blitter, x1, y1, x2, y2, depth, type, attrib);
+               return;
+       }
+
+       /* Some operations (like color resolve on r6xx) don't work
+        * with the conventional primitive types.
+        * One that works is PT_RECTLIST, which we use here. */
+
+       /* setup viewport */
+       viewport.scale[0] = 1.0f;
+       viewport.scale[1] = 1.0f;
+       viewport.scale[2] = 1.0f;
+       viewport.scale[3] = 1.0f;
+       viewport.translate[0] = 0.0f;
+       viewport.translate[1] = 0.0f;
+       viewport.translate[2] = 0.0f;
+       viewport.translate[3] = 0.0f;
+       rctx->context.set_viewport_state(&rctx->context, &viewport);
+
+       /* Upload vertices. The hw rectangle has only 3 vertices,
+        * I guess the 4th one is derived from the first 3.
+        * The vertex specification should match u_blitter's vertex element state. */
+       u_upload_alloc(rctx->uploader, 0, sizeof(float) * 24, &offset, &buf, (void**)&vb);
+       vb[0] = x1;
+       vb[1] = y1;
+       vb[2] = depth;
+       vb[3] = 1;
+
+       vb[8] = x1;
+       vb[9] = y2;
+       vb[10] = depth;
+       vb[11] = 1;
+
+       vb[16] = x2;
+       vb[17] = y1;
+       vb[18] = depth;
+       vb[19] = 1;
+
+       if (attrib) {
+               memcpy(vb+4, attrib->f, sizeof(float)*4);
+               memcpy(vb+12, attrib->f, sizeof(float)*4);
+               memcpy(vb+20, attrib->f, sizeof(float)*4);
+       }
+
+       /* draw */
+       util_draw_vertex_buffer(&rctx->context, NULL, buf, offset,
+                               R600_PRIM_RECTANGLE_LIST, 3, 2);
+       pipe_resource_reference(&buf, NULL);
+}
+
 void _r600_pipe_state_add_reg_bo(struct r600_context *ctx,
                                 struct r600_pipe_state *state,
                                 uint32_t offset, uint32_t value,