[Cogl] [PATCH] texture-2d: factor out all GL specific code
Robert Bragg
robert at sixbynine.org
Mon Sep 24 07:48:08 PDT 2012
From: Robert Bragg <robert at linux.intel.com>
This factors out all of the OpenGL specific code in cogl-texture-2d.c
into cogl-texture-2d-gl.c and where necessary adds indirection through
the CoglDriver vtable so that we can eventually start to experiment with
non-OpenGL backends for Cogl.
---
cogl/Makefile.am | 3 +
cogl/cogl-driver.h | 108 +++++
cogl/cogl-gles2-context.c | 13 +-
cogl/cogl-texture-2d-gl.h | 75 ++++
cogl/cogl-texture-2d-private.h | 10 +
cogl/cogl-texture-2d-sliced.c | 13 +-
cogl/cogl-texture-2d.c | 521 ++++---------------------
cogl/cogl-texture-2d.h | 34 +--
cogl/cogl-texture.c | 13 +-
cogl/cogl.h | 1 +
cogl/driver/gl/cogl-texture-2d-gl-private.h | 112 ++++++
cogl/driver/gl/cogl-texture-2d-gl.c | 575 +++++++++++++++++++++++++++
cogl/driver/gl/gl/cogl-driver-gl.c | 14 +
cogl/driver/gl/gles/cogl-driver-gles.c | 14 +
14 files changed, 1012 insertions(+), 494 deletions(-)
create mode 100644 cogl/cogl-texture-2d-gl.h
create mode 100644 cogl/driver/gl/cogl-texture-2d-gl-private.h
create mode 100644 cogl/driver/gl/cogl-texture-2d-gl.c
diff --git a/cogl/Makefile.am b/cogl/Makefile.am
index 654d10b..6c43b96 100644
--- a/cogl/Makefile.am
+++ b/cogl/Makefile.am
@@ -97,6 +97,7 @@ cogl_experimental_h = \
$(srcdir)/cogl-poll.h \
$(srcdir)/cogl-texture-3d.h \
$(srcdir)/cogl-texture-2d.h \
+ $(srcdir)/cogl-texture-2d-gl.h \
$(srcdir)/cogl-texture-rectangle.h \
$(srcdir)/cogl-texture-2d-sliced.h \
$(srcdir)/cogl-sub-texture.h \
@@ -124,6 +125,8 @@ cogl_gl_prototypes_h = \
# driver sources
cogl_driver_sources = \
$(srcdir)/driver/gl/cogl-framebuffer-gl.c \
+ $(srcdir)/driver/gl/cogl-texture-2d-gl-private.h \
+ $(srcdir)/driver/gl/cogl-texture-2d-gl.c \
$(srcdir)/driver/gl/cogl-pipeline-opengl.c \
$(srcdir)/driver/gl/cogl-pipeline-opengl-private.h \
$(srcdir)/driver/gl/cogl-pipeline-fragend-glsl.c \
diff --git a/cogl/cogl-driver.h b/cogl/cogl-driver.h
index 63b737d..bfedbff 100644
--- a/cogl/cogl-driver.h
+++ b/cogl/cogl-driver.h
@@ -32,11 +32,15 @@ typedef struct _CoglDriverVtable CoglDriverVtable;
struct _CoglDriverVtable
{
+ /* TODO: factor this out since this is OpenGL specific and
+ * so can be ignored by non-OpenGL drivers. */
CoglBool
(* pixel_format_from_gl_internal) (CoglContext *context,
GLenum gl_int_format,
CoglPixelFormat *out_format);
+ /* TODO: factor this out since this is OpenGL specific and
+ * so can be ignored by non-OpenGL drivers. */
CoglPixelFormat
(* pixel_format_to_gl) (CoglContext *context,
CoglPixelFormat format,
@@ -102,6 +106,110 @@ struct _CoglDriverVtable
CoglAttribute **attributes,
int n_attributes,
CoglDrawFlags flags);
+
+ /* Destroys any driver specific resources associated with the given
+ * 2D texture. */
+ void
+ (* texture_2d_free) (CoglTexture2D *tex_2d);
+
+ /* Returns TRUE if the driver can support creating a 2D texture with
+ * the given geometry and specified internal format.
+ */
+ CoglBool
+ (* texture_2d_can_create) (CoglContext *ctx,
+ int width,
+ int height,
+ CoglPixelFormat internal_format);
+
+ /* Initializes driver private state before allocating any specific
+ * storage for a 2D texture, where base texture and texture 2D
+ * members will already be initialized before passing control to
+ * the driver.
+ */
+ void
+ (* texture_2d_init) (CoglTexture2D *tex_2d);
+
+ /* Instantiates a new CoglTexture2D object with un-initialized
+ * storage for a given size and internal format */
+ CoglTexture2D *
+ (* texture_2d_new_with_size) (CoglContext *ctx,
+ int width,
+ int height,
+ CoglPixelFormat internal_format,
+ CoglError **error);
+
+ /* Instantiates a new CoglTexture2D object with storage initialized
+ * with the contents of the given bitmap, using the specified
+ * internal format.
+ */
+ CoglTexture2D *
+ (* texture_2d_new_from_bitmap) (CoglBitmap *bmp,
+ CoglPixelFormat internal_format,
+ CoglError **error);
+
+#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base)
+ /* Instantiates a new CoglTexture2D object with storage initialized
+ * with the contents of the given EGL image.
+ *
+ * This is optional for drivers to support
+ */
+ CoglTexture2D *
+ (* egl_texture_2d_new_from_image) (CoglContext *ctx,
+ int width,
+ int height,
+ CoglPixelFormat format,
+ EGLImageKHR image,
+ CoglError **error);
+#endif
+
+ /* Initialize the specified region of storage of the given texture
+ * with the contents of the specified framebuffer region
+ */
+ void
+ (* texture_2d_copy_from_framebuffer) (CoglTexture2D *tex_2d,
+ CoglFramebuffer *src_fb,
+ int dst_x,
+ int dst_y,
+ int src_x,
+ int src_y,
+ int width,
+ int height);
+
+ /* If the given texture has a corresponding OpenGL texture handle
+ * then return that.
+ *
+ * This is optional
+ */
+ unsigned int
+ (* texture_2d_get_gl_handle) (CoglTexture2D *tex_2d);
+
+ /* Update all mipmap levels > 0 */
+ void
+ (* texture_2d_generate_mipmap) (CoglTexture2D *tex_2d);
+
+ /* Initialize the specified region of storage of the given texture
+ * with the contents of the specified bitmap region
+ */
+ void
+ (* texture_2d_copy_from_bitmap) (CoglTexture2D *tex_2d,
+ CoglBitmap *bitmap,
+ int dst_x,
+ int dst_y,
+ int src_x,
+ int src_y,
+ int width,
+ int height);
+
+ /* Reads back the full contents of the given texture and write it to
+ * @data in the given @format and with the given @rowstride.
+ *
+ * This is optional
+ */
+ void
+ (* texture_2d_get_data) (CoglTexture2D *tex_2d,
+ CoglPixelFormat format,
+ unsigned int rowstride,
+ uint8_t *data);
};
#endif /* __COGL_DRIVER_H */
diff --git a/cogl/cogl-gles2-context.c b/cogl/cogl-gles2-context.c
index 7bb7ff3..65e7598 100644
--- a/cogl/cogl-gles2-context.c
+++ b/cogl/cogl-gles2-context.c
@@ -43,6 +43,7 @@
#include "cogl-onscreen-template-private.h"
#include "cogl-renderer-private.h"
#include "cogl-swap-chain-private.h"
+#include "cogl-texture-2d-gl.h"
#include "cogl-texture-2d-private.h"
#include "cogl-pipeline-opengl-private.h"
#include "cogl-error-private.h"
@@ -1932,12 +1933,12 @@ cogl_gles2_texture_2d_new_from_handle (CoglContext *ctx,
CoglPixelFormat internal_format,
CoglError **error)
{
- return cogl_texture_2d_new_from_foreign (ctx,
- handle,
- width,
- height,
- internal_format,
- error);
+ return cogl_texture_2d_gl_new_from_foreign (ctx,
+ handle,
+ width,
+ height,
+ internal_format,
+ error);
}
CoglBool
diff --git a/cogl/cogl-texture-2d-gl.h b/cogl/cogl-texture-2d-gl.h
new file mode 100644
index 0000000..5136a35
--- /dev/null
+++ b/cogl/cogl-texture-2d-gl.h
@@ -0,0 +1,75 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ *
+ * Authors:
+ * Robert Bragg <robert at linux.intel.com>
+ */
+
+#if !defined(__COGL_H_INSIDE__) && !defined(COGL_COMPILATION)
+#error "Only <cogl/cogl.h> can be included directly."
+#endif
+
+#ifndef _COGL_TEXTURE_2D_GL_H_
+#define _COGL_TEXTURE_2D_GL_H_
+
+#include "cogl-context.h"
+#include "cogl-texture-2d.h"
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+/**
+ * cogl_texture_2d_gl_new_from_foreign:
+ * @ctx: A #CoglContext
+ * @gl_handle: A GL handle for a GL_TEXTURE_2D texture object
+ * @width: Width of the foreign GL texture
+ * @height: Height of the foreign GL texture
+ * @internal_format: The format of the texture
+ * @error: A #CoglError for exceptions
+ *
+ * Wraps an existing GL_TEXTURE_2D texture object as a #CoglTexture2D.
+ * This can be used for integrating Cogl with software using OpenGL
+ * directly.
+ *
+ * <note>The results are undefined for passing an invalid @gl_handle
+ * or if @width or @height don't have the correct texture
+ * geometry.</note>
+ *
+ * Returns: A newly allocated #CoglTexture2D, or if Cogl could not
+ * validate the @gl_handle in some way (perhaps because of
+ * an unsupported format) it will return %NULL and set
+ * @error.
+ *
+ * Since: 2.0
+ */
+CoglTexture2D *
+cogl_texture_2d_gl_new_from_foreign (CoglContext *ctx,
+ unsigned int gl_handle,
+ int width,
+ int height,
+ CoglPixelFormat format,
+ CoglError **error);
+
+G_END_DECLS
+
+#endif /* _COGL_TEXTURE_2D_GL_H_ */
diff --git a/cogl/cogl-texture-2d-private.h b/cogl/cogl-texture-2d-private.h
index 3180a3f..2a57081 100644
--- a/cogl/cogl-texture-2d-private.h
+++ b/cogl/cogl-texture-2d-private.h
@@ -74,6 +74,16 @@ _cogl_egl_texture_2d_new_from_image (CoglContext *ctx,
CoglError **error);
#endif
+CoglTexture2D *
+_cogl_texture_2d_create_base (CoglContext *ctx,
+ int width,
+ int height,
+ CoglPixelFormat internal_format);
+
+void
+_cogl_texture_2d_set_auto_mipmap (CoglTexture *tex,
+ CoglBool value);
+
/*
* _cogl_texture_2d_externally_modified:
* @texture: A #CoglTexture2D object
diff --git a/cogl/cogl-texture-2d-sliced.c b/cogl/cogl-texture-2d-sliced.c
index e988a4a..b03f41f 100644
--- a/cogl/cogl-texture-2d-sliced.c
+++ b/cogl/cogl-texture-2d-sliced.c
@@ -36,6 +36,7 @@
#include "cogl-bitmap.h"
#include "cogl-bitmap-private.h"
#include "cogl-texture-private.h"
+#include "cogl-texture-2d-gl.h"
#include "cogl-texture-2d-private.h"
#include "cogl-texture-2d-sliced-private.h"
#include "cogl-texture-driver.h"
@@ -982,12 +983,12 @@ _cogl_texture_2d_sliced_new_from_foreign (GLuint gl_handle,
y_pot_waste < 0 || y_pot_waste >= height)
return NULL;
- tex_2d = cogl_texture_2d_new_from_foreign (ctx,
- gl_target,
- gl_width,
- gl_height,
- format,
- NULL);
+ tex_2d = cogl_texture_2d_gl_new_from_foreign (ctx,
+ gl_target,
+ gl_width,
+ gl_height,
+ format,
+ NULL);
if (!tex_2d)
return NULL;
diff --git a/cogl/cogl-texture-2d.c b/cogl/cogl-texture-2d.c
index c170490..6b902fb 100644
--- a/cogl/cogl-texture-2d.c
+++ b/cogl/cogl-texture-2d.c
@@ -32,6 +32,7 @@
#include "cogl-util.h"
#include "cogl-texture-private.h"
#include "cogl-texture-2d-private.h"
+#include "cogl-texture-2d-gl-private.h"
#include "cogl-texture-driver.h"
#include "cogl-context-private.h"
#include "cogl-object-private.h"
@@ -64,40 +65,11 @@ typedef struct _CoglTexture2DManualRepeatData
} CoglTexture2DManualRepeatData;
static void
-_cogl_texture_2d_gl_flush_legacy_texobj_wrap_modes (CoglTexture *tex,
- GLenum wrap_mode_s,
- GLenum wrap_mode_t,
- GLenum wrap_mode_p)
-{
- CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex);
- CoglContext *ctx = tex->context;
-
- /* Only set the wrap mode if it's different from the current value
- to avoid too many GL calls. Texture 2D doesn't make use of the r
- coordinate so we can ignore its wrap mode */
- if (tex_2d->gl_legacy_texobj_wrap_mode_s != wrap_mode_s ||
- tex_2d->gl_legacy_texobj_wrap_mode_t != wrap_mode_t)
- {
- _cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
- tex_2d->gl_texture,
- tex_2d->is_foreign);
- GE( ctx, glTexParameteri (GL_TEXTURE_2D,
- GL_TEXTURE_WRAP_S,
- wrap_mode_s) );
- GE( ctx, glTexParameteri (GL_TEXTURE_2D,
- GL_TEXTURE_WRAP_T,
- wrap_mode_t) );
-
- tex_2d->gl_legacy_texobj_wrap_mode_s = wrap_mode_s;
- tex_2d->gl_legacy_texobj_wrap_mode_t = wrap_mode_t;
- }
-}
-
-static void
_cogl_texture_2d_free (CoglTexture2D *tex_2d)
{
- if (!tex_2d->is_foreign)
- _cogl_delete_gl_texture (tex_2d->gl_texture);
+ CoglContext *ctx = COGL_TEXTURE (tex_2d)->context;
+
+ ctx->driver_vtable->texture_2d_free (tex_2d);
/* Chain up */
_cogl_texture_free (COGL_TEXTURE (tex_2d));
@@ -109,10 +81,6 @@ _cogl_texture_2d_can_create (CoglContext *ctx,
unsigned int height,
CoglPixelFormat internal_format)
{
- GLenum gl_intformat;
- GLenum gl_format;
- GLenum gl_type;
-
/* If NPOT textures aren't supported then the size must be a power
of two */
if (!cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_BASIC) &&
@@ -120,26 +88,13 @@ _cogl_texture_2d_can_create (CoglContext *ctx,
!_cogl_util_is_pot (height)))
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 (!ctx->texture_driver->size_supported (ctx,
- GL_TEXTURE_2D,
- gl_intformat,
- gl_format,
- gl_type,
- width,
- height))
- return FALSE;
-
- return TRUE;
+ return ctx->driver_vtable->texture_2d_can_create (ctx,
+ width,
+ height,
+ internal_format);
}
-static void
+void
_cogl_texture_2d_set_auto_mipmap (CoglTexture *tex,
CoglBool value)
{
@@ -148,7 +103,7 @@ _cogl_texture_2d_set_auto_mipmap (CoglTexture *tex,
tex_2d->auto_mipmap = value;
}
-static CoglTexture2D *
+CoglTexture2D *
_cogl_texture_2d_create_base (CoglContext *ctx,
int width,
int height,
@@ -164,19 +119,13 @@ _cogl_texture_2d_create_base (CoglContext *ctx,
tex_2d->mipmaps_dirty = TRUE;
tex_2d->auto_mipmap = TRUE;
- /* 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->is_foreign = FALSE;
tex_2d->format = internal_format;
- return tex_2d;
+ ctx->driver_vtable->texture_2d_init (tex_2d);
+
+ return _cogl_texture_2d_object_new (tex_2d);
}
CoglTexture2D *
@@ -186,11 +135,6 @@ cogl_texture_2d_new_with_size (CoglContext *ctx,
CoglPixelFormat internal_format,
CoglError **error)
{
- CoglTexture2D *tex_2d;
- GLenum gl_intformat;
- GLenum gl_format;
- GLenum gl_type;
-
/* Since no data, we need some internal format */
if (internal_format == COGL_PIXEL_FORMAT_ANY)
internal_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE;
@@ -204,24 +148,11 @@ cogl_texture_2d_new_with_size (CoglContext *ctx,
return NULL;
}
- internal_format = ctx->driver_vtable->pixel_format_to_gl (ctx,
- internal_format,
- &gl_intformat,
- &gl_format,
- &gl_type);
-
- tex_2d = _cogl_texture_2d_create_base (ctx,
- width, height,
- internal_format);
-
- ctx->texture_driver->gen (ctx, GL_TEXTURE_2D, 1, &tex_2d->gl_texture);
- _cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
- tex_2d->gl_texture,
- tex_2d->is_foreign);
- GE( ctx, glTexImage2D (GL_TEXTURE_2D, 0, gl_intformat,
- width, height, 0, gl_format, gl_type, NULL) );
-
- return _cogl_texture_2d_object_new (tex_2d);
+ return ctx->driver_vtable->texture_2d_new_with_size (ctx,
+ width,
+ height,
+ internal_format,
+ error);
}
CoglTexture2D *
@@ -229,12 +160,6 @@ cogl_texture_2d_new_from_bitmap (CoglBitmap *bmp,
CoglPixelFormat internal_format,
CoglError **error)
{
- CoglTexture2D *tex_2d;
- CoglBitmap *dst_bmp;
- GLenum gl_intformat;
- GLenum gl_format;
- GLenum gl_type;
- uint8_t *data;
CoglContext *ctx;
_COGL_RETURN_VAL_IF_FAIL (bmp != NULL, NULL);
@@ -258,54 +183,9 @@ cogl_texture_2d_new_from_bitmap (CoglBitmap *bmp,
}
- if ((dst_bmp = _cogl_texture_prepare_for_upload (bmp,
- internal_format,
- &internal_format,
- &gl_intformat,
- &gl_format,
- &gl_type)) == NULL)
- {
- _cogl_set_error (error, COGL_TEXTURE_ERROR,
- COGL_TEXTURE_ERROR_FORMAT,
- "Failed to prepare texture upload due to format");
- return NULL;
- }
-
- tex_2d = _cogl_texture_2d_create_base (ctx,
- cogl_bitmap_get_width (bmp),
- cogl_bitmap_get_height (bmp),
- internal_format);
-
- /* Keep a copy of the first pixel so that if glGenerateMipmap isn't
- supported we can fallback to using GL_GENERATE_MIPMAP */
- if (!cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN) &&
- (data = _cogl_bitmap_map (dst_bmp,
- COGL_BUFFER_ACCESS_READ, 0)))
- {
- CoglPixelFormat format = cogl_bitmap_get_format (dst_bmp);
- tex_2d->first_pixel.gl_format = gl_format;
- tex_2d->first_pixel.gl_type = gl_type;
- memcpy (tex_2d->first_pixel.data, data,
- _cogl_pixel_format_get_bytes_per_pixel (format));
-
- _cogl_bitmap_unmap (dst_bmp);
- }
-
- ctx->texture_driver->gen (ctx, GL_TEXTURE_2D, 1, &tex_2d->gl_texture);
- ctx->texture_driver->upload_to_gl (ctx,
- GL_TEXTURE_2D,
- tex_2d->gl_texture,
- FALSE,
- dst_bmp,
- gl_intformat,
- gl_format,
- gl_type);
-
- tex_2d->gl_format = gl_intformat;
-
- cogl_object_unref (dst_bmp);
-
- return _cogl_texture_2d_object_new (tex_2d);
+ return ctx->driver_vtable->texture_2d_new_from_bitmap (bmp,
+ internal_format,
+ error);
}
CoglTexture2D *
@@ -344,149 +224,6 @@ cogl_texture_2d_new_from_data (CoglContext *ctx,
return tex_2d;
}
-CoglTexture2D *
-cogl_texture_2d_new_from_foreign (CoglContext *ctx,
- unsigned int gl_handle,
- int width,
- int height,
- CoglPixelFormat format,
- CoglError **error)
-{
- /* NOTE: width, height and internal format are not queriable
- * in GLES, hence such a function prototype.
- */
-
- GLenum gl_error = 0;
- GLint gl_compressed = GL_FALSE;
- GLenum gl_int_format = 0;
- CoglTexture2D *tex_2d;
-
- /* Assert it is a valid GL texture object */
- g_return_val_if_fail (ctx->glIsTexture (gl_handle), NULL);
-
- if (!ctx->texture_driver->allows_foreign_gl_target (ctx, GL_TEXTURE_2D))
- {
- _cogl_set_error (error,
- COGL_SYSTEM_ERROR,
- COGL_SYSTEM_ERROR_UNSUPPORTED,
- "Foreign GL_TEXTURE_2D textures are not "
- "supported by your system");
- return NULL;
- }
-
-
- /* Make sure binding succeeds */
- while ((gl_error = ctx->glGetError ()) != GL_NO_ERROR)
- ;
-
- _cogl_bind_gl_texture_transient (GL_TEXTURE_2D, gl_handle, TRUE);
- if (ctx->glGetError () != GL_NO_ERROR)
- {
- _cogl_set_error (error,
- COGL_SYSTEM_ERROR,
- COGL_SYSTEM_ERROR_UNSUPPORTED,
- "Failed to bind foreign GL_TEXTURE_2D texture");
- return NULL;
- }
-
- /* Obtain texture parameters
- (only level 0 we are interested in) */
-
-#if HAVE_COGL_GL
- if (ctx->driver == COGL_DRIVER_GL)
- {
- GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_2D, 0,
- GL_TEXTURE_COMPRESSED,
- &gl_compressed) );
-
- {
- GLint val;
-
- GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_2D, 0,
- GL_TEXTURE_INTERNAL_FORMAT,
- &val) );
-
- gl_int_format = val;
- }
-
- /* If we can query GL for the actual pixel format then we'll ignore
- the passed in format and use that. */
- if (!ctx->driver_vtable->pixel_format_from_gl_internal (ctx,
- gl_int_format,
- &format))
- {
- _cogl_set_error (error,
- COGL_SYSTEM_ERROR,
- COGL_SYSTEM_ERROR_UNSUPPORTED,
- "Unsupported internal format for foreign texture");
- return NULL;
- }
- }
- else
-#endif
- {
- /* Otherwise we'll assume we can derive the GL format from the
- passed in format */
- ctx->driver_vtable->pixel_format_to_gl (ctx,
- format,
- &gl_int_format,
- NULL,
- NULL);
- }
-
- /* Note: We always trust the given width and height without querying
- * the texture object because the user may be creating a Cogl
- * texture for a texture_from_pixmap object where glTexImage2D may
- * not have been called and the texture_from_pixmap spec doesn't
- * clarify that it is reliable to query back the size from OpenGL.
- */
-
- /* Validate width and height */
- g_return_val_if_fail (width > 0 && height > 0, NULL);
-
- /* Compressed texture images not supported */
- if (gl_compressed == GL_TRUE)
- {
- _cogl_set_error (error,
- COGL_SYSTEM_ERROR,
- COGL_SYSTEM_ERROR_UNSUPPORTED,
- "Compressed foreign textures aren't currently supported");
- return NULL;
- }
-
- /* Note: previously this code would query the texture object for
- whether it has GL_GENERATE_MIPMAP enabled to determine whether to
- auto-generate the mipmap. This doesn't make much sense any more
- since Cogl switch to using glGenerateMipmap. Ideally I think
- cogl_texture_2d_new_from_foreign should take a flags parameter so
- that the application can decide whether it wants
- auto-mipmapping. To be compatible with existing code, Cogl now
- disables its own auto-mipmapping but leaves the value of
- GL_GENERATE_MIPMAP alone so that it would still work but without
- the dirtiness tracking that Cogl would do. */
-
- /* Create new texture */
- tex_2d = _cogl_texture_2d_create_base (ctx,
- width, height,
- format);
- _cogl_texture_2d_set_auto_mipmap (COGL_TEXTURE (tex_2d), FALSE);
-
- /* Setup bitmap info */
- tex_2d->is_foreign = TRUE;
- tex_2d->mipmaps_dirty = TRUE;
-
- tex_2d->format = format;
-
- tex_2d->gl_texture = gl_handle;
- tex_2d->gl_format = gl_int_format;
-
- /* Unknown filter */
- tex_2d->gl_legacy_texobj_min_filter = GL_FALSE;
- tex_2d->gl_legacy_texobj_mag_filter = GL_FALSE;
-
- return _cogl_texture_2d_object_new (tex_2d);
-}
-
#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base)
/* NB: The reason we require the width, height and format to be passed
* even though they may seem redundant is because GLES 1/2 don't
@@ -499,9 +236,6 @@ _cogl_egl_texture_2d_new_from_image (CoglContext *ctx,
EGLImageKHR image,
CoglError **error)
{
- CoglTexture2D *tex_2d;
- GLenum gl_error;
-
_COGL_RETURN_VAL_IF_FAIL (_cogl_context_get_winsys (ctx)->constraints &
COGL_RENDERER_CONSTRAINT_USES_EGL,
NULL);
@@ -510,29 +244,22 @@ _cogl_egl_texture_2d_new_from_image (CoglContext *ctx,
COGL_PRIVATE_FEATURE_TEXTURE_2D_FROM_EGL_IMAGE,
NULL);
- tex_2d = _cogl_texture_2d_create_base (ctx,
- width, height,
- format);
-
- ctx->texture_driver->gen (ctx, GL_TEXTURE_2D, 1, &tex_2d->gl_texture);
- _cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
- tex_2d->gl_texture,
- FALSE);
-
- while ((gl_error = ctx->glGetError ()) != GL_NO_ERROR)
- ;
- ctx->glEGLImageTargetTexture2D (GL_TEXTURE_2D, image);
- if (ctx->glGetError () != GL_NO_ERROR)
+ if (ctx->driver_vtable->egl_texture_2d_new_from_image)
+ return ctx->driver_vtable->egl_texture_2d_new_from_image (ctx,
+ width,
+ height,
+ format,
+ image,
+ error);
+ else
{
_cogl_set_error (error,
- COGL_TEXTURE_ERROR,
- COGL_TEXTURE_ERROR_BAD_PARAMETER,
- "Could not create a CoglTexture2D from a given "
- "EGLImage");
+ COGL_SYSTEM_ERROR,
+ COGL_SYSTEM_ERROR_UNSUPPORTED,
+ "Creating 2D textures from EGL images is not "
+ "supported by the current driver");
return NULL;
}
-
- return _cogl_texture_2d_object_new (tex_2d);
}
#endif /* defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base) */
@@ -624,28 +351,20 @@ _cogl_texture_2d_copy_from_framebuffer (CoglTexture2D *tex_2d,
int height)
{
CoglContext *ctx;
+ CoglFramebuffer *read_fb = _cogl_get_read_framebuffer ();
_COGL_RETURN_IF_FAIL (cogl_is_texture_2d (tex_2d));
ctx = COGL_TEXTURE (tex_2d)->context;
- /* 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_framebuffer_flush_state (cogl_get_draw_framebuffer (),
- _cogl_get_read_framebuffer (),
- COGL_FRAMEBUFFER_STATE_ALL &
- ~COGL_FRAMEBUFFER_STATE_CLIP);
-
- _cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
- tex_2d->gl_texture,
- tex_2d->is_foreign);
-
- ctx->glCopyTexSubImage2D (GL_TEXTURE_2D,
- 0, /* level */
- dst_x, dst_y,
- src_x, src_y,
- width, height);
+ ctx->driver_vtable->texture_2d_copy_from_framebuffer (tex_2d,
+ read_fb,
+ dst_x,
+ dst_y,
+ src_x,
+ src_y,
+ width,
+ height);
tex_2d->mipmaps_dirty = TRUE;
}
@@ -712,75 +431,39 @@ _cogl_texture_2d_get_gl_texture (CoglTexture *tex,
GLuint *out_gl_handle,
GLenum *out_gl_target)
{
+ CoglContext *ctx = tex->context;
CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex);
- if (out_gl_handle)
- *out_gl_handle = tex_2d->gl_texture;
+ if (ctx->driver_vtable->texture_2d_get_gl_handle)
+ {
+ GLuint handle;
- if (out_gl_target)
- *out_gl_target = GL_TEXTURE_2D;
+ if (out_gl_target)
+ *out_gl_target = GL_TEXTURE_2D;
- return TRUE;
-}
+ handle = ctx->driver_vtable->texture_2d_get_gl_handle (tex_2d);
-static void
-_cogl_texture_2d_gl_flush_legacy_texobj_filters (CoglTexture *tex,
- GLenum min_filter,
- GLenum mag_filter)
-{
- CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex);
- CoglContext *ctx = tex->context;
-
- if (min_filter == tex_2d->gl_legacy_texobj_min_filter
- && mag_filter == tex_2d->gl_legacy_texobj_mag_filter)
- return;
+ if (out_gl_handle)
+ *out_gl_handle = handle;
- /* Store new values */
- tex_2d->gl_legacy_texobj_min_filter = min_filter;
- tex_2d->gl_legacy_texobj_mag_filter = mag_filter;
-
- /* Apply new filters to the texture */
- _cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
- tex_2d->gl_texture,
- tex_2d->is_foreign);
- GE( ctx, glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter) );
- GE( ctx, glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter) );
+ return handle ? TRUE : FALSE;
+ }
+ else
+ return FALSE;
}
static void
_cogl_texture_2d_pre_paint (CoglTexture *tex, CoglTexturePrePaintFlags flags)
{
CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex);
- CoglContext *ctx = tex->context;
/* Only update if the mipmaps are dirty */
if ((flags & COGL_TEXTURE_NEEDS_MIPMAP) &&
tex_2d->auto_mipmap && tex_2d->mipmaps_dirty)
{
- _cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
- tex_2d->gl_texture,
- tex_2d->is_foreign);
-
- /* glGenerateMipmap is defined in the FBO extension. If it's not
- available we'll fallback to temporarily enabling
- GL_GENERATE_MIPMAP and reuploading the first pixel */
- if (cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN))
- ctx->texture_driver->gl_generate_mipmaps (ctx, GL_TEXTURE_2D);
-#if defined(HAVE_COGL_GLES) || defined(HAVE_COGL_GL)
- else
- {
- GE( ctx, glTexParameteri (GL_TEXTURE_2D,
- GL_GENERATE_MIPMAP,
- GL_TRUE) );
- GE( ctx, 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( ctx, glTexParameteri (GL_TEXTURE_2D,
- GL_GENERATE_MIPMAP,
- GL_FALSE) );
- }
-#endif
+ CoglContext *ctx = tex->context;
+
+ ctx->driver_vtable->texture_2d_generate_mipmap (tex_2d);
tex_2d->mipmaps_dirty = FALSE;
}
@@ -798,55 +481,24 @@ _cogl_texture_2d_set_region (CoglTexture *tex,
int src_y,
int dst_x,
int dst_y,
- unsigned int dst_width,
- unsigned int dst_height,
+ unsigned int width,
+ unsigned int height,
CoglBitmap *bmp)
{
- CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex);
CoglContext *ctx = tex->context;
- GLenum gl_format;
- GLenum gl_type;
- uint8_t *data;
-
- bmp = _cogl_texture_prepare_for_upload (bmp,
- cogl_texture_get_format (tex),
- NULL,
- NULL,
- &gl_format,
- &gl_type);
-
- /* If this touches the first pixel then we'll update our copy */
- if (dst_x == 0 && dst_y == 0 &&
- !cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN) &&
- (data = _cogl_bitmap_map (bmp, COGL_BUFFER_ACCESS_READ, 0)))
- {
- CoglPixelFormat bpp =
- _cogl_pixel_format_get_bytes_per_pixel (cogl_bitmap_get_format (bmp));
- tex_2d->first_pixel.gl_format = gl_format;
- tex_2d->first_pixel.gl_type = gl_type;
- memcpy (tex_2d->first_pixel.data,
- data + cogl_bitmap_get_rowstride (bmp) * src_y + bpp * src_x,
- bpp);
-
- _cogl_bitmap_unmap (bmp);
- }
+ CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex);
- /* Send data to GL */
- ctx->texture_driver->upload_subregion_to_gl (ctx,
- GL_TEXTURE_2D,
- tex_2d->gl_texture,
- FALSE,
- src_x, src_y,
- dst_x, dst_y,
- dst_width, dst_height,
- bmp,
- gl_format,
- gl_type);
+ ctx->driver_vtable->texture_2d_copy_from_bitmap (tex_2d,
+ bmp,
+ dst_x,
+ dst_y,
+ src_x,
+ src_y,
+ width,
+ height);
tex_2d->mipmaps_dirty = TRUE;
- cogl_object_unref (bmp);
-
return TRUE;
}
@@ -856,33 +508,16 @@ _cogl_texture_2d_get_data (CoglTexture *tex,
unsigned int rowstride,
uint8_t *data)
{
- CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex);
CoglContext *ctx = tex->context;
- int bpp;
- GLenum gl_format;
- GLenum gl_type;
-
- bpp = _cogl_pixel_format_get_bytes_per_pixel (format);
-
- ctx->driver_vtable->pixel_format_to_gl (ctx,
- format,
- NULL, /* internal format */
- &gl_format,
- &gl_type);
-
- ctx->texture_driver->prep_gl_for_pixels_download (ctx,
- rowstride,
- tex_2d->width,
- bpp);
-
- _cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
- tex_2d->gl_texture,
- tex_2d->is_foreign);
- return ctx->texture_driver->gl_get_tex_image (ctx,
- GL_TEXTURE_2D,
- gl_format,
- gl_type,
- data);
+
+ if (ctx->driver_vtable->texture_2d_get_data)
+ {
+ CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex);
+ ctx->driver_vtable->texture_2d_get_data (tex_2d, format, rowstride, data);
+ return TRUE;
+ }
+ else
+ return FALSE;
}
static CoglPixelFormat
diff --git a/cogl/cogl-texture-2d.h b/cogl/cogl-texture-2d.h
index 1fc3d12..d07cdef 100644
--- a/cogl/cogl-texture-2d.h
+++ b/cogl/cogl-texture-2d.h
@@ -32,6 +32,7 @@
#define __COGL_TEXTURE_2D_H
#include "cogl-context.h"
+#include "cogl-bitmap.h"
#include <glib.h>
@@ -186,39 +187,6 @@ cogl_texture_2d_new_from_bitmap (CoglBitmap *bitmap,
CoglPixelFormat internal_format,
CoglError **error);
-
-/**
- * cogl_texture_2d_new_from_foreign:
- * @ctx: A #CoglContext
- * @gl_handle: A GL handle for a GL_TEXTURE_2D texture object
- * @width: Width of the foreign GL texture
- * @height: Height of the foreign GL texture
- * @internal_format: The format of the texture
- * @error: A #CoglError for exceptions
- *
- * Wraps an existing GL_TEXTURE_2D texture object as a #CoglTexture2D.
- * This can be used for integrating Cogl with software using OpenGL
- * directly.
- *
- * <note>The results are undefined for passing an invalid @gl_handle
- * or if @width or @height don't have the correct texture
- * geometry.</note>
- *
- * Returns: A newly allocated #CoglTexture2D, or if Cogl could not
- * validate the @gl_handle in some way (perhaps because of
- * an unsupported format) it will return %NULL and set
- * @error.
- *
- * Since: 2.0
- */
-CoglTexture2D *
-cogl_texture_2d_new_from_foreign (CoglContext *ctx,
- unsigned int gl_handle,
- int width,
- int height,
- CoglPixelFormat format,
- CoglError **error);
-
G_END_DECLS
#endif /* __COGL_TEXTURE_2D_H */
diff --git a/cogl/cogl-texture.c b/cogl/cogl-texture.c
index 67a696b..2d54216 100644
--- a/cogl/cogl-texture.c
+++ b/cogl/cogl-texture.c
@@ -42,6 +42,7 @@
#include "cogl-texture-driver.h"
#include "cogl-texture-2d-sliced-private.h"
#include "cogl-texture-2d-private.h"
+#include "cogl-texture-2d-gl.h"
#include "cogl-texture-rectangle-private.h"
#include "cogl-sub-texture-private.h"
#include "cogl-atlas-texture-private.h"
@@ -489,12 +490,12 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
else
{
_COGL_GET_CONTEXT (ctx, NULL);
- return COGL_TEXTURE (cogl_texture_2d_new_from_foreign (ctx,
- gl_handle,
- width,
- height,
- format,
- NULL));
+ return COGL_TEXTURE (cogl_texture_2d_gl_new_from_foreign (ctx,
+ gl_handle,
+ width,
+ height,
+ format,
+ NULL));
}
}
diff --git a/cogl/cogl.h b/cogl/cogl.h
index 8291bc2..875f32a 100644
--- a/cogl/cogl.h
+++ b/cogl/cogl.h
@@ -65,6 +65,7 @@
#include <cogl/cogl-euler.h>
#include <cogl/cogl-quaternion.h>
#include <cogl/cogl-texture-2d.h>
+#include <cogl/cogl-texture-2d-gl.h>
#include <cogl/cogl-texture-rectangle.h>
#include <cogl/cogl-texture-3d.h>
#include <cogl/cogl-texture-2d-sliced.h>
diff --git a/cogl/driver/gl/cogl-texture-2d-gl-private.h b/cogl/driver/gl/cogl-texture-2d-gl-private.h
new file mode 100644
index 0000000..492c314
--- /dev/null
+++ b/cogl/driver/gl/cogl-texture-2d-gl-private.h
@@ -0,0 +1,112 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ *
+ *
+ * Authors:
+ * Robert Bragg <robert at linux.intel.com>
+ */
+
+#ifndef _COGL_TEXTURE_2D_GL_PRIVATE_H_
+#define _COGL_TEXTURE_2D_GL_PRIVATE_H_
+
+#include "cogl-types.h"
+#include "cogl-context-private.h"
+#include "cogl-texture.h"
+
+void
+_cogl_texture_2d_gl_free (CoglTexture2D *tex_2d);
+
+CoglBool
+_cogl_texture_2d_gl_can_create (CoglContext *ctx,
+ int width,
+ int height,
+ CoglPixelFormat internal_format);
+
+void
+_cogl_texture_2d_gl_init (CoglTexture2D *tex_2d);
+
+CoglTexture2D *
+_cogl_texture_2d_gl_new_with_size (CoglContext *ctx,
+ int width,
+ int height,
+ CoglPixelFormat internal_format,
+ CoglError **error);
+
+CoglTexture2D *
+_cogl_texture_2d_gl_new_from_bitmap (CoglBitmap *bmp,
+ CoglPixelFormat internal_format,
+ CoglError **error);
+
+#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base)
+CoglTexture2D *
+_cogl_egl_texture_2d_gl_new_from_image (CoglContext *ctx,
+ int width,
+ int height,
+ CoglPixelFormat format,
+ EGLImageKHR image,
+ CoglError **error);
+#endif
+
+void
+_cogl_texture_2d_gl_flush_legacy_texobj_filters (CoglTexture *tex,
+ GLenum min_filter,
+ GLenum mag_filter);
+
+void
+_cogl_texture_2d_gl_flush_legacy_texobj_wrap_modes (CoglTexture *tex,
+ GLenum wrap_mode_s,
+ GLenum wrap_mode_t,
+ GLenum wrap_mode_p);
+
+void
+_cogl_texture_2d_gl_copy_from_framebuffer (CoglTexture2D *tex_2d,
+ CoglFramebuffer *src_fb,
+ int dst_x,
+ int dst_y,
+ int src_x,
+ int src_y,
+ int width,
+ int height);
+
+unsigned int
+_cogl_texture_2d_gl_get_gl_handle (CoglTexture2D *tex_2d);
+
+void
+_cogl_texture_2d_gl_generate_mipmap (CoglTexture2D *tex_2d);
+
+void
+_cogl_texture_2d_gl_copy_from_bitmap (CoglTexture2D *tex_2d,
+ CoglBitmap *bitmap,
+ int dst_x,
+ int dst_y,
+ int src_x,
+ int src_y,
+ int width,
+ int height);
+
+void
+_cogl_texture_2d_gl_get_data (CoglTexture2D *tex_2d,
+ CoglPixelFormat format,
+ size_t rowstride,
+ uint8_t *data);
+
+#endif /* _COGL_TEXTURE_2D_GL_PRIVATE_H_ */
diff --git a/cogl/driver/gl/cogl-texture-2d-gl.c b/cogl/driver/gl/cogl-texture-2d-gl.c
new file mode 100644
index 0000000..653405c
--- /dev/null
+++ b/cogl/driver/gl/cogl-texture-2d-gl.c
@@ -0,0 +1,575 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2009,2010,2011,2012 Intel Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ *
+ * Authors:
+ * Neil Roberts <neil at linux.intel.com>
+ * Robert Bragg <robert at linux.intel.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include "cogl-private.h"
+#include "cogl-texture-2d-gl.h"
+#include "cogl-texture-2d-gl-private.h"
+#include "cogl-texture-2d-private.h"
+#include "cogl-pipeline-opengl-private.h"
+#include "cogl-error-private.h"
+
+void
+_cogl_texture_2d_gl_free (CoglTexture2D *tex_2d)
+{
+ if (!tex_2d->is_foreign)
+ _cogl_delete_gl_texture (tex_2d->gl_texture);
+}
+
+CoglBool
+_cogl_texture_2d_gl_can_create (CoglContext *ctx,
+ int width,
+ int height,
+ CoglPixelFormat internal_format)
+{
+ GLenum gl_intformat;
+ GLenum gl_format;
+ GLenum gl_type;
+
+ 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 (!ctx->texture_driver->size_supported (ctx,
+ GL_TEXTURE_2D,
+ gl_intformat,
+ gl_format,
+ gl_type,
+ width,
+ height))
+ return FALSE;
+
+ return TRUE;
+}
+
+void
+_cogl_texture_2d_gl_init (CoglTexture2D *tex_2d)
+{
+ /* 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;
+}
+
+CoglTexture2D *
+_cogl_texture_2d_gl_new_with_size (CoglContext *ctx,
+ int width,
+ int height,
+ CoglPixelFormat internal_format,
+ CoglError **error)
+{
+ CoglTexture2D *tex_2d;
+ GLenum gl_intformat;
+ GLenum gl_format;
+ GLenum gl_type;
+
+ internal_format = ctx->driver_vtable->pixel_format_to_gl (ctx,
+ internal_format,
+ &gl_intformat,
+ &gl_format,
+ &gl_type);
+
+ tex_2d = _cogl_texture_2d_create_base (ctx,
+ width, height,
+ internal_format);
+
+ ctx->texture_driver->gen (ctx, GL_TEXTURE_2D, 1, &tex_2d->gl_texture);
+ _cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
+ tex_2d->gl_texture,
+ tex_2d->is_foreign);
+ GE( ctx, glTexImage2D (GL_TEXTURE_2D, 0, gl_intformat,
+ width, height, 0, gl_format, gl_type, NULL) );
+
+ return tex_2d;
+}
+
+CoglTexture2D *
+_cogl_texture_2d_gl_new_from_bitmap (CoglBitmap *bmp,
+ CoglPixelFormat internal_format,
+ CoglError **error)
+{
+ CoglContext *ctx = _cogl_bitmap_get_context (bmp);
+ CoglTexture2D *tex_2d;
+ CoglBitmap *dst_bmp;
+ GLenum gl_intformat;
+ GLenum gl_format;
+ GLenum gl_type;
+ uint8_t *data;
+
+ if ((dst_bmp = _cogl_texture_prepare_for_upload (bmp,
+ internal_format,
+ &internal_format,
+ &gl_intformat,
+ &gl_format,
+ &gl_type)) == NULL)
+ {
+ _cogl_set_error (error, COGL_TEXTURE_ERROR,
+ COGL_TEXTURE_ERROR_FORMAT,
+ "Failed to prepare texture upload due to format");
+ return NULL;
+ }
+
+ tex_2d = _cogl_texture_2d_create_base (ctx,
+ cogl_bitmap_get_width (bmp),
+ cogl_bitmap_get_height (bmp),
+ internal_format);
+
+ /* Keep a copy of the first pixel so that if glGenerateMipmap isn't
+ supported we can fallback to using GL_GENERATE_MIPMAP */
+ if (!cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN) &&
+ (data = _cogl_bitmap_map (dst_bmp,
+ COGL_BUFFER_ACCESS_READ, 0)))
+ {
+ CoglPixelFormat format = cogl_bitmap_get_format (dst_bmp);
+ tex_2d->first_pixel.gl_format = gl_format;
+ tex_2d->first_pixel.gl_type = gl_type;
+ memcpy (tex_2d->first_pixel.data, data,
+ _cogl_pixel_format_get_bytes_per_pixel (format));
+
+ _cogl_bitmap_unmap (dst_bmp);
+ }
+
+ ctx->texture_driver->gen (ctx, GL_TEXTURE_2D, 1, &tex_2d->gl_texture);
+ ctx->texture_driver->upload_to_gl (ctx,
+ GL_TEXTURE_2D,
+ tex_2d->gl_texture,
+ FALSE,
+ dst_bmp,
+ gl_intformat,
+ gl_format,
+ gl_type);
+
+ tex_2d->gl_format = gl_intformat;
+
+ cogl_object_unref (dst_bmp);
+
+ return tex_2d;
+
+}
+
+#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base)
+CoglTexture2D *
+_cogl_egl_texture_2d_gl_new_from_image (CoglContext *ctx,
+ int width,
+ int height,
+ CoglPixelFormat format,
+ EGLImageKHR image,
+ CoglError **error)
+{
+ CoglTexture2D *tex_2d;
+ GLenum gl_error;
+
+ tex_2d = _cogl_texture_2d_create_base (ctx,
+ width, height,
+ format);
+
+ ctx->texture_driver->gen (ctx, GL_TEXTURE_2D, 1, &tex_2d->gl_texture);
+ _cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
+ tex_2d->gl_texture,
+ FALSE);
+
+ while ((gl_error = ctx->glGetError ()) != GL_NO_ERROR)
+ ;
+ ctx->glEGLImageTargetTexture2D (GL_TEXTURE_2D, image);
+ if (ctx->glGetError () != GL_NO_ERROR)
+ {
+ _cogl_set_error (error,
+ COGL_TEXTURE_ERROR,
+ COGL_TEXTURE_ERROR_BAD_PARAMETER,
+ "Could not create a CoglTexture2D from a given "
+ "EGLImage");
+ return NULL;
+ }
+
+ return tex_2d;
+}
+#endif
+
+void
+_cogl_texture_2d_gl_flush_legacy_texobj_filters (CoglTexture *tex,
+ GLenum min_filter,
+ GLenum mag_filter)
+{
+ CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex);
+ CoglContext *ctx = tex->context;
+
+ if (min_filter == tex_2d->gl_legacy_texobj_min_filter
+ && mag_filter == tex_2d->gl_legacy_texobj_mag_filter)
+ return;
+
+ /* Store new values */
+ tex_2d->gl_legacy_texobj_min_filter = min_filter;
+ tex_2d->gl_legacy_texobj_mag_filter = mag_filter;
+
+ /* Apply new filters to the texture */
+ _cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
+ tex_2d->gl_texture,
+ tex_2d->is_foreign);
+ GE( ctx, glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter) );
+ GE( ctx, glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter) );
+}
+
+void
+_cogl_texture_2d_gl_flush_legacy_texobj_wrap_modes (CoglTexture *tex,
+ GLenum wrap_mode_s,
+ GLenum wrap_mode_t,
+ GLenum wrap_mode_p)
+{
+ CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex);
+ CoglContext *ctx = tex->context;
+
+ /* Only set the wrap mode if it's different from the current value
+ to avoid too many GL calls. Texture 2D doesn't make use of the r
+ coordinate so we can ignore its wrap mode */
+ if (tex_2d->gl_legacy_texobj_wrap_mode_s != wrap_mode_s ||
+ tex_2d->gl_legacy_texobj_wrap_mode_t != wrap_mode_t)
+ {
+ _cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
+ tex_2d->gl_texture,
+ tex_2d->is_foreign);
+ GE( ctx, glTexParameteri (GL_TEXTURE_2D,
+ GL_TEXTURE_WRAP_S,
+ wrap_mode_s) );
+ GE( ctx, glTexParameteri (GL_TEXTURE_2D,
+ GL_TEXTURE_WRAP_T,
+ wrap_mode_t) );
+
+ tex_2d->gl_legacy_texobj_wrap_mode_s = wrap_mode_s;
+ tex_2d->gl_legacy_texobj_wrap_mode_t = wrap_mode_t;
+ }
+}
+
+CoglTexture2D *
+cogl_texture_2d_gl_new_from_foreign (CoglContext *ctx,
+ unsigned int gl_handle,
+ int width,
+ int height,
+ CoglPixelFormat format,
+ CoglError **error)
+{
+ /* NOTE: width, height and internal format are not queriable
+ * in GLES, hence such a function prototype.
+ */
+
+ GLenum gl_error = 0;
+ GLint gl_compressed = GL_FALSE;
+ GLenum gl_int_format = 0;
+ CoglTexture2D *tex_2d;
+
+ /* Assert it is a valid GL texture object */
+ g_return_val_if_fail (ctx->glIsTexture (gl_handle), NULL);
+
+ if (!ctx->texture_driver->allows_foreign_gl_target (ctx, GL_TEXTURE_2D))
+ {
+ _cogl_set_error (error,
+ COGL_SYSTEM_ERROR,
+ COGL_SYSTEM_ERROR_UNSUPPORTED,
+ "Foreign GL_TEXTURE_2D textures are not "
+ "supported by your system");
+ return NULL;
+ }
+
+
+ /* Make sure binding succeeds */
+ while ((gl_error = ctx->glGetError ()) != GL_NO_ERROR)
+ ;
+
+ _cogl_bind_gl_texture_transient (GL_TEXTURE_2D, gl_handle, TRUE);
+ if (ctx->glGetError () != GL_NO_ERROR)
+ {
+ _cogl_set_error (error,
+ COGL_SYSTEM_ERROR,
+ COGL_SYSTEM_ERROR_UNSUPPORTED,
+ "Failed to bind foreign GL_TEXTURE_2D texture");
+ return NULL;
+ }
+
+ /* Obtain texture parameters
+ (only level 0 we are interested in) */
+
+#if HAVE_COGL_GL
+ if (ctx->driver == COGL_DRIVER_GL)
+ {
+ GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_2D, 0,
+ GL_TEXTURE_COMPRESSED,
+ &gl_compressed) );
+
+ {
+ GLint val;
+
+ GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_2D, 0,
+ GL_TEXTURE_INTERNAL_FORMAT,
+ &val) );
+
+ gl_int_format = val;
+ }
+
+ /* If we can query GL for the actual pixel format then we'll ignore
+ the passed in format and use that. */
+ if (!ctx->driver_vtable->pixel_format_from_gl_internal (ctx,
+ gl_int_format,
+ &format))
+ {
+ _cogl_set_error (error,
+ COGL_SYSTEM_ERROR,
+ COGL_SYSTEM_ERROR_UNSUPPORTED,
+ "Unsupported internal format for foreign texture");
+ return NULL;
+ }
+ }
+ else
+#endif
+ {
+ /* Otherwise we'll assume we can derive the GL format from the
+ passed in format */
+ ctx->driver_vtable->pixel_format_to_gl (ctx,
+ format,
+ &gl_int_format,
+ NULL,
+ NULL);
+ }
+
+ /* Note: We always trust the given width and height without querying
+ * the texture object because the user may be creating a Cogl
+ * texture for a texture_from_pixmap object where glTexImage2D may
+ * not have been called and the texture_from_pixmap spec doesn't
+ * clarify that it is reliable to query back the size from OpenGL.
+ */
+
+ /* Validate width and height */
+ g_return_val_if_fail (width > 0 && height > 0, NULL);
+
+ /* Compressed texture images not supported */
+ if (gl_compressed == GL_TRUE)
+ {
+ _cogl_set_error (error,
+ COGL_SYSTEM_ERROR,
+ COGL_SYSTEM_ERROR_UNSUPPORTED,
+ "Compressed foreign textures aren't currently supported");
+ return NULL;
+ }
+
+ /* Note: previously this code would query the texture object for
+ whether it has GL_GENERATE_MIPMAP enabled to determine whether to
+ auto-generate the mipmap. This doesn't make much sense any more
+ since Cogl switch to using glGenerateMipmap. Ideally I think
+ cogl_texture_2d_new_from_foreign should take a flags parameter so
+ that the application can decide whether it wants
+ auto-mipmapping. To be compatible with existing code, Cogl now
+ disables its own auto-mipmapping but leaves the value of
+ GL_GENERATE_MIPMAP alone so that it would still work but without
+ the dirtiness tracking that Cogl would do. */
+
+ /* Create new texture */
+ tex_2d = _cogl_texture_2d_create_base (ctx,
+ width, height,
+ format);
+ _cogl_texture_2d_set_auto_mipmap (COGL_TEXTURE (tex_2d), FALSE);
+
+ /* Setup bitmap info */
+ tex_2d->is_foreign = TRUE;
+ tex_2d->mipmaps_dirty = TRUE;
+
+ tex_2d->format = format;
+
+ tex_2d->gl_texture = gl_handle;
+ tex_2d->gl_format = gl_int_format;
+
+ /* Unknown filter */
+ tex_2d->gl_legacy_texobj_min_filter = GL_FALSE;
+ tex_2d->gl_legacy_texobj_mag_filter = GL_FALSE;
+
+ return tex_2d;
+}
+
+void
+_cogl_texture_2d_gl_copy_from_framebuffer (CoglTexture2D *tex_2d,
+ CoglFramebuffer *src_fb,
+ int dst_x,
+ int dst_y,
+ int src_x,
+ int src_y,
+ int width,
+ int height)
+{
+ CoglContext *ctx = COGL_TEXTURE (tex_2d)->context;
+
+ /* 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_framebuffer_flush_state (cogl_get_draw_framebuffer (),
+ src_fb,
+ COGL_FRAMEBUFFER_STATE_ALL &
+ ~COGL_FRAMEBUFFER_STATE_CLIP);
+
+ _cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
+ tex_2d->gl_texture,
+ tex_2d->is_foreign);
+
+ 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 (CoglTexture2D *tex_2d)
+{
+ return tex_2d->gl_texture;
+}
+
+void
+_cogl_texture_2d_gl_generate_mipmap (CoglTexture2D *tex_2d)
+{
+ CoglContext *ctx = COGL_TEXTURE (tex_2d)->context;
+
+ _cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
+ tex_2d->gl_texture,
+ tex_2d->is_foreign);
+
+ /* glGenerateMipmap is defined in the FBO extension. If it's not
+ available we'll fallback to temporarily enabling
+ GL_GENERATE_MIPMAP and reuploading the first pixel */
+ if (cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN))
+ ctx->texture_driver->gl_generate_mipmaps (ctx, GL_TEXTURE_2D);
+#if defined(HAVE_COGL_GLES) || defined(HAVE_COGL_GL)
+ else
+ {
+ GE( ctx, glTexParameteri (GL_TEXTURE_2D,
+ GL_GENERATE_MIPMAP,
+ GL_TRUE) );
+ GE( ctx, 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( ctx, glTexParameteri (GL_TEXTURE_2D,
+ GL_GENERATE_MIPMAP,
+ GL_FALSE) );
+ }
+#endif
+}
+
+void
+_cogl_texture_2d_gl_copy_from_bitmap (CoglTexture2D *tex_2d,
+ CoglBitmap *bmp,
+ int dst_x,
+ int dst_y,
+ int src_x,
+ int src_y,
+ int width,
+ int height)
+{
+ CoglTexture *tex = COGL_TEXTURE (tex_2d);
+ CoglContext *ctx = tex->context;
+ GLenum gl_format;
+ GLenum gl_type;
+ uint8_t *data;
+
+ bmp = _cogl_texture_prepare_for_upload (bmp,
+ cogl_texture_get_format (tex),
+ NULL,
+ NULL,
+ &gl_format,
+ &gl_type);
+
+ /* If this touches the first pixel then we'll update our copy */
+ if (dst_x == 0 && dst_y == 0 &&
+ !cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN) &&
+ (data = _cogl_bitmap_map (bmp, COGL_BUFFER_ACCESS_READ, 0)))
+ {
+ CoglPixelFormat bpp =
+ _cogl_pixel_format_get_bytes_per_pixel (cogl_bitmap_get_format (bmp));
+ tex_2d->first_pixel.gl_format = gl_format;
+ tex_2d->first_pixel.gl_type = gl_type;
+ memcpy (tex_2d->first_pixel.data,
+ data + cogl_bitmap_get_rowstride (bmp) * src_y + bpp * src_x,
+ bpp);
+
+ _cogl_bitmap_unmap (bmp);
+ }
+
+ /* Send data to GL */
+ ctx->texture_driver->upload_subregion_to_gl (ctx,
+ GL_TEXTURE_2D,
+ tex_2d->gl_texture,
+ FALSE,
+ src_x, src_y,
+ dst_x, dst_y,
+ width, height,
+ bmp,
+ gl_format,
+ gl_type);
+
+ cogl_object_unref (bmp);
+}
+
+void
+_cogl_texture_2d_gl_get_data (CoglTexture2D *tex_2d,
+ CoglPixelFormat format,
+ size_t rowstride,
+ uint8_t *data)
+{
+ CoglContext *ctx = COGL_TEXTURE (tex_2d)->context;
+ int bpp;
+ GLenum gl_format;
+ GLenum gl_type;
+
+ bpp = _cogl_pixel_format_get_bytes_per_pixel (format);
+
+ ctx->driver_vtable->pixel_format_to_gl (ctx,
+ format,
+ NULL, /* internal format */
+ &gl_format,
+ &gl_type);
+
+ ctx->texture_driver->prep_gl_for_pixels_download (ctx,
+ rowstride,
+ tex_2d->width,
+ bpp);
+
+ _cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
+ tex_2d->gl_texture,
+ tex_2d->is_foreign);
+
+ ctx->texture_driver->gl_get_tex_image (ctx,
+ GL_TEXTURE_2D,
+ gl_format,
+ gl_type,
+ data);
+}
diff --git a/cogl/driver/gl/gl/cogl-driver-gl.c b/cogl/driver/gl/gl/cogl-driver-gl.c
index 06d0024..32bd294 100644
--- a/cogl/driver/gl/gl/cogl-driver-gl.c
+++ b/cogl/driver/gl/gl/cogl-driver-gl.c
@@ -34,6 +34,7 @@
#include "cogl-renderer-private.h"
#include "cogl-error-private.h"
#include "cogl-framebuffer-gl-private.h"
+#include "cogl-texture-2d-gl-private.h"
static CoglBool
_cogl_driver_pixel_format_from_gl_internal (CoglContext *context,
@@ -533,4 +534,17 @@ _cogl_driver_gl =
_cogl_framebuffer_gl_discard_buffers,
_cogl_framebuffer_gl_draw_attributes,
_cogl_framebuffer_gl_draw_indexed_attributes,
+ _cogl_texture_2d_gl_free,
+ _cogl_texture_2d_gl_can_create,
+ _cogl_texture_2d_gl_init,
+ _cogl_texture_2d_gl_new_with_size,
+ _cogl_texture_2d_gl_new_from_bitmap,
+#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base)
+ _cogl_egl_texture_2d_gl_new_from_image,
+#endif
+ _cogl_texture_2d_gl_copy_from_framebuffer,
+ _cogl_texture_2d_gl_get_gl_handle,
+ _cogl_texture_2d_gl_generate_mipmap,
+ _cogl_texture_2d_gl_copy_from_bitmap,
+ _cogl_texture_2d_gl_get_data,
};
diff --git a/cogl/driver/gl/gles/cogl-driver-gles.c b/cogl/driver/gl/gles/cogl-driver-gles.c
index 8948d73..eb799a9 100644
--- a/cogl/driver/gl/gles/cogl-driver-gles.c
+++ b/cogl/driver/gl/gles/cogl-driver-gles.c
@@ -33,6 +33,7 @@
#include "cogl-renderer-private.h"
#include "cogl-private.h"
#include "cogl-framebuffer-gl-private.h"
+#include "cogl-texture-2d-gl-private.h"
#ifndef GL_UNSIGNED_INT_24_8
#define GL_UNSIGNED_INT_24_8 0x84FA
@@ -351,4 +352,17 @@ _cogl_driver_gles =
_cogl_framebuffer_gl_discard_buffers,
_cogl_framebuffer_gl_draw_attributes,
_cogl_framebuffer_gl_draw_indexed_attributes,
+ _cogl_texture_2d_gl_free,
+ _cogl_texture_2d_gl_can_create,
+ _cogl_texture_2d_gl_init,
+ _cogl_texture_2d_gl_new_with_size,
+ _cogl_texture_2d_gl_new_from_bitmap,
+#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base)
+ _cogl_egl_texture_2d_gl_new_from_image,
+#endif
+ _cogl_texture_2d_gl_copy_from_framebuffer,
+ _cogl_texture_2d_gl_get_gl_handle,
+ _cogl_texture_2d_gl_generate_mipmap,
+ _cogl_texture_2d_gl_copy_from_bitmap,
+ NULL, /* texture_2d_get_data */
};
--
1.7.7.6
More information about the Cogl
mailing list