mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-25 02:10:11 +01:00
st: If the hw supports it do hw conversion of texture uploads
This commit is contained in:
parent
cafea75280
commit
55ed2a7365
1 changed files with 160 additions and 4 deletions
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue