util: adapt to clear interface changes

This commit is contained in:
Roland Scheidegger
2010-05-29 00:02:05 +02:00
parent 0cd70b554c
commit a1d5131d2e
5 changed files with 152 additions and 96 deletions
+86 -42
View File
@@ -26,8 +26,8 @@
/**
* @file
* Blitter utility to facilitate acceleration of the clear, resource_copy_region,
* and resource_fill_region functions.
* Blitter utility to facilitate acceleration of the clear, clearRT, clearDS
* resource_copy_region functions.
*
* @author Marek Olšák
*/
@@ -88,6 +88,7 @@ struct blitter_context_priv
void *dsa_write_depth_stencil;
void *dsa_write_depth_keep_stencil;
void *dsa_keep_depth_stencil;
void *dsa_keep_depth_write_stencil;
void *velem_state;
@@ -161,8 +162,12 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
dsa.stencil[0].writemask = 0xff;
ctx->dsa_write_depth_stencil =
pipe->create_depth_stencil_alpha_state(pipe, &dsa);
/* The DSA state objects which write depth and stencil are created
* on-demand. */
dsa.depth.enabled = 0;
dsa.depth.writemask = 0;
ctx->dsa_keep_depth_write_stencil =
pipe->create_depth_stencil_alpha_state(pipe, &dsa);
/* sampler state */
sampler_state = &ctx->template_sampler_state;
@@ -234,6 +239,7 @@ void util_blitter_destroy(struct blitter_context *blitter)
pipe->delete_depth_stencil_alpha_state(pipe,
ctx->dsa_write_depth_keep_stencil);
pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil);
pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil);
pipe->delete_rasterizer_state(pipe, ctx->rs_state);
pipe->delete_vs_state(pipe, ctx->vs_col);
@@ -605,11 +611,19 @@ void util_blitter_clear(struct blitter_context *blitter,
else
pipe->bind_blend_state(pipe, ctx->blend_keep_color);
if (clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) {
if ((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) {
sr.ref_value[0] = stencil & 0xff;
pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil);
pipe->set_stencil_ref(pipe, &sr);
}
else if (clear_buffers & PIPE_CLEAR_DEPTH) {
pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil);
}
else if (clear_buffers & PIPE_CLEAR_STENCIL) {
sr.ref_value[0] = stencil & 0xff;
pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil);
pipe->set_stencil_ref(pipe, &sr);
}
else
pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
@@ -766,48 +780,21 @@ void util_blitter_copy_region(struct blitter_context *blitter,
pipe_surface_reference(&dstsurf, NULL);
}
/* Fill a region of a surface with a constant value. */
void util_blitter_fill_region(struct blitter_context *blitter,
struct pipe_resource *dst,
struct pipe_subresource subdst,
unsigned dstx, unsigned dsty, unsigned dstz,
unsigned width, unsigned height,
unsigned value)
/* Clear a region of a color surface to a constant value. */
void util_blitter_clearRT(struct blitter_context *blitter,
struct pipe_surface *dstsurf,
const float *rgba,
unsigned dstx, unsigned dsty,
unsigned width, unsigned height)
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
struct pipe_context *pipe = ctx->pipe;
struct pipe_screen *screen = pipe->screen;
struct pipe_surface *dstsurf;
struct pipe_framebuffer_state fb_state;
float rgba[4];
ubyte ub_rgba[4] = {0};
union util_color color;
int i;
assert(dst);
if (!dst)
assert(dstsurf->texture);
if (!dstsurf->texture)
return;
/* check if we can render to the surface */
if (util_format_is_depth_or_stencil(dst->format) || /* unlikely, but you never know */
!screen->is_format_supported(screen, dst->format, dst->target,
dst->nr_samples,
PIPE_BIND_RENDER_TARGET, 0)) {
util_resource_fill_region(pipe, dst, subdst, dstx, dsty, dstz,
width, height, value);
return;
}
dstsurf = screen->get_tex_surface(screen, dst, subdst.face, subdst.level,
dstz, PIPE_BIND_RENDER_TARGET);
/* unpack the color */
color.ui = value;
util_unpack_color_ub(dst->format, &color,
ub_rgba, ub_rgba+1, ub_rgba+2, ub_rgba+3);
for (i = 0; i < 4; i++)
rgba[i] = ubyte_to_float(ub_rgba[i]);
/* check the saved state */
blitter_check_saved_CSOs(ctx);
assert(blitter->saved_fb_state.nr_cbufs != ~0);
@@ -832,6 +819,63 @@ void util_blitter_fill_region(struct blitter_context *blitter,
blitter_set_rectangle(ctx, 0, 0, width, height, dstsurf->width, dstsurf->height, 0);
blitter_draw_quad(ctx);
blitter_restore_CSOs(ctx);
pipe_surface_reference(&dstsurf, NULL);
}
/* Clear a region of a depth stencil surface. */
void util_blitter_clearDS(struct blitter_context *blitter,
struct pipe_surface *dstsurf,
unsigned clear_flags,
double depth,
unsigned stencil,
unsigned dstx, unsigned dsty,
unsigned width, unsigned height)
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
struct pipe_context *pipe = ctx->pipe;
struct pipe_framebuffer_state fb_state;
struct pipe_stencil_ref sr = { { 0 } };
assert(dstsurf->texture);
if (!dstsurf->texture)
return;
/* check the saved state */
blitter_check_saved_CSOs(ctx);
assert(blitter->saved_fb_state.nr_cbufs != ~0);
/* bind CSOs */
pipe->bind_blend_state(pipe, ctx->blend_keep_color);
if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) {
sr.ref_value[0] = stencil & 0xff;
pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil);
pipe->set_stencil_ref(pipe, &sr);
}
else if (clear_flags & PIPE_CLEAR_DEPTH) {
pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil);
}
else if (clear_flags & PIPE_CLEAR_STENCIL) {
sr.ref_value[0] = stencil & 0xff;
pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil);
pipe->set_stencil_ref(pipe, &sr);
}
else
/* hmm that should be illegal probably, or make it a no-op somewhere */
pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
pipe->bind_rasterizer_state(pipe, ctx->rs_state);
pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0));
pipe->bind_vs_state(pipe, ctx->vs_col);
pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
/* set a framebuffer state */
fb_state.width = dstsurf->width;
fb_state.height = dstsurf->height;
fb_state.nr_cbufs = 0;
fb_state.cbufs[0] = 0;
fb_state.zsbuf = dstsurf;
pipe->set_framebuffer_state(pipe, &fb_state);
blitter_set_rectangle(ctx, 0, 0, width, height, dstsurf->width, dstsurf->height, depth);
blitter_draw_quad(ctx);
blitter_restore_CSOs(ctx);
}
+21 -10
View File
@@ -123,22 +123,33 @@ void util_blitter_copy_region(struct blitter_context *blitter,
boolean ignore_stencil);
/**
* Fill a region of a surface with a constant value.
*
* If the surface cannot be rendered to or it's a depth-stencil format,
* a software fallback path is taken.
* Clear a region of a (color) surface to a constant value.
*
* These states must be saved in the blitter in addition to the state objects
* already required to be saved:
* - framebuffer state
*/
void util_blitter_fill_region(struct blitter_context *blitter,
struct pipe_resource *dst,
struct pipe_subresource subdst,
unsigned dstx, unsigned dsty, unsigned dstz,
unsigned width, unsigned height,
unsigned value);
void util_blitter_clearRT(struct blitter_context *blitter,
struct pipe_surface *dst,
const float *rgba,
unsigned dstx, unsigned dsty,
unsigned width, unsigned height);
/**
* Clear a region of a depth-stencil surface, both stencil and depth
* or only one of them if this is a combined depth-stencil surface.
*
* These states must be saved in the blitter in addition to the state objects
* already required to be saved:
* - framebuffer state
*/
void util_blitter_clearDS(struct blitter_context *blitter,
struct pipe_surface *dst,
unsigned clear_flags,
double depth,
unsigned stencil,
unsigned dstx, unsigned dsty,
unsigned width, unsigned height);
/* The functions below should be used to save currently bound constant state
* objects inside a driver. The objects are automatically restored at the end
+8 -19
View File
@@ -31,9 +31,6 @@
#include "pipe/p_context.h"
#include "pipe/p_state.h"
#include "util/u_pack_color.h"
#include "util/u_rect.h"
#include "util/u_surface.h"
/**
@@ -46,25 +43,17 @@ util_clear(struct pipe_context *pipe,
const float *rgba, double depth, unsigned stencil)
{
if (buffers & PIPE_CLEAR_COLOR) {
struct pipe_surface *ps = framebuffer->cbufs[0];
struct pipe_subresource subdst;
union util_color uc;
subdst.face = ps->face;
subdst.level = ps->level;
util_pack_color(rgba, ps->format, &uc);
pipe->resource_fill_region(pipe, ps->texture, subdst, 0, 0, ps->zslice,
ps->width, ps->height, uc.ui);
unsigned i;
for (i = 0; i < framebuffer->nr_cbufs; i++) {
struct pipe_surface *ps = framebuffer->cbufs[i];
pipe->clearRT(pipe, ps, rgba, 0, 0, ps->width, ps->height);
}
}
if (buffers & PIPE_CLEAR_DEPTHSTENCIL) {
struct pipe_surface *ps = framebuffer->zsbuf;
struct pipe_subresource subdst;
subdst.face = ps->face;
subdst.level = ps->level;
pipe->resource_fill_region(pipe, ps->texture, subdst, 0, 0, ps->zslice,
ps->width, ps->height,
util_pack_z_stencil(ps->format, depth, stencil));
pipe->clearDS(pipe, ps, buffers & PIPE_CLEAR_DEPTHSTENCIL,
depth, stencil,
0, 0, ps->width, ps->height);
}
}
+32 -20
View File
@@ -40,6 +40,7 @@
#include "util/u_inlines.h"
#include "util/u_rect.h"
#include "util/u_surface.h"
#include "util/u_pack_color.h"
/**
@@ -195,26 +196,33 @@ util_resource_copy_region(struct pipe_context *pipe,
/**
* Fallback for pipe->resource_fill_region() function.
* Fallback for pipe->clearRT() function.
* XXX this looks too hackish to be really useful.
* cpp > 4 looks like a gross hack at best...
* and we're missing the equivalent clearDS fallback.
* Plus can't use these transfer fallbacks when clearing
* multisampled surfaces for instance.
*/
void
util_resource_fill_region(struct pipe_context *pipe,
struct pipe_resource *dst,
struct pipe_subresource subdst,
unsigned dstx, unsigned dsty, unsigned dstz,
unsigned width, unsigned height, unsigned value)
util_clearRT(struct pipe_context *pipe,
struct pipe_surface *dst,
const float *rgba,
unsigned dstx, unsigned dsty,
unsigned width, unsigned height)
{
struct pipe_transfer *dst_trans;
void *dst_map;
union util_color uc;
assert(dst);
if (!dst)
assert(dst->texture);
if (!dst->texture)
return;
util_pack_color(rgba, dst->texture->format, &uc);
dst_trans = pipe_get_transfer(pipe,
dst,
subdst.face,
subdst.level,
dstz,
dst->texture,
dst->face,
dst->level,
dst->zslice,
PIPE_TRANSFER_WRITE,
dstx, dsty, width, height);
@@ -225,22 +233,26 @@ util_resource_fill_region(struct pipe_context *pipe,
if (dst_map) {
assert(dst_trans->stride > 0);
switch (util_format_get_blocksize(dst->format)) {
switch (util_format_get_blocksize(dst->texture->format)) {
case 1:
case 2:
case 4:
util_fill_rect(dst_map, dst->format,
dst_trans->stride,
0, 0, width, height, value);
util_pack_color(rgba, dst->texture->format, &uc);
util_fill_rect(dst_map, dst->texture->format,
dst_trans->stride,
0, 0, width, height, uc.ui);
break;
case 8:
{
/* expand the 4-byte clear value to an 8-byte value */
/* should probably not convert back from ubyte but not
sure what this code really achieved since it doesn't even
check for format type... */
ushort *row = (ushort *) dst_map;
ushort val0 = UBYTE_TO_USHORT((value >> 0) & 0xff);
ushort val1 = UBYTE_TO_USHORT((value >> 8) & 0xff);
ushort val2 = UBYTE_TO_USHORT((value >> 16) & 0xff);
ushort val3 = UBYTE_TO_USHORT((value >> 24) & 0xff);
ushort val0 = UBYTE_TO_USHORT((uc.ui >> 0) & 0xff);
ushort val1 = UBYTE_TO_USHORT((uc.ui >> 8) & 0xff);
ushort val2 = UBYTE_TO_USHORT((uc.ui >> 16) & 0xff);
ushort val3 = UBYTE_TO_USHORT((uc.ui >> 24) & 0xff);
unsigned i, j;
val0 = (val0 << 8) | val0;
val1 = (val1 << 8) | val1;
+5 -5
View File
@@ -57,11 +57,11 @@ util_resource_copy_region(struct pipe_context *pipe,
unsigned w, unsigned h);
extern void
util_resource_fill_region(struct pipe_context *pipe,
struct pipe_resource *dst,
struct pipe_subresource subdst,
unsigned dstx, unsigned dsty, unsigned dstz,
unsigned width, unsigned height, unsigned value);
util_clearRT(struct pipe_context *pipe,
struct pipe_surface *dst,
const float *rgba,
unsigned dstx, unsigned dsty,
unsigned width, unsigned height);