cogl/driver: Move various texture functions to TextureDriverGL
As they are now shared between GL3 and GLES3 texture driver, there is no need anymore for having them in a separate header and included. Cleanup the names of the functions while doing so. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4163>
This commit is contained in:
parent
1401c745d7
commit
a2fdeac9e7
@ -36,27 +36,7 @@
|
||||
#include "cogl/cogl-types.h"
|
||||
#include "cogl/cogl-context-private.h"
|
||||
#include "cogl/cogl-texture.h"
|
||||
#include "cogl/cogl-texture-driver.h"
|
||||
|
||||
void
|
||||
_cogl_texture_2d_gl_free (CoglTextureDriver *driver,
|
||||
CoglTexture2D *tex_2d);
|
||||
|
||||
gboolean
|
||||
_cogl_texture_2d_gl_can_create (CoglTextureDriver *driver,
|
||||
CoglContext *ctx,
|
||||
int width,
|
||||
int height,
|
||||
CoglPixelFormat internal_format);
|
||||
|
||||
void
|
||||
_cogl_texture_2d_gl_init (CoglTextureDriver *driver,
|
||||
CoglTexture2D *tex_2d);
|
||||
|
||||
gboolean
|
||||
_cogl_texture_2d_gl_allocate (CoglTextureDriver *driver,
|
||||
CoglTexture *tex,
|
||||
GError **error);
|
||||
|
||||
#if defined (HAVE_EGL)
|
||||
gboolean
|
||||
@ -74,36 +54,3 @@ void
|
||||
_cogl_texture_2d_gl_flush_legacy_texobj_wrap_modes (CoglTexture *tex,
|
||||
GLenum wrap_mode_s,
|
||||
GLenum wrap_mode_t);
|
||||
|
||||
void
|
||||
_cogl_texture_2d_gl_copy_from_framebuffer (CoglTextureDriver *driver,
|
||||
CoglTexture2D *tex_2d,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int width,
|
||||
int height,
|
||||
CoglFramebuffer *src_fb,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
int level);
|
||||
|
||||
unsigned int
|
||||
_cogl_texture_2d_gl_get_gl_handle (CoglTextureDriver *driver,
|
||||
CoglTexture2D *tex_2d);
|
||||
|
||||
void
|
||||
_cogl_texture_2d_gl_generate_mipmap (CoglTextureDriver *driver,
|
||||
CoglTexture2D *tex_2d);
|
||||
|
||||
gboolean
|
||||
_cogl_texture_2d_gl_copy_from_bitmap (CoglTextureDriver *driver,
|
||||
CoglTexture2D *tex_2d,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int width,
|
||||
int height,
|
||||
CoglBitmap *bitmap,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
int level,
|
||||
GError **error);
|
||||
|
@ -45,335 +45,6 @@
|
||||
#include "cogl/driver/gl/cogl-util-gl-private.h"
|
||||
|
||||
#if defined (HAVE_EGL)
|
||||
|
||||
/* We need this define from GLES2, but can't include the header
|
||||
as its type definitions may conflict with the GL ones
|
||||
*/
|
||||
#ifndef GL_OES_EGL_image_external
|
||||
#define GL_OES_EGL_image_external 1
|
||||
#define GL_TEXTURE_EXTERNAL_OES 0x8D65
|
||||
#define GL_TEXTURE_BINDING_EXTERNAL_OES 0x8D67
|
||||
#define GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES 0x8D68
|
||||
#define GL_SAMPLER_EXTERNAL_OES 0x8D66
|
||||
#endif /* GL_OES_EGL_image_external */
|
||||
|
||||
#endif /* defined (HAVE_EGL) */
|
||||
|
||||
void
|
||||
_cogl_texture_2d_gl_free (CoglTextureDriver *driver,
|
||||
CoglTexture2D *tex_2d)
|
||||
{
|
||||
if (tex_2d->gl_texture)
|
||||
_cogl_delete_gl_texture (cogl_texture_get_context (COGL_TEXTURE (tex_2d)),
|
||||
tex_2d->gl_texture);
|
||||
|
||||
#if defined (HAVE_EGL)
|
||||
g_clear_pointer (&tex_2d->egl_image_external.user_data,
|
||||
tex_2d->egl_image_external.destroy);
|
||||
#endif
|
||||
}
|
||||
|
||||
gboolean
|
||||
_cogl_texture_2d_gl_can_create (CoglTextureDriver *driver,
|
||||
CoglContext *ctx,
|
||||
int width,
|
||||
int height,
|
||||
CoglPixelFormat internal_format)
|
||||
{
|
||||
CoglTextureDriverClass *tex_driver =
|
||||
COGL_TEXTURE_DRIVER_GET_CLASS (ctx->texture_driver);
|
||||
GLenum gl_intformat;
|
||||
GLenum gl_format;
|
||||
GLenum gl_type;
|
||||
|
||||
/* We only support single plane formats for now */
|
||||
if (cogl_pixel_format_get_n_planes (internal_format) != 1)
|
||||
return FALSE;
|
||||
|
||||
ctx->driver_vtable->pixel_format_to_gl (ctx,
|
||||
internal_format,
|
||||
&gl_intformat,
|
||||
&gl_format,
|
||||
&gl_type);
|
||||
|
||||
/* Check that the driver can create a texture with that size */
|
||||
if (!tex_driver->size_supported (ctx->texture_driver,
|
||||
ctx,
|
||||
GL_TEXTURE_2D,
|
||||
gl_intformat,
|
||||
gl_format,
|
||||
gl_type,
|
||||
width,
|
||||
height))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_texture_2d_gl_init (CoglTextureDriver *driver,
|
||||
CoglTexture2D *tex_2d)
|
||||
{
|
||||
tex_2d->gl_texture = 0;
|
||||
|
||||
/* We default to GL_LINEAR for both filters */
|
||||
tex_2d->gl_legacy_texobj_min_filter = GL_LINEAR;
|
||||
tex_2d->gl_legacy_texobj_mag_filter = GL_LINEAR;
|
||||
|
||||
/* Wrap mode not yet set */
|
||||
tex_2d->gl_legacy_texobj_wrap_mode_s = GL_FALSE;
|
||||
tex_2d->gl_legacy_texobj_wrap_mode_t = GL_FALSE;
|
||||
|
||||
tex_2d->egl_image_external.user_data = NULL;
|
||||
tex_2d->egl_image_external.destroy = NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
allocate_with_size (CoglTexture2D *tex_2d,
|
||||
CoglTextureLoader *loader,
|
||||
GError **error)
|
||||
{
|
||||
CoglTexture *tex = COGL_TEXTURE (tex_2d);
|
||||
CoglPixelFormat internal_format;
|
||||
int width = loader->src.sized.width;
|
||||
int height = loader->src.sized.height;
|
||||
CoglContext *ctx = cogl_texture_get_context (tex);
|
||||
CoglTextureDriverClass *tex_driver =
|
||||
COGL_TEXTURE_DRIVER_GET_CLASS (ctx->texture_driver);
|
||||
GLenum gl_intformat;
|
||||
GLenum gl_format;
|
||||
GLenum gl_type;
|
||||
GLenum gl_texture;
|
||||
|
||||
internal_format =
|
||||
_cogl_texture_determine_internal_format (tex, loader->src.sized.format);
|
||||
|
||||
if (!_cogl_texture_2d_gl_can_create (ctx->texture_driver,
|
||||
ctx,
|
||||
width,
|
||||
height,
|
||||
internal_format))
|
||||
{
|
||||
g_set_error_literal (error, COGL_TEXTURE_ERROR,
|
||||
COGL_TEXTURE_ERROR_SIZE,
|
||||
"Failed to create texture 2d due to size/format"
|
||||
" constraints");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ctx->driver_vtable->pixel_format_to_gl (ctx,
|
||||
internal_format,
|
||||
&gl_intformat,
|
||||
&gl_format,
|
||||
&gl_type);
|
||||
|
||||
gl_texture = tex_driver->gen (ctx->texture_driver,
|
||||
ctx,
|
||||
GL_TEXTURE_2D,
|
||||
internal_format);
|
||||
|
||||
tex_2d->gl_internal_format = gl_intformat;
|
||||
|
||||
_cogl_bind_gl_texture_transient (ctx, GL_TEXTURE_2D,
|
||||
gl_texture);
|
||||
|
||||
/* Clear any GL errors */
|
||||
_cogl_gl_util_clear_gl_errors (ctx);
|
||||
|
||||
ctx->glTexImage2D (GL_TEXTURE_2D, 0, gl_intformat,
|
||||
width, height, 0, gl_format, gl_type, NULL);
|
||||
|
||||
if (_cogl_gl_util_catch_out_of_memory (ctx, error))
|
||||
{
|
||||
GE( ctx, glDeleteTextures (1, &gl_texture) );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
tex_2d->gl_texture = gl_texture;
|
||||
tex_2d->gl_internal_format = gl_intformat;
|
||||
|
||||
tex_2d->internal_format = internal_format;
|
||||
|
||||
_cogl_texture_set_allocated (tex, internal_format, width, height);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
allocate_from_bitmap (CoglTexture2D *tex_2d,
|
||||
CoglTextureLoader *loader,
|
||||
GError **error)
|
||||
{
|
||||
CoglTexture *tex = COGL_TEXTURE (tex_2d);
|
||||
CoglBitmap *bmp = loader->src.bitmap.bitmap;
|
||||
CoglContext *ctx = _cogl_bitmap_get_context (bmp);
|
||||
CoglTextureDriverClass *tex_driver =
|
||||
COGL_TEXTURE_DRIVER_GET_CLASS (ctx->texture_driver);
|
||||
CoglPixelFormat internal_format;
|
||||
int width = cogl_bitmap_get_width (bmp);
|
||||
int height = cogl_bitmap_get_height (bmp);
|
||||
CoglBitmap *upload_bmp;
|
||||
GLenum gl_intformat;
|
||||
GLenum gl_format;
|
||||
GLenum gl_type;
|
||||
|
||||
internal_format =
|
||||
_cogl_texture_determine_internal_format (tex, cogl_bitmap_get_format (bmp));
|
||||
|
||||
if (!_cogl_texture_2d_gl_can_create (ctx->texture_driver,
|
||||
ctx,
|
||||
width,
|
||||
height,
|
||||
internal_format))
|
||||
{
|
||||
g_set_error_literal (error, COGL_TEXTURE_ERROR,
|
||||
COGL_TEXTURE_ERROR_SIZE,
|
||||
"Failed to create texture 2d due to size/format"
|
||||
" constraints");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
upload_bmp = _cogl_bitmap_convert_for_upload (bmp,
|
||||
internal_format,
|
||||
error);
|
||||
if (upload_bmp == NULL)
|
||||
return FALSE;
|
||||
|
||||
ctx->driver_vtable->pixel_format_to_gl (ctx,
|
||||
cogl_bitmap_get_format (upload_bmp),
|
||||
NULL, /* internal format */
|
||||
&gl_format,
|
||||
&gl_type);
|
||||
ctx->driver_vtable->pixel_format_to_gl (ctx,
|
||||
internal_format,
|
||||
&gl_intformat,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
tex_2d->gl_texture = tex_driver->gen (ctx->texture_driver,
|
||||
ctx,
|
||||
GL_TEXTURE_2D,
|
||||
internal_format);
|
||||
if (!tex_driver->upload_to_gl (ctx->texture_driver,
|
||||
ctx,
|
||||
GL_TEXTURE_2D,
|
||||
tex_2d->gl_texture,
|
||||
upload_bmp,
|
||||
gl_intformat,
|
||||
gl_format,
|
||||
gl_type,
|
||||
error))
|
||||
{
|
||||
g_object_unref (upload_bmp);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
tex_2d->gl_internal_format = gl_intformat;
|
||||
|
||||
g_object_unref (upload_bmp);
|
||||
|
||||
tex_2d->internal_format = internal_format;
|
||||
|
||||
_cogl_texture_set_allocated (tex, internal_format, width, height);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#if defined (HAVE_EGL) && defined (EGL_KHR_image_base)
|
||||
static gboolean
|
||||
allocate_from_egl_image (CoglTexture2D *tex_2d,
|
||||
CoglTextureLoader *loader,
|
||||
GError **error)
|
||||
{
|
||||
CoglTexture *tex = COGL_TEXTURE (tex_2d);
|
||||
CoglContext *ctx = cogl_texture_get_context (tex);
|
||||
CoglPixelFormat internal_format = loader->src.egl_image.format;
|
||||
CoglTextureDriverClass *tex_driver =
|
||||
COGL_TEXTURE_DRIVER_GET_CLASS (ctx->texture_driver);
|
||||
|
||||
tex_2d->gl_texture = tex_driver->gen (ctx->texture_driver,
|
||||
ctx,
|
||||
GL_TEXTURE_2D,
|
||||
internal_format);
|
||||
|
||||
if (!cogl_texture_2d_gl_bind_egl_image (tex_2d,
|
||||
loader->src.egl_image.image,
|
||||
error))
|
||||
{
|
||||
GE( ctx, glDeleteTextures (1, &tex_2d->gl_texture) );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
tex_2d->internal_format = internal_format;
|
||||
tex_2d->is_get_data_supported =
|
||||
!(loader->src.egl_image.flags & COGL_EGL_IMAGE_FLAG_NO_GET_DATA);
|
||||
|
||||
_cogl_texture_set_allocated (tex,
|
||||
internal_format,
|
||||
loader->src.egl_image.width,
|
||||
loader->src.egl_image.height);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_EGL)
|
||||
static gboolean
|
||||
allocate_custom_egl_image_external (CoglTexture2D *tex_2d,
|
||||
CoglTextureLoader *loader,
|
||||
GError **error)
|
||||
{
|
||||
CoglTexture *tex = COGL_TEXTURE (tex_2d);
|
||||
CoglContext *ctx = cogl_texture_get_context (tex);
|
||||
CoglPixelFormat external_format;
|
||||
CoglPixelFormat internal_format;
|
||||
|
||||
external_format = loader->src.egl_image_external.format;
|
||||
internal_format = _cogl_texture_determine_internal_format (tex,
|
||||
external_format);
|
||||
|
||||
_cogl_gl_util_clear_gl_errors (ctx);
|
||||
|
||||
GE (ctx, glActiveTexture (GL_TEXTURE0));
|
||||
GE (ctx, glGenTextures (1, &tex_2d->gl_texture));
|
||||
|
||||
GE (ctx, glBindTexture (GL_TEXTURE_EXTERNAL_OES,
|
||||
tex_2d->gl_texture));
|
||||
|
||||
if (_cogl_gl_util_get_error (ctx) != GL_NO_ERROR)
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
COGL_TEXTURE_ERROR,
|
||||
COGL_TEXTURE_ERROR_BAD_PARAMETER,
|
||||
"Could not create a CoglTexture2D from a given "
|
||||
"EGLImage");
|
||||
GE( ctx, glDeleteTextures (1, &tex_2d->gl_texture) );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GE (ctx, glTexParameteri(GL_TEXTURE_EXTERNAL_OES,
|
||||
GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
|
||||
GE (ctx, glTexParameteri(GL_TEXTURE_EXTERNAL_OES,
|
||||
GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
|
||||
|
||||
if (!loader->src.egl_image_external.alloc (tex_2d,
|
||||
tex_2d->egl_image_external.user_data,
|
||||
error))
|
||||
{
|
||||
GE (ctx, glBindTexture (GL_TEXTURE_EXTERNAL_OES, 0));
|
||||
GE (ctx, glDeleteTextures (1, &tex_2d->gl_texture));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GE (ctx, glBindTexture (GL_TEXTURE_EXTERNAL_OES, 0));
|
||||
|
||||
tex_2d->internal_format = internal_format;
|
||||
tex_2d->gl_target = GL_TEXTURE_EXTERNAL_OES;
|
||||
tex_2d->is_get_data_supported = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
cogl_texture_2d_gl_bind_egl_image (CoglTexture2D *tex_2d,
|
||||
EGLImageKHR image,
|
||||
@ -438,39 +109,6 @@ cogl_texture_2d_new_from_egl_image_external (CoglContext *ctx,
|
||||
}
|
||||
#endif /* defined (HAVE_EGL) */
|
||||
|
||||
gboolean
|
||||
_cogl_texture_2d_gl_allocate (CoglTextureDriver *driver,
|
||||
CoglTexture *tex,
|
||||
GError **error)
|
||||
{
|
||||
CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex);
|
||||
CoglTextureLoader *loader = cogl_texture_get_loader (tex);
|
||||
|
||||
g_return_val_if_fail (loader, FALSE);
|
||||
|
||||
switch (loader->src_type)
|
||||
{
|
||||
case COGL_TEXTURE_SOURCE_TYPE_SIZE:
|
||||
return allocate_with_size (tex_2d, loader, error);
|
||||
case COGL_TEXTURE_SOURCE_TYPE_BITMAP:
|
||||
return allocate_from_bitmap (tex_2d, loader, error);
|
||||
case COGL_TEXTURE_SOURCE_TYPE_EGL_IMAGE:
|
||||
#if defined (HAVE_EGL) && defined (EGL_KHR_image_base)
|
||||
return allocate_from_egl_image (tex_2d, loader, error);
|
||||
#else
|
||||
g_return_val_if_reached (FALSE);
|
||||
#endif
|
||||
case COGL_TEXTURE_SOURCE_TYPE_EGL_IMAGE_EXTERNAL:
|
||||
#if defined (HAVE_EGL)
|
||||
return allocate_custom_egl_image_external (tex_2d, loader, error);
|
||||
#else
|
||||
g_return_val_if_reached (FALSE);
|
||||
#endif
|
||||
}
|
||||
|
||||
g_return_val_if_reached (FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_texture_2d_gl_flush_legacy_texobj_filters (CoglTexture *tex,
|
||||
GLenum min_filter,
|
||||
@ -530,114 +168,3 @@ _cogl_texture_2d_gl_flush_legacy_texobj_wrap_modes (CoglTexture *tex,
|
||||
tex_2d->gl_legacy_texobj_wrap_mode_t = wrap_mode_t;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_texture_2d_gl_copy_from_framebuffer (CoglTextureDriver *driver,
|
||||
CoglTexture2D *tex_2d,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int width,
|
||||
int height,
|
||||
CoglFramebuffer *src_fb,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
int level)
|
||||
{
|
||||
CoglTexture *tex = COGL_TEXTURE (tex_2d);
|
||||
CoglContext *ctx = cogl_texture_get_context (tex);
|
||||
|
||||
/* Make sure the current framebuffers are bound, though we don't need to
|
||||
* flush the clip state here since we aren't going to draw to the
|
||||
* framebuffer. */
|
||||
cogl_context_flush_framebuffer_state (ctx,
|
||||
ctx->current_draw_buffer,
|
||||
src_fb,
|
||||
(COGL_FRAMEBUFFER_STATE_ALL &
|
||||
~COGL_FRAMEBUFFER_STATE_CLIP));
|
||||
|
||||
_cogl_bind_gl_texture_transient (ctx, GL_TEXTURE_2D,
|
||||
tex_2d->gl_texture);
|
||||
|
||||
ctx->glCopyTexSubImage2D (GL_TEXTURE_2D,
|
||||
0, /* level */
|
||||
dst_x, dst_y,
|
||||
src_x, src_y,
|
||||
width, height);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
_cogl_texture_2d_gl_get_gl_handle (CoglTextureDriver *driver,
|
||||
CoglTexture2D *tex_2d)
|
||||
{
|
||||
return tex_2d->gl_texture;
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_texture_2d_gl_generate_mipmap (CoglTextureDriver *driver,
|
||||
CoglTexture2D *tex_2d)
|
||||
{
|
||||
_cogl_texture_gl_generate_mipmaps (COGL_TEXTURE (tex_2d));
|
||||
}
|
||||
|
||||
gboolean
|
||||
_cogl_texture_2d_gl_copy_from_bitmap (CoglTextureDriver *driver,
|
||||
CoglTexture2D *tex_2d,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int width,
|
||||
int height,
|
||||
CoglBitmap *bmp,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
int level,
|
||||
GError **error)
|
||||
{
|
||||
CoglTexture *tex = COGL_TEXTURE (tex_2d);
|
||||
CoglContext *ctx = cogl_texture_get_context (tex);
|
||||
CoglTextureDriverClass *tex_driver =
|
||||
COGL_TEXTURE_DRIVER_GET_CLASS (ctx->texture_driver);
|
||||
CoglBitmap *upload_bmp;
|
||||
CoglPixelFormat upload_format;
|
||||
GLenum gl_format;
|
||||
GLenum gl_type;
|
||||
gboolean status = TRUE;
|
||||
|
||||
upload_bmp =
|
||||
_cogl_bitmap_convert_for_upload (bmp,
|
||||
cogl_texture_get_format (tex),
|
||||
error);
|
||||
if (upload_bmp == NULL)
|
||||
return FALSE;
|
||||
|
||||
upload_format = cogl_bitmap_get_format (upload_bmp);
|
||||
|
||||
/* Only support single plane formats */
|
||||
if (upload_format == COGL_PIXEL_FORMAT_ANY ||
|
||||
cogl_pixel_format_get_n_planes (upload_format) != 1)
|
||||
return FALSE;
|
||||
|
||||
ctx->driver_vtable->pixel_format_to_gl (ctx,
|
||||
upload_format,
|
||||
NULL, /* internal gl format */
|
||||
&gl_format,
|
||||
&gl_type);
|
||||
|
||||
if (cogl_texture_get_max_level_set (tex) < level)
|
||||
cogl_texture_gl_set_max_level (tex, level);
|
||||
|
||||
status = tex_driver->upload_subregion_to_gl (ctx->texture_driver,
|
||||
ctx,
|
||||
tex,
|
||||
src_x, src_y,
|
||||
dst_x, dst_y,
|
||||
width, height,
|
||||
level,
|
||||
upload_bmp,
|
||||
gl_format,
|
||||
gl_type,
|
||||
error);
|
||||
|
||||
g_object_unref (upload_bmp);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -28,24 +28,497 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "cogl/driver/gl/cogl-pipeline-opengl-private.h"
|
||||
#include "cogl/driver/gl/cogl-texture-driver-gl-private.h"
|
||||
#include "cogl/driver/gl/cogl-texture-2d-gl-private.h"
|
||||
#include "cogl/driver/gl/cogl-texture-gl-private.h"
|
||||
#include "cogl/driver/gl/cogl-util-gl-private.h"
|
||||
#include "cogl/cogl-texture-2d-private.h"
|
||||
|
||||
#if defined (HAVE_EGL)
|
||||
/* We need this define from GLES2, but can't include the header
|
||||
as its type definitions may conflict with the GL ones
|
||||
*/
|
||||
#define GL_TEXTURE_EXTERNAL_OES 0x8D65
|
||||
#endif /* defined (HAVE_EGL) */
|
||||
|
||||
|
||||
|
||||
G_DEFINE_TYPE (CoglTextureDriverGL, cogl_texture_driver_gl, COGL_TYPE_TEXTURE_DRIVER)
|
||||
|
||||
static void
|
||||
cogl_texture_driver_gl_texture_2d_free (CoglTextureDriver *driver,
|
||||
CoglTexture2D *tex_2d)
|
||||
{
|
||||
if (tex_2d->gl_texture)
|
||||
_cogl_delete_gl_texture (cogl_texture_get_context (COGL_TEXTURE (tex_2d)),
|
||||
tex_2d->gl_texture);
|
||||
|
||||
#if defined (HAVE_EGL)
|
||||
g_clear_pointer (&tex_2d->egl_image_external.user_data,
|
||||
tex_2d->egl_image_external.destroy);
|
||||
#endif
|
||||
}
|
||||
|
||||
static gboolean
|
||||
cogl_texture_driver_gl_texture_2d_can_create (CoglTextureDriver *driver,
|
||||
CoglContext *ctx,
|
||||
int width,
|
||||
int height,
|
||||
CoglPixelFormat internal_format)
|
||||
{
|
||||
CoglTextureDriverClass *tex_driver =
|
||||
COGL_TEXTURE_DRIVER_GET_CLASS (ctx->texture_driver);
|
||||
GLenum gl_intformat;
|
||||
GLenum gl_format;
|
||||
GLenum gl_type;
|
||||
|
||||
/* We only support single plane formats for now */
|
||||
if (cogl_pixel_format_get_n_planes (internal_format) != 1)
|
||||
return FALSE;
|
||||
|
||||
ctx->driver_vtable->pixel_format_to_gl (ctx,
|
||||
internal_format,
|
||||
&gl_intformat,
|
||||
&gl_format,
|
||||
&gl_type);
|
||||
|
||||
/* Check that the driver can create a texture with that size */
|
||||
if (!tex_driver->size_supported (ctx->texture_driver,
|
||||
ctx,
|
||||
GL_TEXTURE_2D,
|
||||
gl_intformat,
|
||||
gl_format,
|
||||
gl_type,
|
||||
width,
|
||||
height))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
allocate_with_size (CoglTexture2D *tex_2d,
|
||||
CoglTextureLoader *loader,
|
||||
GError **error)
|
||||
{
|
||||
CoglTexture *tex = COGL_TEXTURE (tex_2d);
|
||||
CoglPixelFormat internal_format;
|
||||
int width = loader->src.sized.width;
|
||||
int height = loader->src.sized.height;
|
||||
CoglContext *ctx = cogl_texture_get_context (tex);
|
||||
CoglTextureDriverClass *tex_driver =
|
||||
COGL_TEXTURE_DRIVER_GET_CLASS (ctx->texture_driver);
|
||||
GLenum gl_intformat;
|
||||
GLenum gl_format;
|
||||
GLenum gl_type;
|
||||
GLenum gl_texture;
|
||||
|
||||
internal_format =
|
||||
_cogl_texture_determine_internal_format (tex, loader->src.sized.format);
|
||||
|
||||
if (!cogl_texture_driver_gl_texture_2d_can_create (ctx->texture_driver,
|
||||
ctx,
|
||||
width,
|
||||
height,
|
||||
internal_format))
|
||||
{
|
||||
g_set_error_literal (error, COGL_TEXTURE_ERROR,
|
||||
COGL_TEXTURE_ERROR_SIZE,
|
||||
"Failed to create texture 2d due to size/format"
|
||||
" constraints");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ctx->driver_vtable->pixel_format_to_gl (ctx,
|
||||
internal_format,
|
||||
&gl_intformat,
|
||||
&gl_format,
|
||||
&gl_type);
|
||||
|
||||
gl_texture = tex_driver->gen (ctx->texture_driver,
|
||||
ctx,
|
||||
GL_TEXTURE_2D,
|
||||
internal_format);
|
||||
|
||||
tex_2d->gl_internal_format = gl_intformat;
|
||||
|
||||
_cogl_bind_gl_texture_transient (ctx, GL_TEXTURE_2D,
|
||||
gl_texture);
|
||||
|
||||
/* Clear any GL errors */
|
||||
_cogl_gl_util_clear_gl_errors (ctx);
|
||||
|
||||
ctx->glTexImage2D (GL_TEXTURE_2D, 0, gl_intformat,
|
||||
width, height, 0, gl_format, gl_type, NULL);
|
||||
|
||||
if (_cogl_gl_util_catch_out_of_memory (ctx, error))
|
||||
{
|
||||
GE ( ctx, glDeleteTextures (1, &gl_texture) );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
tex_2d->gl_texture = gl_texture;
|
||||
tex_2d->gl_internal_format = gl_intformat;
|
||||
|
||||
tex_2d->internal_format = internal_format;
|
||||
|
||||
_cogl_texture_set_allocated (tex, internal_format, width, height);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
allocate_from_bitmap (CoglTexture2D *tex_2d,
|
||||
CoglTextureLoader *loader,
|
||||
GError **error)
|
||||
{
|
||||
CoglTexture *tex = COGL_TEXTURE (tex_2d);
|
||||
CoglBitmap *bmp = loader->src.bitmap.bitmap;
|
||||
CoglContext *ctx = _cogl_bitmap_get_context (bmp);
|
||||
CoglTextureDriverClass *tex_driver =
|
||||
COGL_TEXTURE_DRIVER_GET_CLASS (ctx->texture_driver);
|
||||
CoglPixelFormat internal_format;
|
||||
int width = cogl_bitmap_get_width (bmp);
|
||||
int height = cogl_bitmap_get_height (bmp);
|
||||
CoglBitmap *upload_bmp;
|
||||
GLenum gl_intformat;
|
||||
GLenum gl_format;
|
||||
GLenum gl_type;
|
||||
|
||||
internal_format =
|
||||
_cogl_texture_determine_internal_format (tex, cogl_bitmap_get_format (bmp));
|
||||
|
||||
if (!cogl_texture_driver_gl_texture_2d_can_create (ctx->texture_driver,
|
||||
ctx,
|
||||
width,
|
||||
height,
|
||||
internal_format))
|
||||
{
|
||||
g_set_error_literal (error, COGL_TEXTURE_ERROR,
|
||||
COGL_TEXTURE_ERROR_SIZE,
|
||||
"Failed to create texture 2d due to size/format"
|
||||
" constraints");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
upload_bmp = _cogl_bitmap_convert_for_upload (bmp,
|
||||
internal_format,
|
||||
error);
|
||||
if (upload_bmp == NULL)
|
||||
return FALSE;
|
||||
|
||||
ctx->driver_vtable->pixel_format_to_gl (ctx,
|
||||
cogl_bitmap_get_format (upload_bmp),
|
||||
NULL, /* internal format */
|
||||
&gl_format,
|
||||
&gl_type);
|
||||
ctx->driver_vtable->pixel_format_to_gl (ctx,
|
||||
internal_format,
|
||||
&gl_intformat,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
tex_2d->gl_texture = tex_driver->gen (ctx->texture_driver,
|
||||
ctx,
|
||||
GL_TEXTURE_2D,
|
||||
internal_format);
|
||||
if (!tex_driver->upload_to_gl (ctx->texture_driver,
|
||||
ctx,
|
||||
GL_TEXTURE_2D,
|
||||
tex_2d->gl_texture,
|
||||
upload_bmp,
|
||||
gl_intformat,
|
||||
gl_format,
|
||||
gl_type,
|
||||
error))
|
||||
{
|
||||
g_object_unref (upload_bmp);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
tex_2d->gl_internal_format = gl_intformat;
|
||||
|
||||
g_object_unref (upload_bmp);
|
||||
|
||||
tex_2d->internal_format = internal_format;
|
||||
|
||||
_cogl_texture_set_allocated (tex, internal_format, width, height);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#if defined (HAVE_EGL) && defined (EGL_KHR_image_base)
|
||||
static gboolean
|
||||
allocate_from_egl_image (CoglTexture2D *tex_2d,
|
||||
CoglTextureLoader *loader,
|
||||
GError **error)
|
||||
{
|
||||
CoglTexture *tex = COGL_TEXTURE (tex_2d);
|
||||
CoglContext *ctx = cogl_texture_get_context (tex);
|
||||
CoglPixelFormat internal_format = loader->src.egl_image.format;
|
||||
CoglTextureDriverClass *tex_driver =
|
||||
COGL_TEXTURE_DRIVER_GET_CLASS (ctx->texture_driver);
|
||||
|
||||
tex_2d->gl_texture = tex_driver->gen (ctx->texture_driver,
|
||||
ctx,
|
||||
GL_TEXTURE_2D,
|
||||
internal_format);
|
||||
|
||||
if (!cogl_texture_2d_gl_bind_egl_image (tex_2d,
|
||||
loader->src.egl_image.image,
|
||||
error))
|
||||
{
|
||||
GE ( ctx, glDeleteTextures (1, &tex_2d->gl_texture) );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
tex_2d->internal_format = internal_format;
|
||||
tex_2d->is_get_data_supported =
|
||||
!(loader->src.egl_image.flags & COGL_EGL_IMAGE_FLAG_NO_GET_DATA);
|
||||
|
||||
_cogl_texture_set_allocated (tex,
|
||||
internal_format,
|
||||
loader->src.egl_image.width,
|
||||
loader->src.egl_image.height);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_EGL)
|
||||
static gboolean
|
||||
allocate_custom_egl_image_external (CoglTexture2D *tex_2d,
|
||||
CoglTextureLoader *loader,
|
||||
GError **error)
|
||||
{
|
||||
CoglTexture *tex = COGL_TEXTURE (tex_2d);
|
||||
CoglContext *ctx = cogl_texture_get_context (tex);
|
||||
CoglPixelFormat external_format;
|
||||
CoglPixelFormat internal_format;
|
||||
|
||||
external_format = loader->src.egl_image_external.format;
|
||||
internal_format = _cogl_texture_determine_internal_format (tex,
|
||||
external_format);
|
||||
|
||||
_cogl_gl_util_clear_gl_errors (ctx);
|
||||
|
||||
GE (ctx, glActiveTexture (GL_TEXTURE0));
|
||||
GE (ctx, glGenTextures (1, &tex_2d->gl_texture));
|
||||
|
||||
GE (ctx, glBindTexture (GL_TEXTURE_EXTERNAL_OES,
|
||||
tex_2d->gl_texture));
|
||||
|
||||
if (_cogl_gl_util_get_error (ctx) != GL_NO_ERROR)
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
COGL_TEXTURE_ERROR,
|
||||
COGL_TEXTURE_ERROR_BAD_PARAMETER,
|
||||
"Could not create a CoglTexture2D from a given "
|
||||
"EGLImage");
|
||||
GE ( ctx, glDeleteTextures (1, &tex_2d->gl_texture) );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GE (ctx, glTexParameteri (GL_TEXTURE_EXTERNAL_OES,
|
||||
GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
|
||||
GE (ctx, glTexParameteri (GL_TEXTURE_EXTERNAL_OES,
|
||||
GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
|
||||
|
||||
if (!loader->src.egl_image_external.alloc (tex_2d,
|
||||
tex_2d->egl_image_external.user_data,
|
||||
error))
|
||||
{
|
||||
GE (ctx, glBindTexture (GL_TEXTURE_EXTERNAL_OES, 0));
|
||||
GE (ctx, glDeleteTextures (1, &tex_2d->gl_texture));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GE (ctx, glBindTexture (GL_TEXTURE_EXTERNAL_OES, 0));
|
||||
|
||||
tex_2d->internal_format = internal_format;
|
||||
tex_2d->gl_target = GL_TEXTURE_EXTERNAL_OES;
|
||||
tex_2d->is_get_data_supported = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
cogl_texture_driver_gl_texture_2d_allocate (CoglTextureDriver *driver,
|
||||
CoglTexture *tex,
|
||||
GError **error)
|
||||
{
|
||||
CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex);
|
||||
CoglTextureLoader *loader = cogl_texture_get_loader (tex);
|
||||
|
||||
g_return_val_if_fail (loader, FALSE);
|
||||
|
||||
switch (loader->src_type)
|
||||
{
|
||||
case COGL_TEXTURE_SOURCE_TYPE_SIZE:
|
||||
return allocate_with_size (tex_2d, loader, error);
|
||||
case COGL_TEXTURE_SOURCE_TYPE_BITMAP:
|
||||
return allocate_from_bitmap (tex_2d, loader, error);
|
||||
case COGL_TEXTURE_SOURCE_TYPE_EGL_IMAGE:
|
||||
#if defined (HAVE_EGL) && defined (EGL_KHR_image_base)
|
||||
return allocate_from_egl_image (tex_2d, loader, error);
|
||||
#else
|
||||
g_return_val_if_reached (FALSE);
|
||||
#endif
|
||||
case COGL_TEXTURE_SOURCE_TYPE_EGL_IMAGE_EXTERNAL:
|
||||
#if defined (HAVE_EGL)
|
||||
return allocate_custom_egl_image_external (tex_2d, loader, error);
|
||||
#else
|
||||
g_return_val_if_reached (FALSE);
|
||||
#endif
|
||||
}
|
||||
|
||||
g_return_val_if_reached (FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
cogl_texture_driver_gl_texture_2d_init (CoglTextureDriver *driver,
|
||||
CoglTexture2D *tex_2d)
|
||||
{
|
||||
tex_2d->gl_texture = 0;
|
||||
|
||||
/* We default to GL_LINEAR for both filters */
|
||||
tex_2d->gl_legacy_texobj_min_filter = GL_LINEAR;
|
||||
tex_2d->gl_legacy_texobj_mag_filter = GL_LINEAR;
|
||||
|
||||
/* Wrap mode not yet set */
|
||||
tex_2d->gl_legacy_texobj_wrap_mode_s = GL_FALSE;
|
||||
tex_2d->gl_legacy_texobj_wrap_mode_t = GL_FALSE;
|
||||
|
||||
tex_2d->egl_image_external.user_data = NULL;
|
||||
tex_2d->egl_image_external.destroy = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
cogl_texture_driver_gl_texture_2d_copy_from_framebuffer (CoglTextureDriver *driver,
|
||||
CoglTexture2D *tex_2d,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int width,
|
||||
int height,
|
||||
CoglFramebuffer *src_fb,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
int level)
|
||||
{
|
||||
CoglTexture *tex = COGL_TEXTURE (tex_2d);
|
||||
CoglContext *ctx = cogl_texture_get_context (tex);
|
||||
|
||||
/* Make sure the current framebuffers are bound, though we don't need to
|
||||
* flush the clip state here since we aren't going to draw to the
|
||||
* framebuffer. */
|
||||
cogl_context_flush_framebuffer_state (ctx,
|
||||
ctx->current_draw_buffer,
|
||||
src_fb,
|
||||
(COGL_FRAMEBUFFER_STATE_ALL &
|
||||
~COGL_FRAMEBUFFER_STATE_CLIP));
|
||||
|
||||
_cogl_bind_gl_texture_transient (ctx, GL_TEXTURE_2D,
|
||||
tex_2d->gl_texture);
|
||||
|
||||
ctx->glCopyTexSubImage2D (GL_TEXTURE_2D,
|
||||
0, /* level */
|
||||
dst_x, dst_y,
|
||||
src_x, src_y,
|
||||
width, height);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
cogl_texture_driver_gl_texture_2d_get_gl_handle (CoglTextureDriver *driver,
|
||||
CoglTexture2D *tex_2d)
|
||||
{
|
||||
return tex_2d->gl_texture;
|
||||
}
|
||||
|
||||
static void
|
||||
cogl_texture_driver_gl_texture_2d_generate_mipmap (CoglTextureDriver *driver,
|
||||
CoglTexture2D *tex_2d)
|
||||
{
|
||||
_cogl_texture_gl_generate_mipmaps (COGL_TEXTURE (tex_2d));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
cogl_texture_driver_gl_texture_2d_copy_from_bitmap (CoglTextureDriver *driver,
|
||||
CoglTexture2D *tex_2d,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int width,
|
||||
int height,
|
||||
CoglBitmap *bmp,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
int level,
|
||||
GError **error)
|
||||
{
|
||||
CoglTexture *tex = COGL_TEXTURE (tex_2d);
|
||||
CoglContext *ctx = cogl_texture_get_context (tex);
|
||||
CoglTextureDriverClass *tex_driver =
|
||||
COGL_TEXTURE_DRIVER_GET_CLASS (ctx->texture_driver);
|
||||
CoglBitmap *upload_bmp;
|
||||
CoglPixelFormat upload_format;
|
||||
GLenum gl_format;
|
||||
GLenum gl_type;
|
||||
gboolean status = TRUE;
|
||||
|
||||
upload_bmp =
|
||||
_cogl_bitmap_convert_for_upload (bmp,
|
||||
cogl_texture_get_format (tex),
|
||||
error);
|
||||
if (upload_bmp == NULL)
|
||||
return FALSE;
|
||||
|
||||
upload_format = cogl_bitmap_get_format (upload_bmp);
|
||||
|
||||
/* Only support single plane formats */
|
||||
if (upload_format == COGL_PIXEL_FORMAT_ANY ||
|
||||
cogl_pixel_format_get_n_planes (upload_format) != 1)
|
||||
return FALSE;
|
||||
|
||||
ctx->driver_vtable->pixel_format_to_gl (ctx,
|
||||
upload_format,
|
||||
NULL, /* internal gl format */
|
||||
&gl_format,
|
||||
&gl_type);
|
||||
|
||||
if (cogl_texture_get_max_level_set (tex) < level)
|
||||
cogl_texture_gl_set_max_level (tex, level);
|
||||
|
||||
status = tex_driver->upload_subregion_to_gl (ctx->texture_driver,
|
||||
ctx,
|
||||
tex,
|
||||
src_x, src_y,
|
||||
dst_x, dst_y,
|
||||
width, height,
|
||||
level,
|
||||
upload_bmp,
|
||||
gl_format,
|
||||
gl_type,
|
||||
error);
|
||||
|
||||
g_object_unref (upload_bmp);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
cogl_texture_driver_gl_class_init (CoglTextureDriverGLClass *klass)
|
||||
{
|
||||
CoglTextureDriverClass *driver_klass = COGL_TEXTURE_DRIVER_CLASS (klass);
|
||||
|
||||
driver_klass->texture_2d_free = _cogl_texture_2d_gl_free;
|
||||
driver_klass->texture_2d_can_create = _cogl_texture_2d_gl_can_create;
|
||||
driver_klass->texture_2d_init = _cogl_texture_2d_gl_init;
|
||||
driver_klass->texture_2d_allocate = _cogl_texture_2d_gl_allocate;
|
||||
driver_klass->texture_2d_copy_from_framebuffer = _cogl_texture_2d_gl_copy_from_framebuffer;
|
||||
driver_klass->texture_2d_get_gl_handle = _cogl_texture_2d_gl_get_gl_handle;
|
||||
driver_klass->texture_2d_generate_mipmap = _cogl_texture_2d_gl_generate_mipmap;
|
||||
driver_klass->texture_2d_copy_from_bitmap = _cogl_texture_2d_gl_copy_from_bitmap;
|
||||
driver_klass->texture_2d_free = cogl_texture_driver_gl_texture_2d_free;
|
||||
driver_klass->texture_2d_can_create = cogl_texture_driver_gl_texture_2d_can_create;
|
||||
driver_klass->texture_2d_init = cogl_texture_driver_gl_texture_2d_init;
|
||||
driver_klass->texture_2d_allocate = cogl_texture_driver_gl_texture_2d_allocate;
|
||||
driver_klass->texture_2d_copy_from_framebuffer = cogl_texture_driver_gl_texture_2d_copy_from_framebuffer;
|
||||
driver_klass->texture_2d_get_gl_handle = cogl_texture_driver_gl_texture_2d_get_gl_handle;
|
||||
driver_klass->texture_2d_generate_mipmap = cogl_texture_driver_gl_texture_2d_generate_mipmap;
|
||||
driver_klass->texture_2d_copy_from_bitmap = cogl_texture_driver_gl_texture_2d_copy_from_bitmap;
|
||||
}
|
||||
|
||||
static void
|
||||
|
Loading…
x
Reference in New Issue
Block a user