From 187d7fb2fec7da889f25366696faaac4c2e8f9c4 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Fri, 24 Aug 2012 05:57:22 +0200 Subject: [PATCH] r600g: implement draw_rectangle callback 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 | 21 ++---- src/gallium/auxiliary/util/u_blitter.h | 9 +++ src/gallium/drivers/r600/r600_pipe.c | 1 + src/gallium/drivers/r600/r600_pipe.h | 4 ++ src/gallium/drivers/r600/r600_state_common.c | 69 +++++++++++++++++++- 5 files changed, 88 insertions(+), 16 deletions(-) diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c index ad4ccd9eb46..03ed91fa0b5 100644 --- a/src/gallium/auxiliary/util/u_blitter.c +++ b/src/gallium/auxiliary/util/u_blitter.c @@ -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; diff --git a/src/gallium/auxiliary/util/u_blitter.h b/src/gallium/auxiliary/util/u_blitter.h index e06e8b12d53..2055fd64f40 100644 --- a/src/gallium/auxiliary/util/u_blitter.h +++ b/src/gallium/auxiliary/util/u_blitter.h @@ -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 diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c index 34ba80b244f..77adeaef8bc 100644 --- a/src/gallium/drivers/r600/r600_pipe.c +++ b/src/gallium/drivers/r600/r600_pipe.c @@ -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 */ diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h index 074eed432dc..9cbf0c88e64 100644 --- a/src/gallium/drivers/r600/r600_pipe.h +++ b/src/gallium/drivers/r600/r600_pipe.h @@ -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); diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c index 77c3e20599e..e8801329d3f 100644 --- a/src/gallium/drivers/r600/r600_state_common.c +++ b/src/gallium/drivers/r600/r600_state_common.c @@ -27,11 +27,13 @@ #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 +#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, -- 2.30.2