diff options
Diffstat (limited to 'mesalib/src/mesa/state_tracker/st_cb_drawpixels.c')
-rw-r--r-- | mesalib/src/mesa/state_tracker/st_cb_drawpixels.c | 281 |
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 |