/* Now we can safely assume we have a valid GL context and can
* start issueing cogl commands
*/
+ /* - will call to backend and cogl */
+ _clutter_feature_init ();
/*
* Resolution requires display to be open, so can only be queried after
/* Initiate event collection */
_clutter_backend_init_events (ctx->backend);
- /* finally features - will call to backend and cogl */
- _clutter_feature_init ();
-
clutter_is_initialized = TRUE;
ctx->is_initialized = TRUE;
$(srcdir)/cogl-spans.c \
$(srcdir)/cogl-journal-private.h \
$(srcdir)/cogl-journal.c \
+ $(srcdir)/cogl-draw-buffer-private.h \
+ $(srcdir)/cogl-draw-buffer.c \
$(BUILT_SOURCES) \
$(NULL)
#include "cogl-primitives.h"
#include "cogl-context.h"
#include "cogl-internal.h"
+#include "cogl-draw-buffer-private.h"
/* These are defined in the particular backend (float in GL vs fixed
in GL ES) */
float width,
float height)
{
- CoglClipStackEntryWindowRect *entry;
+ CoglHandle draw_buffer;
+ CoglClipStackState *clip_state;
CoglClipStack *stack;
- float v[4];
+ CoglClipStackEntryWindowRect *entry;
+ float viewport_height;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
- stack = (CoglClipStack *) ctx->clip.stacks->data;
+ /* We don't log clip stack changes in the journal so we must flush
+ * it before making modifications */
+ _cogl_journal_flush ();
- cogl_get_viewport (v);
+ draw_buffer = _cogl_get_draw_buffer ();
+ clip_state = _cogl_draw_buffer_get_clip_state (draw_buffer);
+
+ stack = clip_state->stacks->data;
+
+ viewport_height = _cogl_draw_buffer_get_viewport_height (draw_buffer);
entry = g_slice_new (CoglClipStackEntryWindowRect);
* with (0,0) at bottom left. */
entry->type = COGL_CLIP_STACK_WINDOW_RECT;
entry->x0 = x_offset;
- entry->y0 = v[3] - y_offset - height;
+ entry->y0 = viewport_height - y_offset - height;
entry->x1 = x_offset + width;
- entry->y1 = v[3] - y_offset;
+ entry->y1 = viewport_height - y_offset;
/* Store it in the stack */
stack->stack_top = g_list_prepend (stack->stack_top, entry);
- ctx->clip.stack_dirty = TRUE;
+ clip_state->stack_dirty = TRUE;
}
/* Scale from OpenGL <-1,1> coordinates system to window coordinates
float width,
float height)
{
- CoglClipStackEntryRect *entry;
+ CoglHandle draw_buffer;
+ CoglClipStackState *clip_state;
CoglClipStack *stack;
+ CoglClipStackEntryRect *entry;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
+ /* We don't log clip stack changes in the journal so we must flush
+ * it before making modifications */
+ _cogl_journal_flush ();
+
/* Try and catch window space rectangles so we can redirect to
* cogl_clip_push_window_rect which will use scissoring. */
if (try_pushing_rect_as_window_rect (x_offset, y_offset, width, height))
return;
- stack = (CoglClipStack *) ctx->clip.stacks->data;
+ draw_buffer = _cogl_get_draw_buffer ();
+ clip_state = _cogl_draw_buffer_get_clip_state (draw_buffer);
+
+ stack = clip_state->stacks->data;
entry = g_slice_new (CoglClipStackEntryRect);
/* Store it in the stack */
stack->stack_top = g_list_prepend (stack->stack_top, entry);
- ctx->clip.stack_dirty = TRUE;
+ clip_state->stack_dirty = TRUE;
}
void
cogl_clip_push_from_path_preserve (void)
{
- CoglClipStackEntryPath *entry;
+ CoglHandle draw_buffer;
+ CoglClipStackState *clip_state;
CoglClipStack *stack;
+ CoglClipStackEntryPath *entry;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
- stack = (CoglClipStack *) ctx->clip.stacks->data;
+ /* We don't log clip stack changes in the journal so we must flush
+ * it before making modifications */
+ _cogl_journal_flush ();
+
+ draw_buffer = _cogl_get_draw_buffer ();
+ clip_state = _cogl_draw_buffer_get_clip_state (draw_buffer);
+
+ stack = clip_state->stacks->data;
entry = g_malloc (sizeof (CoglClipStackEntryPath)
+ sizeof (CoglPathNode) * (ctx->path_nodes->len - 1));
/* Store it in the stack */
stack->stack_top = g_list_prepend (stack->stack_top, entry);
- ctx->clip.stack_dirty = TRUE;
+ clip_state->stack_dirty = TRUE;
}
void
cogl_path_new ();
}
-void
-cogl_clip_pop (void)
+static void
+_cogl_clip_pop_real (CoglClipStackState *clip_state)
{
- gpointer entry;
CoglClipStack *stack;
+ gpointer entry;
CoglClipStackEntryType type;
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+ /* We don't log clip stack changes in the journal so we must flush
+ * it before making modifications */
+ _cogl_journal_flush ();
- stack = (CoglClipStack *) ctx->clip.stacks->data;
+ stack = clip_state->stacks->data;
g_return_if_fail (stack->stack_top != NULL);
stack->stack_top = g_list_delete_link (stack->stack_top,
stack->stack_top);
- ctx->clip.stack_dirty = TRUE;
+ clip_state->stack_dirty = TRUE;
+}
+
+void
+cogl_clip_pop (void)
+{
+ CoglHandle draw_buffer;
+ CoglClipStackState *clip_state;
+
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+ draw_buffer = _cogl_get_draw_buffer ();
+ clip_state = _cogl_draw_buffer_get_clip_state (draw_buffer);
+
+ _cogl_clip_pop_real (clip_state);
}
void
-_cogl_clip_stack_rebuild (void)
+_cogl_flush_clip_state (CoglClipStackState *clip_state)
{
- int has_clip_planes = cogl_features_available (COGL_FEATURE_FOUR_CLIP_PLANES);
+ CoglClipStack *stack;
+ int has_clip_planes;
gboolean using_clip_planes = FALSE;
gboolean using_stencil_buffer = FALSE;
GList *node;
- CoglClipStack *stack;
gint scissor_x0 = 0;
gint scissor_y0 = 0;
gint scissor_x1 = G_MAXINT;
gint scissor_y1 = G_MAXINT;
- CoglMatrixStack *modelview_stack;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+ CoglMatrixStack *modelview_stack =
+ _cogl_draw_buffer_get_modelview_stack (_cogl_get_draw_buffer ());
- modelview_stack = ctx->modelview_stack;
+ if (!clip_state->stack_dirty)
+ return;
/* The current primitive journal does not support tracking changes to the
* clip stack... */
_cogl_journal_flush ();
- stack = (CoglClipStack *) ctx->clip.stacks->data;
+ /* XXX: the handling of clipping is quite complex. It may involve use of
+ * the Cogl Journal or other Cogl APIs which may end up recursively
+ * wanting to ensure the clip state is flushed. We need to ensure we
+ * don't recurse infinitely...
+ */
+ clip_state->stack_dirty = FALSE;
+
+ has_clip_planes = cogl_features_available (COGL_FEATURE_FOUR_CLIP_PLANES);
+
+ stack = clip_state->stacks->data;
- ctx->clip.stack_dirty = FALSE;
- ctx->clip.stencil_used = FALSE;
+ clip_state->stencil_used = FALSE;
_cogl_disable_clip_planes ();
_cogl_disable_stencil_buffer ();
scissor_y1 - scissor_y0));
}
- ctx->clip.stencil_used = using_stencil_buffer;
+ clip_state->stencil_used = using_stencil_buffer;
}
+/* XXX: This should never have been made public API! */
void
cogl_clip_ensure (void)
{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+ CoglClipStackState *clip_state;
- if (ctx->clip.stack_dirty)
- _cogl_clip_stack_rebuild ();
+ clip_state = _cogl_draw_buffer_get_clip_state (_cogl_get_draw_buffer ());
+ _cogl_flush_clip_state (clip_state);
}
-void
-cogl_clip_stack_save (void)
+static void
+_cogl_clip_stack_save_real (CoglClipStackState *clip_state)
{
CoglClipStack *stack;
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+ /* We don't log clip stack changes in the journal so we must flush
+ * it before making modifications */
+ _cogl_journal_flush ();
stack = g_slice_new (CoglClipStack);
stack->stack_top = NULL;
- ctx->clip.stacks = g_slist_prepend (ctx->clip.stacks, stack);
-
- ctx->clip.stack_dirty = TRUE;
+ clip_state->stacks = g_slist_prepend (clip_state->stacks, stack);
+ clip_state->stack_dirty = TRUE;
}
void
-cogl_clip_stack_restore (void)
+cogl_clip_stack_save (void)
{
- CoglClipStack *stack;
+ CoglHandle draw_buffer;
+ CoglClipStackState *clip_state;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
- g_return_if_fail (ctx->clip.stacks != NULL);
+ draw_buffer = _cogl_get_draw_buffer ();
+ clip_state = _cogl_draw_buffer_get_clip_state (draw_buffer);
+
+ _cogl_clip_stack_save_real (clip_state);
+}
+
+static void
+_cogl_clip_stack_restore_real (CoglClipStackState *clip_state)
+{
+ CoglClipStack *stack;
+
+ g_return_if_fail (clip_state->stacks != NULL);
- stack = (CoglClipStack *) ctx->clip.stacks->data;
+ /* We don't log clip stack changes in the journal so we must flush
+ * it before making modifications */
+ _cogl_journal_flush ();
+
+ stack = clip_state->stacks->data;
/* Empty the current stack */
while (stack->stack_top)
- cogl_clip_pop ();
+ _cogl_clip_pop_real (clip_state);
/* Revert to an old stack */
g_slice_free (CoglClipStack, stack);
- ctx->clip.stacks = g_slist_delete_link (ctx->clip.stacks,
- ctx->clip.stacks);
+ clip_state->stacks = g_slist_delete_link (clip_state->stacks,
+ clip_state->stacks);
- ctx->clip.stack_dirty = TRUE;
+ clip_state->stack_dirty = TRUE;
}
void
-_cogl_clip_stack_state_init (void)
+cogl_clip_stack_restore (void)
{
+ CoglHandle draw_buffer;
+ CoglClipStackState *clip_state;
+
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
- ctx->clip.stacks = NULL;
- ctx->clip.stack_dirty = TRUE;
+ draw_buffer = _cogl_get_draw_buffer ();
+ clip_state = _cogl_draw_buffer_get_clip_state (draw_buffer);
- /* Add an intial stack */
- cogl_clip_stack_save ();
+ _cogl_clip_stack_restore_real (clip_state);
}
void
-_cogl_clip_stack_state_destroy (void)
+_cogl_clip_stack_state_init (CoglClipStackState *clip_state)
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
+ clip_state->stacks = NULL;
+ clip_state->stack_dirty = TRUE;
+
+ /* Add an intial stack */
+ _cogl_clip_stack_save_real (clip_state);
+}
+
+void
+_cogl_clip_stack_state_destroy (CoglClipStackState *clip_state)
+{
/* Destroy all of the stacks */
- while (ctx->clip.stacks)
- cogl_clip_stack_restore ();
+ while (clip_state->stacks)
+ _cogl_clip_stack_restore_real (clip_state);
}
+
+void
+_cogl_clip_stack_state_dirty (CoglClipStackState *clip_state)
+{
+ clip_state->stack_dirty = TRUE;
+}
+
gboolean stencil_used;
};
-void _cogl_clip_stack_state_init (void);
-void _cogl_clip_stack_state_destroy (void);
-void _cogl_clip_stack_rebuild (void);
-void _cogl_clip_stack_merge (void);
+void _cogl_clip_stack_state_init (CoglClipStackState *state);
+void _cogl_clip_stack_state_destroy (CoglClipStackState *state);
+void _cogl_clip_stack_state_dirty (CoglClipStackState *state);
+
+void _cogl_flush_clip_state (CoglClipStackState *clip_state);
#endif /* __COGL_CLIP_STACK_H */
#include "cogl-journal-private.h"
#include "cogl-texture-private.h"
#include "cogl-material-private.h"
+#include "cogl-draw-buffer-private.h"
#include <string.h>
{
GLubyte default_texture_data[] = { 0xff, 0xff, 0xff, 0x0 };
gulong enable_flags = 0;
- CoglDrawBufferState *draw_buffer;
+ CoglHandle window_buffer;
if (_context != NULL)
return FALSE;
_context->indirect = gl_is_indirect;
_context->flushed_matrix_mode = COGL_MATRIX_MODELVIEW;
- _context->modelview_stack = _cogl_matrix_stack_new ();
- _context->projection_stack = _cogl_matrix_stack_new ();
_context->texture_units = NULL;
_context->default_material = cogl_material_new ();
sizeof (CoglLayerInfo));
_context->n_texcoord_arrays_enabled = 0;
- draw_buffer = g_slice_new0 (CoglDrawBufferState);
- draw_buffer->target = COGL_WINDOW_BUFFER;
- draw_buffer->offscreen = COGL_INVALID_HANDLE;
- _context->draw_buffer_stack =
- g_slist_prepend (NULL, draw_buffer);
+ _context->draw_buffer_stack = _cogl_create_draw_buffer_stack ();
+ window_buffer = _cogl_onscreen_new ();
+ /* XXX: When setting up the window buffer, cogl_set_draw_buffer
+ * assumes that the handle can be found in ctx->window_buffer */
+ _context->window_buffer = window_buffer;
+ cogl_set_draw_buffer (COGL_WINDOW_BUFFER, 0/* ignored */);
+ _context->dirty_bound_framebuffer = TRUE;
+ _context->dirty_viewport = TRUE;
_context->path_nodes = g_array_new (FALSE, FALSE, sizeof (CoglPathNode));
_context->last_path = 0;
_context->in_begin_gl_block = FALSE;
- _context->viewport_width = 0;
- _context->viewport_height = 0;
-
_context->quad_indices_byte = COGL_INVALID_HANDLE;
_context->quad_indices_short = COGL_INVALID_HANDLE;
_context->quad_indices_short_len = 0;
_context->texture_download_material = COGL_INVALID_HANDLE;
- /* Initialise the clip stack */
- _cogl_clip_stack_state_init ();
-
/* Initialise the driver specific state */
+ /* TODO: combine these two into one function */
_cogl_create_context_driver (_context);
+ _cogl_features_init ();
/* Create default textures used for fall backs */
_context->default_gl_texture_2d_tex =
void
_cogl_destroy_context ()
{
+
if (_context == NULL)
return;
- _cogl_clip_stack_state_destroy ();
-
- _cogl_matrix_stack_destroy (_context->modelview_stack);
- _cogl_matrix_stack_destroy (_context->projection_stack);
-
_cogl_destroy_texture_units ();
+ _cogl_free_draw_buffer_stack (_context->draw_buffer_stack);
+
if (_context->path_nodes)
g_array_free (_context->path_nodes, TRUE);
typedef struct
{
- CoglBufferTarget target;
- CoglHandle offscreen;
-} CoglDrawBufferState;
-
-typedef struct
-{
/* Features cache */
CoglFeatureFlags feature_flags;
gboolean features_cached;
/* Client-side matrix stack or NULL if none */
CoglMatrixMode flushed_matrix_mode;
- CoglMatrixStack *projection_stack;
- CoglMatrixStack *modelview_stack;
-
GList *texture_units;
/* Cache of inverse projection matrix */
GArray *current_layers;
guint n_texcoord_arrays_enabled;
- /* Framebuffer objects */
+ /* Draw Buffers */
GSList *draw_buffer_stack;
-
- /* Clip stack */
- CoglClipStackState clip;
+ CoglHandle window_buffer;
+ gboolean dirty_bound_framebuffer;
+ gboolean dirty_viewport;
/* Primitives */
floatVec2 path_start;
gboolean in_begin_gl_block;
- guint viewport_width;
- guint viewport_height;
-
CoglHandle texture_download_material;
CoglContextDriver drv;
--- /dev/null
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2007,2008,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.
+ */
+
+#ifndef __COGL_DRAW_BUFFER_PRIVATE_H
+#define __COGL_DRAW_BUFFER_PRIVATE_H
+
+#include "cogl-handle.h"
+#include "cogl-matrix-stack.h"
+#include "cogl-clip-stack.h"
+
+typedef enum _CoglDrawBufferType {
+ COGL_DRAW_BUFFER_TYPE_ONSCREEN,
+ COGL_DRAW_BUFFER_TYPE_OFFSCREEN
+} CoglDrawBufferType;
+
+typedef struct
+{
+ CoglHandleObject _parent;
+ CoglDrawBufferType type;
+ int width;
+ int height;
+
+ CoglMatrixStack *modelview_stack;
+ CoglMatrixStack *projection_stack;
+ int viewport_x;
+ int viewport_y;
+ int viewport_width;
+ int viewport_height;
+
+ CoglClipStackState clip_state;
+} CoglDrawBuffer;
+
+#define COGL_DRAW_BUFFER(X) ((CoglDrawBuffer *)(X))
+
+typedef struct _CoglDrawBufferStackEntry
+{
+ CoglBufferTarget target;
+ CoglHandle draw_buffer;
+} CoglDrawBufferStackEntry;
+
+typedef struct _CoglOffscreen
+{
+ CoglDrawBuffer _parent;
+ GLuint fbo_handle;
+ GLuint gl_stencil_handle;
+} CoglOffscreen;
+
+#define COGL_OFFSCREEN(X) ((CoglOffscreen *)(X))
+
+typedef struct _CoglOnscreen
+{
+ CoglDrawBuffer _parent;
+} CoglOnscreen;
+
+#define COGL_ONSCREEN(X) ((CoglOnscreen *)(X))
+
+void
+_cogl_draw_buffer_state_init (void);
+CoglClipStackState *
+_cogl_draw_buffer_get_clip_state (CoglHandle handle);
+void
+_cogl_draw_buffer_set_viewport (CoglHandle handle,
+ int x,
+ int y,
+ int width,
+ int height);
+int
+_cogl_draw_buffer_get_viewport_x (CoglHandle handle);
+int
+_cogl_draw_buffer_get_viewport_y (CoglHandle handle);
+int
+_cogl_draw_buffer_get_viewport_width (CoglHandle handle);
+int
+_cogl_draw_buffer_get_viewport_height (CoglHandle handle);
+void
+_cogl_draw_buffer_get_viewport4fv (CoglHandle handle, int *viewport);
+CoglMatrixStack *
+_cogl_draw_buffer_get_modelview_stack (CoglHandle handle);
+CoglMatrixStack *
+_cogl_draw_buffer_get_projection_stack (CoglHandle handle);
+
+typedef enum _CoglDrawBufferFlushFlags
+{
+ /* XXX: When using this, that imples you are going to manually load the
+ * modelview matrix (via glLoadMatrix). _cogl_matrix_stack_flush_to_gl wont
+ * be called for draw_buffer->modelview_stack, and the modelview_stack will
+ * also be marked as dirty. */
+ COGL_DRAW_BUFFER_FLUSH_SKIP_MODELVIEW = 1L<<0,
+} CoglDrawBufferFlushFlags;
+
+void
+_cogl_draw_buffer_flush_state (CoglHandle handle,
+ CoglDrawBufferFlushFlags flags);
+
+CoglHandle
+_cogl_onscreen_new (void);
+
+CoglHandle
+_cogl_get_draw_buffer (void);
+GSList *
+_cogl_create_draw_buffer_stack (void);
+void
+_cogl_free_draw_buffer_stack (GSList *stack);
+
+#endif /* __COGL_DRAW_BUFFER_PRIVATE_H */
+
--- /dev/null
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2007,2008,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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "cogl.h"
+#include "cogl-internal.h"
+#include "cogl-context.h"
+#include "cogl-handle.h"
+#include "cogl-util.h"
+#include "cogl-texture-private.h"
+#include "cogl-draw-buffer-private.h"
+#include "cogl-clip-stack.h"
+
+#ifdef HAVE_COGL_GLES2
+
+#include "../gles/cogl-gles2-wrapper.h"
+
+#else
+
+#define glGenRenderbuffers ctx->drv.pf_glGenRenderbuffers
+#define glDeleteRenderbuffers ctx->drv.pf_glDeleteRenderbuffers
+#define glBindRenderbuffer ctx->drv.pf_glBindRenderbuffer
+#define glRenderbufferStorage ctx->drv.pf_glRenderbufferStorage
+#define glGenFramebuffers ctx->drv.pf_glGenFramebuffers
+#define glBindFramebuffer ctx->drv.pf_glBindFramebuffer
+#define glFramebufferTexture2D ctx->drv.pf_glFramebufferTexture2D
+#define glFramebufferRenderbuffer ctx->drv.pf_glFramebufferRenderbuffer
+#define glCheckFramebufferStatus ctx->drv.pf_glCheckFramebufferStatus
+#define glDeleteFramebuffers ctx->drv.pf_glDeleteFramebuffers
+
+#endif
+
+#ifndef GL_FRAMEBUFFER
+#define GL_FRAMEBUFFER 0x8D40
+#endif
+#ifndef GL_RENDERBUFFER
+#define GL_RENDERBUFFER 0x8D41
+#endif
+#ifndef GL_STENCIL_ATTACHMENT
+#define GL_STENCIL_ATTACHMENT 0x8D00
+#endif
+#ifndef GL_COLOR_ATTACHMENT0
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#endif
+#ifndef GL_FRAMEBUFFER_COMPLETE
+#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#endif
+#ifndef GL_STENCIL_INDEX8
+#define GL_STENCIL_INDEX8 0x8D48
+#endif
+
+static void _cogl_draw_buffer_free (CoglDrawBuffer *draw_buffer);
+static void _cogl_onscreen_free (CoglOnscreen *onscreen);
+static void _cogl_offscreen_free (CoglOffscreen *offscreen);
+
+COGL_HANDLE_DEFINE (Onscreen, onscreen);
+COGL_HANDLE_DEFINE (Offscreen, offscreen);
+
+/* XXX:
+ * The CoglHandle macros don't support any form of inheritance, so for
+ * now we implement the CoglHandle support for the CoglDrawBuffer
+ * abstract class manually.
+ */
+
+gboolean
+cogl_is_draw_buffer (CoglHandle handle)
+{
+ CoglHandleObject *obj = (CoglHandleObject *)handle;
+
+ if (handle == COGL_INVALID_HANDLE)
+ return FALSE;
+
+ return obj->klass->type == _cogl_handle_onscreen_get_type ()
+ || obj->klass->type == _cogl_handle_offscreen_get_type ();
+}
+
+static void
+_cogl_draw_buffer_init (CoglDrawBuffer *draw_buffer,
+ CoglDrawBufferType type,
+ int width,
+ int height)
+{
+ draw_buffer->type = type;
+ draw_buffer->width = width;
+ draw_buffer->height = height;
+ draw_buffer->viewport_x = 0;
+ draw_buffer->viewport_y = 0;
+ draw_buffer->viewport_width = width;
+ draw_buffer->viewport_height = height;
+
+ draw_buffer->modelview_stack = _cogl_matrix_stack_new ();
+ draw_buffer->projection_stack = _cogl_matrix_stack_new ();
+
+ /* Initialise the clip stack */
+ _cogl_clip_stack_state_init (&draw_buffer->clip_state);
+}
+
+void
+_cogl_draw_buffer_free (CoglDrawBuffer *draw_buffer)
+{
+ _cogl_clip_stack_state_destroy (&draw_buffer->clip_state);
+
+ _cogl_matrix_stack_destroy (draw_buffer->modelview_stack);
+ draw_buffer->modelview_stack = NULL;
+
+ _cogl_matrix_stack_destroy (draw_buffer->projection_stack);
+ draw_buffer->projection_stack = NULL;
+}
+
+CoglClipStackState *
+_cogl_draw_buffer_get_clip_state (CoglHandle handle)
+{
+ CoglDrawBuffer *draw_buffer = COGL_DRAW_BUFFER (handle);
+
+ return &draw_buffer->clip_state;
+}
+
+void
+_cogl_draw_buffer_set_viewport (CoglHandle handle,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ CoglDrawBuffer *draw_buffer = COGL_DRAW_BUFFER (handle);
+
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+ if (draw_buffer->viewport_x == x &&
+ draw_buffer->viewport_y == y &&
+ draw_buffer->viewport_width == width &&
+ draw_buffer->viewport_height == height)
+ return;
+
+ _cogl_journal_flush ();
+
+ draw_buffer->viewport_x = x;
+ draw_buffer->viewport_y = y;
+ draw_buffer->viewport_width = width;
+ draw_buffer->viewport_height = height;
+
+ if (_cogl_get_draw_buffer () == draw_buffer)
+ ctx->dirty_viewport = TRUE;
+}
+
+int
+_cogl_draw_buffer_get_viewport_x (CoglHandle handle)
+{
+ CoglDrawBuffer *draw_buffer = COGL_DRAW_BUFFER (handle);
+ return draw_buffer->viewport_x;
+}
+
+int
+_cogl_draw_buffer_get_viewport_y (CoglHandle handle)
+{
+ CoglDrawBuffer *draw_buffer = COGL_DRAW_BUFFER (handle);
+ return draw_buffer->viewport_y;
+}
+
+int
+_cogl_draw_buffer_get_viewport_width (CoglHandle handle)
+{
+ CoglDrawBuffer *draw_buffer = COGL_DRAW_BUFFER (handle);
+ return draw_buffer->viewport_width;
+}
+
+int
+_cogl_draw_buffer_get_viewport_height (CoglHandle handle)
+{
+ CoglDrawBuffer *draw_buffer = COGL_DRAW_BUFFER (handle);
+ return draw_buffer->viewport_height;
+}
+
+void
+_cogl_draw_buffer_get_viewport4fv (CoglHandle handle, int *viewport)
+{
+ CoglDrawBuffer *draw_buffer = COGL_DRAW_BUFFER (handle);
+ viewport[0] = draw_buffer->viewport_x;
+ viewport[1] = draw_buffer->viewport_y;
+ viewport[2] = draw_buffer->viewport_width;
+ viewport[3] = draw_buffer->viewport_height;
+}
+
+CoglMatrixStack *
+_cogl_draw_buffer_get_modelview_stack (CoglHandle handle)
+{
+ CoglDrawBuffer *draw_buffer = COGL_DRAW_BUFFER (handle);
+ return draw_buffer->modelview_stack;
+}
+
+CoglMatrixStack *
+_cogl_draw_buffer_get_projection_stack (CoglHandle handle)
+{
+ CoglDrawBuffer *draw_buffer = COGL_DRAW_BUFFER (handle);
+ return draw_buffer->projection_stack;
+}
+
+CoglHandle
+cogl_offscreen_new_to_texture (CoglHandle texhandle)
+{
+ CoglOffscreen *offscreen;
+ int width;
+ int height;
+ GLuint tex_gl_handle;
+ GLenum tex_gl_target;
+ GLuint fbo_gl_handle;
+ GLuint gl_stencil_handle;
+ GLenum status;
+
+ _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
+
+ if (!cogl_features_available (COGL_FEATURE_OFFSCREEN))
+ return COGL_INVALID_HANDLE;
+
+ /* Make texhandle is a valid texture object */
+ if (!cogl_is_texture (texhandle))
+ return COGL_INVALID_HANDLE;
+
+ /* The texture must not be sliced */
+ if (cogl_texture_is_sliced (texhandle))
+ return COGL_INVALID_HANDLE;
+
+ /* Pick the single texture slice width, height and GL id */
+
+ width = cogl_texture_get_width (texhandle);
+ height = cogl_texture_get_height (texhandle);
+
+ if (!cogl_texture_get_gl_texture (texhandle, &tex_gl_handle, &tex_gl_target))
+ return COGL_INVALID_HANDLE;
+
+ if (tex_gl_target != GL_TEXTURE_2D)
+ return COGL_INVALID_HANDLE;
+
+ /* Create a renderbuffer for stenciling */
+ GE (glGenRenderbuffers (1, &gl_stencil_handle));
+ GE (glBindRenderbuffer (GL_RENDERBUFFER, gl_stencil_handle));
+ GE (glRenderbufferStorage (GL_RENDERBUFFER, GL_STENCIL_INDEX8,
+ cogl_texture_get_width (texhandle),
+ cogl_texture_get_height (texhandle)));
+ GE (glBindRenderbuffer (GL_RENDERBUFFER, 0));
+
+ /* We are about to generate and bind a new fbo, so when next flushing the
+ * journal, we will need to rebind the current draw buffer... */
+ ctx->dirty_bound_framebuffer = 1;
+
+ /* Generate framebuffer */
+ glGenFramebuffers (1, &fbo_gl_handle);
+ GE (glBindFramebuffer (GL_FRAMEBUFFER, fbo_gl_handle));
+ GE (glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ tex_gl_target, tex_gl_handle, 0));
+ GE (glFramebufferRenderbuffer (GL_FRAMEBUFFER,
+ GL_STENCIL_ATTACHMENT,
+ GL_RENDERBUFFER, gl_stencil_handle));
+
+ /* XXX: The framebuffer_object spec isn't clear in defining whether attaching
+ * a texture as a renderbuffer with mipmap filtering enabled while the
+ * mipmaps have not been uploaded should result in an incomplete framebuffer
+ * object. (different drivers make different decisions)
+ *
+ * To avoid an error with drivers that do consider this a problem we
+ * explicitly set non mipmapped filters here. These will later be reset when
+ * the texture is actually used for rendering according to the filters set on
+ * the corresponding CoglMaterial.
+ */
+ _cogl_texture_set_filters (texhandle, GL_NEAREST, GL_NEAREST);
+
+ /* Make sure it's complete */
+ status = glCheckFramebufferStatus (GL_FRAMEBUFFER);
+
+ if (status != GL_FRAMEBUFFER_COMPLETE)
+ {
+ /* Stencil renderbuffers aren't always supported. Try again
+ without the stencil buffer */
+ GE (glFramebufferRenderbuffer (GL_FRAMEBUFFER,
+ GL_STENCIL_ATTACHMENT,
+ GL_RENDERBUFFER,
+ 0));
+ GE (glDeleteRenderbuffers (1, &gl_stencil_handle));
+ gl_stencil_handle = 0;
+
+ status = glCheckFramebufferStatus (GL_FRAMEBUFFER);
+
+ if (status != GL_FRAMEBUFFER_COMPLETE)
+ {
+ /* Still failing, so give up */
+ GE (glDeleteFramebuffers (1, &fbo_gl_handle));
+ GE (glBindFramebuffer (GL_FRAMEBUFFER, 0));
+ return COGL_INVALID_HANDLE;
+ }
+ }
+
+ offscreen = g_new0 (CoglOffscreen, 1);
+
+ _cogl_draw_buffer_init (COGL_DRAW_BUFFER (offscreen),
+ COGL_DRAW_BUFFER_TYPE_OFFSCREEN,
+ width,
+ height);
+
+ offscreen->fbo_handle = fbo_gl_handle;
+ offscreen->gl_stencil_handle = gl_stencil_handle;
+
+ /* XXX: Can we get a away with removing this? It wasn't documented, and most
+ * users of the API are hopefully setting up the modelview from scratch
+ * anyway */
+#if 0
+ cogl_matrix_translate (&draw_buffer->modelview, -1.0f, -1.0f, 0.0f);
+ cogl_matrix_scale (&draw_buffer->modelview,
+ 2.0f / draw_buffer->width, 2.0f / draw_buffer->height, 1.0f);
+#endif
+
+ return _cogl_offscreen_handle_new (offscreen);
+}
+
+static void
+_cogl_offscreen_free (CoglOffscreen *offscreen)
+{
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+ /* Chain up to parent */
+ _cogl_draw_buffer_free (COGL_DRAW_BUFFER (offscreen));
+
+ if (offscreen->gl_stencil_handle)
+ GE (glDeleteRenderbuffers (1, &offscreen->gl_stencil_handle));
+ GE (glDeleteFramebuffers (1, &offscreen->fbo_handle));
+ g_free (offscreen);
+}
+
+CoglHandle
+_cogl_onscreen_new (void)
+{
+ CoglOnscreen *onscreen;
+
+ /* XXX: Until we have full winsys support in Cogl then we can't fully
+ * implement CoglOnscreen draw buffers, since we can't, e.g. keep track of
+ * the window size. */
+
+ onscreen = g_new0 (CoglOnscreen, 1);
+ _cogl_draw_buffer_init (COGL_DRAW_BUFFER (onscreen),
+ COGL_DRAW_BUFFER_TYPE_ONSCREEN,
+ 0xdeadbeef, /* width */
+ 0xdeadbeef); /* height */
+
+ return _cogl_onscreen_handle_new (onscreen);
+}
+
+static void
+_cogl_onscreen_free (CoglOnscreen *onscreen)
+{
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+ /* Chain up to parent */
+ _cogl_draw_buffer_free (COGL_DRAW_BUFFER (onscreen));
+
+ g_free (onscreen);
+}
+
+GSList *
+_cogl_create_draw_buffer_stack (void)
+{
+ GSList *stack = NULL;
+ CoglDrawBufferStackEntry *entry;
+
+ entry = g_slice_new0 (CoglDrawBufferStackEntry);
+ entry->target = COGL_WINDOW_BUFFER;
+ entry->draw_buffer = COGL_INVALID_HANDLE;
+
+ return g_slist_prepend (stack, entry);
+}
+
+void
+_cogl_free_draw_buffer_stack (GSList *stack)
+{
+ GSList *l;
+
+ for (l = stack; l != NULL; l = l->next)
+ {
+ CoglDrawBufferStackEntry *entry = l->data;
+ CoglDrawBuffer *draw_buffer = COGL_DRAW_BUFFER (entry->draw_buffer);
+ if (draw_buffer->type == COGL_DRAW_BUFFER_TYPE_OFFSCREEN)
+ _cogl_offscreen_free (COGL_OFFSCREEN (draw_buffer));
+ else
+ _cogl_onscreen_free (COGL_ONSCREEN (draw_buffer));
+ }
+ g_slist_free (stack);
+}
+
+/* XXX: The target argument is redundant; when we break API, we should
+ * remove it! */
+void
+cogl_set_draw_buffer (CoglBufferTarget target, CoglHandle handle)
+{
+ CoglDrawBuffer *draw_buffer = NULL;
+ CoglDrawBufferStackEntry *entry;
+
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+ _cogl_journal_flush ();
+
+ g_assert (ctx->draw_buffer_stack != NULL);
+ entry = ctx->draw_buffer_stack->data;
+
+ if (target == COGL_WINDOW_BUFFER)
+ handle = ctx->window_buffer;
+ else if (!cogl_is_draw_buffer (handle))
+ return;
+
+ draw_buffer = COGL_DRAW_BUFFER (handle);
+
+ if (entry->draw_buffer != draw_buffer)
+ {
+ entry->target = target;
+
+ ctx->dirty_bound_framebuffer = 1;
+ ctx->dirty_viewport = 1;
+
+ if (draw_buffer != COGL_INVALID_HANDLE)
+ cogl_handle_ref (draw_buffer);
+ if (entry->draw_buffer != COGL_INVALID_HANDLE)
+ cogl_handle_unref (entry->draw_buffer);
+ entry->draw_buffer = draw_buffer;
+
+ /* We've effectively just switched the current modelview and
+ * projection matrix stacks and clip state so we need to dirty
+ * them to ensure they get flushed for the next batch of geometry
+ * we flush */
+ _cogl_matrix_stack_dirty (draw_buffer->modelview_stack);
+ _cogl_matrix_stack_dirty (draw_buffer->projection_stack);
+ _cogl_clip_stack_state_dirty (&draw_buffer->clip_state);
+ }
+}
+
+CoglHandle
+_cogl_get_draw_buffer (void)
+{
+ CoglDrawBufferStackEntry *entry;
+
+ _COGL_GET_CONTEXT (ctx, NULL);
+
+ g_assert (ctx->draw_buffer_stack);
+ entry = ctx->draw_buffer_stack->data;
+
+ return entry->draw_buffer;
+}
+
+void
+cogl_push_draw_buffer (void)
+{
+ CoglDrawBufferStackEntry *old;
+ CoglDrawBufferStackEntry *entry;
+
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+ entry = g_slice_new0 (CoglDrawBufferStackEntry);
+
+ g_assert (ctx->draw_buffer_stack);
+
+ old = ctx->draw_buffer_stack->data;
+ *entry = *old;
+
+ cogl_handle_ref (entry->draw_buffer);
+
+ ctx->draw_buffer_stack =
+ g_slist_prepend (ctx->draw_buffer_stack, entry);
+}
+
+void
+cogl_pop_draw_buffer (void)
+{
+ CoglDrawBufferStackEntry *to_pop;
+ CoglDrawBufferStackEntry *to_restore;
+
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+ g_assert (ctx->draw_buffer_stack != NULL);
+
+ to_pop = ctx->draw_buffer_stack->data;
+ to_restore = ctx->draw_buffer_stack->next->data;
+
+ cogl_set_draw_buffer (to_restore->target, to_restore->draw_buffer);
+
+ cogl_handle_unref (to_pop->draw_buffer);
+ ctx->draw_buffer_stack =
+ g_slist_remove_link (ctx->draw_buffer_stack,
+ ctx->draw_buffer_stack);
+ g_slice_free (CoglDrawBufferStackEntry, to_pop);
+}
+
+void
+_cogl_draw_buffer_flush_state (CoglHandle handle,
+ CoglDrawBufferFlushFlags flags)
+{
+ CoglDrawBuffer *draw_buffer;
+
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+ draw_buffer = COGL_DRAW_BUFFER (handle);
+
+ if (cogl_features_available (COGL_FEATURE_OFFSCREEN) &&
+ ctx->dirty_bound_framebuffer)
+ {
+ if (draw_buffer->type == COGL_DRAW_BUFFER_TYPE_OFFSCREEN)
+ {
+ GE (glBindFramebuffer (GL_FRAMEBUFFER,
+ COGL_OFFSCREEN (draw_buffer)->fbo_handle));
+ }
+ else
+ GE (glBindFramebuffer (GL_FRAMEBUFFER, 0));
+ ctx->dirty_bound_framebuffer = FALSE;
+ }
+
+ if (ctx->dirty_viewport)
+ {
+ GE (glViewport (draw_buffer->viewport_x,
+ draw_buffer->viewport_y,
+ draw_buffer->viewport_width,
+ draw_buffer->viewport_height));
+ ctx->dirty_viewport = FALSE;
+ }
+
+ /* XXX: Flushing clip state may trash the modelview and projection
+ * matrices so we must do it before flushing the matrices...
+ */
+ _cogl_flush_clip_state (&draw_buffer->clip_state);
+
+ if (!(flags & COGL_DRAW_BUFFER_FLUSH_SKIP_MODELVIEW))
+ _cogl_matrix_stack_flush_to_gl (draw_buffer->modelview_stack,
+ COGL_MATRIX_MODELVIEW);
+
+ _cogl_matrix_stack_flush_to_gl (draw_buffer->projection_stack,
+ COGL_MATRIX_PROJECTION);
+}
+
#include "cogl-texture-private.h"
#include "cogl-material-private.h"
#include "cogl-vertex-buffer-private.h"
+#include "cogl-draw-buffer-private.h"
#include <string.h>
#include <gmodule.h>
GLuint journal_vbo;
gboolean vbo_fallback =
(cogl_get_features () & COGL_FEATURE_VBOS) ? FALSE : TRUE;
+ CoglHandle draw_buffer;
+ CoglMatrixStack *modelview_stack;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
else
state.vbo_offset = (char *)ctx->logged_vertices->data;
- _cogl_matrix_stack_flush_to_gl (ctx->projection_stack,
- COGL_MATRIX_PROJECTION);
+ draw_buffer = _cogl_get_draw_buffer ();
+ modelview_stack = _cogl_draw_buffer_get_modelview_stack (draw_buffer);
+ state.modelview_stack = modelview_stack;
- state.modelview_stack = ctx->modelview_stack;
- _cogl_matrix_stack_push (ctx->modelview_stack);
+ _cogl_matrix_stack_push (modelview_stack);
/* If we have transformed all our quads at log time then we ensure no
* further model transform is applied by loading the identity matrix
* here... */
if (G_LIKELY (!(cogl_debug_flags & COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM)))
{
- _cogl_matrix_stack_load_identity (ctx->modelview_stack);
- _cogl_matrix_stack_flush_to_gl (ctx->modelview_stack,
- COGL_MATRIX_MODELVIEW);
+ _cogl_matrix_stack_load_identity (modelview_stack);
+ _cogl_matrix_stack_flush_to_gl (modelview_stack, COGL_MATRIX_MODELVIEW);
}
/* batch_and_call() batches a list of journal entries according to some
_cogl_journal_flush_vbo_offsets_and_entries, /* callback */
&state); /* data */
- _cogl_matrix_stack_pop (ctx->modelview_stack);
+ _cogl_matrix_stack_pop (modelview_stack);
for (i = 0; i < ctx->journal->len; i++)
{
g_array_set_size (ctx->logged_vertices, 0);
}
+static void
+_cogl_journal_init (void)
+{
+ /* Here we flush anything that we know must remain constant until the
+ * next the the journal is flushed. Note: This lets up flush things
+ * that themselves depend on the journal, such as clip state. */
+
+ /* NB: the journal deals with flushing the modelview stack manually */
+ _cogl_draw_buffer_flush_state (_cogl_get_draw_buffer (),
+ COGL_DRAW_BUFFER_FLUSH_SKIP_MODELVIEW);
+}
+
void
_cogl_journal_log_quad (float x_1,
float y_1,
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
+ if (ctx->logged_vertices->len == 0)
+ _cogl_journal_init ();
+
/* The vertex data is logged into a separate array in a layout that can be
* directly passed to OpenGL
*/
#include "cogl-texture-private.h"
#include "cogl-material-private.h"
#include "cogl-vertex-buffer-private.h"
+#include "cogl-draw-buffer-private.h"
#include <string.h>
#include <math.h>
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
- cogl_clip_ensure ();
-
material = ctx->source_material;
layers = cogl_material_get_layers (material);
options.layer0_override_texture = gl_handle;
_cogl_material_flush_gl_state (ctx->source_material, &options);
- _cogl_flush_matrix_stacks ();
GE (glDrawArrays (GL_TRIANGLE_FAN, 0, state->n_vertices));
}
options.flags |= COGL_MATERIAL_FLUSH_SKIP_GL_COLOR;
options.fallback_layers = fallback_layers;
_cogl_material_flush_gl_state (ctx->source_material, &options);
- _cogl_flush_matrix_stacks ();
GE (glDrawArrays (GL_TRIANGLE_FAN, 0, n_vertices));
}
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
_cogl_journal_flush ();
- cogl_clip_ensure ();
+
+ /* NB: _cogl_draw_buffer_flush_state may disrupt various state (such
+ * as the material state) when flushing the clip stack, so should
+ * always be done first when preparing to draw. */
+ _cogl_draw_buffer_flush_state (_cogl_get_draw_buffer (), 0);
material = ctx->source_material;
layers = cogl_material_get_layers (ctx->source_material);
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
- _cogl_journal_flush ();
- cogl_clip_ensure ();
-
if (ctx->path_nodes->len == 0)
return;
if (ctx->path_nodes->len == 0)
return;
- _cogl_journal_flush ();
- cogl_clip_ensure ();
-
- _cogl_path_stroke_nodes();
+ _cogl_path_stroke_nodes ();
}
void
#include "cogl-context.h"
#include "cogl-handle.h"
#include "cogl-primitives.h"
+#include "cogl-draw-buffer-private.h"
#include <string.h>
#include <stdlib.h>
GLuint target_gl_type)
{
gint bpp;
- GLint viewport[4];
+ CoglHandle draw_buffer;
+ int viewport[4];
CoglBitmap alpha_bmp;
CoglHandle prev_source;
CoglMatrixStack *projection_stack;
bpp = _cogl_get_format_bpp (COGL_PIXEL_FORMAT_RGBA_8888);
+ draw_buffer = _cogl_get_draw_buffer ();
/* Viewport needs to have some size and be inside the window for this */
- GE( glGetIntegerv (GL_VIEWPORT, viewport));
+ _cogl_draw_buffer_get_viewport4fv (draw_buffer, viewport);
if (viewport[0] < 0 || viewport[1] < 0 ||
viewport[2] <= 0 || viewport[3] <= 0)
return FALSE;
* works)
*/
- _cogl_matrix_stack_push (ctx->projection_stack);
- _cogl_matrix_stack_load_identity (ctx->projection_stack);
- _cogl_matrix_stack_ortho (ctx->projection_stack,
+ projection_stack = _cogl_draw_buffer_get_projection_stack (draw_buffer);
+ _cogl_matrix_stack_push (projection_stack);
+ _cogl_matrix_stack_load_identity (projection_stack);
+ _cogl_matrix_stack_ortho (projection_stack,
0, (float)(viewport[2]),
0, (float)(viewport[3]),
(float)(0),
(float)(100));
- _cogl_matrix_stack_push (ctx->modelview_stack);
- _cogl_matrix_stack_load_identity (ctx->modelview_stack);
+ modelview_stack = _cogl_draw_buffer_get_modelview_stack (draw_buffer);
+ _cogl_matrix_stack_push (modelview_stack);
+ _cogl_matrix_stack_load_identity (modelview_stack);
/* Direct copy operation */
#include "cogl-texture-private.h"
#include "cogl-material-private.h"
#include "cogl-primitives.h"
+#include "cogl-draw-buffer-private.h"
#define PAD_FOR_ALIGNMENT(VAR, TYPE_SIZE) \
(VAR = TYPE_SIZE + ((VAR - 1) & ~(TYPE_SIZE - 1)))
}
ctx->n_texcoord_arrays_enabled = max_texcoord_attrib_unit + 1;
+ /* NB: _cogl_draw_buffer_flush_state may disrupt various state (such
+ * as the material state) when flushing the clip stack, so should
+ * always be done first when preparing to draw. */
+ _cogl_draw_buffer_flush_state (_cogl_get_draw_buffer (), 0);
+
options.flags =
COGL_MATERIAL_FLUSH_FALLBACK_MASK |
COGL_MATERIAL_FLUSH_DISABLE_MASK;
return;
_cogl_journal_flush ();
- cogl_clip_ensure ();
buffer = _cogl_vertex_buffer_pointer_from_handle (handle);
- cogl_clip_ensure ();
- _cogl_flush_matrix_stacks ();
enable_state_for_drawing_buffer (buffer);
- /* FIXME: flush cogl cache */
GE (glDrawArrays (mode, first, count));
disable_state_for_drawing_buffer (buffer);
return;
_cogl_journal_flush ();
- cogl_clip_ensure ();
buffer = _cogl_vertex_buffer_pointer_from_handle (handle);
indices = _cogl_vertex_buffer_indices_pointer_from_handle (indices_handle);
- cogl_clip_ensure ();
- _cogl_flush_matrix_stacks ();
enable_state_for_drawing_buffer (buffer);
byte_offset = indices_offset * get_indices_type_size (indices->type);
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, (void *)byte_offset));
#include "cogl-context.h"
#include "cogl-material-private.h"
#include "cogl-winsys.h"
+#include "cogl-draw-buffer-private.h"
#if defined (HAVE_COGL_GLES2) || defined (HAVE_COGL_GLES)
#include "cogl-gles2-wrapper.h"
COGL_NOTE (DRAW, "Clear begin");
- cogl_clip_ensure ();
+ _cogl_journal_flush ();
+
+ /* NB: _cogl_draw_buffer_flush_state may disrupt various state (such
+ * as the material state) when flushing the clip stack, so should
+ * always be done first when preparing to draw. */
+ _cogl_draw_buffer_flush_state (_cogl_get_draw_buffer (), 0);
if (buffers & COGL_BUFFER_BIT_COLOR)
{
#endif
GLfloat angle;
CoglMatrix inverse_projection;
+ CoglHandle draw_buffer = _cogl_get_draw_buffer ();
+ CoglMatrixStack *modelview_stack =
+ _cogl_draw_buffer_get_modelview_stack (draw_buffer);
+
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
/* Calculate the angle between the axes and the line crossing the
angle = atan2f (vertex_b[1] - vertex_a[1],
vertex_b[0] - vertex_a[0]) * (180.0/G_PI);
- _cogl_matrix_stack_push (ctx->modelview_stack);
+ _cogl_matrix_stack_push (modelview_stack);
+
/* Load the identity matrix and multiply by the reverse of the
projection matrix so we can specify the plane in screen
coordinates */
- _cogl_matrix_stack_load_identity (ctx->modelview_stack);
+ _cogl_matrix_stack_load_identity (modelview_stack);
cogl_matrix_init_from_array (&inverse_projection,
ctx->inverse_projection);
- _cogl_matrix_stack_multiply (ctx->modelview_stack, &inverse_projection);
+ _cogl_matrix_stack_multiply (modelview_stack, &inverse_projection);
/* Rotate about point a */
- _cogl_matrix_stack_translate (ctx->modelview_stack,
+ _cogl_matrix_stack_translate (modelview_stack,
vertex_a[0], vertex_a[1], vertex_a[2]);
/* Rotate the plane by the calculated angle so that it will connect
the two points */
- _cogl_matrix_stack_rotate (ctx->modelview_stack, angle, 0.0f, 0.0f, 1.0f);
- _cogl_matrix_stack_translate (ctx->modelview_stack,
+ _cogl_matrix_stack_rotate (modelview_stack, angle, 0.0f, 0.0f, 1.0f);
+ _cogl_matrix_stack_translate (modelview_stack,
-vertex_a[0], -vertex_a[1], -vertex_a[2]);
- _cogl_flush_matrix_stacks ();
+ _cogl_matrix_stack_flush_to_gl (modelview_stack, COGL_MATRIX_MODELVIEW);
plane[0] = 0;
plane[1] = -1.0;
GE( glClipPlane (plane_num, plane) );
#endif
- _cogl_matrix_stack_pop (ctx->modelview_stack);
+ _cogl_matrix_stack_pop (modelview_stack);
}
void
float width,
float height)
{
+ CoglHandle draw_buffer = _cogl_get_draw_buffer ();
+ CoglMatrixStack *modelview_stack =
+ _cogl_draw_buffer_get_modelview_stack (draw_buffer);
CoglMatrix modelview_matrix;
+ CoglMatrixStack *projection_stack =
+ _cogl_draw_buffer_get_projection_stack (draw_buffer);
CoglMatrix projection_matrix;
float vertex_tl[4] = { x_offset, y_offset, 0, 1.0 };
float vertex_br[4] = { x_offset + width, y_offset + height,
0, 1.0 };
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- _cogl_matrix_stack_get (ctx->projection_stack, &projection_matrix);
- _cogl_matrix_stack_get (ctx->modelview_stack, &modelview_matrix);
+ _cogl_matrix_stack_get (projection_stack, &projection_matrix);
+ _cogl_matrix_stack_get (modelview_stack, &modelview_matrix);
project_vertex (&modelview_matrix, &projection_matrix, vertex_tl);
project_vertex (&modelview_matrix, &projection_matrix, vertex_tr);
gboolean first)
{
CoglHandle current_source;
+ CoglHandle draw_buffer = _cogl_get_draw_buffer ();
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
* batched geometry before we start... */
_cogl_journal_flush ();
+ _cogl_draw_buffer_flush_state (draw_buffer, 0);
+
/* temporarily swap in our special stenciling material */
current_source = cogl_handle_ref (ctx->source_material);
cogl_set_source (ctx->stencil_material);
}
else
{
+ CoglMatrixStack *modelview_stack =
+ _cogl_draw_buffer_get_modelview_stack (draw_buffer);
+ CoglMatrixStack *projection_stack =
+ _cogl_draw_buffer_get_projection_stack (draw_buffer);
+
/* Add one to every pixel of the stencil buffer in the
rectangle */
GE( glStencilFunc (GL_NEVER, 0x1, 0x3) );
rectangle are set will be valid */
GE( glStencilOp (GL_DECR, GL_DECR, GL_DECR) );
- _cogl_matrix_stack_push (ctx->projection_stack);
- _cogl_matrix_stack_load_identity (ctx->projection_stack);
+ _cogl_matrix_stack_push (projection_stack);
+ _cogl_matrix_stack_load_identity (projection_stack);
- _cogl_matrix_stack_push (ctx->modelview_stack);
- _cogl_matrix_stack_load_identity (ctx->modelview_stack);
+ _cogl_matrix_stack_push (modelview_stack);
+ _cogl_matrix_stack_load_identity (modelview_stack);
cogl_rectangle (-1.0, -1.0, 1.0, 1.0);
- _cogl_matrix_stack_pop (ctx->modelview_stack);
- _cogl_matrix_stack_pop (ctx->projection_stack);
+ _cogl_matrix_stack_pop (modelview_stack);
+ _cogl_matrix_stack_pop (projection_stack);
}
/* make sure our rectangles hit the stencil buffer before we restore
GE( glDisable (GL_CLIP_PLANE0) );
}
-/* XXX: This should be deprecated and Cogl should be left to manage
- * the glViewport automatically when switching draw buffers. */
void
-cogl_viewport (guint width,
- guint height)
+_cogl_set_viewport (int x,
+ int y,
+ int width,
+ int height)
{
+ CoglHandle draw_buffer;
+
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
- COGL_NOTE (MISC, "glViewport(0, 0, %u, %u)", width, height);
- GE( glViewport (0, 0, width, height) );
+ draw_buffer = _cogl_get_draw_buffer ();
- ctx->viewport_width = width;
- ctx->viewport_height = height;
+ _cogl_draw_buffer_set_viewport (draw_buffer,
+ x,
+ y,
+ width,
+ height);
+}
+
+/* XXX: This should be deprecated, and we should expose a way to also
+ * specify an x and y viewport offset */
+void
+cogl_viewport (guint width,
+ guint height)
+{
+ _cogl_set_viewport (0, 0, width, height);
}
void
{
float z_camera;
CoglMatrix projection_matrix;
+ CoglMatrixStack *modelview_stack;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
cogl_get_projection_matrix (&projection_matrix);
z_camera = 0.5 * projection_matrix.xx;
- _cogl_matrix_stack_load_identity (ctx->modelview_stack);
- _cogl_matrix_stack_translate (ctx->modelview_stack, -0.5f, -0.5f, -z_camera);
- _cogl_matrix_stack_scale (ctx->modelview_stack,
+ modelview_stack =
+ _cogl_draw_buffer_get_modelview_stack (_cogl_get_draw_buffer ());
+ _cogl_matrix_stack_load_identity (modelview_stack);
+ _cogl_matrix_stack_translate (modelview_stack, -0.5f, -0.5f, -z_camera);
+ _cogl_matrix_stack_scale (modelview_stack,
1.0f / width, -1.0f / height, 1.0f / width);
- _cogl_matrix_stack_translate (ctx->modelview_stack,
+ _cogl_matrix_stack_translate (modelview_stack,
0.0f, -1.0 * height, 0.0f);
}
{
_COGL_GET_CONTEXT (ctx, 0);
- if (!ctx->features_cached)
- _cogl_features_init ();
-
if (cogl_debug_flags & COGL_DEBUG_DISABLE_VBOS)
ctx->feature_flags &= ~COGL_FEATURE_VBOS;
return (ctx->feature_flags & features) == features;
}
-/* XXX: This function should be deprecated, and replaced with a
- * cogl_draw_buffer_get_size() API instead. We don't support offset
- * viewports, and you can't have floating point viewport sizes. */
+/* XXX: This function should either be replaced with one returning
+ * integers, or removed/deprecated and make the
+ * _cogl_draw_buffer_get_viewport* functions public.
+ */
void
cogl_get_viewport (float v[4])
{
+ CoglHandle draw_buffer;
+ int viewport[4];
+ int i;
+
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
- v[0] = 0;
- v[1] = 0;
- v[2] = ctx->viewport_width;
- v[3] = ctx->viewport_height;
+ draw_buffer = _cogl_get_draw_buffer ();
+ _cogl_draw_buffer_get_viewport4fv (draw_buffer, viewport);
+
+ for (i = 0; i < 4; i++)
+ v[i] = viewport[i];
}
void
void
cogl_flush_gl_state (int flags)
{
- _cogl_flush_matrix_stacks ();
+ _cogl_draw_buffer_flush_state (_cogl_get_draw_buffer (), 0);
}
#endif
CoglPixelFormat format,
guint8 *pixels)
{
- GLint viewport[4];
- GLint viewport_height;
- int rowstride = width * 4;
- guint8 *temprow;
+ int viewport_height;
+ int rowstride = width * 4;
+ guint8 *temprow;
+ CoglHandle draw_buffer;
+
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
g_return_if_fail (format == COGL_PIXEL_FORMAT_RGBA_8888);
g_return_if_fail (source == COGL_READ_PIXELS_COLOR_BUFFER);
temprow = g_alloca (rowstride * sizeof (guint8));
- glGetIntegerv (GL_VIEWPORT, viewport);
- viewport_height = viewport[3];
+ draw_buffer = _cogl_get_draw_buffer ();
+ viewport_height = _cogl_draw_buffer_get_viewport_height (draw_buffer);
/* The y co-ordinate should be given in OpenGL's coordinate system
so 0 is the bottom row */
/* Flush all batched primitives */
cogl_flush ();
- /* Flush our clipping state to GL */
- cogl_clip_ensure ();
-
- /* Flush any client side matrix state */
- _cogl_flush_matrix_stacks ();
-
+ /* Flush framebuffer state, including clip state, modelview and
+ * projection matrix state
+ *
+ * NB: _cogl_draw_buffer_flush_state may disrupt various state (such
+ * as the material state) when flushing the clip stack, so should
+ * always be done first when preparing to draw. */
+ _cogl_draw_buffer_flush_state (_cogl_get_draw_buffer (), 0);
/* Setup the state for the current material */
void
cogl_push_matrix (void)
{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
- _cogl_matrix_stack_push (ctx->modelview_stack);
+ CoglMatrixStack *modelview_stack =
+ _cogl_draw_buffer_get_modelview_stack (_cogl_get_draw_buffer ());
+ _cogl_matrix_stack_push (modelview_stack);
}
void
cogl_pop_matrix (void)
{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
- _cogl_matrix_stack_pop (ctx->modelview_stack);
+ CoglMatrixStack *modelview_stack =
+ _cogl_draw_buffer_get_modelview_stack (_cogl_get_draw_buffer ());
+ _cogl_matrix_stack_pop (modelview_stack);
}
void
cogl_scale (float x, float y, float z)
{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
- _cogl_matrix_stack_scale (ctx->modelview_stack, x, y, z);
+ CoglMatrixStack *modelview_stack =
+ _cogl_draw_buffer_get_modelview_stack (_cogl_get_draw_buffer ());
+ _cogl_matrix_stack_scale (modelview_stack, x, y, z);
}
void
cogl_translate (float x, float y, float z)
{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
- _cogl_matrix_stack_translate (ctx->modelview_stack, x, y, z);
+ CoglMatrixStack *modelview_stack =
+ _cogl_draw_buffer_get_modelview_stack (_cogl_get_draw_buffer ());
+ _cogl_matrix_stack_translate (modelview_stack, x, y, z);
}
void
cogl_rotate (float angle, float x, float y, float z)
{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
- _cogl_matrix_stack_rotate (ctx->modelview_stack, angle, x, y, z);
+ CoglMatrixStack *modelview_stack =
+ _cogl_draw_buffer_get_modelview_stack (_cogl_get_draw_buffer ());
+ _cogl_matrix_stack_rotate (modelview_stack, angle, x, y, z);
}
void
float z_far)
{
float c, d;
+ CoglMatrixStack *projection_stack =
+ _cogl_draw_buffer_get_projection_stack (_cogl_get_draw_buffer ());
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
- _cogl_matrix_stack_load_identity (ctx->projection_stack);
+ _cogl_matrix_stack_load_identity (projection_stack);
- _cogl_matrix_stack_frustum (ctx->projection_stack,
+ _cogl_matrix_stack_frustum (projection_stack,
left,
right,
bottom,
float z_far)
{
CoglMatrix ortho;
+ CoglMatrixStack *projection_stack =
+ _cogl_draw_buffer_get_projection_stack (_cogl_get_draw_buffer ());
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
cogl_matrix_init_identity (&ortho);
cogl_matrix_ortho (&ortho, left, right, bottom, top, z_near, z_far);
- _cogl_matrix_stack_set (ctx->projection_stack, &ortho);
+ _cogl_matrix_stack_set (projection_stack, &ortho);
/* Calculate and store the inverse of the matrix */
memset (ctx->inverse_projection, 0, sizeof (float) * 16);
void
cogl_get_modelview_matrix (CoglMatrix *matrix)
{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
- _cogl_matrix_stack_get (ctx->modelview_stack, matrix);
+ CoglMatrixStack *modelview_stack =
+ _cogl_draw_buffer_get_modelview_stack (_cogl_get_draw_buffer ());
+ _cogl_matrix_stack_get (modelview_stack, matrix);
}
void
cogl_set_modelview_matrix (CoglMatrix *matrix)
{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
- _cogl_matrix_stack_set (ctx->modelview_stack, matrix);
+ CoglMatrixStack *modelview_stack =
+ _cogl_draw_buffer_get_modelview_stack (_cogl_get_draw_buffer ());
+ _cogl_matrix_stack_set (modelview_stack, matrix);
}
void
cogl_get_projection_matrix (CoglMatrix *matrix)
{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
- _cogl_matrix_stack_get (ctx->projection_stack, matrix);
+ CoglMatrixStack *projection_stack =
+ _cogl_draw_buffer_get_projection_stack (_cogl_get_draw_buffer ());
+ _cogl_matrix_stack_get (projection_stack, matrix);
}
void
cogl_set_projection_matrix (CoglMatrix *matrix)
{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
- _cogl_matrix_stack_set (ctx->projection_stack, matrix);
+ CoglMatrixStack *projection_stack =
+ _cogl_draw_buffer_get_projection_stack (_cogl_get_draw_buffer ());
+ _cogl_matrix_stack_set (projection_stack, matrix);
/* FIXME: Update the inverse projection matrix!! Presumably use
* of clip planes must currently be broken if this API is used. */
}
-void
-_cogl_flush_matrix_stacks (void)
+CoglClipStackState *
+_cogl_get_clip_state (void)
{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
- _cogl_matrix_stack_flush_to_gl (ctx->projection_stack,
- COGL_MATRIX_PROJECTION);
- _cogl_matrix_stack_flush_to_gl (ctx->modelview_stack,
- COGL_MATRIX_MODELVIEW);
+ CoglHandle draw_buffer;
+
+ draw_buffer = _cogl_get_draw_buffer ();
+ return _cogl_draw_buffer_get_clip_state (draw_buffer);
}
/* private */
void _cogl_set_indirect_context (gboolean indirect);
+void _cogl_set_viewport (int x, int y, int width, int height);
G_END_DECLS
cogl.c \
cogl-primitives.c \
cogl-texture-driver.c \
- cogl-fbo.h \
- cogl-fbo.c \
cogl-shader-private.h \
cogl-shader.c \
cogl-program.h \
void
_cogl_create_context_driver (CoglContext *_context)
{
- _context->drv.pf_glGenRenderbuffersEXT = NULL;
- _context->drv.pf_glBindRenderbufferEXT = NULL;
- _context->drv.pf_glRenderbufferStorageEXT = NULL;
- _context->drv.pf_glGenFramebuffersEXT = NULL;
- _context->drv.pf_glBindFramebufferEXT = NULL;
- _context->drv.pf_glFramebufferTexture2DEXT = NULL;
- _context->drv.pf_glFramebufferRenderbufferEXT = NULL;
- _context->drv.pf_glCheckFramebufferStatusEXT = NULL;
- _context->drv.pf_glDeleteFramebuffersEXT = NULL;
+ _context->drv.pf_glGenRenderbuffers = NULL;
+ _context->drv.pf_glBindRenderbuffer = NULL;
+ _context->drv.pf_glRenderbufferStorage = NULL;
+ _context->drv.pf_glGenFramebuffers = NULL;
+ _context->drv.pf_glBindFramebuffer = NULL;
+ _context->drv.pf_glFramebufferTexture2D = NULL;
+ _context->drv.pf_glFramebufferRenderbuffer = NULL;
+ _context->drv.pf_glCheckFramebufferStatus = NULL;
+ _context->drv.pf_glDeleteFramebuffers = NULL;
+
_context->drv.pf_glBlitFramebufferEXT = NULL;
_context->drv.pf_glRenderbufferStorageMultisampleEXT = NULL;
typedef struct _CoglContextDriver
{
/* Relying on glext.h to define these */
- COGL_PFNGLGENRENDERBUFFERSEXTPROC pf_glGenRenderbuffersEXT;
- COGL_PFNGLDELETERENDERBUFFERSEXTPROC pf_glDeleteRenderbuffersEXT;
- COGL_PFNGLBINDRENDERBUFFEREXTPROC pf_glBindRenderbufferEXT;
- COGL_PFNGLRENDERBUFFERSTORAGEEXTPROC pf_glRenderbufferStorageEXT;
- COGL_PFNGLGENFRAMEBUFFERSEXTPROC pf_glGenFramebuffersEXT;
- COGL_PFNGLBINDFRAMEBUFFEREXTPROC pf_glBindFramebufferEXT;
- COGL_PFNGLFRAMEBUFFERTEXTURE2DEXTPROC pf_glFramebufferTexture2DEXT;
- COGL_PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC pf_glFramebufferRenderbufferEXT;
- COGL_PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC pf_glCheckFramebufferStatusEXT;
- COGL_PFNGLDELETEFRAMEBUFFERSEXTPROC pf_glDeleteFramebuffersEXT;
+ COGL_PFNGLGENRENDERBUFFERSPROC pf_glGenRenderbuffers;
+ COGL_PFNGLDELETERENDERBUFFERSPROC pf_glDeleteRenderbuffers;
+ COGL_PFNGLBINDRENDERBUFFERPROC pf_glBindRenderbuffer;
+ COGL_PFNGLRENDERBUFFERSTORAGEPROC pf_glRenderbufferStorage;
+ COGL_PFNGLGENFRAMEBUFFERSPROC pf_glGenFramebuffers;
+ COGL_PFNGLBINDFRAMEBUFFERPROC pf_glBindFramebuffer;
+ COGL_PFNGLFRAMEBUFFERTEXTURE2DPROC pf_glFramebufferTexture2D;
+ COGL_PFNGLFRAMEBUFFERRENDERBUFFERPROC pf_glFramebufferRenderbuffer;
+ COGL_PFNGLCHECKFRAMEBUFFERSTATUSPROC pf_glCheckFramebufferStatus;
+ COGL_PFNGLDELETEFRAMEBUFFERSPROC pf_glDeleteFramebuffers;
+ COGL_PFNGLGENERATEMIPMAPPROC pf_glGenerateMipmap;
+
COGL_PFNGLBLITFRAMEBUFFEREXTPROC pf_glBlitFramebufferEXT;
COGL_PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC pf_glRenderbufferStorageMultisampleEXT;
- COGL_PFNGLGENERATEMIPMAPEXTPROC pf_glGenerateMipmapEXT;
COGL_PFNGLCREATEPROGRAMOBJECTARBPROC pf_glCreateProgramObjectARB;
COGL_PFNGLCREATESHADEROBJECTARBPROC pf_glCreateShaderObjectARB;
#endif
typedef void
- (APIENTRYP COGL_PFNGLGENRENDERBUFFERSEXTPROC)
+ (APIENTRYP COGL_PFNGLGENRENDERBUFFERSPROC)
(GLsizei n,
GLuint *renderbuffers);
typedef void
- (APIENTRYP COGL_PFNGLBINDRENDERBUFFEREXTPROC)
+ (APIENTRYP COGL_PFNGLBINDRENDERBUFFERPROC)
(GLenum target,
GLuint renderbuffer);
typedef void
- (APIENTRYP COGL_PFNGLRENDERBUFFERSTORAGEEXTPROC)
+ (APIENTRYP COGL_PFNGLRENDERBUFFERSTORAGEPROC)
(GLenum target,
GLenum internalformat,
GLsizei width,
GLsizei height);
typedef void
- (APIENTRYP COGL_PFNGLGENFRAMEBUFFERSEXTPROC)
+ (APIENTRYP COGL_PFNGLGENFRAMEBUFFERSPROC)
(GLsizei n,
GLuint *framebuffers);
typedef void
- (APIENTRYP COGL_PFNGLBINDFRAMEBUFFEREXTPROC)
+ (APIENTRYP COGL_PFNGLBINDFRAMEBUFFERPROC)
(GLenum target,
GLuint framebuffer);
typedef void
- (APIENTRYP COGL_PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)
+ (APIENTRYP COGL_PFNGLFRAMEBUFFERTEXTURE2DPROC)
(GLenum target,
GLenum attachment,
GLenum textarget,
GLint level);
typedef void
- (APIENTRYP COGL_PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)
+ (APIENTRYP COGL_PFNGLFRAMEBUFFERRENDERBUFFERPROC)
(GLenum target,
GLenum attachment,
GLenum renderbuffertarget,
GLuint renderbuffer);
typedef GLenum
- (APIENTRYP COGL_PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)
+ (APIENTRYP COGL_PFNGLCHECKFRAMEBUFFERSTATUSPROC)
(GLenum target);
typedef void
- (APIENTRYP COGL_PFNGLDELETEFRAMEBUFFERSEXTPROC)
+ (APIENTRYP COGL_PFNGLDELETEFRAMEBUFFERSPROC)
(GLsizei n,
const GLuint *framebuffers);
typedef void
- (APIENTRYP COGL_PFNGLDELETERENDERBUFFERSEXTPROC)
+ (APIENTRYP COGL_PFNGLDELETERENDERBUFFERSPROC)
(GLsizei n,
const GLuint *renderbuffers);
typedef void
+ (APIENTRYP COGL_PFNGLGENERATEMIPMAPPROC)
+ (GLenum target);
+
+typedef void
(APIENTRYP COGL_PFNGLBLITFRAMEBUFFEREXTPROC)
(GLint srcX0,
GLint srcY0,
GLsizei width,
GLsizei height);
-typedef void
- (APIENTRYP COGL_PFNGLGENERATEMIPMAPEXTPROC)
- (GLenum target);
-
typedef GLhandleARB
(APIENTRYP COGL_PFNGLCREATEPROGRAMOBJECTARBPROC)
(void);
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-#include "cogl-internal.h"
-#include "cogl-util.h"
-#include "cogl-texture-private.h"
-#include "cogl-fbo.h"
-#include "cogl-context.h"
-#include "cogl-handle.h"
-
-/* Expecting EXT functions not to be defined - redirect to pointers in context */
-#define glGenRenderbuffersEXT ctx->drv.pf_glGenRenderbuffersEXT
-#define glDeleteRenderbuffersEXT ctx->drv.pf_glDeleteRenderbuffersEXT
-#define glBindRenderbufferEXT ctx->drv.pf_glBindRenderbufferEXT
-#define glRenderbufferStorageEXT ctx->drv.pf_glRenderbufferStorageEXT
-#define glGenFramebuffersEXT ctx->drv.pf_glGenFramebuffersEXT
-#define glBindFramebufferEXT ctx->drv.pf_glBindFramebufferEXT
-#define glFramebufferTexture2DEXT ctx->drv.pf_glFramebufferTexture2DEXT
-#define glFramebufferRenderbufferEXT ctx->drv.pf_glFramebufferRenderbufferEXT
-#define glCheckFramebufferStatusEXT ctx->drv.pf_glCheckFramebufferStatusEXT
-#define glDeleteFramebuffersEXT ctx->drv.pf_glDeleteFramebuffersEXT
-#define glBlitFramebufferEXT ctx->drv.pf_glBlitFramebufferEXT
-#define glRenderbufferStorageMultisampleEXT ctx->drv.pf_glRenderbufferStorageMultisampleEXT
-
-#ifndef GL_READ_FRAMEBUFFER_EXT
-#define GL_READ_FRAMEBUFFER_EXT 0x8CA8
-#endif
-#ifndef GL_DRAW_FRAMEBUFFER_EXT
-#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9
-#endif
-
-static void _cogl_offscreen_free (CoglFbo *fbo);
-
-COGL_HANDLE_DEFINE (Fbo, offscreen);
-
-CoglHandle
-cogl_offscreen_new_to_texture (CoglHandle texhandle)
-{
- CoglFbo *fbo;
- int width;
- int height;
- GLuint tex_gl_handle;
- GLenum tex_gl_target;
- GLuint fbo_gl_handle;
- GLuint gl_stencil_handle;
- GLenum status;
-
- _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
-
- if (!cogl_features_available (COGL_FEATURE_OFFSCREEN))
- return COGL_INVALID_HANDLE;
-
- /* Make texhandle is a valid texture object */
- if (!cogl_is_texture (texhandle))
- return COGL_INVALID_HANDLE;
-
- /* The texture must not be sliced */
- if (cogl_texture_is_sliced (texhandle))
- return COGL_INVALID_HANDLE;
-
- /* Pick the single texture slice width, height and GL id */
-
- width = cogl_texture_get_width (texhandle);
- height = cogl_texture_get_height (texhandle);
-
- if (!cogl_texture_get_gl_texture (texhandle, &tex_gl_handle, &tex_gl_target))
- return COGL_INVALID_HANDLE;
-
- if (tex_gl_target != GL_TEXTURE_2D)
- return COGL_INVALID_HANDLE;
-
- /* Create a renderbuffer for stenciling */
- GE( glGenRenderbuffersEXT (1, &gl_stencil_handle) );
- GE( glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, gl_stencil_handle) );
- GE( glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX8_EXT,
- cogl_texture_get_width (texhandle),
- cogl_texture_get_height (texhandle)) );
- GE( glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, 0) );
-
- /* Generate framebuffer */
- glGenFramebuffersEXT (1, &fbo_gl_handle);
- GE( glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, fbo_gl_handle) );
- GE( glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
- tex_gl_target, tex_gl_handle, 0) );
- GE( glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT,
- GL_STENCIL_ATTACHMENT_EXT,
- GL_RENDERBUFFER_EXT, gl_stencil_handle) );
-
- /* XXX: The framebuffer_object spec isn't clear in defining whether attaching
- * a texture as a renderbuffer with mipmap filtering enabled while the
- * mipmaps have not been uploaded should result in an incomplete framebuffer
- * object. (different drivers make different decisions)
- *
- * To avoid an error with drivers that do consider this a problem we
- * explicitly set non mipmapped filters here. These will later be reset when
- * the texture is actually used for rendering according to the filters set on
- * the corresponding CoglMaterial.
- */
- _cogl_texture_set_filters (texhandle, GL_NEAREST, GL_NEAREST);
-
- /* Make sure it's complete */
- status = glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT);
-
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
- {
- /* Stencil renderbuffers aren't always supported. Try again
- without the stencil buffer */
- GE( glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT,
- GL_STENCIL_ATTACHMENT_EXT,
- GL_RENDERBUFFER_EXT,
- 0) );
- GE( glDeleteRenderbuffersEXT (1, &gl_stencil_handle) );
- gl_stencil_handle = 0;
-
- status = glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT);
-
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
- {
- /* Still failing, so give up */
- GE( glDeleteFramebuffersEXT (1, &fbo_gl_handle) );
- GE( glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0) );
- return COGL_INVALID_HANDLE;
- }
- }
-
- GE( glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0) );
-
- /* Allocate and init a CoglFbo object (store non-wasted size
- for subsequent blits and viewport setup) */
- fbo = (CoglFbo*) g_malloc (sizeof (CoglFbo));
- fbo->width = width;
- fbo->height = height;
- fbo->gl_handle = fbo_gl_handle;
- fbo->gl_stencil_handle = gl_stencil_handle;
-
- return _cogl_offscreen_handle_new (fbo);
-}
-
-static void
-_cogl_offscreen_free (CoglFbo *fbo)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- /* Frees FBO resources but its handle is not
- released! Do that separately before this! */
- if (fbo->gl_stencil_handle)
- GE( glDeleteRenderbuffersEXT (1, &fbo->gl_stencil_handle) );
- GE( glDeleteFramebuffersEXT (1, &fbo->gl_handle) );
- g_free (fbo);
-}
-
-void
-cogl_set_draw_buffer (CoglBufferTarget target, CoglHandle offscreen)
-{
- CoglFbo *fbo = NULL;
- CoglDrawBufferState *draw_buffer;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- _cogl_journal_flush ();
-
- g_assert (ctx->draw_buffer_stack != NULL);
- draw_buffer = ctx->draw_buffer_stack->data;
-
- if (target == COGL_OFFSCREEN_BUFFER)
- {
- /* Make sure it is a valid fbo handle */
- if (!cogl_is_offscreen (offscreen))
- return;
-
- fbo = _cogl_offscreen_pointer_from_handle (offscreen);
-
- /* Check current draw buffer target */
- if (draw_buffer->target != COGL_OFFSCREEN_BUFFER)
- {
- /* Push the viewport and matrix setup if redirecting
- from a non-screen buffer */
- GE( glPushAttrib (GL_VIEWPORT_BIT) );
-
- _cogl_matrix_stack_push (ctx->projection_stack);
- _cogl_matrix_stack_load_identity (ctx->projection_stack);
-
- _cogl_matrix_stack_push (ctx->modelview_stack);
- _cogl_matrix_stack_load_identity (ctx->modelview_stack);
- }
- else
- {
- /* Override viewport and matrix setup if redirecting
- from another offscreen buffer */
- _cogl_matrix_stack_load_identity (ctx->projection_stack);
-
- _cogl_matrix_stack_load_identity (ctx->modelview_stack);
- }
-
- /* Setup new viewport and matrices */
- cogl_viewport (fbo->width, fbo->height);
- _cogl_matrix_stack_translate (ctx->modelview_stack, -1.0f, -1.0f, 0.0f);
- _cogl_matrix_stack_scale (ctx->modelview_stack, 2.0f / fbo->width, 2.0f / fbo->height, 1.0f);
-
- /* Bind offscreen framebuffer object */
- GE( glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, fbo->gl_handle) );
- GE( glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE) );
- }
- else if (target & COGL_WINDOW_BUFFER)
- {
- /* Check current draw buffer target */
- if (draw_buffer->target == COGL_OFFSCREEN_BUFFER)
- {
- /* Pop viewport and matrices if redirecting back
- from an offscreen buffer */
- GE( glPopAttrib () );
-
- _cogl_matrix_stack_pop (ctx->projection_stack);
-
- _cogl_matrix_stack_pop (ctx->modelview_stack);
- }
-
- /* Bind window framebuffer object */
- GE( glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0) );
- }
-
- /* Store new target */
- draw_buffer->target = target;
- if (draw_buffer->offscreen != offscreen)
- {
- if (draw_buffer->offscreen != COGL_INVALID_HANDLE)
- cogl_handle_unref (draw_buffer->offscreen);
- if (offscreen != COGL_INVALID_HANDLE)
- cogl_handle_ref (offscreen);
- draw_buffer->offscreen = offscreen;
- }
-}
-
-void
-cogl_push_draw_buffer(void)
-{
- CoglDrawBufferState *old;
- CoglDrawBufferState *draw_buffer;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- g_assert (ctx->draw_buffer_stack != NULL);
- old = ctx->draw_buffer_stack->data;
-
- draw_buffer = g_slice_new0 (CoglDrawBufferState);
- *draw_buffer = *old;
-
- ctx->draw_buffer_stack =
- g_slist_prepend (ctx->draw_buffer_stack, draw_buffer);
-}
-
-void
-cogl_pop_draw_buffer(void)
-{
- CoglDrawBufferState *to_pop;
- CoglDrawBufferState *to_restore;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- g_assert (ctx->draw_buffer_stack != NULL);
- if (ctx->draw_buffer_stack->next == NULL)
- {
- g_warning ("1 more cogl_pop_draw_buffer() than cogl_push_draw_buffer()");
- return;
- }
-
- to_pop = ctx->draw_buffer_stack->data;
- to_restore = ctx->draw_buffer_stack->next->data;
-
- /* the logic in cogl_set_draw_buffer() only works if
- * to_pop is still on top of the stack, because
- * cogl_set_draw_buffer() needs to know the previous
- * state.
- */
- cogl_set_draw_buffer (to_restore->target, to_restore->offscreen);
-
- /* cogl_set_draw_buffer() should have set top of stack
- * to to_restore
- */
- g_assert (to_restore->target == to_pop->target);
- g_assert (to_restore->offscreen == to_pop->offscreen);
-
- g_assert (ctx->draw_buffer_stack->data == to_pop);
- ctx->draw_buffer_stack =
- g_slist_remove_link (ctx->draw_buffer_stack,
- ctx->draw_buffer_stack);
-
- g_slice_free (CoglDrawBufferState, to_pop);
-}
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,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.
- */
-
-#ifndef __COGL_FBO_H
-#define __COGL_FBO_H
-
-#include "cogl-handle.h"
-
-typedef struct
-{
- CoglHandleObject _parent;
- int width;
- int height;
- GLuint gl_handle;
- GLuint gl_stencil_handle;
-
-} CoglFbo;
-
-#endif /* __COGL_FBO_H */
#include "cogl-context.h"
#include "cogl-clip-stack.h"
#include "cogl-material-private.h"
+#include "cogl-clip-stack.h"
+#include "cogl-draw-buffer-private.h"
#include <string.h>
#include <gmodule.h>
}
void
-_cogl_path_stroke_nodes ()
+_cogl_path_stroke_nodes (void)
{
guint path_start = 0;
gulong enable_flags = COGL_ENABLE_VERTEX_ARRAY;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
+ _cogl_journal_flush ();
+
+ /* NB: _cogl_draw_buffer_flush_state may disrupt various state (such
+ * as the material state) when flushing the clip stack, so should
+ * always be done first when preparing to draw. */
+ _cogl_draw_buffer_flush_state (_cogl_get_draw_buffer (), 0);
+
enable_flags |= _cogl_material_get_cogl_enable_flags (ctx->source_material);
cogl_enable (enable_flags);
options.disable_layers = (guint32)~0;
_cogl_material_flush_gl_state (ctx->source_material, &options);
- _cogl_flush_matrix_stacks ();
while (path_start < ctx->path_nodes->len)
{
CoglPathNode *path,
gboolean merge)
{
- guint path_start = 0;
- guint sub_path_num = 0;
- float bounds_x;
- float bounds_y;
- float bounds_w;
- float bounds_h;
- gulong enable_flags = COGL_ENABLE_VERTEX_ARRAY;
- CoglHandle prev_source;
- int i;
+ guint path_start = 0;
+ guint sub_path_num = 0;
+ float bounds_x;
+ float bounds_y;
+ float bounds_w;
+ float bounds_h;
+ gulong enable_flags = COGL_ENABLE_VERTEX_ARRAY;
+ CoglHandle prev_source;
+ int i;
+ CoglHandle draw_buffer = _cogl_get_draw_buffer ();
+ CoglMatrixStack *modelview_stack =
+ _cogl_draw_buffer_get_modelview_stack (draw_buffer);
+ CoglMatrixStack *projection_stack =
+ _cogl_draw_buffer_get_projection_stack (draw_buffer);
+
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
+ /* We don't track changes to the stencil buffer in the journal
+ * so we need to flush any batched geometry first */
_cogl_journal_flush ();
+ /* NB: _cogl_draw_buffer_flush_state may disrupt various state (such
+ * as the material state) when flushing the clip stack, so should
+ * always be done first when preparing to draw. */
+ _cogl_draw_buffer_flush_state (draw_buffer, 0);
+
/* Just setup a simple material that doesn't use texturing... */
prev_source = cogl_handle_ref (ctx->source_material);
cogl_set_source (ctx->stencil_material);
}
else
{
- GE( glClear (GL_STENCIL_BUFFER_BIT) );
+ cogl_clear (NULL, COGL_BUFFER_BIT_STENCIL);
GE( glStencilMask (1) );
GE( glStencilFunc (GL_LEQUAL, 0x1, 0x3) );
}
}
ctx->n_texcoord_arrays_enabled = 0;
- _cogl_flush_matrix_stacks ();
-
while (path_start < path_size)
{
GE( glVertexPointer (2, GL_FLOAT, sizeof (CoglPathNode),
significant bit */
GE( glStencilMask (merge ? 6 : 3) );
GE( glStencilOp (GL_ZERO, GL_REPLACE, GL_REPLACE) );
- glRectf (bounds_x, bounds_y,
- bounds_x + bounds_w, bounds_y + bounds_h);
+ cogl_rectangle (bounds_x, bounds_y,
+ bounds_x + bounds_w, bounds_y + bounds_h);
+ /* Make sure the rectangle hits the stencil buffer before
+ * directly changing other GL state. */
+ _cogl_journal_flush ();
+ /* NB: The journal flushing may trash the modelview state and
+ * enable flags */
+ _cogl_matrix_stack_flush_to_gl (modelview_stack,
+ COGL_MATRIX_MODELVIEW);
+ cogl_enable (enable_flags);
+
GE( glStencilOp (GL_INVERT, GL_INVERT, GL_INVERT) );
}
/* Decrement all of the bits twice so that only pixels where the
value is 3 will remain */
- _cogl_matrix_stack_push (ctx->projection_stack);
- _cogl_matrix_stack_load_identity (ctx->projection_stack);
-
- _cogl_matrix_stack_push (ctx->modelview_stack);
- _cogl_matrix_stack_load_identity (ctx->modelview_stack);
+ _cogl_matrix_stack_push (projection_stack);
+ _cogl_matrix_stack_load_identity (projection_stack);
+ _cogl_matrix_stack_flush_to_gl (projection_stack,
+ COGL_MATRIX_PROJECTION);
- _cogl_flush_matrix_stacks ();
+ _cogl_matrix_stack_push (modelview_stack);
+ _cogl_matrix_stack_load_identity (modelview_stack);
+ _cogl_matrix_stack_flush_to_gl (modelview_stack,
+ COGL_MATRIX_MODELVIEW);
- glRectf (-1.0, -1.0, 1.0, 1.0);
- glRectf (-1.0, -1.0, 1.0, 1.0);
+ cogl_rectangle (-1.0, -1.0, 1.0, 1.0);
+ cogl_rectangle (-1.0, -1.0, 1.0, 1.0);
+ /* Make sure these rectangles hit the stencil buffer before we
+ * restore the stencil op/func. */
+ _cogl_journal_flush ();
- _cogl_matrix_stack_pop (ctx->modelview_stack);
- _cogl_matrix_stack_pop (ctx->projection_stack);
+ _cogl_matrix_stack_pop (modelview_stack);
+ _cogl_matrix_stack_pop (projection_stack);
}
GE( glStencilMask (~(GLuint) 0) );
}
void
-_cogl_path_fill_nodes ()
+_cogl_path_fill_nodes (void)
{
+ CoglHandle draw_buffer;
+ CoglClipStackState *clip_state;
float bounds_x;
float bounds_y;
float bounds_w;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
+ _cogl_journal_flush ();
+
+ draw_buffer = _cogl_get_draw_buffer ();
+ clip_state = _cogl_draw_buffer_get_clip_state (draw_buffer);
+
_cogl_path_get_bounds (ctx->path_nodes_min, ctx->path_nodes_max,
&bounds_x, &bounds_y, &bounds_w, &bounds_h);
ctx->path_nodes->len,
&g_array_index (ctx->path_nodes,
CoglPathNode, 0),
- ctx->clip.stencil_used);
+ clip_state->stencil_used);
cogl_rectangle (bounds_x, bounds_y,
bounds_x + bounds_w, bounds_y + bounds_h);
/* The stencil buffer now contains garbage so the clip area needs to
be rebuilt */
- ctx->clip.stack_dirty = TRUE;
+ _cogl_clip_stack_state_dirty (clip_state);
}
+
#include <stdlib.h>
#include <math.h>
-#define glGenerateMipmap ctx->drv.pf_glGenerateMipmapEXT
+#define glGenerateMipmap ctx->drv.pf_glGenerateMipmap
void
_cogl_texture_driver_bind (GLenum gl_target,
#include "cogl-internal.h"
#include "cogl-context.h"
+typedef struct _CoglGLSymbolTableEntry
+{
+ const char *name;
+ void *ptr;
+} CoglGLSymbolTableEntry;
+
gboolean
cogl_check_extension (const gchar *name, const gchar *ext)
{
return FALSE;
}
+gboolean
+_cogl_resolve_gl_symbols (CoglGLSymbolTableEntry *symbol_table,
+ const char *suffix)
+{
+ int i;
+ gboolean status = TRUE;
+ for (i = 0; symbol_table[i].name; i++)
+ {
+ char *full_name = g_strdup_printf ("%s%s", symbol_table[i].name, suffix);
+ *((CoglFuncPtr *)symbol_table[i].ptr) = cogl_get_proc_address (full_name);
+ g_free (full_name);
+ if (!*((CoglFuncPtr *)symbol_table[i].ptr))
+ {
+ status = FALSE;
+ break;
+ }
+ }
+ return status;
+}
+
#ifdef HAVE_CLUTTER_OSX
static gboolean
really_enable_npot (void)
const gchar *gl_extensions;
GLint max_clip_planes = 0;
GLint num_stencil_bits = 0;
+ gboolean fbo_ARB = FALSE;
+ gboolean fbo_EXT = FALSE;
+ const char *suffix;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
flags |= COGL_FEATURE_SHADERS_GLSL;
}
- if (cogl_check_extension ("GL_EXT_framebuffer_object", gl_extensions) ||
- cogl_check_extension ("GL_ARB_framebuffer_object", gl_extensions))
+ fbo_ARB = cogl_check_extension ("GL_ARB_framebuffer_object", gl_extensions);
+ if (fbo_ARB)
+ suffix = "";
+ else
+ {
+ fbo_EXT = cogl_check_extension ("GL_EXT_framebuffer_object", gl_extensions);
+ if (fbo_EXT)
+ suffix = "EXT";
+ }
+
+ if (fbo_ARB || fbo_EXT)
{
- ctx->drv.pf_glGenRenderbuffersEXT =
- (COGL_PFNGLGENRENDERBUFFERSEXTPROC)
- cogl_get_proc_address ("glGenRenderbuffersEXT");
-
- ctx->drv.pf_glDeleteRenderbuffersEXT =
- (COGL_PFNGLDELETERENDERBUFFERSEXTPROC)
- cogl_get_proc_address ("glDeleteRenderbuffersEXT");
-
- ctx->drv.pf_glBindRenderbufferEXT =
- (COGL_PFNGLBINDRENDERBUFFEREXTPROC)
- cogl_get_proc_address ("glBindRenderbufferEXT");
-
- ctx->drv.pf_glRenderbufferStorageEXT =
- (COGL_PFNGLRENDERBUFFERSTORAGEEXTPROC)
- cogl_get_proc_address ("glRenderbufferStorageEXT");
-
- ctx->drv.pf_glGenFramebuffersEXT =
- (COGL_PFNGLGENFRAMEBUFFERSEXTPROC)
- cogl_get_proc_address ("glGenFramebuffersEXT");
-
- ctx->drv.pf_glBindFramebufferEXT =
- (COGL_PFNGLBINDFRAMEBUFFEREXTPROC)
- cogl_get_proc_address ("glBindFramebufferEXT");
-
- ctx->drv.pf_glFramebufferTexture2DEXT =
- (COGL_PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)
- cogl_get_proc_address ("glFramebufferTexture2DEXT");
-
- ctx->drv.pf_glFramebufferRenderbufferEXT =
- (COGL_PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)
- cogl_get_proc_address ("glFramebufferRenderbufferEXT");
-
- ctx->drv.pf_glCheckFramebufferStatusEXT =
- (COGL_PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)
- cogl_get_proc_address ("glCheckFramebufferStatusEXT");
-
- ctx->drv.pf_glDeleteFramebuffersEXT =
- (COGL_PFNGLDELETEFRAMEBUFFERSEXTPROC)
- cogl_get_proc_address ("glDeleteFramebuffersEXT");
-
- ctx->drv.pf_glGenerateMipmapEXT =
- (COGL_PFNGLGENERATEMIPMAPEXTPROC)
- cogl_get_proc_address ("glGenerateMipmapEXT");
-
- if (ctx->drv.pf_glGenRenderbuffersEXT &&
- ctx->drv.pf_glBindRenderbufferEXT &&
- ctx->drv.pf_glRenderbufferStorageEXT &&
- ctx->drv.pf_glGenFramebuffersEXT &&
- ctx->drv.pf_glBindFramebufferEXT &&
- ctx->drv.pf_glFramebufferTexture2DEXT &&
- ctx->drv.pf_glFramebufferRenderbufferEXT &&
- ctx->drv.pf_glCheckFramebufferStatusEXT &&
- ctx->drv.pf_glDeleteFramebuffersEXT &&
- ctx->drv.pf_glGenerateMipmapEXT)
- flags |= COGL_FEATURE_OFFSCREEN;
+ CoglGLSymbolTableEntry symbol_table[] = {
+ {"glGenRenderbuffers", &ctx->drv.pf_glGenRenderbuffers},
+ {"glDeleteRenderbuffers", &ctx->drv.pf_glDeleteRenderbuffers},
+ {"glBindRenderbuffer", &ctx->drv.pf_glBindRenderbuffer},
+ {"glRenderbufferStorage", &ctx->drv.pf_glRenderbufferStorage},
+ {"glGenFramebuffers", &ctx->drv.pf_glGenFramebuffers},
+ {"glBindFramebuffer", &ctx->drv.pf_glBindFramebuffer},
+ {"glFramebufferTexture2D", &ctx->drv.pf_glFramebufferTexture2D},
+ {"glFramebufferRenderbuffer", &ctx->drv.pf_glFramebufferRenderbuffer},
+ {"glCheckFramebufferStatus", &ctx->drv.pf_glCheckFramebufferStatus},
+ {"glDeleteFramebuffers", &ctx->drv.pf_glDeleteFramebuffers},
+ {"glGenerateMipmap", &ctx->drv.pf_glGenerateMipmap},
+ {NULL, NULL}
+ };
+
+ if (_cogl_resolve_gl_symbols (symbol_table, suffix))
+ flags |= COGL_FEATURE_OFFSCREEN;
}
if (cogl_check_extension ("GL_EXT_framebuffer_blit", gl_extensions))
$(CLUTTER_DEBUG_CFLAGS) \
$(MAINTAINER_CFLAGS)
libclutter_cogl_driver_la_SOURCES = \
- cogl-fbo.h \
cogl.c \
cogl-primitives.c \
cogl-texture-driver.c \
- cogl-fbo.c \
cogl-context-driver.c \
cogl-context-driver.h \
cogl-gles2-wrapper.h \
void
_cogl_create_context_driver (CoglContext *context)
{
+ context->drv.pf_glGenRenderbuffers = NULL;
+ context->drv.pf_glBindRenderbuffer = NULL;
+ context->drv.pf_glRenderbufferStorage = NULL;
+ context->drv.pf_glGenFramebuffers = NULL;
+ context->drv.pf_glBindFramebuffer = NULL;
+ context->drv.pf_glFramebufferTexture2D = NULL;
+ context->drv.pf_glFramebufferRenderbuffer = NULL;
+ context->drv.pf_glCheckFramebufferStatus = NULL;
+ context->drv.pf_glDeleteFramebuffers = NULL;
+
/* Init the GLES2 wrapper */
#ifdef HAVE_COGL_GLES2
cogl_gles2_wrapper_init (&context->drv.gles2);
#ifndef __COGL_CONTEXT_DRIVER_H
#define __COGL_CONTEXT_DRIVER_H
+#include "cogl.h"
#include "cogl-gles2-wrapper.h"
typedef struct _CoglContextDriver
{
+ COGL_PFNGLGENRENDERBUFFERSPROC pf_glGenRenderbuffers;
+ COGL_PFNGLDELETERENDERBUFFERSPROC pf_glDeleteRenderbuffers;
+ COGL_PFNGLBINDRENDERBUFFERPROC pf_glBindRenderbuffer;
+ COGL_PFNGLRENDERBUFFERSTORAGEPROC pf_glRenderbufferStorage;
+ COGL_PFNGLGENFRAMEBUFFERSPROC pf_glGenFramebuffers;
+ COGL_PFNGLBINDFRAMEBUFFERPROC pf_glBindFramebuffer;
+ COGL_PFNGLFRAMEBUFFERTEXTURE2DPROC pf_glFramebufferTexture2D;
+ COGL_PFNGLFRAMEBUFFERRENDERBUFFERPROC pf_glFramebufferRenderbuffer;
+ COGL_PFNGLCHECKFRAMEBUFFERSTATUSPROC pf_glCheckFramebufferStatus;
+ COGL_PFNGLDELETEFRAMEBUFFERSPROC pf_glDeleteFramebuffers;
+ COGL_PFNGLGENERATEMIPMAPPROC pf_glGenerateMipmap;
+
#ifdef HAVE_COGL_GLES2
CoglGles2Wrapper gles2;
-
- /* Viewport store for FBOs. Needed because glPushAttrib() isn't
- supported */
- GLint viewport_store[4];
#endif
} CoglContextDriver;
#define CGL_SHININESS 0x1601
#endif
+/* Extension function prototypes */
+
+#ifndef APIENTRY
+#define APIENTRY
+#endif
+
+#ifndef APIENTRYP
+#define APIENTRYP APIENTRY *
+#endif
+
+typedef void
+ (APIENTRYP COGL_PFNGLGENRENDERBUFFERSPROC)
+ (GLsizei n,
+ GLuint *renderbuffers);
+
+typedef void
+ (APIENTRYP COGL_PFNGLBINDRENDERBUFFERPROC)
+ (GLenum target,
+ GLuint renderbuffer);
+
+typedef void
+ (APIENTRYP COGL_PFNGLRENDERBUFFERSTORAGEPROC)
+ (GLenum target,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+
+typedef void
+ (APIENTRYP COGL_PFNGLGENFRAMEBUFFERSPROC)
+ (GLsizei n,
+ GLuint *framebuffers);
+
+typedef void
+ (APIENTRYP COGL_PFNGLBINDFRAMEBUFFERPROC)
+ (GLenum target,
+ GLuint framebuffer);
+
+typedef void
+ (APIENTRYP COGL_PFNGLFRAMEBUFFERTEXTURE2DPROC)
+ (GLenum target,
+ GLenum attachment,
+ GLenum textarget,
+ GLuint texture,
+ GLint level);
+
+typedef void
+ (APIENTRYP COGL_PFNGLFRAMEBUFFERRENDERBUFFERPROC)
+ (GLenum target,
+ GLenum attachment,
+ GLenum renderbuffertarget,
+ GLuint renderbuffer);
+
+typedef GLenum
+ (APIENTRYP COGL_PFNGLCHECKFRAMEBUFFERSTATUSPROC)
+ (GLenum target);
+
+typedef void
+ (APIENTRYP COGL_PFNGLDELETEFRAMEBUFFERSPROC)
+ (GLsizei n,
+ const GLuint *framebuffers);
+
+typedef void
+ (APIENTRYP COGL_PFNGLDELETERENDERBUFFERSPROC)
+ (GLsizei n,
+ const GLuint *renderbuffers);
+
+typedef void
+ (APIENTRYP COGL_PFNGLGENERATEMIPMAPPROC)
+ (GLenum target);
+
G_END_DECLS
#endif
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2008,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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-#include "cogl-internal.h"
-#include "cogl-util.h"
-#include "cogl-texture-private.h"
-#include "cogl-fbo.h"
-#include "cogl-context.h"
-#include "cogl-handle.h"
-#include "cogl-gles2-wrapper.h"
-
-#ifdef HAVE_COGL_GLES2
-
-static void _cogl_offscreen_free (CoglFbo *fbo);
-
-COGL_HANDLE_DEFINE (Fbo, offscreen);
-
-CoglHandle
-cogl_offscreen_new_to_texture (CoglHandle texhandle)
-{
- CoglFbo *fbo;
- int width;
- int height;
- GLuint tex_gl_handle;
- GLenum tex_gl_target;
- GLuint fbo_gl_handle;
- GLuint gl_stencil_handle;
- GLenum status;
-
- _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
-
- if (!cogl_features_available (COGL_FEATURE_OFFSCREEN))
- return COGL_INVALID_HANDLE;
-
- /* Make texhandle is a valid texture object */
- if (!cogl_is_texture (texhandle))
- return COGL_INVALID_HANDLE;
-
- /* The texture must not be sliced */
- if (cogl_texture_is_sliced (texhandle))
- return COGL_INVALID_HANDLE;
-
- /* Pick the single texture slice width, height and GL id */
-
- width = cogl_texture_get_width (texhandle);
- height = cogl_texture_get_height (texhandle);
-
- if (!cogl_texture_get_gl_texture (texhandle, &tex_gl_handle, &tex_gl_target))
- return COGL_INVALID_HANDLE;
-
- if (tex_gl_target != GL_TEXTURE_2D)
- return COGL_INVALID_HANDLE;
-
- /* Create a renderbuffer for stenciling */
- GE( glGenRenderbuffers (1, &gl_stencil_handle) );
- GE( glBindRenderbuffer (GL_RENDERBUFFER, gl_stencil_handle) );
- GE( glRenderbufferStorage (GL_RENDERBUFFER, GL_STENCIL_INDEX8,
- cogl_texture_get_width (texhandle),
- cogl_texture_get_height (texhandle)) );
- GE( glBindRenderbuffer (GL_RENDERBUFFER, 0) );
-
- /* Generate framebuffer */
- glGenFramebuffers (1, &fbo_gl_handle);
- GE( glBindFramebuffer (GL_FRAMEBUFFER, fbo_gl_handle) );
- GE( glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- tex_gl_target, tex_gl_handle, 0) );
- GE( glFramebufferRenderbuffer (GL_FRAMEBUFFER,
- GL_STENCIL_ATTACHMENT,
- GL_RENDERBUFFER, gl_stencil_handle) );
-
- /* Make sure it's complete */
- status = glCheckFramebufferStatus (GL_FRAMEBUFFER);
-
- if (status != GL_FRAMEBUFFER_COMPLETE)
- {
- /* Stencil renderbuffers aren't always supported. Try again
- without the stencil buffer */
- GE( glFramebufferRenderbuffer (GL_FRAMEBUFFER,
- GL_STENCIL_ATTACHMENT,
- GL_RENDERBUFFER,
- 0) );
- GE( glDeleteRenderbuffers (1, &gl_stencil_handle) );
- gl_stencil_handle = 0;
-
- status = glCheckFramebufferStatus (GL_FRAMEBUFFER);
-
- if (status != GL_FRAMEBUFFER_COMPLETE)
- {
- /* Still failing, so give up */
- GE( glDeleteFramebuffers (1, &fbo_gl_handle) );
- GE( glBindFramebuffer (GL_FRAMEBUFFER, 0) );
- return COGL_INVALID_HANDLE;
- }
- }
-
- GE( glBindFramebuffer (GL_FRAMEBUFFER, 0) );
-
- /* Allocate and init a CoglFbo object (store non-wasted size
- for subsequent blits and viewport setup) */
- fbo = (CoglFbo*) g_malloc (sizeof (CoglFbo));
- fbo->width = width;
- fbo->height = height;
- fbo->gl_handle = fbo_gl_handle;
- fbo->gl_stencil_handle = gl_stencil_handle;
-
- return _cogl_offscreen_handle_new (fbo);
-}
-
-static void
-_cogl_offscreen_free (CoglFbo *fbo)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- /* Frees FBO resources but its handle is not
- released! Do that separately before this! */
- if (fbo->gl_stencil_handle)
- GE( glDeleteRenderbuffers (1, &fbo->gl_stencil_handle) );
- GE( glDeleteFramebuffers (1, &fbo->gl_handle) );
- g_free (fbo);
-}
-
-void
-cogl_set_draw_buffer (CoglBufferTarget target, CoglHandle offscreen)
-{
- CoglFbo *fbo = NULL;
- CoglDrawBufferState *draw_buffer;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- _cogl_journal_flush ();
-
- g_assert (ctx->draw_buffer_stack != NULL);
- draw_buffer = ctx->draw_buffer_stack->data;
-
- if (target == COGL_OFFSCREEN_BUFFER)
- {
- /* Make sure it is a valid fbo handle */
- if (!cogl_is_offscreen (offscreen))
- return;
-
- fbo = _cogl_offscreen_pointer_from_handle (offscreen);
-
- /* Check current draw buffer target */
- if (draw_buffer->target != COGL_OFFSCREEN_BUFFER)
- {
- /* Push the viewport and matrix setup if redirecting
- from a non-screen buffer */
- GE( glGetIntegerv (GL_VIEWPORT, ctx->drv.viewport_store) );
-
- _cogl_matrix_stack_push (ctx->projection_stack);
- _cogl_matrix_stack_load_identity (ctx->projection_stack);
-
- _cogl_matrix_stack_push (ctx->modelview_stack);
- _cogl_matrix_stack_load_identity (ctx->modelview_stack);
- }
- else
- {
- /* Override viewport and matrix setup if redirecting
- from another offscreen buffer */
- _cogl_matrix_stack_load_identity (ctx->projection_stack);
-
- _cogl_matrix_stack_load_identity (ctx->modelview_stack);
- }
-
- /* Setup new viewport and matrices */
-<<<<<<< HEAD:clutter/cogl/cogl/driver/gles/cogl-fbo.c
- GE( glViewport (0, 0, fbo->width, fbo->height) );
- _cogl_matrix_stack_translate (ctx->modelview_stack, -1.0f, -1.0f, 0.0f);
- _cogl_matrix_stack_scale (ctx->modelview_stack,
- 2.0f / fbo->width, 2.0f / fbo->height, 1.0f);
-=======
- cogl_viewport (fbo->width, fbo->height);
- _cogl_current_matrix_translate (-1.0f, -1.0f, 0.0f);
- _cogl_current_matrix_scale (2.0f / fbo->width, 2.0f / fbo->height, 1.0f);
->>>>>>> c3e471c... [cogl-fbo] Bring the gles code more in line with gl code:clutter/cogl/cogl/driver/gles/cogl-fbo.c
-
- /* Bind offscreen framebuffer object */
- GE( glBindFramebuffer (GL_FRAMEBUFFER, fbo->gl_handle) );
- GE( glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE) );
- }
- else if (target & COGL_WINDOW_BUFFER)
- {
- /* Check current draw buffer target */
- if (draw_buffer->target == COGL_OFFSCREEN_BUFFER)
- {
- /* Pop viewport and matrices if redirecting back
- from an offscreen buffer */
- GE( glViewport (ctx->drv.viewport_store[0],
- ctx->drv.viewport_store[1],
- ctx->drv.viewport_store[2],
- ctx->drv.viewport_store[3]) );
-
- _cogl_matrix_stack_pop (ctx->projection_stack);
-
- _cogl_matrix_stack_pop (ctx->modelview_stack);
- }
-
- /* Bind window framebuffer object */
- GE( glBindFramebuffer (GL_FRAMEBUFFER, 0) );
- }
-
- /* Store new target */
- draw_buffer->target = target;
- if (draw_buffer->offscreen != offscreen)
- {
- if (draw_buffer->offscreen != COGL_INVALID_HANDLE)
- cogl_handle_unref (draw_buffer->offscreen);
- if (offscreen != COGL_INVALID_HANDLE)
- cogl_handle_ref (offscreen);
- draw_buffer->offscreen = offscreen;
- }
-}
-
-void
-cogl_push_draw_buffer(void)
-{
- CoglDrawBufferState *old;
- CoglDrawBufferState *draw_buffer;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- g_assert (ctx->draw_buffer_stack != NULL);
- old = ctx->draw_buffer_stack->data;
-
- draw_buffer = g_slice_new0 (CoglDrawBufferState);
- *draw_buffer = *old;
-
- ctx->draw_buffer_stack =
- g_slist_prepend (ctx->draw_buffer_stack, draw_buffer);
-}
-
-void
-cogl_pop_draw_buffer(void)
-{
- CoglDrawBufferState *to_pop;
- CoglDrawBufferState *to_restore;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- g_assert (ctx->draw_buffer_stack != NULL);
- if (ctx->draw_buffer_stack->next == NULL)
- {
- g_warning ("1 more cogl_pop_draw_buffer() than cogl_push_draw_buffer()");
- return;
- }
-
- to_pop = ctx->draw_buffer_stack->data;
- to_restore = ctx->draw_buffer_stack->next->data;
-
- /* the logic in cogl_set_draw_buffer() only works if
- * to_pop is still on top of the stack, because
- * cogl_set_draw_buffer() needs to know the previous
- * state.
- */
- cogl_set_draw_buffer (to_restore->target, to_restore->offscreen);
-
- /* cogl_set_draw_buffer() should have set top of stack
- * to to_restore
- */
- g_assert (to_restore->target == to_pop->target);
- g_assert (to_restore->offscreen == to_pop->offscreen);
-
- g_assert (ctx->draw_buffer_stack->data == to_pop);
- ctx->draw_buffer_stack =
- g_slist_remove_link (ctx->draw_buffer_stack,
- ctx->draw_buffer_stack);
-
- g_slice_free (CoglDrawBufferState, to_pop);
-}
-
-#else /* HAVE_COGL_GLES2 */
-
-/* No support on regular OpenGL 1.1 */
-
-gboolean
-cogl_is_offscreen (CoglHandle handle)
-{
- return FALSE;
-}
-
-CoglHandle
-cogl_offscreen_new_to_texture (CoglHandle texhandle)
-{
- return COGL_INVALID_HANDLE;
-}
-
-CoglHandle
-cogl_offscreen_ref (CoglHandle handle)
-{
- return COGL_INVALID_HANDLE;
-}
-
-void
-cogl_offscreen_unref (CoglHandle handle)
-{
-}
-
-void
-cogl_set_draw_buffer (CoglBufferTarget target, CoglHandle offscreen)
-{
-}
-
-#endif /* HAVE_COGL_GLES2 */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,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.
- */
-
-#ifndef __COGL_FBO_H
-#define __COGL_FBO_H
-
-#include "cogl-handle.h"
-
-typedef struct
-{
- CoglHandleObject _parent;
- int width;
- int height;
- GLuint gl_handle;
- GLuint gl_stencil_handle;
-
-} CoglFbo;
-
-#endif /* __COGL_FBO_H */
#include "cogl-context.h"
#include "cogl-clip-stack.h"
#include "cogl-material-private.h"
+#include "cogl-clip-stack.h"
+#include "cogl-draw-buffer-private.h"
+#include "cogl-clip-stack.h"
#include <string.h>
#include <gmodule.h>
}
void
-_cogl_path_stroke_nodes ()
+_cogl_path_stroke_nodes (void)
{
guint path_start = 0;
gulong enable_flags = COGL_ENABLE_VERTEX_ARRAY;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
+ _cogl_journal_flush ();
+
+ /* NB: _cogl_draw_buffer_flush_state may disrupt various state (such
+ * as the material state) when flushing the clip stack, so should
+ * always be done first when preparing to draw. */
+ _cogl_draw_buffer_flush_state (_cogl_get_draw_buffer (), 0);
+
enable_flags |= _cogl_material_get_cogl_enable_flags (ctx->source_material);
cogl_enable (enable_flags);
options.flags = COGL_MATERIAL_FLUSH_DISABLE_MASK;
+ /* disable all texture layers */
options.disable_layers = (guint32)~0;
- _cogl_material_flush_gl_state (ctx->source_material,&options);
- _cogl_flush_matrix_stacks();
+
+ _cogl_material_flush_gl_state (ctx->source_material, &options);
while (path_start < ctx->path_nodes->len)
{
CoglPathNode *path,
gboolean merge)
{
- guint path_start = 0;
- guint sub_path_num = 0;
- float bounds_x;
- float bounds_y;
- float bounds_w;
- float bounds_h;
- gulong enable_flags = COGL_ENABLE_VERTEX_ARRAY;
+ guint path_start = 0;
+ guint sub_path_num = 0;
+ float bounds_x;
+ float bounds_y;
+ float bounds_w;
+ float bounds_h;
+ gulong enable_flags = COGL_ENABLE_VERTEX_ARRAY;
+ CoglHandle prev_source;
+ int i;
+ CoglHandle draw_buffer = _cogl_get_draw_buffer ();
+ CoglMatrixStack *modelview_stack =
+ _cogl_draw_buffer_get_modelview_stack (draw_buffer);
+ CoglMatrixStack *projection_stack =
+ _cogl_draw_buffer_get_projection_stack (draw_buffer);
+
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
+ /* We don't track changes to the stencil buffer in the journal
+ * so we need to flush any batched geometry first */
+ _cogl_journal_flush ();
+
+ /* NB: _cogl_draw_buffer_flush_state may disrupt various state (such
+ * as the material state) when flushing the clip stack, so should
+ * always be done first when preparing to draw. */
+ _cogl_draw_buffer_flush_state (draw_buffer, 0);
+
/* Just setup a simple material that doesn't use texturing... */
- _cogl_material_flush_gl_state (ctx->stencil_material, NULL);
+ prev_source = cogl_handle_ref (ctx->source_material);
+ cogl_set_source (ctx->stencil_material);
+
+ _cogl_material_flush_gl_state (ctx->source_material, NULL);
enable_flags |=
_cogl_material_get_cogl_enable_flags (ctx->source_material);
}
else
{
- GE( glClear (GL_STENCIL_BUFFER_BIT) );
+ cogl_clear (NULL, COGL_BUFFER_BIT_STENCIL);
GE( glStencilMask (1) );
GE( glStencilFunc (GL_LEQUAL, 0x1, 0x3) );
}
GE( glColorMask (FALSE, FALSE, FALSE, FALSE) );
GE( glDepthMask (FALSE) );
- _cogl_matrix_stack_flush_to_gl (ctx->modelview_stack, COGL_MATRIX_MODELVIEW);
+ for (i = 0; i < ctx->n_texcoord_arrays_enabled; i++)
+ {
+ GE (glClientActiveTexture (GL_TEXTURE0 + i));
+ GE (glDisableClientState (GL_TEXTURE_COORD_ARRAY));
+ }
+ ctx->n_texcoord_arrays_enabled = 0;
+
while (path_start < path_size)
{
GE( glVertexPointer (2, GL_FLOAT, sizeof (CoglPathNode),
GE( glStencilOp (GL_ZERO, GL_REPLACE, GL_REPLACE) );
cogl_rectangle (bounds_x, bounds_y,
bounds_x + bounds_w, bounds_y + bounds_h);
+ /* Make sure the rectangle hits the stencil buffer before
+ * directly changing other GL state. */
+ _cogl_journal_flush ();
+ /* NB: The journal flushing may trash the modelview state and
+ * enable flags */
+ _cogl_matrix_stack_flush_to_gl (modelview_stack,
+ COGL_MATRIX_MODELVIEW);
+ cogl_enable (enable_flags);
GE( glStencilOp (GL_INVERT, GL_INVERT, GL_INVERT) );
}
/* Decrement all of the bits twice so that only pixels where the
value is 3 will remain */
- _cogl_matrix_stack_push (ctx->projection_stack);
- _cogl_matrix_stack_load_identity (ctx->projection_stack);
+ _cogl_matrix_stack_push (projection_stack);
+ _cogl_matrix_stack_load_identity (projection_stack);
+ _cogl_matrix_stack_flush_to_gl (projection_stack,
+ COGL_MATRIX_PROJECTION);
- _cogl_matrix_stack_push (ctx->modelview_stack);
- _cogl_matrix_stack_load_identity (ctx->modelview_stack);
+ _cogl_matrix_stack_push (modelview_stack);
+ _cogl_matrix_stack_load_identity (modelview_stack);
+ _cogl_matrix_stack_flush_to_gl (modelview_stack,
+ COGL_MATRIX_MODELVIEW);
cogl_rectangle (-1.0, -1.0, 1.0, 1.0);
cogl_rectangle (-1.0, -1.0, 1.0, 1.0);
+ /* Make sure these rectangles hit the stencil buffer before we
+ * restore the stencil op/func. */
+ _cogl_journal_flush ();
- _cogl_matrix_stack_pop (ctx->modelview_stack);
- _cogl_matrix_stack_pop (ctx->projection_stack);
+ _cogl_matrix_stack_pop (modelview_stack);
+ _cogl_matrix_stack_pop (projection_stack);
}
GE( glStencilMask (~(GLuint) 0) );
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
+ /* We are going to use GL to draw directly so make sure any
+ * previously batched geometry gets to GL before we start...
+ */
+ _cogl_journal_flush ();
+
+ /* NB: _cogl_draw_buffer_flush_state may disrupt various state (such
+ * as the material state) when flushing the clip stack, so should
+ * always be done first when preparing to draw. */
+ _cogl_draw_buffer_flush_state (_cogl_get_draw_buffer (), 0);
+
+ _cogl_material_flush_gl_state (ctx->source_material, NULL);
+
+ cogl_enable (COGL_ENABLE_VERTEX_ARRAY
+ | (ctx->color_alpha < 255 ? COGL_ENABLE_BLEND : 0));
+
/* clear scanline intersection lists */
for (i=0; i < bounds_h; i++)
scanlines[i]=NULL;
}
/* render triangles */
- cogl_enable (COGL_ENABLE_VERTEX_ARRAY
- | (ctx->color_alpha < 255 ? COGL_ENABLE_BLEND : 0));
GE ( glVertexPointer (2, GL_FLOAT, 0, coords ) );
GE ( glDrawArrays (GL_TRIANGLES, 0, spans * 2 * 3));
g_free (coords);
}
void
-_cogl_path_fill_nodes ()
+_cogl_path_fill_nodes (void)
{
float bounds_x;
float bounds_y;
if (cogl_features_available (COGL_FEATURE_STENCIL_BUFFER))
{
+ CoglHandle draw_buffer;
+ CoglClipStackState *clip_state;
+
+ _cogl_journal_flush ();
+
+ draw_buffer = _cogl_get_draw_buffer ();
+ clip_state = _cogl_draw_buffer_get_clip_state (draw_buffer);
+
_cogl_add_path_to_stencil_buffer (ctx->path_nodes_min,
ctx->path_nodes_max,
ctx->path_nodes->len,
&g_array_index (ctx->path_nodes,
CoglPathNode, 0),
- ctx->clip.stencil_used);
+ clip_state->stencil_used);
cogl_rectangle (bounds_x, bounds_y,
bounds_x + bounds_w, bounds_y + bounds_h);
/* The stencil buffer now contains garbage so the clip area needs to
be rebuilt */
- ctx->clip.stack_dirty = TRUE;
+ _cogl_clip_stack_state_dirty (clip_state);
}
else
{
#include "cogl-internal.h"
#include "cogl-context.h"
+typedef struct _CoglGLSymbolTableEntry
+{
+ const char *name;
+ void *ptr;
+} CoglGLSymbolTableEntry;
+
+gboolean
+cogl_check_extension (const gchar *name, const gchar *ext)
+{
+ gchar *end;
+ gint name_len, n;
+
+ if (name == NULL || ext == NULL)
+ return FALSE;
+
+ end = (gchar*)(ext + strlen(ext));
+
+ name_len = strlen(name);
+
+ while (ext < end)
+ {
+ n = strcspn(ext, " ");
+
+ if ((name_len == n) && (!strncmp(name, ext, n)))
+ return TRUE;
+ ext += (n + 1);
+ }
+
+ return FALSE;
+}
+
+gboolean
+_cogl_resolve_gl_symbols (CoglGLSymbolTableEntry *symbol_table,
+ const char *suffix)
+{
+ int i;
+ gboolean status = TRUE;
+ for (i = 0; symbol_table[i].name; i++)
+ {
+ char *full_name = g_strdup_printf ("%s%s", symbol_table[i].name, suffix);
+ *((CoglFuncPtr *)symbol_table[i].ptr) = cogl_get_proc_address (full_name);
+ g_free (full_name);
+ if (!*((CoglFuncPtr *)symbol_table[i].ptr))
+ {
+ status = FALSE;
+ break;
+ }
+ }
+ return status;
+}
void
CoglFeatureFlags flags = 0;
int max_clip_planes = 0;
GLint num_stencil_bits = 0;
+ const char *gl_extensions;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
+ gl_extensions = (const char*) glGetString (GL_EXTENSIONS);
+
+ if (cogl_check_extension ("GL_OES_framebuffer_object", gl_extensions))
+ {
+ g_assert (0);
+ CoglGLSymbolTableEntry symbol_table[] = {
+ {"glGenRenderbuffers", &ctx->drv.pf_glGenRenderbuffers},
+ {"glDeleteRenderbuffers", &ctx->drv.pf_glDeleteRenderbuffers},
+ {"glBindRenderbuffer", &ctx->drv.pf_glBindRenderbuffer},
+ {"glRenderbufferStorage", &ctx->drv.pf_glRenderbufferStorage},
+ {"glGenFramebuffers", &ctx->drv.pf_glGenFramebuffers},
+ {"glBindFramebuffer", &ctx->drv.pf_glBindFramebuffer},
+ {"glFramebufferTexture2D", &ctx->drv.pf_glFramebufferTexture2D},
+ {"glFramebufferRenderbuffer", &ctx->drv.pf_glFramebufferRenderbuffer},
+ {"glCheckFramebufferStatus", &ctx->drv.pf_glCheckFramebufferStatus},
+ {"glDeleteFramebuffers", &ctx->drv.pf_glDeleteFramebuffers},
+ {"glGenerateMipmap", &ctx->drv.pf_glGenerateMipmap},
+ {NULL, NULL}
+ };
+
+ if (_cogl_resolve_gl_symbols (symbol_table, "OES"))
+ flags |= COGL_FEATURE_OFFSCREEN;
+ }
+
GE( glGetIntegerv (GL_STENCIL_BITS, &num_stencil_bits) );
/* We need at least three stencil bits to combine clips */
if (num_stencil_bits > 2)