void _mesa_update_fetch_functions(struct gl_context *ctx, GLuint unit) { struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current; struct gl_sampler_object *samp; GLuint face, i; GLuint dims; if (!texObj) return; samp = _mesa_get_samplerobj(ctx, unit); dims = _mesa_get_texture_dimensions(texObj->Target); for (face = 0; face < 6; face++) { for (i = 0; i < MAX_TEXTURE_LEVELS; i++) { if (texObj->Image[face][i]) { set_fetch_functions(samp, swrast_texture_image(texObj->Image[face][i]), dims); } } } }
/** * This is the software fallback for Driver.GetTexImage(). * All error checking will have been done before this routine is called. * We'll call ctx->Driver.MapTextureImage() to access the data, then * unmap with ctx->Driver.UnmapTextureImage(). */ void _mesa_GetTexImage_sw(struct gl_context *ctx, GLenum format, GLenum type, GLvoid *pixels, struct gl_texture_image *texImage) { const GLuint dimensions = _mesa_get_texture_dimensions(texImage->TexObject->Target); /* map dest buffer, if PBO */ if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { /* Packing texture image into a PBO. * Map the (potentially) VRAM-based buffer into our process space so * we can write into it with the code below. * A hardware driver might use a sophisticated blit to move the * texture data to the PBO if the PBO is in VRAM along with the texture. */ GLubyte *buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, ctx->Pack.BufferObj->Size, GL_MAP_WRITE_BIT, ctx->Pack.BufferObj, MAP_INTERNAL); if (!buf) { /* out of memory or other unexpected error */ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage(map PBO failed)"); return; } /* <pixels> was an offset into the PBO. * Now make it a real, client-side pointer inside the mapped region. */ pixels = ADD_POINTERS(buf, pixels); } if (get_tex_memcpy(ctx, format, type, pixels, texImage)) { /* all done */ } else if (format == GL_DEPTH_COMPONENT) { get_tex_depth(ctx, dimensions, format, type, pixels, texImage); } else if (format == GL_DEPTH_STENCIL) { get_tex_depth_stencil(ctx, dimensions, format, type, pixels, texImage); } else if (format == GL_STENCIL_INDEX) { get_tex_stencil(ctx, dimensions, format, type, pixels, texImage); } else if (format == GL_YCBCR_MESA) { get_tex_ycbcr(ctx, dimensions, format, type, pixels, texImage); } else { get_tex_rgba(ctx, dimensions, format, type, pixels, texImage); } if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { ctx->Driver.UnmapBuffer(ctx, ctx->Pack.BufferObj, MAP_INTERNAL); } }
/* * Returns the dimensions associated to a target. GL_TEXTURE_BUFFER and * GL_RENDERBUFFER have associated a dimension, but they are not textures * per-se, so we can't just call _mesa_get_texture_dimension directly. */ static GLint _get_target_dimensions(GLenum target) { switch(target) { case GL_TEXTURE_BUFFER: return 1; case GL_RENDERBUFFER: return 2; default: return _mesa_get_texture_dimensions(target); } }
void _mesa_update_fetch_functions(struct gl_texture_object *texObj) { GLuint face, i; GLuint dims; dims = _mesa_get_texture_dimensions(texObj->Target); for (face = 0; face < 6; face++) { for (i = 0; i < MAX_TEXTURE_LEVELS; i++) { if (texObj->Image[face][i]) { set_fetch_functions(swrast_texture_image(texObj->Image[face][i]), dims); } } } }
/** * This is the software fallback for Driver.GetCompressedTexImage(). * All error checking will have been done before this routine is called. */ void _mesa_GetCompressedTexImage_sw(struct gl_context *ctx, struct gl_texture_image *texImage, GLvoid *img) { const GLuint dimensions = _mesa_get_texture_dimensions(texImage->TexObject->Target); struct compressed_pixelstore store; GLint slice; GLubyte *dest; _mesa_compute_compressed_pixelstore(dimensions, texImage->TexFormat, texImage->Width, texImage->Height, texImage->Depth, &ctx->Pack, &store); if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { /* pack texture image into a PBO */ dest = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, ctx->Pack.BufferObj->Size, GL_MAP_WRITE_BIT, ctx->Pack.BufferObj, MAP_INTERNAL); if (!dest) { /* out of memory or other unexpected error */ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetCompresssedTexImage(map PBO failed)"); return; } dest = ADD_POINTERS(dest, img); } else { dest = img; } dest += store.SkipBytes; for (slice = 0; slice < store.CopySlices; slice++) { GLint srcRowStride; GLubyte *src; /* map src texture buffer */ ctx->Driver.MapTextureImage(ctx, texImage, slice, 0, 0, texImage->Width, texImage->Height, GL_MAP_READ_BIT, &src, &srcRowStride); if (src) { GLint i; for (i = 0; i < store.CopyRowsPerSlice; i++) { memcpy(dest, src, store.CopyBytesPerRow); dest += store.TotalBytesPerRow; src += srcRowStride; } ctx->Driver.UnmapTextureImage(ctx, texImage, slice); /* Advance to next slice */ dest += store.TotalBytesPerRow * (store.TotalRowsPerSlice - store.CopyRowsPerSlice); } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetCompresssedTexImage"); } } if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { ctx->Driver.UnmapBuffer(ctx, ctx->Pack.BufferObj, MAP_INTERNAL); } }
/** * Do error checking for a glGetCompressedTexImage() call. * \return GL_TRUE if any error, GL_FALSE if no errors. */ static GLboolean getcompressedteximage_error_check(struct gl_context *ctx, struct gl_texture_image *texImage, GLenum target, GLint level, GLsizei clientMemSize, GLvoid *img, bool dsa) { const GLint maxLevels = _mesa_max_texture_levels(ctx, target); GLuint compressedSize, dimensions; const char *suffix = dsa ? "ture" : ""; assert(texImage); if (!legal_getteximage_target(ctx, target, dsa)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTex%sImage(target=%s)", suffix, _mesa_lookup_enum_by_nr(target)); return GL_TRUE; } assert(maxLevels != 0); if (level < 0 || level >= maxLevels) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTex%sImage(bad level = %d)", suffix, level); return GL_TRUE; } if (!_mesa_is_format_compressed(texImage->TexFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTex%sImage(texture is not compressed)", suffix); return GL_TRUE; } compressedSize = _mesa_format_image_size(texImage->TexFormat, texImage->Width, texImage->Height, texImage->Depth); /* Check for invalid pixel storage modes */ dimensions = _mesa_get_texture_dimensions(texImage->TexObject->Target); if (!_mesa_compressed_pixel_storage_error_check(ctx, dimensions, &ctx->Pack, dsa ? "glGetCompressedTextureImage": "glGetCompressedTexImage")) { return GL_TRUE; } if (!_mesa_is_bufferobj(ctx->Pack.BufferObj)) { /* do bounds checking on writing to client memory */ if (clientMemSize < (GLsizei) compressedSize) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(out of bounds access: bufSize (%d) is too small)", dsa ? "glGetCompressedTextureImage" : "glGetnCompressedTexImageARB", clientMemSize); return GL_TRUE; } } else { /* do bounds checking on PBO write */ if ((const GLubyte *) img + compressedSize > (const GLubyte *) ctx->Pack.BufferObj->Size) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTex%sImage(out of bounds PBO access)", suffix); return GL_TRUE; } /* make sure PBO is not mapped */ if (_mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTex%sImage(PBO is mapped)", suffix); return GL_TRUE; } } return GL_FALSE; }
/** * Do error checking for a glGetCompressedTexImage() call. * \return GL_TRUE if any error, GL_FALSE if no errors. */ static GLboolean getcompressedteximage_error_check(struct gl_context *ctx, GLenum target, GLint level, GLsizei clientMemSize, GLvoid *img) { struct gl_texture_object *texObj; struct gl_texture_image *texImage; const GLint maxLevels = _mesa_max_texture_levels(ctx, target); GLuint compressedSize, dimensions; if (!legal_getteximage_target(ctx, target)) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImage(target=0x%x)", target); return GL_TRUE; } assert(maxLevels != 0); if (level < 0 || level >= maxLevels) { _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(bad level = %d)", level); return GL_TRUE; } texObj = _mesa_get_current_tex_object(ctx, target); if (!texObj) { _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)"); return GL_TRUE; } texImage = _mesa_select_tex_image(ctx, texObj, target, level); if (!texImage) { /* probably invalid mipmap level */ _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)"); return GL_TRUE; } if (!_mesa_is_format_compressed(texImage->TexFormat)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB(texture is not compressed)"); return GL_TRUE; } compressedSize = _mesa_format_image_size(texImage->TexFormat, texImage->Width, texImage->Height, texImage->Depth); /* Check for invalid pixel storage modes */ dimensions = _mesa_get_texture_dimensions(texImage->TexObject->Target); if (!_mesa_compressed_texture_pixel_storage_error_check(ctx, dimensions, &ctx->Pack, "glGetCompressedTexImageARB")) { return GL_TRUE; } if (!_mesa_is_bufferobj(ctx->Pack.BufferObj)) { /* do bounds checking on writing to client memory */ if (clientMemSize < (GLsizei) compressedSize) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetnCompressedTexImageARB(out of bounds access:" " bufSize (%d) is too small)", clientMemSize); return GL_TRUE; } } else { /* do bounds checking on PBO write */ if ((const GLubyte *) img + compressedSize > (const GLubyte *) ctx->Pack.BufferObj->Size) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImage(out of bounds PBO access)"); return GL_TRUE; } /* make sure PBO is not mapped */ if (_mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImage(PBO is mapped)"); return GL_TRUE; } } return GL_FALSE; }