mirror of
https://github.com/brl/mutter.git
synced 2024-12-25 20:32:16 +00:00
[draw-buffers] First pass at overhauling Cogl's framebuffer management
Cogl's support for offscreen rendering was originally written just to support the clutter_texture_new_from_actor API and due to lack of documentation and several confusing - non orthogonal - side effects of using the API it wasn't really possible to use directly. This commit does a number of things: - It removes {gl,gles}/cogl-fbo.{c,h} and adds shared cogl-draw-buffer.{c,h} files instead which should be easier to maintain. - internally CoglFbo objects are now called CoglDrawBuffers. A CoglDrawBuffer is an abstract base class that is inherited from to implement CoglOnscreen and CoglOffscreen draw buffers. CoglOffscreen draw buffers will initially be used to support the cogl_offscreen_new_to_texture API, and CoglOnscreen draw buffers will start to be used internally to represent windows as we aim to migrate some of Clutter's backend code to Cogl. - It makes draw buffer objects the owners of the following state: - viewport - projection matrix stack - modelview matrix stack - clip state (This means when you switch between draw buffers you will automatically be switching to their associated viewport, matrix and clip state) Aside from hopefully making cogl_offscreen_new_to_texture be more useful short term by having simpler and well defined semantics for cogl_set_draw_buffer, as mentioned above this is the first step for a couple of other things: - Its a step toward moving ownership for windows down from Clutter backends into Cogl, by (internally at least) introducing the CoglOnscreen draw buffer. Note: the plan is that cogl_set_draw_buffer will accept on or offscreen draw buffer handles, and the "target" argument will become redundant since we will instead query the type of the given draw buffer handle. - Because we have a common type for on and offscreen framebuffers we can provide a unified API for framebuffer management. Things like: - blitting between buffers - managing ancillary buffers (e.g. attaching depth and stencil buffers) - size requisition - clearing
This commit is contained in:
parent
6b2ff320ca
commit
bb3a008318
@ -120,6 +120,8 @@ libclutter_cogl_la_SOURCES = \
|
||||
$(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)
|
||||
|
||||
|
@ -34,6 +34,7 @@
|
||||
#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) */
|
||||
@ -119,15 +120,24 @@ cogl_clip_push_window_rect (float x_offset,
|
||||
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);
|
||||
|
||||
@ -135,14 +145,14 @@ cogl_clip_push_window_rect (float x_offset,
|
||||
* 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
|
||||
@ -214,17 +224,26 @@ cogl_clip_push (float x_offset,
|
||||
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);
|
||||
|
||||
@ -240,18 +259,27 @@ cogl_clip_push (float x_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;
|
||||
}
|
||||
|
||||
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));
|
||||
@ -268,7 +296,7 @@ cogl_clip_push_from_path_preserve (void)
|
||||
/* 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
|
||||
@ -279,16 +307,18 @@ cogl_clip_push_from_path (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);
|
||||
|
||||
@ -306,35 +336,57 @@ cogl_clip_pop (void)
|
||||
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_stack_rebuild (void)
|
||||
cogl_clip_pop (void)
|
||||
{
|
||||
int has_clip_planes = cogl_features_available (COGL_FEATURE_FOUR_CLIP_PLANES);
|
||||
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_flush_clip_state (CoglClipStackState *clip_state)
|
||||
{
|
||||
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;
|
||||
CoglMatrixStack *modelview_stack =
|
||||
_cogl_draw_buffer_get_modelview_stack (_cogl_get_draw_buffer ());
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
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;
|
||||
|
||||
ctx->clip.stack_dirty = FALSE;
|
||||
ctx->clip.stencil_used = FALSE;
|
||||
has_clip_planes = cogl_features_available (COGL_FEATURE_FOUR_CLIP_PLANES);
|
||||
|
||||
stack = clip_state->stacks->data;
|
||||
|
||||
clip_state->stencil_used = FALSE;
|
||||
|
||||
_cogl_disable_clip_planes ();
|
||||
_cogl_disable_stencil_buffer ();
|
||||
@ -433,74 +485,111 @@ _cogl_clip_stack_rebuild (void)
|
||||
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);
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_clip_stack_save_real (CoglClipStackState *clip_state)
|
||||
{
|
||||
CoglClipStack *stack;
|
||||
|
||||
/* 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;
|
||||
|
||||
clip_state->stacks = g_slist_prepend (clip_state->stacks, stack);
|
||||
clip_state->stack_dirty = TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
cogl_clip_stack_save (void)
|
||||
{
|
||||
CoglClipStack *stack;
|
||||
CoglHandle draw_buffer;
|
||||
CoglClipStackState *clip_state;
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
stack = g_slice_new (CoglClipStack);
|
||||
stack->stack_top = NULL;
|
||||
draw_buffer = _cogl_get_draw_buffer ();
|
||||
clip_state = _cogl_draw_buffer_get_clip_state (draw_buffer);
|
||||
|
||||
ctx->clip.stacks = g_slist_prepend (ctx->clip.stacks, stack);
|
||||
_cogl_clip_stack_save_real (clip_state);
|
||||
}
|
||||
|
||||
ctx->clip.stack_dirty = TRUE;
|
||||
static void
|
||||
_cogl_clip_stack_restore_real (CoglClipStackState *clip_state)
|
||||
{
|
||||
CoglClipStack *stack;
|
||||
|
||||
g_return_if_fail (clip_state->stacks != NULL);
|
||||
|
||||
/* 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_real (clip_state);
|
||||
|
||||
/* Revert to an old stack */
|
||||
g_slice_free (CoglClipStack, stack);
|
||||
clip_state->stacks = g_slist_delete_link (clip_state->stacks,
|
||||
clip_state->stacks);
|
||||
|
||||
clip_state->stack_dirty = TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
cogl_clip_stack_restore (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);
|
||||
|
||||
stack = (CoglClipStack *) ctx->clip.stacks->data;
|
||||
|
||||
/* Empty the current stack */
|
||||
while (stack->stack_top)
|
||||
cogl_clip_pop ();
|
||||
|
||||
/* Revert to an old stack */
|
||||
g_slice_free (CoglClipStack, stack);
|
||||
ctx->clip.stacks = g_slist_delete_link (ctx->clip.stacks,
|
||||
ctx->clip.stacks);
|
||||
|
||||
ctx->clip.stack_dirty = TRUE;
|
||||
_cogl_clip_stack_restore_real (clip_state);
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_clip_stack_state_init (void)
|
||||
_cogl_clip_stack_state_init (CoglClipStackState *clip_state)
|
||||
{
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
ctx->clip.stacks = NULL;
|
||||
ctx->clip.stack_dirty = TRUE;
|
||||
clip_state->stacks = NULL;
|
||||
clip_state->stack_dirty = TRUE;
|
||||
|
||||
/* Add an intial stack */
|
||||
cogl_clip_stack_save ();
|
||||
_cogl_clip_stack_save_real (clip_state);
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_clip_stack_state_destroy (void)
|
||||
_cogl_clip_stack_state_destroy (CoglClipStackState *clip_state)
|
||||
{
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
@ -35,9 +35,10 @@ struct _CoglClipStackState
|
||||
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 */
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "cogl-journal-private.h"
|
||||
#include "cogl-texture-private.h"
|
||||
#include "cogl-material-private.h"
|
||||
#include "cogl-draw-buffer-private.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@ -46,7 +47,7 @@ cogl_create_context (void)
|
||||
{
|
||||
GLubyte default_texture_data[] = { 0xff, 0xff, 0xff, 0x0 };
|
||||
gulong enable_flags = 0;
|
||||
CoglDrawBufferState *draw_buffer;
|
||||
CoglHandle window_buffer;
|
||||
|
||||
if (_context != NULL)
|
||||
return FALSE;
|
||||
@ -66,8 +67,6 @@ cogl_create_context (void)
|
||||
_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 ();
|
||||
@ -87,11 +86,14 @@ cogl_create_context (void)
|
||||
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;
|
||||
@ -99,20 +101,16 @@ cogl_create_context (void)
|
||||
|
||||
_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 =
|
||||
@ -146,16 +144,14 @@ cogl_create_context (void)
|
||||
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);
|
||||
|
||||
|
@ -38,12 +38,6 @@ typedef struct
|
||||
GLubyte c[4];
|
||||
} CoglTextureGLVertex;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CoglBufferTarget target;
|
||||
CoglHandle offscreen;
|
||||
} CoglDrawBufferState;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* Features cache */
|
||||
@ -60,9 +54,6 @@ typedef struct
|
||||
|
||||
/* 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 */
|
||||
@ -91,11 +82,11 @@ typedef struct
|
||||
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;
|
||||
@ -114,9 +105,6 @@ typedef struct
|
||||
|
||||
gboolean in_begin_gl_block;
|
||||
|
||||
guint viewport_width;
|
||||
guint viewport_height;
|
||||
|
||||
CoglHandle texture_download_material;
|
||||
|
||||
CoglContextDriver drv;
|
||||
|
126
cogl/cogl-draw-buffer-private.h
Normal file
126
cogl/cogl-draw-buffer-private.h
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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 */
|
||||
|
555
cogl/cogl-draw-buffer.c
Normal file
555
cogl/cogl-draw-buffer.c
Normal file
@ -0,0 +1,555 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
@ -32,6 +32,7 @@
|
||||
#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>
|
||||
@ -531,6 +532,8 @@ _cogl_journal_flush (void)
|
||||
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);
|
||||
|
||||
@ -547,20 +550,19 @@ _cogl_journal_flush (void)
|
||||
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
|
||||
@ -591,7 +593,7 @@ _cogl_journal_flush (void)
|
||||
_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++)
|
||||
{
|
||||
@ -607,6 +609,18 @@ _cogl_journal_flush (void)
|
||||
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,
|
||||
@ -632,6 +646,9 @@ _cogl_journal_log_quad (float x_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
|
||||
*/
|
||||
|
@ -32,6 +32,7 @@
|
||||
#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>
|
||||
@ -396,8 +397,6 @@ _cogl_rectangles_with_multitexture_coords (
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
cogl_clip_ensure ();
|
||||
|
||||
material = ctx->source_material;
|
||||
|
||||
layers = cogl_material_get_layers (material);
|
||||
@ -706,7 +705,6 @@ draw_polygon_sub_texture_cb (CoglHandle tex_handle,
|
||||
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));
|
||||
}
|
||||
@ -840,7 +838,6 @@ _cogl_multitexture_polygon_single_primitive (CoglTextureVertex *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));
|
||||
}
|
||||
@ -866,7 +863,11 @@ cogl_polygon (CoglTextureVertex *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);
|
||||
@ -1030,9 +1031,6 @@ cogl_path_fill_preserve (void)
|
||||
{
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
_cogl_journal_flush ();
|
||||
cogl_clip_ensure ();
|
||||
|
||||
if (ctx->path_nodes->len == 0)
|
||||
return;
|
||||
|
||||
@ -1055,10 +1053,7 @@ cogl_path_stroke_preserve (void)
|
||||
if (ctx->path_nodes->len == 0)
|
||||
return;
|
||||
|
||||
_cogl_journal_flush ();
|
||||
cogl_clip_ensure ();
|
||||
|
||||
_cogl_path_stroke_nodes();
|
||||
_cogl_path_stroke_nodes ();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "cogl-context.h"
|
||||
#include "cogl-handle.h"
|
||||
#include "cogl-primitives.h"
|
||||
#include "cogl-draw-buffer-private.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
@ -667,7 +668,8 @@ _cogl_texture_draw_and_read (CoglTexture *tex,
|
||||
GLuint target_gl_type)
|
||||
{
|
||||
gint bpp;
|
||||
GLint viewport[4];
|
||||
CoglHandle draw_buffer;
|
||||
int viewport[4];
|
||||
CoglBitmap alpha_bmp;
|
||||
CoglHandle prev_source;
|
||||
CoglMatrixStack *projection_stack;
|
||||
@ -677,8 +679,9 @@ _cogl_texture_draw_and_read (CoglTexture *tex,
|
||||
|
||||
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;
|
||||
@ -688,16 +691,18 @@ _cogl_texture_draw_and_read (CoglTexture *tex,
|
||||
* 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 */
|
||||
|
||||
|
@ -138,6 +138,7 @@
|
||||
#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)))
|
||||
@ -1664,6 +1665,11 @@ enable_state_for_drawing_buffer (CoglVertexBuffer *buffer)
|
||||
}
|
||||
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;
|
||||
@ -1753,15 +1759,11 @@ cogl_vertex_buffer_draw (CoglHandle handle,
|
||||
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);
|
||||
@ -1885,7 +1887,6 @@ cogl_vertex_buffer_draw_elements (CoglHandle handle,
|
||||
return;
|
||||
|
||||
_cogl_journal_flush ();
|
||||
cogl_clip_ensure ();
|
||||
|
||||
buffer = _cogl_vertex_buffer_pointer_from_handle (handle);
|
||||
|
||||
@ -1894,8 +1895,6 @@ cogl_vertex_buffer_draw_elements (CoglHandle 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);
|
||||
@ -1905,7 +1904,6 @@ cogl_vertex_buffer_draw_elements (CoglHandle handle,
|
||||
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));
|
||||
|
||||
|
222
cogl/cogl.c
222
cogl/cogl.c
@ -38,6 +38,7 @@
|
||||
#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"
|
||||
@ -116,7 +117,12 @@ cogl_clear (const CoglColor *color, gulong buffers)
|
||||
|
||||
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)
|
||||
{
|
||||
@ -327,6 +333,10 @@ set_clip_plane (GLint plane_num,
|
||||
#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
|
||||
@ -334,24 +344,25 @@ set_clip_plane (GLint plane_num,
|
||||
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;
|
||||
@ -363,7 +374,7 @@ set_clip_plane (GLint plane_num,
|
||||
GE( glClipPlane (plane_num, plane) );
|
||||
#endif
|
||||
|
||||
_cogl_matrix_stack_pop (ctx->modelview_stack);
|
||||
_cogl_matrix_stack_pop (modelview_stack);
|
||||
}
|
||||
|
||||
void
|
||||
@ -372,7 +383,12 @@ _cogl_set_clip_planes (float x_offset,
|
||||
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 };
|
||||
@ -381,10 +397,8 @@ _cogl_set_clip_planes (float x_offset,
|
||||
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);
|
||||
@ -422,6 +436,7 @@ _cogl_add_stencil_clip (float x_offset,
|
||||
gboolean first)
|
||||
{
|
||||
CoglHandle current_source;
|
||||
CoglHandle draw_buffer = _cogl_get_draw_buffer ();
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
@ -429,6 +444,8 @@ _cogl_add_stencil_clip (float x_offset,
|
||||
* 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);
|
||||
@ -450,6 +467,11 @@ _cogl_add_stencil_clip (float x_offset,
|
||||
}
|
||||
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) );
|
||||
@ -466,16 +488,16 @@ _cogl_add_stencil_clip (float x_offset,
|
||||
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
|
||||
@ -515,19 +537,32 @@ _cogl_disable_clip_planes (void)
|
||||
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_set_viewport (int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
CoglHandle draw_buffer;
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
draw_buffer = _cogl_get_draw_buffer ();
|
||||
|
||||
_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_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
COGL_NOTE (MISC, "glViewport(0, 0, %u, %u)", width, height);
|
||||
GE( glViewport (0, 0, width, height) );
|
||||
|
||||
ctx->viewport_width = width;
|
||||
ctx->viewport_height = height;
|
||||
_cogl_set_viewport (0, 0, width, height);
|
||||
}
|
||||
|
||||
void
|
||||
@ -540,6 +575,7 @@ _cogl_setup_viewport (guint width,
|
||||
{
|
||||
float z_camera;
|
||||
CoglMatrix projection_matrix;
|
||||
CoglMatrixStack *modelview_stack;
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
@ -593,11 +629,13 @@ _cogl_setup_viewport (guint width,
|
||||
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);
|
||||
}
|
||||
|
||||
@ -606,9 +644,6 @@ cogl_get_features (void)
|
||||
{
|
||||
_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;
|
||||
|
||||
@ -626,18 +661,24 @@ cogl_features_available (CoglFeatureFlags features)
|
||||
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
|
||||
@ -733,7 +774,7 @@ cogl_disable_fog (void)
|
||||
void
|
||||
cogl_flush_gl_state (int flags)
|
||||
{
|
||||
_cogl_flush_matrix_stacks ();
|
||||
_cogl_draw_buffer_flush_state (_cogl_get_draw_buffer (), 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -752,18 +793,20 @@ cogl_read_pixels (int x,
|
||||
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 */
|
||||
@ -825,12 +868,13 @@ cogl_begin_gl (void)
|
||||
/* 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 */
|
||||
|
||||
@ -940,36 +984,41 @@ _cogl_destroy_texture_units (void)
|
||||
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
|
||||
@ -997,12 +1046,14 @@ cogl_frustum (float left,
|
||||
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,
|
||||
@ -1036,12 +1087,14 @@ cogl_ortho (float left,
|
||||
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);
|
||||
@ -1060,41 +1113,44 @@ cogl_ortho (float left,
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -867,6 +867,7 @@ void cogl_flush_gl_state (int flags);
|
||||
|
||||
/* private */
|
||||
void _cogl_set_indirect_context (gboolean indirect);
|
||||
void _cogl_set_viewport (int x, int y, int width, int height);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -25,8 +25,6 @@ libclutter_cogl_driver_la_SOURCES = \
|
||||
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 \
|
||||
|
@ -30,15 +30,16 @@
|
||||
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;
|
||||
|
||||
|
@ -29,19 +29,20 @@
|
||||
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;
|
||||
|
@ -698,34 +698,34 @@ G_BEGIN_DECLS
|
||||
#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,
|
||||
@ -733,26 +733,30 @@ typedef void
|
||||
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,
|
||||
@ -774,10 +778,6 @@ typedef void
|
||||
GLsizei width,
|
||||
GLsizei height);
|
||||
|
||||
typedef void
|
||||
(APIENTRYP COGL_PFNGLGENERATEMIPMAPEXTPROC)
|
||||
(GLenum target);
|
||||
|
||||
typedef GLhandleARB
|
||||
(APIENTRYP COGL_PFNGLCREATEPROGRAMOBJECTARBPROC)
|
||||
(void);
|
||||
|
@ -1,315 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
@ -1,39 +0,0 @@
|
||||
/*
|
||||
* 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 */
|
@ -30,6 +30,8 @@
|
||||
#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>
|
||||
@ -74,7 +76,7 @@ _cogl_path_add_node (gboolean new_sub_path,
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_path_stroke_nodes ()
|
||||
_cogl_path_stroke_nodes (void)
|
||||
{
|
||||
guint path_start = 0;
|
||||
gulong enable_flags = COGL_ENABLE_VERTEX_ARRAY;
|
||||
@ -82,6 +84,13 @@ _cogl_path_stroke_nodes ()
|
||||
|
||||
_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);
|
||||
|
||||
@ -90,7 +99,6 @@ _cogl_path_stroke_nodes ()
|
||||
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)
|
||||
{
|
||||
@ -127,20 +135,33 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min,
|
||||
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);
|
||||
@ -161,7 +182,7 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min,
|
||||
}
|
||||
else
|
||||
{
|
||||
GE( glClear (GL_STENCIL_BUFFER_BIT) );
|
||||
cogl_clear (NULL, COGL_BUFFER_BIT_STENCIL);
|
||||
GE( glStencilMask (1) );
|
||||
GE( glStencilFunc (GL_LEQUAL, 0x1, 0x3) );
|
||||
}
|
||||
@ -179,8 +200,6 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min,
|
||||
}
|
||||
ctx->n_texcoord_arrays_enabled = 0;
|
||||
|
||||
_cogl_flush_matrix_stacks ();
|
||||
|
||||
while (path_start < path_size)
|
||||
{
|
||||
GE( glVertexPointer (2, GL_FLOAT, sizeof (CoglPathNode),
|
||||
@ -194,8 +213,17 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min,
|
||||
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) );
|
||||
}
|
||||
|
||||
@ -216,19 +244,24 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min,
|
||||
/* 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_flush_matrix_stacks ();
|
||||
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 ();
|
||||
|
||||
glRectf (-1.0, -1.0, 1.0, 1.0);
|
||||
glRectf (-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);
|
||||
}
|
||||
|
||||
GE( glStencilMask (~(GLuint) 0) );
|
||||
@ -244,8 +277,10 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min,
|
||||
}
|
||||
|
||||
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;
|
||||
@ -253,6 +288,11 @@ _cogl_path_fill_nodes ()
|
||||
|
||||
_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);
|
||||
|
||||
@ -261,12 +301,13 @@ _cogl_path_fill_nodes ()
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@
|
||||
#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,
|
||||
|
@ -32,6 +32,12 @@
|
||||
#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)
|
||||
{
|
||||
@ -57,6 +63,26 @@ 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)
|
||||
@ -90,6 +116,9 @@ _cogl_features_init (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);
|
||||
|
||||
@ -284,64 +313,35 @@ _cogl_features_init (void)
|
||||
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
|
||||
{
|
||||
ctx->drv.pf_glGenRenderbuffersEXT =
|
||||
(COGL_PFNGLGENRENDERBUFFERSEXTPROC)
|
||||
cogl_get_proc_address ("glGenRenderbuffersEXT");
|
||||
fbo_EXT = cogl_check_extension ("GL_EXT_framebuffer_object", gl_extensions);
|
||||
if (fbo_EXT)
|
||||
suffix = "EXT";
|
||||
}
|
||||
|
||||
ctx->drv.pf_glDeleteRenderbuffersEXT =
|
||||
(COGL_PFNGLDELETERENDERBUFFERSEXTPROC)
|
||||
cogl_get_proc_address ("glDeleteRenderbuffersEXT");
|
||||
if (fbo_ARB || fbo_EXT)
|
||||
{
|
||||
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}
|
||||
};
|
||||
|
||||
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;
|
||||
if (_cogl_resolve_gl_symbols (symbol_table, suffix))
|
||||
flags |= COGL_FEATURE_OFFSCREEN;
|
||||
}
|
||||
|
||||
if (cogl_check_extension ("GL_EXT_framebuffer_blit", gl_extensions))
|
||||
|
@ -22,11 +22,9 @@ libclutter_cogl_driver_la_CPPFLAGS = \
|
||||
$(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 \
|
||||
|
@ -31,6 +31,16 @@
|
||||
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);
|
||||
|
@ -24,17 +24,26 @@
|
||||
#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;
|
||||
|
||||
|
@ -633,6 +633,76 @@ G_BEGIN_DECLS
|
||||
#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
|
||||
|
@ -1,328 +0,0 @@
|
||||
/*
|
||||
* 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 */
|
@ -1,39 +0,0 @@
|
||||
/*
|
||||
* 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 */
|
@ -30,6 +30,9 @@
|
||||
#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>
|
||||
@ -72,7 +75,7 @@ _cogl_path_add_node (gboolean new_sub_path,
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_path_stroke_nodes ()
|
||||
_cogl_path_stroke_nodes (void)
|
||||
{
|
||||
guint path_start = 0;
|
||||
gulong enable_flags = COGL_ENABLE_VERTEX_ARRAY;
|
||||
@ -80,13 +83,21 @@ _cogl_path_stroke_nodes ()
|
||||
|
||||
_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)
|
||||
{
|
||||
@ -129,18 +140,38 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min,
|
||||
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);
|
||||
@ -156,7 +187,7 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min,
|
||||
}
|
||||
else
|
||||
{
|
||||
GE( glClear (GL_STENCIL_BUFFER_BIT) );
|
||||
cogl_clear (NULL, COGL_BUFFER_BIT_STENCIL);
|
||||
GE( glStencilMask (1) );
|
||||
GE( glStencilFunc (GL_LEQUAL, 0x1, 0x3) );
|
||||
}
|
||||
@ -167,7 +198,13 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min,
|
||||
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),
|
||||
@ -183,6 +220,14 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min,
|
||||
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) );
|
||||
}
|
||||
@ -204,17 +249,24 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min,
|
||||
/* 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) );
|
||||
@ -250,6 +302,21 @@ _cogl_path_fill_nodes_scanlines (CoglPathNode *path,
|
||||
|
||||
_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;
|
||||
@ -386,8 +453,6 @@ _cogl_path_fill_nodes_scanlines (CoglPathNode *path,
|
||||
}
|
||||
|
||||
/* 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);
|
||||
@ -395,7 +460,7 @@ _cogl_path_fill_nodes_scanlines (CoglPathNode *path,
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_path_fill_nodes ()
|
||||
_cogl_path_fill_nodes (void)
|
||||
{
|
||||
float bounds_x;
|
||||
float bounds_y;
|
||||
@ -409,19 +474,27 @@ _cogl_path_fill_nodes ()
|
||||
|
||||
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
|
||||
{
|
||||
|
@ -31,6 +31,56 @@
|
||||
#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
|
||||
@ -39,9 +89,34 @@ _cogl_features_init (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)
|
||||
|
Loading…
Reference in New Issue
Block a user