* 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.
*/
/**
#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"
_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;
+ /* RowStride and ImageSlices[] describe how to address texels in 'Data' */
+ swImg->RowStride = _mesa_format_row_stride(texImage->TexFormat,
+ texImage->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;
-
- 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;
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;
}
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;
}
* 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)
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 <pixels> 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);
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);
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;
+ }
+
+ if (!swImage->ImageSlices) {
+ swImage->ImageSlices =
+ calloc(texture_slices(texImage), sizeof(void *));
+ if (!swImage->ImageSlices)
+ continue;
+ }
- /* XXX we'll eventually call _swrast_map_teximage() here */
- swImage->Data = swImage->Buffer;
+ 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);
}
}
}
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;
+
+ if (swImage->Buffer)
+ return;
- /* XXX we'll eventually call _swrast_unmap_teximage() here */
- swImage->Data = NULL;
+ 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;
+ }
}
}
}
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);
}
}
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);
- }
-}
-
-
-/**
- * Map or unmap any textures that we may be rendering to as renderbuffers.
- */
-static void
-map_unmap_renderbuffers(struct gl_context *ctx,
- struct gl_framebuffer *fb,
- GLboolean map)
-{
- GLuint i;
-
- for (i = 0; i < Elements(fb->Attachment); i++) {
- struct gl_texture_object *texObj = fb->Attachment[i].Texture;
- if (texObj) {
- const GLuint level = fb->Attachment[i].TextureLevel;
- const GLuint face = fb->Attachment[i].CubeMapFace;
- struct gl_texture_image *texImage = texObj->Image[face][level];
- if (texImage) {
- struct swrast_texture_image *swImage
- = swrast_texture_image(texImage);
-
- if (map) {
- /* XXX we'll eventually call _swrast_map_teximage() here */
- swImage->Data = swImage->Buffer;
- }
- else {
- /* XXX we'll eventually call _swrast_unmap_teximage() here */
- swImage->Data = NULL;
- }
- }
- }
- }
-}
-
-void
-_swrast_map_renderbuffers(struct gl_context *ctx)
-{
- map_unmap_renderbuffers(ctx, ctx->DrawBuffer, GL_TRUE);
- if (ctx->ReadBuffer != ctx->DrawBuffer)
- map_unmap_renderbuffers(ctx, ctx->ReadBuffer, GL_TRUE);
-}
-
-
-void
-_swrast_unmap_renderbuffers(struct gl_context *ctx)
-{
- map_unmap_renderbuffers(ctx, ctx->DrawBuffer, GL_FALSE);
- if (ctx->ReadBuffer != ctx->DrawBuffer)
- map_unmap_renderbuffers(ctx, ctx->ReadBuffer, GL_FALSE);
-}
-
-
-
-/**
- * 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;
- }
- }
+ if (texObj)
+ _swrast_unmap_texture(ctx, texObj);
}
-
- return GL_TRUE;
}
-