diff options
Diffstat (limited to 'src/gallium')
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_rast.c | 122 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_rast.h | 9 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_scene.c | 1 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_scene.h | 1 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_setup.c | 217 | ||||
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_setup_context.h | 3 |
6 files changed, 190 insertions, 163 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c index 0ae5976eedc..d50ee482142 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast.c +++ b/src/gallium/drivers/llvmpipe/lp_rast.c @@ -110,25 +110,6 @@ lp_rast_tile_begin(struct lp_rasterizer_task *task, /** - * Examine a framebuffer object to determine if any of the colorbuffers - * use a pure integer format. - * XXX this could be a gallium utility function if useful elsewhere. - */ -static boolean -is_fb_pure_integer(const struct pipe_framebuffer_state *fb) -{ - unsigned i; - for (i = 0; i < fb->nr_cbufs; i++) { - if (fb->cbufs[i] && - util_format_is_pure_integer(fb->cbufs[i]->format)) { - return TRUE; - } - } - return FALSE; -} - - -/** * Clear the rasterizer's current color tile. * This is a bin command called during bin processing. * Clear commands always clear all bound layers. @@ -138,87 +119,42 @@ lp_rast_clear_color(struct lp_rasterizer_task *task, const union lp_rast_cmd_arg arg) { const struct lp_scene *scene = task->scene; + unsigned cbuf = arg.clear_rb->cbuf; + union util_color uc; + enum pipe_format format; - if (scene->fb.nr_cbufs) { - unsigned i; - union util_color uc; - - if (is_fb_pure_integer(&scene->fb)) { - /* - * We expect int/uint clear values here, though some APIs - * might disagree (but in any case util_pack_color() - * couldn't handle it)... - */ - LP_DBG(DEBUG_RAST, "%s pure int 0x%x,0x%x,0x%x,0x%x\n", __FUNCTION__, - arg.clear_color.ui[0], - arg.clear_color.ui[1], - arg.clear_color.ui[2], - arg.clear_color.ui[3]); - - for (i = 0; i < scene->fb.nr_cbufs; i++) { - enum pipe_format format = scene->fb.cbufs[i]->format; - - if (util_format_is_pure_sint(format)) { - util_format_write_4i(format, arg.clear_color.i, 0, &uc, 0, 0, 0, 1, 1); - } - else { - assert(util_format_is_pure_uint(format)); - util_format_write_4ui(format, arg.clear_color.ui, 0, &uc, 0, 0, 0, 1, 1); - } - - util_fill_box(scene->cbufs[i].map, - format, - scene->cbufs[i].stride, - scene->cbufs[i].layer_stride, - task->x, - task->y, - 0, - task->width, - task->height, - scene->fb_max_layer + 1, - &uc); - } - } - else { - uint8_t clear_color[4]; - - for (i = 0; i < 4; ++i) { - clear_color[i] = float_to_ubyte(arg.clear_color.f[i]); - } + /* we never bin clear commands for non-existing buffers */ + assert(cbuf < scene->fb.nr_cbufs); + assert(scene->fb.cbufs[cbuf]); - LP_DBG(DEBUG_RAST, "%s 0x%x,0x%x,0x%x,0x%x\n", __FUNCTION__, - clear_color[0], - clear_color[1], - clear_color[2], - clear_color[3]); - - for (i = 0; i < scene->fb.nr_cbufs; i++) { - if (scene->fb.cbufs[i]) { - util_pack_color(arg.clear_color.f, - scene->fb.cbufs[i]->format, &uc); - - util_fill_box(scene->cbufs[i].map, - scene->fb.cbufs[i]->format, - scene->cbufs[i].stride, - scene->cbufs[i].layer_stride, - task->x, - task->y, - 0, - task->width, - task->height, - scene->fb_max_layer + 1, - &uc); - } - } - } - } + format = scene->fb.cbufs[cbuf]->format; + uc = arg.clear_rb->color_val; + /* + * this is pretty rough since we have target format (bunch of bytes...) here. + * dump it as raw 4 dwords. + */ + LP_DBG(DEBUG_RAST, "%s clear value (target format %d) raw 0x%x,0x%x,0x%x,0x%x\n", + __FUNCTION__, format, uc.ui[0], uc.ui[1], uc.ui[2], uc.ui[3]); + + + util_fill_box(scene->cbufs[cbuf].map, + format, + scene->cbufs[cbuf].stride, + scene->cbufs[cbuf].layer_stride, + task->x, + task->y, + 0, + task->width, + task->height, + scene->fb_max_layer + 1, + &uc); + + /* this will increase for each rb which probably doesn't mean much */ LP_COUNT(nr_color_tile_clear); } - - /** * Clear the rasterizer's current z/stencil tile. * This is a bin command called during bin processing. diff --git a/src/gallium/drivers/llvmpipe/lp_rast.h b/src/gallium/drivers/llvmpipe/lp_rast.h index e2a9ec20892..6bd917d962f 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast.h +++ b/src/gallium/drivers/llvmpipe/lp_rast.h @@ -38,6 +38,7 @@ #define LP_RAST_H #include "pipe/p_compiler.h" +#include "util/u_pack_color.h" #include "lp_jit.h" @@ -136,6 +137,12 @@ struct lp_rast_triangle { }; +struct lp_rast_clear_rb { + union util_color color_val; + unsigned cbuf; +}; + + #define GET_A0(inputs) ((float (*)[4])((inputs)+1)) #define GET_DADX(inputs) ((float (*)[4])((char *)((inputs) + 1) + (inputs)->stride)) #define GET_DADY(inputs) ((float (*)[4])((char *)((inputs) + 1) + 2 * (inputs)->stride)) @@ -164,7 +171,7 @@ union lp_rast_cmd_arg { unsigned plane_mask; } triangle; const struct lp_rast_state *set_state; - union pipe_color_union clear_color; + const struct lp_rast_clear_rb *clear_rb; struct { uint64_t value; uint64_t mask; diff --git a/src/gallium/drivers/llvmpipe/lp_scene.c b/src/gallium/drivers/llvmpipe/lp_scene.c index 9ba5f1ace2e..9a8df275d89 100644 --- a/src/gallium/drivers/llvmpipe/lp_scene.c +++ b/src/gallium/drivers/llvmpipe/lp_scene.c @@ -292,7 +292,6 @@ lp_scene_end_rasterization(struct lp_scene *scene ) scene->scene_size = 0; scene->resource_reference_size = 0; - scene->has_depthstencil_clear = FALSE; scene->alloc_failed = FALSE; util_unreference_framebuffer_state( &scene->fb ); diff --git a/src/gallium/drivers/llvmpipe/lp_scene.h b/src/gallium/drivers/llvmpipe/lp_scene.h index 94b1779f04c..19a38115afe 100644 --- a/src/gallium/drivers/llvmpipe/lp_scene.h +++ b/src/gallium/drivers/llvmpipe/lp_scene.h @@ -165,7 +165,6 @@ struct lp_scene { unsigned resource_reference_size; boolean alloc_failed; - boolean has_depthstencil_clear; boolean discard; /** * Number of active tiles in each dimension. diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index b4ce92558bd..77ac3af993d 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -202,25 +202,38 @@ begin_binning( struct lp_setup_context *setup ) util_format_is_depth_and_stencil(setup->fb.zsbuf->format)) need_zsload = TRUE; - LP_DBG(DEBUG_SETUP, "%s color: %s depth: %s\n", __FUNCTION__, - (setup->clear.flags & PIPE_CLEAR_COLOR) ? "clear": "load", + LP_DBG(DEBUG_SETUP, "%s color clear bufs: %x depth: %s\n", __FUNCTION__, + setup->clear.flags >> 2, need_zsload ? "clear": "load"); - if (setup->fb.nr_cbufs) { - if (setup->clear.flags & PIPE_CLEAR_COLOR) { - ok = lp_scene_bin_everywhere( scene, - LP_RAST_OP_CLEAR_COLOR, - setup->clear.color ); - if (!ok) - return FALSE; + if (setup->clear.flags & PIPE_CLEAR_COLOR) { + unsigned cbuf; + for (cbuf = 0; cbuf < setup->fb.nr_cbufs; cbuf++) { + assert(PIPE_CLEAR_COLOR0 == 1 << 2); + if (setup->clear.flags & (1 << (2 + cbuf))) { + union lp_rast_cmd_arg clearrb_arg; + struct lp_rast_clear_rb *cc_scene = + (struct lp_rast_clear_rb *) + lp_scene_alloc(scene, sizeof(struct lp_rast_clear_rb)); + + if (!cc_scene) { + return FALSE; + } + + cc_scene->cbuf = cbuf; + cc_scene->color_val = setup->clear.color_val[cbuf]; + clearrb_arg.clear_rb = cc_scene; + + if (!lp_scene_bin_everywhere(scene, + LP_RAST_OP_CLEAR_COLOR, + clearrb_arg)) + return FALSE; + } } } if (setup->fb.zsbuf) { if (setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) { - if (!need_zsload) - scene->has_depthstencil_clear = TRUE; - ok = lp_scene_bin_everywhere( scene, LP_RAST_OP_CLEAR_ZSTENCIL, lp_rast_arg_clearzs( @@ -367,41 +380,107 @@ lp_setup_bind_framebuffer( struct lp_setup_context *setup, } +/* + * Try to clear one color buffer of the attached fb, either by binning a clear + * command or queuing up the clear for later (when binning is started). + */ static boolean -lp_setup_try_clear( struct lp_setup_context *setup, - const union pipe_color_union *color, - double depth, - unsigned stencil, - unsigned flags ) +lp_setup_try_clear_color_buffer(struct lp_setup_context *setup, + const union pipe_color_union *color, + unsigned cbuf) { - uint64_t zsmask = 0; - uint64_t zsvalue = 0; - union lp_rast_cmd_arg color_arg; - unsigned i; + union lp_rast_cmd_arg clearrb_arg; + union util_color uc; + enum pipe_format format = setup->fb.cbufs[cbuf]->format; LP_DBG(DEBUG_SETUP, "%s state %d\n", __FUNCTION__, setup->state); - if (flags & PIPE_CLEAR_COLOR) { - for (i = 0; i < 4; i++) - color_arg.clear_color.i[i] = color->i[i]; + if (util_format_is_pure_integer(format)) { + /* + * We expect int/uint clear values here, though some APIs + * might disagree (but in any case util_pack_color() + * couldn't handle it)... + */ + if (util_format_is_pure_sint(format)) { + util_format_write_4i(format, color->i, 0, &uc, 0, 0, 0, 1, 1); + } + else { + assert(util_format_is_pure_uint(format)); + util_format_write_4ui(format, color->ui, 0, &uc, 0, 0, 0, 1, 1); + } + } + else { + util_pack_color(color->f, format, &uc); } - if (flags & PIPE_CLEAR_DEPTHSTENCIL) { - uint32_t zmask = (flags & PIPE_CLEAR_DEPTH) ? ~0 : 0; - uint8_t smask = (flags & PIPE_CLEAR_STENCIL) ? ~0 : 0; + if (setup->state == SETUP_ACTIVE) { + struct lp_scene *scene = setup->scene; + + /* Add the clear to existing scene. In the unusual case where + * both color and depth-stencil are being cleared when there's + * already been some rendering, we could discard the currently + * binned scene and start again, but I don't see that as being + * a common usage. + */ + struct lp_rast_clear_rb *cc_scene = + (struct lp_rast_clear_rb *) + lp_scene_alloc_aligned(scene, sizeof(struct lp_rast_clear_rb), 8); - zsvalue = util_pack64_z_stencil(setup->fb.zsbuf->format, - depth, - stencil); + if (!cc_scene) { + return FALSE; + } + cc_scene->cbuf = cbuf; + cc_scene->color_val = uc; + clearrb_arg.clear_rb = cc_scene; - zsmask = util_pack64_mask_z_stencil(setup->fb.zsbuf->format, - zmask, - smask); + if (!lp_scene_bin_everywhere(scene, + LP_RAST_OP_CLEAR_COLOR, + clearrb_arg)) + return FALSE; + } + else { + /* Put ourselves into the 'pre-clear' state, specifically to try + * and accumulate multiple clears to color and depth_stencil + * buffers which the app or state-tracker might issue + * separately. + */ + set_scene_state( setup, SETUP_CLEARED, __FUNCTION__ ); - zsvalue &= zsmask; + assert(PIPE_CLEAR_COLOR0 == (1 << 2)); + setup->clear.flags |= 1 << (cbuf + 2); + setup->clear.color_val[cbuf] = uc; } + return TRUE; +} + +static boolean +lp_setup_try_clear_zs(struct lp_setup_context *setup, + double depth, + unsigned stencil, + unsigned flags) +{ + uint64_t zsmask = 0; + uint64_t zsvalue = 0; + uint32_t zmask32; + uint8_t smask8; + + LP_DBG(DEBUG_SETUP, "%s state %d\n", __FUNCTION__, setup->state); + + zmask32 = (flags & PIPE_CLEAR_DEPTH) ? ~0 : 0; + smask8 = (flags & PIPE_CLEAR_STENCIL) ? ~0 : 0; + + zsvalue = util_pack64_z_stencil(setup->fb.zsbuf->format, + depth, + stencil); + + zsmask = util_pack64_mask_z_stencil(setup->fb.zsbuf->format, + zmask32, + smask8); + + zsvalue &= zsmask; + if (setup->state == SETUP_ACTIVE) { struct lp_scene *scene = setup->scene; @@ -411,19 +490,10 @@ lp_setup_try_clear( struct lp_setup_context *setup, * binned scene and start again, but I don't see that as being * a common usage. */ - if (flags & PIPE_CLEAR_COLOR) { - if (!lp_scene_bin_everywhere( scene, - LP_RAST_OP_CLEAR_COLOR, - color_arg )) - return FALSE; - } - - if (flags & PIPE_CLEAR_DEPTHSTENCIL) { - if (!lp_scene_bin_everywhere( scene, - LP_RAST_OP_CLEAR_ZSTENCIL, - lp_rast_arg_clearzs(zsvalue, zsmask) )) - return FALSE; - } + if (!lp_scene_bin_everywhere(scene, + LP_RAST_OP_CLEAR_ZSTENCIL, + lp_rast_arg_clearzs(zsvalue, zsmask))) + return FALSE; } else { /* Put ourselves into the 'pre-clear' state, specifically to try @@ -435,19 +505,11 @@ lp_setup_try_clear( struct lp_setup_context *setup, setup->clear.flags |= flags; - if (flags & PIPE_CLEAR_DEPTHSTENCIL) { - setup->clear.zsmask |= zsmask; - setup->clear.zsvalue = - (setup->clear.zsvalue & ~zsmask) | (zsvalue & zsmask); - } - - if (flags & PIPE_CLEAR_COLOR) { - memcpy(&setup->clear.color.clear_color, - &color_arg, - sizeof setup->clear.color.clear_color); - } + setup->clear.zsmask |= zsmask; + setup->clear.zsvalue = + (setup->clear.zsvalue & ~zsmask) | (zsvalue & zsmask); } - + return TRUE; } @@ -458,15 +520,38 @@ lp_setup_clear( struct lp_setup_context *setup, unsigned stencil, unsigned flags ) { - if (!lp_setup_try_clear( setup, color, depth, stencil, flags )) { - lp_setup_flush(setup, NULL, __FUNCTION__); + unsigned i; - if (!lp_setup_try_clear( setup, color, depth, stencil, flags )) - assert(0); - } -} + /* + * Note any of these (max 9) clears could fail (but at most there should + * be just one failure!). This avoids doing the previous succeeded + * clears again (we still clear tiles twice if a clear command succeeded + * partially for one buffer). + */ + if (flags & PIPE_CLEAR_DEPTHSTENCIL) { + unsigned flagszs = flags & PIPE_CLEAR_DEPTHSTENCIL; + if (!lp_setup_try_clear_zs(setup, depth, stencil, flagszs)) { + lp_setup_flush(setup, NULL, __FUNCTION__); + if (!lp_setup_try_clear_zs(setup, depth, stencil, flagszs)) + assert(0); + } + } + if (flags & PIPE_CLEAR_COLOR) { + assert(PIPE_CLEAR_COLOR0 == (1 << 2)); + for (i = 0; i < setup->fb.nr_cbufs; i++) { + if ((flags & (1 << (2 + i))) && setup->fb.cbufs[i]) { + if (!lp_setup_try_clear_color_buffer(setup, color, i)) { + lp_setup_flush(setup, NULL, __FUNCTION__); + + if (!lp_setup_try_clear_color_buffer(setup, color, i)) + assert(0); + } + } + } + } +} @@ -503,7 +588,7 @@ lp_setup_set_line_state( struct lp_setup_context *setup, void lp_setup_set_point_state( struct lp_setup_context *setup, - float point_size, + float point_size, boolean point_size_per_vertex, uint sprite_coord_enable, uint sprite_coord_origin) diff --git a/src/gallium/drivers/llvmpipe/lp_setup_context.h b/src/gallium/drivers/llvmpipe/lp_setup_context.h index b3fb24ac497..ef54403e1b5 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_context.h +++ b/src/gallium/drivers/llvmpipe/lp_setup_context.h @@ -42,6 +42,7 @@ #include "draw/draw_vbuf.h" #include "util/u_rect.h" +#include "util/u_pack_color.h" #define LP_SETUP_NEW_FS 0x01 #define LP_SETUP_NEW_CONSTANTS 0x02 @@ -116,7 +117,7 @@ struct lp_setup_context struct { unsigned flags; - union lp_rast_cmd_arg color; /**< lp_rast_clear_color() cmd */ + union util_color color_val[PIPE_MAX_COLOR_BUFS]; uint64_t zsmask; uint64_t zsvalue; /**< lp_rast_clear_zstencil() cmd */ } clear; |