|
|
@@ -231,70 +231,86 @@ default_bindings(struct st_context *st, enum pipe_format format) |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** Return number of image dimensions (1, 2 or 3) for a texture target. */ |
|
|
|
static GLuint |
|
|
|
get_texture_dims(GLenum target) |
|
|
|
{ |
|
|
|
switch (target) { |
|
|
|
case GL_TEXTURE_1D: |
|
|
|
case GL_TEXTURE_1D_ARRAY_EXT: |
|
|
|
return 1; |
|
|
|
case GL_TEXTURE_2D: |
|
|
|
case GL_TEXTURE_CUBE_MAP_ARB: |
|
|
|
case GL_TEXTURE_RECTANGLE_NV: |
|
|
|
case GL_TEXTURE_2D_ARRAY_EXT: |
|
|
|
return 2; |
|
|
|
case GL_TEXTURE_3D: |
|
|
|
return 3; |
|
|
|
default: |
|
|
|
assert(0 && "invalid texture target in get_texture_dims()"); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Allocate a pipe_resource object for the given st_texture_object using |
|
|
|
* the given st_texture_image to guess the mipmap size/levels. |
|
|
|
* Try to allocate a pipe_resource object for the given st_texture_object. |
|
|
|
* |
|
|
|
* [comments...] |
|
|
|
* Otherwise, store it in memory if (Border != 0) or (any dimension == |
|
|
|
* 1). |
|
|
|
* |
|
|
|
* Otherwise, if max_level >= level >= min_level, create texture with |
|
|
|
* space for images from min_level down to max_level. |
|
|
|
* We use the given st_texture_image as a clue to determine the size of the |
|
|
|
* mipmap image at level=0. |
|
|
|
* |
|
|
|
* Otherwise, create texture with space for images from (level 0)..(1x1). |
|
|
|
* Consider pruning this texture at a validation if the saving is worth it. |
|
|
|
*/ |
|
|
|
static void |
|
|
|
guess_and_alloc_texture(struct st_context *st, |
|
|
|
struct st_texture_object *stObj, |
|
|
|
const struct st_texture_image *stImage) |
|
|
|
{ |
|
|
|
GLuint firstLevel; |
|
|
|
GLuint lastLevel; |
|
|
|
GLuint width = stImage->base.Width2; /* size w/out border */ |
|
|
|
GLuint height = stImage->base.Height2; |
|
|
|
GLuint depth = stImage->base.Depth2; |
|
|
|
GLuint i, bindings; |
|
|
|
const GLuint dims = get_texture_dims(stObj->base.Target); |
|
|
|
GLuint level, lastLevel, width, height, depth; |
|
|
|
GLuint bindings; |
|
|
|
enum pipe_format fmt; |
|
|
|
|
|
|
|
DBG("%s\n", __FUNCTION__); |
|
|
|
|
|
|
|
assert(!stObj->pt); |
|
|
|
|
|
|
|
if (stObj->pt && |
|
|
|
(GLint) stImage->level > stObj->base.BaseLevel && |
|
|
|
(stImage->base.Width == 1 || |
|
|
|
(stObj->base.Target != GL_TEXTURE_1D && |
|
|
|
stImage->base.Height == 1) || |
|
|
|
(stObj->base.Target == GL_TEXTURE_3D && |
|
|
|
stImage->base.Depth == 1))) |
|
|
|
return; |
|
|
|
level = stImage->level; |
|
|
|
width = stImage->base.Width2; /* size w/out border */ |
|
|
|
height = stImage->base.Height2; |
|
|
|
depth = stImage->base.Depth2; |
|
|
|
|
|
|
|
/* If this image disrespects BaseLevel, allocate from level zero. |
|
|
|
* Usually BaseLevel == 0, so it's unlikely to happen. |
|
|
|
*/ |
|
|
|
if ((GLint) stImage->level < stObj->base.BaseLevel) |
|
|
|
firstLevel = 0; |
|
|
|
else |
|
|
|
firstLevel = stObj->base.BaseLevel; |
|
|
|
assert(width > 0); |
|
|
|
assert(height > 0); |
|
|
|
assert(depth > 0); |
|
|
|
|
|
|
|
|
|
|
|
/* Figure out image dimensions at start level. |
|
|
|
/* Depending on the image's size, we can't always make a guess here. |
|
|
|
*/ |
|
|
|
for (i = stImage->level; i > firstLevel; i--) { |
|
|
|
if (level > 0) { |
|
|
|
if ( (dims >= 1 && width == 1) || |
|
|
|
(dims >= 2 && height == 1) || |
|
|
|
(dims >= 3 && depth == 1) ) { |
|
|
|
/* we can't determine the image size at level=0 */ |
|
|
|
stObj->width0 = stObj->height0 = stObj->depth0 = 0; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* grow the image size until we hit level = 0 */ |
|
|
|
while (level > 0) { |
|
|
|
if (width != 1) |
|
|
|
width <<= 1; |
|
|
|
if (height != 1) |
|
|
|
height <<= 1; |
|
|
|
if (depth != 1) |
|
|
|
depth <<= 1; |
|
|
|
} |
|
|
|
level--; |
|
|
|
} |
|
|
|
|
|
|
|
if (width == 0 || height == 0 || depth == 0) { |
|
|
|
/* no texture needed */ |
|
|
|
return; |
|
|
|
} |
|
|
|
assert(level == 0); |
|
|
|
|
|
|
|
/* At this point, (width x height x depth) is the expected size of |
|
|
|
* the level=0 mipmap image. |
|
|
|
*/ |
|
|
|
|
|
|
|
/* Guess a reasonable value for lastLevel. This is probably going |
|
|
|
* to be wrong fairly often and might mean that we have to look at |
|
|
@@ -306,18 +322,23 @@ guess_and_alloc_texture(struct st_context *st, |
|
|
|
stImage->base._BaseFormat == GL_DEPTH_COMPONENT || |
|
|
|
stImage->base._BaseFormat == GL_DEPTH_STENCIL_EXT) && |
|
|
|
!stObj->base.GenerateMipmap && |
|
|
|
stImage->level == firstLevel) { |
|
|
|
stImage->level == 0) { |
|
|
|
/* only alloc space for a single mipmap level */ |
|
|
|
lastLevel = firstLevel; |
|
|
|
lastLevel = 0; |
|
|
|
} |
|
|
|
else { |
|
|
|
/* alloc space for a full mipmap */ |
|
|
|
GLuint l2width = util_logbase2(width); |
|
|
|
GLuint l2height = util_logbase2(height); |
|
|
|
GLuint l2depth = util_logbase2(depth); |
|
|
|
lastLevel = firstLevel + MAX2(MAX2(l2width, l2height), l2depth); |
|
|
|
lastLevel = MAX2(MAX2(l2width, l2height), l2depth); |
|
|
|
} |
|
|
|
|
|
|
|
/* Save the level=0 dimensions */ |
|
|
|
stObj->width0 = width; |
|
|
|
stObj->height0 = height; |
|
|
|
stObj->depth0 = depth; |
|
|
|
|
|
|
|
fmt = st_mesa_format_to_pipe_format(stImage->base.TexFormat); |
|
|
|
|
|
|
|
bindings = default_bindings(st, fmt); |
|
|
@@ -581,15 +602,13 @@ st_TexImage(GLcontext * ctx, |
|
|
|
* mipmap. If so, free the old mipmap. |
|
|
|
*/ |
|
|
|
if (stObj->pt) { |
|
|
|
if (stObj->teximage_realloc || |
|
|
|
level > (GLint) stObj->pt->last_level || |
|
|
|
if (level > (GLint) stObj->pt->last_level || |
|
|
|
!st_texture_match_image(stObj->pt, &stImage->base, |
|
|
|
stImage->face, stImage->level)) { |
|
|
|
DBG("release it\n"); |
|
|
|
pipe_resource_reference(&stObj->pt, NULL); |
|
|
|
assert(!stObj->pt); |
|
|
|
pipe_sampler_view_reference(&stObj->sampler_view, NULL); |
|
|
|
stObj->teximage_realloc = FALSE; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@@ -1757,12 +1776,26 @@ st_CopyTexSubImage3D(GLcontext * ctx, GLenum target, GLint level, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Copy image data from stImage into the texture object 'stObj' at level |
|
|
|
* 'dstLevel'. |
|
|
|
*/ |
|
|
|
static void |
|
|
|
copy_image_data_to_texture(struct st_context *st, |
|
|
|
struct st_texture_object *stObj, |
|
|
|
GLuint dstLevel, |
|
|
|
struct st_texture_image *stImage) |
|
|
|
{ |
|
|
|
/* debug checks */ |
|
|
|
{ |
|
|
|
const struct gl_texture_image *dstImage = |
|
|
|
stObj->base.Image[stImage->face][stImage->level]; |
|
|
|
assert(dstImage); |
|
|
|
assert(dstImage->Width == stImage->base.Width); |
|
|
|
assert(dstImage->Height == stImage->base.Height); |
|
|
|
assert(dstImage->Depth == stImage->base.Depth); |
|
|
|
} |
|
|
|
|
|
|
|
if (stImage->pt) { |
|
|
|
/* Copy potentially with the blitter: |
|
|
|
*/ |
|
|
@@ -1811,8 +1844,9 @@ st_finalize_texture(GLcontext *ctx, |
|
|
|
struct st_context *st = st_context(ctx); |
|
|
|
struct st_texture_object *stObj = st_texture_object(tObj); |
|
|
|
const GLuint nr_faces = (stObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; |
|
|
|
GLuint blockSize, face; |
|
|
|
GLuint face; |
|
|
|
struct st_texture_image *firstImage; |
|
|
|
enum pipe_format firstImageFormat; |
|
|
|
|
|
|
|
*needFlush = GL_FALSE; |
|
|
|
|
|
|
@@ -1827,10 +1861,11 @@ st_finalize_texture(GLcontext *ctx, |
|
|
|
stObj->base.MinFilter == GL_NEAREST) |
|
|
|
stObj->lastLevel = stObj->base.BaseLevel; |
|
|
|
else |
|
|
|
stObj->lastLevel = stObj->base._MaxLevel - stObj->base.BaseLevel; |
|
|
|
stObj->lastLevel = stObj->base._MaxLevel; |
|
|
|
} |
|
|
|
|
|
|
|
firstImage = st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]); |
|
|
|
assert(firstImage); |
|
|
|
|
|
|
|
/* If both firstImage and stObj point to a texture which can contain |
|
|
|
* all active images, favour firstImage. Note that because of the |
|
|
@@ -1844,22 +1879,23 @@ st_finalize_texture(GLcontext *ctx, |
|
|
|
pipe_sampler_view_reference(&stObj->sampler_view, NULL); |
|
|
|
} |
|
|
|
|
|
|
|
/* bytes per pixel block (blocks are usually 1x1) */ |
|
|
|
blockSize = _mesa_get_format_bytes(firstImage->base.TexFormat); |
|
|
|
/* Find gallium format for the Mesa texture */ |
|
|
|
firstImageFormat = st_mesa_format_to_pipe_format(firstImage->base.TexFormat); |
|
|
|
|
|
|
|
/* If we already have a gallium texture, check that it matches the texture |
|
|
|
* object's format, target, size, num_levels, etc. |
|
|
|
*/ |
|
|
|
if (stObj->pt) { |
|
|
|
const enum pipe_format fmt = |
|
|
|
st_mesa_format_to_pipe_format(firstImage->base.TexFormat); |
|
|
|
if (stObj->pt->target != gl_target_to_pipe(stObj->base.Target) || |
|
|
|
stObj->pt->format != fmt || |
|
|
|
stObj->pt->last_level < stObj->lastLevel || |
|
|
|
stObj->pt->width0 != firstImage->base.Width2 || |
|
|
|
stObj->pt->height0 != firstImage->base.Height2 || |
|
|
|
stObj->pt->depth0 != firstImage->base.Depth2) |
|
|
|
stObj->pt->format != firstImageFormat || |
|
|
|
stObj->pt->last_level != stObj->lastLevel || |
|
|
|
stObj->pt->width0 != stObj->width0 || |
|
|
|
stObj->pt->height0 != stObj->height0 || |
|
|
|
stObj->pt->depth0 != stObj->depth0) |
|
|
|
{ |
|
|
|
/* The gallium texture does not match the Mesa texture so delete the |
|
|
|
* gallium texture now. We'll make a new one below. |
|
|
|
*/ |
|
|
|
pipe_resource_reference(&stObj->pt, NULL); |
|
|
|
pipe_sampler_view_reference(&stObj->sampler_view, NULL); |
|
|
|
st->dirty.st |= ST_NEW_FRAMEBUFFER; |
|
|
@@ -1869,17 +1905,15 @@ st_finalize_texture(GLcontext *ctx, |
|
|
|
/* May need to create a new gallium texture: |
|
|
|
*/ |
|
|
|
if (!stObj->pt) { |
|
|
|
const enum pipe_format fmt = |
|
|
|
st_mesa_format_to_pipe_format(firstImage->base.TexFormat); |
|
|
|
GLuint bindings = default_bindings(st, fmt); |
|
|
|
GLuint bindings = default_bindings(st, firstImageFormat); |
|
|
|
|
|
|
|
stObj->pt = st_texture_create(st, |
|
|
|
gl_target_to_pipe(stObj->base.Target), |
|
|
|
fmt, |
|
|
|
firstImageFormat, |
|
|
|
stObj->lastLevel, |
|
|
|
firstImage->base.Width2, |
|
|
|
firstImage->base.Height2, |
|
|
|
firstImage->base.Depth2, |
|
|
|
stObj->width0, |
|
|
|
stObj->height0, |
|
|
|
stObj->depth0, |
|
|
|
bindings); |
|
|
|
|
|
|
|
if (!stObj->pt) { |
|
|
@@ -1894,7 +1928,7 @@ st_finalize_texture(GLcontext *ctx, |
|
|
|
GLuint level; |
|
|
|
for (level = 0; level <= stObj->lastLevel; level++) { |
|
|
|
struct st_texture_image *stImage = |
|
|
|
st_texture_image(stObj->base.Image[face][stObj->base.BaseLevel + level]); |
|
|
|
st_texture_image(stObj->base.Image[face][level]); |
|
|
|
|
|
|
|
/* Need to import images in main memory or held in other textures. |
|
|
|
*/ |