aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/mesa/state_tracker/st_cb_drawpixels.c')
-rw-r--r--mesalib/src/mesa/state_tracker/st_cb_drawpixels.c281
1 files changed, 150 insertions, 131 deletions
diff --git a/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c b/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c
index 68359e803..0200a6270 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c
@@ -460,12 +460,12 @@ internal_format(struct gl_context *ctx, GLenum format, GLenum type)
*/
static struct pipe_resource *
alloc_texture(struct st_context *st, GLsizei width, GLsizei height,
- enum pipe_format texFormat)
+ enum pipe_format texFormat, unsigned bind)
{
struct pipe_resource *pt;
pt = st_texture_create(st, st->internal_target, texFormat, 0,
- width, height, 1, 1, 0, PIPE_BIND_SAMPLER_VIEW);
+ width, height, 1, 1, 0, bind);
return pt;
}
@@ -515,7 +515,7 @@ make_texture(struct st_context *st,
return NULL;
/* alloc temporary texture */
- pt = alloc_texture(st, width, height, pipeFormat);
+ pt = alloc_texture(st, width, height, pipeFormat, PIPE_BIND_SAMPLER_VIEW);
if (!pt) {
_mesa_unmap_pbo_source(ctx, unpack);
return NULL;
@@ -1308,29 +1308,38 @@ st_get_color_read_renderbuffer(struct gl_context *ctx)
}
-/** Do the src/dest regions overlap? */
-static GLboolean
-regions_overlap(GLint srcX, GLint srcY, GLint dstX, GLint dstY,
- GLsizei width, GLsizei height)
+/**
+ * \return TRUE if two regions overlap, FALSE otherwise
+ */
+static boolean
+regions_overlap(int srcX0, int srcY0,
+ int srcX1, int srcY1,
+ int dstX0, int dstY0,
+ int dstX1, int dstY1)
{
- if (srcX + width <= dstX ||
- dstX + width <= srcX ||
- srcY + height <= dstY ||
- dstY + height <= srcY)
- return GL_FALSE;
- else
- return GL_TRUE;
+ if (MAX2(srcX0, srcX1) < MIN2(dstX0, dstX1))
+ return FALSE; /* src completely left of dst */
+
+ if (MAX2(dstX0, dstX1) < MIN2(srcX0, srcX1))
+ return FALSE; /* dst completely left of src */
+
+ if (MAX2(srcY0, srcY1) < MIN2(dstY0, dstY1))
+ return FALSE; /* src completely above dst */
+
+ if (MAX2(dstY0, dstY1) < MIN2(srcY0, srcY1))
+ return FALSE; /* dst completely above src */
+
+ return TRUE; /* some overlap */
}
/**
* Try to do a glCopyPixels for simple cases with a blit by calling
- * pipe->resource_copy_region().
+ * pipe->blit().
*
* We can do this when we're copying color pixels (depth/stencil
* eventually) with no pixel zoom, no pixel transfer ops, no
- * per-fragment ops, the src/dest regions don't overlap and the
- * src/dest pixel formats are the same.
+ * per-fragment ops, and the src/dest regions don't overlap.
*/
static GLboolean
blit_copy_pixels(struct gl_context *ctx, GLint srcx, GLint srcy,
@@ -1339,8 +1348,9 @@ blit_copy_pixels(struct gl_context *ctx, GLint srcx, GLint srcy,
{
struct st_context *st = st_context(ctx);
struct pipe_context *pipe = st->pipe;
+ struct pipe_screen *screen = pipe->screen;
struct gl_pixelstore_attrib pack, unpack;
- GLint readX, readY, readW, readH;
+ GLint readX, readY, readW, readH, drawX, drawY, drawW, drawH;
if (type == GL_COLOR &&
ctx->Pixel.ZoomX == 1.0 &&
@@ -1354,11 +1364,10 @@ blit_copy_pixels(struct gl_context *ctx, GLint srcx, GLint srcy,
!ctx->FragmentProgram.Enabled &&
!ctx->VertexProgram.Enabled &&
!ctx->Shader.CurrentFragmentProgram &&
- st_fb_orientation(ctx->ReadBuffer) == st_fb_orientation(ctx->DrawBuffer) &&
ctx->DrawBuffer->_NumColorDrawBuffers == 1 &&
- !ctx->Query.CondRenderQuery) {
+ !ctx->Query.CondRenderQuery &&
+ !ctx->Query.CurrentOcclusionObject) {
struct st_renderbuffer *rbRead, *rbDraw;
- GLint drawX, drawY;
/*
* Clip the read region against the src buffer bounds.
@@ -1385,29 +1394,65 @@ blit_copy_pixels(struct gl_context *ctx, GLint srcx, GLint srcy,
readX = readX - pack.SkipPixels + unpack.SkipPixels;
readY = readY - pack.SkipRows + unpack.SkipRows;
+ drawW = readW;
+ drawH = readH;
+
rbRead = st_get_color_read_renderbuffer(ctx);
rbDraw = st_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0]);
- if ((rbRead != rbDraw ||
- !regions_overlap(readX, readY, drawX, drawY, readW, readH)) &&
- rbRead->Base.Format == rbDraw->Base.Format) {
- struct pipe_box srcBox;
-
- /* flip src/dst position if needed */
- if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
- /* both buffers will have the same orientation */
- readY = ctx->ReadBuffer->Height - readY - readH;
- drawY = ctx->DrawBuffer->Height - drawY - readH;
- }
+ /* Flip src/dst position depending on the orientation of buffers. */
+ if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
+ readY = rbRead->Base.Height - readY;
+ readH = -readH;
+ }
- u_box_2d(readX, readY, readW, readH, &srcBox);
+ if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
+ /* We can't flip the destination for pipe->blit, so we only adjust
+ * its position and flip the source.
+ */
+ drawY = rbDraw->Base.Height - drawY - drawH;
+ readY += readH;
+ readH = -readH;
+ }
- pipe->resource_copy_region(pipe,
- rbDraw->texture,
- rbDraw->rtt_level, drawX, drawY, 0,
- rbRead->texture,
- rbRead->rtt_level, &srcBox);
- return GL_TRUE;
+ if (rbRead != rbDraw ||
+ !regions_overlap(readX, readY, readX + readW, readY + readH,
+ drawX, drawY, drawX + drawW, drawY + drawH)) {
+ struct pipe_blit_info blit;
+
+ memset(&blit, 0, sizeof(blit));
+ blit.src.resource = rbRead->texture;
+ blit.src.level = rbRead->rtt_level;
+ blit.src.format = rbRead->texture->format;
+ blit.src.box.x = readX;
+ blit.src.box.y = readY;
+ blit.src.box.z = rbRead->rtt_face + rbRead->rtt_slice;
+ blit.src.box.width = readW;
+ blit.src.box.height = readH;
+ blit.src.box.depth = 1;
+ blit.dst.resource = rbDraw->texture;
+ blit.dst.level = rbDraw->rtt_level;
+ blit.dst.format = rbDraw->texture->format;
+ blit.dst.box.x = drawX;
+ blit.dst.box.y = drawY;
+ blit.dst.box.z = rbDraw->rtt_face + rbDraw->rtt_slice;
+ blit.dst.box.width = drawW;
+ blit.dst.box.height = drawH;
+ blit.dst.box.depth = 1;
+ blit.mask = PIPE_MASK_RGBA;
+ blit.filter = PIPE_TEX_FILTER_NEAREST;
+
+ if (screen->is_format_supported(screen, blit.src.format,
+ blit.src.resource->target,
+ blit.src.resource->nr_samples,
+ PIPE_BIND_SAMPLER_VIEW) &&
+ screen->is_format_supported(screen, blit.dst.format,
+ blit.dst.resource->target,
+ blit.dst.resource->nr_samples,
+ PIPE_BIND_RENDER_TARGET)) {
+ pipe->blit(pipe, &blit);
+ return GL_TRUE;
+ }
}
}
@@ -1429,10 +1474,10 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
struct pipe_sampler_view *sv[2];
int num_sampler_view = 1;
GLfloat *color;
- enum pipe_format srcFormat, texFormat;
+ enum pipe_format srcFormat;
+ unsigned srcBind;
GLboolean invertTex = GL_FALSE;
GLint readX, readY, readW, readH;
- GLuint sample_count;
struct gl_pixelstore_attrib pack = ctx->DefaultPacking;
struct st_fp_variant *fpv;
@@ -1494,35 +1539,46 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
/* update fragment program constants */
st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT);
- sample_count = rbRead->texture->nr_samples;
- /* I believe this would be legal, presumably would need to do a resolve
- for color, and for depth/stencil spec says to just use one of the
- depth/stencil samples per pixel? Need some transfer clarifications. */
- assert(sample_count < 2);
-
+ /* Choose the format for the temporary texture. */
srcFormat = rbRead->texture->format;
+ srcBind = PIPE_BIND_SAMPLER_VIEW |
+ (type == GL_COLOR ? PIPE_BIND_RENDER_TARGET : PIPE_BIND_DEPTH_STENCIL);
- if (screen->is_format_supported(screen, srcFormat, st->internal_target,
- sample_count,
- PIPE_BIND_SAMPLER_VIEW)) {
- texFormat = srcFormat;
- }
- else {
- /* srcFormat can't be used as a texture format */
+ if (!screen->is_format_supported(screen, srcFormat, st->internal_target, 0,
+ srcBind)) {
if (type == GL_DEPTH) {
- texFormat = st_choose_format(st, GL_DEPTH_COMPONENT,
- GL_NONE, GL_NONE, st->internal_target,
- sample_count, PIPE_BIND_DEPTH_STENCIL,
- FALSE);
- assert(texFormat != PIPE_FORMAT_NONE);
+ srcFormat = st_choose_format(st, GL_DEPTH_COMPONENT, GL_NONE,
+ GL_NONE, st->internal_target, 0,
+ srcBind, FALSE);
}
else {
- /* default color format */
- texFormat = st_choose_format(st, GL_RGBA,
- GL_NONE, GL_NONE, st->internal_target,
- sample_count, PIPE_BIND_SAMPLER_VIEW,
- FALSE);
- assert(texFormat != PIPE_FORMAT_NONE);
+ assert(type == GL_COLOR);
+
+ if (util_format_is_float(srcFormat)) {
+ srcFormat = st_choose_format(st, GL_RGBA32F, GL_NONE,
+ GL_NONE, st->internal_target, 0,
+ srcBind, FALSE);
+ }
+ else if (util_format_is_pure_sint(srcFormat)) {
+ srcFormat = st_choose_format(st, GL_RGBA32I, GL_NONE,
+ GL_NONE, st->internal_target, 0,
+ srcBind, FALSE);
+ }
+ else if (util_format_is_pure_uint(srcFormat)) {
+ srcFormat = st_choose_format(st, GL_RGBA32UI, GL_NONE,
+ GL_NONE, st->internal_target, 0,
+ srcBind, FALSE);
+ }
+ else {
+ srcFormat = st_choose_format(st, GL_RGBA, GL_NONE,
+ GL_NONE, st->internal_target, 0,
+ srcBind, FALSE);
+ }
+ }
+
+ if (srcFormat == PIPE_FORMAT_NONE) {
+ assert(0 && "cannot choose a format for src of CopyPixels");
+ return;
}
}
@@ -1554,8 +1610,8 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
readW = MAX2(0, readW);
readH = MAX2(0, readH);
- /* alloc temporary texture */
- pt = alloc_texture(st, width, height, texFormat);
+ /* Allocate the temporary texture. */
+ pt = alloc_texture(st, width, height, srcFormat, srcBind);
if (!pt)
return;
@@ -1565,70 +1621,33 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
return;
}
- /* Make temporary texture which is a copy of the src region.
- */
- if (srcFormat == texFormat) {
- struct pipe_box src_box;
- u_box_2d(readX, readY, readW, readH, &src_box);
- /* copy source framebuffer surface into mipmap/texture */
- pipe->resource_copy_region(pipe,
- pt, /* dest tex */
- 0, /* dest lvl */
- pack.SkipPixels, pack.SkipRows, 0, /* dest pos */
- rbRead->texture, /* src tex */
- rbRead->rtt_level, /* src lvl */
- &src_box);
-
- }
- else {
- /* CPU-based fallback/conversion */
- struct pipe_transfer *ptRead;
- void *mapRead =
- pipe_transfer_map(st->pipe, rbRead->texture,
- rbRead->rtt_level,
- rbRead->rtt_face + rbRead->rtt_slice,
- PIPE_TRANSFER_READ,
- readX, readY, readW, readH, &ptRead);
- struct pipe_transfer *ptTex;
- void *mapTex;
- enum pipe_transfer_usage transfer_usage;
-
- if (ST_DEBUG & DEBUG_FALLBACK)
- debug_printf("%s: fallback processing\n", __FUNCTION__);
-
- if (type == GL_DEPTH && util_format_is_depth_and_stencil(pt->format))
- transfer_usage = PIPE_TRANSFER_READ_WRITE;
- else
- transfer_usage = PIPE_TRANSFER_WRITE;
-
- mapTex = pipe_transfer_map(st->pipe, pt, 0, 0, transfer_usage,
- 0, 0, width, height, &ptTex);
-
- /* copy image from ptRead surface to ptTex surface */
- if (type == GL_COLOR) {
- /* alternate path using get/put_tile() */
- GLfloat *buf = malloc(width * height * 4 * sizeof(GLfloat));
- enum pipe_format readFormat, drawFormat;
- readFormat = util_format_linear(rbRead->texture->format);
- drawFormat = util_format_linear(pt->format);
- pipe_get_tile_rgba_format(ptRead, mapRead, 0, 0, readW, readH,
- readFormat, buf);
- pipe_put_tile_rgba_format(ptTex, mapTex, pack.SkipPixels,
- pack.SkipRows,
- readW, readH, drawFormat, buf);
- free(buf);
- }
- else {
- /* GL_DEPTH */
- GLuint *buf = malloc(width * height * sizeof(GLuint));
- pipe_get_tile_z(ptRead, mapRead, 0, 0, readW, readH, buf);
- pipe_put_tile_z(ptTex, mapTex, pack.SkipPixels, pack.SkipRows,
- readW, readH, buf);
- free(buf);
- }
-
- pipe->transfer_unmap(pipe, ptRead);
- pipe->transfer_unmap(pipe, ptTex);
+ /* Copy the src region to the temporary texture. */
+ {
+ struct pipe_blit_info blit;
+
+ memset(&blit, 0, sizeof(blit));
+ blit.src.resource = rbRead->texture;
+ blit.src.level = rbRead->rtt_level;
+ blit.src.format = rbRead->texture->format;
+ blit.src.box.x = readX;
+ blit.src.box.y = readY;
+ blit.src.box.z = rbRead->rtt_face + rbRead->rtt_slice;
+ blit.src.box.width = readW;
+ blit.src.box.height = readH;
+ blit.src.box.depth = 1;
+ blit.dst.resource = pt;
+ blit.dst.level = 0;
+ blit.dst.format = pt->format;
+ blit.dst.box.x = pack.SkipPixels;
+ blit.dst.box.y = pack.SkipRows;
+ blit.dst.box.z = 0;
+ blit.dst.box.width = readW;
+ blit.dst.box.height = readH;
+ blit.dst.box.depth = 1;
+ blit.mask = util_format_get_mask(pt->format) & ~PIPE_MASK_S;
+ blit.filter = PIPE_TEX_FILTER_NEAREST;
+
+ pipe->blit(pipe, &blit);
}
/* OK, the texture 'pt' contains the src image/pixels. Now draw a