st/mesa: Do GL_RGBA->GL_RGB texsubimage on hardware

State tracker currently backs GL_RGB textures with RGBA almost always.
This means we need to maintain A==1 in these textures to give correct GL_RGB
sampling results.

This change offloads the RGBA->RGB copy to hardware using the new writemask
version of u_blit_pixels.

More src/dstLogical/dstActual triples could be shifted to hardware by
this technique in future patches.
This commit is contained in:
Keith Whitwell
2009-09-02 18:30:11 +01:00
committed by Brian Paul
parent 862724d3c2
commit 8fc945cd84

View File

@@ -56,6 +56,7 @@
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "pipe/p_inlines.h"
#include "pipe/p_shader_tokens.h"
#include "util/u_tile.h"
#include "util/u_blit.h"
#include "util/u_surface.h"
@@ -1393,6 +1394,36 @@ fallback_copy_texsubimage(GLcontext *ctx, GLenum target, GLint level,
}
static unsigned
compatible_src_dst_formats(const struct gl_renderbuffer *src,
const struct gl_texture_image *dst)
{
const GLenum srcFormat = src->_BaseFormat;
const GLenum dstLogicalFormat = dst->_BaseFormat;
if (srcFormat == dstLogicalFormat) {
/* This is the same as matching_base_formats, which should
* always pass, as it did previously.
*/
return TGSI_WRITEMASK_XYZW;
}
else if (srcFormat == GL_RGBA &&
dstLogicalFormat == GL_RGB) {
/* Add a single special case to cope with RGBA->RGB transfers,
* setting A to 1.0 to cope with situations where the RGB
* destination is actually stored as RGBA.
*/
return TGSI_WRITEMASK_XYZ; /* A ==> 1.0 */
}
else {
/* Otherwise fail.
*/
return 0;
}
}
/**
* Do a CopyTex[Sub]Image1/2/3D() using a hardware (blit) path if possible.
* Note that the region to copy has already been clipped so we know we
@@ -1422,6 +1453,9 @@ st_copy_texsubimage(GLcontext *ctx,
enum pipe_format dest_format, src_format;
GLboolean use_fallback = GL_TRUE;
GLboolean matching_base_formats;
GLuint format_writemask;
struct pipe_surface *dest_surface = NULL;
GLboolean do_flip = (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP);
/* any rendering in progress must flushed before we grab the fb image */
st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
@@ -1492,13 +1526,14 @@ st_copy_texsubimage(GLcontext *ctx,
* textured-quad paths.
*/
matching_base_formats = (strb->Base._BaseFormat == texImage->_BaseFormat);
format_writemask = compatible_src_dst_formats(&strb->Base, texImage);
if (matching_base_formats && ctx->_ImageTransferState == 0x0) {
/* try potential hardware path */
struct pipe_surface *dest_surface = NULL;
boolean do_flip = (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP);
if (ctx->_ImageTransferState == 0x0) {
if (src_format == dest_format && !do_flip) {
if (matching_base_formats &&
src_format == dest_format &&
!do_flip)
{
/* use surface_copy() / blit */
dest_surface = screen->get_tex_surface(screen, stImage->pt,
@@ -1518,7 +1553,8 @@ st_copy_texsubimage(GLcontext *ctx,
width, height);
use_fallback = GL_FALSE;
}
else if (screen->is_format_supported(screen, src_format,
else if (format_writemask &&
screen->is_format_supported(screen, src_format,
PIPE_TEXTURE_2D,
PIPE_TEXTURE_USAGE_SAMPLER,
0) &&
@@ -1542,14 +1578,15 @@ st_copy_texsubimage(GLcontext *ctx,
srcY0 = srcY;
srcY1 = srcY0 + height;
}
util_blit_pixels(ctx->st->blit,
strb->surface,
srcX, srcY0,
srcX + width, srcY1,
dest_surface,
destX, destY,
destX + width, destY + height,
0.0, PIPE_TEX_MIPFILTER_NEAREST);
util_blit_pixels_writemask(ctx->st->blit,
strb->surface,
srcX, srcY0,
srcX + width, srcY1,
dest_surface,
destX, destY,
destX + width, destY + height,
0.0, PIPE_TEX_MIPFILTER_NEAREST,
format_writemask);
use_fallback = GL_FALSE;
}