diff options
Diffstat (limited to 'mesalib/src/mesa/state_tracker/st_cb_texture.c')
-rw-r--r-- | mesalib/src/mesa/state_tracker/st_cb_texture.c | 102 |
1 files changed, 92 insertions, 10 deletions
diff --git a/mesalib/src/mesa/state_tracker/st_cb_texture.c b/mesalib/src/mesa/state_tracker/st_cb_texture.c index 260df09f5..76bf78bbf 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_texture.c +++ b/mesalib/src/mesa/state_tracker/st_cb_texture.c @@ -460,6 +460,91 @@ guess_and_alloc_texture(struct st_context *st, /** + * Called via ctx->Driver.AllocTextureImageBuffer(). + * If the texture object/buffer already has space for the indicated image, + * we're done. Otherwise, allocate memory for the new texture image. + * XXX This function and st_TexImage() have some duplicated code. That + * can be cleaned up in the future. + */ +static GLboolean +st_AllocTextureImageBuffer(struct gl_context *ctx, + struct gl_texture_image *texImage, + gl_format format, GLsizei width, + GLsizei height, GLsizei depth) +{ + 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; + + DBG("%s\n", __FUNCTION__); + + assert(width > 0); + assert(height > 0); + assert(depth > 0); + assert(!texImage->Data); + assert(!stImage->pt); /* xxx this might be wrong */ + + /* Look if the parent texture object has space for this image */ + if (stObj->pt && + level <= stObj->pt->last_level && + st_texture_match_image(stObj->pt, texImage)) { + /* this image will fit in the existing texture object's memory */ + pipe_resource_reference(&stImage->pt, stObj->pt); + return GL_TRUE; + } + + /* The parent texture object does not have space for this image */ + + pipe_resource_reference(&stObj->pt, NULL); + pipe_sampler_view_reference(&stObj->sampler_view, NULL); + + 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; + } + } + + if (stObj->pt && + st_texture_match_image(stObj->pt, texImage)) { + /* The image will live in the object's mipmap memory */ + pipe_resource_reference(&stImage->pt, stObj->pt); + assert(stImage->pt); + return GL_TRUE; + } + else { + /* Create a new, temporary texture/resource/buffer to hold this + * one texture image. + */ + enum pipe_format format = + st_mesa_format_to_pipe_format(texImage->TexFormat); + GLuint bindings = default_bindings(st, format); + GLuint ptWidth, ptHeight, ptDepth, ptLayers; + + st_gl_texture_dims_to_pipe_dims(stObj->base.Target, + width, height, depth, + &ptWidth, &ptHeight, &ptDepth, &ptLayers); + + stImage->pt = st_texture_create(st, + gl_target_to_pipe(stObj->base.Target), + format, + 0, /* lastLevel */ + ptWidth, + ptHeight, + ptDepth, + ptLayers, + bindings); + return stImage->pt != NULL; + } +} + + +/** * Adjust pixel unpack params and image dimensions to strip off the * texture border. * Gallium doesn't support texture borders. They've seldem been used @@ -815,15 +900,14 @@ st_CompressedTexImage2D(struct gl_context *ctx, GLenum target, GLint level, * a textured quad. Store the results in the user's buffer. */ static void -decompress_with_blit(struct gl_context * ctx, GLenum target, GLint level, +decompress_with_blit(struct gl_context * ctx, GLenum format, GLenum type, GLvoid *pixels, - struct gl_texture_object *texObj, struct gl_texture_image *texImage) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct st_texture_image *stImage = st_texture_image(texImage); - struct st_texture_object *stObj = st_texture_object(texObj); + struct st_texture_object *stObj = st_texture_object(texImage->TexObject); struct pipe_sampler_view *src_view = st_get_texture_sampler_view(stObj, pipe); const GLuint width = texImage->Width; @@ -848,7 +932,7 @@ decompress_with_blit(struct gl_context * ctx, GLenum target, GLint level, } /* Choose the source mipmap level */ - src_view->u.tex.first_level = src_view->u.tex.last_level = level; + src_view->u.tex.first_level = src_view->u.tex.last_level = texImage->Level; /* blit/render/decompress */ util_blit_pixels_tex(st->blit, @@ -925,9 +1009,8 @@ decompress_with_blit(struct gl_context * ctx, GLenum target, GLint level, * Called via ctx->Driver.GetTexImage() */ static void -st_GetTexImage(struct gl_context * ctx, GLenum target, GLint level, +st_GetTexImage(struct gl_context * ctx, GLenum format, GLenum type, GLvoid * pixels, - struct gl_texture_object *texObj, struct gl_texture_image *texImage) { struct st_texture_image *stImage = st_texture_image(texImage); @@ -938,12 +1021,10 @@ st_GetTexImage(struct gl_context * ctx, GLenum target, GLint level, * faster than using the fallback code in texcompress.c. * Note that we only expect RGBA formats (no Z/depth formats). */ - decompress_with_blit(ctx, target, level, format, type, pixels, - texObj, texImage); + decompress_with_blit(ctx, format, type, pixels, texImage); } else { - _mesa_get_teximage(ctx, target, level, format, type, pixels, - texObj, texImage); + _mesa_get_teximage(ctx, format, type, pixels, texImage); } } @@ -1841,6 +1922,7 @@ st_init_texture_functions(struct dd_function_table *functions) functions->NewTextureImage = st_NewTextureImage; functions->DeleteTextureImage = st_DeleteTextureImage; functions->DeleteTexture = st_DeleteTextureObject; + functions->AllocTextureImageBuffer = st_AllocTextureImageBuffer; functions->FreeTextureImageBuffer = st_FreeTextureImageBuffer; functions->MapTextureImage = st_MapTextureImage; functions->UnmapTextureImage = st_UnmapTextureImage; |