st/mesa: handle texture_from_pixmap and other surface-based textures correctly

There were 2 issues with it:
1) The texture format which should be used for texturing was only set
   in gl_texture_image::TexFormat, which wasn't used for sampler views.
2) Textures are sometimes reallocated under some circumstances
   in st_finalize_texture, which is unacceptable if the texture comes
   from a window system.

The issues are resolved as follows:
1) If surface_based is true (texture_from_pixmap, etc.), store the format
   in a new variable st_texture_object::surface_format.
2) Don't reallocate a surface-based texture in st_finalize_texture.

Also don't use st_ChooseTextureFormat is st_context_teximage, because
the format is dictated by the caller.

This fixes the glx-tfp piglit test.

Reviewed-by: Adam Jackson <ajax@redhat.com>
This commit is contained in:
Marek Olšák
2013-05-10 02:03:15 +02:00
parent 5a3fac4d26
commit 639d0f73c1
7 changed files with 21 additions and 62 deletions

View File

@@ -239,7 +239,8 @@ update_single_texture(struct st_context *st,
st_mesa_format_to_pipe_format(stObj->base._BufferObjectFormat); st_mesa_format_to_pipe_format(stObj->base._BufferObjectFormat);
} }
else { else {
view_format = stObj->pt->format; view_format =
stObj->surface_based ? stObj->surface_format : stObj->pt->format;
/* If sRGB decoding is off, use the linear format */ /* If sRGB decoding is off, use the linear format */
if (samp->sRGBDecode == GL_SKIP_DECODE_EXT) { if (samp->sRGBDecode == GL_SKIP_DECODE_EXT) {

View File

@@ -131,6 +131,7 @@ st_bind_surface(struct gl_context *ctx, GLenum target,
stObj->width0 = ps->width; stObj->width0 = ps->width;
stObj->height0 = ps->height; stObj->height0 = ps->height;
stObj->depth0 = 1; stObj->depth0 = 1;
stObj->surface_format = ps->format;
_mesa_dirty_texobj(ctx, texObj, GL_TRUE); _mesa_dirty_texobj(ctx, texObj, GL_TRUE);
} }

View File

@@ -1540,6 +1540,11 @@ st_finalize_texture(struct gl_context *ctx,
pipe_sampler_view_release(st->pipe, &stObj->sampler_view); pipe_sampler_view_release(st->pipe, &stObj->sampler_view);
} }
/* If this texture comes from a window system, there is nothing else to do. */
if (stObj->surface_based) {
return GL_TRUE;
}
/* Find gallium format for the Mesa texture */ /* Find gallium format for the Mesa texture */
firstImageFormat = st_mesa_format_to_pipe_format(firstImage->base.TexFormat); firstImageFormat = st_mesa_format_to_pipe_format(firstImage->base.TexFormat);
@@ -1567,7 +1572,7 @@ st_finalize_texture(struct gl_context *ctx,
*/ */
if (stObj->pt) { if (stObj->pt) {
if (stObj->pt->target != gl_target_to_pipe(stObj->base.Target) || if (stObj->pt->target != gl_target_to_pipe(stObj->base.Target) ||
!st_sampler_compat_formats(stObj->pt->format, firstImageFormat) || stObj->pt->format != firstImageFormat ||
stObj->pt->last_level < stObj->lastLevel || stObj->pt->last_level < stObj->lastLevel ||
stObj->pt->width0 != ptWidth || stObj->pt->width0 != ptWidth ||
stObj->pt->height0 != ptHeight || stObj->pt->height0 != ptHeight ||

View File

@@ -1800,41 +1800,6 @@ st_QuerySamplesForFormat(struct gl_context *ctx, GLenum target,
} }
GLboolean
st_sampler_compat_formats(enum pipe_format format1, enum pipe_format format2)
{
if (format1 == format2)
return GL_TRUE;
if (format1 == PIPE_FORMAT_B8G8R8A8_UNORM &&
format2 == PIPE_FORMAT_B8G8R8X8_UNORM)
return GL_TRUE;
if (format1 == PIPE_FORMAT_B8G8R8X8_UNORM &&
format2 == PIPE_FORMAT_B8G8R8A8_UNORM)
return GL_TRUE;
if (format1 == PIPE_FORMAT_A8B8G8R8_UNORM &&
format2 == PIPE_FORMAT_X8B8G8R8_UNORM)
return GL_TRUE;
if (format1 == PIPE_FORMAT_X8B8G8R8_UNORM &&
format2 == PIPE_FORMAT_A8B8G8R8_UNORM)
return GL_TRUE;
if (format1 == PIPE_FORMAT_A8R8G8B8_UNORM &&
format2 == PIPE_FORMAT_X8R8G8B8_UNORM)
return GL_TRUE;
if (format1 == PIPE_FORMAT_X8R8G8B8_UNORM &&
format2 == PIPE_FORMAT_A8R8G8B8_UNORM)
return GL_TRUE;
return GL_FALSE;
}
/** /**
* This is used for translating texture border color and the clear * This is used for translating texture border color and the clear
* color. For example, the clear color is interpreted according to * color. For example, the clear color is interpreted according to

View File

@@ -70,10 +70,6 @@ size_t
st_QuerySamplesForFormat(struct gl_context *ctx, GLenum target, st_QuerySamplesForFormat(struct gl_context *ctx, GLenum target,
GLenum internalFormat, int samples[16]); GLenum internalFormat, int samples[16]);
/* can we use a sampler view to translate these formats
only used to make TFP so far */
extern GLboolean
st_sampler_compat_formats(enum pipe_format format1, enum pipe_format format2);
extern void extern void

View File

@@ -467,7 +467,7 @@ st_context_flush(struct st_context_iface *stctxi, unsigned flags,
static boolean static boolean
st_context_teximage(struct st_context_iface *stctxi, st_context_teximage(struct st_context_iface *stctxi,
enum st_texture_type tex_type, enum st_texture_type tex_type,
int level, enum pipe_format internal_format, int level, enum pipe_format pipe_format,
struct pipe_resource *tex, boolean mipmap) struct pipe_resource *tex, boolean mipmap)
{ {
struct st_context *st = (struct st_context *) stctxi; struct st_context *st = (struct st_context *) stctxi;
@@ -511,29 +511,13 @@ st_context_teximage(struct st_context_iface *stctxi,
texImage = _mesa_get_tex_image(ctx, texObj, target, level); texImage = _mesa_get_tex_image(ctx, texObj, target, level);
stImage = st_texture_image(texImage); stImage = st_texture_image(texImage);
if (tex) { if (tex) {
gl_format texFormat; gl_format texFormat = st_pipe_format_to_mesa_format(pipe_format);
/* if (util_format_has_alpha(tex->format))
* XXX When internal_format and tex->format differ, st_finalize_texture
* needs to allocate a new texture with internal_format and copy the
* texture here into the new one. It will result in surface_copy being
* called on surfaces whose formats differ.
*
* To avoid that, internal_format is (wrongly) ignored here. A sane fix
* is to use a sampler view.
*/
if (!st_sampler_compat_formats(tex->format, internal_format))
internal_format = tex->format;
if (util_format_get_component_bits(internal_format,
UTIL_FORMAT_COLORSPACE_RGB, 3) > 0)
internalFormat = GL_RGBA; internalFormat = GL_RGBA;
else else
internalFormat = GL_RGB; internalFormat = GL_RGB;
texFormat = st_ChooseTextureFormat(ctx, target, internalFormat,
GL_BGRA, GL_UNSIGNED_BYTE);
_mesa_init_teximage_fields(ctx, texImage, _mesa_init_teximage_fields(ctx, texImage,
tex->width0, tex->height0, 1, 0, tex->width0, tex->height0, 1, 0,
internalFormat, texFormat); internalFormat, texFormat);
@@ -562,6 +546,7 @@ st_context_teximage(struct st_context_iface *stctxi,
stObj->width0 = width; stObj->width0 = width;
stObj->height0 = height; stObj->height0 = height;
stObj->depth0 = depth; stObj->depth0 = depth;
stObj->surface_format = pipe_format;
_mesa_dirty_texobj(ctx, texObj, GL_TRUE); _mesa_dirty_texobj(ctx, texObj, GL_TRUE);
_mesa_unlock_texture(ctx, texObj); _mesa_unlock_texture(ctx, texObj);

View File

@@ -87,10 +87,16 @@ struct st_texture_object
*/ */
struct pipe_sampler_view *sampler_view; struct pipe_sampler_view *sampler_view;
/* True if there is/was a surface bound to this texture object. It helps /* True if this texture comes from the window system. Such a texture
* track whether the texture object is surface based or not. * cannot be reallocated and the format can only be changed with a sampler
* view or a surface.
*/ */
GLboolean surface_based; GLboolean surface_based;
/* If surface_based is true, this format should be used for all sampler
* views and surfaces instead of pt->format.
*/
enum pipe_format surface_format;
}; };