X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fswrast%2Fs_texture.c;h=9ccd0e34702ea6c5cdd1d33f6367aaa8f67d6677;hb=0f235c960c8a564ff8817835716e8f377b2f5f16;hp=f945a6b0fa8dd2766923f345cd576a1b2fe27472;hpb=7d1ddec92168e9b6ead0da80b18364a75f9a85e6;p=mesa.git diff --git a/src/mesa/swrast/s_texture.c b/src/mesa/swrast/s_texture.c index f945a6b0fa8..9ccd0e34702 100644 --- a/src/mesa/swrast/s_texture.c +++ b/src/mesa/swrast/s_texture.c @@ -16,9 +16,10 @@ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. */ /** @@ -29,6 +30,7 @@ #include "main/context.h" #include "main/fbobject.h" #include "main/teximage.h" +#include "main/texobj.h" #include "swrast/swrast.h" #include "swrast/s_context.h" @@ -57,48 +59,77 @@ _swrast_delete_texture_image(struct gl_context *ctx, _mesa_delete_texture_image(ctx, texImage); } +static unsigned int +texture_slices(struct gl_texture_image *texImage) +{ + if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) + return texImage->Height; + else + return texImage->Depth; +} + +unsigned int +_swrast_teximage_slice_height(struct gl_texture_image *texImage) +{ + /* For 1D array textures, the slices are all 1 pixel high, and Height is + * the number of slices. + */ + if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) + return 1; + else + return texImage->Height; +} /** * Called via ctx->Driver.AllocTextureImageBuffer() */ GLboolean _swrast_alloc_texture_image_buffer(struct gl_context *ctx, - struct gl_texture_image *texImage, - gl_format format, GLsizei width, - GLsizei height, GLsizei depth) + struct gl_texture_image *texImage) { struct swrast_texture_image *swImg = swrast_texture_image(texImage); - GLuint bytes = _mesa_format_image_size(format, width, height, depth); + GLuint bytesPerSlice; + GLuint slices = texture_slices(texImage); GLuint i; - /* This _should_ be true (revisit if these ever fail) */ - assert(texImage->Width == width); - assert(texImage->Height == height); - assert(texImage->Depth == depth); + if (!_swrast_init_texture_image(texImage)) + return GL_FALSE; + + bytesPerSlice = _mesa_format_image_size(texImage->TexFormat, texImage->Width, + _swrast_teximage_slice_height(texImage), 1); assert(!swImg->Buffer); - swImg->Buffer = _mesa_align_malloc(bytes, 512); + swImg->Buffer = _mesa_align_malloc(bytesPerSlice * slices, 512); if (!swImg->Buffer) return GL_FALSE; - /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */ - swImg->RowStride = width; - - /* Allocate the ImageOffsets array and initialize to typical values. - * We allocate the array for 1D/2D textures too in order to avoid special- - * case code in the texstore routines. - */ - swImg->ImageOffsets = (GLuint *) malloc(depth * sizeof(GLuint)); - if (!swImg->ImageOffsets) - return GL_FALSE; + /* RowStride and ImageSlices[] describe how to address texels in 'Data' */ + swImg->RowStride = _mesa_format_row_stride(texImage->TexFormat, + texImage->Width); - for (i = 0; i < depth; i++) { - swImg->ImageOffsets[i] = i * width * height; + for (i = 0; i < slices; i++) { + swImg->ImageSlices[i] = swImg->Buffer + bytesPerSlice * i; } - if ((width == 1 || _mesa_is_pow_two(texImage->Width2)) && - (height == 1 || _mesa_is_pow_two(texImage->Height2)) && - (depth == 1 || _mesa_is_pow_two(texImage->Depth2))) + return GL_TRUE; +} + + +/** + * Code that overrides ctx->Driver.AllocTextureImageBuffer may use this to + * initialize the fields of swrast_texture_image without allocating the image + * buffer or initializing RowStride or the contents of ImageSlices. + * + * Returns GL_TRUE on success, GL_FALSE on memory allocation failure. + */ +GLboolean +_swrast_init_texture_image(struct gl_texture_image *texImage) +{ + struct swrast_texture_image *swImg = swrast_texture_image(texImage); + + if ((texImage->Width == 1 || _mesa_is_pow_two(texImage->Width2)) && + (texImage->Height == 1 || _mesa_is_pow_two(texImage->Height2)) && + (texImage->Depth == 1 || _mesa_is_pow_two(texImage->Depth2))) swImg->_IsPowerOfTwo = GL_TRUE; else swImg->_IsPowerOfTwo = GL_FALSE; @@ -116,6 +147,11 @@ _swrast_alloc_texture_image_buffer(struct gl_context *ctx, swImg->DepthScale = (GLfloat) texImage->Depth; } + assert(!swImg->ImageSlices); + swImg->ImageSlices = calloc(texture_slices(texImage), sizeof(void *)); + if (!swImg->ImageSlices) + return GL_FALSE; + return GL_TRUE; } @@ -128,15 +164,12 @@ _swrast_free_texture_image_buffer(struct gl_context *ctx, struct gl_texture_image *texImage) { struct swrast_texture_image *swImage = swrast_texture_image(texImage); - if (swImage->Buffer) { - _mesa_align_free(swImage->Buffer); - swImage->Buffer = NULL; - } - if (swImage->ImageOffsets) { - free(swImage->ImageOffsets); - swImage->ImageOffsets = NULL; - } + _mesa_align_free(swImage->Buffer); + swImage->Buffer = NULL; + + free(swImage->ImageSlices); + swImage->ImageSlices = NULL; } @@ -144,8 +177,8 @@ _swrast_free_texture_image_buffer(struct gl_context *ctx, * Error checking for debugging only. */ static void -_mesa_check_map_teximage(struct gl_texture_image *texImage, - GLuint slice, GLuint x, GLuint y, GLuint w, GLuint h) +check_map_teximage(const struct gl_texture_image *texImage, + GLuint slice, GLuint x, GLuint y, GLuint w, GLuint h) { if (texImage->TexObject->Target == GL_TEXTURE_1D) @@ -183,7 +216,16 @@ _swrast_map_teximage(struct gl_context *ctx, GLint stride, texelSize; GLuint bw, bh; - _mesa_check_map_teximage(texImage, slice, x, y, w, h); + check_map_teximage(texImage, slice, x, y, w, h); + + if (!swImage->Buffer) { + /* Either glTexImage was called with a NULL argument or + * we ran out of memory when allocating texture memory, + */ + *mapOut = NULL; + *rowStrideOut = 0; + return; + } texelSize = _mesa_get_format_bytes(texImage->TexFormat); stride = _mesa_format_row_stride(texImage->TexFormat, texImage->Width); @@ -192,30 +234,14 @@ _swrast_map_teximage(struct gl_context *ctx, assert(x % bw == 0); assert(y % bh == 0); - if (!swImage->Buffer) { - /* probably ran out of memory when allocating tex mem */ - *mapOut = NULL; - return; - } - - map = swImage->Buffer; - - if (texImage->TexObject->Target == GL_TEXTURE_3D || - texImage->TexObject->Target == GL_TEXTURE_2D_ARRAY) { - GLuint sliceSize = _mesa_format_image_size(texImage->TexFormat, - texImage->Width, - texImage->Height, - 1); - assert(slice < texImage->Depth); - map += slice * sliceSize; - } else if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) { - GLuint sliceSize = _mesa_format_image_size(texImage->TexFormat, - texImage->Width, - 1, - 1); - assert(slice < texImage->Height); - map += slice * sliceSize; - } + /* This function can only be used with a swrast-allocated buffer, in which + * case ImageSlices is populated with pointers into Buffer. + */ + assert(swImage->Buffer); + assert(swImage->Buffer == swImage->ImageSlices[0]); + + assert(slice < texture_slices(texImage)); + map = swImage->ImageSlices[slice]; /* apply x/y offset to map address */ map += stride * (y / bh) + texelSize * (x / bw); @@ -236,18 +262,57 @@ _swrast_unmap_teximage(struct gl_context *ctx, void _swrast_map_texture(struct gl_context *ctx, struct gl_texture_object *texObj) { - const GLuint faces = texObj->Target == GL_TEXTURE_CUBE_MAP ? 6 : 1; + const GLuint faces = _mesa_num_tex_faces(texObj->Target); GLuint face, level; for (face = 0; face < faces; face++) { for (level = texObj->BaseLevel; level < MAX_TEXTURE_LEVELS; level++) { struct gl_texture_image *texImage = texObj->Image[face][level]; - if (texImage) { - struct swrast_texture_image *swImage = - swrast_texture_image(texImage); + struct swrast_texture_image *swImage = swrast_texture_image(texImage); + unsigned int i, slices; + + if (!texImage) + continue; + + /* In the case of a swrast-allocated texture buffer, the ImageSlices + * and RowStride are always available. + */ + if (swImage->Buffer) { + assert(swImage->ImageSlices[0] == swImage->Buffer); + continue; + } - /* XXX we'll eventually call _swrast_map_teximage() here */ - swImage->Map = swImage->Buffer; + if (!swImage->ImageSlices) { + swImage->ImageSlices = + calloc(texture_slices(texImage), sizeof(void *)); + if (!swImage->ImageSlices) + continue; + } + + slices = texture_slices(texImage); + + for (i = 0; i < slices; i++) { + GLubyte *map; + GLint rowStride; + + if (swImage->ImageSlices[i]) + continue; + + ctx->Driver.MapTextureImage(ctx, texImage, i, + 0, 0, + texImage->Width, texImage->Height, + GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, + &map, &rowStride); + + swImage->ImageSlices[i] = map; + /* A swrast-using driver has to return the same rowstride for + * every slice of the same texture, since we don't track them + * separately. + */ + if (i == 0) + swImage->RowStride = rowStride; + else + assert(swImage->RowStride == rowStride); } } } @@ -257,18 +322,31 @@ _swrast_map_texture(struct gl_context *ctx, struct gl_texture_object *texObj) void _swrast_unmap_texture(struct gl_context *ctx, struct gl_texture_object *texObj) { - const GLuint faces = texObj->Target == GL_TEXTURE_CUBE_MAP ? 6 : 1; + const GLuint faces = _mesa_num_tex_faces(texObj->Target); GLuint face, level; for (face = 0; face < faces; face++) { for (level = texObj->BaseLevel; level < MAX_TEXTURE_LEVELS; level++) { struct gl_texture_image *texImage = texObj->Image[face][level]; - if (texImage) { - struct swrast_texture_image *swImage - = swrast_texture_image(texImage); + struct swrast_texture_image *swImage = swrast_texture_image(texImage); + unsigned int i, slices; + + if (!texImage) + continue; - /* XXX we'll eventually call _swrast_unmap_teximage() here */ - swImage->Map = NULL; + if (swImage->Buffer) + return; + + if (!swImage->ImageSlices) + continue; + + slices = texture_slices(texImage); + + for (i = 0; i < slices; i++) { + if (swImage->ImageSlices[i]) { + ctx->Driver.UnmapTextureImage(ctx, texImage, i); + swImage->ImageSlices[i] = NULL; + } } } } @@ -281,16 +359,13 @@ _swrast_unmap_texture(struct gl_context *ctx, struct gl_texture_object *texObj) void _swrast_map_textures(struct gl_context *ctx) { - GLbitfield enabledUnits = ctx->Texture._EnabledUnits; + int unit; - /* loop over enabled texture units */ - while (enabledUnits) { - GLuint unit = ffs(enabledUnits) - 1; + for (unit = 0; unit <= ctx->Texture._MaxEnabledTexImageUnit; unit++) { struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current; - - _swrast_map_texture(ctx, texObj); - enabledUnits &= ~(1 << unit); + if (texObj) + _swrast_map_texture(ctx, texObj); } } @@ -301,172 +376,11 @@ _swrast_map_textures(struct gl_context *ctx) void _swrast_unmap_textures(struct gl_context *ctx) { - GLbitfield enabledUnits = ctx->Texture._EnabledUnits; - - /* loop over enabled texture units */ - while (enabledUnits) { - GLuint unit = ffs(enabledUnits) - 1; + int unit; + for (unit = 0; unit <= ctx->Texture._MaxEnabledTexImageUnit; unit++) { struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current; - - _swrast_unmap_texture(ctx, texObj); - enabledUnits &= ~(1 << unit); + if (texObj) + _swrast_unmap_texture(ctx, texObj); } } - - -static void -map_attachment(struct gl_context *ctx, - struct gl_framebuffer *fb, - gl_buffer_index buffer) -{ - struct gl_texture_object *texObj = fb->Attachment[buffer].Texture; - struct gl_renderbuffer *rb = fb->Attachment[buffer].Renderbuffer; - - if (texObj) { - const GLuint level = fb->Attachment[buffer].TextureLevel; - const GLuint face = fb->Attachment[buffer].CubeMapFace; - struct gl_texture_image *texImage = texObj->Image[face][level]; - if (texImage) { - struct swrast_texture_image *swImage - = swrast_texture_image(texImage); - - /* XXX we'll eventually call _swrast_map_teximage() here */ - swImage->Map = swImage->Buffer; - if (rb) { - rb->Map = swImage->Buffer; - rb->RowStrideBytes = swImage->RowStride * - _mesa_get_format_bytes(swImage->Base.TexFormat); - } - } - } - else if (rb) { - /* Map ordinary renderbuffer */ - /* XXX don't map color buffers yet */ - if (buffer == BUFFER_DEPTH || buffer == BUFFER_STENCIL) { - ctx->Driver.MapRenderbuffer(ctx, rb, - 0, 0, rb->Width, rb->Height, - GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, - &rb->Map, &rb->RowStrideBytes); - assert(rb->Map); - } - } -} - - -static void -unmap_attachment(struct gl_context *ctx, - struct gl_framebuffer *fb, - gl_buffer_index buffer) -{ - struct gl_texture_object *texObj = fb->Attachment[buffer].Texture; - struct gl_renderbuffer *rb = fb->Attachment[buffer].Renderbuffer; - - if (texObj) { - const GLuint level = fb->Attachment[buffer].TextureLevel; - const GLuint face = fb->Attachment[buffer].CubeMapFace; - struct gl_texture_image *texImage = texObj->Image[face][level]; - if (texImage) { - - /* XXX we'll eventually call _swrast_unmap_teximage() here */ - } - } - else if (rb) { - /* unmap ordinary renderbuffer */ - /* XXX don't map color buffers yet */ - if (buffer == BUFFER_DEPTH || buffer == BUFFER_STENCIL) { - ctx->Driver.UnmapRenderbuffer(ctx, rb); - } - } - - rb->Map = NULL; - rb->RowStrideBytes = 0; -} - - -/** - * Map the renderbuffers we'll use for tri/line/point rendering. - */ -void -_swrast_map_renderbuffers(struct gl_context *ctx) -{ - struct gl_framebuffer *fb = ctx->DrawBuffer; - struct gl_renderbuffer *depthRb, *stencilRb; - GLuint buf; - - depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer; - if (depthRb) { - /* map depth buffer */ - map_attachment(ctx, fb, BUFFER_DEPTH); - } - - stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer; - if (stencilRb && stencilRb != depthRb) { - /* map stencil buffer */ - map_attachment(ctx, fb, BUFFER_STENCIL); - } - - for (buf = 0; buf < fb->_NumColorDrawBuffers; buf++) { - map_attachment(ctx, fb, fb->_ColorDrawBufferIndexes[buf]); - } -} - - -/** - * Unmap renderbuffers after rendering. - */ -void -_swrast_unmap_renderbuffers(struct gl_context *ctx) -{ - struct gl_framebuffer *fb = ctx->DrawBuffer; - struct gl_renderbuffer *depthRb, *stencilRb; - GLuint buf; - - depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer; - if (depthRb) { - /* map depth buffer */ - unmap_attachment(ctx, fb, BUFFER_DEPTH); - } - - stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer; - if (stencilRb && stencilRb != depthRb) { - /* map stencil buffer */ - unmap_attachment(ctx, fb, BUFFER_STENCIL); - } - - for (buf = 0; buf < fb->_NumColorDrawBuffers; buf++) { - unmap_attachment(ctx, fb, fb->_ColorDrawBufferIndexes[buf]); - } -} - - - -/** - * Called via ctx->Driver.AllocTextureStorage() - * Just have to allocate memory for the texture images. - */ -GLboolean -_swrast_AllocTextureStorage(struct gl_context *ctx, - struct gl_texture_object *texObj, - GLsizei levels, GLsizei width, - GLsizei height, GLsizei depth) -{ - const GLint numFaces = (texObj->Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; - GLint face, level; - - for (face = 0; face < numFaces; face++) { - for (level = 0; level < levels; level++) { - struct gl_texture_image *texImage = texObj->Image[face][level]; - if (!_swrast_alloc_texture_image_buffer(ctx, texImage, - texImage->TexFormat, - texImage->Width, - texImage->Height, - texImage->Depth)) { - return GL_FALSE; - } - } - } - - return GL_TRUE; -} -