X-Git-Url: https://git.libre-soc.org/?p=mesa.git;a=blobdiff_plain;f=src%2Fmesa%2Fstate_tracker%2Fst_cb_texture.c;h=a2d7aa6a6d3ce1dbf4973756ffa4724bf37de52b;hp=df5f16efd629ecddf5890c3e4e951c12e83355ae;hb=a0f84396913d478c926626593514de1ab6ebb439;hpb=1bdd342b60cf4426bfa29030032f23f1e4c80fb6 diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c index df5f16efd62..a2d7aa6a6d3 100644 --- a/src/mesa/state_tracker/st_cb_texture.c +++ b/src/mesa/state_tracker/st_cb_texture.c @@ -34,7 +34,7 @@ #include "main/format_utils.h" #include "main/glformats.h" #include "main/image.h" -#include "main/imports.h" + #include "main/macros.h" #include "main/mipmap.h" #include "main/pack.h" @@ -195,6 +195,22 @@ st_DeleteTextureObject(struct gl_context *ctx, _mesa_delete_texture_object(ctx, texObj); } +/** + * Called via ctx->Driver.TextureRemovedFromShared() + * When texture is removed from ctx->Shared->TexObjects we lose + * the ability to clean up views on context destruction, which may + * lead to dangling pointers to destroyed contexts. + * Release the views to prevent this. + */ +static void +st_TextureReleaseAllSamplerViews(struct gl_context *ctx, + struct gl_texture_object *texObj) +{ + struct st_context *st = st_context(ctx); + struct st_texture_object *stObj = st_texture_object(texObj); + + st_texture_release_all_sampler_views(st, stObj); +} /** called via ctx->Driver.FreeTextureImageBuffer() */ static void @@ -215,7 +231,9 @@ st_FreeTextureImageBuffer(struct gl_context *ctx, stImage->transfer = NULL; stImage->num_transfers = 0; - if (stImage->compressed_data) { + if (stImage->compressed_data && + pipe_reference(&stImage->compressed_data->reference, NULL)) { + free(stImage->compressed_data->ptr); free(stImage->compressed_data); stImage->compressed_data = NULL; } @@ -226,6 +244,18 @@ st_FreeTextureImageBuffer(struct gl_context *ctx, st_texture_release_all_sampler_views(st, stObj); } +bool +st_astc_format_fallback(const struct st_context *st, mesa_format format) +{ + if (!_mesa_is_format_astc_2d(format)) + return false; + + if (format == MESA_FORMAT_RGBA_ASTC_5x5 || + format == MESA_FORMAT_SRGB8_ALPHA8_ASTC_5x5) + return !st->has_astc_5x5_ldr; + + return !st->has_astc_2d_ldr; +} bool st_compressed_format_fallback(struct st_context *st, mesa_format format) @@ -236,8 +266,8 @@ st_compressed_format_fallback(struct st_context *st, mesa_format format) if (_mesa_is_format_etc2(format)) return !st->has_etc2; - if (_mesa_is_format_astc_2d(format)) - return !st->has_astc_2d_ldr; + if (st_astc_format_fallback(st, format)) + return true; return false; } @@ -252,16 +282,21 @@ compressed_tex_fallback_allocate(struct st_context *st, if (!st_compressed_format_fallback(st, texImage->TexFormat)) return; - if (stImage->compressed_data) + if (stImage->compressed_data && + pipe_reference(&stImage->compressed_data->reference, NULL)) { + free(stImage->compressed_data->ptr); free(stImage->compressed_data); + } unsigned data_size = _mesa_format_image_size(texImage->TexFormat, texImage->Width2, texImage->Height2, texImage->Depth2); - stImage->compressed_data = + stImage->compressed_data = ST_CALLOC_STRUCT(st_compressed_data); + stImage->compressed_data->ptr = malloc(data_size * _mesa_num_tex_faces(texImage->TexObject->Target)); + pipe_reference_init(&stImage->compressed_data->reference, 1); } @@ -308,8 +343,9 @@ st_MapTextureImage(struct gl_context *ctx, _mesa_format_row_stride(texImage->TexFormat, texImage->Width2); unsigned block_size = _mesa_get_format_bytes(texImage->TexFormat); + assert(stImage->compressed_data); *mapOut = itransfer->temp_data = - stImage->compressed_data + + stImage->compressed_data->ptr + (z * y_blocks + (y / blk_h)) * stride + (x / blk_w) * block_size; itransfer->map = map; @@ -513,6 +549,17 @@ allocate_full_mipmap(const struct st_texture_object *stObj, if (stImage->base.Level > 0 || stObj->base.GenerateMipmap) return TRUE; + /* If the application has explicitly called glTextureParameter to set + * GL_TEXTURE_MAX_LEVEL, such that (max - base) > 0, then they're trying + * to communicate that they will have multiple miplevels. + * + * Core Mesa will initialize MaxLevel to value much larger than + * MAX_TEXTURE_LEVELS, so we check that to see if it's been set at all. + */ + if (stObj->base.MaxLevel < MAX_TEXTURE_LEVELS && + stObj->base.MaxLevel - stObj->base.BaseLevel > 0) + return TRUE; + if (stImage->base._BaseFormat == GL_DEPTH_COMPONENT || stImage->base._BaseFormat == GL_DEPTH_STENCIL_EXT) /* depth/stencil textures are seldom mipmapped */ @@ -662,7 +709,6 @@ st_AllocTextureImageBuffer(struct gl_context *ctx, struct st_context *st = st_context(ctx); struct st_texture_image *stImage = st_texture_image(texImage); struct st_texture_object *stObj = st_texture_object(texImage->TexObject); - const GLuint level = texImage->Level; GLuint width = texImage->Width; GLuint height = texImage->Height; GLuint depth = texImage->Depth; @@ -674,29 +720,34 @@ st_AllocTextureImageBuffer(struct gl_context *ctx, stObj->needs_validation = true; compressed_tex_fallback_allocate(st, stImage); + const bool allowAllocateToStObj = !stObj->pt || + stObj->pt->last_level == 0 || + texImage->Level == 0; - /* Look if the parent texture object has space for this image */ - if (stObj->pt && - level <= stObj->pt->last_level && - st_texture_match_image(st, stObj->pt, texImage)) { - /* this image will fit in the existing texture object's memory */ - pipe_resource_reference(&stImage->pt, stObj->pt); - return GL_TRUE; - } + if (allowAllocateToStObj) { + /* Look if the parent texture object has space for this image */ + if (stObj->pt && + st_texture_match_image(st, stObj->pt, texImage)) { + /* this image will fit in the existing texture object's memory */ + pipe_resource_reference(&stImage->pt, stObj->pt); + assert(stImage->pt); + return GL_TRUE; + } - /* The parent texture object does not have space for this image */ + /* The parent texture object does not have space for this image */ - pipe_resource_reference(&stObj->pt, NULL); - st_texture_release_all_sampler_views(st, stObj); + pipe_resource_reference(&stObj->pt, NULL); + st_texture_release_all_sampler_views(st, stObj); - if (!guess_and_alloc_texture(st, stObj, stImage)) { - /* Probably out of memory. - * Try flushing any pending rendering, then retry. - */ - st_finish(st); if (!guess_and_alloc_texture(st, stObj, stImage)) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); - return GL_FALSE; + /* Probably out of memory. + * Try flushing any pending rendering, then retry. + */ + st_finish(st); + if (!guess_and_alloc_texture(st, stObj, stImage)) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); + return GL_FALSE; + } } } @@ -1464,7 +1515,7 @@ st_TexSubImage(struct gl_context *ctx, GLuint dims, /* Try texture_subdata, which should be the fastest memcpy path. */ if (pixels && - !_mesa_is_bufferobj(unpack->BufferObj) && + !unpack->BufferObj && _mesa_texstore_can_use_memcpy(ctx, texImage->_BaseFormat, texImage->TexFormat, format, type, unpack)) { @@ -1488,7 +1539,7 @@ st_TexSubImage(struct gl_context *ctx, GLuint dims, } util_throttle_memory_usage(pipe, &st->throttle, - width * height * depth * + (uint64_t) width * height * depth * util_format_get_blocksize(dst->format)); u_box_3d(xoffset, yoffset, zoffset + dstz, width, height, depth, &box); @@ -1534,7 +1585,7 @@ st_TexSubImage(struct gl_context *ctx, GLuint dims, goto fallback; } - if (_mesa_is_bufferobj(unpack->BufferObj)) { + if (unpack->BufferObj) { if (try_pbo_upload(ctx, dims, texImage, format, type, dst_format, xoffset, yoffset, zoffset, width, height, depth, pixels, unpack)) @@ -1597,7 +1648,7 @@ st_TexSubImage(struct gl_context *ctx, GLuint dims, } util_throttle_memory_usage(pipe, &st->throttle, - width * height * depth * + (uint64_t) width * height * depth * util_format_get_blocksize(src_templ.format)); throttled = true; @@ -1693,7 +1744,7 @@ st_TexSubImage(struct gl_context *ctx, GLuint dims, fallback: if (!throttled) { util_throttle_memory_usage(pipe, &st->throttle, - width * height * depth * + (uint64_t) width * height * depth * _mesa_get_format_bytes(texImage->TexFormat)); } _mesa_store_texsubimage(ctx, dims, texImage, xoffset, yoffset, zoffset, @@ -1754,7 +1805,7 @@ st_CompressedTexSubImage(struct gl_context *ctx, GLuint dims, goto fallback; } - if (!_mesa_is_bufferobj(ctx->Unpack.BufferObj)) + if (!ctx->Unpack.BufferObj) goto fallback; if (st_compressed_format_fallback(st, texImage->TexFormat)) @@ -2212,8 +2263,8 @@ st_GetTexSubImage(struct gl_context * ctx, slice, 0, 0); /* get float[4] rgba row from surface */ - pipe_get_tile_rgba_format(tex_xfer, map, 0, 0, width, height, - dst_format, rgba); + pipe_get_tile_rgba(tex_xfer, map, 0, 0, width, height, dst_format, + rgba); _mesa_format_convert(dest, dstMesaFormat, dstStride, rgba, RGBA32_FLOAT, srcStride, @@ -2289,6 +2340,10 @@ fallback_copy_texsubimage(struct gl_context *ctx, PIPE_TRANSFER_READ, srcX, srcY, width, height, &src_trans); + if (!map) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage()"); + return; + } if ((baseFormat == GL_DEPTH_COMPONENT || baseFormat == GL_DEPTH_STENCIL) && @@ -2301,6 +2356,10 @@ fallback_copy_texsubimage(struct gl_context *ctx, destX, destY, slice, dst_width, dst_height, dst_depth, &transfer); + if (!texDest) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage()"); + goto err; + } if (baseFormat == GL_DEPTH_COMPONENT || baseFormat == GL_DEPTH_STENCIL) { @@ -2322,20 +2381,19 @@ fallback_copy_texsubimage(struct gl_context *ctx, data = malloc(width * sizeof(uint)); if (data) { + unsigned dst_stride = (stImage->pt->target == PIPE_TEXTURE_1D_ARRAY ? + transfer->layer_stride : transfer->stride); /* To avoid a large temp memory allocation, do copy row by row */ for (row = 0; row < height; row++, srcY += yStep) { - pipe_get_tile_z(src_trans, map, 0, srcY, width, 1, data); + util_format_unpack_z_32unorm(strb->texture->format, + data, (uint8_t *)map + src_trans->stride * srcY, + width); if (scaleOrBias) { _mesa_scale_and_bias_depth_uint(ctx, width, data); } - if (stImage->pt->target == PIPE_TEXTURE_1D_ARRAY) { - pipe_put_tile_z(transfer, texDest + row*transfer->layer_stride, - 0, 0, width, 1, data); - } - else { - pipe_put_tile_z(transfer, texDest, 0, row, width, 1, data); - } + util_format_pack_z_32unorm(stImage->pt->format, + texDest + row * dst_stride, data, width); } } else { @@ -2349,7 +2407,7 @@ fallback_copy_texsubimage(struct gl_context *ctx, GLfloat *tempSrc = malloc(width * height * 4 * sizeof(GLfloat)); - if (tempSrc && texDest) { + if (tempSrc) { const GLint dims = 2; GLint dstRowStride; struct gl_texture_image *texImage = &stImage->base; @@ -2370,9 +2428,9 @@ fallback_copy_texsubimage(struct gl_context *ctx, /* XXX this usually involves a lot of int/float conversion. * try to avoid that someday. */ - pipe_get_tile_rgba_format(src_trans, map, 0, 0, width, height, - util_format_linear(strb->texture->format), - tempSrc); + pipe_get_tile_rgba(src_trans, map, 0, 0, width, height, + util_format_linear(strb->texture->format), + tempSrc); /* Store into texture memory. * Note that this does some special things such as pixel transfer @@ -2397,6 +2455,7 @@ fallback_copy_texsubimage(struct gl_context *ctx, } st_texture_image_unmap(st, stImage, slice); +err: pipe->transfer_unmap(pipe, src_trans); } @@ -3034,7 +3093,7 @@ st_TestProxyTexImage(struct gl_context *ctx, GLenum target, } else { /* assume a full set of mipmaps */ - pt.last_level = _mesa_logbase2(MAX3(width, height, depth)); + pt.last_level = util_logbase2(MAX3(width, height, depth)); } return pipe->screen->can_create_resource(pipe->screen, &pt); @@ -3069,7 +3128,15 @@ st_TextureView(struct gl_context *ctx, for (face = 0; face < numFaces; face++) { struct st_texture_image *stImage = st_texture_image(texObj->Image[face][level]); + struct st_texture_image *origImage = + st_texture_image(origTexObj->Image[face][level]); pipe_resource_reference(&stImage->pt, tex->pt); + if (origImage && + origImage->compressed_data) { + pipe_reference(NULL, + &origImage->compressed_data->reference); + stImage->compressed_data = origImage->compressed_data; + } } } @@ -3324,6 +3391,7 @@ st_init_texture_functions(struct dd_function_table *functions) functions->NewTextureImage = st_NewTextureImage; functions->DeleteTextureImage = st_DeleteTextureImage; functions->DeleteTexture = st_DeleteTextureObject; + functions->TextureRemovedFromShared = st_TextureReleaseAllSamplerViews; functions->AllocTextureImageBuffer = st_AllocTextureImageBuffer; functions->FreeTextureImageBuffer = st_FreeTextureImageBuffer; functions->MapTextureImage = st_MapTextureImage;