From 8eb66da6b0fbb022028d012a428a399892a0c0f3 Mon Sep 17 00:00:00 2001 From: Johan Bilien Date: Fri, 24 Apr 2009 15:07:49 +0100 Subject: [PATCH 01/37] Unnecessary glColorMask on alpha drops performance Bug 1228 - Unnecessary glColorMask on alpha drops performance With DRI2, alpha is allowed in the window's framebuffer Signed-off-by: Emmanuele Bassi --- gl/cogl-fbo.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/gl/cogl-fbo.c b/gl/cogl-fbo.c index 13463d345..501871976 100644 --- a/gl/cogl-fbo.c +++ b/gl/cogl-fbo.c @@ -321,13 +321,7 @@ cogl_draw_buffer (CoglBufferTarget target, CoglHandle offscreen) /* Bind window framebuffer object */ GE( glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0) ); - - if (target == COGL_WINDOW_BUFFER) - { - /* Draw to RGB channels */ - GE( glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE) ); - } - else if (target == COGL_MASK_BUFFER) + if (target == COGL_MASK_BUFFER) { /* Draw only to ALPHA channel */ GE( glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE) ); From c56d5b1468e411450f0370070196abec0ccec7d6 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Sat, 23 May 2009 19:18:18 +0100 Subject: [PATCH 02/37] [cogl] Remove max_waste argument from Texture ctors The CoglTexture constructors expose the "max-waste" argument for controlling the maximum amount of wasted areas for slicing or, if set to -1, disables slicing. Slicing is really relevant only for large images that are never repeated, so it's a useful feature only in controlled use cases. Specifying the amount of wasted area is, on the other hand, just a way to mess up this feature; 99% the times, you either pull this number out of thin air, hoping it's right, or you try to do the right thing and you choose the wrong number anyway. Instead, we can use the CoglTextureFlags to control whether the texture should not be sliced (useful for Clutter-GST and for the texture-from-pixmap actors) and provide a reasonable value for enabling the slicing ourself. At some point, we might even provide a way to change the default at compile time or at run time, for particular platforms. Since max_waste is gone, the :tile-waste property of ClutterTexture becomes read-only, and it proxies the cogl_texture_get_max_waste() function. Inside Clutter, the only cases where the max_waste argument was not set to -1 are in the Pango glyph cache (which is a POT texture anyway) and inside the test cases where we want to force slicing; for the latter we can create larger textures that will be bigger than the threshold we set. Signed-off-by: Emmanuele Bassi Signed-off-by: Robert Bragg Signed-off-by: Neil Roberts --- cogl-texture.h | 34 +++++++------------ cogl-types.h | 4 ++- common/cogl-util.c | 1 + gl/cogl-context.c | 6 ++-- gl/cogl-texture.c | 81 +++++++++++++++++++++++---------------------- gles/cogl-context.c | 6 ++-- gles/cogl-texture.c | 60 +++++++++++++++++++-------------- 7 files changed, 97 insertions(+), 95 deletions(-) diff --git a/cogl-texture.h b/cogl-texture.h index 6a8b00a01..d4cc4e812 100644 --- a/cogl-texture.h +++ b/cogl-texture.h @@ -41,12 +41,12 @@ G_BEGIN_DECLS * loading and manipulating textures. */ +#define COGL_TEXTURE_MAX_WASTE 127 + /** * cogl_texture_new_with_size: * @width: width of texture in pixels. * @height: height of texture in pixels. - * @max_waste: maximum extra horizontal and|or vertical margin pixels - * to make the texture fit GPU limitations * @flags: Optional flags for the texture, or %COGL_TEXTURE_NONE * @internal_format: the #CoglPixelFormat to use for the GPU storage of the * texture. @@ -60,15 +60,12 @@ G_BEGIN_DECLS */ CoglHandle cogl_texture_new_with_size (guint width, guint height, - gint max_waste, CoglTextureFlags flags, CoglPixelFormat internal_format); /** * cogl_texture_new_from_file: * @filename: the file to load - * @max_waste: maximum extra horizontal and|or vertical margin pixels - * to make the texture fit GPU limitations * @flags: Optional flags for the texture, or %COGL_TEXTURE_NONE * @internal_format: the #CoglPixelFormat to use for the GPU storage of the * texture @@ -82,7 +79,6 @@ CoglHandle cogl_texture_new_with_size (guint width, * Since: 0.8 */ CoglHandle cogl_texture_new_from_file (const gchar *filename, - gint max_waste, CoglTextureFlags flags, CoglPixelFormat internal_format, GError **error); @@ -91,8 +87,6 @@ CoglHandle cogl_texture_new_from_file (const gchar *filename, * cogl_texture_new_from_data: * @width: width of texture in pixels * @height: height of texture in pixels - * @max_waste: maximum extra horizontal and|or vertical margin pixels - * to make the texture fit GPU limitations * @flags: Optional flags for the texture, or %COGL_TEXTURE_NONE * @format: the #CoglPixelFormat the buffer is stored in in RAM * @internal_format: the #CoglPixelFormat that will be used for storing @@ -110,7 +104,6 @@ CoglHandle cogl_texture_new_from_file (const gchar *filename, */ CoglHandle cogl_texture_new_from_data (guint width, guint height, - gint max_waste, CoglTextureFlags flags, CoglPixelFormat format, CoglPixelFormat internal_format, @@ -136,19 +129,17 @@ CoglHandle cogl_texture_new_from_data (guint width, * * Since: 0.8 */ -CoglHandle cogl_texture_new_from_foreign (GLuint gl_handle, - GLenum gl_target, - GLuint width, - GLuint height, - GLuint x_pot_waste, - GLuint y_pot_waste, - CoglPixelFormat format); +CoglHandle cogl_texture_new_from_foreign (GLuint gl_handle, + GLenum gl_target, + GLuint width, + GLuint height, + GLuint x_pot_waste, + GLuint y_pot_waste, + CoglPixelFormat format); /** * cogl_texture_new_from_bitmap: * @bmp_handle: A CoglBitmap handle - * @max_waste: maximum extra horizontal and|or vertical margin pixels - * to make the texture fit GPU limitations * @flags: Optional flags for the texture, or %COGL_TEXTURE_NONE * @internal_format: the #CoglPixelFormat to use for the GPU storage of the * texture @@ -160,10 +151,9 @@ CoglHandle cogl_texture_new_from_foreign (GLuint gl_handle, * * Since: 1.0 */ -CoglHandle cogl_texture_new_from_bitmap (CoglHandle bmp_handle, - gint max_waste, - CoglTextureFlags flags, - CoglPixelFormat internal_format); +CoglHandle cogl_texture_new_from_bitmap (CoglHandle bmp_handle, + CoglTextureFlags flags, + CoglPixelFormat internal_format); /** * cogl_is_texture: diff --git a/cogl-types.h b/cogl-types.h index a4ecd4193..719ecd087 100644 --- a/cogl-types.h +++ b/cogl-types.h @@ -292,6 +292,7 @@ struct _CoglTextureVertex * @COGL_TEXTURE_NONE: No flags specified * @COGL_TEXTURE_AUTO_MIPMAP: Enables the automatic generation of the * mipmap pyramid from the base level image whenever it is updated + * @COGL_TEXTURE_NO_SLICING: Disables the slicing of the texture * * Flags to pass to the cogl_texture_new_* family of functions. * @@ -299,7 +300,8 @@ struct _CoglTextureVertex */ typedef enum { COGL_TEXTURE_NONE = 0, - COGL_TEXTURE_AUTO_MIPMAP = 1 << 0 + COGL_TEXTURE_AUTO_MIPMAP = 1 << 0, + COGL_TEXTURE_NO_SLICING = 1 << 1 } CoglTextureFlags; #define COGL_TYPE_TEXTURE_FLAGS (cogl_texture_flags_get_type ()) diff --git a/common/cogl-util.c b/common/cogl-util.c index d71b9ffd8..2b9ccba27 100644 --- a/common/cogl-util.c +++ b/common/cogl-util.c @@ -223,6 +223,7 @@ cogl_texture_flags_get_type (void) static const GFlagsValue values[] = { { COGL_TEXTURE_NONE, "COGL_TEXTURE_NONE", "none" }, { COGL_TEXTURE_AUTO_MIPMAP, "COGL_TEXTURE_AUTO_MIPMAP", "auto-mipmap" }, + { COGL_TEXTURE_NO_SLICING, "COGL_TEXTURE_NO_SLICING", "no-slicing" }, { 0, NULL, NULL } }; diff --git a/gl/cogl-context.c b/gl/cogl-context.c index 986da8aa8..2c17408c2 100644 --- a/gl/cogl-context.c +++ b/gl/cogl-context.c @@ -146,8 +146,7 @@ cogl_create_context () _context->default_gl_texture_2d_tex = cogl_texture_new_from_data (1, /* width */ 1, /* height */ - -1, /* max waste */ - COGL_TEXTURE_NONE, /* flags */ + COGL_TEXTURE_NO_SLICING, COGL_PIXEL_FORMAT_RGBA_8888, /* data format */ /* internal format */ COGL_PIXEL_FORMAT_RGBA_8888, @@ -156,8 +155,7 @@ cogl_create_context () _context->default_gl_texture_rect_tex = cogl_texture_new_from_data (1, /* width */ 1, /* height */ - -1, /* max waste */ - COGL_TEXTURE_NONE, /* flags */ + COGL_TEXTURE_NO_SLICING, COGL_PIXEL_FORMAT_RGBA_8888, /* data format */ /* internal format */ COGL_PIXEL_FORMAT_RGBA_8888, diff --git a/gl/cogl-texture.c b/gl/cogl-texture.c index ce2ee11ed..80e428eba 100644 --- a/gl/cogl-texture.c +++ b/gl/cogl-texture.c @@ -644,10 +644,10 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex, } static gint -_cogl_rect_slices_for_size (gint size_to_fill, - gint max_span_size, - gint max_waste, - GArray *out_spans) +_cogl_rect_slices_for_size (gint size_to_fill, + gint max_span_size, + gint max_waste, + GArray *out_spans) { gint n_spans = 0; CoglTexSliceSpan span; @@ -679,10 +679,10 @@ _cogl_rect_slices_for_size (gint size_to_fill, } static gint -_cogl_pot_slices_for_size (gint size_to_fill, - gint max_span_size, - gint max_waste, - GArray *out_spans) +_cogl_pot_slices_for_size (gint size_to_fill, + gint max_span_size, + gint max_waste, + GArray *out_spans) { gint n_spans = 0; CoglTexSliceSpan span; @@ -693,7 +693,8 @@ _cogl_pot_slices_for_size (gint size_to_fill, span.waste = 0; /* Fix invalid max_waste */ - if (max_waste < 0) max_waste = 0; + if (max_waste < 0) + max_waste = 0; while (TRUE) { @@ -826,10 +827,10 @@ _cogl_texture_slices_create (CoglTexture *tex) /* Check if size supported else bail out */ if (!_cogl_texture_size_supported (tex->gl_target, - tex->gl_format, - tex->gl_type, - max_width, - max_height)) + tex->gl_format, + tex->gl_type, + max_width, + max_height)) { return FALSE; } @@ -1199,11 +1200,10 @@ _cogl_texture_free (CoglTexture *tex) } CoglHandle -cogl_texture_new_with_size (guint width, - guint height, - gint max_waste, - CoglTextureFlags flags, - CoglPixelFormat internal_format) +cogl_texture_new_with_size (guint width, + guint height, + CoglTextureFlags flags, + CoglPixelFormat internal_format) { CoglTexture *tex; gint bpp; @@ -1234,7 +1234,11 @@ cogl_texture_new_with_size (guint width, tex->slice_y_spans = NULL; tex->slice_gl_handles = NULL; - tex->max_waste = max_waste; + if (flags & COGL_TEXTURE_NO_SLICING) + tex->max_waste = -1; + else + tex->max_waste = COGL_TEXTURE_MAX_WASTE; + tex->min_filter = COGL_TEXTURE_FILTER_NEAREST; tex->mag_filter = COGL_TEXTURE_FILTER_NEAREST; @@ -1258,7 +1262,6 @@ cogl_texture_new_with_size (guint width, CoglHandle cogl_texture_new_from_data (guint width, guint height, - gint max_waste, CoglTextureFlags flags, CoglPixelFormat format, CoglPixelFormat internal_format, @@ -1295,7 +1298,11 @@ cogl_texture_new_from_data (guint width, tex->slice_y_spans = NULL; tex->slice_gl_handles = NULL; - tex->max_waste = max_waste; + if (flags & COGL_TEXTURE_NO_SLICING) + tex->max_waste = -1; + else + tex->max_waste = COGL_TEXTURE_MAX_WASTE; + tex->min_filter = COGL_TEXTURE_FILTER_NEAREST; tex->mag_filter = COGL_TEXTURE_FILTER_NEAREST; @@ -1328,10 +1335,9 @@ cogl_texture_new_from_data (guint width, } CoglHandle -cogl_texture_new_from_bitmap (CoglHandle bmp_handle, - gint max_waste, - CoglTextureFlags flags, - CoglPixelFormat internal_format) +cogl_texture_new_from_bitmap (CoglHandle bmp_handle, + CoglTextureFlags flags, + CoglPixelFormat internal_format) { CoglTexture *tex; CoglBitmap *bmp = (CoglBitmap *)bmp_handle; @@ -1352,7 +1358,11 @@ cogl_texture_new_from_bitmap (CoglHandle bmp_handle, tex->slice_y_spans = NULL; tex->slice_gl_handles = NULL; - tex->max_waste = max_waste; + if (flags & COGL_TEXTURE_NO_SLICING) + tex->max_waste = -1; + else + tex->max_waste = COGL_TEXTURE_MAX_WASTE; + tex->min_filter = COGL_TEXTURE_FILTER_NEAREST; tex->mag_filter = COGL_TEXTURE_FILTER_NEAREST; @@ -1389,13 +1399,12 @@ cogl_texture_new_from_bitmap (CoglHandle bmp_handle, CoglHandle cogl_texture_new_from_file (const gchar *filename, - gint max_waste, CoglTextureFlags flags, CoglPixelFormat internal_format, GError **error) { - CoglHandle bmp; - CoglHandle handle; + CoglHandle bmp; + CoglHandle handle; g_return_val_if_fail (error == NULL || *error == NULL, COGL_INVALID_HANDLE); @@ -1403,10 +1412,7 @@ cogl_texture_new_from_file (const gchar *filename, if (bmp == COGL_INVALID_HANDLE) return COGL_INVALID_HANDLE; - handle = cogl_texture_new_from_bitmap (bmp, - max_waste, - flags, - internal_format); + handle = cogl_texture_new_from_bitmap (bmp, flags, internal_format); cogl_handle_unref (bmp); return handle; @@ -1509,14 +1515,11 @@ cogl_texture_new_from_foreign (GLuint gl_handle, return COGL_INVALID_HANDLE; /* Try and match to a cogl format */ - if (!_cogl_pixel_format_from_gl_internal (gl_int_format, - &format)) - { - return COGL_INVALID_HANDLE; - } + if (!_cogl_pixel_format_from_gl_internal (gl_int_format, &format)) + return COGL_INVALID_HANDLE; /* Create new texture */ - tex = (CoglTexture*) g_malloc ( sizeof (CoglTexture)); + tex = (CoglTexture *) g_malloc (sizeof (CoglTexture)); /* Setup bitmap info */ tex->is_foreign = TRUE; diff --git a/gles/cogl-context.c b/gles/cogl-context.c index d70d59d35..f187c0b88 100644 --- a/gles/cogl-context.c +++ b/gles/cogl-context.c @@ -107,8 +107,7 @@ cogl_create_context () _context->default_gl_texture_2d_tex = cogl_texture_new_from_data (1, /* width */ 1, /* height */ - -1, /* max waste */ - COGL_TEXTURE_NONE, /* flags */ + COGL_TEXTURE_NO_SLICING, /* flags */ COGL_PIXEL_FORMAT_RGBA_8888, /* data format */ /* internal format */ COGL_PIXEL_FORMAT_RGBA_8888, @@ -117,8 +116,7 @@ cogl_create_context () _context->default_gl_texture_rect_tex = cogl_texture_new_from_data (1, /* width */ 1, /* height */ - -1, /* max waste */ - COGL_TEXTURE_NONE, /* flags */ + COGL_TEXTURE_NO_SLICING, /* flags */ COGL_PIXEL_FORMAT_RGBA_8888, /* data format */ /* internal format */ COGL_PIXEL_FORMAT_RGBA_8888, diff --git a/gles/cogl-texture.c b/gles/cogl-texture.c index 1564faf2a..8f4cf733e 100644 --- a/gles/cogl-texture.c +++ b/gles/cogl-texture.c @@ -858,7 +858,8 @@ _cogl_pot_slices_for_size (gint size_to_fill, span.waste = 0; /* Fix invalid max_waste */ - if (max_waste < 0) max_waste = 0; + if (max_waste < 0) + max_waste = 0; while (TRUE) { @@ -866,7 +867,9 @@ _cogl_pot_slices_for_size (gint size_to_fill, if (size_to_fill > span.size) { /* Not yet - add a span of this size */ - if (out_spans) g_array_append_val (out_spans, span); + if (out_spans) + g_array_append_val (out_spans, span); + span.start += span.size; size_to_fill -= span.size; n_spans++; @@ -875,7 +878,9 @@ _cogl_pot_slices_for_size (gint size_to_fill, { /* Yes and waste is small enough */ span.waste = span.size - size_to_fill; - if (out_spans) g_array_append_val (out_spans, span); + if (out_spans) + g_array_append_val (out_spans, span); + return ++n_spans; } else @@ -971,10 +976,10 @@ _cogl_texture_slices_create (CoglTexture *tex) /* Check if size supported else bail out */ if (!_cogl_texture_size_supported (tex->gl_target, - tex->gl_format, - tex->gl_type, - max_width, - max_height)) + tex->gl_format, + tex->gl_type, + max_width, + max_height)) { return FALSE; } @@ -1288,11 +1293,10 @@ _cogl_texture_free (CoglTexture *tex) } CoglHandle -cogl_texture_new_with_size (guint width, - guint height, - gint max_waste, - CoglTextureFlags flags, - CoglPixelFormat internal_format) +cogl_texture_new_with_size (guint width, + guint height, + CoglTextureFlags flags, + CoglPixelFormat internal_format) { CoglTexture *tex; gint bpp; @@ -1323,7 +1327,11 @@ cogl_texture_new_with_size (guint width, tex->slice_y_spans = NULL; tex->slice_gl_handles = NULL; - tex->max_waste = max_waste; + if (flags & COGL_TEXTURE_NO_SLICING) + tex->max_waste = -1; + else + tex->max_waste = COGL_TEXTURE_MAX_WASTE; + tex->min_filter = CGL_NEAREST; tex->mag_filter = CGL_NEAREST; @@ -1347,7 +1355,6 @@ cogl_texture_new_with_size (guint width, CoglHandle cogl_texture_new_from_data (guint width, guint height, - gint max_waste, CoglTextureFlags flags, CoglPixelFormat format, CoglPixelFormat internal_format, @@ -1384,7 +1391,11 @@ cogl_texture_new_from_data (guint width, tex->slice_y_spans = NULL; tex->slice_gl_handles = NULL; - tex->max_waste = max_waste; + if (flags & COGL_TEXTURE_NO_SLICING) + tex->max_waste = -1; + else + tex->max_waste = COGL_TEXTURE_MAX_WASTE; + tex->min_filter = CGL_NEAREST; tex->mag_filter = CGL_NEAREST; @@ -1417,10 +1428,9 @@ cogl_texture_new_from_data (guint width, } CoglHandle -cogl_texture_new_from_bitmap (CoglHandle bmp_handle, - gint max_waste, - CoglTextureFlags flags, - CoglPixelFormat internal_format) +cogl_texture_new_from_bitmap (CoglHandle bmp_handle, + CoglTextureFlags flags, + CoglPixelFormat internal_format) { CoglTexture *tex; CoglBitmap *bmp = (CoglBitmap *)bmp_handle; @@ -1439,7 +1449,11 @@ cogl_texture_new_from_bitmap (CoglHandle bmp_handle, tex->slice_y_spans = NULL; tex->slice_gl_handles = NULL; - tex->max_waste = max_waste; + if (flags & COGL_TEXTURE_NO_SLICING) + tex->max_waste = -1; + else + tex->max_waste = COGL_TEXTURE_MAX_WASTE; + tex->min_filter = CGL_NEAREST; tex->mag_filter = CGL_NEAREST; @@ -1476,7 +1490,6 @@ cogl_texture_new_from_bitmap (CoglHandle bmp_handle, CoglHandle cogl_texture_new_from_file (const gchar *filename, - gint max_waste, CoglTextureFlags flags, CoglPixelFormat internal_format, GError **error) @@ -1490,10 +1503,7 @@ cogl_texture_new_from_file (const gchar *filename, if (bmp == COGL_INVALID_HANDLE) return COGL_INVALID_HANDLE; - handle = cogl_texture_new_from_bitmap (bmp, - max_waste, - flags, - internal_format); + handle = cogl_texture_new_from_bitmap (bmp, flags, internal_format); cogl_handle_unref (bmp); return handle; From 344dc626386de4f53d162215370fe3d65170ca95 Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Wed, 27 May 2009 23:39:18 +0100 Subject: [PATCH 03/37] [build] Fixes some compiler warnings when building for GLES 2 There were a number of variables shadowing other symbols, and an unused display variable. --- gles/cogl-gles2-wrapper.c | 20 ++++++++++---------- gles/cogl-primitives.c | 36 ++++++++++++++++++------------------ 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/gles/cogl-gles2-wrapper.c b/gles/cogl-gles2-wrapper.c index 523676dd2..aec15b7a0 100644 --- a/gles/cogl-gles2-wrapper.c +++ b/gles/cogl-gles2-wrapper.c @@ -89,13 +89,13 @@ cogl_gles2_wrapper_create_shader (GLenum type, const char *source) if (!status) { - char log[1024]; + char shader_log[1024]; GLint len; - glGetShaderInfoLog (shader, sizeof (log) - 1, &len, log); - log[len] = '\0'; + glGetShaderInfoLog (shader, sizeof (shader_log) - 1, &len, shader_log); + shader_log[len] = '\0'; - g_critical ("%s", log); + g_critical ("%s", shader_log); glDeleteShader (shader); @@ -538,9 +538,9 @@ cogl_gles2_wrapper_get_program (const CoglGles2WrapperSettings *settings) CoglShader *shader = _cogl_shader_pointer_from_handle ((CoglHandle) node->data); - if (shader->type == CGL_VERTEX_SHADER) + if (shader->type == COGL_SHADER_TYPE_VERTEX) custom_vertex_shader = TRUE; - else if (shader->type == CGL_FRAGMENT_SHADER) + else if (shader->type == COGL_SHADER_TYPE_FRAGMENT) custom_fragment_shader = TRUE; } } @@ -581,13 +581,13 @@ cogl_gles2_wrapper_get_program (const CoglGles2WrapperSettings *settings) if (!status) { - char log[1024]; + char shader_log[1024]; GLint len; - glGetProgramInfoLog (program->program, sizeof (log) - 1, &len, log); - log[len] = '\0'; + glGetProgramInfoLog (program->program, sizeof (shader_log) - 1, &len, shader_log); + shader_log[len] = '\0'; - g_critical ("%s", log); + g_critical ("%s", shader_log); glDeleteProgram (program->program); g_slice_free (CoglGles2WrapperProgram, program); diff --git a/gles/cogl-primitives.c b/gles/cogl-primitives.c index 1e03e1ea2..24b6b0759 100644 --- a/gles/cogl-primitives.c +++ b/gles/cogl-primitives.c @@ -361,30 +361,30 @@ _cogl_path_fill_nodes_scanlines (CoglPathNode *path, while (iter) { GSList *next = iter->next; - GLfloat x0, x1; - GLfloat y0, y1; + GLfloat x_0, x_1; + GLfloat y_0, y_1; if (!next) break; - x0 = GPOINTER_TO_INT (iter->data); - x1 = GPOINTER_TO_INT (next->data); - y0 = bounds_y + i; - y1 = bounds_y + i + 1.0625f; + x_0 = GPOINTER_TO_INT (iter->data); + x_1 = GPOINTER_TO_INT (next->data); + y_0 = bounds_y + i; + y_1 = bounds_y + i + 1.0625f; /* render scanlines 1.0625 high to avoid gaps when transformed */ - coords[span_no * 12 + 0] = x0; - coords[span_no * 12 + 1] = y0; - coords[span_no * 12 + 2] = x1; - coords[span_no * 12 + 3] = y0; - coords[span_no * 12 + 4] = x1; - coords[span_no * 12 + 5] = y1; - coords[span_no * 12 + 6] = x0; - coords[span_no * 12 + 7] = y0; - coords[span_no * 12 + 8] = x0; - coords[span_no * 12 + 9] = y1; - coords[span_no * 12 + 10] = x1; - coords[span_no * 12 + 11] = y1; + coords[span_no * 12 + 0] = x_0; + coords[span_no * 12 + 1] = y_0; + coords[span_no * 12 + 2] = x_1; + coords[span_no * 12 + 3] = y_0; + coords[span_no * 12 + 4] = x_1; + coords[span_no * 12 + 5] = y_1; + coords[span_no * 12 + 6] = x_0; + coords[span_no * 12 + 7] = y_0; + coords[span_no * 12 + 8] = x_0; + coords[span_no * 12 + 9] = y_1; + coords[span_no * 12 + 10] = x_1; + coords[span_no * 12 + 11] = y_1; span_no ++; iter = next->next; } From bc8a18ebc38fb5bde2bd23e080b2d2228a9a9f08 Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Mon, 11 May 2009 00:40:41 +0100 Subject: [PATCH 04/37] [cogl-material] Support string based blending and layer combine descriptions Setting up layer combine functions and blend modes is very awkward to do programatically. This adds a parser for string based descriptions which are more consise and readable. E.g. a material layer combine function could now be given as: "RGBA = ADD (TEXTURE[A], PREVIOUS[RGB])" or "RGB = REPLACE (PREVIOUS)" "A = MODULATE (PREVIOUS, TEXTURE)" The simple syntax and grammar are only designed to expose standard fixed function hardware, more advanced combining must be done with shaders. This includes standalone documentation of blend strings covering the aspects that are common to blending and texture combining, and adds documentation with examples specific to the new cogl_material_set_blend() and cogl_material_layer_set_combine() functions. Note: The hope is to remove the now redundant bits of the material API before 1.0 --- cogl-debug.h | 20 +- cogl-material.h | 244 ++++++- common/Makefile.am | 2 + common/cogl-blend-string.c | 999 +++++++++++++++++++++++++++ common/cogl-blend-string.h | 151 ++++ common/cogl-debug.c | 3 +- common/cogl-material-private.h | 13 +- common/cogl-material.c | 406 ++++++++++- doc/reference/cogl/Makefile.am | 9 +- doc/reference/cogl/blend-strings.xml | 130 ++++ doc/reference/cogl/cogl-docs.xml | 1 + doc/reference/cogl/cogl-sections.txt | 4 + gl/cogl-context.c | 3 + gl/cogl-context.h | 3 + gl/cogl-defines.h.in | 12 + gl/cogl.c | 10 + gles/cogl-gles2-wrapper.c | 9 +- gles/cogl-gles2-wrapper.h | 5 +- gles/cogl-texture.c | 49 +- 19 files changed, 1990 insertions(+), 83 deletions(-) create mode 100644 common/cogl-blend-string.c create mode 100644 common/cogl-blend-string.h create mode 100644 doc/reference/cogl/blend-strings.xml diff --git a/cogl-debug.h b/cogl-debug.h index b31a36c52..8aa1e8f87 100644 --- a/cogl-debug.h +++ b/cogl-debug.h @@ -29,15 +29,16 @@ G_BEGIN_DECLS typedef enum { - COGL_DEBUG_MISC = 1 << 0, - COGL_DEBUG_TEXTURE = 1 << 1, - COGL_DEBUG_MATERIAL = 1 << 2, - COGL_DEBUG_SHADER = 1 << 3, - COGL_DEBUG_OFFSCREEN = 1 << 4, - COGL_DEBUG_DRAW = 1 << 5, - COGL_DEBUG_PANGO = 1 << 6, - COGL_DEBUG_RECTANGLES = 1 << 7, - COGL_DEBUG_HANDLE = 1 << 8 + COGL_DEBUG_MISC = 1 << 0, + COGL_DEBUG_TEXTURE = 1 << 1, + COGL_DEBUG_MATERIAL = 1 << 2, + COGL_DEBUG_SHADER = 1 << 3, + COGL_DEBUG_OFFSCREEN = 1 << 4, + COGL_DEBUG_DRAW = 1 << 5, + COGL_DEBUG_PANGO = 1 << 6, + COGL_DEBUG_RECTANGLES = 1 << 7, + COGL_DEBUG_HANDLE = 1 << 8, + COGL_DEBUG_BLEND_STRINGS = 1 << 9 } CoglDebugFlags; #ifdef COGL_ENABLE_DEBUG @@ -69,3 +70,4 @@ extern guint cogl_debug_flags; G_END_DECLS #endif /* __COGL_DEBUG_H__ */ + diff --git a/cogl-material.h b/cogl-material.h index 95a474831..d69ae276c 100644 --- a/cogl-material.h +++ b/cogl-material.h @@ -43,7 +43,6 @@ G_BEGIN_DECLS * blended together. */ - /** * cogl_material_new: * @@ -378,10 +377,12 @@ void cogl_material_set_alpha_test_function (CoglHandle material, * @COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA: (1-As, 1-As, 1-As, 1-As) * @COGL_MATERIAL_BLEND_FACTOR_DST_ALPHA: (Ad, Ad, Ad, Ad) * @COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_DST_ALPHA: (1-Ad, 1-Ad, 1-Ad, 1-Ad) + * @COGL_MATERIAL_BLEND_FACTOR_CONSTANT: (Rc, Gc, Bc, Ac) + * @COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_CONSTANT: (1-Rc, 1-Gc, 1-Bc, 1-Ac) + * @COGL_MATERIAL_BLEND_FACTOR_CONSTANT_ALPHA: (Ac, Ac, Ac, Ac) + * @COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA: (1-Ac, 1-Ac, 1-Ac, 1-Ac) * @COGL_MATERIAL_BLEND_FACTOR_SRC_ALPHA_SATURATE: (f,f,f,1) where f=MIN(As,1-Ad) * - * Blending occurs after the alpha test function, and combines fragments with - * the framebuffer. * * A fixed function is used to determine the blended color, which is based on * the incoming source color of your fragment (Rs, Gs, Bs, As), a source @@ -411,6 +412,14 @@ typedef enum _CoglMaterialBlendFactor COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA = GL_ONE_MINUS_SRC_ALPHA, COGL_MATERIAL_BLEND_FACTOR_DST_ALPHA = GL_DST_ALPHA, COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_DST_ALPHA = GL_ONE_MINUS_DST_ALPHA, +#ifdef HAVE_COGL_GL + COGL_MATERIAL_BLEND_FACTOR_CONSTANT = GL_CONSTANT_COLOR, + COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_CONSTANT = + GL_ONE_MINUS_CONSTANT_COLOR, + COGL_MATERIAL_BLEND_FACTOR_CONSTANT_ALPHA = GL_CONSTANT_ALPHA, + COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA = + GL_ONE_MINUS_CONSTANT_ALPHA, +#endif COGL_MATERIAL_BLEND_FACTOR_SRC_ALPHA_SATURATE = GL_SRC_ALPHA_SATURATE, } CoglMaterialBlendFactor; @@ -442,6 +451,92 @@ void cogl_material_set_blend_factors (CoglHandle material, CoglMaterialBlendFactor src_factor, CoglMaterialBlendFactor dst_factor); +/** + * cogl_material_set_blend: + * @material: A CoglMaterial object + * @blend_string: A Cogl blend string + * describing the desired blend function. + * @error: A GError that may report lack of driver support if you give + * separate blend string statements for the alpha channel and RGB + * channels since some drivers or backends such as GLES 1.1 dont + * support this. + * + * If not already familiar; please refer + * here for an overview of what blend + * strings are and there syntax. + * + * Blending occurs after the alpha test function, and combines fragments with + * the framebuffer. + + * Currently the only blend function Cogl exposes is ADD(). So any valid + * blend statements will be of the form: + * + * + * <channel-mask>=ADD(SRC_COLOR*(<factor>), DST_COLOR*(<factor>)) + * + * + * NOTE: The brackets around blend factors are currently not optional! + * + * This is the list of source-names usable as blend factors: + * + * SRC_COLOR: The color of the in comming fragment + * DST_COLOR: The color of the framebuffer + * + * CONSTANT: The constant set via cogl_material_set_blend_constant() + * + * The source names can be used according to the + * color-source and factor syntax, + * so for example "(1-SRC_COLOR[A])" would be a valid factor, as would + * "(CONSTANT[RGB])" + * + * These can also be used as factors: + * + * 0: (0, 0, 0, 0) + * 1: (1, 1, 1, 1) + * SRC_ALPHA_SATURATE_FACTOR: (f,f,f,1) + * where f=MIN(SRC_COLOR[A],1-DST_COLOR[A]) + * + * + * Remember; all color components are normalized to the range [0, 1] before + * computing the result of blending. + * + *
+ * Examples + * Blend a non-premultiplied source over a destination with + * premultiplied alpha: + * + * "RGB = ADD(SRC_COLOR*(SRC_COLOR[A]), DST_COLOR*(1-SRC_COLOR[A]))" + * "A = ADD(SRC_COLOR, DST_COLOR*(1-SRC_COLOR[A]))" + * + * Blend a premultiplied source over a destination with premultiplied alpha: + * + * "RGBA = ADD(SRC_COLOR, DST_COLOR*(1-SRC_COLOR[A]))" + * + *
+ * + * Returns: TRUE if the blend string was successfully parsed, and the described + * blending is supported by the underlying driver/hardware. If there + * was an error, it returns FALSE. + * + * Since: 1.0 + */ +gboolean cogl_material_set_blend (CoglHandle material, + const char *blend_string, + GError **error); + +/** + * cogl_material_set_blend_constant: + * @material: A CoglMaterial object + * @constant_color: The constant color you want + * + * When blending is setup to reference a CONSTANT blend factor then + * blending will depend on the constant set with this function. + * + * Since: 1.0 + */ +void cogl_material_set_blend_constant (CoglHandle material, + CoglColor *constant_color); + /** * cogl_material_set_layer: * @material: A CoglMaterial object @@ -460,7 +555,7 @@ void cogl_material_set_blend_factors (CoglHandle material, * Since 1.0 */ void cogl_material_set_layer (CoglHandle material, - gint layer_index, + int layer_index, CoglHandle texture); /** @@ -473,6 +568,113 @@ void cogl_material_set_layer (CoglHandle material, void cogl_material_remove_layer (CoglHandle material, gint layer_index); + +/** + * cogl_material_set_layer_combine: + * @material: A CoglMaterial object + * @layer_index: Specifies the layer you want define a combine function for + * @blend_string: A Cogl blend string + * describing the desired texture combine function. + * @error: A GError that may report parse errors or lack of GPU/driver support. + * + * If not already familiar; you can refer + * here for an overview of what blend + * strings are and there syntax. + * + * These are all the functions available for texture combining: + * + * REPLACE(arg0) = arg0 + * MODULATE(arg0, arg1) = arg0 x arg1 + * ADD(arg0, arg1) = arg0 + arg1 + * ADD_SIGNED(arg0, arg1) = arg0 + arg1 - 0.5 + * INTERPOLATE(arg0, arg1, arg2) = + * arg0 x arg2 + arg1 x (1 - arg2) + * SUBTRACT(arg0, arg1) = arg0 - arg1 + * + * DOT3_RGB(arg0, arg1) = + * + * 4 x ((arg0[R] - 0.5)) * (arg1[R] - 0.5) + + * (arg0[G] - 0.5)) * (arg1[G] - 0.5) + + * (arg0[B] - 0.5)) * (arg1[B] - 0.5)) + * + * + * DOT3_RGBA(arg0, arg1) = + * + * 4 x ((arg0[R] - 0.5)) * (arg1[R] - 0.5) + + * (arg0[G] - 0.5)) * (arg1[G] - 0.5) + + * (arg0[B] - 0.5)) * (arg1[B] - 0.5)) + * + * + * + * + * Refer to the + * color-source syntax for + * describing the arguments. The valid source names for texture combining + * are: + * + * + * TEXTURE: Use the color from the current texture layer + * + * + * TEXTURE_0, TEXTURE_1, etc: Use the color from the specified texture layer + * + * + * CONSTANT: Use the color from the constant given with + * cogl_material_set_layer_constant() + * + * + * PRIMARY: Use the color of the material as set with cogl_material_set_color() + * + * + * PREVIOUS: Either use the texture color from the previous layer, or if this + * is layer 0, use the color of the material as set with + * cogl_material_set_color() + * + * + *
+ * Example + * This is effectively what the default blending is: + * + * "RGBA = MODULATE (PREVIOUS, TEXTURE)" + * + * This could be used to cross-fade between two images, using the alpha + * component of a constant as the interpolator. The constant color + * is given by calling cogl_material_set_layer_constant. + * + * RGBA = INTERPOLATE (PREVIOUS, TEXTURE, CONSTANT[A]) + * + *
+ * Note: you can't give a multiplication factor for arguments as you can + * with blending. + * + * Returns: TRUE if the blend string was successfully parsed, and the described + * texture combining is supported by the underlying driver/hardware. + * If there was an error, it returns FALSE. + * + * Since: 1.0 + */ +gboolean +cogl_material_set_layer_combine (CoglHandle material, + gint layer_index, + const char *blend_string, + GError **error); + +/** + * cogl_material_set_layer_combine_constant: + * @material: A CoglMaterial object + * @layer_index: Specifies the layer you want to specify a constant used + * for texture combining + * @color_constant: The constant color you want + * + * When you are using the 'CONSTANT' color source in a layer combine + * description then you can use this function to define its value. + * + * Since 1.0 + */ +void cogl_material_set_layer_combine_constant (CoglHandle material, + int layer_index, + CoglColor *constant); + /** * CoglMaterialLayerCombineFunc: * @COGL_MATERIAL_LAYER_COMBINE_FUNC_REPLACE: Arg0 @@ -600,7 +802,7 @@ typedef enum _CoglMaterialLayerCombineChannels * */ void cogl_material_set_layer_combine_function (CoglHandle material, - gint layer_index, + int layer_index, CoglMaterialLayerCombineChannels channels, CoglMaterialLayerCombineFunc func); @@ -650,8 +852,8 @@ typedef enum _CoglMaterialLayerCombineSrc * */ void cogl_material_set_layer_combine_arg_src (CoglHandle material, - gint layer_index, - gint argument, + int layer_index, + int argument, CoglMaterialLayerCombineChannels channels, CoglMaterialLayerCombineSrc src); @@ -674,33 +876,11 @@ typedef enum _CoglMaterialLayerCombineOp * */ void cogl_material_set_layer_combine_arg_op (CoglHandle material, - gint layer_index, - gint argument, + int layer_index, + int argument, CoglMaterialLayerCombineChannels channels, CoglMaterialLayerCombineOp op); -/* TODO: */ -#if 0 - I think it would be be really neat to support a simple string description - of the fixed function texture combine modes exposed above. I think we can - consider this stuff to be set in stone from the POV that more advanced - texture combine functions are catered for with GLSL, so it seems reasonable - to find a concise string representation that can represent all the above - modes in a *much* more readable/useable fashion. I think somthing like - this would be quite nice: - - "MODULATE(TEXTURE[RGB], PREVIOUS[A])" - "ADD(TEXTURE[A],PREVIOUS[RGB])" - "INTERPOLATE(TEXTURE[1-A], PREVIOUS[RGB])" - -void cogl_material_set_layer_rgb_combine (CoglHandle material - gint layer_index, - const char *combine_description); -void cogl_material_set_layer_alpha_combine (CoglHandle material - gint layer_index, - const char *combine_description); -#endif - /** * cogl_material_set_layer_matrix: * @material: A CoglMaterial object @@ -709,7 +889,7 @@ void cogl_material_set_layer_alpha_combine (CoglHandle material * and rotate a single layer of a material used to fill your geometry. */ void cogl_material_set_layer_matrix (CoglHandle material, - gint layer_index, + int layer_index, CoglMatrix *matrix); diff --git a/common/Makefile.am b/common/Makefile.am index 138893a14..c4e6eb2f7 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -39,4 +39,6 @@ libclutter_cogl_common_la_SOURCES = \ cogl-matrix-stack.h \ cogl-material.c \ cogl-material-private.h \ + cogl-blend-string.c \ + cogl-blend-string.h \ cogl-debug.c diff --git a/common/cogl-blend-string.c b/common/cogl-blend-string.c new file mode 100644 index 000000000..2e7bdd8d3 --- /dev/null +++ b/common/cogl-blend-string.c @@ -0,0 +1,999 @@ +/* + * Cogl + * + * An object oriented GL/GLES Abstraction/Utility Layer + * + * Copyright (C) 2009 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, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Authors: + * Robert Bragg + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include + +#include "cogl.h" +#include "cogl-internal.h" +#include "cogl-context.h" +#include "cogl-debug.h" +#include "cogl-blend-string.h" + +typedef enum _ParserState +{ + PARSER_STATE_EXPECT_DEST_CHANNELS, + PARSER_STATE_SCRAPING_DEST_CHANNELS, + PARSER_STATE_EXPECT_FUNCTION_NAME, + PARSER_STATE_SCRAPING_FUNCTION_NAME, + PARSER_STATE_EXPECT_ARG_START, + PARSER_STATE_EXPECT_STATEMENT_END +} ParserState; + +typedef enum _ParserArgState +{ + PARSER_ARG_STATE_START, + PARSER_ARG_STATE_EXPECT_MINUS, + PARSER_ARG_STATE_EXPECT_COLOR_SRC_NAME, + PARSER_ARG_STATE_SCRAPING_COLOR_SRC_NAME, + PARSER_ARG_STATE_MAYBE_COLOR_MASK, + PARSER_ARG_STATE_SCRAPING_MASK, + PARSER_ARG_STATE_MAYBE_MULT, + PARSER_ARG_STATE_EXPECT_OPEN_PAREN, + PARSER_ARG_STATE_EXPECT_FACTOR, + PARSER_ARG_STATE_MAYBE_SRC_ALPHA_SATURATE, + PARSER_ARG_STATE_MAYBE_MINUS, + PARSER_ARG_STATE_EXPECT_CLOSE_PAREN, + PARSER_ARG_STATE_EXPECT_END +} ParserArgState; + + +#define DEFINE_COLOR_SOURCE(NAME, NAME_LEN) \ + {.type = COGL_BLEND_STRING_COLOR_SOURCE_ ## NAME, \ + .name = #NAME, \ + .name_len = NAME_LEN} + +static CoglBlendStringColorSourceInfo blending_color_sources[] = { + DEFINE_COLOR_SOURCE (SRC_COLOR, 9), + DEFINE_COLOR_SOURCE (DST_COLOR, 9), + DEFINE_COLOR_SOURCE (CONSTANT, 8) +}; + +static CoglBlendStringColorSourceInfo tex_combine_color_sources[] = { + DEFINE_COLOR_SOURCE (TEXTURE, 7), + /* DEFINE_COLOR_SOURCE (TEXTURE_N, *) - handled manually */ + DEFINE_COLOR_SOURCE (PRIMARY, 7), + DEFINE_COLOR_SOURCE (CONSTANT, 8), + DEFINE_COLOR_SOURCE (PREVIOUS, 8) +}; + +static CoglBlendStringColorSourceInfo tex_combine_texture_n_color_source = { + .type = COGL_BLEND_STRING_COLOR_SOURCE_TEXTURE_N, + .name = "TEXTURE_N", + .name_len = 0 +}; + +#undef DEFINE_COLOR_SOURCE + +#define DEFINE_FUNCTION(NAME, NAME_LEN, ARGC) \ + { .type = COGL_BLEND_STRING_FUNCTION_ ## NAME, \ + .name = #NAME, \ + .name_len = NAME_LEN, \ + .argc = ARGC } + +/* NB: These must be sorted so any name that's a subset of another + * comes later than the longer name. */ +static CoglBlendStringFunctionInfo tex_combine_functions[] = { + DEFINE_FUNCTION (AUTO_COMPOSITE, 14, 0), + DEFINE_FUNCTION (REPLACE, 7, 1), + DEFINE_FUNCTION (MODULATE, 8, 2), + DEFINE_FUNCTION (ADD_SIGNED, 10, 2), + DEFINE_FUNCTION (ADD, 3, 2), + DEFINE_FUNCTION (INTERPOLATE, 11, 3), + DEFINE_FUNCTION (SUBTRACT, 8, 2), + DEFINE_FUNCTION (DOT3_RGBA, 9, 2), + DEFINE_FUNCTION (DOT3_RGB, 8, 2) +}; + +static CoglBlendStringFunctionInfo blend_functions[] = { + DEFINE_FUNCTION (AUTO_COMPOSITE, 14, 0), + DEFINE_FUNCTION (ADD, 3, 2) +}; + +#undef DEFINE_FUNCTION + +GQuark +_cogl_blend_string_error_quark (void) +{ + return g_quark_from_static_string ("cogl-blend-string-error-quark"); +} + +void +_cogl_blend_string_split_rgba_statement (CoglBlendStringStatement *statement, + CoglBlendStringStatement *rgb, + CoglBlendStringStatement *a) +{ + int i; + + memcpy (rgb, statement, sizeof (CoglBlendStringStatement)); + memcpy (a, statement, sizeof (CoglBlendStringStatement)); + + rgb->mask = COGL_BLEND_STRING_CHANNEL_MASK_RGB; + a->mask = COGL_BLEND_STRING_CHANNEL_MASK_ALPHA; + + for (i = 0; i < statement->function->argc; i++) + { + CoglBlendStringArgument *arg = &statement->args[i]; + CoglBlendStringArgument *rgb_arg = &rgb->args[i]; + CoglBlendStringArgument *a_arg = &a->args[i]; + + if (arg->source.mask == COGL_BLEND_STRING_CHANNEL_MASK_RGBA) + { + rgb_arg->source.mask = COGL_BLEND_STRING_CHANNEL_MASK_RGB; + a_arg->source.mask = COGL_BLEND_STRING_CHANNEL_MASK_ALPHA; + } + + if (arg->factor.is_color && + arg->factor.source.mask == COGL_BLEND_STRING_CHANNEL_MASK_RGBA) + { + rgb_arg->factor.source.mask = COGL_BLEND_STRING_CHANNEL_MASK_RGB; + a_arg->factor.source.mask = COGL_BLEND_STRING_CHANNEL_MASK_ALPHA; + } + } +} + +static gboolean +validate_tex_combine_statements (CoglBlendStringStatement *statements, + int n_statements, + GError **error) +{ + int i, j; + const char *error_string; + CoglBlendStringError detail = COGL_BLEND_STRING_ERROR_INVALID_ERROR; + + for (i = 0; i < n_statements; i++) + { +#ifdef HAVE_COGL_GLES2 + if (statements[i].function->type != COGL_BLEND_STRING_FUNCTION_MODULATE) + { + error_string = "Using anything but MODULATE() for texture combining" + " under GLES 2 is currently unsupported"; + detail = COGL_BLEND_STRING_ERROR_GPU_UNSUPPORTED_ERROR; + goto error; + } +#endif + for (j = 0; j < statements[i].function->argc; j++) + { + CoglBlendStringArgument *arg = &statements[i].args[j]; + if (arg->source.is_zero) + { + error_string = "You can't use the constant '0' as a texture " + "combine argument"; + goto error; + } + if (!arg->factor.is_one) + { + error_string = "Argument factors are only relevant to blending " + "not texture combining"; + goto error; + } +#ifdef HAVE_COGL_GLES2 + if (arg->source.info->type == COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT) + { + error_string = "Using a constant for texture combining isn't " + "currently supported with GLES 2 " + "(TODO: glTexEnvf)"; + detail = COGL_BLEND_STRING_ERROR_GPU_UNSUPPORTED_ERROR; + goto error; + } +#endif + } + } + + return TRUE; + +error: + g_set_error (error, + COGL_BLEND_STRING_ERROR, + detail, + "Invalid texture combine string: %s", + error_string); + + if (cogl_debug_flags & COGL_DEBUG_BLEND_STRINGS) + { + g_debug ("Invalid texture combine string: %s", + error_string); + } + return FALSE; +} + +static gboolean +validate_blend_statements (CoglBlendStringStatement *statements, + int n_statements, + GError **error) +{ + int i, j; + const char *error_string; + CoglBlendStringError detail = COGL_BLEND_STRING_ERROR_INVALID_ERROR; + +#ifdef HAVE_COGL_GL + _COGL_GET_CONTEXT (ctx, 0); +#endif + +#ifdef HAVE_COGL_GL + if (n_statements == 2) + { + /* glBlendEquationSeperate is GL 2.0 only */ + if (!ctx->pf_glBlendEquationSeparate && + statements[0].function->type != statements[1].function->type) + { + error_string = "Separate blend functions for the RGB an A " + "channels isn't supported by the driver"; + detail = COGL_BLEND_STRING_ERROR_GPU_UNSUPPORTED_ERROR; + goto error; + } + } +#elif defined(HAVE_COGL_GLES) + if (n_statements != 1) + { + error_string = "Separate blend functions for the RGB an A " + "channels isn't supported by the GLES 1"; + detail = COGL_BLEND_STRING_ERROR_GPU_UNSUPPORTED_ERROR; + goto error; + } +#endif + + for (i = 0; i < n_statements; i++) + for (j = 0; j < statements[i].function->argc; j++) + { + CoglBlendStringArgument *arg = &statements[i].args[j]; + + if (arg->source.is_zero) + continue; + + if ((j == 0 && + arg->source.info->type != + COGL_BLEND_STRING_COLOR_SOURCE_SRC_COLOR) + || (j == 1 && + arg->source.info->type != + COGL_BLEND_STRING_COLOR_SOURCE_DST_COLOR)) + { + error_string = "For blending you must always use SRC_COLOR " + "for arg0 and DST_COLOR for arg1"; + goto error; + } + +#ifdef HAVE_COGL_GLES + if (arg->factor.is_color && + arg->factor.source.info->type == COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT) + { + error_string = "GLES Doesn't support constant blend factors"; + detail = COGL_BLEND_STRING_ERROR_GPU_UNSUPPORTED_ERROR; + goto error; + } +#endif + } + + return TRUE; + +error: + g_set_error (error, + COGL_BLEND_STRING_ERROR, + detail, + "Invalid blend string: %s", + error_string); + return FALSE; +} + +static gboolean +validate_statements_for_context (CoglBlendStringStatement *statements, + int n_statements, + CoglBlendStringContext context, + GError **error) +{ + const char *error_string; + + if (n_statements == 1) + { + if (statements[0].mask == COGL_BLEND_STRING_CHANNEL_MASK_ALPHA) + { + error_string = "You need to also give a blend statement for the RGB" + "channels"; + goto error; + } + else if (statements[0].mask == COGL_BLEND_STRING_CHANNEL_MASK_RGB) + { + error_string = "You need to also give a blend statement for the " + "Alpha channel"; + goto error; + } + } + + if (context == COGL_BLEND_STRING_CONTEXT_BLENDING) + return validate_blend_statements (statements, n_statements, error); + else + return validate_tex_combine_statements (statements, n_statements, error); + +error: + g_set_error (error, + COGL_BLEND_STRING_ERROR, + COGL_BLEND_STRING_ERROR_INVALID_ERROR, + "Invalid %s string: %s", + context == COGL_BLEND_STRING_CONTEXT_BLENDING ? + "blend" : "texture combine", + error_string); + + if (cogl_debug_flags & COGL_DEBUG_BLEND_STRINGS) + { + g_debug ("Invalid %s string: %s", + context == COGL_BLEND_STRING_CONTEXT_BLENDING ? + "blend" : "texture combine", + error_string); + } + + return FALSE; +} + +static void +print_argument (CoglBlendStringArgument *arg) +{ + const char *mask_names[] = { + "RGB", + "A", + "RGBA" + }; + + g_print (" Arg:\n"); + g_print (" is zero = %s\n", arg->source.is_zero ? "yes" : "no"); + if (!arg->source.is_zero) + { + g_print (" color source = %s\n", arg->source.info->name); + g_print (" one minus = %s\n", arg->source.one_minus ? "yes" : "no"); + g_print (" mask = %s\n", mask_names[arg->source.mask]); + g_print (" texture = %d\n", arg->source.texture); + g_print ("\n"); + g_print (" factor is_one = %s\n", arg->factor.is_one ? "yes" : "no"); + g_print (" factor is_src_alpha_saturate = %s\n", + arg->factor.is_src_alpha_saturate ? "yes" : "no"); + g_print (" factor is_color = %s\n", arg->factor.is_color ? "yes" : "no"); + if (arg->factor.is_color) + { + g_print (" factor color:is zero = %s\n", + arg->factor.source.is_zero ? "yes" : "no"); + g_print (" factor color:color source = %s\n", + arg->factor.source.info->name); + g_print (" factor color:one minus = %s\n", + arg->factor.source.one_minus ? "yes" : "no"); + g_print (" factor color:mask = %s\n", + mask_names[arg->factor.source.mask]); + g_print (" factor color:texture = %d\n", + arg->factor.source.texture); + } + } +} + +static void +print_statement (int num, CoglBlendStringStatement *statement) +{ + const char *mask_names[] = { + "RGB", + "A", + "RGBA" + }; + int i; + g_print ("Statement %d:\n", num); + g_print (" Destination channel mask = %s\n", + mask_names[statement->mask]); + g_print (" Function = %s\n", statement->function->name); + for (i = 0; i < statement->function->argc; i++) + print_argument (&statement->args[i]); +} + +static const CoglBlendStringFunctionInfo * +get_function_info (const char *mark, + const char *p, + CoglBlendStringContext context) +{ + size_t len = p - mark; + CoglBlendStringFunctionInfo *functions; + size_t array_len; + int i; + + if (context == COGL_BLEND_STRING_CONTEXT_BLENDING) + { + functions = blend_functions; + array_len = G_N_ELEMENTS (blend_functions); + } + else + { + functions = tex_combine_functions; + array_len = G_N_ELEMENTS (tex_combine_functions); + } + + for (i = 0; i < array_len; i++) + { + if (len >= functions[i].name_len + && strncmp (mark, functions[i].name, functions[i].name_len) == 0) + return &functions[i]; + } + return NULL; +} + +static const CoglBlendStringColorSourceInfo * +get_color_src_info (const char *mark, + const char *p, + CoglBlendStringContext context) +{ + size_t len = p - mark; + CoglBlendStringColorSourceInfo *sources; + size_t array_len; + int i; + + if (context == COGL_BLEND_STRING_CONTEXT_BLENDING) + { + sources = blending_color_sources; + array_len = G_N_ELEMENTS (blending_color_sources); + } + else + { + sources = tex_combine_color_sources; + array_len = G_N_ELEMENTS (tex_combine_color_sources); + } + + for (i = 0; i < array_len; i++) + { + if (len >= sources[i].name_len + && strncmp (mark, sources[i].name, sources[i].name_len) == 0) + return &sources[i]; + } + + if (len >= 9 && + strncmp (mark, "TEXTURE_", 8) == 0 && + g_ascii_isdigit (mark[8])) + { + return &tex_combine_texture_n_color_source; + } + + return NULL; +} + +static gboolean +is_symbol_char (const char c) +{ + return (g_ascii_isalpha (c) || c == '_') ? TRUE : FALSE; +} + +static gboolean +parse_argument (const char *string, /* original user string */ + const char **ret_p, /* start of argument IN:OUT */ + const CoglBlendStringStatement *statement, + int current_arg, + CoglBlendStringArgument *arg, /* OUT */ + CoglBlendStringContext context, + GError **error) +{ + const char *p = *ret_p; + const char *mark; + const char *error_string; + ParserArgState state = PARSER_ARG_STATE_START; + gboolean parsing_factor = FALSE; + + arg->source.is_zero = FALSE; + arg->source.info = NULL; + arg->source.texture = 0; + arg->source.one_minus = FALSE; + arg->source.mask = statement->mask; + + arg->factor.is_one = FALSE; + arg->factor.is_color = FALSE; + arg->factor.is_src_alpha_saturate = FALSE; + + arg->factor.source.is_zero = FALSE; + arg->factor.source.info = NULL; + arg->factor.source.texture = 0; + arg->factor.source.one_minus = FALSE; + arg->factor.source.mask = statement->mask; + + do + { + if (g_ascii_isspace (*p)) + continue; + + if (*p == '\0') + { + error_string = "Unexpected end of string while parsing argument"; + goto error; + } + + switch (state) + { + case PARSER_ARG_STATE_START: + if (*p == '1') + state = PARSER_ARG_STATE_EXPECT_MINUS; + else if (*p == '0') + { + arg->source.is_zero = TRUE; + state = PARSER_ARG_STATE_EXPECT_END; + } + else + { + p--; /* backtrack */ + state = PARSER_ARG_STATE_EXPECT_COLOR_SRC_NAME; + } + continue; + + case PARSER_ARG_STATE_EXPECT_MINUS: + if (*p != '-') + { + error_string = "expected a '-' following the 1"; + goto error; + } + arg->source.one_minus = TRUE; + state = PARSER_ARG_STATE_EXPECT_COLOR_SRC_NAME; + continue; + + case PARSER_ARG_STATE_EXPECT_COLOR_SRC_NAME: + if (!is_symbol_char (*p)) + { + error_string = "expected a color source name"; + goto error; + } + state = PARSER_ARG_STATE_SCRAPING_COLOR_SRC_NAME; + mark = p; + if (parsing_factor) + arg->factor.is_color = TRUE; + + /* fall through */ + case PARSER_ARG_STATE_SCRAPING_COLOR_SRC_NAME: + if (!is_symbol_char (*p)) + { + CoglBlendStringColorSource *source = + parsing_factor ? &arg->factor.source : &arg->source; + source->info = get_color_src_info (mark, p, context); + if (!source->info) + { + error_string = "Unknown color source name"; + goto error; + } + if (source->info->type == + COGL_BLEND_STRING_COLOR_SOURCE_TEXTURE_N) + { + char *endp; + source->texture = + strtoul (&mark[strlen ("TEXTURE_")], &endp, 10); + if (mark == endp) + { + error_string = "invalid texture number given with " + "TEXTURE_N color source"; + goto error; + } + p = endp; + } + state = PARSER_ARG_STATE_MAYBE_COLOR_MASK; + } + else + continue; + + /* fall through */ + case PARSER_ARG_STATE_MAYBE_COLOR_MASK: + if (*p != '[') + { + p--; /* backtrack */ + if (!parsing_factor) + state = PARSER_ARG_STATE_MAYBE_MULT; + else + state = PARSER_ARG_STATE_EXPECT_END; + continue; + } + state = PARSER_ARG_STATE_SCRAPING_MASK; + mark = p; + + /* fall through */ + case PARSER_ARG_STATE_SCRAPING_MASK: + if (*p == ']') + { + size_t len = p - mark; + CoglBlendStringColorSource *source = + parsing_factor ? &arg->factor.source : &arg->source; + + if (len == 5 && strncmp (mark, "[RGBA", len) == 0) + { + if (statement->mask != COGL_BLEND_STRING_CHANNEL_MASK_RGBA) + { + error_string = "You can't use an RGBA color mask if the " + "statement hasn't also got an RGBA= mask"; + goto error; + } + source->mask = COGL_BLEND_STRING_CHANNEL_MASK_RGBA; + } + else if (len == 4 && strncmp (mark, "[RGB", len) == 0) + source->mask = COGL_BLEND_STRING_CHANNEL_MASK_RGB; + else if (len == 2 && strncmp (mark, "[A", len) == 0) + source->mask = COGL_BLEND_STRING_CHANNEL_MASK_ALPHA; + else + { + error_string = "Expected a channel mask of [RGBA]" + "[RGB] or [A]"; + goto error; + } + if (parsing_factor) + state = PARSER_ARG_STATE_EXPECT_CLOSE_PAREN; + else + state = PARSER_ARG_STATE_MAYBE_MULT; + } + continue; + + case PARSER_ARG_STATE_EXPECT_OPEN_PAREN: + if (*p != '(') + { + error_string = "Expected '(' before blend factor - the parser " + "currently requires that all blend factors " + "following a '*' be surrounded in brackets"; + goto error; + } + parsing_factor = TRUE; + state = PARSER_ARG_STATE_EXPECT_FACTOR; + continue; + + case PARSER_ARG_STATE_EXPECT_FACTOR: + if (*p == '1') + state = PARSER_ARG_STATE_MAYBE_MINUS; + else if (*p == '0') + { + arg->source.is_zero = TRUE; + state = PARSER_ARG_STATE_EXPECT_CLOSE_PAREN; + } + else + { + state = PARSER_ARG_STATE_MAYBE_SRC_ALPHA_SATURATE; + mark = p; + } + continue; + + case PARSER_ARG_STATE_MAYBE_SRC_ALPHA_SATURATE: + if (!is_symbol_char (*p)) + { + size_t len = p - mark; + if (len >= strlen ("SRC_ALPHA_SATURATE") && + strncmp (mark, "SRC_ALPHA_SATURATE", len) == 0) + { + arg->factor.is_src_alpha_saturate = TRUE; + state = PARSER_ARG_STATE_EXPECT_CLOSE_PAREN; + } + else + { + state = PARSER_ARG_STATE_EXPECT_COLOR_SRC_NAME; + p = mark - 1; /* backtrack */ + } + } + continue; + + case PARSER_ARG_STATE_MAYBE_MINUS: + if (*p == '-') + { + arg->factor.source.one_minus = TRUE; + state = PARSER_ARG_STATE_EXPECT_COLOR_SRC_NAME; + } + else + { + arg->factor.is_one = TRUE; + state = PARSER_ARG_STATE_EXPECT_CLOSE_PAREN; + } + continue; + + case PARSER_ARG_STATE_EXPECT_CLOSE_PAREN: + if (*p != ')') + { + error_string = "Expected closing parenthesis after blend factor"; + goto error; + } + state = PARSER_ARG_STATE_EXPECT_END; + continue; + + case PARSER_ARG_STATE_MAYBE_MULT: + if (*p == '*') + { + state = PARSER_ARG_STATE_EXPECT_OPEN_PAREN; + continue; + } + arg->factor.is_one = TRUE; + state = PARSER_ARG_STATE_EXPECT_END; + + /* fall through */ + case PARSER_ARG_STATE_EXPECT_END: + if (*p != ',' && *p != ')') + { + error_string = "expected , or )"; + goto error; + } + + *ret_p = p - 1; + return TRUE; + } + } + while (p++); + +error: + { + int offset = p - string; + g_set_error (error, + COGL_BLEND_STRING_ERROR, + COGL_BLEND_STRING_ERROR_ARGUMENT_PARSE_ERROR, + "Syntax error for argument %d at offset %d: %s", + current_arg, + offset, + error_string); + + if (cogl_debug_flags & COGL_DEBUG_BLEND_STRINGS) + { + g_debug ("Syntax error for argument %d at offset %d: %s", + current_arg, offset, error_string); + } + return FALSE; + } +} + +int +_cogl_blend_string_compile (const char *string, + CoglBlendStringContext context, + CoglBlendStringStatement *statements, + GError **error) +{ + const char *p = string; + const char *mark; + const char *error_string; + ParserState state = PARSER_STATE_EXPECT_DEST_CHANNELS; + CoglBlendStringStatement *statement = statements; + int current_statement = 0; + int current_arg = 0; + int remaining_argc; + +#if 0 + cogl_debug_flags |= COGL_DEBUG_BLEND_STRINGS; +#endif + + if (cogl_debug_flags & COGL_DEBUG_BLEND_STRINGS) + { + COGL_NOTE (BLEND_STRINGS, "Compiling %s string:\n%s\n", + context == COGL_BLEND_STRING_CONTEXT_BLENDING ? + "blend" : "texture combine", + string); + } + + do + { + if (g_ascii_isspace (*p)) + continue; + + if (*p == '\0') + { + switch (state) + { + case PARSER_STATE_EXPECT_DEST_CHANNELS: + if (current_statement != 0) + goto finished; + error_string = "Empty statement"; + goto error; + case PARSER_STATE_SCRAPING_DEST_CHANNELS: + error_string = "Expected an '=' following the destination " + "channel mask"; + goto error; + case PARSER_STATE_EXPECT_FUNCTION_NAME: + error_string = "Expected a function name"; + goto error; + case PARSER_STATE_SCRAPING_FUNCTION_NAME: + error_string = "Expected parenthesis after the function name"; + goto error; + case PARSER_STATE_EXPECT_ARG_START: + error_string = "Expected to find the start of an argument"; + goto error; + case PARSER_STATE_EXPECT_STATEMENT_END: + error_string = "Expected closing parenthesis for statement"; + goto error; + } + } + + switch (state) + { + case PARSER_STATE_EXPECT_DEST_CHANNELS: + mark = p; + state = PARSER_STATE_SCRAPING_DEST_CHANNELS; + + /* fall through */ + case PARSER_STATE_SCRAPING_DEST_CHANNELS: + if (*p != '=') + continue; + if (strncmp (mark, "RGBA", 4) == 0) + statement->mask = COGL_BLEND_STRING_CHANNEL_MASK_RGBA; + else if (strncmp (mark, "RGB", 3) == 0) + statement->mask = COGL_BLEND_STRING_CHANNEL_MASK_RGB; + else if (strncmp (mark, "A", 1) == 0) + statement->mask = COGL_BLEND_STRING_CHANNEL_MASK_ALPHA; + else + { + error_string = "Unknown destination channel mask; " + "expected RGBA=, RGB= or A="; + goto error; + } + state = PARSER_STATE_EXPECT_FUNCTION_NAME; + continue; + + case PARSER_STATE_EXPECT_FUNCTION_NAME: + mark = p; + state = PARSER_STATE_SCRAPING_FUNCTION_NAME; + + /* fall through */ + case PARSER_STATE_SCRAPING_FUNCTION_NAME: + if (*p != '(') + { + if (!is_symbol_char (*p)) + { + error_string = "non alpha numeric character in function" + "name"; + goto error; + } + continue; + } + statement->function = get_function_info (mark, p, context); + if (!statement->function) + { + error_string = "Unknown function name"; + goto error; + } + remaining_argc = statement->function->argc; + current_arg = 0; + state = PARSER_STATE_EXPECT_ARG_START; + + /* fall through */ + case PARSER_STATE_EXPECT_ARG_START: + if (*p != '(' && *p != ',') + continue; + if (remaining_argc) + { + p++; /* parse_argument expects to see the first char of the arg */ + if (!parse_argument (string, &p, statement, + current_arg, &statement->args[current_arg], + context, error)) + return 0; + current_arg++; + remaining_argc--; + } + if (!remaining_argc) + state = PARSER_STATE_EXPECT_STATEMENT_END; + continue; + + case PARSER_STATE_EXPECT_STATEMENT_END: + if (*p != ')') + { + error_string = "Expected end of statement"; + goto error; + } + state = PARSER_STATE_EXPECT_DEST_CHANNELS; + if (current_statement++ == 1) + goto finished; + statement = &statements[current_statement]; + } + } + while (p++); + +finished: + + if (cogl_debug_flags & COGL_DEBUG_BLEND_STRINGS) + { + if (current_statement > 0) + print_statement (0, &statements[0]); + if (current_statement > 1) + print_statement (1, &statements[1]); + } + + if (!validate_statements_for_context (statements, + current_statement, + context, + error)) + return 0; + + return current_statement; + +error: + { + int offset = p - string; + g_set_error (error, + COGL_BLEND_STRING_ERROR, + COGL_BLEND_STRING_ERROR_PARSE_ERROR, + "Syntax error at offset %d: %s", + offset, + error_string); + + if (cogl_debug_flags & COGL_DEBUG_BLEND_STRINGS) + { + g_debug ("Syntax error at offset %d: %s", + offset, error_string); + } + return 0; + } +} + +/* + * INTERNAL TESTING CODE ... + */ + +struct _TestString +{ + const char *string; + CoglBlendStringContext context; +}; + +int +_cogl_blend_string_test (void) +{ + struct _TestString strings[] = { + {" A = MODULATE ( TEXTURE[RGB], PREVIOUS[A], PREVIOUS[A] ) ", + COGL_BLEND_STRING_CONTEXT_TEXTURE_COMBINE }, + {" RGB = MODULATE ( TEXTURE[RGB], PREVIOUS[A] ) ", + COGL_BLEND_STRING_CONTEXT_TEXTURE_COMBINE }, + {"A=ADD(TEXTURE[A],PREVIOUS[RGB])", + COGL_BLEND_STRING_CONTEXT_TEXTURE_COMBINE }, + {"A=ADD(TEXTURE[A],PREVIOUS[RGB])", + COGL_BLEND_STRING_CONTEXT_TEXTURE_COMBINE }, + + {"RGBA = ADD(SRC_COLOR*(SRC_COLOR[A]), DST_COLOR*(1-SRC_COLOR[A]))", + COGL_BLEND_STRING_CONTEXT_BLENDING }, + {"RGB = ADD(SRC_COLOR, DST_COLOR*(0))", + COGL_BLEND_STRING_CONTEXT_BLENDING }, + {"RGB = ADD(SRC_COLOR, 0)", + COGL_BLEND_STRING_CONTEXT_BLENDING }, + {"RGB = ADD()", + COGL_BLEND_STRING_CONTEXT_BLENDING }, + {"RGB = ADD(SRC_COLOR, 0, DST_COLOR)", + COGL_BLEND_STRING_CONTEXT_BLENDING }, + {NULL} + }; + int i; + + GError *error = NULL; + for (i = 0; strings[i].string; i++) + { + CoglBlendStringStatement statements[2]; + int count = _cogl_blend_string_compile (strings[i].string, + strings[i].context, + statements, + &error); + if (!count) + { + g_print ("Failed to parse string:\n%s\n%s\n", + strings[i].string, + error->message); + g_error_free (error); + error = NULL; + continue; + } + g_print ("Original:\n"); + g_print ("%s\n", strings[i].string); + if (count > 0) + print_statement (0, &statements[0]); + if (count > 1) + print_statement (1, &statements[1]); + } + + return 0; +} + diff --git a/common/cogl-blend-string.h b/common/cogl-blend-string.h new file mode 100644 index 000000000..a3e3888f8 --- /dev/null +++ b/common/cogl-blend-string.h @@ -0,0 +1,151 @@ +/* + * Cogl + * + * An object oriented GL/GLES Abstraction/Utility Layer + * + * Copyright (C) 2009 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, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Authors: + * Robert Bragg + */ + +#ifndef COGL_BLEND_STRING_H +#define COGL_BLEND_STRING_H + +#include +#include + +typedef enum _CoglBlendStringContext +{ + COGL_BLEND_STRING_CONTEXT_BLENDING, + COGL_BLEND_STRING_CONTEXT_TEXTURE_COMBINE +} CoglBlendStringContext; + +#define COGL_BLEND_STRING_ERROR _cogl_blend_string_error_quark () + +typedef enum _CoglBlendStringError +{ + COGL_BLEND_STRING_ERROR_PARSE_ERROR, + COGL_BLEND_STRING_ERROR_ARGUMENT_PARSE_ERROR, + COGL_BLEND_STRING_ERROR_INVALID_ERROR, + COGL_BLEND_STRING_ERROR_GPU_UNSUPPORTED_ERROR +} CoglBlendStringError; + +/* NB: debug stringify code will get upset if these + * are re-ordered */ +typedef enum _CoglBlendStringChannelMask +{ + COGL_BLEND_STRING_CHANNEL_MASK_RGB, + COGL_BLEND_STRING_CHANNEL_MASK_ALPHA, + COGL_BLEND_STRING_CHANNEL_MASK_RGBA +} CoglBlendStringChannelMask; + +typedef enum _CoglBlendStringColorSourceType +{ + /* blending */ + COGL_BLEND_STRING_COLOR_SOURCE_SRC_COLOR, + COGL_BLEND_STRING_COLOR_SOURCE_DST_COLOR, + + /* shared */ + COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT, + + /* texture combining */ + COGL_BLEND_STRING_COLOR_SOURCE_TEXTURE, + COGL_BLEND_STRING_COLOR_SOURCE_TEXTURE_N, + COGL_BLEND_STRING_COLOR_SOURCE_PRIMARY, + COGL_BLEND_STRING_COLOR_SOURCE_PREVIOUS +} CoglBlendStringColorSourceType; + +typedef struct _CoglBlendStringColorSourceInfo +{ + CoglBlendStringColorSourceType type; + const char *name; + size_t name_len; +} CoglBlendStringColorSourceInfo; + +typedef struct _CoglBlendStringColorSource +{ + gboolean is_zero; + const CoglBlendStringColorSourceInfo *info; + int texture; /* for the TEXTURE_N color source */ + gboolean one_minus; + CoglBlendStringChannelMask mask; +} CoglBlendStringColorSource; + +typedef struct _CoglBlendStringFactor +{ + gboolean is_one; + gboolean is_src_alpha_saturate; + gboolean is_color; + CoglBlendStringColorSource source; +} CoglBlendStringFactor; + +typedef struct _CoglBlendStringArgument +{ + CoglBlendStringColorSource source; + CoglBlendStringFactor factor; +} CoglBlendStringArgument; + +typedef enum _CoglBlendStringFunctionType +{ + /* shared */ + COGL_BLEND_STRING_FUNCTION_AUTO_COMPOSITE, + COGL_BLEND_STRING_FUNCTION_ADD, + + /* texture combine only */ + COGL_BLEND_STRING_FUNCTION_REPLACE, + COGL_BLEND_STRING_FUNCTION_MODULATE, + COGL_BLEND_STRING_FUNCTION_ADD_SIGNED, + COGL_BLEND_STRING_FUNCTION_INTERPOLATE, + COGL_BLEND_STRING_FUNCTION_SUBTRACT, + COGL_BLEND_STRING_FUNCTION_DOT3_RGB, + COGL_BLEND_STRING_FUNCTION_DOT3_RGBA +} CoglBlendStringFunctionType; + +typedef struct _CoglBlendStringFunctionInfo +{ + enum _CoglBlendStringFunctionType type; + const char *name; + size_t name_len; + int argc; +} CoglBlendStringFunctionInfo; + +typedef struct _CoglBlendStringStatement +{ + CoglBlendStringChannelMask mask; + const CoglBlendStringFunctionInfo *function; + CoglBlendStringArgument args[3]; +} CoglBlendStringStatement; + + +gboolean +_cogl_blend_string_compile (const char *string, + CoglBlendStringContext context, + CoglBlendStringStatement *statements, + GError **error); + +void +_cogl_blend_string_split_rgba_statement (CoglBlendStringStatement *statement, + CoglBlendStringStatement *rgb, + CoglBlendStringStatement *a); + +GQuark +_cogl_blend_string_error_quark (void); + +#endif /* COGL_BLEND_STRING_H */ + diff --git a/common/cogl-debug.c b/common/cogl-debug.c index 85721fc22..b6dfd7559 100644 --- a/common/cogl-debug.c +++ b/common/cogl-debug.c @@ -39,7 +39,8 @@ static const GDebugKey cogl_debug_keys[] = { { "draw", COGL_DEBUG_DRAW }, { "pango", COGL_DEBUG_PANGO }, { "rectangles", COGL_DEBUG_RECTANGLES }, - { "handle", COGL_DEBUG_HANDLE } + { "handle", COGL_DEBUG_HANDLE }, + { "blend-strings", COGL_DEBUG_BLEND_STRINGS } }; static const gint n_cogl_debug_keys = G_N_ELEMENTS (cogl_debug_keys); diff --git a/common/cogl-material-private.h b/common/cogl-material-private.h index 05d4242dd..f0e053eff 100644 --- a/common/cogl-material-private.h +++ b/common/cogl-material-private.h @@ -78,6 +78,8 @@ struct _CoglMaterialLayer CoglMaterialLayerCombineSrc texture_combine_alpha_src[3]; CoglMaterialLayerCombineOp texture_combine_alpha_op[3]; + GLfloat texture_combine_constant[4]; + /* TODO: Support purely GLSL based material layers */ CoglMatrix matrix; @@ -114,8 +116,15 @@ struct _CoglMaterial GLfloat alpha_func_reference; /* Determines how this material is blended with other primitives */ - CoglMaterialBlendFactor blend_src_factor; - CoglMaterialBlendFactor blend_dst_factor; +#ifndef HAVE_COGL_GLES + GLenum blend_equation_rgb; + GLenum blend_equation_alpha; + CoglMaterialBlendFactor blend_dst_factor_alpha; + CoglMaterialBlendFactor blend_src_factor_alpha; + GLfloat blend_constant[4]; +#endif + CoglMaterialBlendFactor blend_src_factor_rgb; + CoglMaterialBlendFactor blend_dst_factor_rgb; GList *layers; }; diff --git a/common/cogl-material.c b/common/cogl-material.c index c456cac6a..cc1ae0691 100644 --- a/common/cogl-material.c +++ b/common/cogl-material.c @@ -35,6 +35,7 @@ #include "cogl-material-private.h" #include "cogl-texture-private.h" +#include "cogl-blend-string.h" #include #include @@ -50,6 +51,8 @@ #ifdef HAVE_COGL_GL #define glActiveTexture ctx->pf_glActiveTexture #define glClientActiveTexture ctx->pf_glClientActiveTexture +#define glBlendFuncSeparate ctx->pf_glBlendFuncSeparate +#define glBlendEquationSeparate ctx->pf_glBlendEquationSeparate #endif static void _cogl_material_free (CoglMaterial *tex); @@ -60,6 +63,12 @@ COGL_HANDLE_DEFINE (MaterialLayer, material_layer); /* #define DISABLE_MATERIAL_CACHE 1 */ +GQuark +_cogl_material_error_quark (void) +{ + return g_quark_from_static_string ("cogl-material-error-quark"); +} + CoglHandle cogl_material_new (void) { @@ -88,8 +97,18 @@ cogl_material_new (void) material->flags |= COGL_MATERIAL_FLAG_DEFAULT_ALPHA_FUNC; /* Not the same as the GL default, but seems saner... */ - material->blend_src_factor = COGL_MATERIAL_BLEND_FACTOR_SRC_ALPHA; - material->blend_dst_factor = COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; +#ifndef HAVE_COGL_GLES + material->blend_equation_rgb = GL_FUNC_ADD; + material->blend_equation_alpha = GL_FUNC_ADD; + material->blend_src_factor_alpha = GL_SRC_ALPHA; + material->blend_dst_factor_alpha = GL_ONE_MINUS_SRC_ALPHA; + material->blend_constant[0] = 0; + material->blend_constant[1] = 0; + material->blend_constant[2] = 0; + material->blend_constant[3] = 0; +#endif + material->blend_src_factor_rgb = GL_SRC_ALPHA; + material->blend_dst_factor_rgb = GL_ONE_MINUS_SRC_ALPHA; material->flags |= COGL_MATERIAL_FLAG_DEFAULT_BLEND_FUNC; material->layers = NULL; @@ -408,6 +427,179 @@ cogl_material_set_alpha_test_function (CoglHandle handle, material->flags &= ~COGL_MATERIAL_FLAG_DEFAULT_ALPHA_FUNC; } +GLenum +arg_to_gl_blend_factor (CoglBlendStringArgument *arg) +{ + if (arg->source.is_zero) + return GL_ZERO; + if (arg->factor.is_one) + return GL_ONE; + else if (arg->factor.is_src_alpha_saturate) + return GL_SRC_ALPHA_SATURATE; + else if (arg->factor.source.info->type == + COGL_BLEND_STRING_COLOR_SOURCE_SRC_COLOR) + { + if (arg->factor.source.mask == COGL_BLEND_STRING_CHANNEL_MASK_RGB) + { + if (arg->factor.source.one_minus) + return GL_ONE_MINUS_SRC_COLOR; + else + return GL_SRC_COLOR; + } + else + { + if (arg->factor.source.one_minus) + return GL_ONE_MINUS_SRC_ALPHA; + else + return GL_SRC_ALPHA; + } + } + else if (arg->factor.source.info->type == + COGL_BLEND_STRING_COLOR_SOURCE_DST_COLOR) + { + if (arg->factor.source.mask == COGL_BLEND_STRING_CHANNEL_MASK_RGB) + { + if (arg->factor.source.one_minus) + return GL_ONE_MINUS_DST_COLOR; + else + return GL_DST_COLOR; + } + else + { + if (arg->factor.source.one_minus) + return GL_ONE_MINUS_DST_ALPHA; + else + return GL_DST_ALPHA; + } + } +#ifndef HAVE_COGL_GLES + else if (arg->factor.source.info->type == + COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT) + { + if (arg->factor.source.mask == COGL_BLEND_STRING_CHANNEL_MASK_RGB) + { + if (arg->factor.source.one_minus) + return GL_ONE_MINUS_CONSTANT_COLOR; + else + return GL_CONSTANT_COLOR; + } + else + { + if (arg->factor.source.one_minus) + return GL_ONE_MINUS_CONSTANT_ALPHA; + else + return GL_CONSTANT_ALPHA; + } + } +#endif + + g_warning ("Unable to determine valid blend factor from blend string\n"); + return GL_ONE; +} + +void +setup_blend_state (CoglBlendStringStatement *statement, + GLenum *blend_equation, + CoglMaterialBlendFactor *blend_src_factor, + CoglMaterialBlendFactor *blend_dst_factor) +{ +#ifndef HAVE_COGL_GLES + switch (statement->function->type) + { + case COGL_BLEND_STRING_FUNCTION_ADD: + *blend_equation = GL_FUNC_ADD; + break; + /* TODO - add more */ + default: + g_warning ("Unsupported blend function given"); + *blend_equation = GL_FUNC_ADD; + } +#endif + + *blend_src_factor = arg_to_gl_blend_factor (&statement->args[0]); + *blend_dst_factor = arg_to_gl_blend_factor (&statement->args[1]); +} + +gboolean +cogl_material_set_blend (CoglHandle handle, + const char *blend_description, + GError **error) +{ + CoglMaterial *material; + CoglBlendStringStatement statements[2]; + CoglBlendStringStatement split[2]; + CoglBlendStringStatement *rgb; + CoglBlendStringStatement *a; + int count; + + g_return_val_if_fail (cogl_is_material (handle), FALSE); + + material = _cogl_material_pointer_from_handle (handle); + + count = + _cogl_blend_string_compile (blend_description, + COGL_BLEND_STRING_CONTEXT_BLENDING, + statements, + error); + if (!count) + return FALSE; + + if (statements[0].mask == COGL_BLEND_STRING_CHANNEL_MASK_RGBA) + { + _cogl_blend_string_split_rgba_statement (statements, + &split[0], &split[1]); + rgb = &split[0]; + a = &split[1]; + } + else + { + rgb = &statements[0]; + a = &statements[1]; + } + +#ifndef HAVE_COGL_GLES + setup_blend_state (rgb, + &material->blend_equation_rgb, + &material->blend_src_factor_rgb, + &material->blend_dst_factor_rgb); + setup_blend_state (a, + &material->blend_equation_alpha, + &material->blend_src_factor_alpha, + &material->blend_dst_factor_alpha); +#else + setup_blend_state (rgb, + NULL, + &material->blend_src_factor_rgb, + &material->blend_dst_factor_rgb); +#endif + + material->flags &= ~COGL_MATERIAL_FLAG_DEFAULT_BLEND_FUNC; + + return TRUE; +} + +void +cogl_material_set_blend_constant (CoglHandle handle, + CoglColor *constant_color) +{ +#ifndef HAVE_COGL_GLES + CoglMaterial *material; + GLfloat *constant; + + g_return_if_fail (cogl_is_material (handle)); + + material = _cogl_material_pointer_from_handle (handle); + + constant = material->blend_constant; + constant[0] = cogl_color_get_red_float (constant_color); + constant[1] = cogl_color_get_green_float (constant_color); + constant[2] = cogl_color_get_blue_float (constant_color); + constant[3] = cogl_color_get_alpha_float (constant_color); + + material->flags &= ~COGL_MATERIAL_FLAG_DEFAULT_BLEND_FUNC; +#endif +} + void cogl_material_set_blend_factors (CoglHandle handle, CoglMaterialBlendFactor src_factor, @@ -418,8 +610,12 @@ cogl_material_set_blend_factors (CoglHandle handle, g_return_if_fail (cogl_is_material (handle)); material = _cogl_material_pointer_from_handle (handle); - material->blend_src_factor = src_factor; - material->blend_dst_factor = dst_factor; + material->blend_src_factor_rgb = src_factor; + material->blend_dst_factor_rgb = dst_factor; +#ifndef HAVE_COGL_GLES + material->blend_src_factor_alpha = src_factor; + material->blend_dst_factor_alpha = dst_factor; +#endif material->flags &= ~COGL_MATERIAL_FLAG_DEFAULT_BLEND_FUNC; } @@ -530,6 +726,169 @@ cogl_material_set_layer (CoglHandle material_handle, layer->flags |= COGL_MATERIAL_LAYER_FLAG_DIRTY; } +static void +setup_texture_combine_state (CoglBlendStringStatement *statement, + CoglMaterialLayerCombineFunc *texture_combine_func, + CoglMaterialLayerCombineSrc *texture_combine_src, + CoglMaterialLayerCombineOp *texture_combine_op) +{ + int i; + + switch (statement->function->type) + { + case COGL_BLEND_STRING_FUNCTION_AUTO_COMPOSITE: + *texture_combine_func = GL_MODULATE; /* FIXME */ + break; + case COGL_BLEND_STRING_FUNCTION_REPLACE: + *texture_combine_func = GL_REPLACE; + break; + case COGL_BLEND_STRING_FUNCTION_MODULATE: + *texture_combine_func = GL_MODULATE; + break; + case COGL_BLEND_STRING_FUNCTION_ADD: + *texture_combine_func = GL_ADD; + break; + case COGL_BLEND_STRING_FUNCTION_ADD_SIGNED: + *texture_combine_func = GL_ADD_SIGNED; + break; + case COGL_BLEND_STRING_FUNCTION_INTERPOLATE: + *texture_combine_func = GL_INTERPOLATE; + break; + case COGL_BLEND_STRING_FUNCTION_SUBTRACT: + *texture_combine_func = GL_SUBTRACT; + break; + case COGL_BLEND_STRING_FUNCTION_DOT3_RGB: + *texture_combine_func = GL_DOT3_RGB; + break; + case COGL_BLEND_STRING_FUNCTION_DOT3_RGBA: + *texture_combine_func = GL_DOT3_RGBA; + break; + } + + for (i = 0; i < statement->function->argc; i++) + { + CoglBlendStringArgument *arg = &statement->args[i]; + + switch (arg->source.info->type) + { + case COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT: + texture_combine_src[i] = GL_CONSTANT; + break; + case COGL_BLEND_STRING_COLOR_SOURCE_TEXTURE: + texture_combine_src[i] = GL_TEXTURE; + break; + case COGL_BLEND_STRING_COLOR_SOURCE_TEXTURE_N: + texture_combine_src[i] = + GL_TEXTURE0 + arg->source.texture; + break; + case COGL_BLEND_STRING_COLOR_SOURCE_PRIMARY: + texture_combine_src[i] = GL_PRIMARY_COLOR; + break; + case COGL_BLEND_STRING_COLOR_SOURCE_PREVIOUS: + texture_combine_src[i] = GL_PREVIOUS; + break; + default: + g_warning ("Unexpected texture combine source"); + texture_combine_src[i] = GL_TEXTURE; + } + + if (arg->source.mask == COGL_BLEND_STRING_CHANNEL_MASK_RGB) + { + if (statement->args[i].source.one_minus) + texture_combine_op[i] = GL_ONE_MINUS_SRC_COLOR; + else + texture_combine_op[i] = GL_SRC_COLOR; + } + else + { + if (statement->args[i].source.one_minus) + texture_combine_op[i] = GL_ONE_MINUS_SRC_ALPHA; + else + texture_combine_op[i] = GL_SRC_ALPHA; + } + } +} + +gboolean +cogl_material_set_layer_combine (CoglHandle handle, + gint layer_index, + const char *combine_description, + GError **error) +{ + CoglMaterial *material; + CoglMaterialLayer *layer; + CoglBlendStringStatement statements[2]; + CoglBlendStringStatement split[2]; + CoglBlendStringStatement *rgb; + CoglBlendStringStatement *a; + int count; + + g_return_val_if_fail (cogl_is_material (handle), FALSE); + + material = _cogl_material_pointer_from_handle (handle); + layer = _cogl_material_get_layer (material, layer_index, TRUE); + + count = + _cogl_blend_string_compile (combine_description, + COGL_BLEND_STRING_CONTEXT_TEXTURE_COMBINE, + statements, + error); + if (!count) + return FALSE; + + if (statements[0].mask == COGL_BLEND_STRING_CHANNEL_MASK_RGBA) + { + _cogl_blend_string_split_rgba_statement (statements, + &split[0], &split[1]); + rgb = &split[0]; + a = &split[1]; + } + else + { + rgb = &statements[0]; + a = &statements[1]; + } + + setup_texture_combine_state (rgb, + &layer->texture_combine_rgb_func, + layer->texture_combine_rgb_src, + layer->texture_combine_rgb_op); + + setup_texture_combine_state (a, + &layer->texture_combine_alpha_func, + layer->texture_combine_alpha_src, + layer->texture_combine_alpha_op); + + + layer->flags |= COGL_MATERIAL_LAYER_FLAG_DIRTY; + layer->flags &= ~COGL_MATERIAL_LAYER_FLAG_DEFAULT_COMBINE; + return TRUE; +} + +void +cogl_material_set_layer_combine_constant (CoglHandle handle, + gint layer_index, + CoglColor *constant_color) +{ + CoglMaterial *material; + CoglMaterialLayer *layer; + GLfloat *constant; + + g_return_if_fail (cogl_is_material (handle)); + + material = _cogl_material_pointer_from_handle (handle); + layer = _cogl_material_get_layer (material, layer_index, TRUE); + + constant = layer->texture_combine_constant; + constant[0] = cogl_color_get_red_float (constant_color); + constant[1] = cogl_color_get_green_float (constant_color); + constant[2] = cogl_color_get_blue_float (constant_color); + constant[3] = cogl_color_get_alpha_float (constant_color); + + layer->flags |= COGL_MATERIAL_LAYER_FLAG_DIRTY; + layer->flags &= ~COGL_MATERIAL_LAYER_FLAG_DEFAULT_COMBINE; +} + void cogl_material_set_layer_combine_function ( CoglHandle handle, @@ -713,7 +1072,7 @@ cogl_material_get_cogl_enable_flags (CoglHandle material_handle) * probably sensible to try and avoid list manipulation for every * primitive emitted in a scene, every frame. * - * Alternativly; we could either add a _foreach function, or maybe + * Alternatively; we could either add a _foreach function, or maybe * a function that gets a passed a buffer (that may be stack allocated) * by the caller. */ @@ -851,6 +1210,9 @@ _cogl_material_layer_flush_gl_sampler_state (CoglMaterialLayer *layer, GE (glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, layer->texture_combine_alpha_op[2])); } + + GE (glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, + layer->texture_combine_constant)); } #ifndef DISABLE_MATERIAL_CACHE @@ -1122,7 +1484,39 @@ _cogl_material_flush_base_gl_state (CoglMaterial *material) if (!(ctx->current_material_flags & COGL_MATERIAL_FLAG_DEFAULT_BLEND_FUNC && material->flags & COGL_MATERIAL_FLAG_DEFAULT_BLEND_FUNC)) { - GE (glBlendFunc (material->blend_src_factor, material->blend_dst_factor)); +#if defined (HAVE_COGL_GLES2) + gboolean have_blend_equation_seperate = TRUE; +#elif defined (HAVE_COGL_GL) + gboolean have_blend_equation_seperate = FALSE; + if (ctx->pf_glBlendEquationSeparate) /* Only GL 2.0 + */ + have_blend_equation_seperate = TRUE; +#endif + +#ifndef HAVE_COGL_GLES /* GLES 1 only has glBlendFunc */ + if (material->blend_src_factor_rgb != material->blend_src_factor_alpha + || (material->blend_src_factor_rgb != + material->blend_src_factor_alpha)) + { + if (have_blend_equation_seperate && + material->blend_equation_rgb != material->blend_equation_alpha) + GE (glBlendEquationSeparate (material->blend_equation_rgb, + material->blend_equation_alpha)); + else + GE (glBlendEquation (material->blend_equation_rgb)); + + GE (glBlendFuncSeparate (material->blend_src_factor_rgb, + material->blend_dst_factor_rgb, + material->blend_src_factor_alpha, + material->blend_dst_factor_alpha)); + GE (glBlendColor (material->blend_constant[0], + material->blend_constant[1], + material->blend_constant[2], + material->blend_constant[3])); + } + else +#endif + GE (glBlendFunc (material->blend_src_factor_rgb, + material->blend_dst_factor_rgb)); } } diff --git a/doc/reference/cogl/Makefile.am b/doc/reference/cogl/Makefile.am index 82b96928f..c2f075e4d 100644 --- a/doc/reference/cogl/Makefile.am +++ b/doc/reference/cogl/Makefile.am @@ -24,7 +24,7 @@ DOC_SOURCE_DIR=../../../clutter/cogl SCANGOBJ_OPTIONS=--type-init-func="g_type_init()" # Extra options to supply to gtkdoc-scan. -# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED" +# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED" SCAN_OPTIONS=--deprecated-guards="COGL_DISABLE_DEPRECATED" # Extra options to supply to gtkdoc-mkdb. @@ -70,12 +70,15 @@ HTML_IMAGES= # Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). # e.g. content_files=running.sgml building.sgml changes-2.0.sgml -content_files= version.xml +content_files = \ + version.xml \ + blend-strings.xml # SGML files where gtk-doc abbrevations (#GtkWidget) are expanded # These files must be listed here *and* in content_files # e.g. expand_content_files=running.sgml -expand_content_files= +expand_content_files = \ + blend-strings.xml # CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library. # Only needed if you are using gtkdoc-scangobj to dynamically query widget diff --git a/doc/reference/cogl/blend-strings.xml b/doc/reference/cogl/blend-strings.xml new file mode 100644 index 000000000..9c3c8d3c9 --- /dev/null +++ b/doc/reference/cogl/blend-strings.xml @@ -0,0 +1,130 @@ + + +]> + + + +Material Blend Strings +3 +COGL Library + + + +Material Blend Strings +A simple syntax and grammar for describing blending and texture +combining functions. + + + +Cogl Blend Strings + +Describing GPU blending and texture combining states is rather awkward to do +in a consise but also readable fashion. Cogl helps by supporting +string based descriptions using a simple syntax. + + +
+Some examples + +Here is an example used for blending: + +"RGBA = ADD (SRC_COLOR * (SRC_COLOR[A]), DST_COLOR * (1-SRC_COLOR[A]))" + +In OpenGL terms this replaces glBlendFunc[Separate] and +glBlendEquation[Separate] + +Actually in this case it's more verbose than the GL equivalent: + + +glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + +But unless you are familiar with OpenGL or refer to its API documentation +you wouldn't know that the default function used by OpenGL is GL_FUNC_ADD +nor would you know that the above arguments determine what the source color +and destination color will be multiplied by before being adding. + + +Here is an example used for texture combining: + +"RGB = REPLACE (PREVIOUS)" +"A = MODULATE (PREVIOUS, TEXTURE)" + + +In OpenGL terms this replaces glTexEnv, and the above example is equivalent +to this OpenGL code: + + + glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); + glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE); + glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); + glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); + glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); + glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE); + glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); + glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); + glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE); + glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); + + +
+ +
+Here's the syntax + + +<statement>: + <channel-mask>=<function-name>(<arg-list>) + + You can either use a single statement with an RGBA channel-mask or you can use + two statements; one with an A channel-mask and the other with an RGB + channel-mask. + +<channel-mask>: + A or RGB or RGBA + +<function-name>: + [A-Za-z_]* + +<arg-list>: + <arg>,<arg> + or <arg> + or "" + + I.e. functions may take 0 or more arguments + +<arg>: + <color-source> + 1 - <color-source> : Only intended for texture combining + <color-source> * ( <factor> ) : Only intended for blending + 0 : Only intended for blending + + See the blending or texture combining sections for further notes and examples. + +<color-source>: + <source-name>[<channel-mask>] + <source-name> + + See the blending or texture combining sections for the list of source-names + valid in each context. + + If a channel mask is not given then the channel mask of the statement + is assumed instead. + +<factor>: + 0 + 1 + <color-source> + 1-<color-source> + SRC_ALPHA_SATURATE + + +
+ + +
+ + +
diff --git a/doc/reference/cogl/cogl-docs.xml b/doc/reference/cogl/cogl-docs.xml index ba5d2cf89..87d665f42 100644 --- a/doc/reference/cogl/cogl-docs.xml +++ b/doc/reference/cogl/cogl-docs.xml @@ -55,6 +55,7 @@ + diff --git a/doc/reference/cogl/cogl-sections.txt b/doc/reference/cogl/cogl-sections.txt index 3032a6863..ca7664132 100644 --- a/doc/reference/cogl/cogl-sections.txt +++ b/doc/reference/cogl/cogl-sections.txt @@ -354,6 +354,8 @@ CoglMaterialAlphaFunc cogl_material_set_alpha_test_function CoglMaterialBlendFactor cogl_material_set_blend_factors +cogl_material_set_blend +cogl_material_set_blend_constant cogl_material_set_layer cogl_material_remove_layer CoglMaterialLayerCombineFunc @@ -363,6 +365,8 @@ CoglMaterialLayerCombineSrc cogl_material_set_layer_combine_arg_src CoglMaterialLayerCombineOp cogl_material_set_layer_combine_arg_op +cogl_material_set_layer_combine +cogl_material_set_layer_combine_constant cogl_material_set_layer_matrix CoglMaterial diff --git a/gl/cogl-context.c b/gl/cogl-context.c index 2c17408c2..b5d89f30b 100644 --- a/gl/cogl-context.c +++ b/gl/cogl-context.c @@ -136,6 +136,9 @@ cogl_create_context () _context->pf_glActiveTexture = NULL; _context->pf_glClientActiveTexture = NULL; + _context->pf_glBlendFuncSeparate = NULL; + _context->pf_glBlendEquationSeparate = NULL; + /* Initialise the clip stack */ _cogl_clip_stack_state_init (); diff --git a/gl/cogl-context.h b/gl/cogl-context.h index 2660ed812..f490d39ac 100644 --- a/gl/cogl-context.h +++ b/gl/cogl-context.h @@ -164,6 +164,9 @@ typedef struct COGL_PFNGLACTIVETEXTUREPROC pf_glActiveTexture; COGL_PFNGLCLIENTACTIVETEXTUREPROC pf_glClientActiveTexture; + + COGL_PFNGLBLENDFUNCSEPARATEPROC pf_glBlendFuncSeparate; + COGL_PFNGLBLENDEQUATIONSEPARATEPROC pf_glBlendEquationSeparate; } CoglContext; CoglContext * diff --git a/gl/cogl-defines.h.in b/gl/cogl-defines.h.in index 8e2df9ec3..bde93c559 100644 --- a/gl/cogl-defines.h.in +++ b/gl/cogl-defines.h.in @@ -1020,6 +1020,18 @@ typedef void (APIENTRYP COGL_PFNGLCLIENTACTIVETEXTUREPROC) (GLenum texture); +typedef void + (APIENTRYP COGL_PFNGLBLENDFUNCSEPARATEPROC) + (GLenum srcRGB, + GLenum dstRGB, + GLenum srcAlpha, + GLenum dstAlpha); + +typedef void + (APIENTRYP COGL_PFNGLBLENDEQUATIONSEPARATEPROC) + (GLenum modeRGB, + GLenum modeAlpha); + G_END_DECLS #endif diff --git a/gl/cogl.c b/gl/cogl.c index b2c5417e7..8fcd3eabd 100644 --- a/gl/cogl.c +++ b/gl/cogl.c @@ -486,6 +486,16 @@ _cogl_features_init (void) (COGL_PFNGLCLIENTACTIVETEXTUREPROC) cogl_get_proc_address ("glClientActiveTexture"); + /* Available in 1.4 */ + ctx->pf_glBlendFuncSeparate = + (COGL_PFNGLBLENDFUNCSEPARATEPROC) + cogl_get_proc_address ("glBlendFuncSeparate"); + + /* Available in 2.0 */ + ctx->pf_glBlendEquationSeparate = + (COGL_PFNGLBLENDEQUATIONSEPARATEPROC) + cogl_get_proc_address ("glBlendEquationSeparate"); + /* Cache features */ ctx->feature_flags = flags; ctx->features_cached = TRUE; diff --git a/gles/cogl-gles2-wrapper.c b/gles/cogl-gles2-wrapper.c index aec15b7a0..979ade598 100644 --- a/gles/cogl-gles2-wrapper.c +++ b/gles/cogl-gles2-wrapper.c @@ -1300,13 +1300,20 @@ cogl_gles2_wrapper_bind_texture (GLenum target, GLuint texture, } void -cogl_wrap_glTexEnvi (GLenum target, GLenum pname, GLfloat param) +cogl_wrap_glTexEnvi (GLenum target, GLenum pname, GLint param) { /* This function is only used to set the texture mode once to GL_MODULATE. The shader is hard-coded to modulate the texture so nothing needs to be done here. */ } +void +cogl_wrap_glTexEnvfv (GLenum target, GLenum pname, const GLfloat *params) +{ + /* FIXME: Currently needed to support texture combining using + * COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT */ +} + void cogl_wrap_glClientActiveTexture (GLenum texture) { diff --git a/gles/cogl-gles2-wrapper.h b/gles/cogl-gles2-wrapper.h index bd7f6d978..51bee2d5c 100644 --- a/gles/cogl-gles2-wrapper.h +++ b/gles/cogl-gles2-wrapper.h @@ -259,6 +259,7 @@ struct _CoglGles2WrapperShader #define GL_TEXTURE_ENV 0x2300 #define GL_TEXTURE_ENV_MODE 0x2200 +#define GL_TEXTURE_ENV_COLOR 0x2201 #define GL_MODULATE 0x2100 #define GL_EXP 0x8000 @@ -327,7 +328,8 @@ void cogl_wrap_glColorPointer (GLint size, GLenum type, GLsizei stride, void cogl_wrap_glNormalPointer (GLenum type, GLsizei stride, const GLvoid *pointer); -void cogl_wrap_glTexEnvi (GLenum target, GLenum pname, GLfloat param); +void cogl_wrap_glTexEnvi (GLenum target, GLenum pname, GLint param); +void cogl_wrap_glTexEnvfv (GLenum target, GLenum pname, const GLfloat *params); void cogl_wrap_glClientActiveTexture (GLenum texture); void cogl_wrap_glActiveTexture (GLenum texture); @@ -384,6 +386,7 @@ void _cogl_gles2_clear_cache_for_program (CoglHandle program); #define glColorPointer cogl_wrap_glColorPointer #define glNormalPointer cogl_wrap_glNormalPointer #define glTexEnvi cogl_wrap_glTexEnvi +#define glTexEnvfv cogl_wrap_glTexEnvfv #define glActiveTexture cogl_wrap_glActiveTexture #define glClientActiveTexture cogl_wrap_glClientActiveTexture #define glEnableClientState cogl_wrap_glEnableClientState diff --git a/gles/cogl-texture.c b/gles/cogl-texture.c index 8f4cf733e..99a18f154 100644 --- a/gles/cogl-texture.c +++ b/gles/cogl-texture.c @@ -442,6 +442,7 @@ _cogl_texture_download_from_gl (CoglTexture *tex, gint bpp; GLint viewport[4]; CoglBitmap alpha_bmp; + CoglHandle prev_source; _COGL_GET_CONTEXT (ctx, FALSE); @@ -477,31 +478,21 @@ _cogl_texture_download_from_gl (CoglTexture *tex, if (ctx->texture_download_material == COGL_INVALID_HANDLE) { ctx->texture_download_material = cogl_material_new (); - cogl_material_set_layer_combine_function ( - ctx->texture_download_material, - 0, /* layer */ - COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGB, - COGL_MATERIAL_LAYER_COMBINE_FUNC_REPLACE); - cogl_material_set_layer_combine_arg_src ( - ctx->texture_download_material, - 0, /* layer */ - 0, /* arg */ - COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGB, - COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE); - cogl_material_set_blend_factors (ctx->texture_download_material, - COGL_MATERIAL_BLEND_FACTOR_ONE, - COGL_MATERIAL_BLEND_FACTOR_ZERO); + cogl_material_set_blend (ctx->texture_download_material, + "RGBA = ADD (SRC_COLOR, 0)", + NULL); } + prev_source = cogl_handle_ref (ctx->source_material); + cogl_set_source (ctx->texture_download_material); + cogl_material_set_layer (ctx->texture_download_material, 0, tex); - cogl_material_set_layer_combine_arg_op ( - ctx->texture_download_material, - 0, /* layer */ - 0, /* arg */ - COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGB, - COGL_MATERIAL_LAYER_COMBINE_OP_SRC_COLOR); - cogl_material_flush_gl_state (ctx->texture_download_material, NULL); + cogl_material_set_layer_combine (ctx->texture_download_material, + 0, /* layer */ + "RGBA = REPLACE (TEXTURE)", + NULL); + _cogl_texture_draw_and_read (tex, target_bmp, viewport); /* Check whether texture has alpha and framebuffer not */ @@ -534,13 +525,11 @@ _cogl_texture_download_from_gl (CoglTexture *tex, alpha_bmp.height); /* Draw alpha values into RGB channels */ - cogl_material_set_layer_combine_arg_op ( - ctx->texture_download_material, - 0, /* layer */ - 0, /* arg */ - COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGB, - COGL_MATERIAL_LAYER_COMBINE_OP_SRC_ALPHA); - cogl_material_flush_gl_state (ctx->texture_download_material, NULL); + cogl_material_set_layer_combine (ctx->texture_download_material, + 0, /* layer */ + "RGBA = REPLACE (TEXTURE[A])", + NULL); + _cogl_texture_draw_and_read (tex, &alpha_bmp, viewport); /* Copy temp R to target A */ @@ -568,6 +557,10 @@ _cogl_texture_download_from_gl (CoglTexture *tex, _cogl_set_current_matrix (COGL_MATRIX_MODELVIEW); _cogl_current_matrix_pop (); + /* restore the original material */ + cogl_set_source (prev_source); + cogl_handle_unref (prev_source); + return TRUE; } From 2dc882f685a282000a1998f98edcb387953c5ac5 Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Sat, 23 May 2009 16:23:00 +0100 Subject: [PATCH 05/37] [cogl-material] Removes all the API made redundant by the blend strings API This removes the following API: cogl_material_set_blend_factors cogl_material_set_layer_combine_function cogl_material_set_layer_combine_arg_src cogl_material_set_layer_combine_arg_op These were rather awkward to use, so since it's expected very few people are using them at this point and it should be straight forward to switch over to blend strings, the API is being removed before we release Clutter 1.0. --- cogl-material.h | 293 --------------------------- common/cogl-material-private.h | 20 +- common/cogl-material.c | 176 +++------------- doc/reference/cogl/cogl-sections.txt | 11 - 4 files changed, 34 insertions(+), 466 deletions(-) diff --git a/cogl-material.h b/cogl-material.h index d69ae276c..cf364d3fa 100644 --- a/cogl-material.h +++ b/cogl-material.h @@ -365,92 +365,6 @@ void cogl_material_set_alpha_test_function (CoglHandle material, CoglMaterialAlphaFunc alpha_func, float alpha_reference); -/** - * CoglMaterialBlendFactor: - * @COGL_MATERIAL_BLEND_FACTOR_ZERO: (0, 0, 0, 0) - * @COGL_MATERIAL_BLEND_FACTOR_ONE: (1, 1, 1, 1) - * @COGL_MATERIAL_BLEND_FACTOR_SRC_COLOR: (Rs, Gs, Bs, As) - * @COGL_MATERIAL_BLEND_FACTOR_DST_COLOR: (Rd, Gd, Bd, Ad) - * @COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_SRC_COLOR: (1-Rs, 1-Gs, 1-Bs, 1-As) - * @COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_DST_COLOR: (1-Rd, 1-Gd, 1-Bd, 1-Ad) - * @COGL_MATERIAL_BLEND_FACTOR_SRC_ALPHA: (As, As, As, As) - * @COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA: (1-As, 1-As, 1-As, 1-As) - * @COGL_MATERIAL_BLEND_FACTOR_DST_ALPHA: (Ad, Ad, Ad, Ad) - * @COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_DST_ALPHA: (1-Ad, 1-Ad, 1-Ad, 1-Ad) - * @COGL_MATERIAL_BLEND_FACTOR_CONSTANT: (Rc, Gc, Bc, Ac) - * @COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_CONSTANT: (1-Rc, 1-Gc, 1-Bc, 1-Ac) - * @COGL_MATERIAL_BLEND_FACTOR_CONSTANT_ALPHA: (Ac, Ac, Ac, Ac) - * @COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA: (1-Ac, 1-Ac, 1-Ac, 1-Ac) - * @COGL_MATERIAL_BLEND_FACTOR_SRC_ALPHA_SATURATE: (f,f,f,1) where f=MIN(As,1-Ad) - * - * - * A fixed function is used to determine the blended color, which is based on - * the incoming source color of your fragment (Rs, Gs, Bs, As), a source - * factor (Sr, Sg, Sb, Sa), a destination color (Rd, Rg, Rb, Ra) and - * a destination factor (Dr, Dg, Db, Da), and is given by these equations: - * - * - * R = Rs*Sr + Rd*Dr - * G = Gs*Sg + Gd*Dg - * B = Bs*Sb + Bd*Db - * A = As*Sa + Ad*Da - * - * - * All factors have a range [0, 1] - * - * The factors are selected with the following constants: - */ -typedef enum _CoglMaterialBlendFactor -{ - COGL_MATERIAL_BLEND_FACTOR_ZERO = GL_ZERO, - COGL_MATERIAL_BLEND_FACTOR_ONE = GL_ONE, - COGL_MATERIAL_BLEND_FACTOR_SRC_COLOR = GL_SRC_COLOR, - COGL_MATERIAL_BLEND_FACTOR_DST_COLOR = GL_DST_COLOR, - COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_SRC_COLOR = GL_ONE_MINUS_SRC_COLOR, - COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_DST_COLOR = GL_ONE_MINUS_DST_COLOR, - COGL_MATERIAL_BLEND_FACTOR_SRC_ALPHA = GL_SRC_ALPHA, - COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA = GL_ONE_MINUS_SRC_ALPHA, - COGL_MATERIAL_BLEND_FACTOR_DST_ALPHA = GL_DST_ALPHA, - COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_DST_ALPHA = GL_ONE_MINUS_DST_ALPHA, -#ifdef HAVE_COGL_GL - COGL_MATERIAL_BLEND_FACTOR_CONSTANT = GL_CONSTANT_COLOR, - COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_CONSTANT = - GL_ONE_MINUS_CONSTANT_COLOR, - COGL_MATERIAL_BLEND_FACTOR_CONSTANT_ALPHA = GL_CONSTANT_ALPHA, - COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA = - GL_ONE_MINUS_CONSTANT_ALPHA, -#endif - COGL_MATERIAL_BLEND_FACTOR_SRC_ALPHA_SATURATE = GL_SRC_ALPHA_SATURATE, -} CoglMaterialBlendFactor; - -/** - * cogl_material_set_blend_factors: - * @material: A CoglMaterial object - * @src_factor: Chooses the @CoglMaterialBlendFactor you want plugged in to - * the blend equation. - * @dst_factor: Chooses the @CoglMaterialBlendFactor you want plugged in to - * the blend equation. - * - * This function lets you control how primitives using this material will get - * blended with the contents of your framebuffer. The blended RGBA components - * are calculated like this: - * - * (RsSr+RdDr, GsSg+GdDg, BsSb+BsSb, AsSa+AdDa) - * - * Where (Rs,Gs,Bs,As) represents your source - material- color, - * (Rd,Gd,Bd,Ad) represents your destination - framebuffer - color, - * (Sr,Sg,Sb,Sa) represents your source blend factor and - * (Dr,Dg,Db,Da) represents you destination blend factor. - * - * All factors lie in the range [0,1] and incoming color components are also - * normalized to the range [0,1] - * - * Since 1.0 - */ -void cogl_material_set_blend_factors (CoglHandle material, - CoglMaterialBlendFactor src_factor, - CoglMaterialBlendFactor dst_factor); - /** * cogl_material_set_blend: * @material: A CoglMaterial object @@ -675,212 +589,6 @@ void cogl_material_set_layer_combine_constant (CoglHandle ma int layer_index, CoglColor *constant); -/** - * CoglMaterialLayerCombineFunc: - * @COGL_MATERIAL_LAYER_COMBINE_FUNC_REPLACE: Arg0 - * @COGL_MATERIAL_LAYER_COMBINE_FUNC_MODULATE: Arg0 x Arg1 - * @COGL_MATERIAL_LAYER_COMBINE_FUNC_ADD: Arg0 + Arg1 - * @COGL_MATERIAL_LAYER_COMBINE_FUNC_ADD_SIGNED: Arg0 + Arg1 - 0.5 - * @COGL_MATERIAL_LAYER_COMBINE_FUNC_INTERPOLATE: Arg0 x Arg + Arg1 x (1-Arg2) - * @COGL_MATERIAL_LAYER_COMBINE_FUNC_SUBTRACT: Arg0 - Arg1 - * @COGL_MATERIAL_LAYER_COMBINE_FUNC_DOT3_RGB: 4 x ((Arg0r - 0.5) x (Arg1r - 0.5)) + - * @COGL_MATERIAL_LAYER_COMBINE_FUNC_DOT3_RGBA: ((Arg0b - 0.5) x (Arg1b - 0.5)) + - * - * A material may comprise of 1 or more layers that can be combined using a - * number of different functions. By default layers are modulated, which is - * to say the components of the current source layer S are simply multipled - * together with the combined results of the previous layer P like this: - * - * - * (Rs*Rp, Gs*Gp, Bs*Bp, As*Ap) - * - * - * For more advanced techniques, Cogl exposes the fixed function texture - * combining capabilities of your GPU to give you greater control. - */ -typedef enum _CoglMaterialLayerCombineFunc -{ - COGL_MATERIAL_LAYER_COMBINE_FUNC_REPLACE = CGL_REPLACE, - COGL_MATERIAL_LAYER_COMBINE_FUNC_MODULATE = CGL_MODULATE, - COGL_MATERIAL_LAYER_COMBINE_FUNC_ADD = CGL_ADD, - COGL_MATERIAL_LAYER_COMBINE_FUNC_ADD_SIGNED = CGL_ADD_SIGNED, - COGL_MATERIAL_LAYER_COMBINE_FUNC_INTERPOLATE = CGL_INTERPOLATE, - COGL_MATERIAL_LAYER_COMBINE_FUNC_SUBTRACT = CGL_SUBTRACT, - COGL_MATERIAL_LAYER_COMBINE_FUNC_DOT3_RGB = CGL_DOT3_RGB, - COGL_MATERIAL_LAYER_COMBINE_FUNC_DOT3_RGBA = CGL_DOT3_RGBA -} CoglMaterialLayerCombineFunc; - -/** - * CoglMaterialLayerCombineChannels: - * @COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGB: Modify the function or argument - * src/op for the RGB components of a - * layer - * @COGL_MATERIAL_LAYER_COMBINE_CHANNELS_ALPHA: Modify the function or argument - * src/op for the Alpha component of a - * layer - * @COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGBA: Modify the function or argument - * src/op for all the components of a - * layer - * - * Cogl optionally lets you describe 2 seperate combine modes for a single - * layer; 1 for the RGB components, and 1 for the Alpha component, so in this - * case you would repeat the 3 steps documented with the - * @cogl_material_set_layer_combine_function function for each channel - * selector. - * - * (Note: you can't have different modes for each channel, so if you need more - * control you will need to use a glsl fragment shader) - */ -typedef enum _CoglMaterialLayerCombineChannels -{ - COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGB, - COGL_MATERIAL_LAYER_COMBINE_CHANNELS_ALPHA, - COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGBA -} CoglMaterialLayerCombineChannels; - -/** - * cogl_material_set_layer_combine_function: - * @material: A CoglMaterial object - * @layer_index: Specifies the layer whos combine mode you want to modify - * @channels: Specifies which channels combine mode you want to modify - * (RGB, ALPHA, or RGBA) - * @func: Specifies the function you want to use for combining fragments - * of the specified layer with the results of previously combined - * layers. - * - * There are three basic steps to describing how a layer should be combined: - * - * - * Choose a function. - * - * - * Specify the source color for each argument of the chosen function. (Note - * the functions don't all take the same number of arguments) - * - * - * Specify an operator for each argument that can modify the corresponding - * source color before the function is applied. - * - * - * - * Cogl optionally lets you describe 2 seperate combine modes for a single - * layer; 1 for the RGB components, and 1 for the Alpha component, so in this - * case you would repeat the 3 steps for each channel selector. - * - * (Note: you can't have different modes for each channel, so if you need more - * control you will need to use a glsl fragment shader) - * - * For example here is how you could elect to use the ADD function for all - * components of layer 1 in your material: - * - * //Step 1: Choose a function. Note the ADD function takes 2 arguments... - * cogl_material_set_layer_combine_function (material, - * 1, - * COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGBA) - * COGL_MATERIAL_LAYER_COMBINE_FUNC_ADD); - * //Step 2: Specify the source color for the 2 ADD function arguments... - * cogl_material_set_layer_combine_arg_src (material, - * 1,//layer index - * 0,//argument index - * COGL_MATERIAL_LAYER_COMBINE_SRC_PREVIOUS); - * cogl_material_set_layer_combine_arg_src (material, - * 1,//layer index - * 1,//argument index - * COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGBA) - * COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE); - * //Step 3: Specify the operators used to modify the arguments... - * cogl_material_set_layer_combine_arg_op (material, - * 1,//layer index - * 0,//argument index - * COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGBA, - * COGL_MATERIAL_LAYER_COMBINE_OP_SRC_COLOR); - * cogl_material_set_layer_combine_arg_op (material, - * 1,//layer index - * 1,//argument index - * COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGBA, - * COGL_MATERIAL_LAYER_COMBINE_OP_SRC_COLOR); - * - */ -void cogl_material_set_layer_combine_function (CoglHandle material, - int layer_index, - CoglMaterialLayerCombineChannels channels, - CoglMaterialLayerCombineFunc func); - -/** - * CoglMaterialLayerCombineSrc: - * @COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE: The fragment color of the current texture layer - * @COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE0: The fragment color of texture unit 0 - * @COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE1: The fragment color of texture unit 1 - * @COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE2: The fragment color of texture unit 2..7 - * @COGL_MATERIAL_LAYER_COMBINE_SRC_CONSTANT: A fixed constant color (TODO: no API yet to specify the actual color!) - * @COGL_MATERIAL_LAYER_COMBINE_SRC_PRIMARY_COLOR: The basic color of the primitive ignoring texturing - * @COGL_MATERIAL_LAYER_COMBINE_SRC_PREVIOUS: The result of combining all previous layers - * - * Note for the constants @COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE0..n the - * numbers may not correspond to the indices you choose for your layers since - * your layer indices don't need to be contiguous. If you need to use these - * it would probably be sensible to ensure the layer indices do infact - * correspond. - */ -typedef enum _CoglMaterialLayerCombineSrc -{ - COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE = GL_TEXTURE, - - /* Can we find a nicer way... */ - COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE0 = GL_TEXTURE0, - COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE1 = GL_TEXTURE1, - COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE2 = GL_TEXTURE2, - COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE3 = GL_TEXTURE3, - COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE4 = GL_TEXTURE4, - COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE5 = GL_TEXTURE5, - COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE6 = GL_TEXTURE6, - COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE7 = GL_TEXTURE7, - /* .. who would ever need more than 8 texture layers.. :-) */ - - COGL_MATERIAL_LAYER_COMBINE_SRC_CONSTANT = CGL_CONSTANT, - COGL_MATERIAL_LAYER_COMBINE_SRC_PRIMARY_COLOR = CGL_PRIMARY_COLOR, - COGL_MATERIAL_LAYER_COMBINE_SRC_PREVIOUS = CGL_PREVIOUS -} CoglMaterialLayerCombineSrc; - -/** - * cogl_material_set_layer_combine_arg_src: - * @material: A CoglMaterial object - * @layer_index: - * @argument: - * @channels: - * @src: - * - */ -void cogl_material_set_layer_combine_arg_src (CoglHandle material, - int layer_index, - int argument, - CoglMaterialLayerCombineChannels channels, - CoglMaterialLayerCombineSrc src); - -typedef enum _CoglMaterialLayerCombineOp -{ - COGL_MATERIAL_LAYER_COMBINE_OP_SRC_COLOR = GL_SRC_COLOR, - COGL_MATERIAL_LAYER_COMBINE_OP_ONE_MINUS_SRC_COLOR = GL_ONE_MINUS_SRC_COLOR, - - COGL_MATERIAL_LAYER_COMBINE_OP_SRC_ALPHA = GL_SRC_ALPHA, - COGL_MATERIAL_LAYER_COMBINE_OP_ONE_MINUS_SRC_ALPHA = GL_ONE_MINUS_SRC_ALPHA -} CoglMaterialLayerCombineOp; - -/** - * cogl_material_set_layer_combine_arg_op: - * @material: A CoglMaterial object - * @layer_index: - * @argument: - * @channels: - * @op: - * - */ -void cogl_material_set_layer_combine_arg_op (CoglHandle material, - int layer_index, - int argument, - CoglMaterialLayerCombineChannels channels, - CoglMaterialLayerCombineOp op); - /** * cogl_material_set_layer_matrix: * @material: A CoglMaterial object @@ -892,7 +600,6 @@ void cogl_material_set_layer_matrix (CoglHandle material, int layer_index, CoglMatrix *matrix); - /** * SECTION:cogl-material-internals * @short_description: Functions for creating custom primitives that make use diff --git a/common/cogl-material-private.h b/common/cogl-material-private.h index f0e053eff..5d3cecfd9 100644 --- a/common/cogl-material-private.h +++ b/common/cogl-material-private.h @@ -70,13 +70,13 @@ struct _CoglMaterialLayer /* Determines how the color of individual texture fragments * are calculated. */ - CoglMaterialLayerCombineFunc texture_combine_rgb_func; - CoglMaterialLayerCombineSrc texture_combine_rgb_src[3]; - CoglMaterialLayerCombineOp texture_combine_rgb_op[3]; + GLint texture_combine_rgb_func; + GLint texture_combine_rgb_src[3]; + GLint texture_combine_rgb_op[3]; - CoglMaterialLayerCombineFunc texture_combine_alpha_func; - CoglMaterialLayerCombineSrc texture_combine_alpha_src[3]; - CoglMaterialLayerCombineOp texture_combine_alpha_op[3]; + GLint texture_combine_alpha_func; + GLint texture_combine_alpha_src[3]; + GLint texture_combine_alpha_op[3]; GLfloat texture_combine_constant[4]; @@ -119,12 +119,12 @@ struct _CoglMaterial #ifndef HAVE_COGL_GLES GLenum blend_equation_rgb; GLenum blend_equation_alpha; - CoglMaterialBlendFactor blend_dst_factor_alpha; - CoglMaterialBlendFactor blend_src_factor_alpha; + GLint blend_src_factor_alpha; + GLint blend_dst_factor_alpha; GLfloat blend_constant[4]; #endif - CoglMaterialBlendFactor blend_src_factor_rgb; - CoglMaterialBlendFactor blend_dst_factor_rgb; + GLint blend_src_factor_rgb; + GLint blend_dst_factor_rgb; GList *layers; }; diff --git a/common/cogl-material.c b/common/cogl-material.c index cc1ae0691..aef14cd00 100644 --- a/common/cogl-material.c +++ b/common/cogl-material.c @@ -500,8 +500,8 @@ arg_to_gl_blend_factor (CoglBlendStringArgument *arg) void setup_blend_state (CoglBlendStringStatement *statement, GLenum *blend_equation, - CoglMaterialBlendFactor *blend_src_factor, - CoglMaterialBlendFactor *blend_dst_factor) + GLint *blend_src_factor, + GLint *blend_dst_factor) { #ifndef HAVE_COGL_GLES switch (statement->function->type) @@ -600,26 +600,6 @@ cogl_material_set_blend_constant (CoglHandle handle, #endif } -void -cogl_material_set_blend_factors (CoglHandle handle, - CoglMaterialBlendFactor src_factor, - CoglMaterialBlendFactor dst_factor) -{ - CoglMaterial *material; - - g_return_if_fail (cogl_is_material (handle)); - - material = _cogl_material_pointer_from_handle (handle); - material->blend_src_factor_rgb = src_factor; - material->blend_dst_factor_rgb = dst_factor; -#ifndef HAVE_COGL_GLES - material->blend_src_factor_alpha = src_factor; - material->blend_dst_factor_alpha = dst_factor; -#endif - - material->flags &= ~COGL_MATERIAL_FLAG_DEFAULT_BLEND_FUNC; -} - /* Asserts that a layer corresponding to the given index exists. If no * match is found, then a new empty layer is added. */ @@ -659,21 +639,16 @@ _cogl_material_get_layer (CoglMaterial *material, /* Choose the same default combine mode as OpenGL: * MODULATE(PREVIOUS[RGBA],TEXTURE[RGBA]) */ - layer->texture_combine_rgb_func = COGL_MATERIAL_LAYER_COMBINE_FUNC_MODULATE; - layer->texture_combine_rgb_src[0] = COGL_MATERIAL_LAYER_COMBINE_SRC_PREVIOUS; - layer->texture_combine_rgb_src[1] = COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE; - layer->texture_combine_rgb_op[0] = COGL_MATERIAL_LAYER_COMBINE_OP_SRC_COLOR; - layer->texture_combine_rgb_op[1] = COGL_MATERIAL_LAYER_COMBINE_OP_SRC_COLOR; - layer->texture_combine_alpha_func = - COGL_MATERIAL_LAYER_COMBINE_FUNC_MODULATE; - layer->texture_combine_alpha_src[0] = - COGL_MATERIAL_LAYER_COMBINE_SRC_PREVIOUS; - layer->texture_combine_alpha_src[1] = - COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE; - layer->texture_combine_alpha_op[0] = - COGL_MATERIAL_LAYER_COMBINE_OP_SRC_ALPHA; - layer->texture_combine_alpha_op[1] = - COGL_MATERIAL_LAYER_COMBINE_OP_SRC_ALPHA; + layer->texture_combine_rgb_func = GL_MODULATE; + layer->texture_combine_rgb_src[0] = GL_PREVIOUS; + layer->texture_combine_rgb_src[1] = GL_TEXTURE; + layer->texture_combine_rgb_op[0] = GL_SRC_COLOR; + layer->texture_combine_rgb_op[1] = GL_SRC_COLOR; + layer->texture_combine_alpha_func = GL_MODULATE; + layer->texture_combine_alpha_src[0] = GL_PREVIOUS; + layer->texture_combine_alpha_src[1] = GL_TEXTURE; + layer->texture_combine_alpha_op[0] = GL_SRC_ALPHA; + layer->texture_combine_alpha_op[1] = GL_SRC_ALPHA; cogl_matrix_init_identity (&layer->matrix); @@ -728,9 +703,9 @@ cogl_material_set_layer (CoglHandle material_handle, static void setup_texture_combine_state (CoglBlendStringStatement *statement, - CoglMaterialLayerCombineFunc *texture_combine_func, - CoglMaterialLayerCombineSrc *texture_combine_src, - CoglMaterialLayerCombineOp *texture_combine_op) + GLint *texture_combine_func, + GLint *texture_combine_src, + GLint *texture_combine_op) { int i; @@ -889,109 +864,6 @@ cogl_material_set_layer_combine_constant (CoglHandle handle, layer->flags &= ~COGL_MATERIAL_LAYER_FLAG_DEFAULT_COMBINE; } -void -cogl_material_set_layer_combine_function ( - CoglHandle handle, - gint layer_index, - CoglMaterialLayerCombineChannels channels, - CoglMaterialLayerCombineFunc func) -{ - CoglMaterial *material; - CoglMaterialLayer *layer; - gboolean set_alpha_func = FALSE; - gboolean set_rgb_func = FALSE; - - g_return_if_fail (cogl_is_material (handle)); - - material = _cogl_material_pointer_from_handle (handle); - layer = _cogl_material_get_layer (material, layer_index, TRUE); - - if (channels == COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGBA) - set_alpha_func = set_rgb_func = TRUE; - else if (channels == COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGB) - set_rgb_func = TRUE; - else if (channels == COGL_MATERIAL_LAYER_COMBINE_CHANNELS_ALPHA) - set_alpha_func = TRUE; - - if (set_rgb_func) - layer->texture_combine_rgb_func = func; - if (set_alpha_func) - layer->texture_combine_alpha_func = func; - - layer->flags |= COGL_MATERIAL_LAYER_FLAG_DIRTY; - layer->flags &= ~COGL_MATERIAL_LAYER_FLAG_DEFAULT_COMBINE; -} - -void -cogl_material_set_layer_combine_arg_src ( - CoglHandle handle, - gint layer_index, - gint argument, - CoglMaterialLayerCombineChannels channels, - CoglMaterialLayerCombineSrc src) -{ - CoglMaterial *material; - CoglMaterialLayer *layer; - gboolean set_arg_alpha_src = FALSE; - gboolean set_arg_rgb_src = FALSE; - - g_return_if_fail (cogl_is_material (handle)); - g_return_if_fail (argument >=0 && argument <= 3); - - material = _cogl_material_pointer_from_handle (handle); - layer = _cogl_material_get_layer (material, layer_index, TRUE); - - if (channels == COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGBA) - set_arg_alpha_src = set_arg_rgb_src = TRUE; - else if (channels == COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGB) - set_arg_rgb_src = TRUE; - else if (channels == COGL_MATERIAL_LAYER_COMBINE_CHANNELS_ALPHA) - set_arg_alpha_src = TRUE; - - if (set_arg_rgb_src) - layer->texture_combine_rgb_src[argument] = src; - if (set_arg_alpha_src) - layer->texture_combine_alpha_src[argument] = src; - - layer->flags |= COGL_MATERIAL_LAYER_FLAG_DIRTY; - layer->flags &= ~COGL_MATERIAL_LAYER_FLAG_DEFAULT_COMBINE; -} - -void -cogl_material_set_layer_combine_arg_op ( - CoglHandle material_handle, - gint layer_index, - gint argument, - CoglMaterialLayerCombineChannels channels, - CoglMaterialLayerCombineOp op) -{ - CoglMaterial *material; - CoglMaterialLayer *layer; - gboolean set_arg_alpha_op = FALSE; - gboolean set_arg_rgb_op = FALSE; - - g_return_if_fail (cogl_is_material (material_handle)); - g_return_if_fail (argument >=0 && argument <= 3); - - material = _cogl_material_pointer_from_handle (material_handle); - layer = _cogl_material_get_layer (material, layer_index, TRUE); - - if (channels == COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGBA) - set_arg_alpha_op = set_arg_rgb_op = TRUE; - else if (channels == COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGB) - set_arg_rgb_op = TRUE; - else if (channels == COGL_MATERIAL_LAYER_COMBINE_CHANNELS_ALPHA) - set_arg_alpha_op = TRUE; - - if (set_arg_rgb_op) - layer->texture_combine_rgb_op[argument] = op; - if (set_arg_alpha_op) - layer->texture_combine_alpha_op[argument] = op; - - layer->flags |= COGL_MATERIAL_LAYER_FLAG_DIRTY; - layer->flags &= ~COGL_MATERIAL_LAYER_FLAG_DEFAULT_COMBINE; -} - void cogl_material_set_layer_matrix (CoglHandle material_handle, gint layer_index, @@ -1119,20 +991,20 @@ cogl_material_layer_get_flags (CoglHandle layer_handle) } static guint -get_n_args_for_combine_func (CoglMaterialLayerCombineFunc func) +get_n_args_for_combine_func (GLint func) { switch (func) { - case COGL_MATERIAL_LAYER_COMBINE_FUNC_REPLACE: + case GL_REPLACE: return 1; - case COGL_MATERIAL_LAYER_COMBINE_FUNC_MODULATE: - case COGL_MATERIAL_LAYER_COMBINE_FUNC_ADD: - case COGL_MATERIAL_LAYER_COMBINE_FUNC_ADD_SIGNED: - case COGL_MATERIAL_LAYER_COMBINE_FUNC_SUBTRACT: - case COGL_MATERIAL_LAYER_COMBINE_FUNC_DOT3_RGB: - case COGL_MATERIAL_LAYER_COMBINE_FUNC_DOT3_RGBA: + case GL_MODULATE: + case GL_ADD: + case GL_ADD_SIGNED: + case GL_SUBTRACT: + case GL_DOT3_RGB: + case GL_DOT3_RGBA: return 2; - case COGL_MATERIAL_LAYER_COMBINE_FUNC_INTERPOLATE: + case GL_INTERPOLATE: return 3; } return 0; diff --git a/doc/reference/cogl/cogl-sections.txt b/doc/reference/cogl/cogl-sections.txt index ca7664132..3b32cda5b 100644 --- a/doc/reference/cogl/cogl-sections.txt +++ b/doc/reference/cogl/cogl-sections.txt @@ -349,22 +349,13 @@ cogl_material_set_specular cogl_material_get_specular cogl_material_set_shininess cogl_material_get_shininess - CoglMaterialAlphaFunc cogl_material_set_alpha_test_function CoglMaterialBlendFactor -cogl_material_set_blend_factors cogl_material_set_blend cogl_material_set_blend_constant cogl_material_set_layer cogl_material_remove_layer -CoglMaterialLayerCombineFunc -cogl_material_set_layer_combine_function -CoglMaterialLayerCombineChannels -CoglMaterialLayerCombineSrc -cogl_material_set_layer_combine_arg_src -CoglMaterialLayerCombineOp -cogl_material_set_layer_combine_arg_op cogl_material_set_layer_combine cogl_material_set_layer_combine_constant cogl_material_set_layer_matrix @@ -372,8 +363,6 @@ cogl_material_set_layer_matrix CoglMaterial CoglMaterialFlags CoglMaterialLayerPrivFlags -cogl_material_set_layer_alpha_combine -cogl_material_set_layer_rgb_combine
From 492f0e5d14fd0622626108468a71436bc1c86f6a Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Sat, 23 May 2009 17:42:10 +0100 Subject: [PATCH 06/37] [material] Reduce the material API in preperation for releasing Clutter 1.0 There were a number of functions intended to support creating of new primitives using materials, but at this point they aren't used outside of Cogl so until someone has a usecase and we can get feedback on this API, it's being removed before we release Clutter 1.0. --- cogl-material.h | 129 ++++----------------------- common/cogl-handle.h | 17 ++-- common/cogl-material-private.h | 86 ++++++++++++++++++ common/cogl-material.c | 6 +- common/cogl-primitives.c | 50 +++++------ common/cogl-vertex-buffer.c | 15 ++-- common/cogl.c | 3 +- doc/reference/cogl/cogl-sections.txt | 3 + gl/cogl-context.c | 4 +- gl/cogl-primitives.c | 15 ++-- gles/cogl-context.c | 4 +- gles/cogl-primitives.c | 15 ++-- 12 files changed, 174 insertions(+), 173 deletions(-) diff --git a/cogl-material.h b/cogl-material.h index cf364d3fa..da822564e 100644 --- a/cogl-material.h +++ b/cogl-material.h @@ -600,34 +600,6 @@ void cogl_material_set_layer_matrix (CoglHandle material, int layer_index, CoglMatrix *matrix); -/** - * SECTION:cogl-material-internals - * @short_description: Functions for creating custom primitives that make use - * of Cogl materials for filling. - * - * Normally you shouldn't need to use this API directly, but if you need to - * developing a custom/specialised primitive - probably using raw OpenGL - then - * this API aims to expose enough of the material internals to support being - * able to fill your geometry according to a given Cogl material. - */ - - -/** - * cogl_material_get_cogl_enable_flags: - * @material: A CoglMaterial object - * - * This determines what flags need to be passed to cogl_enable before this - * material can be used. Normally you shouldn't need to use this function - * directly since Cogl will do this internally, but if you are developing - * custom primitives directly with OpenGL you may want to use this. - * - * Note: This API is hopfully just a stop-gap solution. Ideally cogl_enable - * will be replaced. - */ -/* TODO: find a nicer solution! */ -gulong -cogl_material_get_cogl_enable_flags (CoglHandle handle); - /** * cogl_material_get_layers: * @material: A CoglMaterial object @@ -635,24 +607,15 @@ cogl_material_get_cogl_enable_flags (CoglHandle handle); * This function lets you access a materials internal list of layers * for iteration. * - * Note: Normally you shouldn't need to use this function directly since - * Cogl will do this internally, but if you are developing custom primitives - * directly with OpenGL, you will need to iterate the layers that you want - * to texture with. - * - * Note: This function may return more layers than OpenGL can use at once - * so it's your responsability limit yourself to - * CGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS. - * - * Note: It's a bit out of the ordinary to return a const GList *, but it - * was considered sensible to try and avoid list manipulation for every - * primitive emitted in a scene, every frame. + * Returns: A list of #CoglHandle's that can be passed to the + * cogl_material_layer_* functions. */ const GList *cogl_material_get_layers (CoglHandle material_handle); /** * CoglMaterialLayerType: - * @COGL_MATERIAL_LAYER_TYPE_TEXTURE: The layer represents a CoglTexture + * @COGL_MATERIAL_LAYER_TYPE_TEXTURE: The layer represents a + * Cogl texture */ typedef enum _CoglMaterialLayerType { @@ -661,17 +624,12 @@ typedef enum _CoglMaterialLayerType /** * cogl_material_layer_get_type: - * @layer_handle: A CoglMaterialLayer handle + * @layer_handle: A Cogl material layer handle * * Currently there is only one type of layer defined: * COGL_MATERIAL_LAYER_TYPE_TEXTURE, but considering we may add purely GLSL * based layers in the future, you should write code that checks the type * first. - * - * Note: Normally you shouldn't need to use this function directly since - * Cogl will do this internally, but if you are developing custom primitives - * directly with OpenGL, you will need to iterate the layers that you want - * to texture with, and thus should be checking the layer types. */ CoglMaterialLayerType cogl_material_layer_get_type (CoglHandle layer_handle); @@ -679,75 +637,24 @@ CoglMaterialLayerType cogl_material_layer_get_type (CoglHandle layer_handle); * cogl_material_layer_get_texture: * @layer_handle: A CoglMaterialLayer handle * - * This lets you extract a CoglTexture handle for a specific layer. Normally - * you shouldn't need to use this function directly since Cogl will do this - * internally, but if you are developing custom primitives directly with - * OpenGL you may need this. + * This lets you extract a CoglTexture handle for a specific layer. * * Note: In the future, we may support purely GLSL based layers which will - * likley return COGL_INVALID_HANDLE if you try to get the texture. - * Considering this, you should always call cogl_material_layer_get_type - * first, to check it is of type COGL_MATERIAL_LAYER_TYPE_TEXTURE. + * likely return COGL_INVALID_HANDLE if you try to get the texture. + * Considering this, you can call cogl_material_layer_get_type first, + * to check it is of type COGL_MATERIAL_LAYER_TYPE_TEXTURE. + * + * Note: It is possible for a layer object of type + * COGL_MATERIAL_LAYER_TYPE_TEXTURE to be realized before a texture + * object has been associated with the layer. For example this happens + * if you setup layer combining for a given layer index before calling + * cogl_material_set_layer for that index. + * + * Returns: A CoglHandle to the layers texture object or COGL_INVALID_HANDLE + * if a texture has not been set yet. */ CoglHandle cogl_material_layer_get_texture (CoglHandle layer_handle); -/** - * CoglMaterialLayerFlags: - * @COGL_MATERIAL_LAYER_FLAG_USER_MATRIX: Means the user has supplied a - * custom texture matrix. - */ -typedef enum _CoglMaterialLayerFlags -{ - COGL_MATERIAL_LAYER_FLAG_HAS_USER_MATRIX = 1L<<0 -} CoglMaterialLayerFlags; -/* XXX: NB: if you add flags here you will need to update - * CoglMaterialLayerPrivFlags!!! */ - -/** - * cogl_material_layer_get_flags: - * @layer_handle: A CoglMaterialLayer layer handle - * - * This lets you get a number of flag attributes about the layer. Normally - * you shouldn't need to use this function directly since Cogl will do this - * internally, but if you are developing custom primitives directly with - * OpenGL you may need this. - */ -gulong cogl_material_layer_get_flags (CoglHandle layer_handle); - -/** - * CoglMaterialFlushOption: - * @COGL_MATERIAL_FLUSH_FALLBACK_MASK: Follow this by a guin32 mask - * of the layers that can't be supported with the user supplied texture - * and need to be replaced with fallback textures. (1 = fallback, and the - * least significant bit = layer 0) - * @COGL_MATERIAL_FLUSH_DISABLE_MASK: Follow this by a guint32 mask - * of the layers that you want to completly disable texturing for - * (1 = fallback, and the least significant bit = layer 0) - * @COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE: Follow this by a GLuint OpenGL texture - * name to override the texture used for layer 0 of the material. This is - * intended for dealing with sliced textures where you will need to point - * to each of the texture slices in turn when drawing your geometry. - * Passing a value of 0 is the same as not passing the option at all. - */ -typedef enum _CoglMaterialFlushOption -{ - COGL_MATERIAL_FLUSH_FALLBACK_MASK = 1, - COGL_MATERIAL_FLUSH_DISABLE_MASK, - COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE, -} CoglMaterialFlushOption; - -/** - * cogl_material_flush_gl_state: - * @material: A CoglMaterial object - * @...: A NULL terminated list of (CoglMaterialFlushOption, data) pairs - * - * This function commits the state of the specified CoglMaterial - including - * the texture state for all the layers - to the OpenGL[ES] driver. - * - * Since 1.0 - */ -void cogl_material_flush_gl_state (CoglHandle material, - ...) G_GNUC_NULL_TERMINATED; G_END_DECLS diff --git a/common/cogl-handle.h b/common/cogl-handle.h index 7851932db..6caee0e71 100644 --- a/common/cogl-handle.h +++ b/common/cogl-handle.h @@ -82,7 +82,7 @@ typedef struct _CoglHandleObject static CoglHandleClass _cogl_##type_name##_class; \ \ static GQuark \ -_cogl_##type_name##_get_type (void) \ +_cogl_handle_##type_name##_get_type (void) \ { \ static GQuark type = 0; \ if (!type) \ @@ -99,13 +99,13 @@ _cogl_##type_name##_handle_new (Cogl##TypeName *new_obj) \ obj->klass = &_cogl_##type_name##_class; \ if (!obj->klass->type) \ { \ - obj->klass->type = _cogl_##type_name##_get_type (); \ - obj->klass->virt_free = _cogl_##type_name##_free; \ - } \ + obj->klass->type = _cogl_handle_##type_name##_get_type ();\ + obj->klass->virt_free = _cogl_##type_name##_free; \ + } \ \ - _COGL_HANDLE_DEBUG_NEW (TypeName, obj); \ - return (CoglHandle) new_obj; \ - } \ + _COGL_HANDLE_DEBUG_NEW (TypeName, obj); \ + return (CoglHandle) new_obj; \ +} \ \ Cogl##TypeName * \ _cogl_##type_name##_pointer_from_handle (CoglHandle handle) \ @@ -121,7 +121,8 @@ cogl_is_##type_name (CoglHandle handle) \ if (handle == COGL_INVALID_HANDLE) \ return FALSE; \ \ - return (obj->klass->type == _cogl_##type_name##_get_type ()); \ + return (obj->klass->type == \ + _cogl_handle_##type_name##_get_type ()); \ } \ \ CoglHandle G_GNUC_DEPRECATED \ diff --git a/common/cogl-material-private.h b/common/cogl-material-private.h index 5d3cecfd9..9b2170ecf 100644 --- a/common/cogl-material-private.h +++ b/common/cogl-material-private.h @@ -129,5 +129,91 @@ struct _CoglMaterial GList *layers; }; +/* + * SECTION:cogl-material-internals + * @short_description: Functions for creating custom primitives that make use + * of Cogl materials for filling. + * + * Normally you shouldn't need to use this API directly, but if you need to + * developing a custom/specialised primitive - probably using raw OpenGL - then + * this API aims to expose enough of the material internals to support being + * able to fill your geometry according to a given Cogl material. + */ + + +/* + * cogl_material_get_cogl_enable_flags: + * @material: A CoglMaterial object + * + * This determines what flags need to be passed to cogl_enable before this + * material can be used. Normally you shouldn't need to use this function + * directly since Cogl will do this internally, but if you are developing + * custom primitives directly with OpenGL you may want to use this. + * + * Note: This API is hopfully just a stop-gap solution. Ideally cogl_enable + * will be replaced. + */ +/* TODO: find a nicer solution! */ +gulong _cogl_material_get_cogl_enable_flags (CoglHandle handle); + +/* + * CoglMaterialLayerFlags: + * @COGL_MATERIAL_LAYER_FLAG_USER_MATRIX: Means the user has supplied a + * custom texture matrix. + */ +typedef enum _CoglMaterialLayerFlags +{ + COGL_MATERIAL_LAYER_FLAG_HAS_USER_MATRIX = 1L<<0 +} CoglMaterialLayerFlags; +/* XXX: NB: if you add flags here you will need to update + * CoglMaterialLayerPrivFlags!!! */ + +/* + * cogl_material_layer_get_flags: + * @layer_handle: A CoglMaterialLayer layer handle + * + * This lets you get a number of flag attributes about the layer. Normally + * you shouldn't need to use this function directly since Cogl will do this + * internally, but if you are developing custom primitives directly with + * OpenGL you may need this. + */ +gulong _cogl_material_layer_get_flags (CoglHandle layer_handle); + +/* + * CoglMaterialFlushOption: + * @COGL_MATERIAL_FLUSH_FALLBACK_MASK: Follow this by a guin32 mask + * of the layers that can't be supported with the user supplied texture + * and need to be replaced with fallback textures. (1 = fallback, and the + * least significant bit = layer 0) + * @COGL_MATERIAL_FLUSH_DISABLE_MASK: Follow this by a guint32 mask + * of the layers that you want to completly disable texturing for + * (1 = fallback, and the least significant bit = layer 0) + * @COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE: Follow this by a GLuint OpenGL texture + * name to override the texture used for layer 0 of the material. This is + * intended for dealing with sliced textures where you will need to point + * to each of the texture slices in turn when drawing your geometry. + * Passing a value of 0 is the same as not passing the option at all. + */ +typedef enum _CoglMaterialFlushOption +{ + COGL_MATERIAL_FLUSH_FALLBACK_MASK = 1, + COGL_MATERIAL_FLUSH_DISABLE_MASK, + COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE, +} CoglMaterialFlushOption; + +/* + * cogl_material_flush_gl_state: + * @material: A CoglMaterial object + * @...: A NULL terminated list of (CoglMaterialFlushOption, data) pairs + * + * This function commits the state of the specified CoglMaterial - including + * the texture state for all the layers - to the OpenGL[ES] driver. + * + * Since 1.0 + */ +void _cogl_material_flush_gl_state (CoglHandle material, + ...) G_GNUC_NULL_TERMINATED; + + #endif /* __COGL_MATERIAL_PRIVATE_H */ diff --git a/common/cogl-material.c b/common/cogl-material.c index aef14cd00..7e8567a6e 100644 --- a/common/cogl-material.c +++ b/common/cogl-material.c @@ -921,7 +921,7 @@ cogl_material_remove_layer (CoglHandle material_handle, /* XXX: This API is hopfully just a stop-gap solution. Ideally cogl_enable * will be replaced. */ gulong -cogl_material_get_cogl_enable_flags (CoglHandle material_handle) +_cogl_material_get_cogl_enable_flags (CoglHandle material_handle) { CoglMaterial *material; gulong enable_flags = 0; @@ -979,7 +979,7 @@ cogl_material_layer_get_texture (CoglHandle layer_handle) } gulong -cogl_material_layer_get_flags (CoglHandle layer_handle) +_cogl_material_layer_get_flags (CoglHandle layer_handle) { CoglMaterialLayer *layer; @@ -1393,7 +1393,7 @@ _cogl_material_flush_base_gl_state (CoglMaterial *material) } void -cogl_material_flush_gl_state (CoglHandle handle, ...) +_cogl_material_flush_gl_state (CoglHandle handle, ...) { CoglMaterial *material; va_list ap; diff --git a/common/cogl-primitives.c b/common/cogl-primitives.c index 224769ca2..42e4d41cb 100644 --- a/common/cogl-primitives.c +++ b/common/cogl-primitives.c @@ -29,7 +29,7 @@ #include "cogl-internal.h" #include "cogl-context.h" #include "cogl-texture-private.h" -#include "cogl-material.h" +#include "cogl-material-private.h" #include #include @@ -112,16 +112,16 @@ _cogl_journal_flush_quad_batch (CoglJournalEntry *batch_start, disable_mask = (1 << batch_start->n_layers) - 1; disable_mask = ~disable_mask; - cogl_material_flush_gl_state (ctx->source_material, - COGL_MATERIAL_FLUSH_FALLBACK_MASK, - batch_start->fallback_mask, - COGL_MATERIAL_FLUSH_DISABLE_MASK, - disable_mask, - /* Redundant when dealing with unsliced - * textures but does no harm... */ - COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE, - batch_start->layer0_override_texture, - NULL); + _cogl_material_flush_gl_state (ctx->source_material, + COGL_MATERIAL_FLUSH_FALLBACK_MASK, + batch_start->fallback_mask, + COGL_MATERIAL_FLUSH_DISABLE_MASK, + disable_mask, + /* Redundant when dealing with unsliced + * textures but does no harm... */ + COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE, + batch_start->layer0_override_texture, + NULL); for (i = 0; i < batch_start->n_layers; i++) { @@ -140,7 +140,7 @@ _cogl_journal_flush_quad_batch (CoglJournalEntry *batch_start, /* FIXME: This api is a bit yukky, ideally it will be removed if we * re-work the cogl_enable mechanism */ - enable_flags |= cogl_material_get_cogl_enable_flags (ctx->source_material); + enable_flags |= _cogl_material_get_cogl_enable_flags (ctx->source_material); if (ctx->enable_backface_culling) enable_flags |= COGL_ENABLE_BACKFACE_CULLING; @@ -177,7 +177,7 @@ _cogl_journal_flush_quad_batch (CoglJournalEntry *batch_start, color == 1 ? 0xff : 0x00, color == 2 ? 0xff : 0x00, 0xff); - cogl_material_flush_gl_state (outline, NULL); + _cogl_material_flush_gl_state (outline, NULL); _cogl_current_matrix_state_flush (); GE( glDrawArrays (GL_LINE_LOOP, 4 * i, 4) ); } @@ -791,7 +791,7 @@ _cogl_rectangles_with_multitexture_coords ( /* We don't support multi texturing using textures with any waste if the * user has supplied a custom texture matrix, since we don't know if * the result will end up trying to texture from the waste area. */ - flags = cogl_material_layer_get_flags (layer); + flags = _cogl_material_layer_get_flags (layer); if (flags & COGL_MATERIAL_LAYER_FLAG_HAS_USER_MATRIX && _cogl_texture_span_has_waste (texture, 0, 0)) { @@ -1041,13 +1041,13 @@ _cogl_texture_sliced_polygon (CoglTextureVertex *vertices, v += stride; } - cogl_material_flush_gl_state (ctx->source_material, - COGL_MATERIAL_FLUSH_DISABLE_MASK, - (guint32)~1, /* disable all except the + _cogl_material_flush_gl_state (ctx->source_material, + COGL_MATERIAL_FLUSH_DISABLE_MASK, + (guint32)~1, /* disable all except the first layer */ - COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE, - gl_handle, - NULL); + COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE, + gl_handle, + NULL); _cogl_current_matrix_state_flush (); GE( glDrawArrays (GL_TRIANGLE_FAN, 0, n_vertices) ); @@ -1136,10 +1136,10 @@ _cogl_multitexture_unsliced_polygon (CoglTextureVertex *vertices, c[3] = cogl_color_get_alpha_float (&vertices[i].color); } - cogl_material_flush_gl_state (ctx->source_material, - COGL_MATERIAL_FLUSH_FALLBACK_MASK, - fallback_mask, - NULL); + _cogl_material_flush_gl_state (ctx->source_material, + COGL_MATERIAL_FLUSH_FALLBACK_MASK, + fallback_mask, + NULL); _cogl_current_matrix_state_flush (); GE (glDrawArrays (GL_TRIANGLE_FAN, 0, n_vertices)); @@ -1254,7 +1254,7 @@ cogl_polygon (CoglTextureVertex *vertices, /* Prepare GL state */ enable_flags = COGL_ENABLE_VERTEX_ARRAY; - enable_flags |= cogl_material_get_cogl_enable_flags (ctx->source_material); + enable_flags |= _cogl_material_get_cogl_enable_flags (ctx->source_material); if (ctx->enable_backface_culling) enable_flags |= COGL_ENABLE_BACKFACE_CULLING; diff --git a/common/cogl-vertex-buffer.c b/common/cogl-vertex-buffer.c index f6fa6ba89..842551b04 100644 --- a/common/cogl-vertex-buffer.c +++ b/common/cogl-vertex-buffer.c @@ -136,6 +136,7 @@ #include "cogl-handle.h" #include "cogl-vertex-buffer-private.h" #include "cogl-texture-private.h" +#include "cogl-material-private.h" #define PAD_FOR_ALIGNMENT(VAR, TYPE_SIZE) \ (VAR = TYPE_SIZE + ((VAR - 1) & ~(TYPE_SIZE - 1))) @@ -1638,14 +1639,14 @@ enable_state_for_drawing_buffer (CoglVertexBuffer *buffer) } } - cogl_material_flush_gl_state (ctx->source_material, - COGL_MATERIAL_FLUSH_FALLBACK_MASK, - fallback_mask, - COGL_MATERIAL_FLUSH_DISABLE_MASK, - disable_mask, - NULL); + _cogl_material_flush_gl_state (ctx->source_material, + COGL_MATERIAL_FLUSH_FALLBACK_MASK, + fallback_mask, + COGL_MATERIAL_FLUSH_DISABLE_MASK, + disable_mask, + NULL); - enable_flags |= cogl_material_get_cogl_enable_flags (ctx->source_material); + enable_flags |= _cogl_material_get_cogl_enable_flags (ctx->source_material); if (ctx->enable_backface_culling) enable_flags |= COGL_ENABLE_BACKFACE_CULLING; diff --git a/common/cogl.c b/common/cogl.c index 2495d8172..8b85924f6 100644 --- a/common/cogl.c +++ b/common/cogl.c @@ -42,6 +42,7 @@ typedef CoglFuncPtr (*GLXGetProcAddressProc) (const guint8 *procName); #include "cogl-internal.h" #include "cogl-util.h" #include "cogl-context.h" +#include "cogl-material-private.h" #if defined (HAVE_COGL_GLES2) || defined (HAVE_COGL_GLES) #include "cogl-gles2-wrapper.h" @@ -375,7 +376,7 @@ _cogl_add_stencil_clip (float x_offset, { _COGL_GET_CONTEXT (ctx, NO_RETVAL); - cogl_material_flush_gl_state (ctx->stencil_material, NULL); + _cogl_material_flush_gl_state (ctx->stencil_material, NULL); if (first) { diff --git a/doc/reference/cogl/cogl-sections.txt b/doc/reference/cogl/cogl-sections.txt index 3b32cda5b..1041ded78 100644 --- a/doc/reference/cogl/cogl-sections.txt +++ b/doc/reference/cogl/cogl-sections.txt @@ -359,6 +359,9 @@ cogl_material_remove_layer cogl_material_set_layer_combine cogl_material_set_layer_combine_constant cogl_material_set_layer_matrix +cogl_material_get_layers +cogl_material_layer_get_type +cogl_material_layer_get_texture CoglMaterial CoglMaterialFlags diff --git a/gl/cogl-context.c b/gl/cogl-context.c index b5d89f30b..db5541148 100644 --- a/gl/cogl-context.c +++ b/gl/cogl-context.c @@ -166,9 +166,9 @@ cogl_create_context () default_texture_data); cogl_set_source (_context->default_material); - cogl_material_flush_gl_state (_context->source_material, NULL); + _cogl_material_flush_gl_state (_context->source_material, NULL); enable_flags = - cogl_material_get_cogl_enable_flags (_context->source_material); + _cogl_material_get_cogl_enable_flags (_context->source_material); cogl_enable (enable_flags); return TRUE; diff --git a/gl/cogl-primitives.c b/gl/cogl-primitives.c index f3c11c134..6c106f9ec 100644 --- a/gl/cogl-primitives.c +++ b/gl/cogl-primitives.c @@ -29,6 +29,7 @@ #include "cogl-internal.h" #include "cogl-context.h" #include "cogl-clip-stack.h" +#include "cogl-material-private.h" #include #include @@ -78,13 +79,13 @@ _cogl_path_stroke_nodes () _COGL_GET_CONTEXT (ctx, NO_RETVAL); - enable_flags |= cogl_material_get_cogl_enable_flags (ctx->source_material); + enable_flags |= _cogl_material_get_cogl_enable_flags (ctx->source_material); cogl_enable (enable_flags); - cogl_material_flush_gl_state (ctx->source_material, - COGL_MATERIAL_FLUSH_DISABLE_MASK, - (guint32)~0, /* disable all texture layers */ - NULL); + _cogl_material_flush_gl_state (ctx->source_material, + COGL_MATERIAL_FLUSH_DISABLE_MASK, + (guint32)~0, /* disable all texture layers */ + NULL); _cogl_current_matrix_state_flush (); while (path_start < ctx->path_nodes->len) @@ -133,10 +134,10 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min, _COGL_GET_CONTEXT (ctx, NO_RETVAL); /* Just setup a simple material that doesn't use texturing... */ - cogl_material_flush_gl_state (ctx->stencil_material, NULL); + _cogl_material_flush_gl_state (ctx->stencil_material, NULL); enable_flags |= - cogl_material_get_cogl_enable_flags (ctx->source_material); + _cogl_material_get_cogl_enable_flags (ctx->source_material); cogl_enable (enable_flags); _cogl_path_get_bounds (nodes_min, nodes_max, diff --git a/gles/cogl-context.c b/gles/cogl-context.c index f187c0b88..1d2d02843 100644 --- a/gles/cogl-context.c +++ b/gles/cogl-context.c @@ -124,9 +124,9 @@ cogl_create_context () default_texture_data); cogl_set_source (_context->default_material); - cogl_material_flush_gl_state (_context->source_material, NULL); + _cogl_material_flush_gl_state (_context->source_material, NULL); enable_flags = - cogl_material_get_cogl_enable_flags (_context->source_material); + _cogl_material_get_cogl_enable_flags (_context->source_material); cogl_enable (enable_flags); return TRUE; diff --git a/gles/cogl-primitives.c b/gles/cogl-primitives.c index 24b6b0759..d8dee0ba6 100644 --- a/gles/cogl-primitives.c +++ b/gles/cogl-primitives.c @@ -29,6 +29,7 @@ #include "cogl-internal.h" #include "cogl-context.h" #include "cogl-clip-stack.h" +#include "cogl-material-private.h" #include #include @@ -78,13 +79,13 @@ _cogl_path_stroke_nodes () _COGL_GET_CONTEXT (ctx, NO_RETVAL); - enable_flags |= cogl_material_get_cogl_enable_flags (ctx->source_material); + enable_flags |= _cogl_material_get_cogl_enable_flags (ctx->source_material); cogl_enable (enable_flags); - cogl_material_flush_gl_state (ctx->source_material, - COGL_MATERIAL_FLUSH_DISABLE_MASK, - (guint32)~0, /* disable all texture layers */ - NULL); + _cogl_material_flush_gl_state (ctx->source_material, + COGL_MATERIAL_FLUSH_DISABLE_MASK, + (guint32)~0, /* disable all texture layers */ + NULL); _cogl_current_matrix_state_flush (); while (path_start < ctx->path_nodes->len) @@ -139,10 +140,10 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min, _COGL_GET_CONTEXT (ctx, NO_RETVAL); /* Just setup a simple material that doesn't use texturing... */ - cogl_material_flush_gl_state (ctx->stencil_material, NULL); + _cogl_material_flush_gl_state (ctx->stencil_material, NULL); enable_flags |= - cogl_material_get_cogl_enable_flags (ctx->source_material); + _cogl_material_get_cogl_enable_flags (ctx->source_material); cogl_enable (enable_flags); _cogl_path_get_bounds (nodes_min, nodes_max, From 02faadae8bc89324431406d4fc617eb8b54e2821 Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Sat, 23 May 2009 17:52:18 +0100 Subject: [PATCH 07/37] [cogl] Remove cogl_flush_gl_state from the API This is being removed before we release Clutter 1.0 since the implementation wasn't complete, and so we assume no one is using this yet. Util we have someone with a good usecase, we can't pretend to support breaking out into raw OpenGL. --- cogl.h.in | 8 +++++++- common/cogl.c | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/cogl.h.in b/cogl.h.in index bd3698312..af4b26597 100644 --- a/cogl.h.in +++ b/cogl.h.in @@ -628,7 +628,12 @@ void cogl_push_draw_buffer (void); */ void cogl_pop_draw_buffer (void); -/** +/* XXX: Removed before we release Clutter 1.0 since the implementation + * wasn't complete, and so we assume no one is using this yet. Util we + * have some one with a good usecase, we can't pretend to support breaking + * out into raw OpenGL. */ +#if 0 +/* * cogl_flush_gl_state: * @flags: flags controlling what is flushed; currently unused, pass in 0 * @@ -642,6 +647,7 @@ void cogl_pop_draw_buffer (void); * Since: 1.0 */ void cogl_flush_gl_state (int flags); +#endif /* private */ void _cogl_set_indirect_context (gboolean indirect); diff --git a/common/cogl.c b/common/cogl.c index 8b85924f6..81c43bd5e 100644 --- a/common/cogl.c +++ b/common/cogl.c @@ -654,9 +654,11 @@ cogl_disable_fog (void) glDisable (GL_FOG); } +#if 0 void cogl_flush_gl_state (int flags) { _cogl_current_matrix_state_flush (); } +#endif From 58b89eabdf342b2bc1b684b28fd19dc8774f4795 Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Sun, 24 May 2009 04:04:38 +0100 Subject: [PATCH 08/37] [cogl-vertex-buffers] Support putting index arrays into VBOS It's now possible to add arrays of indices to a Cogl vertex buffer and they will be put into an OpenGL vertex buffer object. Since it's quite common for index arrays to be static it saves the OpenGL driver from having to validate them repeatedly. This changes the cogl_vertex_buffer_draw_elements API: It's no longer possible to provide a pointer to an index array at draw time. So cogl_vertex_buffer_draw_elements now takes an indices identifier that should correspond to an idendifier returned when calling cogl_vertex_buffer_add_indices () --- cogl-vertex-buffer.h | 79 +++++++++---- common/cogl-vertex-buffer-private.h | 33 ++++-- common/cogl-vertex-buffer.c | 161 ++++++++++++++++++++++++--- doc/reference/cogl/cogl-sections.txt | 2 + 4 files changed, 232 insertions(+), 43 deletions(-) diff --git a/cogl-vertex-buffer.h b/cogl-vertex-buffer.h index 717281db0..580ecfa10 100644 --- a/cogl-vertex-buffer.h +++ b/cogl-vertex-buffer.h @@ -256,6 +256,54 @@ cogl_vertex_buffer_draw (CoglHandle handle, GLint first, GLsizei count); +/** + * CoglIndicesType: + * @COGL_INDICES_TYPE_UNSIGNED_BYTE: Your indices are unsigned bytes + * @COGL_INDICES_TYPE_UNSIGNED_SHORT: Your indices are unsigned shorts + * @COGL_INDICES_TYPE_UNSIGNED_INT: You indices are unsigned integers + * + * You should aim to use the smallest data type that gives you enough + * range, since it reduces the size of your index array and can help + * reduce the demand on memory bandwidth. + */ +typedef enum _CoglIndicesType +{ + COGL_INDICES_TYPE_UNSIGNED_BYTE, + COGL_INDICES_TYPE_UNSIGNED_SHORT, + COGL_INDICES_TYPE_UNSIGNED_INT +} CoglIndicesType; + +/** + * cogl_vertex_buffer_add_indices: + * @handle: A vertex buffer handle + * @id: Any unique number. It's used to identify the indices when you later + * call cogl_vertex_buffer_draw_elements() + * @min_index: Specifies the minimum vertex index contained in indices + * @max_index: Specifies the maximum vertex index contained in indices + * @indices_type: a #CoglIndicesType specifying the data type used for + * the indices. + * @indices_array: Specifies the address of your array of indices + * @indices_len: The number of indices in indices_array + * + * Depending on how much geometry you are submitting it can be worthwhile + * optimizing the number of redundant vertices you submit. Using an index + * array allows you to reference vertices multiple times, for example + * during triangle strips. + * + * You should aim to use the COGL_INDICES_TYPE_UNSIGNED_SHORT when possible + * and correctly reflect the range of index values in the {min,max}_index + * arguments. This allows Cogl to optimize the internal storage used for + * the indices and reduce the demand for memory bandwidth. + */ +void +cogl_vertex_buffer_add_indices (CoglHandle handle, + int id, + unsigned int min_index, + unsigned int max_index, + CoglIndicesType indices_type, + const void *indices_array, + size_t indices_len); + /** * cogl_vertex_buffer_draw_elements: * @handle: A vertex buffer handle @@ -270,33 +318,26 @@ cogl_vertex_buffer_draw (CoglHandle handle, * GL_TRIANGLE_FAN * GL_TRIANGLES * - * (Note: only types available in GLES are listed) - * @min_index: Specifies the minimum vertex index contained in indices - * @max_index: Specifies the maximum vertex index contained in indices + * @indices_id: The identifier for a an array of indices previously added to + * the given Cogl vertex buffer using + * cogl_vertex_buffer_add_indices(). + * @indices_offset: An offset into named indices. The offset marks the first + * index to use for drawing. * @count: Specifies the number of vertices you want to draw. - * @indices_type: Specifies the data type used for the indices, and must be - * one of: - * - * GL_UNSIGNED_BYTE - * GL_UNSIGNED_SHORT - * GL_UNSIGNED_INT - * - * @indices: Specifies the address of your array of indices * * This function lets you use an array of indices to specify the vertices - * within your vertex buffer that you want to draw. + * within your vertex buffer that you want to draw. The indices themselves + * are given by calling cogl_vertex_buffer_add_indices () * * Any un-submitted attribute changes are automatically submitted before * drawing. */ void -cogl_vertex_buffer_draw_elements (CoglHandle handle, - GLenum mode, - GLuint min_index, - GLuint max_index, - GLsizei count, - GLenum indices_type, - const GLvoid *indices); +cogl_vertex_buffer_draw_elements (CoglHandle handle, + GLenum mode, + int indices_id, + unsigned int indices_offset, + unsigned int count); /** * cogl_vertex_buffer_ref: diff --git a/common/cogl-vertex-buffer-private.h b/common/cogl-vertex-buffer-private.h index 68a709b54..cc87b1828 100644 --- a/common/cogl-vertex-buffer-private.h +++ b/common/cogl-vertex-buffer-private.h @@ -99,9 +99,9 @@ typedef struct _CoglVertexBufferAttrib union _u { const void *pointer; - gsize vbo_offset; + size_t vbo_offset; } u; - gsize span_bytes; + size_t span_bytes; guint16 stride; guint8 n_components; guint8 texture_unit; @@ -129,24 +129,39 @@ typedef struct _CoglVertexBufferVBO { CoglVertexBufferVBOFlags flags; - /* Note: this is a pointer to handle fallbacks, and normally holds - * a GLuint value */ - gpointer vbo_name; /*!< The name of the corresponding buffer object */ - gsize vbo_bytes; /*!< The lengh of the allocated buffer object in bytes */ + /* Note: this is a pointer to handle fallbacks. It normally holds + * a GLuint VBO name, but when the driver doesn't support VBOs then + * this simply points to an malloc'd buffer. */ + void *vbo_name; /*!< The name of the corresponding buffer object */ + size_t vbo_bytes; /*!< The lengh of the allocated buffer object in bytes */ GList *attributes; } CoglVertexBufferVBO; +typedef struct _CoglVertexBufferIndices +{ + int id; + /* Note: this is a pointer to handle fallbacks. It normally holds + * a GLuint VBO name, but when the driver doesn't support VBOs then + * this simply points to an malloc'd buffer. */ + void *vbo_name; + GLenum type; + GLuint min_index; + GLuint max_index; +} CoglVertexBufferIndices; typedef struct _CoglVertexBuffer { CoglHandleObject _parent; - guint n_vertices; /*!< The number of vertices in the buffer */ - GList *submitted_vbos; /* The VBOs currently submitted to the GPU */ + int n_vertices; /*!< The number of vertices in the buffer */ + GList *submitted_vbos; /* The VBOs currently submitted to the GPU */ /* Note: new_attributes is normally NULL and only valid while * modifying a buffer. */ - GList *new_attributes; /*!< attributes pending submission */ + GList *new_attributes; /*!< attributes pending submission */ + + GList *indices; /*!< A list of associated index arrays */ + } CoglVertexBuffer; #endif /* __COGL_VERTEX_BUFFER_H */ diff --git a/common/cogl-vertex-buffer.c b/common/cogl-vertex-buffer.c index 842551b04..cd450ea93 100644 --- a/common/cogl-vertex-buffer.c +++ b/common/cogl-vertex-buffer.c @@ -214,6 +214,8 @@ cogl_vertex_buffer_new (guint n_vertices) buffer->submitted_vbos = NULL; buffer->new_attributes = NULL; + buffer->indices = NULL; + /* return COGL_INVALID_HANDLE; */ return _cogl_vertex_buffer_handle_new (buffer); } @@ -1727,13 +1729,11 @@ cogl_vertex_buffer_draw (CoglHandle handle, if (!cogl_is_vertex_buffer (handle)) return; - cogl_clip_ensure (); - buffer = _cogl_vertex_buffer_pointer_from_handle (handle); - enable_state_for_drawing_buffer (buffer); - + cogl_clip_ensure (); _cogl_current_matrix_state_flush (); + enable_state_for_drawing_buffer (buffer); /* FIXME: flush cogl cache */ GE (glDrawArrays (mode, first, count)); @@ -1741,35 +1741,158 @@ cogl_vertex_buffer_draw (CoglHandle handle, disable_state_for_drawing_buffer (buffer); } +static void +free_vertex_buffer_indices (CoglVertexBufferIndices *indices) +{ + gboolean fallback = + (cogl_get_features () & COGL_FEATURE_VBOS) ? FALSE : TRUE; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (fallback) + g_free (indices->vbo_name); + else + GE (glDeleteBuffers (1, (GLuint *)&indices->vbo_name)); + + g_slice_free (CoglVertexBufferIndices, indices); +} + +static int +get_indices_type_size (GLuint indices_type) +{ + if (indices_type == GL_UNSIGNED_BYTE) + return sizeof (GLubyte); + if (indices_type == GL_UNSIGNED_SHORT) + return sizeof (GLushort); + else + { + g_critical ("Unknown indices type %d\n", indices_type); + return 0; + } +} + void -cogl_vertex_buffer_draw_elements (CoglHandle handle, - GLenum mode, - GLuint min_index, - GLuint max_index, - GLsizei count, - GLenum indices_type, - const GLvoid *indices) +cogl_vertex_buffer_add_indices (CoglHandle handle, + int id, + unsigned int min_index, + unsigned int max_index, + CoglIndicesType indices_type, + const void *indices_array, + size_t indices_len) { CoglVertexBuffer *buffer; + GList *l; + gboolean fallback = + (cogl_get_features () & COGL_FEATURE_VBOS) ? FALSE : TRUE; + size_t indices_bytes; + CoglVertexBufferIndices *indices; _COGL_GET_CONTEXT (ctx, NO_RETVAL); if (!cogl_is_vertex_buffer (handle)) return; - cogl_clip_ensure (); + buffer = _cogl_vertex_buffer_pointer_from_handle (handle); + + for (l = buffer->indices; l; l = l->next) + { + CoglVertexBufferIndices *current_indices = l->data; + if (current_indices->id == id) + { + free_vertex_buffer_indices (l->data); + buffer->indices = g_list_delete_link (buffer->indices, l); + break; + } + } + + indices = g_slice_alloc (sizeof (CoglVertexBufferIndices)); + indices->id = id; + indices->min_index = min_index; + indices->max_index = max_index; + + if (indices_type == COGL_INDICES_TYPE_UNSIGNED_BYTE) + indices->type = GL_UNSIGNED_BYTE; + else if (indices_type == COGL_INDICES_TYPE_UNSIGNED_SHORT) + indices->type = GL_UNSIGNED_SHORT; + else + { + g_critical ("unknown indices type %d", indices_type); + g_slice_free (CoglVertexBufferIndices, indices); + return; + } + + indices_bytes = get_indices_type_size (indices->type) * indices_len; + if (fallback) + { + indices->vbo_name = g_malloc (indices_len); + memcpy (indices->vbo_name, indices_array, indices_bytes); + } + else + { + GE (glGenBuffers (1, (GLuint *)&indices->vbo_name)); + GE (glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, + GPOINTER_TO_UINT (indices->vbo_name))); + GE (glBufferData (GL_ELEMENT_ARRAY_BUFFER, + indices_bytes, + indices_array, + GL_STATIC_DRAW)); + GE (glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0)); + } + + buffer->indices = g_list_prepend (buffer->indices, indices); +} + +void +cogl_vertex_buffer_draw_elements (CoglHandle handle, + GLenum mode, + int indices_id, + unsigned int indices_offset, + unsigned int count) +{ + CoglVertexBuffer *buffer; + gboolean fallback = + (cogl_get_features () & COGL_FEATURE_VBOS) ? FALSE : TRUE; + size_t byte_offset; + GList *l; + CoglVertexBufferIndices *indices = NULL; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (!cogl_is_vertex_buffer (handle)) + return; buffer = _cogl_vertex_buffer_pointer_from_handle (handle); + cogl_clip_ensure (); + _cogl_current_matrix_state_flush (); enable_state_for_drawing_buffer (buffer); - _cogl_current_matrix_state_flush (); + for (l = buffer->indices; l; l = l->next) + { + CoglVertexBufferIndices *current_indices = l->data; + if (current_indices->id == indices_id) + { + indices = current_indices; + break; + } + } + if (!indices) + return; + + byte_offset = indices_offset * get_indices_type_size (indices->type); + if (fallback) + byte_offset = (size_t)(((char *)indices->vbo_name) + byte_offset); + else + GE (glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, + GPOINTER_TO_UINT (indices->vbo_name))); /* FIXME: flush cogl cache */ - GE (glDrawRangeElements (mode, min_index, max_index, - count, indices_type, indices)); + GE (glDrawRangeElements (mode, indices->min_index, indices->max_index, + count, indices->type, (void *)byte_offset)); disable_state_for_drawing_buffer (buffer); + + GE (glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0)); } static void @@ -1779,8 +1902,16 @@ _cogl_vertex_buffer_free (CoglVertexBuffer *buffer) for (tmp = buffer->submitted_vbos; tmp != NULL; tmp = tmp->next) cogl_vertex_buffer_vbo_free (tmp->data, TRUE); + g_list_free (buffer->submitted_vbos); + for (tmp = buffer->new_attributes; tmp != NULL; tmp = tmp->next) cogl_vertex_buffer_attribute_free (tmp->data); + g_list_free (buffer->new_attributes); + + for (tmp = buffer->indices; tmp != NULL; tmp = tmp->next) + free_vertex_buffer_indices (tmp->data); + g_list_free (buffer->indices); g_slice_free (CoglVertexBuffer, buffer); } + diff --git a/doc/reference/cogl/cogl-sections.txt b/doc/reference/cogl/cogl-sections.txt index 1041ded78..8b1d5161c 100644 --- a/doc/reference/cogl/cogl-sections.txt +++ b/doc/reference/cogl/cogl-sections.txt @@ -307,6 +307,8 @@ cogl_vertex_buffer_submit cogl_vertex_buffer_disable cogl_vertex_buffer_enable cogl_vertex_buffer_draw +CoglIndicesType +cogl_vertex_buffer_add_indices cogl_vertex_buffer_draw_elements CoglVertexBufferAttribFlags From e4d820b75d1b09b952fd78fd161a25da4425c0d3 Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Sun, 24 May 2009 11:33:29 +0100 Subject: [PATCH 09/37] [cogl-vertex-buffer] Seal GL types from the public API We now have CoglAttributeType and CoglVerticesMode typedefs to replace the use of GLenum in the public API. --- cogl-vertex-buffer.h | 118 +++++++++++++++++++++--------------- common/cogl-vertex-buffer.c | 48 +++++++-------- 2 files changed, 93 insertions(+), 73 deletions(-) diff --git a/cogl-vertex-buffer.h b/cogl-vertex-buffer.h index 580ecfa10..4d229bd63 100644 --- a/cogl-vertex-buffer.h +++ b/cogl-vertex-buffer.h @@ -94,6 +94,24 @@ cogl_vertex_buffer_new (guint n_vertices); guint cogl_vertex_buffer_get_n_vertices (CoglHandle handle); +/** + * CoglAttributeType: + * @COGL_ATTRIBUTE_TYPE_BYTE: + * @COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE: + * @COGL_ATTRIBUTE_TYPE_SHORT: + * @COGL_ATTRIBUTE_TYPE_UNSIGNED_SHORT: + * @COGL_ATTRIBUTE_TYPE_FLOAT: + * + */ +typedef enum _CoglAttributeType +{ + COGL_ATTRIBUTE_TYPE_BYTE = GL_BYTE, + COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE = GL_UNSIGNED_BYTE, + COGL_ATTRIBUTE_TYPE_SHORT = GL_SHORT, + COGL_ATTRIBUTE_TYPE_UNSIGNED_SHORT = GL_UNSIGNED_SHORT, + COGL_ATTRIBUTE_TYPE_FLOAT = GL_FLOAT +} CoglAttributeType; + /** * cogl_vertex_buffer_add: * @handle: A vertex buffer handle @@ -111,10 +129,9 @@ cogl_vertex_buffer_get_n_vertices (CoglHandle handle); * the name can have a detail component, E.g. * "gl_Color::active" or "gl_Color::inactive" * @n_components: The number of components per attribute and must be 1,2,3 or 4 - * @gl_type: Specifies the data type of each component (GL_BYTE, GL_UNSIGNED_BYTE, - * GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT or GL_FLOAT) + * @type: a #CoglAttributeType specifying the data type of each component. * @normalized: If GL_TRUE, this specifies that values stored in an integer - * format should be mapped into the range [-1.0, 1.0] or [0.1, 1.0] + * format should be mapped into the range [-1.0, 1.0] or [0.0, 1.0] * for unsigned values. If GL_FALSE they are converted to floats * directly. * @stride: This specifies the number of bytes from the start of one attribute @@ -156,13 +173,13 @@ cogl_vertex_buffer_get_n_vertices (CoglHandle handle); * (Though you can have multiple groups of interleved attributes) */ void -cogl_vertex_buffer_add (CoglHandle handle, - const char *attribute_name, - guint8 n_components, - GLenum gl_type, - gboolean normalized, - guint16 stride, - const void *pointer); +cogl_vertex_buffer_add (CoglHandle handle, + const char *attribute_name, + guint8 n_components, + CoglAttributeType type, + gboolean normalized, + guint16 stride, + const void *pointer); /** * cogl_vertex_buffer_delete: @@ -226,21 +243,33 @@ void cogl_vertex_buffer_enable (CoglHandle handle, const char *attribute_name); +/** + * CoglVerticesMode: + * COGL_VERTICES_MODE_POINTS: + * COGL_VERTICES_MODE_LINE_STRIP: + * COGL_VERTICES_MODE_LINE_LOOP: + * COGL_VERTICES_MODE_LINES: + * COGL_VERTICES_MODE_TRIANGLE_STRIP: + * COGL_VERTICES_MODE_TRIANGLE_FAN: + * COGL_VERTICES_MODE_TRIANGLES: + * + */ +typedef enum _CoglVerticesMode +{ + COGL_VERTICES_MODE_POINTS = GL_POINTS, + COGL_VERTICES_MODE_LINE_STRIP = GL_LINE_STRIP, + COGL_VERTICES_MODE_LINE_LOOP = GL_LINE_LOOP, + COGL_VERTICES_MODE_LINES = GL_LINES, + COGL_VERTICES_MODE_TRIANGLE_STRIP = GL_TRIANGLE_STRIP, + COGL_VERTICES_MODE_TRIANGLE_FAN = GL_TRIANGLE_FAN, + COGL_VERTICES_MODE_TRIANGLES = GL_TRIANGLES +} CoglVerticesMode; + /** * cogl_vertex_buffer_draw: * @handle: A vertex buffer handle - * @mode: Specifies how the vertices should be interpreted, and should be - * a valid GL primitive type: - * - * GL_POINTS - * GL_LINE_STRIP - * GL_LINE_LOOP - * GL_LINES - * GL_TRIANGLE_STRIP - * GL_TRIANGLE_FAN - * GL_TRIANGLES - * - * (Note: only types available in GLES are listed) + * @mode: A #CoglVerticesMode specifying how the vertices should be + * interpreted. * @first: Specifies the index of the first vertex you want to draw with * @count: Specifies the number of vertices you want to draw. * @@ -251,10 +280,10 @@ cogl_vertex_buffer_enable (CoglHandle handle, * drawing. */ void -cogl_vertex_buffer_draw (CoglHandle handle, - GLenum mode, - GLint first, - GLsizei count); +cogl_vertex_buffer_draw (CoglHandle handle, + CoglVerticesMode mode, + int first, + int count); /** * CoglIndicesType: @@ -296,28 +325,19 @@ typedef enum _CoglIndicesType * the indices and reduce the demand for memory bandwidth. */ void -cogl_vertex_buffer_add_indices (CoglHandle handle, - int id, - unsigned int min_index, - unsigned int max_index, - CoglIndicesType indices_type, - const void *indices_array, - size_t indices_len); +cogl_vertex_buffer_add_indices (CoglHandle handle, + int id, + int min_index, + int max_index, + CoglIndicesType indices_type, + const void *indices_array, + int indices_len); /** * cogl_vertex_buffer_draw_elements: * @handle: A vertex buffer handle - * @mode: Specifies how the vertices should be interpreted, and should be - * a valid GL primitive type: - * - * GL_POINTS - * GL_LINE_STRIP - * GL_LINE_LOOP - * GL_LINES - * GL_TRIANGLE_STRIP - * GL_TRIANGLE_FAN - * GL_TRIANGLES - * + * @mode: A #CoglVerticesMode specifying how the vertices should be + * interpreted. * @indices_id: The identifier for a an array of indices previously added to * the given Cogl vertex buffer using * cogl_vertex_buffer_add_indices(). @@ -333,11 +353,11 @@ cogl_vertex_buffer_add_indices (CoglHandle handle, * drawing. */ void -cogl_vertex_buffer_draw_elements (CoglHandle handle, - GLenum mode, - int indices_id, - unsigned int indices_offset, - unsigned int count); +cogl_vertex_buffer_draw_elements (CoglHandle handle, + CoglVerticesMode mode, + int indices_id, + int indices_offset, + int count); /** * cogl_vertex_buffer_ref: diff --git a/common/cogl-vertex-buffer.c b/common/cogl-vertex-buffer.c index cd450ea93..7c8269765 100644 --- a/common/cogl-vertex-buffer.c +++ b/common/cogl-vertex-buffer.c @@ -414,13 +414,13 @@ get_gl_type_size (CoglVertexBufferAttribFlags flags) } void -cogl_vertex_buffer_add (CoglHandle handle, - const char *attribute_name, - guint8 n_components, - GLenum gl_type, - gboolean normalized, - guint16 stride, - const void *pointer) +cogl_vertex_buffer_add (CoglHandle handle, + const char *attribute_name, + guint8 n_components, + CoglAttributeType type, + gboolean normalized, + guint16 stride, + const void *pointer) { CoglVertexBuffer *buffer; GQuark name_quark = g_quark_from_string (attribute_name); @@ -488,7 +488,7 @@ cogl_vertex_buffer_add (CoglHandle handle, attribute->u.pointer = pointer; attribute->texture_unit = texture_unit; - flags |= get_attribute_gl_type_flag_from_gl_type (gl_type); + flags |= get_attribute_gl_type_flag_from_gl_type (type); flags |= COGL_VERTEX_BUFFER_ATTRIB_FLAG_ENABLED; /* Note: We currently just assume, if an attribute is *ever* updated @@ -1719,10 +1719,10 @@ disable_state_for_drawing_buffer (CoglVertexBuffer *buffer) } void -cogl_vertex_buffer_draw (CoglHandle handle, - GLenum mode, - GLint first, - GLsizei count) +cogl_vertex_buffer_draw (CoglHandle handle, + CoglVerticesMode mode, + int first, + int count) { CoglVertexBuffer *buffer; @@ -1772,13 +1772,13 @@ get_indices_type_size (GLuint indices_type) } void -cogl_vertex_buffer_add_indices (CoglHandle handle, - int id, - unsigned int min_index, - unsigned int max_index, - CoglIndicesType indices_type, - const void *indices_array, - size_t indices_len) +cogl_vertex_buffer_add_indices (CoglHandle handle, + int id, + int min_index, + int max_index, + CoglIndicesType indices_type, + const void *indices_array, + int indices_len) { CoglVertexBuffer *buffer; GList *l; @@ -1843,11 +1843,11 @@ cogl_vertex_buffer_add_indices (CoglHandle handle, } void -cogl_vertex_buffer_draw_elements (CoglHandle handle, - GLenum mode, - int indices_id, - unsigned int indices_offset, - unsigned int count) +cogl_vertex_buffer_draw_elements (CoglHandle handle, + CoglVerticesMode mode, + int indices_id, + int indices_offset, + int count) { CoglVertexBuffer *buffer; gboolean fallback = From 1669fd7332ca760f3363c3dfe4afdc8949a6a3cd Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Tue, 26 May 2009 16:27:36 +0100 Subject: [PATCH 10/37] [vbo indices] tweak add_indices api to return an id and add delete_indices api Originally cogl_vertex_buffer_add_indices let the user pass in their own unique ID for the indices; now the Id is generated internally and returned to the caller. --- cogl-vertex-buffer.h | 30 +++++++++++----- common/cogl-vertex-buffer.c | 52 ++++++++++++++++++---------- doc/reference/cogl/cogl-sections.txt | 1 + 3 files changed, 57 insertions(+), 26 deletions(-) diff --git a/cogl-vertex-buffer.h b/cogl-vertex-buffer.h index 4d229bd63..1887db566 100644 --- a/cogl-vertex-buffer.h +++ b/cogl-vertex-buffer.h @@ -305,8 +305,6 @@ typedef enum _CoglIndicesType /** * cogl_vertex_buffer_add_indices: * @handle: A vertex buffer handle - * @id: Any unique number. It's used to identify the indices when you later - * call cogl_vertex_buffer_draw_elements() * @min_index: Specifies the minimum vertex index contained in indices * @max_index: Specifies the maximum vertex index contained in indices * @indices_type: a #CoglIndicesType specifying the data type used for @@ -319,20 +317,36 @@ typedef enum _CoglIndicesType * array allows you to reference vertices multiple times, for example * during triangle strips. * - * You should aim to use the COGL_INDICES_TYPE_UNSIGNED_SHORT when possible - * and correctly reflect the range of index values in the {min,max}_index - * arguments. This allows Cogl to optimize the internal storage used for - * the indices and reduce the demand for memory bandwidth. + * You should aim to use the smallest data type possible and correctly reflect + * the range of index values in the {min,max}_index arguments. This allows Cogl + * to optimize the internal storage used for the indices and reduce the demand + * for memory bandwidth. + * + * Returns: An identifier (greater than 0) for the indices which you can + * pass to cogl_vertex_buffer_draw_elements(). */ -void +int cogl_vertex_buffer_add_indices (CoglHandle handle, - int id, int min_index, int max_index, CoglIndicesType indices_type, const void *indices_array, int indices_len); +/** + * cogl_vertex_buffer_delete_indices: + * @handle: A vertex buffer handle + * @indices_id: The identifier for a an array of indices previously added to + * the given Cogl vertex buffer using + * cogl_vertex_buffer_add_indices(). + * + * Frees the resources associated with a previously added array of vertex + * indices. + */ +void +cogl_vertex_buffer_delete_indices (CoglHandle handle, + int indices_id); + /** * cogl_vertex_buffer_draw_elements: * @handle: A vertex buffer handle diff --git a/common/cogl-vertex-buffer.c b/common/cogl-vertex-buffer.c index 7c8269765..096a4a47c 100644 --- a/common/cogl-vertex-buffer.c +++ b/common/cogl-vertex-buffer.c @@ -1771,9 +1771,8 @@ get_indices_type_size (GLuint indices_type) } } -void +int cogl_vertex_buffer_add_indices (CoglHandle handle, - int id, int min_index, int max_index, CoglIndicesType indices_type, @@ -1781,32 +1780,23 @@ cogl_vertex_buffer_add_indices (CoglHandle handle, int indices_len) { CoglVertexBuffer *buffer; - GList *l; gboolean fallback = (cogl_get_features () & COGL_FEATURE_VBOS) ? FALSE : TRUE; size_t indices_bytes; CoglVertexBufferIndices *indices; - _COGL_GET_CONTEXT (ctx, NO_RETVAL); + static int next_indices_id = 1; + + + _COGL_GET_CONTEXT (ctx, 0); if (!cogl_is_vertex_buffer (handle)) - return; + return 0; buffer = _cogl_vertex_buffer_pointer_from_handle (handle); - for (l = buffer->indices; l; l = l->next) - { - CoglVertexBufferIndices *current_indices = l->data; - if (current_indices->id == id) - { - free_vertex_buffer_indices (l->data); - buffer->indices = g_list_delete_link (buffer->indices, l); - break; - } - } - indices = g_slice_alloc (sizeof (CoglVertexBufferIndices)); - indices->id = id; + indices->id = next_indices_id; indices->min_index = min_index; indices->max_index = max_index; @@ -1818,7 +1808,7 @@ cogl_vertex_buffer_add_indices (CoglHandle handle, { g_critical ("unknown indices type %d", indices_type); g_slice_free (CoglVertexBufferIndices, indices); - return; + return 0; } indices_bytes = get_indices_type_size (indices->type) * indices_len; @@ -1840,6 +1830,32 @@ cogl_vertex_buffer_add_indices (CoglHandle handle, } buffer->indices = g_list_prepend (buffer->indices, indices); + + return next_indices_id++; +} + +void +cogl_vertex_buffer_delete_indices (CoglHandle handle, + int indices_id) +{ + CoglVertexBuffer *buffer; + GList *l; + + if (!cogl_is_vertex_buffer (handle)) + return; + + buffer = _cogl_vertex_buffer_pointer_from_handle (handle); + + for (l = buffer->indices; l; l = l->next) + { + CoglVertexBufferIndices *current_indices = l->data; + if (current_indices->id == indices_id) + { + free_vertex_buffer_indices (l->data); + buffer->indices = g_list_delete_link (buffer->indices, l); + return; + } + } } void diff --git a/doc/reference/cogl/cogl-sections.txt b/doc/reference/cogl/cogl-sections.txt index 8b1d5161c..25f5e98c8 100644 --- a/doc/reference/cogl/cogl-sections.txt +++ b/doc/reference/cogl/cogl-sections.txt @@ -309,6 +309,7 @@ cogl_vertex_buffer_enable cogl_vertex_buffer_draw CoglIndicesType cogl_vertex_buffer_add_indices +cogl_vertex_buffer_delete_indices cogl_vertex_buffer_draw_elements CoglVertexBufferAttribFlags From 25b3c84a5ac8867790669ee22c7f588e6eca66a6 Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Tue, 26 May 2009 15:41:53 +0100 Subject: [PATCH 11/37] [cogl] Remove cogl_{create,destroy}_context from the public API cogl_create_context is dealt with internally when _cogl_get_default context is called, and cogl_destroy_context is currently never called. It might be nicer later to get an object back when creating a context so Cogl can support multiple contexts, so these functions are being removed from the API until we get a chance to address context management properly. For now cogl_destroy_context is still exported as _cogl_destroy_context so Clutter could at least install a library deinit handler to call it. --- cogl.h.in | 28 ++++++++++++---------------- doc/reference/cogl/cogl-sections.txt | 3 --- gl/cogl-context.c | 4 ++-- gles/cogl-context.c | 4 ++-- 4 files changed, 16 insertions(+), 23 deletions(-) diff --git a/cogl.h.in b/cogl.h.in index af4b26597..b5bb55d10 100644 --- a/cogl.h.in +++ b/cogl.h.in @@ -55,22 +55,6 @@ G_BEGIN_DECLS * General utility functions for COGL. */ -/* Context manipulation */ - -/** - * cogl_create_context: - * - * FIXME - */ -gboolean cogl_create_context (void); - -/** - * cogl_destroy_context: - * - * FIXME - */ -void cogl_destroy_context (void); - /** * cogl_get_option_group: * @@ -628,6 +612,18 @@ void cogl_push_draw_buffer (void); */ void cogl_pop_draw_buffer (void); + +/* + * Internal API available only to Clutter. + * + * These are typically only to deal with the poor seperation of + * responsabilities that currently exists between Clutter and Cogl. + * Eventually a lot of the backend code currently in Clutter will + * move down into Cogl and these functions will be removed. + */ + +void _cogl_destroy_context (void); + /* XXX: Removed before we release Clutter 1.0 since the implementation * wasn't complete, and so we assume no one is using this yet. Util we * have some one with a good usecase, we can't pretend to support breaking diff --git a/doc/reference/cogl/cogl-sections.txt b/doc/reference/cogl/cogl-sections.txt index 25f5e98c8..6ee2d9517 100644 --- a/doc/reference/cogl/cogl-sections.txt +++ b/doc/reference/cogl/cogl-sections.txt @@ -15,9 +15,6 @@ COGL_UNPREMULT_MASK CoglPixelFormat CoglBufferTarget -cogl_create_context -cogl_destroy_context - CoglFeatureFlags cogl_get_features cogl_features_available diff --git a/gl/cogl-context.c b/gl/cogl-context.c index db5541148..39415a02a 100644 --- a/gl/cogl-context.c +++ b/gl/cogl-context.c @@ -37,7 +37,7 @@ static CoglContext *_context = NULL; static gboolean gl_is_indirect = FALSE; -gboolean +static gboolean cogl_create_context () { GLubyte default_texture_data[] = { 0xff, 0xff, 0xff, 0x0 }; @@ -175,7 +175,7 @@ cogl_create_context () } void -cogl_destroy_context () +_cogl_destroy_context () { if (_context == NULL) return; diff --git a/gles/cogl-context.c b/gles/cogl-context.c index 1d2d02843..5b6ce7c1b 100644 --- a/gles/cogl-context.c +++ b/gles/cogl-context.c @@ -39,7 +39,7 @@ static CoglContext *_context = NULL; static gboolean gl_is_indirect = FALSE; -gboolean +static gboolean cogl_create_context () { GLubyte default_texture_data[] = { 0xff, 0xff, 0xff, 0x0 }; @@ -133,7 +133,7 @@ cogl_create_context () } void -cogl_destroy_context () +_cogl_destroy_context () { if (_context == NULL) return; From 18193e5322500b9cd3f372223b33581558758312 Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Tue, 26 May 2009 11:33:54 +0100 Subject: [PATCH 12/37] [cogl matrix] Support ortho and perspective projections. This adds cogl_matrix api for multiplying matrices either by a perspective or ortho projective transform. The internal matrix stack and current-matrix APIs also have corresponding support added. New public API: cogl_matrix_perspective cogl_matrix_ortho cogl_ortho cogl_set_modelview_matrix cogl_set_projection_matrix --- cogl-matrix.h | 70 +++++++-- cogl.h.in | 39 +++++ common/cogl-current-matrix.c | 213 +++++++++++++++------------ common/cogl-matrix-stack.c | 72 ++++++--- common/cogl-matrix-stack.h | 20 ++- common/cogl-matrix.c | 87 +++++++++-- doc/reference/cogl/cogl-sections.txt | 19 ++- 7 files changed, 371 insertions(+), 149 deletions(-) diff --git a/cogl-matrix.h b/cogl-matrix.h index ca643f146..bd7b579c7 100644 --- a/cogl-matrix.h +++ b/cogl-matrix.h @@ -199,22 +199,50 @@ void cogl_matrix_frustum (CoglMatrix *matrix, float z_far); /** - * cogl_matrix_transform_point: + * cogl_matrix_perspective: * @matrix: A 4x4 transformation matrix - * @x: The X component of your points position [in:out] - * @y: The Y component of your points position [in:out] - * @z: The Z component of your points position [in:out] - * @w: The W component of your points position [in:out] + * @fov_y: A field of view angle for the Y axis + * @aspect: The ratio of width to height determining the field of view angle + * for the x axis. + * @z_near: The distance to the near clip plane. + * Never pass 0 and always pass a positive number. + * @z_far: The distance to the far clip plane. (Should always be positive) * - * This transforms a point whos position is given and returned - * as four float components. + * Multiplies the matrix by the described perspective matrix + * + * Note: you should be careful not to have to great a z_far / z_near ratio + * since that will reduce the effectiveness of depth testing since there wont + * be enough precision to identify the depth of objects near to each other. */ void -cogl_matrix_transform_point (const CoglMatrix *matrix, - float *x, - float *y, - float *z, - float *w); +cogl_matrix_perspective (CoglMatrix *matrix, + float fov_y, + float aspect, + float z_near, + float z_far); + +/** + * cogl_matrix_ortho: + * @matrix: A 4x4 transformation matrix + * @left: The coordinate for the left clipping plane + * @right: The coordinate for the right clipping plane + * @bottom: The coordinate for the bottom clipping plane + * @top: The coordinate for the top clipping plane + * @near: The coordinate for the near clipping plane (may be negative if + * the plane is behind the viewer) + * @far: The coordinate for the far clipping plane (may be negative if + * the plane is behind the viewer) + * + * Multiples the matrix by a parallel projection matrix. + */ +void +cogl_matrix_ortho (CoglMatrix *matrix, + float left, + float right, + float bottom, + float top, + float near, + float far); /** * cogl_matrix_init_from_array: @@ -234,6 +262,24 @@ void cogl_matrix_init_from_array (CoglMatrix *matrix, const float *array); */ const float *cogl_matrix_get_array (const CoglMatrix *matrix); +/** + * cogl_matrix_transform_point: + * @matrix: A 4x4 transformation matrix + * @x: The X component of your points position [in:out] + * @y: The Y component of your points position [in:out] + * @z: The Z component of your points position [in:out] + * @w: The W component of your points position [in:out] + * + * This transforms a point whos position is given and returned + * as four float components. + */ +void +cogl_matrix_transform_point (const CoglMatrix *matrix, + float *x, + float *y, + float *z, + float *w); + G_END_DECLS #endif /* __COGL_MATRIX_H */ diff --git a/cogl.h.in b/cogl.h.in index b5bb55d10..e66cbc394 100644 --- a/cogl.h.in +++ b/cogl.h.in @@ -170,6 +170,29 @@ void cogl_frustum (float left, float z_near, float z_far); +/** + * cogl_ortho: + * @left: The coordinate for the left clipping plane + * @right: The coordinate for the right clipping plane + * @bottom: The coordinate for the bottom clipping plane + * @top: The coordinate for the top clipping plane + * @near: The coordinate for the near clipping plane (may be negative if + * the plane is behind the viewer) + * @far: The coordinate for the far clipping plane (may be negative if + * the plane is behind the viewer) + * + * Replaces the current projection matrix with a parallel projection + * matrix. + * + * Since: 1.0 + */ +void cogl_ortho (float left, + float right, + float bottom, + float top, + float near, + float far); + /** * cogl_setup_viewport: * @width: Width of the viewport @@ -272,6 +295,14 @@ void cogl_rotate (float angle, */ void cogl_get_modelview_matrix (CoglMatrix *matrix); +/** + * cogl_set_modelview_matrix: + * @matrix: pointer to a CoglMatrix to set as the new model-view matrix + * + * Loads matrix as the new model-view matrix. + */ +void cogl_set_modelview_matrix (CoglMatrix *matrix); + /** * cogl_get_projection_matrix: * @matrix: pointer to a CoglMatrix to recieve the matrix @@ -280,6 +311,14 @@ void cogl_get_modelview_matrix (CoglMatrix *matrix); */ void cogl_get_projection_matrix (CoglMatrix *matrix); +/** + * cogl_set_projection_matrix: + * @matrix: pointer to a CoglMatrix to set as the new projection matrix + * + * Loads matrix as the new projection matrix. + */ +void cogl_set_projection_matrix (CoglMatrix *matrix); + /** * cogl_get_viewport: * @v: pointer to a 4 element array of #floats to diff --git a/common/cogl-current-matrix.c b/common/cogl-current-matrix.c index 0080af0d1..e01987c95 100644 --- a/common/cogl-current-matrix.c +++ b/common/cogl-current-matrix.c @@ -45,6 +45,9 @@ #define glFrustum(L,R,B,T,N,F) \ glFrustumf((GLfloat)L, (GLfloat)R, (GLfloat)B, \ (GLfloat)T, (GLfloat)N, (GLfloat)F) + +#define glOrtho glOrthof + #endif #include @@ -209,30 +212,57 @@ _cogl_current_matrix_frustum (float left, } void -_cogl_current_matrix_ortho (float left, - float right, - float bottom, - float top, - float near_val, - float far_val) +_cogl_current_matrix_perspective (float fov_y, + float aspect, + float z_near, + float z_far) +{ + _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL); + + if (current_stack != NULL) + _cogl_matrix_stack_perspective (current_stack, + fov_y, aspect, z_near, z_far); + else + { + /* NB: There is no glPerspective() (only gluPerspective()) so we use + * cogl_matrix_perspective: */ + CoglMatrix matrix; + _cogl_get_matrix (ctx->matrix_mode, &matrix); + cogl_matrix_perspective (&matrix, + fov_y, aspect, z_near, z_far); + _cogl_current_matrix_load (&matrix); + } +} + +void +_cogl_current_matrix_ortho (float left, + float right, + float bottom, + float top, + float near, + float far) { -#if 0 _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL); if (current_stack != NULL) _cogl_matrix_stack_ortho (current_stack, left, right, - top, bottom, - near_val, - far_val); + bottom, top, + near, + far); else - GE (glOrtho (left, right, bottom, top, near_val, far_val)); + { +#ifdef HAVE_COGL_GLES2 + /* NB: GLES 2 has no glOrtho(): */ + CoglMatrix matrix; + _cogl_get_matrix (ctx->matrix_mode, &matrix); + cogl_matrix_ortho (&matrix, + left, right, bottom, top, near, far); + _cogl_current_matrix_load (&matrix); #else - /* Nobody is using glOrtho right now anyway, so not bothering */ - g_warning ("%s not implemented, need to code cogl_matrix_ortho() if you need" - " this function", - G_STRFUNC); + GE (glOrtho (left, right, bottom, top, near, far)); #endif + } } void @@ -276,6 +306,12 @@ _cogl_get_matrix (CoglMatrixMode mode, } } +void +_cogl_set_matrix (const CoglMatrix *matrix) +{ + _cogl_current_matrix_load (matrix); +} + void _cogl_current_matrix_state_init (void) { @@ -354,85 +390,19 @@ cogl_rotate (float angle, float x, float y, float z) } void -_cogl_set_matrix (const CoglMatrix *matrix) -{ - _cogl_current_matrix_load (matrix); -} - -void -cogl_get_modelview_matrix (CoglMatrix *matrix) -{ - _cogl_get_matrix (COGL_MATRIX_MODELVIEW, - matrix); -} - -void -cogl_get_projection_matrix (CoglMatrix *matrix) -{ - _cogl_get_matrix (COGL_MATRIX_PROJECTION, - matrix); -} - -void -cogl_perspective (float fovy, +cogl_perspective (float fov_y, float aspect, - float zNear, - float zFar) + float z_near, + float z_far) { - float xmax, ymax; - float x, y, c, d; - float fovy_rad_half = (fovy * G_PI) / 360; - CoglMatrix perspective; - GLfloat m[16]; + float ymax = z_near * tanf (fov_y * G_PI / 360.0); - _COGL_GET_CONTEXT (ctx, NO_RETVAL); - - memset (&m[0], 0, sizeof (m)); - - _cogl_set_current_matrix (COGL_MATRIX_PROJECTION); - _cogl_current_matrix_identity (); - - /* - * Based on the original algorithm in perspective(): - * - * 1) xmin = -xmax => xmax + xmin == 0 && xmax - xmin == 2 * xmax - * same true for y, hence: a == 0 && b == 0; - * - * 2) When working with small numbers, we are loosing significant - * precision - */ - ymax = (zNear * (sinf (fovy_rad_half) / cosf (fovy_rad_half))); - xmax = (ymax * aspect); - - x = (zNear / xmax); - y = (zNear / ymax); - c = (-(zFar + zNear) / ( zFar - zNear)); - d = (-(2 * zFar) * zNear) / (zFar - zNear); - -#define M(row,col) m[col*4+row] - M(0,0) = x; - M(1,1) = y; - M(2,2) = c; - M(2,3) = d; - M(3,2) = -1.0; - - cogl_matrix_init_from_array (&perspective, m); - _cogl_current_matrix_multiply (&perspective); - - _cogl_set_current_matrix (COGL_MATRIX_MODELVIEW); - - /* Calculate and store the inverse of the matrix */ - memset (ctx->inverse_projection, 0, sizeof (float) * 16); - -#define m ctx->inverse_projection - M(0, 0) = (1.0 / x); - M(1, 1) = (1.0 / y); - M(2, 3) = -1.0; - M(3, 2) = (1.0 / d); - M(3, 3) = (c / d); -#undef m - -#undef M + cogl_frustum (-ymax * aspect, /* left */ + ymax * aspect, /* right */ + -ymax, /* bottom */ + ymax, /* top */ + z_near, + z_far); } void @@ -474,4 +444,65 @@ cogl_frustum (float left, M(3,2) = 1.0 / d; M(3,3) = c / d; #undef M + + _cogl_set_current_matrix (COGL_MATRIX_MODELVIEW); } + +void +cogl_ortho (float left, + float right, + float bottom, + float top, + float near, + float far) +{ + CoglMatrix ortho; + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + cogl_matrix_init_identity (&ortho); + cogl_matrix_ortho (&ortho, left, right, bottom, top, near, far); + _cogl_set_current_matrix (COGL_MATRIX_PROJECTION); + _cogl_current_matrix_load (&ortho); + + /* Calculate and store the inverse of the matrix */ + memset (ctx->inverse_projection, 0, sizeof (float) * 16); + +#define M(row,col) ctx->inverse_projection[col*4+row] + M(0,0) = 1.0 / ortho.xx; + M(0,3) = -ortho.xw; + M(1,1) = 1.0 / ortho.yy; + M(1,3) = -ortho.yw; + M(2,2) = 1.0 / ortho.zz; + M(2,3) = -ortho.zw; + M(3,3) = 1.0; +#undef M +} + +void +cogl_get_modelview_matrix (CoglMatrix *matrix) +{ + _cogl_get_matrix (COGL_MATRIX_MODELVIEW, + matrix); +} + +void +cogl_set_modelview_matrix (CoglMatrix *matrix) +{ + _cogl_set_current_matrix (COGL_MATRIX_MODELVIEW); + _cogl_current_matrix_load (matrix); +} + +void +cogl_get_projection_matrix (CoglMatrix *matrix) +{ + _cogl_get_matrix (COGL_MATRIX_PROJECTION, + matrix); +} + +void +cogl_set_projection_matrix (CoglMatrix *matrix) +{ + _cogl_set_current_matrix (COGL_MATRIX_PROJECTION); + _cogl_current_matrix_load (matrix); +} + diff --git a/common/cogl-matrix-stack.c b/common/cogl-matrix-stack.c index a72af000d..6ba909840 100644 --- a/common/cogl-matrix-stack.c +++ b/common/cogl-matrix-stack.c @@ -257,6 +257,59 @@ _cogl_matrix_stack_multiply (CoglMatrixStack *stack, stack->flushed_state = NULL; } +void +_cogl_matrix_stack_frustum (CoglMatrixStack *stack, + float left, + float right, + float bottom, + float top, + float z_near, + float z_far) +{ + CoglMatrixState *state; + + state = _cogl_matrix_stack_top_mutable (stack); + cogl_matrix_frustum (&state->matrix, + left, right, bottom, top, + z_near, z_far); + /* mark dirty */ + stack->flushed_state = NULL; +} + +void +_cogl_matrix_stack_perspective (CoglMatrixStack *stack, + float fov_y, + float aspect, + float z_near, + float z_far) +{ + CoglMatrixState *state; + + state = _cogl_matrix_stack_top_mutable (stack); + cogl_matrix_perspective (&state->matrix, + fov_y, aspect, z_near, z_far); + /* mark dirty */ + stack->flushed_state = NULL; +} + +void +_cogl_matrix_stack_ortho (CoglMatrixStack *stack, + float left, + float right, + float bottom, + float top, + float z_near, + float z_far) +{ + CoglMatrixState *state; + + state = _cogl_matrix_stack_top_mutable (stack); + cogl_matrix_ortho (&state->matrix, + left, right, bottom, top, z_near, z_far); + /* mark dirty */ + stack->flushed_state = NULL; +} + void _cogl_matrix_stack_get (CoglMatrixStack *stack, CoglMatrix *matrix) @@ -280,25 +333,6 @@ _cogl_matrix_stack_set (CoglMatrixStack *stack, stack->flushed_state = NULL; } -void -_cogl_matrix_stack_frustum (CoglMatrixStack *stack, - float left, - float right, - float bottom, - float top, - float z_near, - float z_far) -{ - CoglMatrixState *state; - - state = _cogl_matrix_stack_top_mutable (stack); - cogl_matrix_frustum (&state->matrix, - left, right, bottom, top, - z_near, z_far); - /* mark dirty */ - stack->flushed_state = NULL; -} - void _cogl_matrix_stack_flush_to_gl (CoglMatrixStack *stack, GLenum gl_mode) diff --git a/common/cogl-matrix-stack.h b/common/cogl-matrix-stack.h index 00db51685..a766f4bbc 100644 --- a/common/cogl-matrix-stack.h +++ b/common/cogl-matrix-stack.h @@ -51,10 +51,6 @@ void _cogl_matrix_stack_rotate (CoglMatrixStack *stack, float z); void _cogl_matrix_stack_multiply (CoglMatrixStack *stack, const CoglMatrix *matrix); -void _cogl_matrix_stack_get (CoglMatrixStack *stack, - CoglMatrix *matrix); -void _cogl_matrix_stack_set (CoglMatrixStack *stack, - const CoglMatrix *matrix); void _cogl_matrix_stack_frustum (CoglMatrixStack *stack, float left, float right, @@ -62,6 +58,22 @@ void _cogl_matrix_stack_frustum (CoglMatrixStack *stack, float top, float z_near, float z_far); +void _cogl_matrix_stack_perspective (CoglMatrixStack *stack, + float fov_y, + float aspect, + float z_near, + float z_far); +void _cogl_matrix_stack_ortho (CoglMatrixStack *stack, + float left, + float right, + float bottom, + float top, + float z_near, + float z_far); +void _cogl_matrix_stack_get (CoglMatrixStack *stack, + CoglMatrix *matrix); +void _cogl_matrix_stack_set (CoglMatrixStack *stack, + const CoglMatrix *matrix); void _cogl_matrix_stack_flush_to_gl (CoglMatrixStack *stack, GLenum gl_mode); diff --git a/common/cogl-matrix.c b/common/cogl-matrix.c index 6b6f20fae..45f367d73 100644 --- a/common/cogl-matrix.c +++ b/common/cogl-matrix.c @@ -151,21 +151,6 @@ cogl_matrix_invert (CoglMatrix *matrix) } #endif -void -cogl_matrix_transform_point (const CoglMatrix *matrix, - float *x, - float *y, - float *z, - float *w) -{ - float _x = *x, _y = *y, _z = *z, _w = *w; - - *x = matrix->xx * _x + matrix->xy * _y + matrix->xz * _z + matrix->xw * _w; - *y = matrix->yx * _x + matrix->yy * _y + matrix->yz * _z + matrix->yw * _w; - *z = matrix->zx * _x + matrix->zy * _y + matrix->zz * _z + matrix->zw * _w; - *w = matrix->wx * _x + matrix->wy * _y + matrix->wz * _z + matrix->ww * _w; -} - void cogl_matrix_frustum (CoglMatrix *matrix, float left, @@ -208,6 +193,62 @@ cogl_matrix_frustum (CoglMatrix *matrix, cogl_matrix_multiply (matrix, matrix, &frustum); } +void +cogl_matrix_perspective (CoglMatrix *matrix, + float fov_y, + float aspect, + float z_near, + float z_far) +{ + float ymax = z_near * tan (fov_y * G_PI / 360.0); + + cogl_matrix_frustum (matrix, + -ymax * aspect, /* left */ + ymax * aspect, /* right */ + -ymax, /* bottom */ + ymax, /* top */ + z_near, + z_far); +} + +void +cogl_matrix_ortho (CoglMatrix *matrix, + float left, + float right, + float bottom, + float top, + float near, + float far) +{ + CoglMatrix ortho; + + /* column 0 */ + ortho.xx = 2.0 / (right - left); + ortho.yx = 0.0; + ortho.zx = 0.0; + ortho.wx = 0.0; + + /* column 1 */ + ortho.xy = 0.0; + ortho.yy = 2.0 / (top - bottom); + ortho.zy = 0.0; + ortho.wy = 0.0; + + /* column 2 */ + ortho.xz = 0.0; + ortho.yz = 0.0; + ortho.zz = -2.0 / (far - near); + ortho.wz = 0.0; + + /* column 3 */ + ortho.xw = -(right + left) / (right - left); + ortho.yw = -(top + bottom) / (top - bottom); + ortho.zw = -(far + near) / (far - near); + ortho.ww = 1.0; + + cogl_matrix_multiply (matrix, matrix, &ortho); +} + void cogl_matrix_init_from_array (CoglMatrix *matrix, const float *array) { @@ -220,3 +261,19 @@ cogl_matrix_get_array (const CoglMatrix *matrix) return (float *)matrix; } +void +cogl_matrix_transform_point (const CoglMatrix *matrix, + float *x, + float *y, + float *z, + float *w) +{ + float _x = *x, _y = *y, _z = *z, _w = *w; + + *x = matrix->xx * _x + matrix->xy * _y + matrix->xz * _z + matrix->xw * _w; + *y = matrix->yx * _x + matrix->yy * _y + matrix->yz * _z + matrix->yw * _w; + *z = matrix->zx * _x + matrix->zy * _y + matrix->zz * _z + matrix->zw * _w; + *w = matrix->wx * _x + matrix->wy * _y + matrix->wz * _z + matrix->ww * _w; +} + + diff --git a/doc/reference/cogl/cogl-sections.txt b/doc/reference/cogl/cogl-sections.txt index 6ee2d9517..5855a90b1 100644 --- a/doc/reference/cogl/cogl-sections.txt +++ b/doc/reference/cogl/cogl-sections.txt @@ -21,19 +21,22 @@ cogl_features_available cogl_check_extension cogl_get_proc_address -cogl_perspective -cogl_frustum -cogl_setup_viewport -cogl_viewport -cogl_get_modelview_matrix -cogl_get_projection_matrix -cogl_get_viewport - cogl_push_matrix cogl_pop_matrix cogl_scale cogl_translate cogl_rotate +cogl_frustum +cogl_perspective +cogl_ortho + +cogl_get_modelview_matrix +cogl_set_modelview_matrix +cogl_get_projection_matrix +cogl_set_projection_matrix +cogl_viewport +cogl_setup_viewport +cogl_get_viewport cogl_clear cogl_get_bitmasks From 2f0bda49fc4ba19fc2d853f79f48a8bb2e095bac Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Tue, 26 May 2009 16:55:11 +0100 Subject: [PATCH 13/37] [cogl] renamed cogl_enable_* to cogl_set_*_enabled + added getters cogl_enable_depth_test and cogl_enable_backface_culling have been renamed and now have corresponding getters, the new functions are: cogl_set_depth_test_enabled cogl_get_depth_test_enabled cogl_set_backface_culling_enabled cogl_get_backface_culling_enabled --- cogl-deprecated.h | 1 + cogl.h.in | 27 +++++++++++++++++++++++---- common/cogl.c | 25 +++++++++++++++++-------- doc/reference/cogl/cogl-sections.txt | 6 ++++-- 4 files changed, 45 insertions(+), 14 deletions(-) diff --git a/cogl-deprecated.h b/cogl-deprecated.h index 2111e48b4..41e77b3d6 100644 --- a/cogl-deprecated.h +++ b/cogl-deprecated.h @@ -24,5 +24,6 @@ #ifndef COGL_DEPRECATED_H #define cogl_color cogl_color_REPLACED_BY_cogl_set_source_color +#define cogl_enable_depth_test cogl_enable_depth_test_RENAMED_TO_cogl_set_depth_test_enabled #endif diff --git a/cogl.h.in b/cogl.h.in index e66cbc394..188af09cd 100644 --- a/cogl.h.in +++ b/cogl.h.in @@ -331,7 +331,7 @@ void cogl_set_projection_matrix (CoglMatrix *matrix); void cogl_get_viewport (float v[4]); /** - * cogl_enable_depth_test: + * cogl_set_depth_test_enable: * @setting: %TRUE to enable depth testing or %FALSE to disable. * * Sets whether depth testing is enabled. If it is disabled then the @@ -340,10 +340,19 @@ void cogl_get_viewport (float v[4]); * clutter_actor_lower(), otherwise it will also take into account the * actor's depth. Depth testing is disabled by default. */ -void cogl_enable_depth_test (gboolean setting); +void cogl_set_depth_test_enable (gboolean setting); /** - * cogl_enable_backface_culling: + * cogl_get_depth_test_enable: + * + * Queries if depth testing has been enabled via cogl_set_depth_test_enable() + * + * Returns: TRUE if depth testing is enabled else FALSE + */ +gboolean cogl_get_depth_test_enable (void); + +/** + * cogl_set_backface_culling_enabled: * @setting: %TRUE to enable backface culling or %FALSE to disable. * * Sets whether textures positioned so that their backface is showing @@ -352,7 +361,17 @@ void cogl_enable_depth_test (gboolean setting); * only affects calls to the cogl_rectangle* family of functions and * cogl_vertex_buffer_draw*. Backface culling is disabled by default. */ -void cogl_enable_backface_culling (gboolean setting); +void cogl_set_backface_culling_enabled (gboolean setting); + +/** + * cogl_get_backface_culling_enabled: + * + * Queries if backface culling has been enabled via + * cogl_set_backface_culling_enabled() + * + * Returns: TRUE if backface culling is enabled else FALSE + */ +gboolean cogl_get_backface_culling_enabled (void); /** * cogl_set_fog: diff --git a/common/cogl.c b/common/cogl.c index 81c43bd5e..adeb479d2 100644 --- a/common/cogl.c +++ b/common/cogl.c @@ -214,30 +214,39 @@ cogl_get_enable () } void -cogl_enable_depth_test (gboolean setting) +cogl_set_depth_test_enabled (gboolean setting) { if (setting) { glEnable (GL_DEPTH_TEST); - glEnable (GL_ALPHA_TEST); glDepthFunc (GL_LEQUAL); - glAlphaFunc (GL_GREATER, 0.1); } else - { - glDisable (GL_DEPTH_TEST); - glDisable (GL_ALPHA_TEST); - } + glDisable (GL_DEPTH_TEST); +} + +gboolean +cogl_get_depth_test_enabled (void) +{ + return glIsEnabled (GL_DEPTH_TEST) == GL_TRUE ? TRUE : FALSE; } void -cogl_enable_backface_culling (gboolean setting) +cogl_set_backface_culling_enabled (gboolean setting) { _COGL_GET_CONTEXT (ctx, NO_RETVAL); ctx->enable_backface_culling = setting; } +gboolean +cogl_get_backface_culling_enabled (void) +{ + _COGL_GET_CONTEXT (ctx, FALSE); + + return ctx->enable_backface_culling; +} + void cogl_set_source_color (const CoglColor *color) { diff --git a/doc/reference/cogl/cogl-sections.txt b/doc/reference/cogl/cogl-sections.txt index 5855a90b1..c34585ff1 100644 --- a/doc/reference/cogl/cogl-sections.txt +++ b/doc/reference/cogl/cogl-sections.txt @@ -40,8 +40,10 @@ cogl_get_viewport cogl_clear cogl_get_bitmasks -cogl_enable_depth_test -cogl_enable_backface_culling +cogl_set_depth_test_enabled +cogl_get_depth_test_enabled +cogl_set_backface_culling_enabled +cogl_get_backface_culling_enabled CoglFogMode cogl_set_fog From 4b105deb3581ebfa8acbc7992f24477d382ad993 Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Tue, 26 May 2009 18:25:00 +0100 Subject: [PATCH 14/37] [deprecated defines] Adds some missing cogl_texture_* deprecated defines To assist people porting code from 0.8, the cogl_texture_* functions that have been replaced now have defines that give some hint as to how they should be replaced. --- cogl-deprecated.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cogl-deprecated.h b/cogl-deprecated.h index 41e77b3d6..3ccac603d 100644 --- a/cogl-deprecated.h +++ b/cogl-deprecated.h @@ -26,4 +26,12 @@ #define cogl_color cogl_color_REPLACED_BY_cogl_set_source_color #define cogl_enable_depth_test cogl_enable_depth_test_RENAMED_TO_cogl_set_depth_test_enabled +#define cogl_texture_rectangle \ + cogl_texture_rectangle_REPLACE_BY_cogl_set_source_texture_plus_cogl_rectangle_with_texture_coords + +#define cogl_texture_multiple_rectangles \ + cogl_texture_multiple_rectangles_REPLACED_BY_cogl_set_source_texture_plus_cogl_rectangles_with_texture_coords + +#define cogl_texture_polygon cogl_texture_polygon_REPLACED_BY_cogl_set_source_texture_plus_cogl_polygon + #endif From 43623a6c44a9c4778cd72fefde3e76d24762cbdb Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Thu, 28 May 2009 02:03:16 +0100 Subject: [PATCH 15/37] [cogl journal] If we are only flushing one quad use a TRIANGLE_FAN At the moment Cogl doesn't do much batching of quads so most of the time we are flushing a single quad at a time. This patch simplifies how we submit those quads to OpenGL by using glDrawArrays with GL_TRIANGLE_FAN mode instead of sending indexed vertices using GL_TRIANGLES mode. Note: I hope to follow up soon with changes that improve our batching and also move the indices into a VBO so they don't need to be re-validated every time we call glDrawElements. --- common/cogl-primitives.c | 80 +++++++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 34 deletions(-) diff --git a/common/cogl-primitives.c b/common/cogl-primitives.c index 42e4d41cb..ff5401d50 100644 --- a/common/cogl-primitives.c +++ b/common/cogl-primitives.c @@ -72,35 +72,6 @@ _cogl_journal_flush_quad_batch (CoglJournalEntry *batch_start, _COGL_GET_CONTEXT (ctx, NO_RETVAL); - /* The indices are always the same sequence regardless of the vertices so we - * only need to change it if there are more vertices than ever before. */ - needed_indices = batch_len * 6; - if (needed_indices > ctx->static_indices->len) - { - int old_len = ctx->static_indices->len; - int vert_num = old_len / 6 * 4; - GLushort *q; - - /* Add two triangles for each quad to the list of - indices. That makes six new indices but two of the - vertices in the triangles are shared. */ - g_array_set_size (ctx->static_indices, needed_indices); - q = &g_array_index (ctx->static_indices, GLushort, old_len); - - for (i = old_len; - i < ctx->static_indices->len; - i += 6, vert_num += 4) - { - *(q++) = vert_num + 0; - *(q++) = vert_num + 1; - *(q++) = vert_num + 3; - - *(q++) = vert_num + 1; - *(q++) = vert_num + 2; - *(q++) = vert_num + 3; - } - } - /* XXX NB: * Our vertex data is arranged as follows: * 4 vertices per quad: 2 GLfloats per position, @@ -150,11 +121,52 @@ _cogl_journal_flush_quad_batch (CoglJournalEntry *batch_start, GE (glVertexPointer (2, GL_FLOAT, stride, vertex_pointer)); _cogl_current_matrix_state_flush (); - GE (glDrawRangeElements (GL_TRIANGLES, - 0, ctx->static_indices->len - 1, - 6 * batch_len, - GL_UNSIGNED_SHORT, - ctx->static_indices->data)); + + + if (batch_len > 1) + { + /* The indices are always the same sequence regardless of the vertices so + * we only need to change it if there are more vertices than ever before. + */ + needed_indices = batch_len * 6; + if (needed_indices > ctx->static_indices->len) + { + int old_len = ctx->static_indices->len; + int vert_num = old_len / 6 * 4; + GLushort *q; + + /* Add two triangles for each quad to the list of + indices. That makes six new indices but two of the + vertices in the triangles are shared. */ + g_array_set_size (ctx->static_indices, needed_indices); + q = &g_array_index (ctx->static_indices, GLushort, old_len); + + for (i = old_len; + i < ctx->static_indices->len; + i += 6, vert_num += 4) + { + *(q++) = vert_num + 0; + *(q++) = vert_num + 1; + *(q++) = vert_num + 3; + + *(q++) = vert_num + 1; + *(q++) = vert_num + 2; + *(q++) = vert_num + 3; + } + } + + GE (glDrawRangeElements (GL_TRIANGLES, + 0, ctx->static_indices->len - 1, + 6 * batch_len, + GL_UNSIGNED_SHORT, + ctx->static_indices->data)); + } + else + { + GE (glDrawArrays (GL_TRIANGLE_FAN, + 0, /* first */ + 4)); /* n vertices */ + } /* DEBUGGING CODE XXX: From 2367e7d27140df826829177b236534ee1a01be15 Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Thu, 28 May 2009 12:49:29 +0100 Subject: [PATCH 16/37] [cogl vertex buffers] Give indices a CoglHandle so they are shareable Previously indices were tightly bound to a particular Cogl vertex buffer but we would like to be able to share indices so now we have cogl_vertex_buffer_indices_new () which returns a CoglHandle. In particular we could like to have a shared set of indices for drawing lists of quads that can be shared between the pango renderer and the Cogl journal. --- cogl-vertex-buffer.h | 34 ++++------ common/cogl-vertex-buffer-private.h | 7 +-- common/cogl-vertex-buffer.c | 97 +++++++---------------------- 3 files changed, 38 insertions(+), 100 deletions(-) diff --git a/cogl-vertex-buffer.h b/cogl-vertex-buffer.h index 1887db566..ba2cef8b2 100644 --- a/cogl-vertex-buffer.h +++ b/cogl-vertex-buffer.h @@ -303,10 +303,7 @@ typedef enum _CoglIndicesType } CoglIndicesType; /** - * cogl_vertex_buffer_add_indices: - * @handle: A vertex buffer handle - * @min_index: Specifies the minimum vertex index contained in indices - * @max_index: Specifies the maximum vertex index contained in indices + * cogl_vertex_buffer_indices_new: * @indices_type: a #CoglIndicesType specifying the data type used for * the indices. * @indices_array: Specifies the address of your array of indices @@ -317,19 +314,11 @@ typedef enum _CoglIndicesType * array allows you to reference vertices multiple times, for example * during triangle strips. * - * You should aim to use the smallest data type possible and correctly reflect - * the range of index values in the {min,max}_index arguments. This allows Cogl - * to optimize the internal storage used for the indices and reduce the demand - * for memory bandwidth. - * - * Returns: An identifier (greater than 0) for the indices which you can - * pass to cogl_vertex_buffer_draw_elements(). + * Returns: A CoglHandle for the indices which you can pass to + * cogl_vertex_buffer_draw_elements(). */ -int -cogl_vertex_buffer_add_indices (CoglHandle handle, - int min_index, - int max_index, - CoglIndicesType indices_type, +CoglHandle +cogl_vertex_buffer_indices_new (CoglIndicesType indices_type, const void *indices_array, int indices_len); @@ -352,16 +341,17 @@ cogl_vertex_buffer_delete_indices (CoglHandle handle, * @handle: A vertex buffer handle * @mode: A #CoglVerticesMode specifying how the vertices should be * interpreted. - * @indices_id: The identifier for a an array of indices previously added to - * the given Cogl vertex buffer using - * cogl_vertex_buffer_add_indices(). + * @indices: A CoglHandle for a set of indices allocated via + * cogl_vertex_buffer_indices_new () + * @min_index: Specifies the minimum vertex index contained in indices + * @max_index: Specifies the maximum vertex index contained in indices * @indices_offset: An offset into named indices. The offset marks the first * index to use for drawing. * @count: Specifies the number of vertices you want to draw. * * This function lets you use an array of indices to specify the vertices * within your vertex buffer that you want to draw. The indices themselves - * are given by calling cogl_vertex_buffer_add_indices () + * are created by calling cogl_vertex_buffer_indices_new () * * Any un-submitted attribute changes are automatically submitted before * drawing. @@ -369,7 +359,9 @@ cogl_vertex_buffer_delete_indices (CoglHandle handle, void cogl_vertex_buffer_draw_elements (CoglHandle handle, CoglVerticesMode mode, - int indices_id, + CoglHandle indices, + int min_index, + int max_index, int indices_offset, int count); diff --git a/common/cogl-vertex-buffer-private.h b/common/cogl-vertex-buffer-private.h index cc87b1828..17f8725e4 100644 --- a/common/cogl-vertex-buffer-private.h +++ b/common/cogl-vertex-buffer-private.h @@ -139,14 +139,13 @@ typedef struct _CoglVertexBufferVBO typedef struct _CoglVertexBufferIndices { - int id; + CoglHandleObject _parent; + /* Note: this is a pointer to handle fallbacks. It normally holds * a GLuint VBO name, but when the driver doesn't support VBOs then * this simply points to an malloc'd buffer. */ void *vbo_name; GLenum type; - GLuint min_index; - GLuint max_index; } CoglVertexBufferIndices; typedef struct _CoglVertexBuffer @@ -160,8 +159,6 @@ typedef struct _CoglVertexBuffer * modifying a buffer. */ GList *new_attributes; /*!< attributes pending submission */ - GList *indices; /*!< A list of associated index arrays */ - } CoglVertexBuffer; #endif /* __COGL_VERTEX_BUFFER_H */ diff --git a/common/cogl-vertex-buffer.c b/common/cogl-vertex-buffer.c index 096a4a47c..b3c36f0ec 100644 --- a/common/cogl-vertex-buffer.c +++ b/common/cogl-vertex-buffer.c @@ -201,8 +201,10 @@ #endif /* HAVE_COGL_GL */ static void _cogl_vertex_buffer_free (CoglVertexBuffer *buffer); +static void _cogl_vertex_buffer_indices_free (CoglVertexBufferIndices *buffer_indices); COGL_HANDLE_DEFINE (VertexBuffer, vertex_buffer); +COGL_HANDLE_DEFINE (VertexBufferIndices, vertex_buffer_indices); CoglHandle cogl_vertex_buffer_new (guint n_vertices) @@ -214,8 +216,6 @@ cogl_vertex_buffer_new (guint n_vertices) buffer->submitted_vbos = NULL; buffer->new_attributes = NULL; - buffer->indices = NULL; - /* return COGL_INVALID_HANDLE; */ return _cogl_vertex_buffer_handle_new (buffer); } @@ -1741,22 +1741,6 @@ cogl_vertex_buffer_draw (CoglHandle handle, disable_state_for_drawing_buffer (buffer); } -static void -free_vertex_buffer_indices (CoglVertexBufferIndices *indices) -{ - gboolean fallback = - (cogl_get_features () & COGL_FEATURE_VBOS) ? FALSE : TRUE; - - _COGL_GET_CONTEXT (ctx, NO_RETVAL); - - if (fallback) - g_free (indices->vbo_name); - else - GE (glDeleteBuffers (1, (GLuint *)&indices->vbo_name)); - - g_slice_free (CoglVertexBufferIndices, indices); -} - static int get_indices_type_size (GLuint indices_type) { @@ -1771,34 +1755,19 @@ get_indices_type_size (GLuint indices_type) } } -int -cogl_vertex_buffer_add_indices (CoglHandle handle, - int min_index, - int max_index, - CoglIndicesType indices_type, +CoglHandle +cogl_vertex_buffer_indices_new (CoglIndicesType indices_type, const void *indices_array, int indices_len) { - CoglVertexBuffer *buffer; gboolean fallback = (cogl_get_features () & COGL_FEATURE_VBOS) ? FALSE : TRUE; size_t indices_bytes; CoglVertexBufferIndices *indices; - static int next_indices_id = 1; - - _COGL_GET_CONTEXT (ctx, 0); - if (!cogl_is_vertex_buffer (handle)) - return 0; - - buffer = _cogl_vertex_buffer_pointer_from_handle (handle); - indices = g_slice_alloc (sizeof (CoglVertexBufferIndices)); - indices->id = next_indices_id; - indices->min_index = min_index; - indices->max_index = max_index; if (indices_type == COGL_INDICES_TYPE_UNSIGNED_BYTE) indices->type = GL_UNSIGNED_BYTE; @@ -1829,39 +1798,31 @@ cogl_vertex_buffer_add_indices (CoglHandle handle, GE (glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0)); } - buffer->indices = g_list_prepend (buffer->indices, indices); - - return next_indices_id++; + return _cogl_vertex_buffer_indices_handle_new (indices); } void -cogl_vertex_buffer_delete_indices (CoglHandle handle, - int indices_id) +_cogl_vertex_buffer_indices_free (CoglVertexBufferIndices *indices) { - CoglVertexBuffer *buffer; - GList *l; + gboolean fallback = + (cogl_get_features () & COGL_FEATURE_VBOS) ? FALSE : TRUE; - if (!cogl_is_vertex_buffer (handle)) - return; + _COGL_GET_CONTEXT (ctx, NO_RETVAL); - buffer = _cogl_vertex_buffer_pointer_from_handle (handle); + if (fallback) + g_free (indices->vbo_name); + else + GE (glDeleteBuffers (1, (GLuint *)&indices->vbo_name)); - for (l = buffer->indices; l; l = l->next) - { - CoglVertexBufferIndices *current_indices = l->data; - if (current_indices->id == indices_id) - { - free_vertex_buffer_indices (l->data); - buffer->indices = g_list_delete_link (buffer->indices, l); - return; - } - } + g_slice_free (CoglVertexBufferIndices, indices); } void cogl_vertex_buffer_draw_elements (CoglHandle handle, CoglVerticesMode mode, - int indices_id, + CoglHandle indices_handle, + int min_index, + int max_index, int indices_offset, int count) { @@ -1869,7 +1830,6 @@ cogl_vertex_buffer_draw_elements (CoglHandle handle, gboolean fallback = (cogl_get_features () & COGL_FEATURE_VBOS) ? FALSE : TRUE; size_t byte_offset; - GList *l; CoglVertexBufferIndices *indices = NULL; _COGL_GET_CONTEXT (ctx, NO_RETVAL); @@ -1879,22 +1839,15 @@ cogl_vertex_buffer_draw_elements (CoglHandle handle, buffer = _cogl_vertex_buffer_pointer_from_handle (handle); + if (!cogl_is_vertex_buffer_indices (indices_handle)) + return; + + indices = _cogl_vertex_buffer_indices_pointer_from_handle (indices_handle); + cogl_clip_ensure (); _cogl_current_matrix_state_flush (); enable_state_for_drawing_buffer (buffer); - for (l = buffer->indices; l; l = l->next) - { - CoglVertexBufferIndices *current_indices = l->data; - if (current_indices->id == indices_id) - { - indices = current_indices; - break; - } - } - if (!indices) - return; - byte_offset = indices_offset * get_indices_type_size (indices->type); if (fallback) byte_offset = (size_t)(((char *)indices->vbo_name) + byte_offset); @@ -1903,7 +1856,7 @@ cogl_vertex_buffer_draw_elements (CoglHandle handle, GPOINTER_TO_UINT (indices->vbo_name))); /* FIXME: flush cogl cache */ - GE (glDrawRangeElements (mode, indices->min_index, indices->max_index, + GE (glDrawRangeElements (mode, min_index, max_index, count, indices->type, (void *)byte_offset)); disable_state_for_drawing_buffer (buffer); @@ -1924,10 +1877,6 @@ _cogl_vertex_buffer_free (CoglVertexBuffer *buffer) cogl_vertex_buffer_attribute_free (tmp->data); g_list_free (buffer->new_attributes); - for (tmp = buffer->indices; tmp != NULL; tmp = tmp->next) - free_vertex_buffer_indices (tmp->data); - g_list_free (buffer->indices); - g_slice_free (CoglVertexBuffer, buffer); } From b9e1c8258779b3327ddcbab2db8ebc60b232ecc2 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Thu, 28 May 2009 12:52:00 +0100 Subject: [PATCH 17/37] [cogl deprecated] Add backface culling deprecation The backface culling enabling function was split and renamed, just like the depth testing one, so we need to add the macro to the cogl-deprecated.h header. --- cogl-deprecated.h | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/cogl-deprecated.h b/cogl-deprecated.h index 3ccac603d..24dc5b28b 100644 --- a/cogl-deprecated.h +++ b/cogl-deprecated.h @@ -23,15 +23,14 @@ #ifndef COGL_DEPRECATED_H -#define cogl_color cogl_color_REPLACED_BY_cogl_set_source_color -#define cogl_enable_depth_test cogl_enable_depth_test_RENAMED_TO_cogl_set_depth_test_enabled +#define cogl_color cogl_color_REPLACED_BY_cogl_set_source_color +#define cogl_enable_depth_test cogl_enable_depth_test_RENAMED_TO_cogl_set_depth_test_enabled +#define cogl_enable_backface_culling cogl_enable_backface_culling_RENAMED_TO_cogl_set_backface_culling_enabled -#define cogl_texture_rectangle \ - cogl_texture_rectangle_REPLACE_BY_cogl_set_source_texture_plus_cogl_rectangle_with_texture_coords +#define cogl_texture_rectangle cogl_texture_rectangle_REPLACE_BY_cogl_set_source_texture_AND_cogl_rectangle_with_texture_coords -#define cogl_texture_multiple_rectangles \ - cogl_texture_multiple_rectangles_REPLACED_BY_cogl_set_source_texture_plus_cogl_rectangles_with_texture_coords +#define cogl_texture_multiple_rectangles cogl_texture_multiple_rectangles_REPLACED_BY_cogl_set_source_texture_AND_cogl_rectangles_with_texture_coords -#define cogl_texture_polygon cogl_texture_polygon_REPLACED_BY_cogl_set_source_texture_plus_cogl_polygon +#define cogl_texture_polygon cogl_texture_polygon_REPLACED_BY_cogl_set_source_texture_AND_cogl_polygon #endif From 5ed1b03a91f2a43f8f39bb7eb89608f7cf17c22c Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Thu, 28 May 2009 13:03:19 +0100 Subject: [PATCH 18/37] [cogl] Make cogl_setup_viewport() a private function The setup_viewport() function should only be used by Clutter and not by application code. It can be emulated by changing the Stage size and perspective and requeueing a redraw after calling clutter_stage_ensure_viewport(). --- cogl.h.in | 10 ++++++---- common/cogl.c | 16 ++++++++-------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/cogl.h.in b/cogl.h.in index 188af09cd..a671aa00d 100644 --- a/cogl.h.in +++ b/cogl.h.in @@ -193,8 +193,8 @@ void cogl_ortho (float left, float near, float far); -/** - * cogl_setup_viewport: +/* + * _cogl_setup_viewport: * @width: Width of the viewport * @height: Height of the viewport * @fovy: Field of view angle in degrees @@ -208,9 +208,11 @@ void cogl_ortho (float left, * with one that has a viewing angle of @fovy along the y-axis and a * view scaled according to @aspect along the x-axis. The view is * clipped according to @z_near and @z_far on the z-axis. + * + * This function is used only by Clutter. */ -void cogl_setup_viewport (guint width, - guint height, +void _cogl_setup_viewport (guint width, + guint height, float fovy, float aspect, float z_near, diff --git a/common/cogl.c b/common/cogl.c index adeb479d2..336303917 100644 --- a/common/cogl.c +++ b/common/cogl.c @@ -475,12 +475,12 @@ cogl_viewport (guint width, } void -cogl_setup_viewport (guint width, - guint height, - float fovy, - float aspect, - float z_near, - float z_far) +_cogl_setup_viewport (guint width, + guint height, + float fovy, + float aspect, + float z_near, + float z_far) { float z_camera; CoglMatrix projection_matrix; @@ -488,7 +488,7 @@ cogl_setup_viewport (guint width, GE( glViewport (0, 0, width, height) ); /* For Ortho projection. - * _cogl_current_matrix_ortho (0, width << 16, 0, height << 16, -1 << 16, 1 << 16); + * _cogl_current_matrix_ortho (0, width, 0, height, -1, 1); */ cogl_perspective (fovy, aspect, z_near, z_far); @@ -542,7 +542,7 @@ cogl_setup_viewport (guint width, } CoglFeatureFlags -cogl_get_features () +cogl_get_features (void) { _COGL_GET_CONTEXT (ctx, 0); From ae9b871b38dd1c581c4ed7e1629d06697d7b25b1 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Thu, 28 May 2009 17:18:13 +0100 Subject: [PATCH 19/37] [docs] Fixes for the API reference * Add unused symbols * Document and sync argument names with their gtk-doc counterpart * Add missing descriptions --- cogl-material.h | 5 +++++ cogl-shader.h | 14 +++++++++--- cogl-vertex-buffer.h | 33 ++++++++++++++++++---------- cogl.h.in | 4 ++++ doc/reference/cogl/cogl-sections.txt | 6 ----- 5 files changed, 41 insertions(+), 21 deletions(-) diff --git a/cogl-material.h b/cogl-material.h index da822564e..504c173fa 100644 --- a/cogl-material.h +++ b/cogl-material.h @@ -616,6 +616,11 @@ const GList *cogl_material_get_layers (CoglHandle material_handle); * CoglMaterialLayerType: * @COGL_MATERIAL_LAYER_TYPE_TEXTURE: The layer represents a * Cogl texture + * + * Available types of layers for a #CoglMaterial. This enumeration + * might be expanded in later versions. + * + * Since: 1.0 */ typedef enum _CoglMaterialLayerType { diff --git a/cogl-shader.h b/cogl-shader.h index 59c75ede6..f5280722f 100644 --- a/cogl-shader.h +++ b/cogl-shader.h @@ -46,6 +46,10 @@ G_BEGIN_DECLS * CoglShaderType: * @COGL_SHADER_TYPE_VERTEX: A program for proccessing vertices * @COGL_SHADER_TYPE_FRAGMENT: A program for processing fragments + * + * Types of shaders + * + * Since: 1.0 */ typedef enum _CoglShaderType { @@ -132,8 +136,10 @@ void cogl_shader_get_info_log (CoglHandle handle, * cogl_shader_get_type: * @handle: #CoglHandle for a shader. * - * Returns: COGL_SHADER_TYPE_VERTEX if the shader is a vertex processor - * or COGL_SHADER_TYPE_FRAGMENT if the shader is a frament processor + * Retrieves the type of a shader #CoglHandle + * + * Return value: %COGL_SHADER_TYPE_VERTEX if the shader is a vertex processor + * or %COGL_SHADER_TYPE_FRAGMENT if the shader is a frament processor */ CoglShaderType cogl_shader_get_type (CoglHandle handle); @@ -141,7 +147,9 @@ CoglShaderType cogl_shader_get_type (CoglHandle handle); * cogl_shader_is_compiled: * @handle: #CoglHandle for a shader. * - * Returns: TRUE if the shader object has sucessfully be compiled else FALSE + * Retrieves whether a shader #CoglHandle has been compiled + * + * Return value: %TRUE if the shader object has sucessfully be compiled */ gboolean cogl_shader_is_compiled (CoglHandle handle); diff --git a/cogl-vertex-buffer.h b/cogl-vertex-buffer.h index ba2cef8b2..ab37dbced 100644 --- a/cogl-vertex-buffer.h +++ b/cogl-vertex-buffer.h @@ -96,12 +96,17 @@ cogl_vertex_buffer_get_n_vertices (CoglHandle handle); /** * CoglAttributeType: - * @COGL_ATTRIBUTE_TYPE_BYTE: - * @COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE: - * @COGL_ATTRIBUTE_TYPE_SHORT: - * @COGL_ATTRIBUTE_TYPE_UNSIGNED_SHORT: - * @COGL_ATTRIBUTE_TYPE_FLOAT: + * @COGL_ATTRIBUTE_TYPE_BYTE: Data is the same size of a byte + * @COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE: Data is the same size of an + * unsigned byte + * @COGL_ATTRIBUTE_TYPE_SHORT: Data is the same size of a short integer + * @COGL_ATTRIBUTE_TYPE_UNSIGNED_SHORT: Data is the same size of + * an unsigned short integer + * @COGL_ATTRIBUTE_TYPE_FLOAT: Data is the same size of a float * + * Data types for the components of cogl_vertex_buffer_add() + * + * Since: 1.0 */ typedef enum _CoglAttributeType { @@ -245,14 +250,18 @@ cogl_vertex_buffer_enable (CoglHandle handle, /** * CoglVerticesMode: - * COGL_VERTICES_MODE_POINTS: - * COGL_VERTICES_MODE_LINE_STRIP: - * COGL_VERTICES_MODE_LINE_LOOP: - * COGL_VERTICES_MODE_LINES: - * COGL_VERTICES_MODE_TRIANGLE_STRIP: - * COGL_VERTICES_MODE_TRIANGLE_FAN: - * COGL_VERTICES_MODE_TRIANGLES: + * @COGL_VERTICES_MODE_POINTS: FIXME, equivalent to %GL_POINTS + * @COGL_VERTICES_MODE_LINE_STRIP: FIXME, equivalent to %GL_LINE_STRIP + * @COGL_VERTICES_MODE_LINE_LOOP: FIXME, equivalent to %GL_LINE_LOOP + * @COGL_VERTICES_MODE_LINES: FIXME, equivalent to %GL_LINES + * @COGL_VERTICES_MODE_TRIANGLE_STRIP: FIXME, equivalent to %GL_TRIANGLE_STRIP + * @COGL_VERTICES_MODE_TRIANGLE_FAN: FIXME, equivalent to %GL_TRIANGLE_FAN + * @COGL_VERTICES_MODE_TRIANGLES: FIXME, equivalent to %GL_TRIANGLES * + * How vertices passed to cogl_vertex_buffer_draw() and + * cogl_vertex_buffer_draw_elements() should be interpreted + * + * Since: 1.0 */ typedef enum _CoglVerticesMode { diff --git a/cogl.h.in b/cogl.h.in index a671aa00d..611d358ba 100644 --- a/cogl.h.in +++ b/cogl.h.in @@ -412,6 +412,10 @@ void cogl_disable_fog (void); * @COGL_BUFFER_BIT_COLOR: Selects the primary color buffer * @COGL_BUFFER_BIT_DEPTH: Selects the depth buffer * @COGL_BUFFER_BIT_STENCIL: Selects the stencil buffer + * + * Types of auxiliary buffers + * + * Since: 1.0 */ typedef enum _CoglBufferBit { diff --git a/doc/reference/cogl/cogl-sections.txt b/doc/reference/cogl/cogl-sections.txt index c34585ff1..9d49ea53f 100644 --- a/doc/reference/cogl/cogl-sections.txt +++ b/doc/reference/cogl/cogl-sections.txt @@ -376,15 +376,9 @@ CoglMaterialLayerPrivFlags
cogl-material-internals Material Internals -cogl_material_get_cogl_enable_flags -CoglMaterialFlushOption -cogl_material_flush_gl_state CoglMaterialLayer cogl_material_get_layers CoglMaterialLayerType cogl_material_layer_get_type -CoglMaterialLayerFlags -cogl_material_layer_get_flags cogl_material_layer_get_texture -cogl_material_layer_flush_gl_sampler_state
From 34b5352bb5e8d728e89923a7059da90715214b63 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Fri, 29 May 2009 12:31:47 +0100 Subject: [PATCH 20/37] [cogl] Generate enumeration GTypes COGL is starting to have more enumerations than I can handle by hand. Let's use glib-mkenums and be done with it. --- Makefile.am | 40 ++++++---- cogl-shader.h | 5 +- cogl-types.h | 79 +++--------------- cogl.h.in | 11 +-- common/Makefile.am | 53 ++++++++++++- common/cogl-enum-types.c.in | 33 ++++++++ common/cogl-enum-types.h.in | 25 ++++++ common/cogl-util.c | 154 ------------------------------------ gl/Makefile.am | 5 -- 9 files changed, 156 insertions(+), 249 deletions(-) create mode 100644 common/cogl-enum-types.c.in create mode 100644 common/cogl-enum-types.h.in diff --git a/Makefile.am b/Makefile.am index 225b66100..1490ec68a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,3 +1,9 @@ +NULL = + +V = @ +Q = $(V:1=) +QUIET_GEN = $(Q:@=@echo ' GEN '$@;) + SUBDIRS = common $(CLUTTER_COGL) BUILT_SOURCES = cogl.h @@ -23,19 +29,24 @@ CLEANFILES = $(pc_files) AM_CPPFLAGS = $(CLUTTER_CFLAGS) $(CLUTTER_DEBUG_CFLAGS) $(MAINTAINER_CFLAGS) +# COGL installed headers cogl_headers = \ - $(top_srcdir)/clutter/cogl/cogl-bitmap.h \ - $(top_srcdir)/clutter/cogl/cogl-color.h \ - $(top_srcdir)/clutter/cogl/cogl-debug.h \ - $(top_srcdir)/clutter/cogl/cogl-fixed.h \ - $(top_srcdir)/clutter/cogl/cogl-material.h \ - $(top_srcdir)/clutter/cogl/cogl-matrix.h \ - $(top_srcdir)/clutter/cogl/cogl-offscreen.h \ - $(top_srcdir)/clutter/cogl/cogl-path.h \ - $(top_srcdir)/clutter/cogl/cogl-shader.h \ - $(top_srcdir)/clutter/cogl/cogl-texture.h \ - $(top_srcdir)/clutter/cogl/cogl-types.h \ - $(top_srcdir)/clutter/cogl/cogl-vertex-buffer.h + $(top_srcdir)/clutter/cogl/cogl-bitmap.h \ + $(top_srcdir)/clutter/cogl/cogl-color.h \ + $(top_srcdir)/clutter/cogl/cogl-debug.h \ + $(top_srcdir)/clutter/cogl/cogl-fixed.h \ + $(top_srcdir)/clutter/cogl/cogl-material.h \ + $(top_srcdir)/clutter/cogl/cogl-matrix.h \ + $(top_srcdir)/clutter/cogl/cogl-offscreen.h \ + $(top_srcdir)/clutter/cogl/cogl-path.h \ + $(top_srcdir)/clutter/cogl/cogl-shader.h \ + $(top_srcdir)/clutter/cogl/cogl-texture.h \ + $(top_srcdir)/clutter/cogl/cogl-types.h \ + $(top_srcdir)/clutter/cogl/cogl-vertex-buffer.h \ + $(top_builddir)/clutter/cogl/cogl-defines-@CLUTTER_COGL@.h \ + $(top_builddir)/clutter/cogl/cogl-enum-types.h \ + $(top_builddir)/clutter/cogl/cogl.h \ + $(NULL) # HACK - gobject-introspection can't scan a library in another directory # so we create a libclutter-cogl.la that's just identical to the one @@ -44,6 +55,9 @@ noinst_LTLIBRARIES = libclutter-cogl.la libclutter_cogl_la_LIBADD = $(CLUTTER_COGL)/libclutter-cogl.la libclutter_cogl_la_SOURCES = $(cogl_headers) +coglincludedir = $(includedir)/clutter-@CLUTTER_API_VERSION@/cogl +coglinclude_HEADERS = $(cogl_headers) + if HAVE_INTROSPECTION Cogl-@CLUTTER_API_VERSION@.gir: $(INTROSPECTION_SCANNER) $(CLUTTER_COGL)/libclutter-cogl.la $(QUIET_GEN)$(INTROSPECTION_SCANNER) -v \ @@ -59,8 +73,6 @@ Cogl-@CLUTTER_API_VERSION@.gir: $(INTROSPECTION_SCANNER) $(CLUTTER_COGL)/libclut --libtool="$(top_builddir)/doltlibtool" \ --pkg gobject-2.0 \ --output $@ \ - $(top_builddir)/clutter/cogl/cogl-defines-@CLUTTER_COGL@.h \ - $(top_builddir)/clutter/cogl/cogl.h \ $(cogl_headers) BUILT_GIRSOURCES = Cogl-@CLUTTER_API_VERSION@.gir diff --git a/cogl-shader.h b/cogl-shader.h index f5280722f..d0b0ce13e 100644 --- a/cogl-shader.h +++ b/cogl-shader.h @@ -51,8 +51,7 @@ G_BEGIN_DECLS * * Since: 1.0 */ -typedef enum _CoglShaderType -{ +typedef enum { COGL_SHADER_TYPE_VERTEX, COGL_SHADER_TYPE_FRAGMENT } CoglShaderType; @@ -115,7 +114,7 @@ void cogl_shader_source (CoglHandle shader, * Compiles the shader, no return value, but the shader is now ready for * linking into a program. */ -void cogl_shader_compile (CoglHandle handle); +void cogl_shader_compile (CoglHandle handle); /** * cogl_shader_get_info_log: diff --git a/cogl-types.h b/cogl-types.h index 719ecd087..3aa6f5c3c 100644 --- a/cogl-types.h +++ b/cogl-types.h @@ -123,8 +123,7 @@ typedef struct _CoglTextureVertex CoglTextureVertex; * * Since: 0.8 */ -typedef enum -{ +typedef enum { /*< prefix=COGL_PIXEL_FORMAT >*/ COGL_PIXEL_FORMAT_ANY = 0, COGL_PIXEL_FORMAT_A_8 = 1 | COGL_A_BIT, @@ -135,60 +134,21 @@ typedef enum COGL_PIXEL_FORMAT_G_8 = 8, COGL_PIXEL_FORMAT_RGB_888 = COGL_PIXEL_FORMAT_24, + COGL_PIXEL_FORMAT_BGR_888 = (COGL_PIXEL_FORMAT_24 | COGL_BGR_BIT), - COGL_PIXEL_FORMAT_BGR_888 = (COGL_PIXEL_FORMAT_24 | - COGL_BGR_BIT), - - COGL_PIXEL_FORMAT_RGBA_8888 = COGL_PIXEL_FORMAT_32 | - COGL_A_BIT, - - COGL_PIXEL_FORMAT_BGRA_8888 = (COGL_PIXEL_FORMAT_32 | - COGL_A_BIT | - COGL_BGR_BIT), - - COGL_PIXEL_FORMAT_ARGB_8888 = (COGL_PIXEL_FORMAT_32 | - COGL_A_BIT | - COGL_AFIRST_BIT), - - COGL_PIXEL_FORMAT_ABGR_8888 = (COGL_PIXEL_FORMAT_32 | - COGL_A_BIT | - COGL_BGR_BIT | - COGL_AFIRST_BIT), - - COGL_PIXEL_FORMAT_RGBA_8888_PRE = (COGL_PIXEL_FORMAT_32 | - COGL_A_BIT | - COGL_PREMULT_BIT), - - COGL_PIXEL_FORMAT_BGRA_8888_PRE = (COGL_PIXEL_FORMAT_32 | - COGL_A_BIT | - COGL_PREMULT_BIT | - COGL_BGR_BIT), - - COGL_PIXEL_FORMAT_ARGB_8888_PRE = (COGL_PIXEL_FORMAT_32 | - COGL_A_BIT | - COGL_PREMULT_BIT | - COGL_AFIRST_BIT), - - COGL_PIXEL_FORMAT_ABGR_8888_PRE = (COGL_PIXEL_FORMAT_32 | - COGL_A_BIT | - COGL_PREMULT_BIT | - COGL_BGR_BIT | - COGL_AFIRST_BIT), - - COGL_PIXEL_FORMAT_RGBA_4444_PRE = (COGL_PIXEL_FORMAT_RGBA_4444 | - COGL_A_BIT | - COGL_PREMULT_BIT), - - COGL_PIXEL_FORMAT_RGBA_5551_PRE = (COGL_PIXEL_FORMAT_RGBA_5551 | - COGL_A_BIT | - COGL_PREMULT_BIT), - + COGL_PIXEL_FORMAT_RGBA_8888 = (COGL_PIXEL_FORMAT_32 | COGL_A_BIT), + COGL_PIXEL_FORMAT_BGRA_8888 = (COGL_PIXEL_FORMAT_32 | COGL_A_BIT | COGL_BGR_BIT), + COGL_PIXEL_FORMAT_ARGB_8888 = (COGL_PIXEL_FORMAT_32 | COGL_A_BIT | COGL_AFIRST_BIT), + COGL_PIXEL_FORMAT_ABGR_8888 = (COGL_PIXEL_FORMAT_32 | COGL_A_BIT | COGL_BGR_BIT | COGL_AFIRST_BIT), + COGL_PIXEL_FORMAT_RGBA_8888_PRE = (COGL_PIXEL_FORMAT_32 | COGL_A_BIT | COGL_PREMULT_BIT), + COGL_PIXEL_FORMAT_BGRA_8888_PRE = (COGL_PIXEL_FORMAT_32 | COGL_A_BIT | COGL_PREMULT_BIT | COGL_BGR_BIT), + COGL_PIXEL_FORMAT_ARGB_8888_PRE = (COGL_PIXEL_FORMAT_32 | COGL_A_BIT | COGL_PREMULT_BIT | COGL_AFIRST_BIT), + COGL_PIXEL_FORMAT_ABGR_8888_PRE = (COGL_PIXEL_FORMAT_32 | COGL_A_BIT | COGL_PREMULT_BIT | COGL_BGR_BIT | COGL_AFIRST_BIT), + COGL_PIXEL_FORMAT_RGBA_4444_PRE = (COGL_PIXEL_FORMAT_RGBA_4444 | COGL_A_BIT | COGL_PREMULT_BIT), + COGL_PIXEL_FORMAT_RGBA_5551_PRE = (COGL_PIXEL_FORMAT_RGBA_5551 | COGL_A_BIT | COGL_PREMULT_BIT), } CoglPixelFormat; -#define COGL_TYPE_PIXEL_FORMAT (cogl_pixel_format_get_type ()) -GType cogl_pixel_format_get_type (void) G_GNUC_CONST; - /** * CoglFeatureFlags: * @COGL_FEATURE_TEXTURE_RECTANGLE: ARB_texture_rectangle support @@ -222,9 +182,6 @@ typedef enum COGL_FEATURE_VBOS = (1 << 11) } CoglFeatureFlags; -#define COGL_TYPE_FEATURE_FLAGS (cogl_feature_flags_get_type ()) -GType cogl_feature_flags_get_type (void) G_GNUC_CONST; - /** * CoglBufferTarget: * @COGL_WINDOW_BUFFER: FIXME @@ -240,9 +197,6 @@ typedef enum COGL_OFFSCREEN_BUFFER = (1 << 2) } CoglBufferTarget; -#define COGL_TYPE_BUFFER_TARGET (cogl_buffer_target_get_type ()) -GType cogl_buffer_target_get_type (void) G_GNUC_CONST; - /** * CoglColor: * @@ -304,9 +258,6 @@ typedef enum { COGL_TEXTURE_NO_SLICING = 1 << 1 } CoglTextureFlags; -#define COGL_TYPE_TEXTURE_FLAGS (cogl_texture_flags_get_type ()) -GType cogl_texture_flags_get_type (void) G_GNUC_CONST; - /** * CoglFogMode: * @COGL_FOG_MODE_LINEAR: Calculates the fog blend factor as: @@ -335,16 +286,12 @@ GType cogl_texture_flags_get_type (void) G_GNUC_CONST; * * Since: 1.0 */ -typedef enum _CoglFogMode -{ +typedef enum { COGL_FOG_MODE_LINEAR, COGL_FOG_MODE_EXPONENTIAL, COGL_FOG_MODE_EXPONENTIAL_SQUARED } CoglFogMode; -#define COGL_TYPE_FOG_MODE (cogl_fog_mode_get_type ()) -GType cogl_fog_mode_get_type (void) G_GNUC_CONST; - G_END_DECLS #endif /* __COGL_TYPES_H__ */ diff --git a/cogl.h.in b/cogl.h.in index 611d358ba..a468cf717 100644 --- a/cogl.h.in +++ b/cogl.h.in @@ -45,6 +45,7 @@ #include #include #include +#include G_BEGIN_DECLS @@ -417,8 +418,7 @@ void cogl_disable_fog (void); * * Since: 1.0 */ -typedef enum _CoglBufferBit -{ +typedef enum { COGL_BUFFER_BIT_COLOR = 1L<<0, COGL_BUFFER_BIT_DEPTH = 1L<<1, COGL_BUFFER_BIT_STENCIL = 1L<<2 @@ -427,13 +427,14 @@ typedef enum _CoglBufferBit /** * cogl_clear: * @color: Background color to clear to - * @buffers: A mask of @CoglBufferBit's identifying which auxiliary - * buffers to clear + * @buffers: A mask of #CoglBufferBit's identifying which auxiliary + * buffers to clear * * Clears all the auxiliary buffers identified in the @buffers mask, and if * that includes the color buffer then the specified @color is used. */ -void cogl_clear (const CoglColor *color, gulong buffers); +void cogl_clear (const CoglColor *color, + gulong buffers); /** * cogl_set_source: diff --git a/common/Makefile.am b/common/Makefile.am index c4e6eb2f7..df50a1d16 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -1,3 +1,10 @@ +NULL = + +V = @ +Q = $(V:1=) +QUIET_GEN = $(Q:@=@echo ' GEN '$@;) +QUIET_CP = $(Q:@=@echo ' CP '$@;) + INCLUDES = \ -I$(top_srcdir) \ -I$(top_srcdir)/clutter \ @@ -9,12 +16,49 @@ INCLUDES = \ -DG_LOG_DOMAIN=\"Cogl-Common\" \ -DCLUTTER_COMPILATION +cogl_public_h = \ + $(top_srcdir)/clutter/cogl/cogl-bitmap.h \ + $(top_srcdir)/clutter/cogl/cogl-color.h \ + $(top_srcdir)/clutter/cogl/cogl-debug.h \ + $(top_srcdir)/clutter/cogl/cogl-fixed.h \ + $(top_srcdir)/clutter/cogl/cogl-material.h \ + $(top_srcdir)/clutter/cogl/cogl-matrix.h \ + $(top_srcdir)/clutter/cogl/cogl-offscreen.h \ + $(top_srcdir)/clutter/cogl/cogl-path.h \ + $(top_srcdir)/clutter/cogl/cogl-shader.h \ + $(top_srcdir)/clutter/cogl/cogl-texture.h \ + $(top_srcdir)/clutter/cogl/cogl-types.h \ + $(top_srcdir)/clutter/cogl/cogl-vertex-buffer.h \ + $(top_builddir)/clutter/cogl/cogl.h \ + $(NULL) + noinst_LTLIBRARIES = libclutter-cogl-common.la -EXTRA_DIST = stb_image.c + +cogl-enum-types.h: stamp-cogl-enum-types.h + $(QUIET_CP)cp -f $(@F) $(top_builddir)/clutter/cogl/cogl-enum-types.h + +stamp-cogl-enum-types.h: $(cogl_public_h) Makefile + $(QUIET_GEN)( $(GLIB_MKENUMS) \ + --template $(srcdir)/cogl-enum-types.h.in \ + $(cogl_public_h) ) > xgen-ceth \ + && (cmp -s xgen-ceth cogl-enum-types.h || cp -f xgen-ceth cogl-enum-types.h) \ + && rm -f xgen-ceth \ + && echo timestamp > $(@F) + +cogl-enum-types.c: cogl-enum-types.h + $(QUIET_GEN)( $(GLIB_MKENUMS) \ + --template $(srcdir)/cogl-enum-types.c.in \ + $(cogl_public_h) ) > xgen-cetc \ + && cp -f xgen-cetc cogl-enum-types.c \ + && rm -f xgen-cetc + +BUILT_SOURCES = cogl-enum-types.h cogl-enum-types.c libclutter_cogl_common_la_CPPFLAGS = $(CLUTTER_CFLAGS) $(COGL_DEBUG_CFLAGS) $(CLUTTER_DEBUG_CFLAGS) $(MAINTAINER_CFLAGS) libclutter_cogl_common_la_LIBADD = -lm $(CLUTTER_LIBS) libclutter_cogl_common_la_SOURCES = \ + $(top_builddir)/clutter/cogl/common/cogl-enum-types.h \ + $(top_builddir)/clutter/cogl/common/cogl-enum-types.c \ cogl-handle.h \ cogl-internal.h \ cogl.c \ @@ -41,4 +85,9 @@ libclutter_cogl_common_la_SOURCES = \ cogl-material-private.h \ cogl-blend-string.c \ cogl-blend-string.h \ - cogl-debug.c + cogl-debug.c \ + $(NULL) + +EXTRA_DIST = stb_image.c cogl-enum-types.h.in cogl-enum-types.h.in +CLEANFILES = stamp-cogl-enum-types.h +DISTCLEANFILES = cogl-enum-types.h cogl-enum-types.c diff --git a/common/cogl-enum-types.c.in b/common/cogl-enum-types.c.in new file mode 100644 index 000000000..f2c01c78c --- /dev/null +++ b/common/cogl-enum-types.c.in @@ -0,0 +1,33 @@ +/*** BEGIN file-header ***/ +#include "cogl-enum-types.h" +#include "cogl.h" +/*** END file-header ***/ + +/*** BEGIN file-production ***/ +/* enumerations from "@filename@" */ +#include "@filename@" +/*** END file-production ***/ + +/*** BEGIN value-header ***/ +GType +@enum_name@_get_type(void) { + static GType etype = 0; + + if (G_UNLIKELY (!etype)) + { + static const G@Type@Value values[] = { +/*** END value-header ***/ + +/*** BEGIN value-production ***/ + { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, +/*** END value-production ***/ + +/*** BEGIN value-tail ***/ + { 0, NULL, NULL } + }; + etype = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values); + } + + return etype; +} +/*** END value-tail ***/ diff --git a/common/cogl-enum-types.h.in b/common/cogl-enum-types.h.in new file mode 100644 index 000000000..23d705dee --- /dev/null +++ b/common/cogl-enum-types.h.in @@ -0,0 +1,25 @@ +/*** BEGIN file-header ***/ +#ifndef __COGL_ENUM_TYPES_H__ +#define __COGL_ENUM_TYPES_H__ + +#include + +G_BEGIN_DECLS + +/*** END file-header ***/ + +/*** BEGIN file-production ***/ +/* enumerations from "@filename@" */ +/*** END file-production ***/ + +/*** BEGIN file-tail ***/ +G_END_DECLS + +#endif /* !__CLUTTER_ENUM_TYPES_H__ */ +/*** END file-tail ***/ + +/*** BEGIN value-header ***/ +GType @enum_name@_get_type (void) G_GNUC_CONST; +#define COGL_TYPE_@ENUMSHORT@ (@enum_name@_get_type()) + +/*** END value-header ***/ diff --git a/common/cogl-util.c b/common/cogl-util.c index 2b9ccba27..2d86f73f3 100644 --- a/common/cogl-util.c +++ b/common/cogl-util.c @@ -103,160 +103,6 @@ cogl_handle_get_type (void) return our_type; } -GType -cogl_pixel_format_get_type (void) -{ - static GType gtype = 0; - - if (G_UNLIKELY (gtype == 0)) - { - static const GEnumValue values[] = { - { COGL_PIXEL_FORMAT_ANY, "COGL_PIXEL_FORMAT_ANY", "any" }, - { COGL_PIXEL_FORMAT_A_8, "COGL_PIXEL_FORMAT_A_8", "a-8" }, - { COGL_PIXEL_FORMAT_RGB_565, "COGL_PIXEL_FORMAT_RGB_565", "rgb-565" }, - { COGL_PIXEL_FORMAT_RGBA_4444, "COGL_PIXEL_FORMAT_RGBA_4444", "rgba-4444" }, - { COGL_PIXEL_FORMAT_RGBA_5551, "COGL_PIXEL_FORMAT_RGBA_5551", "rgba-5551" }, - { COGL_PIXEL_FORMAT_YUV, "COGL_PIXEL_FORMAT_YUV", "yuv" }, - { COGL_PIXEL_FORMAT_G_8, "COGL_PIXEL_FORMAT_G_8", "g-8" }, - { COGL_PIXEL_FORMAT_RGB_888, "COGL_PIXEL_FORMAT_RGB_888", "rgb-888" }, - { COGL_PIXEL_FORMAT_BGR_888, "COGL_PIXEL_FORMAT_BGR_888", "bgr-888" }, - { COGL_PIXEL_FORMAT_RGBA_8888, "COGL_PIXEL_FORMAT_RGBA_8888", "rgba-8888" }, - { COGL_PIXEL_FORMAT_BGRA_8888, "COGL_PIXEL_FORMAT_BGRA_8888", "bgra-8888" }, - { COGL_PIXEL_FORMAT_ARGB_8888, "COGL_PIXEL_FORMAT_ARGB_8888", "argb-8888" }, - { COGL_PIXEL_FORMAT_ABGR_8888, "COGL_PIXEL_FORMAT_ABGR_8888", "abgr-8888" }, - { COGL_PIXEL_FORMAT_RGBA_8888_PRE, "COGL_PIXEL_FORMAT_RGBA_8888_PRE", "rgba-8888-pre" }, - { COGL_PIXEL_FORMAT_BGRA_8888_PRE, "COGL_PIXEL_FORMAT_BGRA_8888_PRE", "bgra-8888-pre" }, - { COGL_PIXEL_FORMAT_ARGB_8888_PRE, "COGL_PIXEL_FORMAT_ARGB_8888_PRE", "argb-8888-pre" }, - { COGL_PIXEL_FORMAT_ABGR_8888_PRE, "COGL_PIXEL_FORMAT_ABGR_8888_PRE", "abgr-8888-pre" }, - { COGL_PIXEL_FORMAT_RGBA_4444_PRE, "COGL_PIXEL_FORMAT_RGBA_4444_PRE", "rgba-4444-pre" }, - { COGL_PIXEL_FORMAT_RGBA_5551_PRE, "COGL_PIXEL_FORMAT_RGBA_5551_PRE", "rgba-5551-pre" }, - { 0, NULL, NULL } - }; - - gtype = - g_enum_register_static (g_intern_static_string ("CoglPixelFormat"), - values); - } - - return gtype; -} - -GType -cogl_feature_flags_get_type (void) -{ - static GType gtype = 0; - - if (G_UNLIKELY (gtype == 0)) - { - static const GFlagsValue values[] = { - { COGL_FEATURE_TEXTURE_RECTANGLE, "COGL_FEATURE_TEXTURE_RECTANGLE", "texture-rectangle" }, - { COGL_FEATURE_TEXTURE_NPOT, "COGL_FEATURE_TEXTURE_NPOT", "texture-npot" }, - { COGL_FEATURE_TEXTURE_YUV, "COGL_FEATURE_TEXTURE_YUV", "yuv" }, - { COGL_FEATURE_TEXTURE_READ_PIXELS, "COGL_FEATURE_TEXTURE_READ_PIXELS", "read-pixels" }, - { COGL_FEATURE_SHADERS_GLSL, "COGL_FEATURE_SHADERS_GLSL", "shaders-glsl" }, - { COGL_FEATURE_OFFSCREEN, "COGL_FEATURE_OFFSCREEN", "offscreen" }, - { COGL_FEATURE_OFFSCREEN_MULTISAMPLE, "COGL_FEATURE_OFFSCREEN_MULTISAMPLE", "offscreen-multisample" }, - { COGL_FEATURE_OFFSCREEN_BLIT, "COGL_FEATURE_OFFSCREEN_BLIT", "offscreen-blit" }, - { COGL_FEATURE_FOUR_CLIP_PLANES, "COGL_FEATURE_FOUR_CLIP_PLANES", "four-clip-planes" }, - { COGL_FEATURE_STENCIL_BUFFER, "COGL_FEATURE_STENCIL_BUFFER", "stencil-buffer" }, - { 0, NULL, NULL } - }; - - gtype = - g_flags_register_static (g_intern_static_string ("CoglFeatureFlags"), - values); - } - - return gtype; -} - -GType -cogl_buffer_target_get_type (void) -{ - static GType gtype = 0; - - if (G_UNLIKELY (gtype == 0)) - { - static const GFlagsValue values[] = { - { COGL_WINDOW_BUFFER, "COGL_WINDOW_BUFFER", "window-buffer" }, - { COGL_OFFSCREEN_BUFFER, "COGL_OFFSCREEN_BUFFER", "offscreen-buffer" }, - { 0, NULL, NULL } - }; - - gtype = - g_flags_register_static (g_intern_static_string ("CoglBufferTarget"), - values); - } - - return gtype; -} - -GType -cogl_matrix_mode_get_type (void) -{ - static GType gtype = 0; - - if (G_UNLIKELY (gtype == 0)) - { - static const GEnumValue values[] = { - { COGL_MATRIX_MODELVIEW, "COGL_MATRIX_MODELVIEW", "modelview" }, - { COGL_MATRIX_PROJECTION, "COGL_MATRIX_PROJECTION", "projection" }, - { COGL_MATRIX_TEXTURE, "COGL_MATRIX_TEXTURE", "texture" }, - { 0, NULL, NULL } - }; - - gtype = - g_enum_register_static (g_intern_static_string ("CoglMatrixMode"), - values); - } - - return gtype; -} - -GType -cogl_texture_flags_get_type (void) -{ - static GType gtype = 0; - - if (G_UNLIKELY (gtype == 0)) - { - static const GFlagsValue values[] = { - { COGL_TEXTURE_NONE, "COGL_TEXTURE_NONE", "none" }, - { COGL_TEXTURE_AUTO_MIPMAP, "COGL_TEXTURE_AUTO_MIPMAP", "auto-mipmap" }, - { COGL_TEXTURE_NO_SLICING, "COGL_TEXTURE_NO_SLICING", "no-slicing" }, - { 0, NULL, NULL } - }; - - gtype = - g_flags_register_static (g_intern_static_string ("CoglTextureFlags"), - values); - } - - return gtype; -} - -GType -cogl_fog_mode_get_type (void) -{ - static GType gtype = 0; - - if (G_UNLIKELY (gtype == 0)) - { - static const GEnumValue values[] = { - { COGL_FOG_MODE_LINEAR, "COGL_FOG_MODE_LINEAR", "linear" }, - { COGL_FOG_MODE_EXPONENTIAL, "COGL_FOG_MODE_EXPONENTIAL", "exponential" }, - { COGL_FOG_MODE_EXPONENTIAL_SQUARED, "COGL_FOG_MODE_EXPONENTIAL_SQUARED", "exponential-squared" }, - { 0, NULL, NULL } - }; - - gtype = - g_enum_register_static (g_intern_static_string ("CoglFogMode"), - values); - } - - return gtype; -} - /* * CoglFixed */ diff --git a/gl/Makefile.am b/gl/Makefile.am index 367f674f2..dc33e0bb1 100644 --- a/gl/Makefile.am +++ b/gl/Makefile.am @@ -35,11 +35,6 @@ cogl_sources = \ cogl-context.c \ $(NULL) -coglincludedir = $(includedir)/clutter-@CLUTTER_API_VERSION@/cogl -coglinclude_HEADERS = \ - $(cogl_headers) \ - $(top_builddir)/clutter/cogl/cogl.h - INCLUDES = \ -I$(top_srcdir)/clutter/cogl \ -I$(top_srcdir)/clutter/cogl/common \ From 99b2f14d6014c8b855ea85185b8026af079ae690 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Fri, 29 May 2009 12:40:23 +0100 Subject: [PATCH 21/37] Use g_once when registering enumeration types Just like we do with GObject types and G_DEFINE_TYPE, we should use the g_once_init_enter/g_once_init_leave mechanism to make the GType registration of enumeration types thread safe. --- common/cogl-enum-types.c.in | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/common/cogl-enum-types.c.in b/common/cogl-enum-types.c.in index f2c01c78c..157180dfe 100644 --- a/common/cogl-enum-types.c.in +++ b/common/cogl-enum-types.c.in @@ -4,16 +4,19 @@ /*** END file-header ***/ /*** BEGIN file-production ***/ + /* enumerations from "@filename@" */ #include "@filename@" + /*** END file-production ***/ /*** BEGIN value-header ***/ GType -@enum_name@_get_type(void) { - static GType etype = 0; +@enum_name@_get_type (void) +{ + static volatile gsize g_enum_type_id__volatile = 0; - if (G_UNLIKELY (!etype)) + if (g_once_init_enter (&g_enum_type_id__volatile)) { static const G@Type@Value values[] = { /*** END value-header ***/ @@ -25,9 +28,14 @@ GType /*** BEGIN value-tail ***/ { 0, NULL, NULL } }; - etype = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values); + GType g_enum_type_id; + + g_enum_type_id = + g_@type@_register_static (g_intern_static_string ("@EnumName@"), values); + + g_once_init_leave (&g_enum_type_id__volatile, g_enum_type_id); } - return etype; + return g_enum_type_id__volatile; } /*** END value-tail ***/ From 1c8a6bc09b8fa877ff337fefa54c53db20599e2f Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Fri, 29 May 2009 12:50:48 +0100 Subject: [PATCH 22/37] [build] Encode the target into the backend library The libclutter-cogl internal object should be the only dependency for Clutter, since we are already copying it inside clutter/cogl for the introspection scanner. For this reason, the backend-specific, real internal object should be built with the backend encoded into the file name, like libclutter-common. This makes the build output a little bit more clear: instead of having two: LINK libclutter-cogl-common.la ... LINK libclutter-cogl.la LINK libclutter-cogl.la We'll have: LINK libclutter-cogl-common.la ... LINK libclutter-cogl-gl.la LINK libclutter-cogl.la Same applies for the GLES backend. --- Makefile.am | 4 ++-- gl/Makefile.am | 10 +++++----- gles/Makefile.am | 12 ++++++------ 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Makefile.am b/Makefile.am index 1490ec68a..4cbcef334 100644 --- a/Makefile.am +++ b/Makefile.am @@ -52,14 +52,14 @@ cogl_headers = \ # so we create a libclutter-cogl.la that's just identical to the one # in the subdir noinst_LTLIBRARIES = libclutter-cogl.la -libclutter_cogl_la_LIBADD = $(CLUTTER_COGL)/libclutter-cogl.la +libclutter_cogl_la_LIBADD = $(CLUTTER_COGL)/libclutter-cogl-$(CLUTTER_COGL).la libclutter_cogl_la_SOURCES = $(cogl_headers) coglincludedir = $(includedir)/clutter-@CLUTTER_API_VERSION@/cogl coglinclude_HEADERS = $(cogl_headers) if HAVE_INTROSPECTION -Cogl-@CLUTTER_API_VERSION@.gir: $(INTROSPECTION_SCANNER) $(CLUTTER_COGL)/libclutter-cogl.la +Cogl-@CLUTTER_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libclutter-cogl.la $(QUIET_GEN)$(INTROSPECTION_SCANNER) -v \ --namespace Cogl --nsversion=@CLUTTER_API_VERSION@ \ -I$(top_srcdir)/clutter/cogl \ diff --git a/gl/Makefile.am b/gl/Makefile.am index dc33e0bb1..1aab5b649 100644 --- a/gl/Makefile.am +++ b/gl/Makefile.am @@ -45,12 +45,12 @@ INCLUDES = \ -DG_LOG_DOMAIN=\"Cogl-GL\" \ -DCLUTTER_COMPILATION -noinst_LTLIBRARIES = libclutter-cogl.la +noinst_LTLIBRARIES = libclutter-cogl-gl.la -libclutter_cogl_la_CPPFLAGS = $(CLUTTER_CFLAGS) $(COGL_DEBUG_CFLAGS) $(CLUTTER_DEBUG_CFLAGS) $(MAINTAINER_CFLAGS) -libclutter_cogl_la_LIBADD = -lm $(CLUTTER_LIBS) $(top_builddir)/clutter/cogl/common/libclutter-cogl-common.la -libclutter_cogl_la_DEPENDENCIES = $(top_builddir)/clutter/cogl/common/libclutter-cogl-common.la -libclutter_cogl_la_SOURCES = \ +libclutter_cogl_gl_la_CPPFLAGS = $(CLUTTER_CFLAGS) $(COGL_DEBUG_CFLAGS) $(CLUTTER_DEBUG_CFLAGS) $(MAINTAINER_CFLAGS) +libclutter_cogl_gl_la_LIBADD = -lm $(CLUTTER_LIBS) $(top_builddir)/clutter/cogl/common/libclutter-cogl-common.la +libclutter_cogl_gl_la_DEPENDENCIES = $(top_builddir)/clutter/cogl/common/libclutter-cogl-common.la +libclutter_cogl_gl_la_SOURCES = \ $(top_builddir)/clutter/cogl/cogl.h \ $(cogl_headers) \ $(cogl_priv_headers) \ diff --git a/gles/Makefile.am b/gles/Makefile.am index 3f84b4b2f..3ce5365a7 100644 --- a/gles/Makefile.am +++ b/gles/Makefile.am @@ -27,12 +27,12 @@ INCLUDES = \ -DG_LOG_DOMAIN=\"Cogl-GLES\" \ -DCLUTTER_COMPILATION -noinst_LTLIBRARIES = libclutter-cogl.la +noinst_LTLIBRARIES = libclutter-cogl-gles.la -libclutter_cogl_la_CPPFLAGS = $(CLUTTER_CFLAGS) $(COGL_DEBUG_CFLAGS) $(CLUTTER_DEBUG_CFLAGS) $(MAINTAINER_CFLAGS) -libclutter_cogl_la_LIBADD = -lm $(CLUTTER_LIBS) $(top_builddir)/clutter/cogl/common/libclutter-cogl-common.la -libclutter_cogl_la_DEPENDENCIES = $(top_builddir)/clutter/cogl/common/libclutter-cogl-common.la -libclutter_cogl_la_SOURCES = \ +libclutter_cogl_gles_la_CPPFLAGS = $(CLUTTER_CFLAGS) $(COGL_DEBUG_CFLAGS) $(CLUTTER_DEBUG_CFLAGS) $(MAINTAINER_CFLAGS) +libclutter_cogl_gles_la_LIBADD = -lm $(CLUTTER_LIBS) $(top_builddir)/clutter/cogl/common/libclutter-cogl-common.la +libclutter_cogl_gles_la_DEPENDENCIES = $(top_builddir)/clutter/cogl/common/libclutter-cogl-common.la +libclutter_cogl_gles_la_SOURCES = \ $(top_builddir)/clutter/cogl/cogl.h \ $(top_builddir)/clutter/cogl/cogl-defines-gles.h \ $(top_builddir)/clutter/cogl/cogl-color.h \ @@ -60,7 +60,7 @@ libclutter_cogl_la_SOURCES = \ cogl-shader.c if USE_GLES2_WRAPPER -libclutter_cogl_la_SOURCES += \ +libclutter_cogl_gles_la_SOURCES += \ cogl-gles2-wrapper.c \ cogl-fixed-vertex-shader.h \ cogl-fixed-vertex-shader.c \ From 93a9613b59324a8cb332036aa2b15fe98c311c63 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Fri, 29 May 2009 14:27:55 +0100 Subject: [PATCH 23/37] [build] Copy cogl-enum-types.h under the guard We avoid rebuilding cogl-enum-types.h and cogl-enum-types.c by using a "guard" -- a stamp file that will block Makefile. Since we need cogl-enum-types.h into /clutter/cogl as well for the cogl.h include to work, if we copy the cogl-enum-types.h unconditionally it will cause a rebuild of the whole COGL; which will cause a full rebuild. To solve this, we can copy the header file when generating it under the stamp file. --- common/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/Makefile.am b/common/Makefile.am index df50a1d16..a61ed8dda 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -35,13 +35,13 @@ cogl_public_h = \ noinst_LTLIBRARIES = libclutter-cogl-common.la cogl-enum-types.h: stamp-cogl-enum-types.h - $(QUIET_CP)cp -f $(@F) $(top_builddir)/clutter/cogl/cogl-enum-types.h - + @true stamp-cogl-enum-types.h: $(cogl_public_h) Makefile $(QUIET_GEN)( $(GLIB_MKENUMS) \ --template $(srcdir)/cogl-enum-types.h.in \ $(cogl_public_h) ) > xgen-ceth \ && (cmp -s xgen-ceth cogl-enum-types.h || cp -f xgen-ceth cogl-enum-types.h) \ + && cp -f cogl-enum-types.h $(top_builddir)/clutter/cogl/cogl-enum-types.h \ && rm -f xgen-ceth \ && echo timestamp > $(@F) From 5888e45fd73b3f11de1d0a100cc6072ceb80c1df Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Fri, 29 May 2009 17:10:27 +0100 Subject: [PATCH 24/37] [build] Fix dist issues * cogl-deprecated.h is not being installed * cogl-enum-types.c.in is not part of the dist --- Makefile.am | 1 + common/Makefile.am | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 4cbcef334..5dec59880 100644 --- a/Makefile.am +++ b/Makefile.am @@ -34,6 +34,7 @@ cogl_headers = \ $(top_srcdir)/clutter/cogl/cogl-bitmap.h \ $(top_srcdir)/clutter/cogl/cogl-color.h \ $(top_srcdir)/clutter/cogl/cogl-debug.h \ + $(top_srcdir)/clutter/cogl/cogl-deprecated.h \ $(top_srcdir)/clutter/cogl/cogl-fixed.h \ $(top_srcdir)/clutter/cogl/cogl-material.h \ $(top_srcdir)/clutter/cogl/cogl-matrix.h \ diff --git a/common/Makefile.am b/common/Makefile.am index a61ed8dda..7a7dd8232 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -88,6 +88,6 @@ libclutter_cogl_common_la_SOURCES = \ cogl-debug.c \ $(NULL) -EXTRA_DIST = stb_image.c cogl-enum-types.h.in cogl-enum-types.h.in +EXTRA_DIST = stb_image.c cogl-enum-types.h.in cogl-enum-types.c.in CLEANFILES = stamp-cogl-enum-types.h DISTCLEANFILES = cogl-enum-types.h cogl-enum-types.c From 2f319ad839972a393569d53c87689bdc4a5f55b7 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Fri, 29 May 2009 17:50:58 +0100 Subject: [PATCH 25/37] [build] Remove cogl-enum-types.h on distclean The cogl-enum-types.h file is created by glib-mkenums under /clutter/cogl/common, and then copied in /clutter/cogl in order to make the inclusion of that file work inside cogl.h. Since we're copying it in a different location, the Makefile for that location has to clean up the copy. --- Makefile.am | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile.am b/Makefile.am index 5dec59880..cae798703 100644 --- a/Makefile.am +++ b/Makefile.am @@ -49,6 +49,10 @@ cogl_headers = \ $(top_builddir)/clutter/cogl/cogl.h \ $(NULL) +# this is copied in from common/ to make cogl.h work, but we +# need to clean it up ourselves once we're done +DISTCLEANFILES = cogl-enum-types.h + # HACK - gobject-introspection can't scan a library in another directory # so we create a libclutter-cogl.la that's just identical to the one # in the subdir From 39cb36ba0110a65696cff9461caf52227762be34 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Thu, 28 May 2009 13:47:18 +0100 Subject: [PATCH 26/37] [cogl-vertex-buffer] Add cogl_vertex_buffer_indices_get_for_quads This function can be used as an efficient way of drawing groups of quads without using GL_QUADS. It generates a VBO containing the indices needed to render using pairs of GL_TRIANGLES. The VBO is globally cached so that it only needs to be uploaded whenever more indices are requested than ever before. --- cogl-vertex-buffer.h | 40 ++++++++++++++ common/cogl-vertex-buffer.c | 80 ++++++++++++++++++++++++++++ doc/reference/cogl/cogl-sections.txt | 1 + gl/cogl-context.c | 9 ++++ gl/cogl-context.h | 6 +++ gles/cogl-context.c | 9 ++++ gles/cogl-context.h | 7 ++- 7 files changed, 151 insertions(+), 1 deletion(-) diff --git a/cogl-vertex-buffer.h b/cogl-vertex-buffer.h index ab37dbced..f01b5d3dd 100644 --- a/cogl-vertex-buffer.h +++ b/cogl-vertex-buffer.h @@ -394,6 +394,46 @@ cogl_vertex_buffer_ref (CoglHandle handle); void cogl_vertex_buffer_unref (CoglHandle handle); +/** + * cogl_vertex_buffer_indices_get_for_quads: + * @n_indices: the number of indices in the vertex buffer. + * + * Creates a vertex buffer containing the indices needed to draw pairs + * of triangles from a list of vertices grouped as quads. There will + * be at least @n_indices entries in the buffer (but there may be + * more). + * + * The indices will follow this pattern: + * + * 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7 ... etc + * + * For example, if you submit vertices for a quad like this: + * + * |[ + * 0 3 + * ######## + * # # + * # # + * ######## + * 1 2 + * ]| + * + * Then you can request 6 indices to render two triangles like this: + * + * |[ + * 0 0 3 + * ## ######## + * # ## ## # + * # ## ## # + * ######## ## + * 1 2 2 + * ]| + * + * Returns: A %CoglHandle containing the indices. The handled is + * owned by Cogl and should not be modified or unref'd. + */ +CoglHandle +cogl_vertex_buffer_indices_get_for_quads (guint n_indices); G_END_DECLS diff --git a/common/cogl-vertex-buffer.c b/common/cogl-vertex-buffer.c index b3c36f0ec..a36bb1cec 100644 --- a/common/cogl-vertex-buffer.c +++ b/common/cogl-vertex-buffer.c @@ -1880,3 +1880,83 @@ _cogl_vertex_buffer_free (CoglVertexBuffer *buffer) g_slice_free (CoglVertexBuffer, buffer); } +CoglHandle +cogl_vertex_buffer_indices_get_for_quads (guint n_indices) +{ + _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE); + + /* Check if the indices would fit in a byte array */ + if (n_indices <= 256 / 4 * 6) + { + /* Generate the byte array if we haven't already */ + if (ctx->quad_indices_byte == COGL_INVALID_HANDLE) + { + guint8 *byte_array = g_malloc (256 / 4 * 6 * sizeof (guint8)); + guint8 *p = byte_array; + int i, vert_num = 0; + + for (i = 0; i < 256 / 4; i++) + { + *(p++) = vert_num + 0; + *(p++) = vert_num + 1; + *(p++) = vert_num + 2; + *(p++) = vert_num + 0; + *(p++) = vert_num + 2; + *(p++) = vert_num + 3; + vert_num += 4; + } + + ctx->quad_indices_byte + = cogl_vertex_buffer_indices_new (COGL_INDICES_TYPE_UNSIGNED_BYTE, + byte_array, + 256 / 4 * 6); + + g_free (byte_array); + } + + return ctx->quad_indices_byte; + } + else + { + if (ctx->quad_indices_short_len < n_indices) + { + guint16 *short_array; + guint16 *p; + int i, vert_num = 0; + + if (ctx->quad_indices_short != COGL_INVALID_HANDLE) + cogl_handle_unref (ctx->quad_indices_short); + /* Pick a power of two >= MAX (512, n_indices) */ + if (ctx->quad_indices_short_len == 0) + ctx->quad_indices_short_len = 512; + while (ctx->quad_indices_short_len < n_indices) + ctx->quad_indices_short_len *= 2; + + /* Over-allocate to generate a whole number of quads */ + p = short_array = g_malloc ((ctx->quad_indices_short_len + + 5) / 6 * 6 + * sizeof (guint16)); + + /* Fill in the complete quads */ + for (i = 0; i < ctx->quad_indices_short_len; i += 6) + { + *(p++) = vert_num + 0; + *(p++) = vert_num + 1; + *(p++) = vert_num + 2; + *(p++) = vert_num + 0; + *(p++) = vert_num + 2; + *(p++) = vert_num + 3; + vert_num += 4; + } + + ctx->quad_indices_short + = cogl_vertex_buffer_indices_new (COGL_INDICES_TYPE_UNSIGNED_SHORT, + short_array, + ctx->quad_indices_short_len); + + g_free (short_array); + } + + return ctx->quad_indices_short; + } +} diff --git a/doc/reference/cogl/cogl-sections.txt b/doc/reference/cogl/cogl-sections.txt index 9d49ea53f..f596ee042 100644 --- a/doc/reference/cogl/cogl-sections.txt +++ b/doc/reference/cogl/cogl-sections.txt @@ -313,6 +313,7 @@ CoglIndicesType cogl_vertex_buffer_add_indices cogl_vertex_buffer_delete_indices cogl_vertex_buffer_draw_elements +cogl_vertex_buffer_indices_get_for_quads CoglVertexBufferAttribFlags COGL_VERTEX_BUFFER_ATTRIB_FLAG_GL_TYPE_MASK diff --git a/gl/cogl-context.c b/gl/cogl-context.c index 39415a02a..16fcb3e12 100644 --- a/gl/cogl-context.c +++ b/gl/cogl-context.c @@ -171,6 +171,10 @@ cogl_create_context () _cogl_material_get_cogl_enable_flags (_context->source_material); cogl_enable (enable_flags); + _context->quad_indices_byte = COGL_INVALID_HANDLE; + _context->quad_indices_short = COGL_INVALID_HANDLE; + _context->quad_indices_short_len = 0; + return TRUE; } @@ -207,6 +211,11 @@ _cogl_destroy_context () if (_context->current_layers) g_array_free (_context->current_layers, TRUE); + if (_context->quad_indices_byte) + cogl_handle_unref (_context->quad_indices_byte); + if (_context->quad_indices_short) + cogl_handle_unref (_context->quad_indices_short); + g_free (_context); } diff --git a/gl/cogl-context.h b/gl/cogl-context.h index f490d39ac..f5ca54cb2 100644 --- a/gl/cogl-context.h +++ b/gl/cogl-context.h @@ -102,6 +102,12 @@ typedef struct floatVec2 path_nodes_max; CoglHandle stencil_material; + /* Pre-generated VBOs containing indices to generate GL_TRIANGLES + out of a vertex array of quads */ + CoglHandle quad_indices_byte; + guint quad_indices_short_len; + CoglHandle quad_indices_short; + /* Relying on glext.h to define these */ COGL_PFNGLGENRENDERBUFFERSEXTPROC pf_glGenRenderbuffersEXT; COGL_PFNGLDELETERENDERBUFFERSEXTPROC pf_glDeleteRenderbuffersEXT; diff --git a/gles/cogl-context.c b/gles/cogl-context.c index 5b6ce7c1b..d3ec31c5d 100644 --- a/gles/cogl-context.c +++ b/gles/cogl-context.c @@ -129,6 +129,10 @@ cogl_create_context () _cogl_material_get_cogl_enable_flags (_context->source_material); cogl_enable (enable_flags); + _context->quad_indices_byte = COGL_INVALID_HANDLE; + _context->quad_indices_short = COGL_INVALID_HANDLE; + _context->quad_indices_short_len = 0; + return TRUE; } @@ -165,6 +169,11 @@ _cogl_destroy_context () if (_context->current_layers) g_array_free (_context->current_layers, TRUE); + if (_context->quad_indices_byte) + cogl_handle_unref (_context->quad_indices_byte); + if (_context->quad_indices_short) + cogl_handle_unref (_context->quad_indices_short); + g_free (_context); } diff --git a/gles/cogl-context.h b/gles/cogl-context.h index 3542e038d..9c1d44fbe 100644 --- a/gles/cogl-context.h +++ b/gles/cogl-context.h @@ -104,6 +104,12 @@ typedef struct floatVec2 path_nodes_max; CoglHandle stencil_material; + /* Pre-generated VBOs containing indices to generate GL_TRIANGLES + out of a vertex array of quads */ + CoglHandle quad_indices_byte; + guint quad_indices_short_len; + CoglHandle quad_indices_short; + #ifdef HAVE_COGL_GLES2 CoglGles2Wrapper gles2; @@ -111,7 +117,6 @@ typedef struct supported */ GLint viewport_store[4]; #endif - } CoglContext; CoglContext * From 9d41a27f61d1298aaac0a15fc2fbbab8fbb8a15d Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Mon, 1 Jun 2009 17:10:22 +0100 Subject: [PATCH 27/37] Use GL_QUADS for flushing a quad batch Instead of using GL_TRIANGLES and uploading the indices every time, it now uses GL_QUADS instead on OpenGL. Under GLES it still uses indices but it uses the new cogl_vertex_buffer_indices_get_for_quads function to avoid uploading the vertices every time. This requires the _cogl_vertex_buffer_indices_pointer_from_handle function to be exposed privately to the rest of Cogl. The static_indices array has been removed from the Cogl context. --- common/cogl-primitives.c | 71 +++++++++-------------------- common/cogl-vertex-buffer-private.h | 4 ++ gl/cogl-context.c | 3 -- gl/cogl-context.h | 1 - gles/cogl-context.c | 3 -- gles/cogl-context.h | 1 - 6 files changed, 25 insertions(+), 58 deletions(-) diff --git a/common/cogl-primitives.c b/common/cogl-primitives.c index ff5401d50..c43fbde49 100644 --- a/common/cogl-primitives.c +++ b/common/cogl-primitives.c @@ -30,6 +30,7 @@ #include "cogl-context.h" #include "cogl-texture-private.h" #include "cogl-material-private.h" +#include "cogl-vertex-buffer-private.h" #include #include @@ -39,16 +40,8 @@ #ifdef HAVE_COGL_GL -#define glDrawRangeElements ctx->pf_glDrawRangeElements #define glClientActiveTexture ctx->pf_glClientActiveTexture -#else - -/* GLES doesn't have glDrawRangeElements, so we simply pretend it does - * but that it makes no use of the start, end constraints: */ -#define glDrawRangeElements(mode, start, end, count, type, indices) \ - glDrawElements (mode, count, type, indices) - #endif /* these are defined in the particular backend */ @@ -63,7 +56,6 @@ _cogl_journal_flush_quad_batch (CoglJournalEntry *batch_start, gint batch_len, GLfloat *vertex_pointer) { - int needed_indices; gsize stride; int i; gulong enable_flags = 0; @@ -122,52 +114,31 @@ _cogl_journal_flush_quad_batch (CoglJournalEntry *batch_start, GE (glVertexPointer (2, GL_FLOAT, stride, vertex_pointer)); _cogl_current_matrix_state_flush (); +#ifdef HAVE_COGL_GL - if (batch_len > 1) - { - /* The indices are always the same sequence regardless of the vertices so - * we only need to change it if there are more vertices than ever before. - */ - needed_indices = batch_len * 6; - if (needed_indices > ctx->static_indices->len) - { - int old_len = ctx->static_indices->len; - int vert_num = old_len / 6 * 4; - GLushort *q; + GE( glDrawArrays (GL_QUADS, 0, batch_len * 4) ); - /* Add two triangles for each quad to the list of - indices. That makes six new indices but two of the - vertices in the triangles are shared. */ - g_array_set_size (ctx->static_indices, needed_indices); - q = &g_array_index (ctx->static_indices, GLushort, old_len); +#else /* HAVE_COGL_GL */ - for (i = old_len; - i < ctx->static_indices->len; - i += 6, vert_num += 4) - { - *(q++) = vert_num + 0; - *(q++) = vert_num + 1; - *(q++) = vert_num + 3; + /* GLES doesn't support GL_QUADS so we will use GL_TRIANGLES and + indices */ + { + int needed_indices = batch_len * 6; + CoglHandle indices_handle + = cogl_vertex_buffer_indices_get_for_quads (needed_indices); + CoglVertexBufferIndices *indices + = _cogl_vertex_buffer_indices_pointer_from_handle (indices_handle); - *(q++) = vert_num + 1; - *(q++) = vert_num + 2; - *(q++) = vert_num + 3; - } - } - - GE (glDrawRangeElements (GL_TRIANGLES, - 0, ctx->static_indices->len - 1, - 6 * batch_len, - GL_UNSIGNED_SHORT, - ctx->static_indices->data)); - } - else - { - GE (glDrawArrays (GL_TRIANGLE_FAN, - 0, /* first */ - 4)); /* n vertices */ - } + GE (glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, + GPOINTER_TO_UINT (indices->vbo_name))); + GE (glDrawElements (GL_TRIANGLES, + 6 * batch_len, + indices->type, + NULL)); + GE (glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0)); + } +#endif /* HAVE_COGL_GL */ /* DEBUGGING CODE XXX: * This path will cause all rectangles to be drawn with a red, green diff --git a/common/cogl-vertex-buffer-private.h b/common/cogl-vertex-buffer-private.h index 17f8725e4..558765303 100644 --- a/common/cogl-vertex-buffer-private.h +++ b/common/cogl-vertex-buffer-private.h @@ -161,5 +161,9 @@ typedef struct _CoglVertexBuffer } CoglVertexBuffer; +CoglVertexBuffer *_cogl_vertex_buffer_pointer_from_handle (CoglHandle handle); +CoglVertexBufferIndices * + _cogl_vertex_buffer_indices_pointer_from_handle (CoglHandle handle); + #endif /* __COGL_VERTEX_BUFFER_H */ diff --git a/gl/cogl-context.c b/gl/cogl-context.c index 16fcb3e12..201e05db7 100644 --- a/gl/cogl-context.c +++ b/gl/cogl-context.c @@ -69,7 +69,6 @@ cogl_create_context () _context->journal = g_array_new (FALSE, FALSE, sizeof (CoglJournalEntry)); _context->logged_vertices = g_array_new (FALSE, FALSE, sizeof (GLfloat)); - _context->static_indices = g_array_new (FALSE, FALSE, sizeof (GLushort)); _context->polygon_vertices = g_array_new (FALSE, FALSE, sizeof (CoglTextureGLVertex)); @@ -204,8 +203,6 @@ _cogl_destroy_context () if (_context->logged_vertices) g_array_free (_context->logged_vertices, TRUE); - if (_context->static_indices) - g_array_free (_context->static_indices, TRUE); if (_context->polygon_vertices) g_array_free (_context->polygon_vertices, TRUE); if (_context->current_layers) diff --git a/gl/cogl-context.h b/gl/cogl-context.h index f5ca54cb2..10e56e510 100644 --- a/gl/cogl-context.h +++ b/gl/cogl-context.h @@ -78,7 +78,6 @@ typedef struct * can batch things together. */ GArray *journal; GArray *logged_vertices; - GArray *static_indices; GArray *polygon_vertices; /* Some simple caching, to minimize state changes... */ diff --git a/gles/cogl-context.c b/gles/cogl-context.c index d3ec31c5d..293ac4689 100644 --- a/gles/cogl-context.c +++ b/gles/cogl-context.c @@ -72,7 +72,6 @@ cogl_create_context () _context->journal = g_array_new (FALSE, FALSE, sizeof (CoglJournalEntry)); _context->logged_vertices = g_array_new (FALSE, FALSE, sizeof (GLfloat)); - _context->static_indices = g_array_new (FALSE, FALSE, sizeof (GLushort)); _context->polygon_vertices = g_array_new (FALSE, FALSE, sizeof (CoglTextureGLVertex)); @@ -162,8 +161,6 @@ _cogl_destroy_context () if (_context->logged_vertices) g_array_free (_context->logged_vertices, TRUE); - if (_context->static_indices) - g_array_free (_context->static_indices, TRUE); if (_context->polygon_vertices) g_array_free (_context->polygon_vertices, TRUE); if (_context->current_layers) diff --git a/gles/cogl-context.h b/gles/cogl-context.h index 9c1d44fbe..2e39f2bc0 100644 --- a/gles/cogl-context.h +++ b/gles/cogl-context.h @@ -80,7 +80,6 @@ typedef struct * can batch things together. */ GArray *journal; GArray *logged_vertices; - GArray *static_indices; GArray *polygon_vertices; /* Some simple caching, to minimize state changes... */ From c0c7565ffcdd3927279ddb69a84c46034de79fa9 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Mon, 1 Jun 2009 16:31:32 +0100 Subject: [PATCH 28/37] [cogl-shader] Make get_info_log() slightly nicer The cogl_shader_get_info_log() function is very inconvenient for language bindings and for regular use, as it requires a static buffer to be filled -- basically just providing a wrapper around glGetInfoLogARB(). Since COGL aims to be a more convenient API than raw GL we should just make cogl_shader_get_info_log() return an allocated string with the GLSL compiler log. --- cogl-shader.h | 13 ++++++------- gl/cogl-shader.c | 15 ++++++++------- gles/cogl-shader.c | 15 ++++++++------- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/cogl-shader.h b/cogl-shader.h index d0b0ce13e..9eec9bb40 100644 --- a/cogl-shader.h +++ b/cogl-shader.h @@ -106,7 +106,7 @@ gboolean cogl_is_shader (CoglHandle handle); * one. */ void cogl_shader_source (CoglHandle shader, - const char *source); + const gchar *source); /** * cogl_shader_compile: * @handle: #CoglHandle for a shader. @@ -119,17 +119,16 @@ void cogl_shader_compile (CoglHandle handle); /** * cogl_shader_get_info_log: * @handle: #CoglHandle for a shader. - * @size: maximum number of bytes to retrieve. - * @buffer: location for info log. * * Retrieves the information log for a coglobject, can be used in conjunction - * with #cogl_shader_get_parameteriv to retrieve the compiler warnings/error + * with cogl_shader_get_parameteriv() to retrieve the compiler warnings/error * messages that caused a shader to not compile correctly, mainly useful for * debugging purposes. + * + * Return value: a newly allocated string containing the info log. Use + * g_free() to free it */ -void cogl_shader_get_info_log (CoglHandle handle, - size_t size, - char *buffer); +gchar * cogl_shader_get_info_log (CoglHandle handle); /** * cogl_shader_get_type: diff --git a/gl/cogl-shader.c b/gl/cogl-shader.c index 944e6736f..de3302e6a 100644 --- a/gl/cogl-shader.c +++ b/gl/cogl-shader.c @@ -108,22 +108,23 @@ cogl_shader_compile (CoglHandle handle) glCompileShaderARB (shader->gl_handle); } -void -cogl_shader_get_info_log (CoglHandle handle, - size_t size, - char *buffer) +gchar * +cogl_shader_get_info_log (CoglHandle handle) { CoglShader *shader; + char buffer[512]; int len; - _COGL_GET_CONTEXT (ctx, NO_RETVAL); + _COGL_GET_CONTEXT (ctx, NULL); if (!cogl_is_shader (handle)) - return; + return NULL; shader = _cogl_shader_pointer_from_handle (handle); - glGetInfoLogARB (shader->gl_handle, size-1, &len, buffer); + glGetInfoLogARB (shader->gl_handle, 511, &len, buffer); buffer[len]='\0'; + + return g_strdup (buffer); } CoglShaderType diff --git a/gles/cogl-shader.c b/gles/cogl-shader.c index ff5f0c58a..11cbe0c33 100644 --- a/gles/cogl-shader.c +++ b/gles/cogl-shader.c @@ -99,22 +99,23 @@ cogl_shader_compile (CoglHandle handle) glCompileShader (shader->gl_handle); } -void -cogl_shader_get_info_log (CoglHandle handle, - size_t size, - char *buffer) +gchar * +cogl_shader_get_info_log (CoglHandle handle) { CoglShader *shader; + char buffer[512] int len = 0; - _COGL_GET_CONTEXT (ctx, NO_RETVAL); + _COGL_GET_CONTEXT (ctx, NULL); if (!cogl_is_shader (handle)) - return; + return NULL; shader = _cogl_shader_pointer_from_handle (handle); - glGetShaderInfoLog (shader->gl_handle, size - 1, &len, buffer); + glGetShaderInfoLog (shader->gl_handle, 511, &len, buffer); buffer[len] = '\0'; + + return g_strdup (buffer); } CoglShaderType From b900c314b704ef0f2597893cbe1cacfb7a61e294 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Mon, 1 Jun 2009 17:35:41 +0100 Subject: [PATCH 29/37] [docs] Rework the API reference version generation Clutter copies the gtk-doc from the usual gtk+ template, and has a version.xml.in containing only: @VERSION@ Without a newline at the end. Unfortunately, it appears that autoconf has started adding a newline to the generated version.xml which then is used as the payload for the "version" XML entity. Instead of using a secondary file we can make configure generate the whole clutter-docs.xml and cogl-docs.xml files from a template; this way we also get the ability to substitute more autoconf variables into the documentation -- if needs be. --- doc/reference/cogl/Makefile.am | 2 -- doc/reference/cogl/{cogl-docs.xml => cogl-docs.xml.in} | 2 +- doc/reference/cogl/version.xml.in | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) rename doc/reference/cogl/{cogl-docs.xml => cogl-docs.xml.in} (98%) delete mode 100644 doc/reference/cogl/version.xml.in diff --git a/doc/reference/cogl/Makefile.am b/doc/reference/cogl/Makefile.am index c2f075e4d..9888caaa3 100644 --- a/doc/reference/cogl/Makefile.am +++ b/doc/reference/cogl/Makefile.am @@ -71,7 +71,6 @@ HTML_IMAGES= # Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). # e.g. content_files=running.sgml building.sgml changes-2.0.sgml content_files = \ - version.xml \ blend-strings.xml # SGML files where gtk-doc abbrevations (#GtkWidget) are expanded @@ -94,4 +93,3 @@ include $(top_srcdir)/gtk-doc.make # Other files to distribute # e.g. EXTRA_DIST += version.xml.in -EXTRA_DIST += version.xml.in diff --git a/doc/reference/cogl/cogl-docs.xml b/doc/reference/cogl/cogl-docs.xml.in similarity index 98% rename from doc/reference/cogl/cogl-docs.xml rename to doc/reference/cogl/cogl-docs.xml.in index 87d665f42..7f9c1c26b 100644 --- a/doc/reference/cogl/cogl-docs.xml +++ b/doc/reference/cogl/cogl-docs.xml.in @@ -1,7 +1,7 @@ + ]> diff --git a/doc/reference/cogl/version.xml.in b/doc/reference/cogl/version.xml.in deleted file mode 100644 index 7fc1bf340..000000000 --- a/doc/reference/cogl/version.xml.in +++ /dev/null @@ -1 +0,0 @@ -@CLUTTER_VERSION@ \ No newline at end of file From db4fb91fe391d9da822c1427b8c364a416d80a80 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Thu, 4 Jun 2009 11:48:51 +0100 Subject: [PATCH 30/37] Rename 'near' and 'far' variables to 'z_near' and 'z_far' The Windows headers define near and far to be empty so it breaks the build. --- cogl-matrix.h | 12 ++++++------ common/cogl-current-matrix.c | 18 +++++++++--------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/cogl-matrix.h b/cogl-matrix.h index bd7b579c7..3ee94aeb5 100644 --- a/cogl-matrix.h +++ b/cogl-matrix.h @@ -228,10 +228,10 @@ cogl_matrix_perspective (CoglMatrix *matrix, * @right: The coordinate for the right clipping plane * @bottom: The coordinate for the bottom clipping plane * @top: The coordinate for the top clipping plane - * @near: The coordinate for the near clipping plane (may be negative if - * the plane is behind the viewer) - * @far: The coordinate for the far clipping plane (may be negative if - * the plane is behind the viewer) + * @z_near: The coordinate for the near clipping plane (may be negative if + * the plane is behind the viewer) + * @z_far: The coordinate for the far clipping plane (may be negative if + * the plane is behind the viewer) * * Multiples the matrix by a parallel projection matrix. */ @@ -241,8 +241,8 @@ cogl_matrix_ortho (CoglMatrix *matrix, float right, float bottom, float top, - float near, - float far); + float z_near, + float z_far); /** * cogl_matrix_init_from_array: diff --git a/common/cogl-current-matrix.c b/common/cogl-current-matrix.c index e01987c95..6d069bc66 100644 --- a/common/cogl-current-matrix.c +++ b/common/cogl-current-matrix.c @@ -239,8 +239,8 @@ _cogl_current_matrix_ortho (float left, float right, float bottom, float top, - float near, - float far) + float near_val, + float far_val) { _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL); @@ -248,8 +248,8 @@ _cogl_current_matrix_ortho (float left, _cogl_matrix_stack_ortho (current_stack, left, right, bottom, top, - near, - far); + near_val, + far_val); else { #ifdef HAVE_COGL_GLES2 @@ -257,10 +257,10 @@ _cogl_current_matrix_ortho (float left, CoglMatrix matrix; _cogl_get_matrix (ctx->matrix_mode, &matrix); cogl_matrix_ortho (&matrix, - left, right, bottom, top, near, far); + left, right, bottom, top, near_val, far_val); _cogl_current_matrix_load (&matrix); #else - GE (glOrtho (left, right, bottom, top, near, far)); + GE (glOrtho (left, right, bottom, top, near_val, far_val)); #endif } } @@ -453,14 +453,14 @@ cogl_ortho (float left, float right, float bottom, float top, - float near, - float far) + float z_near, + float z_far) { CoglMatrix ortho; _COGL_GET_CONTEXT (ctx, NO_RETVAL); cogl_matrix_init_identity (&ortho); - cogl_matrix_ortho (&ortho, left, right, bottom, top, near, far); + cogl_matrix_ortho (&ortho, left, right, bottom, top, z_near, z_far); _cogl_set_current_matrix (COGL_MATRIX_PROJECTION); _cogl_current_matrix_load (&ortho); From 00ac53042e810d10fe34422d0bf8ec2d4831365b Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Thu, 4 Jun 2009 11:50:06 +0100 Subject: [PATCH 31/37] Load glBlendEquation and glBlendColor using cogl_get_proc_address These are defined since OpenGL 1.2 and since Windows doesn't export any functions defined after 1.1 we need to load them dynamically. --- common/cogl-material.c | 2 ++ gl/cogl-context.h | 2 ++ gl/cogl-defines.h.in | 11 +++++++++++ gl/cogl.c | 7 +++++++ 4 files changed, 22 insertions(+) diff --git a/common/cogl-material.c b/common/cogl-material.c index 7e8567a6e..85f9f343b 100644 --- a/common/cogl-material.c +++ b/common/cogl-material.c @@ -52,6 +52,8 @@ #define glActiveTexture ctx->pf_glActiveTexture #define glClientActiveTexture ctx->pf_glClientActiveTexture #define glBlendFuncSeparate ctx->pf_glBlendFuncSeparate +#define glBlendEquation ctx->pf_glBlendEquation +#define glBlendColor ctx->pf_glBlendColor #define glBlendEquationSeparate ctx->pf_glBlendEquationSeparate #endif diff --git a/gl/cogl-context.h b/gl/cogl-context.h index 10e56e510..3db4c0e9e 100644 --- a/gl/cogl-context.h +++ b/gl/cogl-context.h @@ -170,6 +170,8 @@ typedef struct COGL_PFNGLACTIVETEXTUREPROC pf_glActiveTexture; COGL_PFNGLCLIENTACTIVETEXTUREPROC pf_glClientActiveTexture; + COGL_PFNGLBLENDEQUATIONPROC pf_glBlendEquation; + COGL_PFNGLBLENDCOLORPROC pf_glBlendColor; COGL_PFNGLBLENDFUNCSEPARATEPROC pf_glBlendFuncSeparate; COGL_PFNGLBLENDEQUATIONSEPARATEPROC pf_glBlendEquationSeparate; } CoglContext; diff --git a/gl/cogl-defines.h.in b/gl/cogl-defines.h.in index bde93c559..4805ea5b3 100644 --- a/gl/cogl-defines.h.in +++ b/gl/cogl-defines.h.in @@ -1032,6 +1032,17 @@ typedef void (GLenum modeRGB, GLenum modeAlpha); +typedef void + (APIENTRYP COGL_PFNGLBLENDEQUATIONPROC) + (GLenum mode); + +typedef void + (APIENTRYP COGL_PFNGLBLENDCOLORPROC) + (GLclampf red, + GLclampf green, + GLclampf blue, + GLclampf alpha); + G_END_DECLS #endif diff --git a/gl/cogl.c b/gl/cogl.c index 8fcd3eabd..608bc364e 100644 --- a/gl/cogl.c +++ b/gl/cogl.c @@ -486,6 +486,13 @@ _cogl_features_init (void) (COGL_PFNGLCLIENTACTIVETEXTUREPROC) cogl_get_proc_address ("glClientActiveTexture"); + ctx->pf_glBlendEquation = + (COGL_PFNGLBLENDEQUATIONPROC) + cogl_get_proc_address ("glBlendEquation"); + ctx->pf_glBlendColor = + (COGL_PFNGLBLENDCOLORPROC) + cogl_get_proc_address ("glBlendColor"); + /* Available in 1.4 */ ctx->pf_glBlendFuncSeparate = (COGL_PFNGLBLENDFUNCSEPARATEPROC) From 8909d6a1298fb756f98bd22a870ee4091bb6414a Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Thu, 4 Jun 2009 12:04:47 +0100 Subject: [PATCH 32/37] [gles/cogl-shader] Fix parameter spec for cogl_shader_get_info_log The stub version of cogl_shader_get_info_log needed to be updated to match the changes to the function signature in 61deeafa. --- gles/cogl-shader.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/gles/cogl-shader.c b/gles/cogl-shader.c index 11cbe0c33..74d0add8e 100644 --- a/gles/cogl-shader.c +++ b/gles/cogl-shader.c @@ -200,11 +200,10 @@ cogl_shader_compile (CoglHandle shader_handle) { } -void -cogl_shader_get_info_log (CoglHandle handle, - size_t size, - char *buffer) +gchar * +cogl_shader_get_info_log (CoglHandle handle) { + return NULL; } CoglShaderType From b7c8f8111e86be48eb440358d13e677ccc29cf19 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Wed, 3 Jun 2009 15:22:42 +0100 Subject: [PATCH 33/37] [cogl-material] Allow setting a layer with an invalid texture handle It was previously possible to create a material layer with no texture by setting some property on it such as the matrix. However it was not possible to get back to that state without removing the layer and recreating it. It is useful to be able to remove the texture to free resources without forgetting the state of the layer so we can put a different texture in later. --- common/cogl-material.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/common/cogl-material.c b/common/cogl-material.c index 85f9f343b..f3e7bb417 100644 --- a/common/cogl-material.c +++ b/common/cogl-material.c @@ -671,7 +671,8 @@ cogl_material_set_layer (CoglHandle material_handle, int n_layers; g_return_if_fail (cogl_is_material (material_handle)); - g_return_if_fail (cogl_is_texture (texture_handle)); + g_return_if_fail (texture_handle == COGL_INVALID_HANDLE + || cogl_is_texture (texture_handle)); material = _cogl_material_pointer_from_handle (material_handle); layer = _cogl_material_get_layer (material_handle, layer_index, TRUE); @@ -692,7 +693,8 @@ cogl_material_set_layer (CoglHandle material_handle, * MAX_COMBINED_TEXTURE_IMAGE_UNITS layers. */ } - cogl_handle_ref (texture_handle); + if (texture_handle) + cogl_handle_ref (texture_handle); if (layer->texture) cogl_handle_unref (layer->texture); From e7e897802925346fdd3e212c425acbf2017027c2 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Thu, 4 Jun 2009 16:04:57 +0100 Subject: [PATCH 34/37] [cogl] Move the texture filters to be a property of the material layer The texture filters are now a property of the material layer rather than the texture object. Whenever a texture is painted with a material it sets the filters on all of the GL textures in the Cogl texture. The filter is cached so that it won't be changed unnecessarily. The automatic mipmap generation has changed so that the mipmaps are only generated when the texture is painted instead of every time the data changes. Changing the texture sets a flag to mark that the mipmaps are dirty. This works better if the FBO extension is available because we can use glGenerateMipmap. If the extension is not available it will temporarily enable automatic mipmap generation and reupload the first pixel of each slice. This requires tracking the data for the first pixel. The COGL_TEXTURE_AUTO_MIPMAP flag has been replaced with COGL_TEXTURE_NO_AUTO_MIPMAP so that it will default to auto-mipmapping. The mipmap generation is now effectively free if you are not using a mipmap filter mode so you would only want to disable it if you had some special reason to generate your own mipmaps. ClutterTexture no longer has to store its own copy of the filter mode. Instead it stores it in the material and the property is directly set and read from that. This fixes problems with the filters getting out of sync when a cogl handle is set on the texture directly. It also avoids the mess of having to rerealize the texture if the filter quality changes to HIGH because Cogl will take of generating the mipmaps if needed. --- cogl-material.h | 80 ++++++++++++ cogl-texture.h | 80 ------------ cogl-types.h | 13 +- common/cogl-material-private.h | 3 + common/cogl-material.c | 59 +++++++++ common/cogl-primitives.c | 3 +- doc/reference/cogl/cogl-sections.txt | 7 +- gl/cogl-context.h | 1 + gl/cogl-defines.h.in | 4 + gl/cogl-texture-private.h | 31 ++++- gl/cogl-texture.c | 189 +++++++++++++++++---------- gl/cogl.c | 7 +- 12 files changed, 318 insertions(+), 159 deletions(-) diff --git a/cogl-material.h b/cogl-material.h index 504c173fa..66fbd8d5c 100644 --- a/cogl-material.h +++ b/cogl-material.h @@ -43,6 +43,52 @@ G_BEGIN_DECLS * blended together. */ +/** + * CoglMaterialFilter: + * @COGL_MATERIAL_FILTER_NEAREST: Measuring in manhatten distance from the, + * current pixel center, use the nearest texture + * texel. + * @COGL_MATERIAL_FILTER_LINEAR: Use the weighted average of the 4 texels + * nearest the current pixel center. + * @COGL_MATERIAL_FILTER_NEAREST_MIPMAP_NEAREST: Select the mimap level whose + * texel size most closely matches + * the current pixel, and use the + * COGL_MATERIAL_FILTER_NEAREST + * criterion. + * @COGL_MATERIAL_FILTER_LINEAR_MIPMAP_NEAREST: Select the mimap level whose + * texel size most closely matches + * the current pixel, and use the + * COGL_MATERIAL_FILTER_LINEAR + * criterion. + * @COGL_MATERIAL_FILTER_NEAREST_MIPMAP_LINEAR: Select the two mimap levels + * whose texel size most closely + * matches the current pixel, use + * the COGL_MATERIAL_FILTER_NEAREST + * criterion on each one and take + * their weighted average. + * @COGL_MATERIAL_FILTER_LINEAR_MIPMAP_LINEAR: Select the two mimap levels + * whose texel size most closely + * matches the current pixel, use + * the COGL_MATERIAL_FILTER_LINEAR + * criterion on each one and take + * their weighted average. + * + * Texture filtering is used whenever the current pixel maps either to more + * than one texture element (texel) or less than one. These filter enums + * correspond to different strategies used to come up with a pixel color, by + * possibly referring to multiple neighbouring texels and taking a weighted + * average or simply using the nearest texel. + */ +typedef enum _CoglMaterialFilter +{ + COGL_MATERIAL_FILTER_NEAREST = GL_NEAREST, + COGL_MATERIAL_FILTER_LINEAR = GL_LINEAR, + COGL_MATERIAL_FILTER_NEAREST_MIPMAP_NEAREST = GL_NEAREST_MIPMAP_NEAREST, + COGL_MATERIAL_FILTER_LINEAR_MIPMAP_NEAREST = GL_LINEAR_MIPMAP_NEAREST, + COGL_MATERIAL_FILTER_NEAREST_MIPMAP_LINEAR = GL_NEAREST_MIPMAP_LINEAR, + COGL_MATERIAL_FILTER_LINEAR_MIPMAP_LINEAR = GL_LINEAR_MIPMAP_LINEAR +} CoglMaterialFilter; + /** * cogl_material_new: * @@ -660,6 +706,40 @@ CoglMaterialLayerType cogl_material_layer_get_type (CoglHandle layer_handle); */ CoglHandle cogl_material_layer_get_texture (CoglHandle layer_handle); +/** + * cogl_material_layer_get_min_filter: + * @layer_handle: a #CoglHandle for a material layer. + * + * Query the currently set downscaling filter for a cogl material layer. + * + * Returns: the current downscaling filter for a cogl material layer. + */ +CoglMaterialFilter cogl_material_layer_get_min_filter (CoglHandle layer_handle); + +/** + * cogl_material_layer_get_mag_filter: + * @layer_handle: a #CoglHandle for a material layer. + * + * Query the currently set downscaling filter for a cogl material layer. + * + * Returns: the current downscaling filter for a cogl material layer. + */ +CoglMaterialFilter cogl_material_layer_get_mag_filter (CoglHandle layer_handle); + +/** + * cogl_material_set_layer_filters: + * @handle: a #CoglHandle to a material. + * @layer_index: the layer number to change. + * @min_filter: the filter used when scaling a texture down. + * @mag_filter: the filter used when magnifying a texture. + * + * Changes the decimation and interpolation filters used when a texture is + * drawn at other scales than 100%. + */ +void cogl_material_set_layer_filters (CoglHandle handle, + gint layer_index, + CoglMaterialFilter min_filter, + CoglMaterialFilter mag_filter); G_END_DECLS diff --git a/cogl-texture.h b/cogl-texture.h index d4cc4e812..15cadc879 100644 --- a/cogl-texture.h +++ b/cogl-texture.h @@ -218,72 +218,6 @@ guint cogl_texture_get_rowstride (CoglHandle handle); */ gint cogl_texture_get_max_waste (CoglHandle handle); -/** - * CoglTextureFilter: - * @COGL_TEXTURE_FILTER_NEAREST: Measuring in manhatten distance from the, - * current pixel center, use the nearest texture - * texel. - * @COGL_TEXTURE_FILTER_LINEAR: Use the weighted average of the 4 texels - * nearest the current pixel center. - * @COGL_TEXTURE_FILTER_NEAREST_MIPMAP_NEAREST: Select the mimap level whose - * texel size most closely matches - * the current pixel, and use the - * COGL_TEXTURE_FILTER_NEAREST - * criterion. - * @COGL_TEXTURE_FILTER_LINEAR_MIPMAP_NEAREST: Select the mimap level whose - * texel size most closely matches - * the current pixel, and use the - * COGL_TEXTURE_FILTER_LINEAR - * criterion. - * @COGL_TEXTURE_FILTER_NEAREST_MIPMAP_LINEAR: Select the two mimap levels - * whose texel size most closely - * matches the current pixel, use - * the COGL_TEXTURE_FILTER_NEAREST - * criterion on each one and take - * their weighted average. - * @COGL_TEXTURE_FILTER_LINEAR_MIPMAP_LINEAR: Select the two mimap levels - * whose texel size most closely - * matches the current pixel, use - * the COGL_TEXTURE_FILTER_LINEAR - * criterion on each one and take - * their weighted average. - * - * Texture filtering is used whenever the current pixel maps either to more - * than one texture element (texel) or less than one. These filter enums - * correspond to different strategies used to come up with a pixel color, by - * possibly referring to multiple neighbouring texels and taking a weighted - * average or simply using the nearest texel. - */ -typedef enum _CoglTextureFilter -{ - COGL_TEXTURE_FILTER_NEAREST = GL_NEAREST, - COGL_TEXTURE_FILTER_LINEAR = GL_LINEAR, - COGL_TEXTURE_FILTER_NEAREST_MIPMAP_NEAREST = GL_NEAREST_MIPMAP_NEAREST, - COGL_TEXTURE_FILTER_LINEAR_MIPMAP_NEAREST = GL_LINEAR_MIPMAP_NEAREST, - COGL_TEXTURE_FILTER_NEAREST_MIPMAP_LINEAR = GL_NEAREST_MIPMAP_LINEAR, - COGL_TEXTURE_FILTER_LINEAR_MIPMAP_LINEAR = GL_LINEAR_MIPMAP_LINEAR -} CoglTextureFilter; - -/** - * cogl_texture_get_min_filter: - * @handle: a #CoglHandle for a texture. - * - * Query the currently set downscaling filter for a cogl texture. - * - * Returns: the current downscaling filter for a cogl texture. - */ -CoglTextureFilter cogl_texture_get_min_filter (CoglHandle handle); - -/** - * cogl_texture_get_mag_filter: - * @handle: a #CoglHandle for a texture. - * - * Query the currently set downscaling filter for a cogl texture. - * - * Returns: the current downscaling filter for a cogl texture. - */ -CoglTextureFilter cogl_texture_get_mag_filter (CoglHandle handle); - /** * cogl_texture_is_sliced: * @handle: a #CoglHandle for a texture. @@ -333,20 +267,6 @@ gint cogl_texture_get_data (CoglHandle handle, guint rowstride, guchar *data); -/** - * cogl_texture_set_filters: - * @handle: a #CoglHandle. - * @min_filter: the filter used when scaling the texture down. - * @mag_filter: the filter used when magnifying the texture. - * - * Changes the decimation and interpolation filters used when the texture is - * drawn at other scales than 100%. - */ -void cogl_texture_set_filters (CoglHandle handle, - CoglTextureFilter min_filter, - CoglTextureFilter mag_filter); - - /** * cogl_texture_set_region: * @handle: a #CoglHandle. diff --git a/cogl-types.h b/cogl-types.h index 3aa6f5c3c..0a1360dde 100644 --- a/cogl-types.h +++ b/cogl-types.h @@ -244,8 +244,11 @@ struct _CoglTextureVertex /** * CoglTextureFlags: * @COGL_TEXTURE_NONE: No flags specified - * @COGL_TEXTURE_AUTO_MIPMAP: Enables the automatic generation of the - * mipmap pyramid from the base level image whenever it is updated + * @COGL_TEXTURE_NO_AUTO_MIPMAP: Disables the automatic generation of + * the mipmap pyramid from the base level image whenever it is + * updated. The mipmaps are only generated when the texture is + * rendered with a mipmap filter so it should be free to leave out + * this flag when using other filtering modes. * @COGL_TEXTURE_NO_SLICING: Disables the slicing of the texture * * Flags to pass to the cogl_texture_new_* family of functions. @@ -253,9 +256,9 @@ struct _CoglTextureVertex * Since: 1.0 */ typedef enum { - COGL_TEXTURE_NONE = 0, - COGL_TEXTURE_AUTO_MIPMAP = 1 << 0, - COGL_TEXTURE_NO_SLICING = 1 << 1 + COGL_TEXTURE_NONE = 0, + COGL_TEXTURE_NO_AUTO_MIPMAP = 1 << 0, + COGL_TEXTURE_NO_SLICING = 1 << 1 } CoglTextureFlags; /** diff --git a/common/cogl-material-private.h b/common/cogl-material-private.h index 9b2170ecf..e61ab97bd 100644 --- a/common/cogl-material-private.h +++ b/common/cogl-material-private.h @@ -68,6 +68,9 @@ struct _CoglMaterialLayer CoglHandle texture; /*!< The texture for this layer, or COGL_INVALID_HANDLE for an empty layer */ + CoglMaterialFilter mag_filter; + CoglMaterialFilter min_filter; + /* Determines how the color of individual texture fragments * are calculated. */ GLint texture_combine_rgb_func; diff --git a/common/cogl-material.c b/common/cogl-material.c index f3e7bb417..66a4b0c96 100644 --- a/common/cogl-material.c +++ b/common/cogl-material.c @@ -637,6 +637,8 @@ _cogl_material_get_layer (CoglMaterial *material, layer_handle = _cogl_material_layer_handle_new (layer); layer->index = index_; layer->flags = COGL_MATERIAL_LAYER_FLAG_DEFAULT_COMBINE; + layer->mag_filter = COGL_MATERIAL_FILTER_LINEAR; + layer->min_filter = COGL_MATERIAL_FILTER_LINEAR; layer->texture = COGL_INVALID_HANDLE; /* Choose the same default combine mode as OpenGL: @@ -1014,6 +1016,15 @@ get_n_args_for_combine_func (GLint func) return 0; } +static gboolean +is_mipmap_filter (CoglMaterialFilter filter) +{ + return (filter == COGL_MATERIAL_FILTER_NEAREST_MIPMAP_NEAREST + || filter == COGL_MATERIAL_FILTER_LINEAR_MIPMAP_NEAREST + || filter == COGL_MATERIAL_FILTER_NEAREST_MIPMAP_LINEAR + || filter == COGL_MATERIAL_FILTER_LINEAR_MIPMAP_LINEAR); +} + static void _cogl_material_layer_flush_gl_sampler_state (CoglMaterialLayer *layer, CoglLayerInfo *gl_layer_info) @@ -1214,6 +1225,13 @@ _cogl_material_flush_layers_gl_state (CoglMaterial *material, GE (glActiveTexture (GL_TEXTURE0 + i)); + _cogl_texture_set_filters (layer->texture, + layer->min_filter, + layer->mag_filter); + if (is_mipmap_filter (layer->min_filter) + || is_mipmap_filter (layer->mag_filter)) + _cogl_texture_ensure_mipmaps (layer->texture); + /* FIXME: We could be more clever here and only bind the texture if it is different from gl_layer_info->gl_texture to avoid redundant GL calls. However a few other places in Cogl and @@ -1474,3 +1492,44 @@ cogl_set_source_texture (CoglHandle texture_handle) cogl_set_source (ctx->default_material); } +CoglMaterialFilter +cogl_material_layer_get_min_filter (CoglHandle layer_handle) +{ + CoglMaterialLayer *layer; + + g_return_val_if_fail (cogl_is_material_layer (layer_handle), 0); + + layer = _cogl_material_layer_pointer_from_handle (layer_handle); + + return layer->min_filter; +} + +CoglMaterialFilter +cogl_material_layer_get_mag_filter (CoglHandle layer_handle) +{ + CoglMaterialLayer *layer; + + g_return_val_if_fail (cogl_is_material_layer (layer_handle), 0); + + layer = _cogl_material_layer_pointer_from_handle (layer_handle); + + return layer->mag_filter; +} + +void +cogl_material_set_layer_filters (CoglHandle handle, + gint layer_index, + CoglMaterialFilter min_filter, + CoglMaterialFilter mag_filter) +{ + CoglMaterial *material; + CoglMaterialLayer *layer; + + g_return_if_fail (cogl_is_material (handle)); + + material = _cogl_material_pointer_from_handle (handle); + layer = _cogl_material_get_layer (material, layer_index, TRUE); + + layer->min_filter = min_filter; + layer->mag_filter = mag_filter; +} diff --git a/common/cogl-primitives.c b/common/cogl-primitives.c index c43fbde49..03fe43180 100644 --- a/common/cogl-primitives.c +++ b/common/cogl-primitives.c @@ -1186,7 +1186,8 @@ cogl_polygon (CoglTextureVertex *vertices, use_sliced_polygon_fallback = TRUE; n_layers = 1; - if (tex->min_filter != GL_NEAREST || tex->mag_filter != GL_NEAREST) + if (cogl_material_layer_get_min_filter (layer) != GL_NEAREST + || cogl_material_layer_get_mag_filter (layer) != GL_NEAREST) { static gboolean warning_seen = FALSE; if (!warning_seen) diff --git a/doc/reference/cogl/cogl-sections.txt b/doc/reference/cogl/cogl-sections.txt index f596ee042..872e02d11 100644 --- a/doc/reference/cogl/cogl-sections.txt +++ b/doc/reference/cogl/cogl-sections.txt @@ -132,12 +132,9 @@ cogl_texture_get_height cogl_texture_get_format cogl_texture_get_rowstride cogl_texture_get_max_waste -cogl_texture_get_min_filter -cogl_texture_get_mag_filter cogl_texture_is_sliced cogl_texture_get_gl_texture cogl_texture_get_data -cogl_texture_set_filters cogl_texture_set_region
@@ -366,8 +363,12 @@ cogl_material_set_layer_combine cogl_material_set_layer_combine_constant cogl_material_set_layer_matrix cogl_material_get_layers +CoglMaterialFilter +cogl_material_set_layer_filters cogl_material_layer_get_type cogl_material_layer_get_texture +cogl_material_layer_get_min_filter +cogl_material_layer_get_mag_filter CoglMaterial CoglMaterialFlags diff --git a/gl/cogl-context.h b/gl/cogl-context.h index 3db4c0e9e..d845a6c12 100644 --- a/gl/cogl-context.h +++ b/gl/cogl-context.h @@ -120,6 +120,7 @@ typedef struct COGL_PFNGLDELETEFRAMEBUFFERSEXTPROC pf_glDeleteFramebuffersEXT; COGL_PFNGLBLITFRAMEBUFFEREXTPROC pf_glBlitFramebufferEXT; COGL_PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC pf_glRenderbufferStorageMultisampleEXT; + COGL_PFNGLGENERATEMIPMAPEXTPROC pf_glGenerateMipmapEXT; COGL_PFNGLCREATEPROGRAMOBJECTARBPROC pf_glCreateProgramObjectARB; COGL_PFNGLCREATESHADEROBJECTARBPROC pf_glCreateShaderObjectARB; diff --git a/gl/cogl-defines.h.in b/gl/cogl-defines.h.in index 4805ea5b3..025b4cad0 100644 --- a/gl/cogl-defines.h.in +++ b/gl/cogl-defines.h.in @@ -773,6 +773,10 @@ typedef void GLsizei width, GLsizei height); +typedef void + (APIENTRYP COGL_PFNGLGENERATEMIPMAPEXTPROC) + (GLenum target); + typedef GLhandleARB (APIENTRYP COGL_PFNGLCREATEPROGRAMOBJECTARBPROC) (void); diff --git a/gl/cogl-texture-private.h b/gl/cogl-texture-private.h index 7cf6fe951..365a47921 100644 --- a/gl/cogl-texture-private.h +++ b/gl/cogl-texture-private.h @@ -30,6 +30,7 @@ typedef struct _CoglTexture CoglTexture; typedef struct _CoglTexSliceSpan CoglTexSliceSpan; typedef struct _CoglSpanIter CoglSpanIter; +typedef struct _CoglTexturePixel CoglTexturePixel; struct _CoglTexSliceSpan { @@ -55,6 +56,18 @@ struct _CoglSpanIter gboolean intersects; }; +/* 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 _CoglTexture { CoglHandleObject _parent; @@ -68,11 +81,17 @@ struct _CoglTexture GArray *slice_y_spans; GArray *slice_gl_handles; gint max_waste; - CoglTextureFilter min_filter; - CoglTextureFilter mag_filter; + GLenum min_filter; + GLenum mag_filter; gboolean is_foreign; GLint wrap_mode; gboolean auto_mipmap; + gboolean mipmaps_dirty; + + /* This holds a copy of the first pixel in each slice. It is only + used to force an automatic update of the mipmaps when + glGenerateMipmap is not available. */ + CoglTexturePixel *first_pixels; }; /* To improve batching of geometry when submitting vertices to OpenGL we @@ -93,6 +112,14 @@ void _cogl_texture_set_wrap_mode_parameter (CoglTexture *tex, GLenum wrap_mode); +void +_cogl_texture_set_filters (CoglHandle handle, + GLenum min_filter, + GLenum mag_filter); + +void +_cogl_texture_ensure_mipmaps (CoglHandle handle); + gboolean _cogl_texture_span_has_waste (CoglTexture *tex, gint x_span_index, diff --git a/gl/cogl-texture.c b/gl/cogl-texture.c index 80e428eba..e2c6c264f 100644 --- a/gl/cogl-texture.c +++ b/gl/cogl-texture.c @@ -49,6 +49,7 @@ #define glDrawRangeElements ctx->pf_glDrawRangeElements #define glActiveTexture ctx->pf_glActiveTexture #define glClientActiveTexture ctx->pf_glClientActiveTexture +#define glGenerateMipmap ctx->pf_glGenerateMipmapEXT #else @@ -247,11 +248,12 @@ _cogl_texture_upload_to_gl (CoglTexture *tex) /* Iterate horizontal slices */ for (x = 0; x < tex->slice_x_spans->len; ++x) { + gint slice_num = y * tex->slice_x_spans->len + x; + x_span = &g_array_index (tex->slice_x_spans, CoglTexSliceSpan, x); /* Pick the gl texture object handle */ - gl_handle = g_array_index (tex->slice_gl_handles, GLuint, - y * tex->slice_x_spans->len + x); + gl_handle = g_array_index (tex->slice_gl_handles, GLuint, slice_num); /* Setup gl alignment to match rowstride and top-left corner */ prep_for_gl_pixels_upload (tex->bitmap.rowstride, @@ -259,6 +261,17 @@ _cogl_texture_upload_to_gl (CoglTexture *tex) y_span->start, bpp); + /* Keep a copy of the first pixel if needed */ + if (tex->first_pixels) + { + memcpy (tex->first_pixels[slice_num].data, + tex->bitmap.data + x_span->start * bpp + + y_span->start * tex->bitmap.rowstride, + bpp); + tex->first_pixels[slice_num].gl_format = tex->gl_format; + tex->first_pixels[slice_num].gl_type = tex->gl_type; + } + /* Upload new image data */ GE( glBindTexture (tex->gl_target, gl_handle) ); @@ -343,6 +356,8 @@ _cogl_texture_upload_to_gl (CoglTexture *tex) if (waste_buf) g_free (waste_buf); + tex->mipmaps_dirty = TRUE; + return TRUE; } @@ -494,6 +509,8 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex, _cogl_span_iter_next (&x_iter), source_x += inter_w ) { + gint slice_num; + /* Discard slices out of the subregion early */ if (!x_iter.intersects) { @@ -516,10 +533,10 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex, local_y = (y_iter.intersect_start - y_iter.pos); + slice_num = y_iter.index * tex->slice_x_spans->len + x_iter.index; + /* Pick slice GL handle */ - gl_handle = g_array_index (tex->slice_gl_handles, GLuint, - y_iter.index * tex->slice_x_spans->len + - x_iter.index); + gl_handle = g_array_index (tex->slice_gl_handles, GLuint, slice_num); /* Setup gl alignment to match rowstride and top-left corner */ prep_for_gl_pixels_upload (source_bmp->rowstride, @@ -527,6 +544,17 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex, source_y, bpp); + /* Keep a copy of the first pixel if needed */ + if (tex->first_pixels && local_x == 0 && local_y == 0) + { + memcpy (tex->first_pixels[slice_num].data, + source_bmp->data + source_x * bpp + + source_y * source_bmp->rowstride, + bpp); + tex->first_pixels[slice_num].gl_format = source_gl_format; + tex->first_pixels[slice_num].gl_type = source_gl_type; + } + /* Upload new image data */ GE( glBindTexture (tex->gl_target, gl_handle) ); @@ -640,6 +668,8 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex, if (waste_buf) g_free (waste_buf); + tex->mipmaps_dirty = TRUE; + return TRUE; } @@ -913,6 +943,14 @@ _cogl_texture_slices_create (CoglTexture *tex) g_array_set_size (tex->slice_gl_handles, n_slices); + /* Allocate some space to store a copy of the first pixel of each + slice. This is only needed to glGenerateMipmap (which is part of + the FBO extension) is not available */ + if (cogl_features_available (COGL_FEATURE_OFFSCREEN)) + tex->first_pixels = NULL; + else + tex->first_pixels = g_new (CoglTexturePixel, n_slices); + /* Wrap mode not yet set */ tex->wrap_mode = GL_FALSE; @@ -941,14 +979,6 @@ _cogl_texture_slices_create (CoglTexture *tex) /* Setup texture parameters */ GE( glBindTexture (tex->gl_target, gl_handles[y * n_x_slices + x]) ); - GE( glTexParameteri (tex->gl_target, GL_TEXTURE_MAG_FILTER, - tex->mag_filter) ); - GE( glTexParameteri (tex->gl_target, GL_TEXTURE_MIN_FILTER, - tex->min_filter) ); - - if (tex->auto_mipmap) - GE( glTexParameteri (tex->gl_target, GL_GENERATE_MIPMAP, - GL_TRUE) ); /* Use a transparent border color so that we can leave the color buffer alone when using texture co-ordinates @@ -985,6 +1015,9 @@ _cogl_texture_slices_free (CoglTexture *tex) g_array_free (tex->slice_gl_handles, TRUE); } + + if (tex->first_pixels != NULL) + g_free (tex->first_pixels); } gboolean @@ -1221,7 +1254,8 @@ cogl_texture_new_with_size (guint width, tex = (CoglTexture*) g_malloc (sizeof (CoglTexture)); tex->is_foreign = FALSE; - tex->auto_mipmap = ((flags & COGL_TEXTURE_AUTO_MIPMAP) != 0); + tex->auto_mipmap = (flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0; + tex->mipmaps_dirty = TRUE; tex->bitmap.width = width; tex->bitmap.height = height; @@ -1239,8 +1273,9 @@ cogl_texture_new_with_size (guint width, else tex->max_waste = COGL_TEXTURE_MAX_WASTE; - tex->min_filter = COGL_TEXTURE_FILTER_NEAREST; - tex->mag_filter = COGL_TEXTURE_FILTER_NEAREST; + /* Unknown filter */ + tex->min_filter = GL_FALSE; + tex->mag_filter = GL_FALSE; /* Find closest GL format match */ tex->bitmap.format = @@ -1285,7 +1320,8 @@ cogl_texture_new_from_data (guint width, tex = (CoglTexture*) g_malloc (sizeof (CoglTexture)); tex->is_foreign = FALSE; - tex->auto_mipmap = ((flags & COGL_TEXTURE_AUTO_MIPMAP) != 0); + tex->auto_mipmap = (flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0; + tex->mipmaps_dirty = TRUE; tex->bitmap.width = width; tex->bitmap.height = height; @@ -1303,8 +1339,9 @@ cogl_texture_new_from_data (guint width, else tex->max_waste = COGL_TEXTURE_MAX_WASTE; - tex->min_filter = COGL_TEXTURE_FILTER_NEAREST; - tex->mag_filter = COGL_TEXTURE_FILTER_NEAREST; + /* Unknown filter */ + tex->min_filter = GL_FALSE; + tex->mag_filter = GL_FALSE; /* FIXME: If upload fails we should set some kind of * error flag but still return texture handle (this @@ -1348,7 +1385,8 @@ cogl_texture_new_from_bitmap (CoglHandle bmp_handle, tex = (CoglTexture*) g_malloc ( sizeof (CoglTexture)); tex->is_foreign = FALSE; - tex->auto_mipmap = ((flags & COGL_TEXTURE_AUTO_MIPMAP) != 0); + tex->auto_mipmap = (flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0; + tex->mipmaps_dirty = TRUE; tex->bitmap = *bmp; tex->bitmap_owner = TRUE; @@ -1363,8 +1401,9 @@ cogl_texture_new_from_bitmap (CoglHandle bmp_handle, else tex->max_waste = COGL_TEXTURE_MAX_WASTE; - tex->min_filter = COGL_TEXTURE_FILTER_NEAREST; - tex->mag_filter = COGL_TEXTURE_FILTER_NEAREST; + /* Unknown filter */ + tex->min_filter = GL_FALSE; + tex->mag_filter = GL_FALSE; /* FIXME: If upload fails we should set some kind of * error flag but still return texture handle if the @@ -1440,8 +1479,6 @@ cogl_texture_new_from_foreign (GLuint gl_handle, GLint gl_int_format = 0; GLint gl_width = 0; GLint gl_height = 0; - GLint gl_min_filter; - GLint gl_mag_filter; GLint gl_gen_mipmap; guint bpp; CoglTexture *tex; @@ -1489,14 +1526,6 @@ cogl_texture_new_from_foreign (GLuint gl_handle, GL_TEXTURE_HEIGHT, &gl_height) ); - GE( glGetTexParameteriv (gl_target, - GL_TEXTURE_MIN_FILTER, - &gl_min_filter) ); - - GE( glGetTexParameteriv (gl_target, - GL_TEXTURE_MAG_FILTER, - &gl_mag_filter) ); - GE( glGetTexParameteriv (gl_target, GL_GENERATE_MIPMAP, &gl_gen_mipmap) ); @@ -1524,6 +1553,7 @@ cogl_texture_new_from_foreign (GLuint gl_handle, /* Setup bitmap info */ tex->is_foreign = TRUE; tex->auto_mipmap = (gl_gen_mipmap == GL_TRUE) ? TRUE : FALSE; + tex->mipmaps_dirty = TRUE; bpp = _cogl_get_format_bpp (format); tex->bitmap.format = format; @@ -1537,8 +1567,9 @@ cogl_texture_new_from_foreign (GLuint gl_handle, tex->gl_format = gl_int_format; tex->gl_type = GL_UNSIGNED_BYTE; - tex->min_filter = gl_min_filter; - tex->mag_filter = gl_mag_filter; + /* Unknown filter */ + tex->min_filter = GL_FALSE; + tex->mag_filter = GL_FALSE; tex->max_waste = 0; /* Wrap mode not yet set */ @@ -1684,36 +1715,10 @@ cogl_texture_get_gl_texture (CoglHandle handle, return TRUE; } -CoglTextureFilter -cogl_texture_get_min_filter (CoglHandle handle) -{ - CoglTexture *tex; - - if (!cogl_is_texture (handle)) - return 0; - - tex = _cogl_texture_pointer_from_handle (handle); - - return tex->min_filter; -} - -CoglTextureFilter -cogl_texture_get_mag_filter (CoglHandle handle) -{ - CoglTexture *tex; - - if (!cogl_is_texture (handle)) - return 0; - - tex = _cogl_texture_pointer_from_handle (handle); - - return tex->mag_filter; -} - void -cogl_texture_set_filters (CoglHandle handle, - CoglTextureFilter min_filter, - CoglTextureFilter mag_filter) +_cogl_texture_set_filters (CoglHandle handle, + GLenum min_filter, + GLenum mag_filter) { CoglTexture *tex; GLuint gl_handle; @@ -1724,14 +1729,18 @@ cogl_texture_set_filters (CoglHandle handle, tex = _cogl_texture_pointer_from_handle (handle); - /* Store new values */ - tex->min_filter = min_filter; - tex->mag_filter = mag_filter; - /* Make sure slices were created */ if (tex->slice_gl_handles == NULL) return; + if (min_filter == tex->min_filter + && mag_filter == tex->mag_filter) + return; + + /* Store new values */ + tex->min_filter = min_filter; + tex->mag_filter = mag_filter; + /* Apply new filters to every slice */ for (i=0; islice_gl_handles->len; ++i) { @@ -1744,6 +1753,52 @@ cogl_texture_set_filters (CoglHandle handle, } } +void +_cogl_texture_ensure_mipmaps (CoglHandle handle) +{ + CoglTexture *tex; + int i; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (!cogl_is_texture (handle)) + return; + + tex = _cogl_texture_pointer_from_handle (handle); + + /* Only update if the mipmaps are dirty */ + if (!tex->auto_mipmap || !tex->mipmaps_dirty) + return; + + /* Make sure slices were created */ + if (tex->slice_gl_handles == NULL) + return; + + /* Regenerate the mipmaps on every slice */ + for (i = 0; i < tex->slice_gl_handles->len; i++) + { + GLuint gl_handle = g_array_index (tex->slice_gl_handles, GLuint, i); + GE( glBindTexture (tex->gl_target, gl_handle) ); + + /* glGenerateMipmap is defined in the FBO extension */ + if (cogl_features_available (COGL_FEATURE_OFFSCREEN)) + GE( glGenerateMipmap (tex->gl_target) ); + else + { + CoglTexturePixel *pixel = tex->first_pixels + i; + /* Temporarily enable automatic mipmap generation and + re-upload the first pixel to cause a regeneration */ + GE( glTexParameteri (tex->gl_target, GL_GENERATE_MIPMAP, GL_TRUE) ); + GE( glTexSubImage2D (tex->gl_target, 0, 0, 0, 1, 1, + pixel->gl_format, pixel->gl_type, + pixel->data) ); + GE( glTexParameteri (tex->gl_target, GL_GENERATE_MIPMAP, GL_FALSE) ); + } + } + + tex->mipmaps_dirty = FALSE; +} + gboolean cogl_texture_set_region (CoglHandle handle, gint src_x, diff --git a/gl/cogl.c b/gl/cogl.c index 608bc364e..748c082ac 100644 --- a/gl/cogl.c +++ b/gl/cogl.c @@ -399,6 +399,10 @@ _cogl_features_init (void) (COGL_PFNGLDELETEFRAMEBUFFERSEXTPROC) cogl_get_proc_address ("glDeleteFramebuffersEXT"); + ctx->pf_glGenerateMipmapEXT = + (COGL_PFNGLGENERATEMIPMAPEXTPROC) + cogl_get_proc_address ("glGenerateMipmapEXT"); + if (ctx->pf_glGenRenderbuffersEXT && ctx->pf_glBindRenderbufferEXT && ctx->pf_glRenderbufferStorageEXT && @@ -407,7 +411,8 @@ _cogl_features_init (void) ctx->pf_glFramebufferTexture2DEXT && ctx->pf_glFramebufferRenderbufferEXT && ctx->pf_glCheckFramebufferStatusEXT && - ctx->pf_glDeleteFramebuffersEXT) + ctx->pf_glDeleteFramebuffersEXT && + ctx->pf_glGenerateMipmapEXT) flags |= COGL_FEATURE_OFFSCREEN; } From c2759846dd79eb7b8380476963b8f74ae0e3bf89 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Thu, 4 Jun 2009 22:10:33 +0100 Subject: [PATCH 35/37] [gles/cogl-shader] Add a missing semicolon cogl_shader_get_info_log was missing a semicolon which broke the build on GLES 2. --- gles/cogl-shader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gles/cogl-shader.c b/gles/cogl-shader.c index 74d0add8e..23109be34 100644 --- a/gles/cogl-shader.c +++ b/gles/cogl-shader.c @@ -103,7 +103,7 @@ gchar * cogl_shader_get_info_log (CoglHandle handle) { CoglShader *shader; - char buffer[512] + char buffer[512]; int len = 0; _COGL_GET_CONTEXT (ctx, NULL); From f259deafce304b846313305f6fa8cdb235d5a4cc Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Thu, 4 Jun 2009 22:12:33 +0100 Subject: [PATCH 36/37] Update the GLES backend to have the layer filters in the material This reflects the changes made in 54d8aadf1d86 for the GLES backend. --- gles/cogl-texture-private.h | 31 +++++- gles/cogl-texture.c | 192 ++++++++++++++++++++++-------------- 2 files changed, 147 insertions(+), 76 deletions(-) diff --git a/gles/cogl-texture-private.h b/gles/cogl-texture-private.h index 7cf6fe951..365a47921 100644 --- a/gles/cogl-texture-private.h +++ b/gles/cogl-texture-private.h @@ -30,6 +30,7 @@ typedef struct _CoglTexture CoglTexture; typedef struct _CoglTexSliceSpan CoglTexSliceSpan; typedef struct _CoglSpanIter CoglSpanIter; +typedef struct _CoglTexturePixel CoglTexturePixel; struct _CoglTexSliceSpan { @@ -55,6 +56,18 @@ struct _CoglSpanIter gboolean intersects; }; +/* 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 _CoglTexture { CoglHandleObject _parent; @@ -68,11 +81,17 @@ struct _CoglTexture GArray *slice_y_spans; GArray *slice_gl_handles; gint max_waste; - CoglTextureFilter min_filter; - CoglTextureFilter mag_filter; + GLenum min_filter; + GLenum mag_filter; gboolean is_foreign; GLint wrap_mode; gboolean auto_mipmap; + gboolean mipmaps_dirty; + + /* This holds a copy of the first pixel in each slice. It is only + used to force an automatic update of the mipmaps when + glGenerateMipmap is not available. */ + CoglTexturePixel *first_pixels; }; /* To improve batching of geometry when submitting vertices to OpenGL we @@ -93,6 +112,14 @@ void _cogl_texture_set_wrap_mode_parameter (CoglTexture *tex, GLenum wrap_mode); +void +_cogl_texture_set_filters (CoglHandle handle, + GLenum min_filter, + GLenum mag_filter); + +void +_cogl_texture_ensure_mipmaps (CoglHandle handle); + gboolean _cogl_texture_span_has_waste (CoglTexture *tex, gint x_span_index, diff --git a/gles/cogl-texture.c b/gles/cogl-texture.c index 99a18f154..1929184c0 100644 --- a/gles/cogl-texture.c +++ b/gles/cogl-texture.c @@ -225,11 +225,12 @@ _cogl_texture_upload_to_gl (CoglTexture *tex) /* Iterate horizontal slices */ for (x = 0; x < tex->slice_x_spans->len; ++x) { + gint slice_num = y * tex->slice_x_spans->len + x; + x_span = &g_array_index (tex->slice_x_spans, CoglTexSliceSpan, x); /* Pick the gl texture object handle */ - gl_handle = g_array_index (tex->slice_gl_handles, GLuint, - y * tex->slice_x_spans->len + x); + gl_handle = g_array_index (tex->slice_gl_handles, GLuint, slice_num); /* FIXME: might optimize by not copying to intermediate slice bitmap when source rowstride = bpp * width and the texture @@ -258,6 +259,16 @@ _cogl_texture_upload_to_gl (CoglTexture *tex) slice_bmp.width, slice_bmp.height); + /* Keep a copy of the first pixel if needed */ + if (tex->first_pixels) + { + memcpy (tex->first_pixels[slice_num].data, + slice_bmp.data, + bpp); + tex->first_pixels[slice_num].gl_format = tex->gl_format; + tex->first_pixels[slice_num].gl_type = tex->gl_type; + } + /* Upload new image data */ GE( cogl_gles2_wrapper_bind_texture (tex->gl_target, gl_handle, tex->gl_intformat) ); @@ -338,9 +349,6 @@ _cogl_texture_upload_to_gl (CoglTexture *tex) waste_buf) ); } - if (tex->auto_mipmap) - cogl_wrap_glGenerateMipmap (tex->gl_target); - /* Free temp bitmap */ g_free (slice_bmp.data); } @@ -349,6 +357,8 @@ _cogl_texture_upload_to_gl (CoglTexture *tex) if (waste_buf) g_free (waste_buf); + tex->mipmaps_dirty = TRUE; + return TRUE; } @@ -624,6 +634,8 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex, _cogl_span_iter_next (&x_iter), source_x += inter_w ) { + gint slice_num; + /* Discard slices out of the subregion early */ if (!x_iter.intersects) { @@ -646,10 +658,10 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex, local_y = (y_iter.intersect_start - y_iter.pos); + slice_num = y_iter.index * tex->slice_x_spans->len + x_iter.index; + /* Pick slice GL handle */ - gl_handle = g_array_index (tex->slice_gl_handles, GLuint, - y_iter.index * tex->slice_x_spans->len + - x_iter.index); + gl_handle = g_array_index (tex->slice_gl_handles, GLuint, slice_num); /* FIXME: might optimize by not copying to intermediate slice bitmap when source rowstride = bpp * width and the texture @@ -678,6 +690,15 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex, slice_bmp.width, slice_bmp.height); + /* Keep a copy of the first pixel if needed */ + if (tex->first_pixels && local_x == 0 && local_y == 0) + { + memcpy (tex->first_pixels[slice_num].data, + slice_bmp.data, bpp); + tex->first_pixels[slice_num].gl_format = source_gl_format; + tex->first_pixels[slice_num].gl_type = source_gl_type; + } + /* Upload new image data */ GE( cogl_gles2_wrapper_bind_texture (tex->gl_target, gl_handle, tex->gl_intformat) ); @@ -787,9 +808,6 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex, waste_buf) ); } - if (tex->auto_mipmap) - cogl_wrap_glGenerateMipmap (tex->gl_target); - /* Free temp bitmap */ g_free (slice_bmp.data); } @@ -798,6 +816,8 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex, if (waste_buf) g_free (waste_buf); + tex->mipmaps_dirty = TRUE; + return TRUE; } @@ -1055,6 +1075,14 @@ _cogl_texture_slices_create (CoglTexture *tex) g_array_set_size (tex->slice_gl_handles, n_slices); + /* Allocate some space to store a copy of the first pixel of each + slice. This is only needed to glGenerateMipmap (which is part of + the FBO extension) is not available */ + if (cogl_features_available (COGL_FEATURE_OFFSCREEN)) + tex->first_pixels = NULL; + else + tex->first_pixels = g_new (CoglTexturePixel, n_slices); + /* Wrap mode not yet set */ tex->wrap_mode = GL_FALSE; @@ -1085,20 +1113,11 @@ _cogl_texture_slices_create (CoglTexture *tex) GE( cogl_gles2_wrapper_bind_texture (tex->gl_target, gl_handles[y * n_x_slices + x], tex->gl_intformat) ); - GE( glTexParameteri (tex->gl_target, GL_TEXTURE_MAG_FILTER, - tex->mag_filter) ); - GE( glTexParameteri (tex->gl_target, GL_TEXTURE_MIN_FILTER, - tex->min_filter) ); - GE( glTexParameteri (tex->gl_target, GL_TEXTURE_WRAP_S, tex->wrap_mode) ); GE( glTexParameteri (tex->gl_target, GL_TEXTURE_WRAP_T, tex->wrap_mode) ); - if (tex->auto_mipmap) - GE( glTexParameteri (tex->gl_target, GL_GENERATE_MIPMAP, - GL_TRUE) ); - /* Pass NULL data to init size and internal format */ GE( glTexImage2D (tex->gl_target, 0, tex->gl_intformat, x_span->size, y_span->size, 0, @@ -1128,6 +1147,9 @@ _cogl_texture_slices_free (CoglTexture *tex) g_array_free (tex->slice_gl_handles, TRUE); } + + if (tex->first_pixels != NULL) + g_free (tex->first_pixels); } gboolean @@ -1307,7 +1329,8 @@ cogl_texture_new_with_size (guint width, tex = (CoglTexture*) g_malloc (sizeof (CoglTexture)); tex->is_foreign = FALSE; - tex->auto_mipmap = ((flags & COGL_TEXTURE_AUTO_MIPMAP) != 0); + tex->auto_mipmap = (flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0; + tex->mipmaps_dirty = TRUE; tex->bitmap.width = width; tex->bitmap.height = height; @@ -1325,8 +1348,9 @@ cogl_texture_new_with_size (guint width, else tex->max_waste = COGL_TEXTURE_MAX_WASTE; - tex->min_filter = CGL_NEAREST; - tex->mag_filter = CGL_NEAREST; + /* Unknown filter */ + tex->min_filter = GL_FALSE; + tex->mag_filter = GL_FALSE; /* Find closest GL format match */ tex->bitmap.format = @@ -1371,7 +1395,8 @@ cogl_texture_new_from_data (guint width, tex = (CoglTexture*) g_malloc (sizeof (CoglTexture)); tex->is_foreign = FALSE; - tex->auto_mipmap = ((flags & COGL_TEXTURE_AUTO_MIPMAP) != 0); + tex->auto_mipmap = (flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0; + tex->mipmaps_dirty = TRUE; tex->bitmap.width = width; tex->bitmap.height = height; @@ -1389,8 +1414,9 @@ cogl_texture_new_from_data (guint width, else tex->max_waste = COGL_TEXTURE_MAX_WASTE; - tex->min_filter = CGL_NEAREST; - tex->mag_filter = CGL_NEAREST; + /* Unknown filter */ + tex->min_filter = GL_FALSE; + tex->mag_filter = GL_FALSE; /* FIXME: If upload fails we should set some kind of * error flag but still return texture handle (this @@ -1432,7 +1458,8 @@ cogl_texture_new_from_bitmap (CoglHandle bmp_handle, tex = (CoglTexture*) g_malloc ( sizeof (CoglTexture)); tex->is_foreign = FALSE; - tex->auto_mipmap = ((flags & COGL_TEXTURE_AUTO_MIPMAP) != 0); + tex->auto_mipmap = (flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0; + tex->mipmaps_dirty = TRUE; tex->bitmap = *bmp; tex->bitmap_owner = TRUE; @@ -1447,8 +1474,9 @@ cogl_texture_new_from_bitmap (CoglHandle bmp_handle, else tex->max_waste = COGL_TEXTURE_MAX_WASTE; - tex->min_filter = CGL_NEAREST; - tex->mag_filter = CGL_NEAREST; + /* Unknown filter */ + tex->min_filter = GL_FALSE; + tex->mag_filter = GL_FALSE; /* FIXME: If upload fails we should set some kind of * error flag but still return texture handle if the @@ -1524,8 +1552,6 @@ cogl_texture_new_from_foreign (GLuint gl_handle, GLint gl_int_format = 0; GLint gl_width = 0; GLint gl_height = 0; - GLint gl_min_filter; - GLint gl_mag_filter; GLint gl_gen_mipmap; guint bpp; CoglTexture *tex; @@ -1572,14 +1598,6 @@ cogl_texture_new_from_foreign (GLuint gl_handle, gl_height = height + y_pot_waste; #endif - GE( glGetTexParameteriv (gl_target, - GL_TEXTURE_MIN_FILTER, - &gl_min_filter) ); - - GE( glGetTexParameteriv (gl_target, - GL_TEXTURE_MAG_FILTER, - &gl_mag_filter) ); - GE( glGetTexParameteriv (gl_target, GL_GENERATE_MIPMAP, &gl_gen_mipmap) ); @@ -1610,6 +1628,7 @@ cogl_texture_new_from_foreign (GLuint gl_handle, /* Setup bitmap info */ tex->is_foreign = TRUE; tex->auto_mipmap = (gl_gen_mipmap == GL_TRUE) ? TRUE : FALSE; + tex->mipmaps_dirty = TRUE; bpp = _cogl_get_format_bpp (format); tex->bitmap.format = format; @@ -1623,8 +1642,9 @@ cogl_texture_new_from_foreign (GLuint gl_handle, tex->gl_format = gl_int_format; tex->gl_type = GL_UNSIGNED_BYTE; - tex->min_filter = gl_min_filter; - tex->mag_filter = gl_mag_filter; + /* Unknown filter */ + tex->min_filter = GL_FALSE; + tex->mag_filter = GL_FALSE; tex->max_waste = 0; /* Wrap mode not yet set */ @@ -1770,36 +1790,10 @@ cogl_texture_get_gl_texture (CoglHandle handle, return TRUE; } -CoglTextureFilter -cogl_texture_get_min_filter (CoglHandle handle) -{ - CoglTexture *tex; - - if (!cogl_is_texture (handle)) - return 0; - - tex = _cogl_texture_pointer_from_handle (handle); - - return tex->min_filter; -} - -CoglTextureFilter -cogl_texture_get_mag_filter (CoglHandle handle) -{ - CoglTexture *tex; - - if (!cogl_is_texture (handle)) - return 0; - - tex = _cogl_texture_pointer_from_handle (handle); - - return tex->mag_filter; -} - void -cogl_texture_set_filters (CoglHandle handle, - CoglTextureFilter min_filter, - CoglTextureFilter mag_filter) +_cogl_texture_set_filters (CoglHandle handle, + GLenum min_filter, + GLenum mag_filter) { CoglTexture *tex; GLuint gl_handle; @@ -1810,14 +1804,18 @@ cogl_texture_set_filters (CoglHandle handle, tex = _cogl_texture_pointer_from_handle (handle); - /* Store new values */ - tex->min_filter = min_filter; - tex->mag_filter = mag_filter; - /* Make sure slices were created */ if (tex->slice_gl_handles == NULL) return; + if (min_filter == tex->min_filter + && mag_filter == tex->mag_filter) + return; + + /* Store new values */ + tex->min_filter = min_filter; + tex->mag_filter = mag_filter; + /* Apply new filters to every slice */ for (i=0; islice_gl_handles->len; ++i) { @@ -1830,6 +1828,52 @@ cogl_texture_set_filters (CoglHandle handle, } } +void +_cogl_texture_ensure_mipmaps (CoglHandle handle) +{ + CoglTexture *tex; + int i; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (!cogl_is_texture (handle)) + return; + + tex = _cogl_texture_pointer_from_handle (handle); + + /* Only update if the mipmaps are dirty */ + if (!tex->auto_mipmap || !tex->mipmaps_dirty) + return; + + /* Make sure slices were created */ + if (tex->slice_gl_handles == NULL) + return; + + /* Regenerate the mipmaps on every slice */ + for (i = 0; i < tex->slice_gl_handles->len; i++) + { + GLuint gl_handle = g_array_index (tex->slice_gl_handles, GLuint, i); + GE( glBindTexture (tex->gl_target, gl_handle) ); + + /* glGenerateMipmap is defined in the FBO extension */ + if (cogl_features_available (COGL_FEATURE_OFFSCREEN)) + GE( cogl_wrap_glGenerateMipmap (tex->gl_target) ); + else + { + CoglTexturePixel *pixel = tex->first_pixels + i; + /* Temporarily enable automatic mipmap generation and + re-upload the first pixel to cause a regeneration */ + GE( glTexParameteri (tex->gl_target, GL_GENERATE_MIPMAP, GL_TRUE) ); + GE( glTexSubImage2D (tex->gl_target, 0, 0, 0, 1, 1, + pixel->gl_format, pixel->gl_type, + pixel->data) ); + GE( glTexParameteri (tex->gl_target, GL_GENERATE_MIPMAP, GL_FALSE) ); + } + } + + tex->mipmaps_dirty = FALSE; +} + gboolean cogl_texture_set_region (CoglHandle handle, gint src_x, From b177d24667a7be2f1a54297b8e7641ca58ff0321 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Thu, 4 Jun 2009 22:20:18 +0100 Subject: [PATCH 37/37] [cogl-primitives] Fix an unused variable warning when building GLES The 'tex' variable is only used if #ifdef'd GL code so it was throwing an error under GLES. The variable is now moved into a block inside the #ifdef. --- common/cogl-primitives.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/common/cogl-primitives.c b/common/cogl-primitives.c index 03fe43180..598015521 100644 --- a/common/cogl-primitives.c +++ b/common/cogl-primitives.c @@ -1158,7 +1158,6 @@ cogl_polygon (CoglTextureVertex *vertices, { CoglHandle layer = (CoglHandle)tmp->data; CoglHandle tex_handle = cogl_material_layer_get_texture (layer); - CoglTexture *tex = _cogl_texture_pointer_from_handle (tex_handle); if (i == 0 && cogl_texture_is_sliced (tex_handle)) { @@ -1201,11 +1200,14 @@ cogl_polygon (CoglTextureVertex *vertices, } #ifdef HAVE_COGL_GL - /* Temporarily change the wrapping mode on all of the slices to use - * a transparent border - * XXX: it's doesn't look like we save/restore this, like the comment - * implies? */ - _cogl_texture_set_wrap_mode_parameter (tex, GL_CLAMP_TO_BORDER); + { + CoglTexture *tex = _cogl_texture_pointer_from_handle (tex_handle); + /* Temporarily change the wrapping mode on all of the slices to use + * a transparent border + * XXX: it's doesn't look like we save/restore this, like + * the comment implies? */ + _cogl_texture_set_wrap_mode_parameter (tex, GL_CLAMP_TO_BORDER); + } #endif break; }