st: If the hw supports it do hw conversion of texture uploads

This commit is contained in:
Jakob Bornecrantz 2009-04-08 23:29:18 +02:00
parent cafea75280
commit 55ed2a7365

View file

@ -110,6 +110,25 @@ compressed_num_bytes(GLuint mesaFormat)
}
static GLboolean
is_compressed_mesa_format(const struct gl_texture_format *format)
{
switch (format->MesaFormat) {
case MESA_FORMAT_RGB_DXT1:
case MESA_FORMAT_RGBA_DXT1:
case MESA_FORMAT_RGBA_DXT3:
case MESA_FORMAT_RGBA_DXT5:
case MESA_FORMAT_SRGB_DXT1:
case MESA_FORMAT_SRGBA_DXT1:
case MESA_FORMAT_SRGBA_DXT3:
case MESA_FORMAT_SRGBA_DXT5:
return GL_TRUE;
default:
return GL_FALSE;
}
}
/** called via ctx->Driver.NewTextureImage() */
static struct gl_texture_image *
st_NewTextureImage(GLcontext * ctx)
@ -378,6 +397,110 @@ strip_texture_border(GLint border,
}
/**
* Try to do texture compression via rendering. If the Gallium driver
* can render into a compressed surface this will allow us to do texture
* compression.
* \return GL_TRUE for success, GL_FALSE for failure
*/
static GLboolean
compress_with_blit(GLcontext * ctx,
GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLint width, GLint height, GLint depth,
GLenum format, GLenum type, const void *pixels,
const struct gl_pixelstore_attrib *unpack,
struct gl_texture_image *texImage)
{
const GLuint dstImageOffsets[1] = {0};
struct st_texture_image *stImage = st_texture_image(texImage);
struct pipe_screen *screen = ctx->st->pipe->screen;
const GLuint face = _mesa_tex_target_to_face(target);
const struct gl_texture_format *mesa_format;
struct pipe_texture templ;
struct pipe_texture *src_tex;
struct pipe_surface *dst_surface;
struct pipe_transfer *tex_xfer;
void *map;
if (!stImage->pt) {
/* XXX: Can this happen? Should we assert? */
return GL_FALSE;
}
/* get destination surface (in the compressed texture) */
dst_surface = screen->get_tex_surface(screen, stImage->pt,
stImage->face, stImage->level, 0,
PIPE_BUFFER_USAGE_GPU_WRITE);
if (!dst_surface) {
/* can't render into this format (or other problem) */
return GL_FALSE;
}
/* Choose format for the temporary RGBA texture image.
*/
mesa_format = st_ChooseTextureFormat(ctx, GL_RGBA, format, type);
assert(mesa_format);
if (!mesa_format)
return GL_FALSE;
/* Create the temporary source texture
*/
memset(&templ, 0, sizeof(templ));
templ.target = PIPE_TEXTURE_2D;
templ.format = st_mesa_format_to_pipe_format(mesa_format->MesaFormat);
pf_get_block(templ.format, &templ.block);
templ.width[0] = width;
templ.height[0] = height;
templ.depth[0] = 1;
templ.last_level = 0;
templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER;
src_tex = screen->texture_create(screen, &templ);
if (!src_tex)
return GL_FALSE;
/* Put user's tex data into the temporary texture
*/
tex_xfer = screen->get_tex_transfer(screen, src_tex,
face, level, 0,
PIPE_TRANSFER_WRITE,
0, 0, width, height); /* x, y, w, h */
map = screen->transfer_map(screen, tex_xfer);
mesa_format->StoreImage(ctx, 2, GL_RGBA, mesa_format,
map, /* dest ptr */
0, 0, 0, /* dest x/y/z offset */
tex_xfer->stride, /* dest row stride (bytes) */
dstImageOffsets, /* image offsets (for 3D only) */
width, height, 1, /* size */
format, type, /* source format/type */
pixels, /* source data */
unpack); /* source data packing */
screen->transfer_unmap(screen, tex_xfer);
screen->tex_transfer_destroy(tex_xfer);
/* copy / compress image */
util_blit_pixels_tex(ctx->st->blit,
src_tex, /* pipe_texture (src) */
0, 0, /* src x0, y0 */
width, height, /* src x1, y1 */
dst_surface, /* pipe_surface (dst) */
xoffset, yoffset, /* dst x0, y0 */
xoffset + width, /* dst x1 */
yoffset + height, /* dst y1 */
0.0, /* z */
PIPE_TEX_MIPFILTER_NEAREST);
pipe_surface_reference(&dst_surface, NULL);
pipe_texture_reference(&src_tex, NULL);
return GL_TRUE;
}
/**
* Do glTexImage1/2/3D().
*/
@ -392,8 +515,9 @@ st_TexImage(GLcontext * ctx,
const struct gl_pixelstore_attrib *unpack,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage,
GLsizei imageSize, GLboolean compressed)
GLsizei imageSize, GLboolean compressed_src)
{
struct pipe_screen *screen = ctx->st->pipe->screen;
struct st_texture_object *stObj = st_texture_object(texObj);
struct st_texture_image *stImage = st_texture_image(texImage);
GLint postConvWidth, postConvHeight;
@ -522,7 +646,7 @@ st_TexImage(GLcontext * ctx,
* the expectation that the texture will be set up but nothing
* more will be done. This is where those calls return:
*/
if (compressed) {
if (compressed_src) {
pixels = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, pixels,
unpack,
"glCompressedTexImage");
@ -535,6 +659,21 @@ st_TexImage(GLcontext * ctx,
if (!pixels)
return;
/* See if we can do texture compression with a blit/render.
*/
if (!compressed_src &&
!ctx->Mesa_DXTn &&
is_compressed_mesa_format(texImage->TexFormat) &&
screen->is_format_supported(screen,
stImage->pt->format,
stImage->pt->target,
PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) {
if (compress_with_blit(ctx, target, level, 0, 0, 0, width, height, depth,
format, type, pixels, unpack, texImage)) {
return;
}
}
if (stImage->pt) {
texImage->Data = st_texture_image_map(ctx->st, stImage, 0,
PIPE_TRANSFER_WRITE, 0, 0,
@ -570,7 +709,7 @@ st_TexImage(GLcontext * ctx,
* the blitter to copy. Or, use the hardware to do the format
* conversion and copy:
*/
if (compressed) {
if (compressed_src) {
memcpy(texImage->Data, pixels, imageSize);
}
else {
@ -607,7 +746,7 @@ st_TexImage(GLcontext * ctx,
_mesa_unmap_teximage_pbo(ctx, unpack);
if (stImage->pt) {
if (stImage->pt && texImage->Data) {
st_texture_image_unmap(ctx->st, stImage);
texImage->Data = NULL;
}
@ -787,6 +926,7 @@ st_TexSubimage(GLcontext *ctx, GLint dims, GLenum target, GLint level,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
struct pipe_screen *screen = ctx->st->pipe->screen;
struct st_texture_image *stImage = st_texture_image(texImage);
GLuint dstRowStride;
const GLuint srcImageStride =
@ -804,6 +944,22 @@ st_TexSubimage(GLcontext *ctx, GLint dims, GLenum target, GLint level,
if (!pixels)
return;
/* See if we can do texture compression with a blit/render.
*/
if (!ctx->Mesa_DXTn &&
is_compressed_mesa_format(texImage->TexFormat) &&
screen->is_format_supported(screen,
stImage->pt->format,
stImage->pt->target,
PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) {
if (compress_with_blit(ctx, target, level,
xoffset, yoffset, zoffset,
width, height, depth,
format, type, pixels, packing, texImage)) {
return;
}
}
/* Map buffer if necessary. Need to lock to prevent other contexts
* from uploading the buffer under us.
*/