mirror of
https://github.com/brl/mutter.git
synced 2024-11-23 00:20:42 -05:00
Add a GL_GENERATE_MIPMAP fallback to the texture 2d and 3d backends
The CoglTexture2DSliced backend has a fallback for when the framebuffer extension is missing so it's not possible to use glGenerateMipmap. This involves keeping a copy of the upper-left pixel of the tex image so that we can temporarily enable GL_GENERATE_MIPMAP on the texture object and do a sub texture update by reuploading the contents of the first pixel. This patch copies that mechanism to the 2D and 3D backends. The CoglTexturePixel structure which was previously internal to the sliced backend has been moved to cogl-texture-private.h so that it can be shared.
This commit is contained in:
parent
ff56f4ac6f
commit
ceb57087a7
@ -51,6 +51,8 @@ struct _CoglTexture2D
|
|||||||
GLint wrap_mode_t;
|
GLint wrap_mode_t;
|
||||||
gboolean auto_mipmap;
|
gboolean auto_mipmap;
|
||||||
gboolean mipmaps_dirty;
|
gboolean mipmaps_dirty;
|
||||||
|
|
||||||
|
CoglTexturePixel first_pixel;
|
||||||
};
|
};
|
||||||
|
|
||||||
GQuark
|
GQuark
|
||||||
|
@ -32,19 +32,6 @@
|
|||||||
#define COGL_TEXTURE_2D_SLICED(tex) ((CoglTexture2DSliced *)tex)
|
#define COGL_TEXTURE_2D_SLICED(tex) ((CoglTexture2DSliced *)tex)
|
||||||
|
|
||||||
typedef struct _CoglTexture2DSliced CoglTexture2DSliced;
|
typedef struct _CoglTexture2DSliced CoglTexture2DSliced;
|
||||||
typedef struct _CoglTexturePixel CoglTexturePixel;
|
|
||||||
|
|
||||||
/* This is used to store the first pixel of each slice. This is only
|
|
||||||
used when glGenerateMipmap is not available */
|
|
||||||
struct _CoglTexturePixel
|
|
||||||
{
|
|
||||||
/* We need to store the format of the pixel because we store the
|
|
||||||
data in the source format which might end up being different for
|
|
||||||
each slice if a subregion is updated with a different format */
|
|
||||||
GLenum gl_format;
|
|
||||||
GLenum gl_type;
|
|
||||||
guint8 data[4];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _CoglTexture2DSliced
|
struct _CoglTexture2DSliced
|
||||||
{
|
{
|
||||||
|
@ -166,13 +166,6 @@ _cogl_texture_2d_can_create (unsigned int width,
|
|||||||
GLenum gl_intformat;
|
GLenum gl_intformat;
|
||||||
GLenum gl_type;
|
GLenum gl_type;
|
||||||
|
|
||||||
/* If the driver doesn't support glGenerateMipmap then we need to
|
|
||||||
store a copy of the first pixels to cause an update. Instead of
|
|
||||||
duplicating the code here we'll just make it fallback to
|
|
||||||
CoglTexture2DSliced */
|
|
||||||
if (!cogl_features_available (COGL_FEATURE_OFFSCREEN))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* If NPOT textures aren't supported then the size must be a power
|
/* If NPOT textures aren't supported then the size must be a power
|
||||||
of two */
|
of two */
|
||||||
if (!cogl_features_available (COGL_FEATURE_TEXTURE_NPOT) &&
|
if (!cogl_features_available (COGL_FEATURE_TEXTURE_NPOT) &&
|
||||||
@ -296,6 +289,13 @@ _cogl_texture_2d_new_from_bitmap (CoglHandle bmp_handle,
|
|||||||
flags,
|
flags,
|
||||||
internal_format);
|
internal_format);
|
||||||
|
|
||||||
|
/* Keep a copy of the first pixel so that if glGenerateMipmap isn't
|
||||||
|
supported we can fallback to using GL_GENERATE_MIPMAP */
|
||||||
|
tex_2d->first_pixel.gl_format = gl_format;
|
||||||
|
tex_2d->first_pixel.gl_type = gl_type;
|
||||||
|
memcpy (tex_2d->first_pixel.data, dst_bmp.data,
|
||||||
|
_cogl_get_format_bpp (dst_bmp.format));
|
||||||
|
|
||||||
_cogl_texture_driver_gen (GL_TEXTURE_2D, 1, &tex_2d->gl_texture);
|
_cogl_texture_driver_gen (GL_TEXTURE_2D, 1, &tex_2d->gl_texture);
|
||||||
_cogl_texture_driver_upload_to_gl (GL_TEXTURE_2D,
|
_cogl_texture_driver_upload_to_gl (GL_TEXTURE_2D,
|
||||||
tex_2d->gl_texture,
|
tex_2d->gl_texture,
|
||||||
@ -420,10 +420,25 @@ _cogl_texture_2d_pre_paint (CoglTexture *tex, CoglTexturePrePaintFlags flags)
|
|||||||
_cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
|
_cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
|
||||||
tex_2d->gl_texture,
|
tex_2d->gl_texture,
|
||||||
FALSE);
|
FALSE);
|
||||||
/* glGenerateMipmap is defined in the FBO extension. We only allow
|
|
||||||
CoglTexture2D instances to be created if this feature is
|
/* glGenerateMipmap is defined in the FBO extension. If it's not
|
||||||
available so we don't need to check for the extension */
|
available we'll fallback to temporarily enabling
|
||||||
_cogl_texture_driver_gl_generate_mipmaps (GL_TEXTURE_2D);
|
GL_GENERATE_MIPMAP and reuploading the first pixel */
|
||||||
|
if (cogl_features_available (COGL_FEATURE_OFFSCREEN))
|
||||||
|
_cogl_texture_driver_gl_generate_mipmaps (GL_TEXTURE_2D);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GE( glTexParameteri (GL_TEXTURE_2D,
|
||||||
|
GL_GENERATE_MIPMAP,
|
||||||
|
GL_TRUE) );
|
||||||
|
GE( glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, 1, 1,
|
||||||
|
tex_2d->first_pixel.gl_format,
|
||||||
|
tex_2d->first_pixel.gl_type,
|
||||||
|
tex_2d->first_pixel.data) );
|
||||||
|
GE( glTexParameteri (GL_TEXTURE_2D,
|
||||||
|
GL_GENERATE_MIPMAP,
|
||||||
|
GL_FALSE) );
|
||||||
|
}
|
||||||
|
|
||||||
tex_2d->mipmaps_dirty = FALSE;
|
tex_2d->mipmaps_dirty = FALSE;
|
||||||
}
|
}
|
||||||
@ -454,6 +469,17 @@ _cogl_texture_2d_set_region (CoglTexture *tex,
|
|||||||
&gl_format,
|
&gl_format,
|
||||||
&gl_type);
|
&gl_type);
|
||||||
|
|
||||||
|
/* If this touches the first pixel then we'll update our copy */
|
||||||
|
if (dst_x == 0 && dst_y == 0)
|
||||||
|
{
|
||||||
|
CoglPixelFormat bpp = _cogl_get_format_bpp (bmp->format);
|
||||||
|
tex_2d->first_pixel.gl_format = gl_format;
|
||||||
|
tex_2d->first_pixel.gl_type = gl_type;
|
||||||
|
memcpy (tex_2d->first_pixel.data,
|
||||||
|
bmp->data + bmp->rowstride * src_y + bpp * src_x,
|
||||||
|
bpp);
|
||||||
|
}
|
||||||
|
|
||||||
/* Send data to GL */
|
/* Send data to GL */
|
||||||
_cogl_texture_driver_upload_subregion_to_gl (GL_TEXTURE_2D,
|
_cogl_texture_driver_upload_subregion_to_gl (GL_TEXTURE_2D,
|
||||||
tex_2d->gl_texture,
|
tex_2d->gl_texture,
|
||||||
|
@ -54,6 +54,8 @@ struct _CoglTexture3D
|
|||||||
GLint wrap_mode_p;
|
GLint wrap_mode_p;
|
||||||
gboolean auto_mipmap;
|
gboolean auto_mipmap;
|
||||||
gboolean mipmaps_dirty;
|
gboolean mipmaps_dirty;
|
||||||
|
|
||||||
|
CoglTexturePixel first_pixel;
|
||||||
};
|
};
|
||||||
|
|
||||||
GQuark
|
GQuark
|
||||||
|
@ -222,20 +222,6 @@ _cogl_texture_3d_can_create (unsigned int width,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the driver doesn't support glGenerateMipmap then we need to
|
|
||||||
store a copy of the first pixels to cause an update. Instead of
|
|
||||||
duplicating the code here we'll just make it throw an error */
|
|
||||||
if ((flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0 &&
|
|
||||||
!cogl_features_available (COGL_FEATURE_OFFSCREEN))
|
|
||||||
{
|
|
||||||
g_set_error (error,
|
|
||||||
COGL_ERROR,
|
|
||||||
COGL_ERROR_UNSUPPORTED,
|
|
||||||
"Auto mipmapping was requested but this is not supported "
|
|
||||||
"by Cogl with this driver");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If NPOT textures aren't supported then the size must be a power
|
/* If NPOT textures aren't supported then the size must be a power
|
||||||
of two */
|
of two */
|
||||||
if (!cogl_features_available (COGL_FEATURE_TEXTURE_NPOT) &&
|
if (!cogl_features_available (COGL_FEATURE_TEXTURE_NPOT) &&
|
||||||
@ -359,6 +345,13 @@ _cogl_texture_3d_new_from_bitmap (CoglHandle bmp_handle,
|
|||||||
tex_3d = _cogl_texture_3d_create_base (dst_bmp.width, height, depth,
|
tex_3d = _cogl_texture_3d_create_base (dst_bmp.width, height, depth,
|
||||||
flags, internal_format);
|
flags, internal_format);
|
||||||
|
|
||||||
|
/* Keep a copy of the first pixel so that if glGenerateMipmap isn't
|
||||||
|
supported we can fallback to using GL_GENERATE_MIPMAP */
|
||||||
|
tex_3d->first_pixel.gl_format = gl_format;
|
||||||
|
tex_3d->first_pixel.gl_type = gl_type;
|
||||||
|
memcpy (tex_3d->first_pixel.data, dst_bmp.data,
|
||||||
|
_cogl_get_format_bpp (dst_bmp.format));
|
||||||
|
|
||||||
_cogl_texture_driver_gen (GL_TEXTURE_3D, 1, &tex_3d->gl_texture);
|
_cogl_texture_driver_gen (GL_TEXTURE_3D, 1, &tex_3d->gl_texture);
|
||||||
|
|
||||||
_cogl_texture_driver_upload_to_gl_3d (GL_TEXTURE_3D,
|
_cogl_texture_driver_upload_to_gl_3d (GL_TEXTURE_3D,
|
||||||
@ -565,10 +558,31 @@ _cogl_texture_3d_pre_paint (CoglTexture *tex, CoglTexturePrePaintFlags flags)
|
|||||||
_cogl_bind_gl_texture_transient (GL_TEXTURE_3D,
|
_cogl_bind_gl_texture_transient (GL_TEXTURE_3D,
|
||||||
tex_3d->gl_texture,
|
tex_3d->gl_texture,
|
||||||
FALSE);
|
FALSE);
|
||||||
/* glGenerateMipmap is defined in the FBO extension. We only allow
|
/* glGenerateMipmap is defined in the FBO extension. If it's not
|
||||||
CoglTexture3D instances to be created if this feature is
|
available we'll fallback to temporarily enabling
|
||||||
available so we don't need to check for the extension */
|
GL_GENERATE_MIPMAP and reuploading the first pixel */
|
||||||
_cogl_texture_driver_gl_generate_mipmaps (GL_TEXTURE_3D);
|
if (cogl_features_available (COGL_FEATURE_OFFSCREEN))
|
||||||
|
_cogl_texture_driver_gl_generate_mipmaps (GL_TEXTURE_3D);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GE( glTexParameteri (GL_TEXTURE_3D,
|
||||||
|
GL_GENERATE_MIPMAP,
|
||||||
|
GL_TRUE) );
|
||||||
|
GE( glTexSubImage3D (GL_TEXTURE_3D,
|
||||||
|
0, /* level */
|
||||||
|
0, /* xoffset */
|
||||||
|
0, /* yoffset */
|
||||||
|
0, /* zoffset */
|
||||||
|
1, /* width */
|
||||||
|
1, /* height */
|
||||||
|
1, /* depth */
|
||||||
|
tex_3d->first_pixel.gl_format,
|
||||||
|
tex_3d->first_pixel.gl_type,
|
||||||
|
tex_3d->first_pixel.data) );
|
||||||
|
GE( glTexParameteri (GL_TEXTURE_3D,
|
||||||
|
GL_GENERATE_MIPMAP,
|
||||||
|
GL_FALSE) );
|
||||||
|
}
|
||||||
|
|
||||||
tex_3d->mipmaps_dirty = FALSE;
|
tex_3d->mipmaps_dirty = FALSE;
|
||||||
}
|
}
|
||||||
|
@ -151,6 +151,22 @@ typedef enum _CoglTextureChangeFlags
|
|||||||
|
|
||||||
} CoglTextureChangeFlags;
|
} CoglTextureChangeFlags;
|
||||||
|
|
||||||
|
typedef struct _CoglTexturePixel CoglTexturePixel;
|
||||||
|
|
||||||
|
/* This is used by the texture backends to store the first pixel of
|
||||||
|
each GL texture. This is only used when glGenerateMipmap is not
|
||||||
|
available so that we can temporarily set GL_GENERATE_MIPMAP and
|
||||||
|
reupload a pixel */
|
||||||
|
struct _CoglTexturePixel
|
||||||
|
{
|
||||||
|
/* We need to store the format of the pixel because we store the
|
||||||
|
data in the source format which might end up being different for
|
||||||
|
each slice if a subregion is updated with a different format */
|
||||||
|
GLenum gl_format;
|
||||||
|
GLenum gl_type;
|
||||||
|
guint8 data[4];
|
||||||
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_texture_free (CoglTexture *texture);
|
_cogl_texture_free (CoglTexture *texture);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user