Merge commit 'cogl-reorg-draw-buffers'
* cogl-reorg-draw-buffers: (38 commits) [test-fbo] greatly simplify the test [tests] test-backface-culling: test culling with offscreen rendering [tests] Adds test-cogl-readpixels.c for very basic cogl_read_pixels testing [tests] Adds test-cogl-offscreen to validate offscreen draw buffer [tests] test-cogl-viewport tests semantics of over/under size viewports [test-texture-fbo] comment the colors defined in corner_colors Add a conformance test for clutter_texture_new_from_actor [cogl-texture-2d-sliced] allow COGL_FORMAT_ANY with _new_with_size() [texture] fix rounding when calculating update_fbo viewport offset [texture] switch to a new design for handling offscreen rendering [texture] split out fbo update code from cluter_texture_paint [texture] push/pop draw buffer when painting actors to a texture [texture] Avoid redundant use of cogl_clip_stack_save when drawing offscreen [cogl-draw-buffer] fix Cogl -> GL viewport coord conversion [cogl_clip_push_window_rect] fix Cogl -> GL coordinate conversion [matrix] Adds cogl_matrix_get_inverse API [debug] Adds a COGL_DEBUG=matrices debug option [cogl-matrix] Import Mesa's matrix manipulation code [cogl] avoid any state changes when cogl_set_backface_culling_enable is a nop [cogl] Use clockwise face winding for offscreen buffers with culling enabled ...
This commit is contained in:
commit
0ff420fab5
6
README
6
README
@ -212,6 +212,12 @@ Release Notes for Clutter 1.2
|
|||||||
* Clutter now depends on the system copy of JSON-GLib, and will fall
|
* Clutter now depends on the system copy of JSON-GLib, and will fall
|
||||||
back to the internal copy only if JSON-GLib is not installed.
|
back to the internal copy only if JSON-GLib is not installed.
|
||||||
|
|
||||||
|
Cogl API changes for Clutter 1.2
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
* cogl_viewport is now deprecated in favour of cogl_set_viewport which
|
||||||
|
accepts a viewport offset.
|
||||||
|
|
||||||
Release Notes for Clutter 1.0
|
Release Notes for Clutter 1.0
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
||||||
|
@ -47,6 +47,8 @@
|
|||||||
#include "clutter-marshal.h"
|
#include "clutter-marshal.h"
|
||||||
#include "clutter-private.h"
|
#include "clutter-private.h"
|
||||||
|
|
||||||
|
#include <cogl/cogl.h>
|
||||||
|
|
||||||
G_DEFINE_ABSTRACT_TYPE (ClutterBackend, clutter_backend, G_TYPE_OBJECT);
|
G_DEFINE_ABSTRACT_TYPE (ClutterBackend, clutter_backend, G_TYPE_OBJECT);
|
||||||
|
|
||||||
#define DEFAULT_FONT_NAME "Sans 10"
|
#define DEFAULT_FONT_NAME "Sans 10"
|
||||||
@ -355,7 +357,22 @@ _clutter_backend_ensure_context (ClutterBackend *backend,
|
|||||||
klass = CLUTTER_BACKEND_GET_CLASS (backend);
|
klass = CLUTTER_BACKEND_GET_CLASS (backend);
|
||||||
if (G_LIKELY (klass->ensure_context))
|
if (G_LIKELY (klass->ensure_context))
|
||||||
klass->ensure_context (backend, new_stage);
|
klass->ensure_context (backend, new_stage);
|
||||||
|
|
||||||
|
/* XXX: Until Cogl becomes fully responsible for backend windows
|
||||||
|
* Clutter need to manually keep it informed of the current window size
|
||||||
|
*
|
||||||
|
* NB: This must be done after we ensure_context above because Cogl
|
||||||
|
* always assumes there is a current GL context.
|
||||||
|
*/
|
||||||
|
if (new_stage)
|
||||||
|
{
|
||||||
|
float width, height;
|
||||||
|
|
||||||
|
clutter_actor_get_size (CLUTTER_ACTOR (stage), &width, &height);
|
||||||
|
|
||||||
|
_cogl_onscreen_clutter_backend_set_size (width, height);
|
||||||
|
}
|
||||||
|
|
||||||
/* FIXME: With a NULL stage and thus no active context it may make more
|
/* FIXME: With a NULL stage and thus no active context it may make more
|
||||||
* sense to clean the context but then re call with the default stage
|
* sense to clean the context but then re call with the default stage
|
||||||
* so at least there is some kind of context in place (as to avoid
|
* so at least there is some kind of context in place (as to avoid
|
||||||
|
@ -425,10 +425,12 @@ read_pixels_to_file (char *filename_stem,
|
|||||||
GLubyte *data;
|
GLubyte *data;
|
||||||
GdkPixbuf *pixbuf;
|
GdkPixbuf *pixbuf;
|
||||||
static int read_count = 0;
|
static int read_count = 0;
|
||||||
GdkPixbuf *flipped;
|
|
||||||
|
|
||||||
data = g_malloc (4 * width * height);
|
data = g_malloc (4 * width * height);
|
||||||
glReadPixels (0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
cogl_read_pixels (x, y, width, height,
|
||||||
|
COGL_READ_PIXELS_COLOR_BUFFER,
|
||||||
|
COGL_PIXEL_FORMAT_RGBA_8888,
|
||||||
|
data);
|
||||||
pixbuf = gdk_pixbuf_new_from_data (data,
|
pixbuf = gdk_pixbuf_new_from_data (data,
|
||||||
GDK_COLORSPACE_RGB,
|
GDK_COLORSPACE_RGB,
|
||||||
TRUE, /* has alpha */
|
TRUE, /* has alpha */
|
||||||
@ -439,24 +441,18 @@ read_pixels_to_file (char *filename_stem,
|
|||||||
pixbuf_free, /* callback to free data */
|
pixbuf_free, /* callback to free data */
|
||||||
NULL); /* callback data */
|
NULL); /* callback data */
|
||||||
if (pixbuf)
|
if (pixbuf)
|
||||||
{
|
|
||||||
flipped = gdk_pixbuf_flip (pixbuf, FALSE);
|
|
||||||
g_object_unref (pixbuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flipped)
|
|
||||||
{
|
{
|
||||||
char *filename =
|
char *filename =
|
||||||
g_strdup_printf ("%s-%05d.png", filename_stem, read_count);
|
g_strdup_printf ("%s-%05d.png", filename_stem, read_count);
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
if (!gdk_pixbuf_save (flipped, filename, "png", &error, NULL))
|
if (!gdk_pixbuf_save (pixbuf, filename, "png", &error, NULL))
|
||||||
{
|
{
|
||||||
g_warning ("Failed to save pick buffer to file %s: %s",
|
g_warning ("Failed to save pick buffer to file %s: %s",
|
||||||
filename, error->message);
|
filename, error->message);
|
||||||
g_error_free (error);
|
g_error_free (error);
|
||||||
}
|
}
|
||||||
g_free (filename);
|
g_free (filename);
|
||||||
g_object_unref (flipped);
|
g_object_unref (pixbuf);
|
||||||
read_count++;
|
read_count++;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@ -478,7 +474,6 @@ _clutter_do_pick (ClutterStage *stage,
|
|||||||
{
|
{
|
||||||
ClutterMainContext *context;
|
ClutterMainContext *context;
|
||||||
guchar pixel[4] = { 0xff, 0xff, 0xff, 0xff };
|
guchar pixel[4] = { 0xff, 0xff, 0xff, 0xff };
|
||||||
GLint viewport[4];
|
|
||||||
CoglColor white;
|
CoglColor white;
|
||||||
guint32 id;
|
guint32 id;
|
||||||
GLboolean dither_was_on;
|
GLboolean dither_was_on;
|
||||||
@ -517,17 +512,21 @@ _clutter_do_pick (ClutterStage *stage,
|
|||||||
if (G_LIKELY (!(clutter_debug_flags & CLUTTER_DEBUG_DUMP_PICK_BUFFERS)))
|
if (G_LIKELY (!(clutter_debug_flags & CLUTTER_DEBUG_DUMP_PICK_BUFFERS)))
|
||||||
cogl_clip_pop ();
|
cogl_clip_pop ();
|
||||||
|
|
||||||
/* Calls should work under both GL and GLES, note GLES needs RGBA */
|
|
||||||
glGetIntegerv(GL_VIEWPORT, viewport);
|
|
||||||
|
|
||||||
/* Make sure Cogl flushes any batched geometry to the GPU driver */
|
/* Make sure Cogl flushes any batched geometry to the GPU driver */
|
||||||
cogl_flush ();
|
cogl_flush ();
|
||||||
|
|
||||||
/* Read the color of the screen co-ords pixel */
|
/* Read the color of the screen co-ords pixel */
|
||||||
glReadPixels (x, viewport[3] - y -1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
|
cogl_read_pixels (x, y, 1, 1,
|
||||||
|
COGL_READ_PIXELS_COLOR_BUFFER,
|
||||||
|
COGL_PIXEL_FORMAT_RGBA_8888,
|
||||||
|
pixel);
|
||||||
|
|
||||||
if (G_UNLIKELY (clutter_debug_flags & CLUTTER_DEBUG_DUMP_PICK_BUFFERS))
|
if (G_UNLIKELY (clutter_debug_flags & CLUTTER_DEBUG_DUMP_PICK_BUFFERS))
|
||||||
read_pixels_to_file ("pick-buffer", 0, 0, viewport[2], viewport[3]);
|
{
|
||||||
|
read_pixels_to_file ("pick-buffer", 0, 0,
|
||||||
|
clutter_actor_get_width (CLUTTER_ACTOR (stage)),
|
||||||
|
clutter_actor_get_height (CLUTTER_ACTOR (stage)));
|
||||||
|
}
|
||||||
|
|
||||||
/* Restore whether GL_DITHER was enabled */
|
/* Restore whether GL_DITHER was enabled */
|
||||||
if (dither_was_on)
|
if (dither_was_on)
|
||||||
@ -1338,6 +1337,8 @@ clutter_init_real (GError **error)
|
|||||||
/* Now we can safely assume we have a valid GL context and can
|
/* Now we can safely assume we have a valid GL context and can
|
||||||
* start issueing cogl commands
|
* start issueing cogl commands
|
||||||
*/
|
*/
|
||||||
|
/* - will call to backend and cogl */
|
||||||
|
_clutter_feature_init ();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Resolution requires display to be open, so can only be queried after
|
* Resolution requires display to be open, so can only be queried after
|
||||||
@ -1374,9 +1375,6 @@ clutter_init_real (GError **error)
|
|||||||
/* Initiate event collection */
|
/* Initiate event collection */
|
||||||
_clutter_backend_init_events (ctx->backend);
|
_clutter_backend_init_events (ctx->backend);
|
||||||
|
|
||||||
/* finally features - will call to backend and cogl */
|
|
||||||
_clutter_feature_init ();
|
|
||||||
|
|
||||||
clutter_is_initialized = TRUE;
|
clutter_is_initialized = TRUE;
|
||||||
ctx->is_initialized = TRUE;
|
ctx->is_initialized = TRUE;
|
||||||
|
|
||||||
|
@ -192,6 +192,10 @@ clutter_stage_allocate (ClutterActor *self,
|
|||||||
{
|
{
|
||||||
ClutterActorClass *klass;
|
ClutterActorClass *klass;
|
||||||
|
|
||||||
|
/* XXX: Until Cogl becomes fully responsible for backend windows Clutter
|
||||||
|
* need to manually keep it informed of the current window size */
|
||||||
|
_cogl_onscreen_clutter_backend_set_size (width, height);
|
||||||
|
|
||||||
CLUTTER_NOTE (LAYOUT,
|
CLUTTER_NOTE (LAYOUT,
|
||||||
"Following allocation to %dx%d (origin %s)",
|
"Following allocation to %dx%d (origin %s)",
|
||||||
width, height,
|
width, height,
|
||||||
@ -210,6 +214,10 @@ clutter_stage_allocate (ClutterActor *self,
|
|||||||
|
|
||||||
_clutter_stage_window_get_geometry (priv->impl, &geom);
|
_clutter_stage_window_get_geometry (priv->impl, &geom);
|
||||||
|
|
||||||
|
/* XXX: Until Cogl becomes fully responsible for backend windows Clutter
|
||||||
|
* need to manually keep it informed of the current window size */
|
||||||
|
_cogl_onscreen_clutter_backend_set_size (geom.width, geom.height);
|
||||||
|
|
||||||
override.x1 = 0;
|
override.x1 = 0;
|
||||||
override.y1 = 0;
|
override.y1 = 0;
|
||||||
override.x2 = geom.width;
|
override.x2 = geom.width;
|
||||||
|
@ -251,7 +251,7 @@ clutter_texture_unrealize (ClutterActor *actor)
|
|||||||
|
|
||||||
CLUTTER_MARK();
|
CLUTTER_MARK();
|
||||||
|
|
||||||
if (priv->fbo_source != COGL_INVALID_HANDLE)
|
if (priv->fbo_source != NULL)
|
||||||
{
|
{
|
||||||
/* Free up our fbo handle and texture resources, realize will recreate */
|
/* Free up our fbo handle and texture resources, realize will recreate */
|
||||||
cogl_handle_unref (priv->fbo_handle);
|
cogl_handle_unref (priv->fbo_handle);
|
||||||
@ -449,66 +449,128 @@ clutter_texture_allocate (ClutterActor *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_texture_set_fbo_projection (ClutterActor *self)
|
set_viewport_with_buffer_under_fbo_source (ClutterActor *fbo_source,
|
||||||
|
int viewport_width,
|
||||||
|
int viewport_height)
|
||||||
{
|
{
|
||||||
ClutterTexturePrivate *priv = CLUTTER_TEXTURE (self)->priv;
|
|
||||||
ClutterVertex verts[4];
|
ClutterVertex verts[4];
|
||||||
gfloat viewport[4];
|
float x_min = G_MAXFLOAT, y_min = G_MAXFLOAT;
|
||||||
gfloat x_min, x_max, y_min, y_max;
|
int x_offset, y_offset;
|
||||||
gfloat tx_min, tx_max, ty_min, ty_max;
|
|
||||||
gfloat tan_angle, near_size;
|
|
||||||
ClutterPerspective perspective;
|
|
||||||
ClutterStage *stage;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Get the bounding rectangle of the source as drawn in screen
|
/* Get the actors allocation transformed into screen coordinates.
|
||||||
coordinates */
|
*
|
||||||
clutter_actor_get_abs_allocation_vertices (priv->fbo_source, verts);
|
* XXX: Note: this may not be a bounding box for the actor, since an
|
||||||
|
* actor with depth may escape the box due to its perspective
|
||||||
|
* projection. */
|
||||||
|
clutter_actor_get_abs_allocation_vertices (fbo_source, verts);
|
||||||
|
|
||||||
x_min = x_max = verts[0].x;
|
for (i = 0; i < G_N_ELEMENTS (verts); ++i)
|
||||||
y_min = y_max = verts[0].y;
|
|
||||||
|
|
||||||
for (i = 1; i < G_N_ELEMENTS (verts); ++i)
|
|
||||||
{
|
{
|
||||||
if (verts[i].x < x_min)
|
if (verts[i].x < x_min)
|
||||||
x_min = verts[i].x;
|
x_min = verts[i].x;
|
||||||
|
|
||||||
if (verts[i].x > x_max)
|
|
||||||
x_max = verts[i].x;
|
|
||||||
|
|
||||||
if (verts[i].y < y_min)
|
if (verts[i].y < y_min)
|
||||||
y_min = verts[i].y;
|
y_min = verts[i].y;
|
||||||
|
|
||||||
if (verts[i].y > y_max)
|
|
||||||
y_max = verts[i].y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stage = CLUTTER_STAGE (clutter_actor_get_stage (self));
|
/* XXX: It's not good enough to round by simply truncating the fraction here
|
||||||
clutter_stage_get_perspective (stage, &perspective);
|
* via a cast, as it results in offscreen rendering being offset by 1 pixel
|
||||||
|
* in many cases... */
|
||||||
|
#define ROUND(x) ((x) >= 0 ? (long)((x) + 0.5) : (long)((x) - 0.5))
|
||||||
|
|
||||||
/* Convert the coordinates back to [-1,1] range */
|
x_offset = ROUND (-x_min);
|
||||||
cogl_get_viewport (viewport);
|
y_offset = ROUND (-y_min);
|
||||||
|
|
||||||
tx_min = (x_min / viewport[2])
|
#undef ROUND
|
||||||
* 2 - 1.0;
|
|
||||||
tx_max = (x_max / viewport[2])
|
|
||||||
* 2 - 1.0;
|
|
||||||
ty_min = (y_min / viewport[3])
|
|
||||||
* 2 - 1.0;
|
|
||||||
ty_max = (y_max / viewport[3])
|
|
||||||
* 2 - 1.0;
|
|
||||||
|
|
||||||
/* Set up a projection matrix so that the actor will be projected as
|
/* translate the viewport so that the source actor lands on the
|
||||||
if it was drawn at its original location */
|
* sub-region backed by the offscreen draw buffer... */
|
||||||
tan_angle = tanf ((perspective.fovy / 2) * (G_PI / 180.0));
|
cogl_set_viewport (x_offset, y_offset, viewport_width, viewport_height);
|
||||||
near_size = perspective.z_near * tan_angle;
|
}
|
||||||
|
|
||||||
cogl_frustum ((tx_min * near_size),
|
static void
|
||||||
(tx_max * near_size),
|
update_fbo (ClutterActor *self)
|
||||||
(-ty_min * near_size),
|
{
|
||||||
(-ty_max * near_size),
|
ClutterTexture *texture = CLUTTER_TEXTURE (self);
|
||||||
perspective.z_near,
|
ClutterTexturePrivate *priv = texture->priv;
|
||||||
perspective.z_far);
|
ClutterMainContext *context;
|
||||||
|
ClutterShader *shader = NULL;
|
||||||
|
ClutterActor *stage = NULL;
|
||||||
|
ClutterPerspective perspective;
|
||||||
|
CoglColor transparent_col;
|
||||||
|
|
||||||
|
context = _clutter_context_get_default ();
|
||||||
|
|
||||||
|
if (context->shaders)
|
||||||
|
shader = clutter_actor_get_shader (context->shaders->data);
|
||||||
|
|
||||||
|
/* Temporarily turn off the shader on the top of the context's shader stack,
|
||||||
|
* to restore the GL pipeline to it's natural state.
|
||||||
|
*/
|
||||||
|
if (shader)
|
||||||
|
clutter_shader_set_is_enabled (shader, FALSE);
|
||||||
|
|
||||||
|
/* Redirect drawing to the fbo */
|
||||||
|
cogl_push_draw_buffer ();
|
||||||
|
cogl_set_draw_buffer (COGL_OFFSCREEN_BUFFER, priv->fbo_handle);
|
||||||
|
|
||||||
|
if ((stage = clutter_actor_get_stage (self)))
|
||||||
|
{
|
||||||
|
gfloat stage_width, stage_height;
|
||||||
|
ClutterActor *source_parent;
|
||||||
|
|
||||||
|
/* We copy the projection and modelview matrices from the stage to
|
||||||
|
* the offscreen draw buffer and create a viewport larger than the
|
||||||
|
* offscreen draw buffer - the same size as the stage.
|
||||||
|
*
|
||||||
|
* The fbo source actor gets rendered into this stage size viewport at the
|
||||||
|
* same position it normally would after applying all it's usual parent
|
||||||
|
* transforms and it's own scale and rotate transforms etc.
|
||||||
|
*
|
||||||
|
* The viewport is offset such that the offscreen buffer will be positioned
|
||||||
|
* under the actor.
|
||||||
|
*/
|
||||||
|
|
||||||
|
clutter_stage_get_perspective (CLUTTER_STAGE (stage), &perspective);
|
||||||
|
clutter_actor_get_size (stage, &stage_width, &stage_height);
|
||||||
|
|
||||||
|
/* Set the projection matrix modelview matrix and viewport size as
|
||||||
|
* they are for the stage... */
|
||||||
|
_cogl_setup_viewport (stage_width, stage_height,
|
||||||
|
perspective.fovy,
|
||||||
|
perspective.aspect,
|
||||||
|
perspective.z_near,
|
||||||
|
perspective.z_far);
|
||||||
|
|
||||||
|
/* Negatively offset the viewport so that the offscreen draw buffer is
|
||||||
|
* position underneath the fbo_source actor... */
|
||||||
|
set_viewport_with_buffer_under_fbo_source (priv->fbo_source,
|
||||||
|
stage_width,
|
||||||
|
stage_height);
|
||||||
|
|
||||||
|
/* Reapply the source's parent transformations */
|
||||||
|
if ((source_parent = clutter_actor_get_parent (priv->fbo_source)))
|
||||||
|
_clutter_actor_apply_modelview_transform_recursive (source_parent,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* cogl_clear is called to clear the buffers */
|
||||||
|
cogl_color_set_from_4ub (&transparent_col, 0, 0, 0, 0);
|
||||||
|
cogl_clear (&transparent_col,
|
||||||
|
COGL_BUFFER_BIT_COLOR |
|
||||||
|
COGL_BUFFER_BIT_DEPTH);
|
||||||
|
cogl_disable_fog ();
|
||||||
|
|
||||||
|
/* Render the actor to the fbo */
|
||||||
|
clutter_actor_paint (priv->fbo_source);
|
||||||
|
|
||||||
|
/* Restore drawing to the previous draw buffer */
|
||||||
|
cogl_pop_draw_buffer ();
|
||||||
|
|
||||||
|
/* If there is a shader on top of the shader stack, turn it back on. */
|
||||||
|
if (shader)
|
||||||
|
clutter_shader_set_is_enabled (shader, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -517,7 +579,6 @@ clutter_texture_paint (ClutterActor *self)
|
|||||||
ClutterTexture *texture = CLUTTER_TEXTURE (self);
|
ClutterTexture *texture = CLUTTER_TEXTURE (self);
|
||||||
ClutterTexturePrivate *priv = texture->priv;
|
ClutterTexturePrivate *priv = texture->priv;
|
||||||
ClutterActorBox box = { 0, };
|
ClutterActorBox box = { 0, };
|
||||||
CoglColor transparent_col;
|
|
||||||
gfloat t_w, t_h;
|
gfloat t_w, t_h;
|
||||||
guint8 paint_opacity = clutter_actor_get_paint_opacity (self);
|
guint8 paint_opacity = clutter_actor_get_paint_opacity (self);
|
||||||
|
|
||||||
@ -530,85 +591,7 @@ clutter_texture_paint (ClutterActor *self)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (priv->fbo_handle != COGL_INVALID_HANDLE)
|
if (priv->fbo_handle != COGL_INVALID_HANDLE)
|
||||||
{
|
update_fbo (self);
|
||||||
ClutterMainContext *context;
|
|
||||||
ClutterShader *shader = NULL;
|
|
||||||
ClutterActor *stage = NULL;
|
|
||||||
ClutterPerspective perspective;
|
|
||||||
|
|
||||||
context = _clutter_context_get_default ();
|
|
||||||
|
|
||||||
if (context->shaders)
|
|
||||||
shader = clutter_actor_get_shader (context->shaders->data);
|
|
||||||
|
|
||||||
/* Temporarily turn of the shader on the top of the context's
|
|
||||||
* shader stack, to restore the GL pipeline to it's natural state.
|
|
||||||
*/
|
|
||||||
if (shader)
|
|
||||||
clutter_shader_set_is_enabled (shader, FALSE);
|
|
||||||
|
|
||||||
/* Redirect drawing to the fbo */
|
|
||||||
cogl_set_draw_buffer (COGL_OFFSCREEN_BUFFER, priv->fbo_handle);
|
|
||||||
|
|
||||||
if ((stage = clutter_actor_get_stage (self)))
|
|
||||||
{
|
|
||||||
gfloat stage_width, stage_height;
|
|
||||||
ClutterActor *source_parent;
|
|
||||||
|
|
||||||
clutter_stage_get_perspective (CLUTTER_STAGE (stage), &perspective);
|
|
||||||
clutter_actor_get_size (stage, &stage_width, &stage_height);
|
|
||||||
|
|
||||||
/* Use below to set the modelview matrix as if the viewport
|
|
||||||
was still the same size as the stage */
|
|
||||||
_cogl_setup_viewport (stage_width, stage_height,
|
|
||||||
perspective.fovy,
|
|
||||||
perspective.aspect,
|
|
||||||
perspective.z_near,
|
|
||||||
perspective.z_far);
|
|
||||||
|
|
||||||
/* Use a projection matrix that makes the actor appear as it
|
|
||||||
would if it was rendered at its normal screen location */
|
|
||||||
clutter_texture_set_fbo_projection (self);
|
|
||||||
|
|
||||||
/* Reset the viewport to the size of the FBO */
|
|
||||||
cogl_viewport (priv->image_width, priv->image_height);
|
|
||||||
|
|
||||||
/* Reapply the source's parent transformations */
|
|
||||||
if ((source_parent = clutter_actor_get_parent (priv->fbo_source)))
|
|
||||||
_clutter_actor_apply_modelview_transform_recursive (source_parent,
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* cogl_clear is called to clear the buffers */
|
|
||||||
cogl_color_set_from_4ub (&transparent_col, 0, 0, 0, 0);
|
|
||||||
cogl_clear (&transparent_col,
|
|
||||||
COGL_BUFFER_BIT_COLOR |
|
|
||||||
COGL_BUFFER_BIT_DEPTH);
|
|
||||||
cogl_disable_fog ();
|
|
||||||
|
|
||||||
/* Clear the clipping stack so that if the FBO actor is being
|
|
||||||
clipped then it won't affect drawing the source */
|
|
||||||
cogl_clip_stack_save ();
|
|
||||||
|
|
||||||
/* Render out actor scene to fbo */
|
|
||||||
clutter_actor_paint (priv->fbo_source);
|
|
||||||
|
|
||||||
cogl_clip_stack_restore ();
|
|
||||||
|
|
||||||
/* Restore drawing to the frame buffer */
|
|
||||||
cogl_set_draw_buffer (COGL_WINDOW_BUFFER, COGL_INVALID_HANDLE);
|
|
||||||
|
|
||||||
/* Restore the perspective matrix using cogl_perspective so that
|
|
||||||
the inverse matrix will be right */
|
|
||||||
cogl_perspective (perspective.fovy,
|
|
||||||
perspective.aspect,
|
|
||||||
perspective.z_near,
|
|
||||||
perspective.z_far);
|
|
||||||
|
|
||||||
/* If there is a shader on top of the shader stack, turn it back on. */
|
|
||||||
if (shader)
|
|
||||||
clutter_shader_set_is_enabled (shader, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
CLUTTER_NOTE (PAINT,
|
CLUTTER_NOTE (PAINT,
|
||||||
"painting texture '%s'",
|
"painting texture '%s'",
|
||||||
|
@ -120,6 +120,10 @@ libclutter_cogl_la_SOURCES = \
|
|||||||
$(srcdir)/cogl-spans.c \
|
$(srcdir)/cogl-spans.c \
|
||||||
$(srcdir)/cogl-journal-private.h \
|
$(srcdir)/cogl-journal-private.h \
|
||||||
$(srcdir)/cogl-journal.c \
|
$(srcdir)/cogl-journal.c \
|
||||||
|
$(srcdir)/cogl-draw-buffer-private.h \
|
||||||
|
$(srcdir)/cogl-draw-buffer.c \
|
||||||
|
$(srcdir)/cogl-matrix-mesa.h \
|
||||||
|
$(srcdir)/cogl-matrix-mesa.c \
|
||||||
$(BUILT_SOURCES) \
|
$(BUILT_SOURCES) \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "cogl-primitives.h"
|
#include "cogl-primitives.h"
|
||||||
#include "cogl-context.h"
|
#include "cogl-context.h"
|
||||||
#include "cogl-internal.h"
|
#include "cogl-internal.h"
|
||||||
|
#include "cogl-draw-buffer-private.h"
|
||||||
|
|
||||||
/* These are defined in the particular backend (float in GL vs fixed
|
/* These are defined in the particular backend (float in GL vs fixed
|
||||||
in GL ES) */
|
in GL ES) */
|
||||||
@ -113,45 +114,79 @@ struct _CoglClipStackEntryPath
|
|||||||
CoglPathNode path[1];
|
CoglPathNode path[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* FIXME: deprecate and replace with:
|
||||||
|
* void
|
||||||
|
* cogl_clip_push_window_rectangle (int x_offset,
|
||||||
|
* int y_offset,
|
||||||
|
* int width,
|
||||||
|
* int height);
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
cogl_clip_push_window_rect (float x_offset,
|
cogl_clip_push_window_rect (float x_offset,
|
||||||
float y_offset,
|
float y_offset,
|
||||||
float width,
|
float width,
|
||||||
float height)
|
float height)
|
||||||
{
|
{
|
||||||
CoglClipStackEntryWindowRect *entry;
|
CoglHandle draw_buffer;
|
||||||
|
CoglClipStackState *clip_state;
|
||||||
CoglClipStack *stack;
|
CoglClipStack *stack;
|
||||||
float v[4];
|
int draw_buffer_height;
|
||||||
|
CoglClipStackEntryWindowRect *entry;
|
||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
_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;
|
||||||
|
|
||||||
|
draw_buffer_height = _cogl_draw_buffer_get_height (draw_buffer);
|
||||||
|
|
||||||
entry = g_slice_new (CoglClipStackEntryWindowRect);
|
entry = g_slice_new (CoglClipStackEntryWindowRect);
|
||||||
|
|
||||||
/* We convert from coords with (0,0) at top left to coords
|
/* We store the entry coordinates in OpenGL window coordinate space and so
|
||||||
* with (0,0) at bottom left. */
|
* because Cogl defines the window origin to be top left but OpenGL defines
|
||||||
|
* it as bottom left we may need to convert the incoming coordinates.
|
||||||
|
*
|
||||||
|
* NB: Cogl forces all offscreen rendering to be done upside down so in this
|
||||||
|
* case no conversion is needed.
|
||||||
|
*/
|
||||||
entry->type = COGL_CLIP_STACK_WINDOW_RECT;
|
entry->type = COGL_CLIP_STACK_WINDOW_RECT;
|
||||||
entry->x0 = x_offset;
|
entry->x0 = x_offset;
|
||||||
entry->y0 = v[3] - y_offset - height;
|
|
||||||
entry->x1 = x_offset + width;
|
entry->x1 = x_offset + width;
|
||||||
entry->y1 = v[3] - y_offset;
|
if (cogl_is_offscreen (draw_buffer))
|
||||||
|
{
|
||||||
|
entry->y0 = y_offset;
|
||||||
|
entry->y1 = y_offset + height;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
entry->y0 = draw_buffer_height - y_offset - height;
|
||||||
|
entry->y1 = draw_buffer_height - y_offset;
|
||||||
|
}
|
||||||
|
|
||||||
/* Store it in the stack */
|
/* Store it in the stack */
|
||||||
stack->stack_top = g_list_prepend (stack->stack_top, entry);
|
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
|
/* Scale from OpenGL normalized device coordinates (ranging from -1 to 1)
|
||||||
* <0,window-size> with (0,0) being top left. */
|
* to Cogl window/draw-buffer coordinates (ranging from 0 to buffer-size) with
|
||||||
#define VIEWPORT_SCALE_X(x, w, width, origin) \
|
* (0,0) being top left. */
|
||||||
((((((x) / (w)) + 1.0) / 2) * (width)) + (origin))
|
#define VIEWPORT_TRANSFORM_X(x, vp_origin_x, vp_width) \
|
||||||
#define VIEWPORT_SCALE_Y(y, w, height, origin) \
|
( ( ((x) + 1.0) * ((vp_width) / 2.0) ) + (vp_origin_x) )
|
||||||
((height) - (((((y) / (w)) + 1.0) / 2) * (height)) + (origin))
|
/* Note: for Y we first flip all coordinates around the X axis while in
|
||||||
|
* normalized device coodinates */
|
||||||
|
#define VIEWPORT_TRANSFORM_Y(y, vp_origin_y, vp_height) \
|
||||||
|
( ( ((-(y)) + 1.0) * ((vp_height) / 2.0) ) + (vp_origin_y) )
|
||||||
|
|
||||||
|
/* Transform a homogeneous vertex position from model space to Cogl
|
||||||
|
* window coordinates (with 0,0 being top left) */
|
||||||
static void
|
static void
|
||||||
transform_point (CoglMatrix *matrix_mv,
|
transform_point (CoglMatrix *matrix_mv,
|
||||||
CoglMatrix *matrix_p,
|
CoglMatrix *matrix_p,
|
||||||
@ -162,14 +197,19 @@ transform_point (CoglMatrix *matrix_mv,
|
|||||||
float z = 0;
|
float z = 0;
|
||||||
float w = 1;
|
float w = 1;
|
||||||
|
|
||||||
/* Apply the model view matrix */
|
/* Apply the modelview matrix transform */
|
||||||
cogl_matrix_transform_point (matrix_mv, x, y, &z, &w);
|
cogl_matrix_transform_point (matrix_mv, x, y, &z, &w);
|
||||||
|
|
||||||
/* Apply the projection matrix */
|
/* Apply the projection matrix transform */
|
||||||
cogl_matrix_transform_point (matrix_p, x, y, &z, &w);
|
cogl_matrix_transform_point (matrix_p, x, y, &z, &w);
|
||||||
|
|
||||||
|
/* Perform perspective division */
|
||||||
|
*x /= w;
|
||||||
|
*y /= w;
|
||||||
|
|
||||||
/* Apply viewport transform */
|
/* Apply viewport transform */
|
||||||
*x = VIEWPORT_SCALE_X (*x, w, viewport[2], viewport[0]);
|
*x = VIEWPORT_TRANSFORM_X (*x, viewport[0], viewport[2]);
|
||||||
*y = VIEWPORT_SCALE_Y (*y, w, viewport[3], viewport[1]);
|
*y = VIEWPORT_TRANSFORM_Y (*y, viewport[1], viewport[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef VIEWPORT_SCALE_X
|
#undef VIEWPORT_SCALE_X
|
||||||
@ -193,6 +233,15 @@ try_pushing_rect_as_window_rect (float x_offset,
|
|||||||
|
|
||||||
cogl_get_modelview_matrix (&matrix);
|
cogl_get_modelview_matrix (&matrix);
|
||||||
|
|
||||||
|
/* If the modelview meets these constraints then a transformed rectangle
|
||||||
|
* should still be a rectangle when it reaches screen coordinates.
|
||||||
|
*
|
||||||
|
* FIXME: we are are making certain assumptions about the projection
|
||||||
|
* matrix a.t.m and should really be looking at the combined modelview
|
||||||
|
* and projection matrix.
|
||||||
|
* FIXME: we don't consider rotations that are a multiple of 90 degrees
|
||||||
|
* which could be quite common.
|
||||||
|
*/
|
||||||
if (matrix.xy != 0 || matrix.xz != 0 ||
|
if (matrix.xy != 0 || matrix.xz != 0 ||
|
||||||
matrix.yx != 0 || matrix.yz != 0 ||
|
matrix.yx != 0 || matrix.yz != 0 ||
|
||||||
matrix.zx != 0 || matrix.zy != 0)
|
matrix.zx != 0 || matrix.zy != 0)
|
||||||
@ -204,6 +253,15 @@ try_pushing_rect_as_window_rect (float x_offset,
|
|||||||
transform_point (&matrix, &matrix_p, v, &_x0, &_y0);
|
transform_point (&matrix, &matrix_p, v, &_x0, &_y0);
|
||||||
transform_point (&matrix, &matrix_p, v, &_x1, &_y1);
|
transform_point (&matrix, &matrix_p, v, &_x1, &_y1);
|
||||||
|
|
||||||
|
/* Consider that the modelview matrix may flip the rectangle
|
||||||
|
* along the x or y axis... */
|
||||||
|
#define SWAP(A,B) do { float tmp = B; B = A; A = tmp; } while (0)
|
||||||
|
if (_x0 > _x1)
|
||||||
|
SWAP (_x0, _x1);
|
||||||
|
if (_y0 > _y1)
|
||||||
|
SWAP (_y0, _y1);
|
||||||
|
#undef SWAP
|
||||||
|
|
||||||
cogl_clip_push_window_rect (_x0, _y0, _x1 - _x0, _y1 - _y0);
|
cogl_clip_push_window_rect (_x0, _y0, _x1 - _x0, _y1 - _y0);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -214,17 +272,26 @@ cogl_clip_push (float x_offset,
|
|||||||
float width,
|
float width,
|
||||||
float height)
|
float height)
|
||||||
{
|
{
|
||||||
CoglClipStackEntryRect *entry;
|
CoglHandle draw_buffer;
|
||||||
|
CoglClipStackState *clip_state;
|
||||||
CoglClipStack *stack;
|
CoglClipStack *stack;
|
||||||
|
CoglClipStackEntryRect *entry;
|
||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
_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
|
/* Try and catch window space rectangles so we can redirect to
|
||||||
* cogl_clip_push_window_rect which will use scissoring. */
|
* cogl_clip_push_window_rect which will use scissoring. */
|
||||||
if (try_pushing_rect_as_window_rect (x_offset, y_offset, width, height))
|
if (try_pushing_rect_as_window_rect (x_offset, y_offset, width, height))
|
||||||
return;
|
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);
|
entry = g_slice_new (CoglClipStackEntryRect);
|
||||||
|
|
||||||
@ -240,18 +307,27 @@ cogl_clip_push (float x_offset,
|
|||||||
/* Store it in the stack */
|
/* Store it in the stack */
|
||||||
stack->stack_top = g_list_prepend (stack->stack_top, entry);
|
stack->stack_top = g_list_prepend (stack->stack_top, entry);
|
||||||
|
|
||||||
ctx->clip.stack_dirty = TRUE;
|
clip_state->stack_dirty = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cogl_clip_push_from_path_preserve (void)
|
cogl_clip_push_from_path_preserve (void)
|
||||||
{
|
{
|
||||||
CoglClipStackEntryPath *entry;
|
CoglHandle draw_buffer;
|
||||||
|
CoglClipStackState *clip_state;
|
||||||
CoglClipStack *stack;
|
CoglClipStack *stack;
|
||||||
|
CoglClipStackEntryPath *entry;
|
||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
_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)
|
entry = g_malloc (sizeof (CoglClipStackEntryPath)
|
||||||
+ sizeof (CoglPathNode) * (ctx->path_nodes->len - 1));
|
+ sizeof (CoglPathNode) * (ctx->path_nodes->len - 1));
|
||||||
@ -268,7 +344,7 @@ cogl_clip_push_from_path_preserve (void)
|
|||||||
/* Store it in the stack */
|
/* Store it in the stack */
|
||||||
stack->stack_top = g_list_prepend (stack->stack_top, entry);
|
stack->stack_top = g_list_prepend (stack->stack_top, entry);
|
||||||
|
|
||||||
ctx->clip.stack_dirty = TRUE;
|
clip_state->stack_dirty = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -279,16 +355,18 @@ cogl_clip_push_from_path (void)
|
|||||||
cogl_path_new ();
|
cogl_path_new ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
cogl_clip_pop (void)
|
_cogl_clip_pop_real (CoglClipStackState *clip_state)
|
||||||
{
|
{
|
||||||
gpointer entry;
|
|
||||||
CoglClipStack *stack;
|
CoglClipStack *stack;
|
||||||
|
gpointer entry;
|
||||||
CoglClipStackEntryType type;
|
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);
|
g_return_if_fail (stack->stack_top != NULL);
|
||||||
|
|
||||||
@ -306,35 +384,57 @@ cogl_clip_pop (void)
|
|||||||
stack->stack_top = g_list_delete_link (stack->stack_top,
|
stack->stack_top = g_list_delete_link (stack->stack_top,
|
||||||
stack->stack_top);
|
stack->stack_top);
|
||||||
|
|
||||||
ctx->clip.stack_dirty = TRUE;
|
clip_state->stack_dirty = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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_clip_planes = FALSE;
|
||||||
gboolean using_stencil_buffer = FALSE;
|
gboolean using_stencil_buffer = FALSE;
|
||||||
GList *node;
|
GList *node;
|
||||||
CoglClipStack *stack;
|
|
||||||
gint scissor_x0 = 0;
|
gint scissor_x0 = 0;
|
||||||
gint scissor_y0 = 0;
|
gint scissor_y0 = 0;
|
||||||
gint scissor_x1 = G_MAXINT;
|
gint scissor_x1 = G_MAXINT;
|
||||||
gint scissor_y1 = 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);
|
if (!clip_state->stack_dirty)
|
||||||
|
return;
|
||||||
modelview_stack = ctx->modelview_stack;
|
|
||||||
|
|
||||||
/* The current primitive journal does not support tracking changes to the
|
/* The current primitive journal does not support tracking changes to the
|
||||||
* clip stack... */
|
* clip stack... */
|
||||||
_cogl_journal_flush ();
|
_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;
|
has_clip_planes = cogl_features_available (COGL_FEATURE_FOUR_CLIP_PLANES);
|
||||||
ctx->clip.stencil_used = FALSE;
|
|
||||||
|
stack = clip_state->stacks->data;
|
||||||
|
|
||||||
|
clip_state->stencil_used = FALSE;
|
||||||
|
|
||||||
_cogl_disable_clip_planes ();
|
_cogl_disable_clip_planes ();
|
||||||
_cogl_disable_stencil_buffer ();
|
_cogl_disable_stencil_buffer ();
|
||||||
@ -433,74 +533,111 @@ _cogl_clip_stack_rebuild (void)
|
|||||||
scissor_y1 - scissor_y0));
|
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
|
void
|
||||||
cogl_clip_ensure (void)
|
cogl_clip_ensure (void)
|
||||||
{
|
{
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
CoglClipStackState *clip_state;
|
||||||
|
|
||||||
if (ctx->clip.stack_dirty)
|
clip_state = _cogl_draw_buffer_get_clip_state (_cogl_get_draw_buffer ());
|
||||||
_cogl_clip_stack_rebuild ();
|
_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
|
void
|
||||||
cogl_clip_stack_save (void)
|
cogl_clip_stack_save (void)
|
||||||
{
|
{
|
||||||
CoglClipStack *stack;
|
CoglHandle draw_buffer;
|
||||||
|
CoglClipStackState *clip_state;
|
||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
|
|
||||||
stack = g_slice_new (CoglClipStack);
|
draw_buffer = _cogl_get_draw_buffer ();
|
||||||
stack->stack_top = NULL;
|
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
|
void
|
||||||
cogl_clip_stack_restore (void)
|
cogl_clip_stack_restore (void)
|
||||||
{
|
{
|
||||||
CoglClipStack *stack;
|
CoglHandle draw_buffer;
|
||||||
|
CoglClipStackState *clip_state;
|
||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
_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;
|
_cogl_clip_stack_restore_real (clip_state);
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_clip_stack_state_init (void)
|
_cogl_clip_stack_state_init (CoglClipStackState *clip_state)
|
||||||
{
|
{
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
|
|
||||||
ctx->clip.stacks = NULL;
|
clip_state->stacks = NULL;
|
||||||
ctx->clip.stack_dirty = TRUE;
|
clip_state->stack_dirty = TRUE;
|
||||||
|
|
||||||
/* Add an intial stack */
|
/* Add an intial stack */
|
||||||
cogl_clip_stack_save ();
|
_cogl_clip_stack_save_real (clip_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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 */
|
/* Destroy all of the stacks */
|
||||||
while (ctx->clip.stacks)
|
while (clip_state->stacks)
|
||||||
cogl_clip_stack_restore ();
|
_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;
|
gboolean stencil_used;
|
||||||
};
|
};
|
||||||
|
|
||||||
void _cogl_clip_stack_state_init (void);
|
void _cogl_clip_stack_state_init (CoglClipStackState *state);
|
||||||
void _cogl_clip_stack_state_destroy (void);
|
void _cogl_clip_stack_state_destroy (CoglClipStackState *state);
|
||||||
void _cogl_clip_stack_rebuild (void);
|
void _cogl_clip_stack_state_dirty (CoglClipStackState *state);
|
||||||
void _cogl_clip_stack_merge (void);
|
|
||||||
|
void _cogl_flush_clip_state (CoglClipStackState *clip_state);
|
||||||
|
|
||||||
#endif /* __COGL_CLIP_STACK_H */
|
#endif /* __COGL_CLIP_STACK_H */
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "cogl-journal-private.h"
|
#include "cogl-journal-private.h"
|
||||||
#include "cogl-texture-private.h"
|
#include "cogl-texture-private.h"
|
||||||
#include "cogl-material-private.h"
|
#include "cogl-material-private.h"
|
||||||
|
#include "cogl-draw-buffer-private.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@ -46,7 +47,7 @@ cogl_create_context (void)
|
|||||||
{
|
{
|
||||||
GLubyte default_texture_data[] = { 0xff, 0xff, 0xff, 0x0 };
|
GLubyte default_texture_data[] = { 0xff, 0xff, 0xff, 0x0 };
|
||||||
gulong enable_flags = 0;
|
gulong enable_flags = 0;
|
||||||
CoglDrawBufferState *draw_buffer;
|
CoglHandle window_buffer;
|
||||||
|
|
||||||
if (_context != NULL)
|
if (_context != NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -58,16 +59,24 @@ cogl_create_context (void)
|
|||||||
_context->feature_flags = 0;
|
_context->feature_flags = 0;
|
||||||
_context->features_cached = FALSE;
|
_context->features_cached = FALSE;
|
||||||
|
|
||||||
|
/* Initialise the driver specific state */
|
||||||
|
/* TODO: combine these two into one function */
|
||||||
|
_cogl_create_context_driver (_context);
|
||||||
|
_cogl_features_init ();
|
||||||
|
|
||||||
_context->enable_flags = 0;
|
_context->enable_flags = 0;
|
||||||
_context->color_alpha = 0;
|
_context->color_alpha = 0;
|
||||||
|
|
||||||
_context->enable_backface_culling = FALSE;
|
_context->enable_backface_culling = FALSE;
|
||||||
|
_context->flushed_front_winding = COGL_FRONT_WINDING_COUNTER_CLOCKWISE;
|
||||||
|
|
||||||
_context->indirect = gl_is_indirect;
|
_context->indirect = gl_is_indirect;
|
||||||
|
|
||||||
|
cogl_matrix_init_identity (&_context->identity_matrix);
|
||||||
|
cogl_matrix_init_identity (&_context->y_flip_matrix);
|
||||||
|
cogl_matrix_scale (&_context->y_flip_matrix, 1, -1, 1);
|
||||||
|
|
||||||
_context->flushed_matrix_mode = COGL_MATRIX_MODELVIEW;
|
_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->texture_units = NULL;
|
||||||
|
|
||||||
_context->default_material = cogl_material_new ();
|
_context->default_material = cogl_material_new ();
|
||||||
@ -87,11 +96,14 @@ cogl_create_context (void)
|
|||||||
sizeof (CoglLayerInfo));
|
sizeof (CoglLayerInfo));
|
||||||
_context->n_texcoord_arrays_enabled = 0;
|
_context->n_texcoord_arrays_enabled = 0;
|
||||||
|
|
||||||
draw_buffer = g_slice_new0 (CoglDrawBufferState);
|
_context->draw_buffer_stack = _cogl_create_draw_buffer_stack ();
|
||||||
draw_buffer->target = COGL_WINDOW_BUFFER;
|
window_buffer = _cogl_onscreen_new ();
|
||||||
draw_buffer->offscreen = COGL_INVALID_HANDLE;
|
/* XXX: When setting up the window buffer, cogl_set_draw_buffer
|
||||||
_context->draw_buffer_stack =
|
* assumes that the handle can be found in ctx->window_buffer */
|
||||||
g_slist_prepend (NULL, draw_buffer);
|
_context->window_buffer = window_buffer;
|
||||||
|
cogl_set_draw_buffer (COGL_WINDOW_BUFFER, 0/* ignored */);
|
||||||
|
_context->dirty_bound_framebuffer = TRUE;
|
||||||
|
_context->dirty_gl_viewport = TRUE;
|
||||||
|
|
||||||
_context->path_nodes = g_array_new (FALSE, FALSE, sizeof (CoglPathNode));
|
_context->path_nodes = g_array_new (FALSE, FALSE, sizeof (CoglPathNode));
|
||||||
_context->last_path = 0;
|
_context->last_path = 0;
|
||||||
@ -99,21 +111,12 @@ cogl_create_context (void)
|
|||||||
|
|
||||||
_context->in_begin_gl_block = FALSE;
|
_context->in_begin_gl_block = FALSE;
|
||||||
|
|
||||||
_context->viewport_width = 0;
|
|
||||||
_context->viewport_height = 0;
|
|
||||||
|
|
||||||
_context->quad_indices_byte = COGL_INVALID_HANDLE;
|
_context->quad_indices_byte = COGL_INVALID_HANDLE;
|
||||||
_context->quad_indices_short = COGL_INVALID_HANDLE;
|
_context->quad_indices_short = COGL_INVALID_HANDLE;
|
||||||
_context->quad_indices_short_len = 0;
|
_context->quad_indices_short_len = 0;
|
||||||
|
|
||||||
_context->texture_download_material = COGL_INVALID_HANDLE;
|
_context->texture_download_material = COGL_INVALID_HANDLE;
|
||||||
|
|
||||||
/* Initialise the clip stack */
|
|
||||||
_cogl_clip_stack_state_init ();
|
|
||||||
|
|
||||||
/* Initialise the driver specific state */
|
|
||||||
_cogl_create_context_driver (_context);
|
|
||||||
|
|
||||||
/* Create default textures used for fall backs */
|
/* Create default textures used for fall backs */
|
||||||
_context->default_gl_texture_2d_tex =
|
_context->default_gl_texture_2d_tex =
|
||||||
cogl_texture_new_from_data (1, /* width */
|
cogl_texture_new_from_data (1, /* width */
|
||||||
@ -139,6 +142,7 @@ cogl_create_context (void)
|
|||||||
enable_flags =
|
enable_flags =
|
||||||
_cogl_material_get_cogl_enable_flags (_context->source_material);
|
_cogl_material_get_cogl_enable_flags (_context->source_material);
|
||||||
cogl_enable (enable_flags);
|
cogl_enable (enable_flags);
|
||||||
|
_cogl_flush_face_winding ();
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -146,16 +150,14 @@ cogl_create_context (void)
|
|||||||
void
|
void
|
||||||
_cogl_destroy_context ()
|
_cogl_destroy_context ()
|
||||||
{
|
{
|
||||||
|
|
||||||
if (_context == NULL)
|
if (_context == NULL)
|
||||||
return;
|
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_destroy_texture_units ();
|
||||||
|
|
||||||
|
_cogl_free_draw_buffer_stack (_context->draw_buffer_stack);
|
||||||
|
|
||||||
if (_context->path_nodes)
|
if (_context->path_nodes)
|
||||||
g_array_free (_context->path_nodes, TRUE);
|
g_array_free (_context->path_nodes, TRUE);
|
||||||
|
|
||||||
|
@ -38,12 +38,6 @@ typedef struct
|
|||||||
GLubyte c[4];
|
GLubyte c[4];
|
||||||
} CoglTextureGLVertex;
|
} CoglTextureGLVertex;
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
CoglBufferTarget target;
|
|
||||||
CoglHandle offscreen;
|
|
||||||
} CoglDrawBufferState;
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
/* Features cache */
|
/* Features cache */
|
||||||
@ -55,19 +49,18 @@ typedef struct
|
|||||||
guint8 color_alpha;
|
guint8 color_alpha;
|
||||||
|
|
||||||
gboolean enable_backface_culling;
|
gboolean enable_backface_culling;
|
||||||
|
CoglFrontWinding flushed_front_winding;
|
||||||
|
|
||||||
gboolean indirect;
|
gboolean indirect;
|
||||||
|
|
||||||
|
/* A few handy matrix constants */
|
||||||
|
CoglMatrix identity_matrix;
|
||||||
|
CoglMatrix y_flip_matrix;
|
||||||
|
|
||||||
/* Client-side matrix stack or NULL if none */
|
/* Client-side matrix stack or NULL if none */
|
||||||
CoglMatrixMode flushed_matrix_mode;
|
CoglMatrixMode flushed_matrix_mode;
|
||||||
CoglMatrixStack *projection_stack;
|
|
||||||
CoglMatrixStack *modelview_stack;
|
|
||||||
|
|
||||||
GList *texture_units;
|
GList *texture_units;
|
||||||
|
|
||||||
/* Cache of inverse projection matrix */
|
|
||||||
float inverse_projection[16];
|
|
||||||
|
|
||||||
/* Materials */
|
/* Materials */
|
||||||
CoglHandle default_material;
|
CoglHandle default_material;
|
||||||
CoglHandle source_material;
|
CoglHandle source_material;
|
||||||
@ -91,11 +84,11 @@ typedef struct
|
|||||||
GArray *current_layers;
|
GArray *current_layers;
|
||||||
guint n_texcoord_arrays_enabled;
|
guint n_texcoord_arrays_enabled;
|
||||||
|
|
||||||
/* Framebuffer objects */
|
/* Draw Buffers */
|
||||||
GSList *draw_buffer_stack;
|
GSList *draw_buffer_stack;
|
||||||
|
CoglHandle window_buffer;
|
||||||
/* Clip stack */
|
gboolean dirty_bound_framebuffer;
|
||||||
CoglClipStackState clip;
|
gboolean dirty_gl_viewport;
|
||||||
|
|
||||||
/* Primitives */
|
/* Primitives */
|
||||||
floatVec2 path_start;
|
floatVec2 path_start;
|
||||||
@ -114,9 +107,6 @@ typedef struct
|
|||||||
|
|
||||||
gboolean in_begin_gl_block;
|
gboolean in_begin_gl_block;
|
||||||
|
|
||||||
guint viewport_width;
|
|
||||||
guint viewport_height;
|
|
||||||
|
|
||||||
CoglHandle texture_download_material;
|
CoglHandle texture_download_material;
|
||||||
|
|
||||||
CoglContextDriver drv;
|
CoglContextDriver drv;
|
||||||
|
@ -46,7 +46,8 @@ static const GDebugKey cogl_debug_keys[] = {
|
|||||||
{ "disable-vbos", COGL_DEBUG_DISABLE_VBOS },
|
{ "disable-vbos", COGL_DEBUG_DISABLE_VBOS },
|
||||||
{ "journal", COGL_DEBUG_JOURNAL },
|
{ "journal", COGL_DEBUG_JOURNAL },
|
||||||
{ "batching", COGL_DEBUG_BATCHING },
|
{ "batching", COGL_DEBUG_BATCHING },
|
||||||
{ "disable-software-transform", COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM }
|
{ "disable-software-transform", COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM },
|
||||||
|
{ "matrices", COGL_DEBUG_MATRICES }
|
||||||
};
|
};
|
||||||
|
|
||||||
static const gint n_cogl_debug_keys = G_N_ELEMENTS (cogl_debug_keys);
|
static const gint n_cogl_debug_keys = G_N_ELEMENTS (cogl_debug_keys);
|
||||||
|
@ -44,7 +44,8 @@ typedef enum {
|
|||||||
COGL_DEBUG_DISABLE_VBOS = 1 << 12,
|
COGL_DEBUG_DISABLE_VBOS = 1 << 12,
|
||||||
COGL_DEBUG_JOURNAL = 1 << 13,
|
COGL_DEBUG_JOURNAL = 1 << 13,
|
||||||
COGL_DEBUG_BATCHING = 1 << 14,
|
COGL_DEBUG_BATCHING = 1 << 14,
|
||||||
COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM = 1 << 15
|
COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM = 1 << 15,
|
||||||
|
COGL_DEBUG_MATRICES = 1 << 16
|
||||||
} CoglDebugFlags;
|
} CoglDebugFlags;
|
||||||
|
|
||||||
#ifdef COGL_ENABLE_DEBUG
|
#ifdef COGL_ENABLE_DEBUG
|
||||||
|
133
clutter/cogl/cogl/cogl-draw-buffer-private.h
Normal file
133
clutter/cogl/cogl/cogl-draw-buffer-private.h
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
int
|
||||||
|
_cogl_draw_buffer_get_width (CoglHandle handle);
|
||||||
|
int
|
||||||
|
_cogl_draw_buffer_get_height (CoglHandle handle);
|
||||||
|
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);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
cogl_is_offscreen (CoglHandle handle);
|
||||||
|
|
||||||
|
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 */
|
||||||
|
|
602
clutter/cogl/cogl/cogl-draw-buffer.c
Normal file
602
clutter/cogl/cogl/cogl-draw-buffer.c
Normal file
@ -0,0 +1,602 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_cogl_draw_buffer_get_width (CoglHandle handle)
|
||||||
|
{
|
||||||
|
CoglDrawBuffer *draw_buffer = COGL_DRAW_BUFFER (handle);
|
||||||
|
return draw_buffer->width;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_cogl_draw_buffer_get_height (CoglHandle handle)
|
||||||
|
{
|
||||||
|
CoglDrawBuffer *draw_buffer = COGL_DRAW_BUFFER (handle);
|
||||||
|
return draw_buffer->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
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_gl_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_onscreen_clutter_backend_set_size (int width, int height)
|
||||||
|
{
|
||||||
|
CoglDrawBuffer *draw_buffer;
|
||||||
|
|
||||||
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
|
|
||||||
|
draw_buffer = COGL_DRAW_BUFFER (ctx->window_buffer);
|
||||||
|
|
||||||
|
if (draw_buffer->width == width && draw_buffer->height == height)
|
||||||
|
return;
|
||||||
|
|
||||||
|
draw_buffer->width = width;
|
||||||
|
draw_buffer->height = height;
|
||||||
|
|
||||||
|
/* We'll need to recalculate the GL viewport state derived
|
||||||
|
* from the Cogl viewport */
|
||||||
|
ctx->dirty_gl_viewport = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
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_gl_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_gl_viewport)
|
||||||
|
{
|
||||||
|
int gl_viewport_y;
|
||||||
|
|
||||||
|
/* Convert the Cogl viewport y offset to an OpenGL viewport y offset
|
||||||
|
* NB: OpenGL defines its window and viewport origins to be bottom
|
||||||
|
* left, while Cogl defines them to be top left.
|
||||||
|
* NB: We render upside down to offscreen draw buffers so we don't
|
||||||
|
* need to convert the y offset in this case. */
|
||||||
|
if (cogl_is_offscreen (draw_buffer))
|
||||||
|
gl_viewport_y = draw_buffer->viewport_y;
|
||||||
|
else
|
||||||
|
gl_viewport_y = draw_buffer->height -
|
||||||
|
(draw_buffer->viewport_y + draw_buffer->viewport_height);
|
||||||
|
|
||||||
|
GE (glViewport (draw_buffer->viewport_x,
|
||||||
|
gl_viewport_y,
|
||||||
|
draw_buffer->viewport_width,
|
||||||
|
draw_buffer->viewport_height));
|
||||||
|
ctx->dirty_gl_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);
|
||||||
|
}
|
||||||
|
|
@ -34,6 +34,12 @@ typedef enum
|
|||||||
COGL_MATRIX_TEXTURE
|
COGL_MATRIX_TEXTURE
|
||||||
} CoglMatrixMode;
|
} CoglMatrixMode;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
COGL_FRONT_WINDING_CLOCKWISE,
|
||||||
|
COGL_FRONT_WINDING_COUNTER_CLOCKWISE
|
||||||
|
} CoglFrontWinding;
|
||||||
|
|
||||||
#ifdef HAVE_COGL_GLES2
|
#ifdef HAVE_COGL_GLES2
|
||||||
typedef enum {
|
typedef enum {
|
||||||
COGL_BOXED_NONE,
|
COGL_BOXED_NONE,
|
||||||
@ -105,4 +111,7 @@ _cogl_destroy_texture_units (void);
|
|||||||
|
|
||||||
void _cogl_flush_matrix_stacks (void);
|
void _cogl_flush_matrix_stacks (void);
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_flush_face_winding (void);
|
||||||
|
|
||||||
#endif /* __COGL_INTERNAL_H */
|
#endif /* __COGL_INTERNAL_H */
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "cogl-texture-private.h"
|
#include "cogl-texture-private.h"
|
||||||
#include "cogl-material-private.h"
|
#include "cogl-material-private.h"
|
||||||
#include "cogl-vertex-buffer-private.h"
|
#include "cogl-vertex-buffer-private.h"
|
||||||
|
#include "cogl-draw-buffer-private.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <gmodule.h>
|
#include <gmodule.h>
|
||||||
@ -301,6 +302,7 @@ _cogl_journal_flush_material_and_entries (CoglJournalEntry *batch_start,
|
|||||||
enable_flags |= COGL_ENABLE_VERTEX_ARRAY;
|
enable_flags |= COGL_ENABLE_VERTEX_ARRAY;
|
||||||
enable_flags |= COGL_ENABLE_COLOR_ARRAY;
|
enable_flags |= COGL_ENABLE_COLOR_ARRAY;
|
||||||
cogl_enable (enable_flags);
|
cogl_enable (enable_flags);
|
||||||
|
_cogl_flush_face_winding ();
|
||||||
|
|
||||||
/* If we haven't transformed the quads in software then we need to also break
|
/* If we haven't transformed the quads in software then we need to also break
|
||||||
* up batches according to changes in the modelview matrix... */
|
* up batches according to changes in the modelview matrix... */
|
||||||
@ -531,6 +533,8 @@ _cogl_journal_flush (void)
|
|||||||
GLuint journal_vbo;
|
GLuint journal_vbo;
|
||||||
gboolean vbo_fallback =
|
gboolean vbo_fallback =
|
||||||
(cogl_get_features () & COGL_FEATURE_VBOS) ? FALSE : TRUE;
|
(cogl_get_features () & COGL_FEATURE_VBOS) ? FALSE : TRUE;
|
||||||
|
CoglHandle draw_buffer;
|
||||||
|
CoglMatrixStack *modelview_stack;
|
||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
|
|
||||||
@ -547,20 +551,19 @@ _cogl_journal_flush (void)
|
|||||||
else
|
else
|
||||||
state.vbo_offset = (char *)ctx->logged_vertices->data;
|
state.vbo_offset = (char *)ctx->logged_vertices->data;
|
||||||
|
|
||||||
_cogl_matrix_stack_flush_to_gl (ctx->projection_stack,
|
draw_buffer = _cogl_get_draw_buffer ();
|
||||||
COGL_MATRIX_PROJECTION);
|
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 (modelview_stack);
|
||||||
_cogl_matrix_stack_push (ctx->modelview_stack);
|
|
||||||
|
|
||||||
/* If we have transformed all our quads at log time then we ensure no
|
/* If we have transformed all our quads at log time then we ensure no
|
||||||
* further model transform is applied by loading the identity matrix
|
* further model transform is applied by loading the identity matrix
|
||||||
* here... */
|
* here... */
|
||||||
if (G_LIKELY (!(cogl_debug_flags & COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM)))
|
if (G_LIKELY (!(cogl_debug_flags & COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM)))
|
||||||
{
|
{
|
||||||
_cogl_matrix_stack_load_identity (ctx->modelview_stack);
|
_cogl_matrix_stack_load_identity (modelview_stack);
|
||||||
_cogl_matrix_stack_flush_to_gl (ctx->modelview_stack,
|
_cogl_matrix_stack_flush_to_gl (modelview_stack, COGL_MATRIX_MODELVIEW);
|
||||||
COGL_MATRIX_MODELVIEW);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* batch_and_call() batches a list of journal entries according to some
|
/* batch_and_call() batches a list of journal entries according to some
|
||||||
@ -591,7 +594,7 @@ _cogl_journal_flush (void)
|
|||||||
_cogl_journal_flush_vbo_offsets_and_entries, /* callback */
|
_cogl_journal_flush_vbo_offsets_and_entries, /* callback */
|
||||||
&state); /* data */
|
&state); /* data */
|
||||||
|
|
||||||
_cogl_matrix_stack_pop (ctx->modelview_stack);
|
_cogl_matrix_stack_pop (modelview_stack);
|
||||||
|
|
||||||
for (i = 0; i < ctx->journal->len; i++)
|
for (i = 0; i < ctx->journal->len; i++)
|
||||||
{
|
{
|
||||||
@ -607,6 +610,18 @@ _cogl_journal_flush (void)
|
|||||||
g_array_set_size (ctx->logged_vertices, 0);
|
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
|
void
|
||||||
_cogl_journal_log_quad (float x_1,
|
_cogl_journal_log_quad (float x_1,
|
||||||
float y_1,
|
float y_1,
|
||||||
@ -632,6 +647,9 @@ _cogl_journal_log_quad (float x_1,
|
|||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
_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
|
/* The vertex data is logged into a separate array in a layout that can be
|
||||||
* directly passed to OpenGL
|
* directly passed to OpenGL
|
||||||
*/
|
*/
|
||||||
|
1698
clutter/cogl/cogl/cogl-matrix-mesa.c
Normal file
1698
clutter/cogl/cogl/cogl-matrix-mesa.c
Normal file
File diff suppressed because it is too large
Load Diff
226
clutter/cogl/cogl/cogl-matrix-mesa.h
Normal file
226
clutter/cogl/cogl/cogl-matrix-mesa.h
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
/*
|
||||||
|
* Cogl
|
||||||
|
*
|
||||||
|
* An object oriented GL/GLES Abstraction/Utility Layer
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Intel Corporation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file math/m_matrix.h
|
||||||
|
* Defines basic structures for matrix-handling.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _M_MATRIX_H
|
||||||
|
#define _M_MATRIX_H
|
||||||
|
|
||||||
|
#include <cogl-matrix.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \name Symbolic names to some of the entries in the matrix
|
||||||
|
*
|
||||||
|
* These are handy for the viewport mapping, which is expressed as a matrix.
|
||||||
|
*/
|
||||||
|
/*@{*/
|
||||||
|
#define MAT_SX 0
|
||||||
|
#define MAT_SY 5
|
||||||
|
#define MAT_SZ 10
|
||||||
|
#define MAT_TX 12
|
||||||
|
#define MAT_TY 13
|
||||||
|
#define MAT_TZ 14
|
||||||
|
/*@}*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Different kinds of 4x4 transformation matrices.
|
||||||
|
* We use these to select specific optimized vertex transformation routines.
|
||||||
|
*/
|
||||||
|
enum CoglMatrixType {
|
||||||
|
COGL_MATRIX_TYPE_GENERAL, /**< general 4x4 matrix */
|
||||||
|
COGL_MATRIX_TYPE_IDENTITY, /**< identity matrix */
|
||||||
|
COGL_MATRIX_TYPE_3D_NO_ROT, /**< orthogonal projection and others... */
|
||||||
|
COGL_MATRIX_TYPE_PERSPECTIVE, /**< perspective projection matrix */
|
||||||
|
COGL_MATRIX_TYPE_2D, /**< 2-D transformation */
|
||||||
|
COGL_MATRIX_TYPE_2D_NO_ROT, /**< 2-D scale & translate only */
|
||||||
|
COGL_MATRIX_TYPE_3D /**< 3-D transformation */
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/**
|
||||||
|
* Matrix type to represent 4x4 transformation matrices.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
float *m; /**< 16 matrix elements (16-byte aligned) */
|
||||||
|
float *inv; /**< optional 16-element inverse (16-byte aligned) */
|
||||||
|
unsigned int flags; /**< possible values determined by (of \link
|
||||||
|
* MatFlags MAT_FLAG_* flags\endlink)
|
||||||
|
*/
|
||||||
|
enum CoglMatrixType type;
|
||||||
|
} CoglMatrix;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
_math_matrix_multiply (CoglMatrix *result,
|
||||||
|
const CoglMatrix *a,
|
||||||
|
const CoglMatrix *b);
|
||||||
|
|
||||||
|
void
|
||||||
|
_math_matrix_multiply_array (CoglMatrix *result, const float *b);
|
||||||
|
|
||||||
|
void
|
||||||
|
_math_matrix_init_from_array (CoglMatrix *matrix, const float *array);
|
||||||
|
|
||||||
|
void
|
||||||
|
_math_matrix_translate (CoglMatrix *matrix, float x, float y, float z);
|
||||||
|
|
||||||
|
void
|
||||||
|
_math_matrix_rotate (CoglMatrix *matrix, float angle,
|
||||||
|
float x, float y, float z);
|
||||||
|
|
||||||
|
void
|
||||||
|
_math_matrix_scale (CoglMatrix *matrix, float x, float y, float z);
|
||||||
|
|
||||||
|
void
|
||||||
|
_math_matrix_ortho (CoglMatrix *matrix,
|
||||||
|
float left, float right,
|
||||||
|
float bottom, float top,
|
||||||
|
float nearval, float farval);
|
||||||
|
|
||||||
|
void
|
||||||
|
_math_matrix_frustum (CoglMatrix *matrix,
|
||||||
|
float left, float right,
|
||||||
|
float bottom, float top,
|
||||||
|
float nearval, float farval);
|
||||||
|
|
||||||
|
void
|
||||||
|
_math_matrix_viewport (CoglMatrix *matrix,
|
||||||
|
int x, int y, int width, int height,
|
||||||
|
float z_near, float z_far, float depth_max);
|
||||||
|
|
||||||
|
void
|
||||||
|
_math_matrix_init_identity (CoglMatrix *matrix);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
_math_matrix_update_inverse (CoglMatrix *matrix);
|
||||||
|
|
||||||
|
void
|
||||||
|
_math_matrix_update_type_and_flags (CoglMatrix *matrix);
|
||||||
|
|
||||||
|
void
|
||||||
|
_math_matrix_print (const CoglMatrix *matrix);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
_math_matrix_is_length_preserving (const CoglMatrix *matrix);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
_math_matrix_has_rotation (const CoglMatrix *matrix);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
_math_matrix_is_general_scale (const CoglMatrix *matrix);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
_math_matrix_is_dirty (const CoglMatrix *matrix);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \name Related functions that don't actually operate on CoglMatrix structs
|
||||||
|
*/
|
||||||
|
/*@{*/
|
||||||
|
|
||||||
|
void
|
||||||
|
_math_transposef ( float to[16], const float from[16]);
|
||||||
|
|
||||||
|
void
|
||||||
|
_math_transposed (double to[16], const double from[16]);
|
||||||
|
|
||||||
|
void
|
||||||
|
_math_transposefd (float to[16], const double from[16]);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Transform a point (column vector) by a matrix: Q = M * P
|
||||||
|
*/
|
||||||
|
#define TRANSFORM_POINT( Q, M, P ) \
|
||||||
|
Q[0] = M[0] * P[0] + M[4] * P[1] + M[8] * P[2] + M[12] * P[3]; \
|
||||||
|
Q[1] = M[1] * P[0] + M[5] * P[1] + M[9] * P[2] + M[13] * P[3]; \
|
||||||
|
Q[2] = M[2] * P[0] + M[6] * P[1] + M[10] * P[2] + M[14] * P[3]; \
|
||||||
|
Q[3] = M[3] * P[0] + M[7] * P[1] + M[11] * P[2] + M[15] * P[3];
|
||||||
|
|
||||||
|
|
||||||
|
#define TRANSFORM_POINT3( Q, M, P ) \
|
||||||
|
Q[0] = M[0] * P[0] + M[4] * P[1] + M[8] * P[2] + M[12]; \
|
||||||
|
Q[1] = M[1] * P[0] + M[5] * P[1] + M[9] * P[2] + M[13]; \
|
||||||
|
Q[2] = M[2] * P[0] + M[6] * P[1] + M[10] * P[2] + M[14]; \
|
||||||
|
Q[3] = M[3] * P[0] + M[7] * P[1] + M[11] * P[2] + M[15];
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Transform a normal (row vector) by a matrix: [NX NY NZ] = N * MAT
|
||||||
|
*/
|
||||||
|
#define TRANSFORM_NORMAL( TO, N, MAT ) \
|
||||||
|
do { \
|
||||||
|
TO[0] = N[0] * MAT[0] + N[1] * MAT[1] + N[2] * MAT[2]; \
|
||||||
|
TO[1] = N[0] * MAT[4] + N[1] * MAT[5] + N[2] * MAT[6]; \
|
||||||
|
TO[2] = N[0] * MAT[8] + N[1] * MAT[9] + N[2] * MAT[10]; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform a direction by a matrix.
|
||||||
|
*/
|
||||||
|
#define TRANSFORM_DIRECTION( TO, DIR, MAT ) \
|
||||||
|
do { \
|
||||||
|
TO[0] = DIR[0] * MAT[0] + DIR[1] * MAT[4] + DIR[2] * MAT[8]; \
|
||||||
|
TO[1] = DIR[0] * MAT[1] + DIR[1] * MAT[5] + DIR[2] * MAT[9]; \
|
||||||
|
TO[2] = DIR[0] * MAT[2] + DIR[1] * MAT[6] + DIR[2] * MAT[10];\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
_mesa_transform_vector (float u[4], const float v[4], const float m[16]);
|
||||||
|
|
||||||
|
|
||||||
|
/*@}*/
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* An object oriented GL/GLES Abstraction/Utility Layer
|
* An object oriented GL/GLES Abstraction/Utility Layer
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007,2008,2009 Intel Corporation.
|
* Copyright (C) 2008,2009 Intel Corporation.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
@ -19,21 +19,29 @@
|
|||||||
* License along with this library; if not, write to the
|
* License along with this library; if not, write to the
|
||||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
* Boston, MA 02111-1307, USA.
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Robert Bragg <robert@linux.intel.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __COGL_FBO_H
|
#ifndef __COGL_MATRIX_PRIVATE_H
|
||||||
#define __COGL_FBO_H
|
#define __COGL_MATRIX_PRIVATE_H
|
||||||
|
|
||||||
#include "cogl-handle.h"
|
#include <glib.h>
|
||||||
|
|
||||||
typedef struct
|
G_BEGIN_DECLS
|
||||||
{
|
|
||||||
CoglHandleObject _parent;
|
|
||||||
int width;
|
|
||||||
int height;
|
|
||||||
GLuint gl_handle;
|
|
||||||
GLuint gl_stencil_handle;
|
|
||||||
|
|
||||||
} CoglFbo;
|
#define _COGL_MATRIX_DEBUG_PRINT(MATRIX) \
|
||||||
|
if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_MATRICES)) \
|
||||||
|
{ \
|
||||||
|
g_print ("%s:\n", G_STRFUNC); \
|
||||||
|
_cogl_matrix_print (MATRIX); \
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_matrix_print (CoglMatrix *matrix);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __COGL_MATRIX_PRIVATE_H */
|
||||||
|
|
||||||
#endif /* __COGL_FBO_H */
|
|
@ -22,6 +22,7 @@
|
|||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
* Havoc Pennington <hp@pobox.com> for litl
|
* Havoc Pennington <hp@pobox.com> for litl
|
||||||
|
* Robert Bragg <robert@linux.intel.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
@ -32,6 +33,7 @@
|
|||||||
#include "cogl-context.h"
|
#include "cogl-context.h"
|
||||||
#include "cogl-internal.h"
|
#include "cogl-internal.h"
|
||||||
#include "cogl-matrix-stack.h"
|
#include "cogl-matrix-stack.h"
|
||||||
|
#include "cogl-draw-buffer-private.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
CoglMatrix matrix;
|
CoglMatrix matrix;
|
||||||
@ -346,6 +348,17 @@ _cogl_matrix_stack_ortho (CoglMatrixStack *stack,
|
|||||||
state->is_identity = FALSE;
|
state->is_identity = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
_cogl_matrix_stack_get_inverse (CoglMatrixStack *stack,
|
||||||
|
CoglMatrix *inverse)
|
||||||
|
{
|
||||||
|
CoglMatrixState *state;
|
||||||
|
|
||||||
|
state = _cogl_matrix_stack_top_mutable (stack, TRUE);
|
||||||
|
|
||||||
|
return cogl_matrix_get_inverse (&state->matrix, inverse);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_matrix_stack_get (CoglMatrixStack *stack,
|
_cogl_matrix_stack_get (CoglMatrixStack *stack,
|
||||||
CoglMatrix *matrix)
|
CoglMatrix *matrix)
|
||||||
@ -412,21 +425,35 @@ _cogl_matrix_stack_flush_to_gl (CoglMatrixStack *stack,
|
|||||||
ctx->flushed_matrix_mode = mode;
|
ctx->flushed_matrix_mode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* In theory it might help the GL implementation if we used our
|
/* Because Cogl defines texture coordinates to have a top left origin and
|
||||||
* local analysis of the matrix and called Translate/Scale rather
|
* because offscreen draw buffers may be used for rendering to textures we
|
||||||
* than LoadMatrix to send a 2D matrix
|
* always render upside down to offscreen buffers.
|
||||||
*/
|
*/
|
||||||
|
if (mode == COGL_MATRIX_PROJECTION &&
|
||||||
if (state->is_identity)
|
cogl_is_offscreen (_cogl_get_draw_buffer ()))
|
||||||
{
|
{
|
||||||
if (!stack->flushed_identity)
|
CoglMatrix flipped_projection;
|
||||||
GE (glLoadIdentity ());
|
CoglMatrix *projection =
|
||||||
stack->flushed_identity = TRUE;
|
state->is_identity ? &ctx->identity_matrix : &state->matrix;
|
||||||
|
|
||||||
|
cogl_matrix_multiply (&flipped_projection,
|
||||||
|
&ctx->y_flip_matrix, projection);
|
||||||
|
GE (glLoadMatrixf (cogl_matrix_get_array (&flipped_projection)));
|
||||||
|
stack->flushed_identity = FALSE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GE (glLoadMatrixf (cogl_matrix_get_array (&state->matrix)));
|
if (state->is_identity)
|
||||||
stack->flushed_identity = FALSE;
|
{
|
||||||
|
if (!stack->flushed_identity)
|
||||||
|
GE (glLoadIdentity ());
|
||||||
|
stack->flushed_identity = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GE (glLoadMatrixf (cogl_matrix_get_array (&state->matrix)));
|
||||||
|
stack->flushed_identity = FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
stack->flushed_state = state;
|
stack->flushed_state = state;
|
||||||
}
|
}
|
||||||
|
@ -71,6 +71,9 @@ void _cogl_matrix_stack_ortho (CoglMatrixStack *stack,
|
|||||||
float top,
|
float top,
|
||||||
float z_near,
|
float z_near,
|
||||||
float z_far);
|
float z_far);
|
||||||
|
|
||||||
|
gboolean _cogl_matrix_stack_get_inverse (CoglMatrixStack *stack,
|
||||||
|
CoglMatrix *inverse);
|
||||||
void _cogl_matrix_stack_get (CoglMatrixStack *stack,
|
void _cogl_matrix_stack_get (CoglMatrixStack *stack,
|
||||||
CoglMatrix *matrix);
|
CoglMatrix *matrix);
|
||||||
void _cogl_matrix_stack_set (CoglMatrixStack *stack,
|
void _cogl_matrix_stack_set (CoglMatrixStack *stack,
|
||||||
|
@ -24,20 +24,41 @@
|
|||||||
* Robert Bragg <robert@linux.intel.com>
|
* Robert Bragg <robert@linux.intel.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define USE_MESA_MATRIX_API
|
||||||
|
|
||||||
#include <cogl.h>
|
#include <cogl.h>
|
||||||
#include <cogl-matrix.h>
|
#include <cogl-matrix.h>
|
||||||
|
#include <cogl-matrix-private.h>
|
||||||
|
#ifdef USE_MESA_MATRIX_API
|
||||||
|
#include <cogl-matrix-mesa.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_matrix_print (CoglMatrix *matrix)
|
||||||
|
{
|
||||||
|
float *m = (float *)matrix;
|
||||||
|
int y;
|
||||||
|
|
||||||
|
for (y = 0; y < 4; y++)
|
||||||
|
g_print ("\t%6.4f %6.4f %6.4f %6.4f\n", m[y], m[4+y], m[8+y], m[12+y]);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cogl_matrix_init_identity (CoglMatrix *matrix)
|
cogl_matrix_init_identity (CoglMatrix *matrix)
|
||||||
{
|
{
|
||||||
|
#ifndef USE_MESA_MATRIX_API
|
||||||
matrix->xx = 1; matrix->xy = 0; matrix->xz = 0; matrix->xw = 0;
|
matrix->xx = 1; matrix->xy = 0; matrix->xz = 0; matrix->xw = 0;
|
||||||
matrix->yx = 0; matrix->yy = 1; matrix->yz = 0; matrix->yw = 0;
|
matrix->yx = 0; matrix->yy = 1; matrix->yz = 0; matrix->yw = 0;
|
||||||
matrix->zx = 0; matrix->zy = 0; matrix->zz = 1; matrix->zw = 0;
|
matrix->zx = 0; matrix->zy = 0; matrix->zz = 1; matrix->zw = 0;
|
||||||
matrix->wx = 0; matrix->wy = 0; matrix->wz = 0; matrix->ww = 1;
|
matrix->wx = 0; matrix->wy = 0; matrix->wz = 0; matrix->ww = 1;
|
||||||
|
#else
|
||||||
|
_math_matrix_init_identity (matrix);
|
||||||
|
#endif
|
||||||
|
_COGL_MATRIX_DEBUG_PRINT (matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -45,6 +66,7 @@ cogl_matrix_multiply (CoglMatrix *result,
|
|||||||
const CoglMatrix *a,
|
const CoglMatrix *a,
|
||||||
const CoglMatrix *b)
|
const CoglMatrix *b)
|
||||||
{
|
{
|
||||||
|
#ifndef USE_MESA_MATRIX_API
|
||||||
CoglMatrix r;
|
CoglMatrix r;
|
||||||
|
|
||||||
/* row 0 */
|
/* row 0 */
|
||||||
@ -73,10 +95,14 @@ cogl_matrix_multiply (CoglMatrix *result,
|
|||||||
|
|
||||||
/* The idea was that having this unrolled; it might be easier for the
|
/* The idea was that having this unrolled; it might be easier for the
|
||||||
* compiler to vectorize, but that's probably not true. Mesa does it
|
* compiler to vectorize, but that's probably not true. Mesa does it
|
||||||
* using a single for (i=0; i<4; i++) approach, may that's better...
|
* using a single for (i=0; i<4; i++) approach, maybe that's better...
|
||||||
*/
|
*/
|
||||||
|
|
||||||
*result = r;
|
*result = r;
|
||||||
|
#else
|
||||||
|
_math_matrix_multiply (result, a, b);
|
||||||
|
#endif
|
||||||
|
_COGL_MATRIX_DEBUG_PRINT (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -86,6 +112,7 @@ cogl_matrix_rotate (CoglMatrix *matrix,
|
|||||||
float y,
|
float y,
|
||||||
float z)
|
float z)
|
||||||
{
|
{
|
||||||
|
#ifndef USE_MESA_MATRIX_API
|
||||||
CoglMatrix rotation;
|
CoglMatrix rotation;
|
||||||
CoglMatrix result;
|
CoglMatrix result;
|
||||||
float c, s;
|
float c, s;
|
||||||
@ -116,6 +143,10 @@ cogl_matrix_rotate (CoglMatrix *matrix,
|
|||||||
|
|
||||||
cogl_matrix_multiply (&result, matrix, &rotation);
|
cogl_matrix_multiply (&result, matrix, &rotation);
|
||||||
*matrix = result;
|
*matrix = result;
|
||||||
|
#else
|
||||||
|
_math_matrix_rotate (matrix, angle, x, y, z);
|
||||||
|
#endif
|
||||||
|
_COGL_MATRIX_DEBUG_PRINT (matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -124,10 +155,15 @@ cogl_matrix_translate (CoglMatrix *matrix,
|
|||||||
float y,
|
float y,
|
||||||
float z)
|
float z)
|
||||||
{
|
{
|
||||||
|
#ifndef USE_MESA_MATRIX_API
|
||||||
matrix->xw = matrix->xx * x + matrix->xy * y + matrix->xz * z + matrix->xw;
|
matrix->xw = matrix->xx * x + matrix->xy * y + matrix->xz * z + matrix->xw;
|
||||||
matrix->yw = matrix->yx * x + matrix->yy * y + matrix->yz * z + matrix->yw;
|
matrix->yw = matrix->yx * x + matrix->yy * y + matrix->yz * z + matrix->yw;
|
||||||
matrix->zw = matrix->zx * x + matrix->zy * y + matrix->zz * z + matrix->zw;
|
matrix->zw = matrix->zx * x + matrix->zy * y + matrix->zz * z + matrix->zw;
|
||||||
matrix->ww = matrix->wx * x + matrix->wy * y + matrix->wz * z + matrix->ww;
|
matrix->ww = matrix->wx * x + matrix->wy * y + matrix->wz * z + matrix->ww;
|
||||||
|
#else
|
||||||
|
_math_matrix_translate (matrix, x, y, z);
|
||||||
|
#endif
|
||||||
|
_COGL_MATRIX_DEBUG_PRINT (matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -136,23 +172,16 @@ cogl_matrix_scale (CoglMatrix *matrix,
|
|||||||
float sy,
|
float sy,
|
||||||
float sz)
|
float sz)
|
||||||
{
|
{
|
||||||
|
#ifndef USE_MESA_MATRIX_API
|
||||||
matrix->xx *= sx; matrix->xy *= sy; matrix->xz *= sz;
|
matrix->xx *= sx; matrix->xy *= sy; matrix->xz *= sz;
|
||||||
matrix->yx *= sx; matrix->yy *= sy; matrix->yz *= sz;
|
matrix->yx *= sx; matrix->yy *= sy; matrix->yz *= sz;
|
||||||
matrix->zx *= sx; matrix->zy *= sy; matrix->zz *= sz;
|
matrix->zx *= sx; matrix->zy *= sy; matrix->zz *= sz;
|
||||||
matrix->wx *= sx; matrix->wy *= sy; matrix->wz *= sz;
|
matrix->wx *= sx; matrix->wy *= sy; matrix->wz *= sz;
|
||||||
}
|
#else
|
||||||
|
_math_matrix_scale (matrix, sx, sy, sz);
|
||||||
#if 0
|
|
||||||
gboolean
|
|
||||||
cogl_matrix_invert (CoglMatrix *matrix)
|
|
||||||
{
|
|
||||||
/* TODO */
|
|
||||||
/* Note: It might be nice to also use the flag based tricks that mesa does
|
|
||||||
* to alow it to track the type of transformations a matrix represents
|
|
||||||
* so it can use various assumptions to optimise the inversion.
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
_COGL_MATRIX_DEBUG_PRINT (matrix);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cogl_matrix_frustum (CoglMatrix *matrix,
|
cogl_matrix_frustum (CoglMatrix *matrix,
|
||||||
@ -163,6 +192,7 @@ cogl_matrix_frustum (CoglMatrix *matrix,
|
|||||||
float z_near,
|
float z_near,
|
||||||
float z_far)
|
float z_far)
|
||||||
{
|
{
|
||||||
|
#ifndef USE_MESA_MATRIX_API
|
||||||
float x, y, a, b, c, d;
|
float x, y, a, b, c, d;
|
||||||
CoglMatrix frustum;
|
CoglMatrix frustum;
|
||||||
|
|
||||||
@ -194,6 +224,10 @@ cogl_matrix_frustum (CoglMatrix *matrix,
|
|||||||
frustum.ww = 0.0f;
|
frustum.ww = 0.0f;
|
||||||
|
|
||||||
cogl_matrix_multiply (matrix, matrix, &frustum);
|
cogl_matrix_multiply (matrix, matrix, &frustum);
|
||||||
|
#else
|
||||||
|
_math_matrix_frustum (matrix, left, right, bottom, top, z_near, z_far);
|
||||||
|
#endif
|
||||||
|
_COGL_MATRIX_DEBUG_PRINT (matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -212,6 +246,7 @@ cogl_matrix_perspective (CoglMatrix *matrix,
|
|||||||
ymax, /* top */
|
ymax, /* top */
|
||||||
z_near,
|
z_near,
|
||||||
z_far);
|
z_far);
|
||||||
|
_COGL_MATRIX_DEBUG_PRINT (matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -223,6 +258,7 @@ cogl_matrix_ortho (CoglMatrix *matrix,
|
|||||||
float near_val,
|
float near_val,
|
||||||
float far_val)
|
float far_val)
|
||||||
{
|
{
|
||||||
|
#ifndef USE_MESA_MATRIX_API
|
||||||
CoglMatrix ortho;
|
CoglMatrix ortho;
|
||||||
|
|
||||||
/* column 0 */
|
/* column 0 */
|
||||||
@ -250,12 +286,21 @@ cogl_matrix_ortho (CoglMatrix *matrix,
|
|||||||
ortho.ww = 1.0;
|
ortho.ww = 1.0;
|
||||||
|
|
||||||
cogl_matrix_multiply (matrix, matrix, &ortho);
|
cogl_matrix_multiply (matrix, matrix, &ortho);
|
||||||
|
#else
|
||||||
|
_math_matrix_ortho (matrix, left, right, bottom, top, near_val, far_val);
|
||||||
|
#endif
|
||||||
|
_COGL_MATRIX_DEBUG_PRINT (matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cogl_matrix_init_from_array (CoglMatrix *matrix, const float *array)
|
cogl_matrix_init_from_array (CoglMatrix *matrix, const float *array)
|
||||||
{
|
{
|
||||||
|
#ifndef USE_MESA_MATRIX_API
|
||||||
memcpy (matrix, array, sizeof (float) * 16);
|
memcpy (matrix, array, sizeof (float) * 16);
|
||||||
|
#else
|
||||||
|
_math_matrix_init_from_array (matrix, array);
|
||||||
|
#endif
|
||||||
|
_COGL_MATRIX_DEBUG_PRINT (matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
const float *
|
const float *
|
||||||
@ -264,6 +309,27 @@ cogl_matrix_get_array (const CoglMatrix *matrix)
|
|||||||
return (float *)matrix;
|
return (float *)matrix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
cogl_matrix_get_inverse (const CoglMatrix *matrix, CoglMatrix *inverse)
|
||||||
|
{
|
||||||
|
#ifndef USE_MESA_MATRIX_API
|
||||||
|
#warning "cogl_matrix_get_inverse not supported without Mesa matrix API"
|
||||||
|
cogl_matrix_init_identity (inverse);
|
||||||
|
return FALSE;
|
||||||
|
#else
|
||||||
|
if (_math_matrix_update_inverse ((CoglMatrix *)matrix))
|
||||||
|
{
|
||||||
|
cogl_matrix_init_from_array (inverse, matrix->inv);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cogl_matrix_init_identity (inverse);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cogl_matrix_transform_point (const CoglMatrix *matrix,
|
cogl_matrix_transform_point (const CoglMatrix *matrix,
|
||||||
float *x,
|
float *x,
|
||||||
|
@ -101,9 +101,9 @@ struct _CoglMatrix
|
|||||||
|
|
||||||
/* Note: we may want to extend this later with private flags
|
/* Note: we may want to extend this later with private flags
|
||||||
* and a cache of the inverse transform matrix. */
|
* and a cache of the inverse transform matrix. */
|
||||||
float _padding0[16];
|
float inv[16];
|
||||||
gulong _padding1;
|
gulong type;
|
||||||
gulong _padding2;
|
gulong flags;
|
||||||
gulong _padding3;
|
gulong _padding3;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -266,6 +266,27 @@ void cogl_matrix_init_from_array (CoglMatrix *matrix, const float *array);
|
|||||||
*/
|
*/
|
||||||
G_CONST_RETURN float *cogl_matrix_get_array (const CoglMatrix *matrix);
|
G_CONST_RETURN float *cogl_matrix_get_array (const CoglMatrix *matrix);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cogl_matrix_get_inverse:
|
||||||
|
* @matrix: A 4x4 transformation matrix
|
||||||
|
* @inverse: The destination for a 4x4 inverse transformation matrix
|
||||||
|
*
|
||||||
|
* This gets the inverse transform of a given matrix and uses it to initialize
|
||||||
|
* a new CoglMatrix.
|
||||||
|
*
|
||||||
|
* Note: that although the first parameter is annotated as const to indicate
|
||||||
|
* that the transform it represents isn't modified this function may
|
||||||
|
* technically save a copy of the inverse transform within the given CoglMatrix
|
||||||
|
* so that subsequent requests for the inverse transform may avoid costly
|
||||||
|
* inversion calculations.
|
||||||
|
*
|
||||||
|
* Returns TRUE if the inverse was successfully calculated or FALSE for
|
||||||
|
* degenerate transformations that can't be inverted (in this case the matrix
|
||||||
|
* will simply be initialized with the identity matrix)
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
cogl_matrix_get_inverse (const CoglMatrix *matrix, CoglMatrix *inverse);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cogl_matrix_transform_point:
|
* cogl_matrix_transform_point:
|
||||||
* @matrix: A 4x4 transformation matrix
|
* @matrix: A 4x4 transformation matrix
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "cogl-texture-private.h"
|
#include "cogl-texture-private.h"
|
||||||
#include "cogl-material-private.h"
|
#include "cogl-material-private.h"
|
||||||
#include "cogl-vertex-buffer-private.h"
|
#include "cogl-vertex-buffer-private.h"
|
||||||
|
#include "cogl-draw-buffer-private.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
@ -396,8 +397,6 @@ _cogl_rectangles_with_multitexture_coords (
|
|||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
|
|
||||||
cogl_clip_ensure ();
|
|
||||||
|
|
||||||
material = ctx->source_material;
|
material = ctx->source_material;
|
||||||
|
|
||||||
layers = cogl_material_get_layers (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;
|
options.layer0_override_texture = gl_handle;
|
||||||
|
|
||||||
_cogl_material_flush_gl_state (ctx->source_material, &options);
|
_cogl_material_flush_gl_state (ctx->source_material, &options);
|
||||||
_cogl_flush_matrix_stacks ();
|
|
||||||
|
|
||||||
GE (glDrawArrays (GL_TRIANGLE_FAN, 0, state->n_vertices));
|
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.flags |= COGL_MATERIAL_FLUSH_SKIP_GL_COLOR;
|
||||||
options.fallback_layers = fallback_layers;
|
options.fallback_layers = fallback_layers;
|
||||||
_cogl_material_flush_gl_state (ctx->source_material, &options);
|
_cogl_material_flush_gl_state (ctx->source_material, &options);
|
||||||
_cogl_flush_matrix_stacks ();
|
|
||||||
|
|
||||||
GE (glDrawArrays (GL_TRIANGLE_FAN, 0, n_vertices));
|
GE (glDrawArrays (GL_TRIANGLE_FAN, 0, n_vertices));
|
||||||
}
|
}
|
||||||
@ -866,7 +863,11 @@ cogl_polygon (CoglTextureVertex *vertices,
|
|||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
|
|
||||||
_cogl_journal_flush ();
|
_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;
|
material = ctx->source_material;
|
||||||
layers = cogl_material_get_layers (ctx->source_material);
|
layers = cogl_material_get_layers (ctx->source_material);
|
||||||
@ -978,6 +979,7 @@ cogl_polygon (CoglTextureVertex *vertices,
|
|||||||
}
|
}
|
||||||
|
|
||||||
cogl_enable (enable_flags);
|
cogl_enable (enable_flags);
|
||||||
|
_cogl_flush_face_winding ();
|
||||||
|
|
||||||
GE (glVertexPointer (3, GL_FLOAT, stride_bytes, v));
|
GE (glVertexPointer (3, GL_FLOAT, stride_bytes, v));
|
||||||
|
|
||||||
@ -1030,9 +1032,6 @@ cogl_path_fill_preserve (void)
|
|||||||
{
|
{
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
|
|
||||||
_cogl_journal_flush ();
|
|
||||||
cogl_clip_ensure ();
|
|
||||||
|
|
||||||
if (ctx->path_nodes->len == 0)
|
if (ctx->path_nodes->len == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -1055,10 +1054,7 @@ cogl_path_stroke_preserve (void)
|
|||||||
if (ctx->path_nodes->len == 0)
|
if (ctx->path_nodes->len == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_cogl_journal_flush ();
|
_cogl_path_stroke_nodes ();
|
||||||
cogl_clip_ensure ();
|
|
||||||
|
|
||||||
_cogl_path_stroke_nodes();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -907,7 +907,7 @@ _cogl_texture_2d_sliced_new_with_size (unsigned int width,
|
|||||||
|
|
||||||
/* Since no data, we need some internal format */
|
/* Since no data, we need some internal format */
|
||||||
if (internal_format == COGL_PIXEL_FORMAT_ANY)
|
if (internal_format == COGL_PIXEL_FORMAT_ANY)
|
||||||
return COGL_INVALID_HANDLE;
|
internal_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE;
|
||||||
|
|
||||||
/* Rowstride from width */
|
/* Rowstride from width */
|
||||||
bpp = _cogl_get_format_bpp (internal_format);
|
bpp = _cogl_get_format_bpp (internal_format);
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
#include "cogl-context.h"
|
#include "cogl-context.h"
|
||||||
#include "cogl-handle.h"
|
#include "cogl-handle.h"
|
||||||
#include "cogl-primitives.h"
|
#include "cogl-primitives.h"
|
||||||
|
#include "cogl-draw-buffer-private.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -667,7 +668,8 @@ _cogl_texture_draw_and_read (CoglTexture *tex,
|
|||||||
GLuint target_gl_type)
|
GLuint target_gl_type)
|
||||||
{
|
{
|
||||||
gint bpp;
|
gint bpp;
|
||||||
GLint viewport[4];
|
CoglHandle draw_buffer;
|
||||||
|
int viewport[4];
|
||||||
CoglBitmap alpha_bmp;
|
CoglBitmap alpha_bmp;
|
||||||
CoglHandle prev_source;
|
CoglHandle prev_source;
|
||||||
CoglMatrixStack *projection_stack;
|
CoglMatrixStack *projection_stack;
|
||||||
@ -677,8 +679,9 @@ _cogl_texture_draw_and_read (CoglTexture *tex,
|
|||||||
|
|
||||||
bpp = _cogl_get_format_bpp (COGL_PIXEL_FORMAT_RGBA_8888);
|
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 */
|
/* 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 ||
|
if (viewport[0] < 0 || viewport[1] < 0 ||
|
||||||
viewport[2] <= 0 || viewport[3] <= 0)
|
viewport[2] <= 0 || viewport[3] <= 0)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -688,16 +691,18 @@ _cogl_texture_draw_and_read (CoglTexture *tex,
|
|||||||
* works)
|
* works)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
_cogl_matrix_stack_push (ctx->projection_stack);
|
projection_stack = _cogl_draw_buffer_get_projection_stack (draw_buffer);
|
||||||
_cogl_matrix_stack_load_identity (ctx->projection_stack);
|
_cogl_matrix_stack_push (projection_stack);
|
||||||
_cogl_matrix_stack_ortho (ctx->projection_stack,
|
_cogl_matrix_stack_load_identity (projection_stack);
|
||||||
|
_cogl_matrix_stack_ortho (projection_stack,
|
||||||
0, (float)(viewport[2]),
|
0, (float)(viewport[2]),
|
||||||
0, (float)(viewport[3]),
|
0, (float)(viewport[3]),
|
||||||
(float)(0),
|
(float)(0),
|
||||||
(float)(100));
|
(float)(100));
|
||||||
|
|
||||||
_cogl_matrix_stack_push (ctx->modelview_stack);
|
modelview_stack = _cogl_draw_buffer_get_modelview_stack (draw_buffer);
|
||||||
_cogl_matrix_stack_load_identity (ctx->modelview_stack);
|
_cogl_matrix_stack_push (modelview_stack);
|
||||||
|
_cogl_matrix_stack_load_identity (modelview_stack);
|
||||||
|
|
||||||
/* Direct copy operation */
|
/* Direct copy operation */
|
||||||
|
|
||||||
|
@ -138,6 +138,7 @@
|
|||||||
#include "cogl-texture-private.h"
|
#include "cogl-texture-private.h"
|
||||||
#include "cogl-material-private.h"
|
#include "cogl-material-private.h"
|
||||||
#include "cogl-primitives.h"
|
#include "cogl-primitives.h"
|
||||||
|
#include "cogl-draw-buffer-private.h"
|
||||||
|
|
||||||
#define PAD_FOR_ALIGNMENT(VAR, TYPE_SIZE) \
|
#define PAD_FOR_ALIGNMENT(VAR, TYPE_SIZE) \
|
||||||
(VAR = TYPE_SIZE + ((VAR - 1) & ~(TYPE_SIZE - 1)))
|
(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;
|
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 =
|
options.flags =
|
||||||
COGL_MATERIAL_FLUSH_FALLBACK_MASK |
|
COGL_MATERIAL_FLUSH_FALLBACK_MASK |
|
||||||
COGL_MATERIAL_FLUSH_DISABLE_MASK;
|
COGL_MATERIAL_FLUSH_DISABLE_MASK;
|
||||||
@ -1677,6 +1683,7 @@ enable_state_for_drawing_buffer (CoglVertexBuffer *buffer)
|
|||||||
enable_flags |= COGL_ENABLE_BACKFACE_CULLING;
|
enable_flags |= COGL_ENABLE_BACKFACE_CULLING;
|
||||||
|
|
||||||
cogl_enable (enable_flags);
|
cogl_enable (enable_flags);
|
||||||
|
_cogl_flush_face_winding ();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1753,15 +1760,11 @@ cogl_vertex_buffer_draw (CoglHandle handle,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
_cogl_journal_flush ();
|
_cogl_journal_flush ();
|
||||||
cogl_clip_ensure ();
|
|
||||||
|
|
||||||
buffer = _cogl_vertex_buffer_pointer_from_handle (handle);
|
buffer = _cogl_vertex_buffer_pointer_from_handle (handle);
|
||||||
|
|
||||||
cogl_clip_ensure ();
|
|
||||||
_cogl_flush_matrix_stacks ();
|
|
||||||
enable_state_for_drawing_buffer (buffer);
|
enable_state_for_drawing_buffer (buffer);
|
||||||
|
|
||||||
/* FIXME: flush cogl cache */
|
|
||||||
GE (glDrawArrays (mode, first, count));
|
GE (glDrawArrays (mode, first, count));
|
||||||
|
|
||||||
disable_state_for_drawing_buffer (buffer);
|
disable_state_for_drawing_buffer (buffer);
|
||||||
@ -1885,7 +1888,6 @@ cogl_vertex_buffer_draw_elements (CoglHandle handle,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
_cogl_journal_flush ();
|
_cogl_journal_flush ();
|
||||||
cogl_clip_ensure ();
|
|
||||||
|
|
||||||
buffer = _cogl_vertex_buffer_pointer_from_handle (handle);
|
buffer = _cogl_vertex_buffer_pointer_from_handle (handle);
|
||||||
|
|
||||||
@ -1894,8 +1896,6 @@ cogl_vertex_buffer_draw_elements (CoglHandle handle,
|
|||||||
|
|
||||||
indices = _cogl_vertex_buffer_indices_pointer_from_handle (indices_handle);
|
indices = _cogl_vertex_buffer_indices_pointer_from_handle (indices_handle);
|
||||||
|
|
||||||
cogl_clip_ensure ();
|
|
||||||
_cogl_flush_matrix_stacks ();
|
|
||||||
enable_state_for_drawing_buffer (buffer);
|
enable_state_for_drawing_buffer (buffer);
|
||||||
|
|
||||||
byte_offset = indices_offset * get_indices_type_size (indices->type);
|
byte_offset = indices_offset * get_indices_type_size (indices->type);
|
||||||
@ -1905,7 +1905,6 @@ cogl_vertex_buffer_draw_elements (CoglHandle handle,
|
|||||||
GE (glBindBuffer (GL_ELEMENT_ARRAY_BUFFER,
|
GE (glBindBuffer (GL_ELEMENT_ARRAY_BUFFER,
|
||||||
GPOINTER_TO_UINT (indices->vbo_name)));
|
GPOINTER_TO_UINT (indices->vbo_name)));
|
||||||
|
|
||||||
/* FIXME: flush cogl cache */
|
|
||||||
GE (glDrawRangeElements (mode, min_index, max_index,
|
GE (glDrawRangeElements (mode, min_index, max_index,
|
||||||
count, indices->type, (void *)byte_offset));
|
count, indices->type, (void *)byte_offset));
|
||||||
|
|
||||||
|
@ -38,6 +38,8 @@
|
|||||||
#include "cogl-context.h"
|
#include "cogl-context.h"
|
||||||
#include "cogl-material-private.h"
|
#include "cogl-material-private.h"
|
||||||
#include "cogl-winsys.h"
|
#include "cogl-winsys.h"
|
||||||
|
#include "cogl-draw-buffer-private.h"
|
||||||
|
#include "cogl-matrix-private.h"
|
||||||
|
|
||||||
#if defined (HAVE_COGL_GLES2) || defined (HAVE_COGL_GLES)
|
#if defined (HAVE_COGL_GLES2) || defined (HAVE_COGL_GLES)
|
||||||
#include "cogl-gles2-wrapper.h"
|
#include "cogl-gles2-wrapper.h"
|
||||||
@ -116,7 +118,12 @@ cogl_clear (const CoglColor *color, gulong buffers)
|
|||||||
|
|
||||||
COGL_NOTE (DRAW, "Clear begin");
|
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)
|
if (buffers & COGL_BUFFER_BIT_COLOR)
|
||||||
{
|
{
|
||||||
@ -264,6 +271,9 @@ cogl_set_backface_culling_enabled (gboolean setting)
|
|||||||
{
|
{
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
|
|
||||||
|
if (ctx->enable_backface_culling == setting)
|
||||||
|
return;
|
||||||
|
|
||||||
/* Currently the journal can't track changes to backface culling state... */
|
/* Currently the journal can't track changes to backface culling state... */
|
||||||
_cogl_journal_flush ();
|
_cogl_journal_flush ();
|
||||||
|
|
||||||
@ -278,6 +288,38 @@ cogl_get_backface_culling_enabled (void)
|
|||||||
return ctx->enable_backface_culling;
|
return ctx->enable_backface_culling;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_flush_face_winding (void)
|
||||||
|
{
|
||||||
|
CoglFrontWinding winding;
|
||||||
|
|
||||||
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
|
|
||||||
|
/* The front face winding doesn't matter if we aren't performing any
|
||||||
|
* backface culling... */
|
||||||
|
if (!ctx->enable_backface_culling)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* NB: We use a clockwise face winding order when drawing offscreen because
|
||||||
|
* all offscreen rendering is done upside down resulting in reversed winding
|
||||||
|
* for all triangles.
|
||||||
|
*/
|
||||||
|
if (cogl_is_offscreen (_cogl_get_draw_buffer ()))
|
||||||
|
winding = COGL_FRONT_WINDING_CLOCKWISE;
|
||||||
|
else
|
||||||
|
winding = COGL_FRONT_WINDING_COUNTER_CLOCKWISE;
|
||||||
|
|
||||||
|
if (winding != ctx->flushed_front_winding)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (winding == COGL_FRONT_WINDING_CLOCKWISE)
|
||||||
|
GE (glFrontFace (GL_CW));
|
||||||
|
else
|
||||||
|
GE (glFrontFace (GL_CCW));
|
||||||
|
ctx->flushed_front_winding = winding;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cogl_set_source_color (const CoglColor *color)
|
cogl_set_source_color (const CoglColor *color)
|
||||||
{
|
{
|
||||||
@ -326,32 +368,38 @@ set_clip_plane (GLint plane_num,
|
|||||||
GLdouble plane[4];
|
GLdouble plane[4];
|
||||||
#endif
|
#endif
|
||||||
GLfloat angle;
|
GLfloat angle;
|
||||||
|
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);
|
||||||
CoglMatrix inverse_projection;
|
CoglMatrix inverse_projection;
|
||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
|
|
||||||
|
_cogl_matrix_stack_get_inverse (projection_stack, &inverse_projection);
|
||||||
|
|
||||||
/* Calculate the angle between the axes and the line crossing the
|
/* Calculate the angle between the axes and the line crossing the
|
||||||
two points */
|
two points */
|
||||||
angle = atan2f (vertex_b[1] - vertex_a[1],
|
angle = atan2f (vertex_b[1] - vertex_a[1],
|
||||||
vertex_b[0] - vertex_a[0]) * (180.0/G_PI);
|
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
|
/* Load the inverse of the projection matrix so we can specify the plane
|
||||||
coordinates */
|
* in screen coordinates */
|
||||||
_cogl_matrix_stack_load_identity (ctx->modelview_stack);
|
_cogl_matrix_stack_set (modelview_stack, &inverse_projection);
|
||||||
cogl_matrix_init_from_array (&inverse_projection,
|
|
||||||
ctx->inverse_projection);
|
|
||||||
_cogl_matrix_stack_multiply (ctx->modelview_stack, &inverse_projection);
|
|
||||||
/* Rotate about point a */
|
/* 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]);
|
vertex_a[0], vertex_a[1], vertex_a[2]);
|
||||||
/* Rotate the plane by the calculated angle so that it will connect
|
/* Rotate the plane by the calculated angle so that it will connect
|
||||||
the two points */
|
the two points */
|
||||||
_cogl_matrix_stack_rotate (ctx->modelview_stack, angle, 0.0f, 0.0f, 1.0f);
|
_cogl_matrix_stack_rotate (modelview_stack, angle, 0.0f, 0.0f, 1.0f);
|
||||||
_cogl_matrix_stack_translate (ctx->modelview_stack,
|
_cogl_matrix_stack_translate (modelview_stack,
|
||||||
-vertex_a[0], -vertex_a[1], -vertex_a[2]);
|
-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[0] = 0;
|
||||||
plane[1] = -1.0;
|
plane[1] = -1.0;
|
||||||
@ -363,7 +411,7 @@ set_clip_plane (GLint plane_num,
|
|||||||
GE( glClipPlane (plane_num, plane) );
|
GE( glClipPlane (plane_num, plane) );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_cogl_matrix_stack_pop (ctx->modelview_stack);
|
_cogl_matrix_stack_pop (modelview_stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -372,7 +420,12 @@ _cogl_set_clip_planes (float x_offset,
|
|||||||
float width,
|
float width,
|
||||||
float height)
|
float height)
|
||||||
{
|
{
|
||||||
|
CoglHandle draw_buffer = _cogl_get_draw_buffer ();
|
||||||
|
CoglMatrixStack *modelview_stack =
|
||||||
|
_cogl_draw_buffer_get_modelview_stack (draw_buffer);
|
||||||
CoglMatrix modelview_matrix;
|
CoglMatrix modelview_matrix;
|
||||||
|
CoglMatrixStack *projection_stack =
|
||||||
|
_cogl_draw_buffer_get_projection_stack (draw_buffer);
|
||||||
CoglMatrix projection_matrix;
|
CoglMatrix projection_matrix;
|
||||||
|
|
||||||
float vertex_tl[4] = { x_offset, y_offset, 0, 1.0 };
|
float vertex_tl[4] = { x_offset, y_offset, 0, 1.0 };
|
||||||
@ -381,10 +434,8 @@ _cogl_set_clip_planes (float x_offset,
|
|||||||
float vertex_br[4] = { x_offset + width, y_offset + height,
|
float vertex_br[4] = { x_offset + width, y_offset + height,
|
||||||
0, 1.0 };
|
0, 1.0 };
|
||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
_cogl_matrix_stack_get (projection_stack, &projection_matrix);
|
||||||
|
_cogl_matrix_stack_get (modelview_stack, &modelview_matrix);
|
||||||
_cogl_matrix_stack_get (ctx->projection_stack, &projection_matrix);
|
|
||||||
_cogl_matrix_stack_get (ctx->modelview_stack, &modelview_matrix);
|
|
||||||
|
|
||||||
project_vertex (&modelview_matrix, &projection_matrix, vertex_tl);
|
project_vertex (&modelview_matrix, &projection_matrix, vertex_tl);
|
||||||
project_vertex (&modelview_matrix, &projection_matrix, vertex_tr);
|
project_vertex (&modelview_matrix, &projection_matrix, vertex_tr);
|
||||||
@ -422,6 +473,7 @@ _cogl_add_stencil_clip (float x_offset,
|
|||||||
gboolean first)
|
gboolean first)
|
||||||
{
|
{
|
||||||
CoglHandle current_source;
|
CoglHandle current_source;
|
||||||
|
CoglHandle draw_buffer = _cogl_get_draw_buffer ();
|
||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
|
|
||||||
@ -429,6 +481,8 @@ _cogl_add_stencil_clip (float x_offset,
|
|||||||
* batched geometry before we start... */
|
* batched geometry before we start... */
|
||||||
_cogl_journal_flush ();
|
_cogl_journal_flush ();
|
||||||
|
|
||||||
|
_cogl_draw_buffer_flush_state (draw_buffer, 0);
|
||||||
|
|
||||||
/* temporarily swap in our special stenciling material */
|
/* temporarily swap in our special stenciling material */
|
||||||
current_source = cogl_handle_ref (ctx->source_material);
|
current_source = cogl_handle_ref (ctx->source_material);
|
||||||
cogl_set_source (ctx->stencil_material);
|
cogl_set_source (ctx->stencil_material);
|
||||||
@ -450,6 +504,11 @@ _cogl_add_stencil_clip (float x_offset,
|
|||||||
}
|
}
|
||||||
else
|
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
|
/* Add one to every pixel of the stencil buffer in the
|
||||||
rectangle */
|
rectangle */
|
||||||
GE( glStencilFunc (GL_NEVER, 0x1, 0x3) );
|
GE( glStencilFunc (GL_NEVER, 0x1, 0x3) );
|
||||||
@ -466,16 +525,16 @@ _cogl_add_stencil_clip (float x_offset,
|
|||||||
rectangle are set will be valid */
|
rectangle are set will be valid */
|
||||||
GE( glStencilOp (GL_DECR, GL_DECR, GL_DECR) );
|
GE( glStencilOp (GL_DECR, GL_DECR, GL_DECR) );
|
||||||
|
|
||||||
_cogl_matrix_stack_push (ctx->projection_stack);
|
_cogl_matrix_stack_push (projection_stack);
|
||||||
_cogl_matrix_stack_load_identity (ctx->projection_stack);
|
_cogl_matrix_stack_load_identity (projection_stack);
|
||||||
|
|
||||||
_cogl_matrix_stack_push (ctx->modelview_stack);
|
_cogl_matrix_stack_push (modelview_stack);
|
||||||
_cogl_matrix_stack_load_identity (ctx->modelview_stack);
|
_cogl_matrix_stack_load_identity (modelview_stack);
|
||||||
|
|
||||||
cogl_rectangle (-1.0, -1.0, 1.0, 1.0);
|
cogl_rectangle (-1.0, -1.0, 1.0, 1.0);
|
||||||
|
|
||||||
_cogl_matrix_stack_pop (ctx->modelview_stack);
|
_cogl_matrix_stack_pop (modelview_stack);
|
||||||
_cogl_matrix_stack_pop (ctx->projection_stack);
|
_cogl_matrix_stack_pop (projection_stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make sure our rectangles hit the stencil buffer before we restore
|
/* make sure our rectangles hit the stencil buffer before we restore
|
||||||
@ -515,19 +574,32 @@ _cogl_disable_clip_planes (void)
|
|||||||
GE( glDisable (GL_CLIP_PLANE0) );
|
GE( glDisable (GL_CLIP_PLANE0) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX: This should be deprecated and Cogl should be left to manage
|
void
|
||||||
* the glViewport automatically when switching draw buffers. */
|
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
|
void
|
||||||
cogl_viewport (guint width,
|
cogl_viewport (guint width,
|
||||||
guint height)
|
guint height)
|
||||||
{
|
{
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
cogl_set_viewport (0, 0, width, height);
|
||||||
|
|
||||||
COGL_NOTE (MISC, "glViewport(0, 0, %u, %u)", width, height);
|
|
||||||
GE( glViewport (0, 0, width, height) );
|
|
||||||
|
|
||||||
ctx->viewport_width = width;
|
|
||||||
ctx->viewport_height = height;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -540,10 +612,11 @@ _cogl_setup_viewport (guint width,
|
|||||||
{
|
{
|
||||||
float z_camera;
|
float z_camera;
|
||||||
CoglMatrix projection_matrix;
|
CoglMatrix projection_matrix;
|
||||||
|
CoglMatrixStack *modelview_stack;
|
||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
|
|
||||||
cogl_viewport (width, height);
|
cogl_set_viewport (0, 0, width, height);
|
||||||
|
|
||||||
/* For Ortho projection.
|
/* For Ortho projection.
|
||||||
* _cogl_matrix_stack_ortho (projection_stack, 0, width, 0, height, -1, 1);
|
* _cogl_matrix_stack_ortho (projection_stack, 0, width, 0, height, -1, 1);
|
||||||
@ -593,11 +666,13 @@ _cogl_setup_viewport (guint width,
|
|||||||
cogl_get_projection_matrix (&projection_matrix);
|
cogl_get_projection_matrix (&projection_matrix);
|
||||||
z_camera = 0.5 * projection_matrix.xx;
|
z_camera = 0.5 * projection_matrix.xx;
|
||||||
|
|
||||||
_cogl_matrix_stack_load_identity (ctx->modelview_stack);
|
modelview_stack =
|
||||||
_cogl_matrix_stack_translate (ctx->modelview_stack, -0.5f, -0.5f, -z_camera);
|
_cogl_draw_buffer_get_modelview_stack (_cogl_get_draw_buffer ());
|
||||||
_cogl_matrix_stack_scale (ctx->modelview_stack,
|
_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);
|
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);
|
0.0f, -1.0 * height, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -606,9 +681,6 @@ cogl_get_features (void)
|
|||||||
{
|
{
|
||||||
_COGL_GET_CONTEXT (ctx, 0);
|
_COGL_GET_CONTEXT (ctx, 0);
|
||||||
|
|
||||||
if (!ctx->features_cached)
|
|
||||||
_cogl_features_init ();
|
|
||||||
|
|
||||||
if (cogl_debug_flags & COGL_DEBUG_DISABLE_VBOS)
|
if (cogl_debug_flags & COGL_DEBUG_DISABLE_VBOS)
|
||||||
ctx->feature_flags &= ~COGL_FEATURE_VBOS;
|
ctx->feature_flags &= ~COGL_FEATURE_VBOS;
|
||||||
|
|
||||||
@ -626,18 +698,24 @@ cogl_features_available (CoglFeatureFlags features)
|
|||||||
return (ctx->feature_flags & features) == features;
|
return (ctx->feature_flags & features) == features;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX: This function should be deprecated, and replaced with a
|
/* XXX: This function should either be replaced with one returning
|
||||||
* cogl_draw_buffer_get_size() API instead. We don't support offset
|
* integers, or removed/deprecated and make the
|
||||||
* viewports, and you can't have floating point viewport sizes. */
|
* _cogl_draw_buffer_get_viewport* functions public.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
cogl_get_viewport (float v[4])
|
cogl_get_viewport (float v[4])
|
||||||
{
|
{
|
||||||
|
CoglHandle draw_buffer;
|
||||||
|
int viewport[4];
|
||||||
|
int i;
|
||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
|
|
||||||
v[0] = 0;
|
draw_buffer = _cogl_get_draw_buffer ();
|
||||||
v[1] = 0;
|
_cogl_draw_buffer_get_viewport4fv (draw_buffer, viewport);
|
||||||
v[2] = ctx->viewport_width;
|
|
||||||
v[3] = ctx->viewport_height;
|
for (i = 0; i < 4; i++)
|
||||||
|
v[i] = viewport[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -733,7 +811,7 @@ cogl_disable_fog (void)
|
|||||||
void
|
void
|
||||||
cogl_flush_gl_state (int flags)
|
cogl_flush_gl_state (int flags)
|
||||||
{
|
{
|
||||||
_cogl_flush_matrix_stacks ();
|
_cogl_draw_buffer_flush_state (_cogl_get_draw_buffer (), 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -752,37 +830,52 @@ cogl_read_pixels (int x,
|
|||||||
CoglPixelFormat format,
|
CoglPixelFormat format,
|
||||||
guint8 *pixels)
|
guint8 *pixels)
|
||||||
{
|
{
|
||||||
GLint viewport[4];
|
CoglHandle draw_buffer;
|
||||||
GLint viewport_height;
|
int draw_buffer_height;
|
||||||
int rowstride = width * 4;
|
int rowstride = width * 4;
|
||||||
guint8 *temprow;
|
guint8 *temprow;
|
||||||
|
|
||||||
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
|
|
||||||
g_return_if_fail (format == COGL_PIXEL_FORMAT_RGBA_8888);
|
g_return_if_fail (format == COGL_PIXEL_FORMAT_RGBA_8888);
|
||||||
g_return_if_fail (source == COGL_READ_PIXELS_COLOR_BUFFER);
|
g_return_if_fail (source == COGL_READ_PIXELS_COLOR_BUFFER);
|
||||||
|
|
||||||
temprow = g_alloca (rowstride * sizeof (guint8));
|
temprow = g_alloca (rowstride * sizeof (guint8));
|
||||||
|
|
||||||
glGetIntegerv (GL_VIEWPORT, viewport);
|
draw_buffer = _cogl_get_draw_buffer ();
|
||||||
viewport_height = viewport[3];
|
|
||||||
|
_cogl_draw_buffer_flush_state (draw_buffer, 0);
|
||||||
|
|
||||||
|
draw_buffer_height = _cogl_draw_buffer_get_height (draw_buffer);
|
||||||
|
|
||||||
/* The y co-ordinate should be given in OpenGL's coordinate system
|
/* The y co-ordinate should be given in OpenGL's coordinate system
|
||||||
so 0 is the bottom row */
|
* so 0 is the bottom row
|
||||||
y = viewport_height - y - height;
|
*
|
||||||
|
* NB: all offscreen rendering is done upside down so no conversion
|
||||||
/* Setup the pixel store parameters that may have been changed by
|
* is necissary in this case.
|
||||||
Cogl */
|
*/
|
||||||
glPixelStorei (GL_PACK_ALIGNMENT, 4);
|
if (!cogl_is_offscreen (draw_buffer))
|
||||||
#ifdef HAVE_COGL_GL
|
y = draw_buffer_height - y - height;
|
||||||
glPixelStorei (GL_PACK_ROW_LENGTH, 0);
|
|
||||||
glPixelStorei (GL_PACK_SKIP_PIXELS, 0);
|
|
||||||
glPixelStorei (GL_PACK_SKIP_ROWS, 0);
|
|
||||||
#endif /* HAVE_COGL_GL */
|
|
||||||
|
|
||||||
/* make sure any batched primitives get emitted to the GL driver before
|
/* make sure any batched primitives get emitted to the GL driver before
|
||||||
* issuing our read pixels... */
|
* issuing our read pixels... */
|
||||||
cogl_flush ();
|
cogl_flush ();
|
||||||
|
|
||||||
glReadPixels (x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
/* Setup the pixel store parameters that may have been changed by
|
||||||
|
Cogl */
|
||||||
|
GE (glPixelStorei (GL_PACK_ALIGNMENT, 1));
|
||||||
|
#ifdef HAVE_COGL_GL
|
||||||
|
GE (glPixelStorei (GL_PACK_ROW_LENGTH, 0));
|
||||||
|
GE (glPixelStorei (GL_PACK_SKIP_PIXELS, 0));
|
||||||
|
GE (glPixelStorei (GL_PACK_SKIP_ROWS, 0));
|
||||||
|
#endif /* HAVE_COGL_GL */
|
||||||
|
|
||||||
|
GE (glReadPixels (x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
|
||||||
|
|
||||||
|
/* NB: All offscreen rendering is done upside down so there is no need
|
||||||
|
* to flip in this case... */
|
||||||
|
if (cogl_is_offscreen (draw_buffer))
|
||||||
|
return;
|
||||||
|
|
||||||
/* TODO: consider using the GL_MESA_pack_invert extension in the future
|
/* TODO: consider using the GL_MESA_pack_invert extension in the future
|
||||||
* to avoid this flip... */
|
* to avoid this flip... */
|
||||||
@ -825,12 +918,13 @@ cogl_begin_gl (void)
|
|||||||
/* Flush all batched primitives */
|
/* Flush all batched primitives */
|
||||||
cogl_flush ();
|
cogl_flush ();
|
||||||
|
|
||||||
/* Flush our clipping state to GL */
|
/* Flush framebuffer state, including clip state, modelview and
|
||||||
cogl_clip_ensure ();
|
* projection matrix state
|
||||||
|
*
|
||||||
/* Flush any client side matrix state */
|
* NB: _cogl_draw_buffer_flush_state may disrupt various state (such
|
||||||
_cogl_flush_matrix_stacks ();
|
* 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 */
|
/* Setup the state for the current material */
|
||||||
|
|
||||||
@ -852,6 +946,7 @@ cogl_begin_gl (void)
|
|||||||
enable_flags |= COGL_ENABLE_BACKFACE_CULLING;
|
enable_flags |= COGL_ENABLE_BACKFACE_CULLING;
|
||||||
|
|
||||||
cogl_enable (enable_flags);
|
cogl_enable (enable_flags);
|
||||||
|
_cogl_flush_face_winding ();
|
||||||
|
|
||||||
/* Disable all client texture coordinate arrays */
|
/* Disable all client texture coordinate arrays */
|
||||||
for (i = 0; i < ctx->n_texcoord_arrays_enabled; i++)
|
for (i = 0; i < ctx->n_texcoord_arrays_enabled; i++)
|
||||||
@ -940,36 +1035,41 @@ _cogl_destroy_texture_units (void)
|
|||||||
void
|
void
|
||||||
cogl_push_matrix (void)
|
cogl_push_matrix (void)
|
||||||
{
|
{
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
CoglMatrixStack *modelview_stack =
|
||||||
_cogl_matrix_stack_push (ctx->modelview_stack);
|
_cogl_draw_buffer_get_modelview_stack (_cogl_get_draw_buffer ());
|
||||||
|
_cogl_matrix_stack_push (modelview_stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cogl_pop_matrix (void)
|
cogl_pop_matrix (void)
|
||||||
{
|
{
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
CoglMatrixStack *modelview_stack =
|
||||||
_cogl_matrix_stack_pop (ctx->modelview_stack);
|
_cogl_draw_buffer_get_modelview_stack (_cogl_get_draw_buffer ());
|
||||||
|
_cogl_matrix_stack_pop (modelview_stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cogl_scale (float x, float y, float z)
|
cogl_scale (float x, float y, float z)
|
||||||
{
|
{
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
CoglMatrixStack *modelview_stack =
|
||||||
_cogl_matrix_stack_scale (ctx->modelview_stack, x, y, z);
|
_cogl_draw_buffer_get_modelview_stack (_cogl_get_draw_buffer ());
|
||||||
|
_cogl_matrix_stack_scale (modelview_stack, x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cogl_translate (float x, float y, float z)
|
cogl_translate (float x, float y, float z)
|
||||||
{
|
{
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
CoglMatrixStack *modelview_stack =
|
||||||
_cogl_matrix_stack_translate (ctx->modelview_stack, x, y, z);
|
_cogl_draw_buffer_get_modelview_stack (_cogl_get_draw_buffer ());
|
||||||
|
_cogl_matrix_stack_translate (modelview_stack, x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cogl_rotate (float angle, float x, float y, float z)
|
cogl_rotate (float angle, float x, float y, float z)
|
||||||
{
|
{
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
CoglMatrixStack *modelview_stack =
|
||||||
_cogl_matrix_stack_rotate (ctx->modelview_stack, angle, x, y, z);
|
_cogl_draw_buffer_get_modelview_stack (_cogl_get_draw_buffer ());
|
||||||
|
_cogl_matrix_stack_rotate (modelview_stack, angle, x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -996,35 +1096,20 @@ cogl_frustum (float left,
|
|||||||
float z_near,
|
float z_near,
|
||||||
float z_far)
|
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_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,
|
left,
|
||||||
right,
|
right,
|
||||||
bottom,
|
bottom,
|
||||||
top,
|
top,
|
||||||
z_near,
|
z_near,
|
||||||
z_far);
|
z_far);
|
||||||
|
|
||||||
/* Calculate and store the inverse of the matrix */
|
|
||||||
memset (ctx->inverse_projection, 0, sizeof (float) * 16);
|
|
||||||
|
|
||||||
c = - (z_far + z_near) / (z_far - z_near);
|
|
||||||
d = - (2 * (z_far * z_near)) / (z_far - z_near);
|
|
||||||
|
|
||||||
#define M(row,col) ctx->inverse_projection[col*4+row]
|
|
||||||
M(0,0) = (right - left) / (2 * z_near);
|
|
||||||
M(0,3) = (right + left) / (2 * z_near);
|
|
||||||
M(1,1) = (top - bottom) / (2 * z_near);
|
|
||||||
M(1,3) = (top + bottom) / (2 * z_near);
|
|
||||||
M(2,3) = -1.0;
|
|
||||||
M(3,2) = 1.0 / d;
|
|
||||||
M(3,3) = c / d;
|
|
||||||
#undef M
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1036,65 +1121,61 @@ cogl_ortho (float left,
|
|||||||
float z_far)
|
float z_far)
|
||||||
{
|
{
|
||||||
CoglMatrix ortho;
|
CoglMatrix ortho;
|
||||||
|
CoglMatrixStack *projection_stack =
|
||||||
|
_cogl_draw_buffer_get_projection_stack (_cogl_get_draw_buffer ());
|
||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
|
|
||||||
cogl_matrix_init_identity (&ortho);
|
cogl_matrix_init_identity (&ortho);
|
||||||
cogl_matrix_ortho (&ortho, left, right, bottom, top, z_near, z_far);
|
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);
|
|
||||||
|
|
||||||
#define M(row,col) ctx->inverse_projection[col*4+row]
|
|
||||||
M(0,0) = 1.0 / ortho.xx;
|
|
||||||
M(0,3) = -ortho.xw;
|
|
||||||
M(1,1) = 1.0 / ortho.yy;
|
|
||||||
M(1,3) = -ortho.yw;
|
|
||||||
M(2,2) = 1.0 / ortho.zz;
|
|
||||||
M(2,3) = -ortho.zw;
|
|
||||||
M(3,3) = 1.0;
|
|
||||||
#undef M
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cogl_get_modelview_matrix (CoglMatrix *matrix)
|
cogl_get_modelview_matrix (CoglMatrix *matrix)
|
||||||
{
|
{
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
CoglMatrixStack *modelview_stack =
|
||||||
_cogl_matrix_stack_get (ctx->modelview_stack, matrix);
|
_cogl_draw_buffer_get_modelview_stack (_cogl_get_draw_buffer ());
|
||||||
|
_cogl_matrix_stack_get (modelview_stack, matrix);
|
||||||
|
_COGL_MATRIX_DEBUG_PRINT (matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cogl_set_modelview_matrix (CoglMatrix *matrix)
|
cogl_set_modelview_matrix (CoglMatrix *matrix)
|
||||||
{
|
{
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
CoglMatrixStack *modelview_stack =
|
||||||
_cogl_matrix_stack_set (ctx->modelview_stack, matrix);
|
_cogl_draw_buffer_get_modelview_stack (_cogl_get_draw_buffer ());
|
||||||
|
_cogl_matrix_stack_set (modelview_stack, matrix);
|
||||||
|
_COGL_MATRIX_DEBUG_PRINT (matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cogl_get_projection_matrix (CoglMatrix *matrix)
|
cogl_get_projection_matrix (CoglMatrix *matrix)
|
||||||
{
|
{
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
CoglMatrixStack *projection_stack =
|
||||||
_cogl_matrix_stack_get (ctx->projection_stack, matrix);
|
_cogl_draw_buffer_get_projection_stack (_cogl_get_draw_buffer ());
|
||||||
|
_cogl_matrix_stack_get (projection_stack, matrix);
|
||||||
|
_COGL_MATRIX_DEBUG_PRINT (matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cogl_set_projection_matrix (CoglMatrix *matrix)
|
cogl_set_projection_matrix (CoglMatrix *matrix)
|
||||||
{
|
{
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
CoglMatrixStack *projection_stack =
|
||||||
_cogl_matrix_stack_set (ctx->projection_stack, matrix);
|
_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
|
/* FIXME: Update the inverse projection matrix!! Presumably use
|
||||||
* of clip planes must currently be broken if this API is used. */
|
* of clip planes must currently be broken if this API is used. */
|
||||||
|
_COGL_MATRIX_DEBUG_PRINT (matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
CoglClipStackState *
|
||||||
_cogl_flush_matrix_stacks (void)
|
_cogl_get_clip_state (void)
|
||||||
{
|
{
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
CoglHandle draw_buffer;
|
||||||
_cogl_matrix_stack_flush_to_gl (ctx->projection_stack,
|
|
||||||
COGL_MATRIX_PROJECTION);
|
draw_buffer = _cogl_get_draw_buffer ();
|
||||||
_cogl_matrix_stack_flush_to_gl (ctx->modelview_stack,
|
return _cogl_draw_buffer_get_clip_state (draw_buffer);
|
||||||
COGL_MATRIX_MODELVIEW);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,6 +219,8 @@ void _cogl_setup_viewport (guint width,
|
|||||||
float z_near,
|
float z_near,
|
||||||
float z_far);
|
float z_far);
|
||||||
|
|
||||||
|
#ifndef COGL_DISABLE_DEPRECATED
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cogl_viewport:
|
* cogl_viewport:
|
||||||
* @width: Width of the viewport
|
* @width: Width of the viewport
|
||||||
@ -229,7 +231,25 @@ void _cogl_setup_viewport (guint width,
|
|||||||
* Since: 0.8.2
|
* Since: 0.8.2
|
||||||
*/
|
*/
|
||||||
void cogl_viewport (guint width,
|
void cogl_viewport (guint width,
|
||||||
guint height);
|
guint height) G_GNUC_DEPRECATED;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cogl_set_viewport:
|
||||||
|
* @x: viewport X offset
|
||||||
|
* @x: viewport Y offset
|
||||||
|
* @width: Width of the viewport
|
||||||
|
* @height: Height of the viewport
|
||||||
|
*
|
||||||
|
* Replace the current viewport with the given values.
|
||||||
|
*
|
||||||
|
* Since: 1.2
|
||||||
|
*/
|
||||||
|
void cogl_set_viewport (int x,
|
||||||
|
int y,
|
||||||
|
int width,
|
||||||
|
int height);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cogl_push_matrix:
|
* cogl_push_matrix:
|
||||||
@ -867,6 +887,10 @@ void cogl_flush_gl_state (int flags);
|
|||||||
|
|
||||||
/* private */
|
/* private */
|
||||||
void _cogl_set_indirect_context (gboolean indirect);
|
void _cogl_set_indirect_context (gboolean indirect);
|
||||||
|
void _cogl_set_viewport (int x, int y, int width, int height);
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_onscreen_clutter_backend_set_size (int width, int height);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
@ -25,8 +25,6 @@ libclutter_cogl_driver_la_SOURCES = \
|
|||||||
cogl.c \
|
cogl.c \
|
||||||
cogl-primitives.c \
|
cogl-primitives.c \
|
||||||
cogl-texture-driver.c \
|
cogl-texture-driver.c \
|
||||||
cogl-fbo.h \
|
|
||||||
cogl-fbo.c \
|
|
||||||
cogl-shader-private.h \
|
cogl-shader-private.h \
|
||||||
cogl-shader.c \
|
cogl-shader.c \
|
||||||
cogl-program.h \
|
cogl-program.h \
|
||||||
|
@ -30,15 +30,16 @@
|
|||||||
void
|
void
|
||||||
_cogl_create_context_driver (CoglContext *_context)
|
_cogl_create_context_driver (CoglContext *_context)
|
||||||
{
|
{
|
||||||
_context->drv.pf_glGenRenderbuffersEXT = NULL;
|
_context->drv.pf_glGenRenderbuffers = NULL;
|
||||||
_context->drv.pf_glBindRenderbufferEXT = NULL;
|
_context->drv.pf_glBindRenderbuffer = NULL;
|
||||||
_context->drv.pf_glRenderbufferStorageEXT = NULL;
|
_context->drv.pf_glRenderbufferStorage = NULL;
|
||||||
_context->drv.pf_glGenFramebuffersEXT = NULL;
|
_context->drv.pf_glGenFramebuffers = NULL;
|
||||||
_context->drv.pf_glBindFramebufferEXT = NULL;
|
_context->drv.pf_glBindFramebuffer = NULL;
|
||||||
_context->drv.pf_glFramebufferTexture2DEXT = NULL;
|
_context->drv.pf_glFramebufferTexture2D = NULL;
|
||||||
_context->drv.pf_glFramebufferRenderbufferEXT = NULL;
|
_context->drv.pf_glFramebufferRenderbuffer = NULL;
|
||||||
_context->drv.pf_glCheckFramebufferStatusEXT = NULL;
|
_context->drv.pf_glCheckFramebufferStatus = NULL;
|
||||||
_context->drv.pf_glDeleteFramebuffersEXT = NULL;
|
_context->drv.pf_glDeleteFramebuffers = NULL;
|
||||||
|
|
||||||
_context->drv.pf_glBlitFramebufferEXT = NULL;
|
_context->drv.pf_glBlitFramebufferEXT = NULL;
|
||||||
_context->drv.pf_glRenderbufferStorageMultisampleEXT = NULL;
|
_context->drv.pf_glRenderbufferStorageMultisampleEXT = NULL;
|
||||||
|
|
||||||
|
@ -29,19 +29,20 @@
|
|||||||
typedef struct _CoglContextDriver
|
typedef struct _CoglContextDriver
|
||||||
{
|
{
|
||||||
/* Relying on glext.h to define these */
|
/* Relying on glext.h to define these */
|
||||||
COGL_PFNGLGENRENDERBUFFERSEXTPROC pf_glGenRenderbuffersEXT;
|
COGL_PFNGLGENRENDERBUFFERSPROC pf_glGenRenderbuffers;
|
||||||
COGL_PFNGLDELETERENDERBUFFERSEXTPROC pf_glDeleteRenderbuffersEXT;
|
COGL_PFNGLDELETERENDERBUFFERSPROC pf_glDeleteRenderbuffers;
|
||||||
COGL_PFNGLBINDRENDERBUFFEREXTPROC pf_glBindRenderbufferEXT;
|
COGL_PFNGLBINDRENDERBUFFERPROC pf_glBindRenderbuffer;
|
||||||
COGL_PFNGLRENDERBUFFERSTORAGEEXTPROC pf_glRenderbufferStorageEXT;
|
COGL_PFNGLRENDERBUFFERSTORAGEPROC pf_glRenderbufferStorage;
|
||||||
COGL_PFNGLGENFRAMEBUFFERSEXTPROC pf_glGenFramebuffersEXT;
|
COGL_PFNGLGENFRAMEBUFFERSPROC pf_glGenFramebuffers;
|
||||||
COGL_PFNGLBINDFRAMEBUFFEREXTPROC pf_glBindFramebufferEXT;
|
COGL_PFNGLBINDFRAMEBUFFERPROC pf_glBindFramebuffer;
|
||||||
COGL_PFNGLFRAMEBUFFERTEXTURE2DEXTPROC pf_glFramebufferTexture2DEXT;
|
COGL_PFNGLFRAMEBUFFERTEXTURE2DPROC pf_glFramebufferTexture2D;
|
||||||
COGL_PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC pf_glFramebufferRenderbufferEXT;
|
COGL_PFNGLFRAMEBUFFERRENDERBUFFERPROC pf_glFramebufferRenderbuffer;
|
||||||
COGL_PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC pf_glCheckFramebufferStatusEXT;
|
COGL_PFNGLCHECKFRAMEBUFFERSTATUSPROC pf_glCheckFramebufferStatus;
|
||||||
COGL_PFNGLDELETEFRAMEBUFFERSEXTPROC pf_glDeleteFramebuffersEXT;
|
COGL_PFNGLDELETEFRAMEBUFFERSPROC pf_glDeleteFramebuffers;
|
||||||
|
COGL_PFNGLGENERATEMIPMAPPROC pf_glGenerateMipmap;
|
||||||
|
|
||||||
COGL_PFNGLBLITFRAMEBUFFEREXTPROC pf_glBlitFramebufferEXT;
|
COGL_PFNGLBLITFRAMEBUFFEREXTPROC pf_glBlitFramebufferEXT;
|
||||||
COGL_PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC pf_glRenderbufferStorageMultisampleEXT;
|
COGL_PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC pf_glRenderbufferStorageMultisampleEXT;
|
||||||
COGL_PFNGLGENERATEMIPMAPEXTPROC pf_glGenerateMipmapEXT;
|
|
||||||
|
|
||||||
COGL_PFNGLCREATEPROGRAMOBJECTARBPROC pf_glCreateProgramObjectARB;
|
COGL_PFNGLCREATEPROGRAMOBJECTARBPROC pf_glCreateProgramObjectARB;
|
||||||
COGL_PFNGLCREATESHADEROBJECTARBPROC pf_glCreateShaderObjectARB;
|
COGL_PFNGLCREATESHADEROBJECTARBPROC pf_glCreateShaderObjectARB;
|
||||||
|
@ -698,34 +698,34 @@ G_BEGIN_DECLS
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef void
|
typedef void
|
||||||
(APIENTRYP COGL_PFNGLGENRENDERBUFFERSEXTPROC)
|
(APIENTRYP COGL_PFNGLGENRENDERBUFFERSPROC)
|
||||||
(GLsizei n,
|
(GLsizei n,
|
||||||
GLuint *renderbuffers);
|
GLuint *renderbuffers);
|
||||||
|
|
||||||
typedef void
|
typedef void
|
||||||
(APIENTRYP COGL_PFNGLBINDRENDERBUFFEREXTPROC)
|
(APIENTRYP COGL_PFNGLBINDRENDERBUFFERPROC)
|
||||||
(GLenum target,
|
(GLenum target,
|
||||||
GLuint renderbuffer);
|
GLuint renderbuffer);
|
||||||
|
|
||||||
typedef void
|
typedef void
|
||||||
(APIENTRYP COGL_PFNGLRENDERBUFFERSTORAGEEXTPROC)
|
(APIENTRYP COGL_PFNGLRENDERBUFFERSTORAGEPROC)
|
||||||
(GLenum target,
|
(GLenum target,
|
||||||
GLenum internalformat,
|
GLenum internalformat,
|
||||||
GLsizei width,
|
GLsizei width,
|
||||||
GLsizei height);
|
GLsizei height);
|
||||||
|
|
||||||
typedef void
|
typedef void
|
||||||
(APIENTRYP COGL_PFNGLGENFRAMEBUFFERSEXTPROC)
|
(APIENTRYP COGL_PFNGLGENFRAMEBUFFERSPROC)
|
||||||
(GLsizei n,
|
(GLsizei n,
|
||||||
GLuint *framebuffers);
|
GLuint *framebuffers);
|
||||||
|
|
||||||
typedef void
|
typedef void
|
||||||
(APIENTRYP COGL_PFNGLBINDFRAMEBUFFEREXTPROC)
|
(APIENTRYP COGL_PFNGLBINDFRAMEBUFFERPROC)
|
||||||
(GLenum target,
|
(GLenum target,
|
||||||
GLuint framebuffer);
|
GLuint framebuffer);
|
||||||
|
|
||||||
typedef void
|
typedef void
|
||||||
(APIENTRYP COGL_PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)
|
(APIENTRYP COGL_PFNGLFRAMEBUFFERTEXTURE2DPROC)
|
||||||
(GLenum target,
|
(GLenum target,
|
||||||
GLenum attachment,
|
GLenum attachment,
|
||||||
GLenum textarget,
|
GLenum textarget,
|
||||||
@ -733,26 +733,30 @@ typedef void
|
|||||||
GLint level);
|
GLint level);
|
||||||
|
|
||||||
typedef void
|
typedef void
|
||||||
(APIENTRYP COGL_PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)
|
(APIENTRYP COGL_PFNGLFRAMEBUFFERRENDERBUFFERPROC)
|
||||||
(GLenum target,
|
(GLenum target,
|
||||||
GLenum attachment,
|
GLenum attachment,
|
||||||
GLenum renderbuffertarget,
|
GLenum renderbuffertarget,
|
||||||
GLuint renderbuffer);
|
GLuint renderbuffer);
|
||||||
|
|
||||||
typedef GLenum
|
typedef GLenum
|
||||||
(APIENTRYP COGL_PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)
|
(APIENTRYP COGL_PFNGLCHECKFRAMEBUFFERSTATUSPROC)
|
||||||
(GLenum target);
|
(GLenum target);
|
||||||
|
|
||||||
typedef void
|
typedef void
|
||||||
(APIENTRYP COGL_PFNGLDELETEFRAMEBUFFERSEXTPROC)
|
(APIENTRYP COGL_PFNGLDELETEFRAMEBUFFERSPROC)
|
||||||
(GLsizei n,
|
(GLsizei n,
|
||||||
const GLuint *framebuffers);
|
const GLuint *framebuffers);
|
||||||
|
|
||||||
typedef void
|
typedef void
|
||||||
(APIENTRYP COGL_PFNGLDELETERENDERBUFFERSEXTPROC)
|
(APIENTRYP COGL_PFNGLDELETERENDERBUFFERSPROC)
|
||||||
(GLsizei n,
|
(GLsizei n,
|
||||||
const GLuint *renderbuffers);
|
const GLuint *renderbuffers);
|
||||||
|
|
||||||
|
typedef void
|
||||||
|
(APIENTRYP COGL_PFNGLGENERATEMIPMAPPROC)
|
||||||
|
(GLenum target);
|
||||||
|
|
||||||
typedef void
|
typedef void
|
||||||
(APIENTRYP COGL_PFNGLBLITFRAMEBUFFEREXTPROC)
|
(APIENTRYP COGL_PFNGLBLITFRAMEBUFFEREXTPROC)
|
||||||
(GLint srcX0,
|
(GLint srcX0,
|
||||||
@ -774,10 +778,6 @@ typedef void
|
|||||||
GLsizei width,
|
GLsizei width,
|
||||||
GLsizei height);
|
GLsizei height);
|
||||||
|
|
||||||
typedef void
|
|
||||||
(APIENTRYP COGL_PFNGLGENERATEMIPMAPEXTPROC)
|
|
||||||
(GLenum target);
|
|
||||||
|
|
||||||
typedef GLhandleARB
|
typedef GLhandleARB
|
||||||
(APIENTRYP COGL_PFNGLCREATEPROGRAMOBJECTARBPROC)
|
(APIENTRYP COGL_PFNGLCREATEPROGRAMOBJECTARBPROC)
|
||||||
(void);
|
(void);
|
||||||
|
@ -1,325 +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) );
|
|
||||||
|
|
||||||
/* Some implementation require a clear before drawing
|
|
||||||
to an fbo. Luckily it is affected by scissor test. */
|
|
||||||
/* FIXME: test where exactly this is needed end whether
|
|
||||||
a glClear with 0 argument is enough */
|
|
||||||
GE( glPushAttrib (GL_SCISSOR_BIT) );
|
|
||||||
GE( glScissor (0,0,0,0) );
|
|
||||||
GE( glEnable (GL_SCISSOR_TEST) );
|
|
||||||
GE( glClear (GL_COLOR_BUFFER_BIT) );
|
|
||||||
GE( glPopAttrib () );
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
@ -30,6 +30,8 @@
|
|||||||
#include "cogl-context.h"
|
#include "cogl-context.h"
|
||||||
#include "cogl-clip-stack.h"
|
#include "cogl-clip-stack.h"
|
||||||
#include "cogl-material-private.h"
|
#include "cogl-material-private.h"
|
||||||
|
#include "cogl-clip-stack.h"
|
||||||
|
#include "cogl-draw-buffer-private.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <gmodule.h>
|
#include <gmodule.h>
|
||||||
@ -74,7 +76,7 @@ _cogl_path_add_node (gboolean new_sub_path,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_path_stroke_nodes ()
|
_cogl_path_stroke_nodes (void)
|
||||||
{
|
{
|
||||||
guint path_start = 0;
|
guint path_start = 0;
|
||||||
gulong enable_flags = COGL_ENABLE_VERTEX_ARRAY;
|
gulong enable_flags = COGL_ENABLE_VERTEX_ARRAY;
|
||||||
@ -82,6 +84,13 @@ _cogl_path_stroke_nodes ()
|
|||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
_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);
|
enable_flags |= _cogl_material_get_cogl_enable_flags (ctx->source_material);
|
||||||
cogl_enable (enable_flags);
|
cogl_enable (enable_flags);
|
||||||
|
|
||||||
@ -90,7 +99,6 @@ _cogl_path_stroke_nodes ()
|
|||||||
options.disable_layers = (guint32)~0;
|
options.disable_layers = (guint32)~0;
|
||||||
|
|
||||||
_cogl_material_flush_gl_state (ctx->source_material, &options);
|
_cogl_material_flush_gl_state (ctx->source_material, &options);
|
||||||
_cogl_flush_matrix_stacks ();
|
|
||||||
|
|
||||||
while (path_start < ctx->path_nodes->len)
|
while (path_start < ctx->path_nodes->len)
|
||||||
{
|
{
|
||||||
@ -127,20 +135,33 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min,
|
|||||||
CoglPathNode *path,
|
CoglPathNode *path,
|
||||||
gboolean merge)
|
gboolean merge)
|
||||||
{
|
{
|
||||||
guint path_start = 0;
|
guint path_start = 0;
|
||||||
guint sub_path_num = 0;
|
guint sub_path_num = 0;
|
||||||
float bounds_x;
|
float bounds_x;
|
||||||
float bounds_y;
|
float bounds_y;
|
||||||
float bounds_w;
|
float bounds_w;
|
||||||
float bounds_h;
|
float bounds_h;
|
||||||
gulong enable_flags = COGL_ENABLE_VERTEX_ARRAY;
|
gulong enable_flags = COGL_ENABLE_VERTEX_ARRAY;
|
||||||
CoglHandle prev_source;
|
CoglHandle prev_source;
|
||||||
int i;
|
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);
|
_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 ();
|
_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... */
|
/* Just setup a simple material that doesn't use texturing... */
|
||||||
prev_source = cogl_handle_ref (ctx->source_material);
|
prev_source = cogl_handle_ref (ctx->source_material);
|
||||||
cogl_set_source (ctx->stencil_material);
|
cogl_set_source (ctx->stencil_material);
|
||||||
@ -161,7 +182,7 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GE( glClear (GL_STENCIL_BUFFER_BIT) );
|
cogl_clear (NULL, COGL_BUFFER_BIT_STENCIL);
|
||||||
GE( glStencilMask (1) );
|
GE( glStencilMask (1) );
|
||||||
GE( glStencilFunc (GL_LEQUAL, 0x1, 0x3) );
|
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;
|
ctx->n_texcoord_arrays_enabled = 0;
|
||||||
|
|
||||||
_cogl_flush_matrix_stacks ();
|
|
||||||
|
|
||||||
while (path_start < path_size)
|
while (path_start < path_size)
|
||||||
{
|
{
|
||||||
GE( glVertexPointer (2, GL_FLOAT, sizeof (CoglPathNode),
|
GE( glVertexPointer (2, GL_FLOAT, sizeof (CoglPathNode),
|
||||||
@ -194,8 +213,17 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min,
|
|||||||
significant bit */
|
significant bit */
|
||||||
GE( glStencilMask (merge ? 6 : 3) );
|
GE( glStencilMask (merge ? 6 : 3) );
|
||||||
GE( glStencilOp (GL_ZERO, GL_REPLACE, GL_REPLACE) );
|
GE( glStencilOp (GL_ZERO, GL_REPLACE, GL_REPLACE) );
|
||||||
glRectf (bounds_x, bounds_y,
|
cogl_rectangle (bounds_x, bounds_y,
|
||||||
bounds_x + bounds_w, bounds_y + bounds_h);
|
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) );
|
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
|
/* Decrement all of the bits twice so that only pixels where the
|
||||||
value is 3 will remain */
|
value is 3 will remain */
|
||||||
|
|
||||||
_cogl_matrix_stack_push (ctx->projection_stack);
|
_cogl_matrix_stack_push (projection_stack);
|
||||||
_cogl_matrix_stack_load_identity (ctx->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_push (modelview_stack);
|
||||||
_cogl_matrix_stack_load_identity (ctx->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);
|
_cogl_matrix_stack_pop (modelview_stack);
|
||||||
glRectf (-1.0, -1.0, 1.0, 1.0);
|
_cogl_matrix_stack_pop (projection_stack);
|
||||||
|
|
||||||
_cogl_matrix_stack_pop (ctx->modelview_stack);
|
|
||||||
_cogl_matrix_stack_pop (ctx->projection_stack);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GE( glStencilMask (~(GLuint) 0) );
|
GE( glStencilMask (~(GLuint) 0) );
|
||||||
@ -244,8 +277,10 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_path_fill_nodes ()
|
_cogl_path_fill_nodes (void)
|
||||||
{
|
{
|
||||||
|
CoglHandle draw_buffer;
|
||||||
|
CoglClipStackState *clip_state;
|
||||||
float bounds_x;
|
float bounds_x;
|
||||||
float bounds_y;
|
float bounds_y;
|
||||||
float bounds_w;
|
float bounds_w;
|
||||||
@ -253,6 +288,11 @@ _cogl_path_fill_nodes ()
|
|||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
_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,
|
_cogl_path_get_bounds (ctx->path_nodes_min, ctx->path_nodes_max,
|
||||||
&bounds_x, &bounds_y, &bounds_w, &bounds_h);
|
&bounds_x, &bounds_y, &bounds_w, &bounds_h);
|
||||||
|
|
||||||
@ -261,12 +301,13 @@ _cogl_path_fill_nodes ()
|
|||||||
ctx->path_nodes->len,
|
ctx->path_nodes->len,
|
||||||
&g_array_index (ctx->path_nodes,
|
&g_array_index (ctx->path_nodes,
|
||||||
CoglPathNode, 0),
|
CoglPathNode, 0),
|
||||||
ctx->clip.stencil_used);
|
clip_state->stencil_used);
|
||||||
|
|
||||||
cogl_rectangle (bounds_x, bounds_y,
|
cogl_rectangle (bounds_x, bounds_y,
|
||||||
bounds_x + bounds_w, bounds_y + bounds_h);
|
bounds_x + bounds_w, bounds_y + bounds_h);
|
||||||
|
|
||||||
/* The stencil buffer now contains garbage so the clip area needs to
|
/* The stencil buffer now contains garbage so the clip area needs to
|
||||||
be rebuilt */
|
be rebuilt */
|
||||||
ctx->clip.stack_dirty = TRUE;
|
_cogl_clip_stack_state_dirty (clip_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#define glGenerateMipmap ctx->drv.pf_glGenerateMipmapEXT
|
#define glGenerateMipmap ctx->drv.pf_glGenerateMipmap
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_texture_driver_bind (GLenum gl_target,
|
_cogl_texture_driver_bind (GLenum gl_target,
|
||||||
|
@ -32,6 +32,12 @@
|
|||||||
#include "cogl-internal.h"
|
#include "cogl-internal.h"
|
||||||
#include "cogl-context.h"
|
#include "cogl-context.h"
|
||||||
|
|
||||||
|
typedef struct _CoglGLSymbolTableEntry
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
void *ptr;
|
||||||
|
} CoglGLSymbolTableEntry;
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
cogl_check_extension (const gchar *name, const gchar *ext)
|
cogl_check_extension (const gchar *name, const gchar *ext)
|
||||||
{
|
{
|
||||||
@ -57,6 +63,26 @@ cogl_check_extension (const gchar *name, const gchar *ext)
|
|||||||
return FALSE;
|
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
|
#ifdef HAVE_CLUTTER_OSX
|
||||||
static gboolean
|
static gboolean
|
||||||
really_enable_npot (void)
|
really_enable_npot (void)
|
||||||
@ -90,6 +116,9 @@ _cogl_features_init (void)
|
|||||||
const gchar *gl_extensions;
|
const gchar *gl_extensions;
|
||||||
GLint max_clip_planes = 0;
|
GLint max_clip_planes = 0;
|
||||||
GLint num_stencil_bits = 0;
|
GLint num_stencil_bits = 0;
|
||||||
|
gboolean fbo_ARB = FALSE;
|
||||||
|
gboolean fbo_EXT = FALSE;
|
||||||
|
const char *suffix;
|
||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
|
|
||||||
@ -284,64 +313,35 @@ _cogl_features_init (void)
|
|||||||
flags |= COGL_FEATURE_SHADERS_GLSL;
|
flags |= COGL_FEATURE_SHADERS_GLSL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cogl_check_extension ("GL_EXT_framebuffer_object", gl_extensions) ||
|
fbo_ARB = cogl_check_extension ("GL_ARB_framebuffer_object", gl_extensions);
|
||||||
cogl_check_extension ("GL_ARB_framebuffer_object", gl_extensions))
|
if (fbo_ARB)
|
||||||
|
suffix = "";
|
||||||
|
else
|
||||||
{
|
{
|
||||||
ctx->drv.pf_glGenRenderbuffersEXT =
|
fbo_EXT = cogl_check_extension ("GL_EXT_framebuffer_object", gl_extensions);
|
||||||
(COGL_PFNGLGENRENDERBUFFERSEXTPROC)
|
if (fbo_EXT)
|
||||||
cogl_get_proc_address ("glGenRenderbuffersEXT");
|
suffix = "EXT";
|
||||||
|
}
|
||||||
|
|
||||||
ctx->drv.pf_glDeleteRenderbuffersEXT =
|
if (fbo_ARB || fbo_EXT)
|
||||||
(COGL_PFNGLDELETERENDERBUFFERSEXTPROC)
|
{
|
||||||
cogl_get_proc_address ("glDeleteRenderbuffersEXT");
|
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 =
|
if (_cogl_resolve_gl_symbols (symbol_table, suffix))
|
||||||
(COGL_PFNGLBINDRENDERBUFFEREXTPROC)
|
flags |= COGL_FEATURE_OFFSCREEN;
|
||||||
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_check_extension ("GL_EXT_framebuffer_blit", gl_extensions))
|
if (cogl_check_extension ("GL_EXT_framebuffer_blit", gl_extensions))
|
||||||
|
@ -22,11 +22,9 @@ libclutter_cogl_driver_la_CPPFLAGS = \
|
|||||||
$(CLUTTER_DEBUG_CFLAGS) \
|
$(CLUTTER_DEBUG_CFLAGS) \
|
||||||
$(MAINTAINER_CFLAGS)
|
$(MAINTAINER_CFLAGS)
|
||||||
libclutter_cogl_driver_la_SOURCES = \
|
libclutter_cogl_driver_la_SOURCES = \
|
||||||
cogl-fbo.h \
|
|
||||||
cogl.c \
|
cogl.c \
|
||||||
cogl-primitives.c \
|
cogl-primitives.c \
|
||||||
cogl-texture-driver.c \
|
cogl-texture-driver.c \
|
||||||
cogl-fbo.c \
|
|
||||||
cogl-context-driver.c \
|
cogl-context-driver.c \
|
||||||
cogl-context-driver.h \
|
cogl-context-driver.h \
|
||||||
cogl-gles2-wrapper.h \
|
cogl-gles2-wrapper.h \
|
||||||
|
@ -31,6 +31,16 @@
|
|||||||
void
|
void
|
||||||
_cogl_create_context_driver (CoglContext *context)
|
_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 */
|
/* Init the GLES2 wrapper */
|
||||||
#ifdef HAVE_COGL_GLES2
|
#ifdef HAVE_COGL_GLES2
|
||||||
cogl_gles2_wrapper_init (&context->drv.gles2);
|
cogl_gles2_wrapper_init (&context->drv.gles2);
|
||||||
|
@ -24,17 +24,26 @@
|
|||||||
#ifndef __COGL_CONTEXT_DRIVER_H
|
#ifndef __COGL_CONTEXT_DRIVER_H
|
||||||
#define __COGL_CONTEXT_DRIVER_H
|
#define __COGL_CONTEXT_DRIVER_H
|
||||||
|
|
||||||
|
#include "cogl.h"
|
||||||
#include "cogl-gles2-wrapper.h"
|
#include "cogl-gles2-wrapper.h"
|
||||||
|
|
||||||
typedef struct _CoglContextDriver
|
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
|
#ifdef HAVE_COGL_GLES2
|
||||||
CoglGles2Wrapper gles2;
|
CoglGles2Wrapper gles2;
|
||||||
|
|
||||||
/* Viewport store for FBOs. Needed because glPushAttrib() isn't
|
|
||||||
supported */
|
|
||||||
GLint viewport_store[4];
|
|
||||||
#endif
|
#endif
|
||||||
} CoglContextDriver;
|
} CoglContextDriver;
|
||||||
|
|
||||||
|
@ -633,6 +633,76 @@ G_BEGIN_DECLS
|
|||||||
#define CGL_SHININESS 0x1601
|
#define CGL_SHININESS 0x1601
|
||||||
#endif
|
#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
|
G_END_DECLS
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,339 +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);
|
|
||||||
|
|
||||||
g_assert (ctx->draw_buffer_stack != NULL);
|
|
||||||
draw_buffer = ctx->draw_buffer_stack->data;
|
|
||||||
|
|
||||||
if (target == COGL_OFFSCREEN_BUFFER)
|
|
||||||
{
|
|
||||||
GLboolean scissor_enabled;
|
|
||||||
GLint scissor_box[4];
|
|
||||||
|
|
||||||
/* 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 */
|
|
||||||
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);
|
|
||||||
|
|
||||||
/* Bind offscreen framebuffer object */
|
|
||||||
GE( glBindFramebuffer (GL_FRAMEBUFFER, fbo->gl_handle) );
|
|
||||||
GE( glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE) );
|
|
||||||
|
|
||||||
/* Some implementation require a clear before drawing
|
|
||||||
to an fbo. Luckily it is affected by scissor test. */
|
|
||||||
/* FIXME: test where exactly this is needed end whether
|
|
||||||
a glClear with 0 argument is enough */
|
|
||||||
|
|
||||||
scissor_enabled = glIsEnabled (GL_SCISSOR_TEST);
|
|
||||||
GE( glGetIntegerv (GL_SCISSOR_BOX, scissor_box) );
|
|
||||||
GE( glScissor (0, 0, 0, 0) );
|
|
||||||
GE( glEnable (GL_SCISSOR_TEST) );
|
|
||||||
GE( glClear (GL_COLOR_BUFFER_BIT) );
|
|
||||||
if (!scissor_enabled)
|
|
||||||
glDisable (GL_SCISSOR_TEST);
|
|
||||||
glScissor (scissor_box[0], scissor_box[1],
|
|
||||||
scissor_box[2], scissor_box[3]);
|
|
||||||
|
|
||||||
}
|
|
||||||
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-context.h"
|
||||||
#include "cogl-clip-stack.h"
|
#include "cogl-clip-stack.h"
|
||||||
#include "cogl-material-private.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 <string.h>
|
||||||
#include <gmodule.h>
|
#include <gmodule.h>
|
||||||
@ -72,7 +75,7 @@ _cogl_path_add_node (gboolean new_sub_path,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_path_stroke_nodes ()
|
_cogl_path_stroke_nodes (void)
|
||||||
{
|
{
|
||||||
guint path_start = 0;
|
guint path_start = 0;
|
||||||
gulong enable_flags = COGL_ENABLE_VERTEX_ARRAY;
|
gulong enable_flags = COGL_ENABLE_VERTEX_ARRAY;
|
||||||
@ -80,13 +83,21 @@ _cogl_path_stroke_nodes ()
|
|||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
_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);
|
enable_flags |= _cogl_material_get_cogl_enable_flags (ctx->source_material);
|
||||||
cogl_enable (enable_flags);
|
cogl_enable (enable_flags);
|
||||||
|
|
||||||
options.flags = COGL_MATERIAL_FLUSH_DISABLE_MASK;
|
options.flags = COGL_MATERIAL_FLUSH_DISABLE_MASK;
|
||||||
|
/* disable all texture layers */
|
||||||
options.disable_layers = (guint32)~0;
|
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)
|
while (path_start < ctx->path_nodes->len)
|
||||||
{
|
{
|
||||||
@ -129,18 +140,38 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min,
|
|||||||
CoglPathNode *path,
|
CoglPathNode *path,
|
||||||
gboolean merge)
|
gboolean merge)
|
||||||
{
|
{
|
||||||
guint path_start = 0;
|
guint path_start = 0;
|
||||||
guint sub_path_num = 0;
|
guint sub_path_num = 0;
|
||||||
float bounds_x;
|
float bounds_x;
|
||||||
float bounds_y;
|
float bounds_y;
|
||||||
float bounds_w;
|
float bounds_w;
|
||||||
float bounds_h;
|
float bounds_h;
|
||||||
gulong enable_flags = COGL_ENABLE_VERTEX_ARRAY;
|
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);
|
_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... */
|
/* 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 |=
|
enable_flags |=
|
||||||
_cogl_material_get_cogl_enable_flags (ctx->source_material);
|
_cogl_material_get_cogl_enable_flags (ctx->source_material);
|
||||||
@ -156,7 +187,7 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GE( glClear (GL_STENCIL_BUFFER_BIT) );
|
cogl_clear (NULL, COGL_BUFFER_BIT_STENCIL);
|
||||||
GE( glStencilMask (1) );
|
GE( glStencilMask (1) );
|
||||||
GE( glStencilFunc (GL_LEQUAL, 0x1, 0x3) );
|
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( glColorMask (FALSE, FALSE, FALSE, FALSE) );
|
||||||
GE( glDepthMask (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)
|
while (path_start < path_size)
|
||||||
{
|
{
|
||||||
GE( glVertexPointer (2, GL_FLOAT, sizeof (CoglPathNode),
|
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) );
|
GE( glStencilOp (GL_ZERO, GL_REPLACE, GL_REPLACE) );
|
||||||
cogl_rectangle (bounds_x, bounds_y,
|
cogl_rectangle (bounds_x, bounds_y,
|
||||||
bounds_x + bounds_w, bounds_y + bounds_h);
|
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) );
|
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
|
/* Decrement all of the bits twice so that only pixels where the
|
||||||
value is 3 will remain */
|
value is 3 will remain */
|
||||||
|
|
||||||
_cogl_matrix_stack_push (ctx->projection_stack);
|
_cogl_matrix_stack_push (projection_stack);
|
||||||
_cogl_matrix_stack_load_identity (ctx->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_push (modelview_stack);
|
||||||
_cogl_matrix_stack_load_identity (ctx->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);
|
||||||
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 (modelview_stack);
|
||||||
_cogl_matrix_stack_pop (ctx->projection_stack);
|
_cogl_matrix_stack_pop (projection_stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
GE( glStencilMask (~(GLuint) 0) );
|
GE( glStencilMask (~(GLuint) 0) );
|
||||||
@ -250,6 +302,21 @@ _cogl_path_fill_nodes_scanlines (CoglPathNode *path,
|
|||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
_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 */
|
/* clear scanline intersection lists */
|
||||||
for (i=0; i < bounds_h; i++)
|
for (i=0; i < bounds_h; i++)
|
||||||
scanlines[i]=NULL;
|
scanlines[i]=NULL;
|
||||||
@ -386,8 +453,6 @@ _cogl_path_fill_nodes_scanlines (CoglPathNode *path,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* render triangles */
|
/* render triangles */
|
||||||
cogl_enable (COGL_ENABLE_VERTEX_ARRAY
|
|
||||||
| (ctx->color_alpha < 255 ? COGL_ENABLE_BLEND : 0));
|
|
||||||
GE ( glVertexPointer (2, GL_FLOAT, 0, coords ) );
|
GE ( glVertexPointer (2, GL_FLOAT, 0, coords ) );
|
||||||
GE ( glDrawArrays (GL_TRIANGLES, 0, spans * 2 * 3));
|
GE ( glDrawArrays (GL_TRIANGLES, 0, spans * 2 * 3));
|
||||||
g_free (coords);
|
g_free (coords);
|
||||||
@ -395,7 +460,7 @@ _cogl_path_fill_nodes_scanlines (CoglPathNode *path,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_path_fill_nodes ()
|
_cogl_path_fill_nodes (void)
|
||||||
{
|
{
|
||||||
float bounds_x;
|
float bounds_x;
|
||||||
float bounds_y;
|
float bounds_y;
|
||||||
@ -409,19 +474,27 @@ _cogl_path_fill_nodes ()
|
|||||||
|
|
||||||
if (cogl_features_available (COGL_FEATURE_STENCIL_BUFFER))
|
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,
|
_cogl_add_path_to_stencil_buffer (ctx->path_nodes_min,
|
||||||
ctx->path_nodes_max,
|
ctx->path_nodes_max,
|
||||||
ctx->path_nodes->len,
|
ctx->path_nodes->len,
|
||||||
&g_array_index (ctx->path_nodes,
|
&g_array_index (ctx->path_nodes,
|
||||||
CoglPathNode, 0),
|
CoglPathNode, 0),
|
||||||
ctx->clip.stencil_used);
|
clip_state->stencil_used);
|
||||||
|
|
||||||
cogl_rectangle (bounds_x, bounds_y,
|
cogl_rectangle (bounds_x, bounds_y,
|
||||||
bounds_x + bounds_w, bounds_y + bounds_h);
|
bounds_x + bounds_w, bounds_y + bounds_h);
|
||||||
|
|
||||||
/* The stencil buffer now contains garbage so the clip area needs to
|
/* The stencil buffer now contains garbage so the clip area needs to
|
||||||
be rebuilt */
|
be rebuilt */
|
||||||
ctx->clip.stack_dirty = TRUE;
|
_cogl_clip_stack_state_dirty (clip_state);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -31,6 +31,56 @@
|
|||||||
#include "cogl-internal.h"
|
#include "cogl-internal.h"
|
||||||
#include "cogl-context.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
|
void
|
||||||
@ -39,9 +89,34 @@ _cogl_features_init (void)
|
|||||||
CoglFeatureFlags flags = 0;
|
CoglFeatureFlags flags = 0;
|
||||||
int max_clip_planes = 0;
|
int max_clip_planes = 0;
|
||||||
GLint num_stencil_bits = 0;
|
GLint num_stencil_bits = 0;
|
||||||
|
const char *gl_extensions;
|
||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
_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) );
|
GE( glGetIntegerv (GL_STENCIL_BITS, &num_stencil_bits) );
|
||||||
/* We need at least three stencil bits to combine clips */
|
/* We need at least three stencil bits to combine clips */
|
||||||
if (num_stencil_bits > 2)
|
if (num_stencil_bits > 2)
|
||||||
|
@ -210,6 +210,7 @@ clutter_stage_x11_resize (ClutterStageWindow *stage_window,
|
|||||||
ClutterBackend *backend = clutter_get_default_backend ();
|
ClutterBackend *backend = clutter_get_default_backend ();
|
||||||
ClutterBackendX11 *backend_x11;
|
ClutterBackendX11 *backend_x11;
|
||||||
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
|
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
|
||||||
|
ClutterStage *stage = stage_x11->wrapper;
|
||||||
gboolean resize;
|
gboolean resize;
|
||||||
|
|
||||||
resize = clutter_stage_get_user_resizable (stage_x11->wrapper);
|
resize = clutter_stage_get_user_resizable (stage_x11->wrapper);
|
||||||
@ -250,6 +251,22 @@ clutter_stage_x11_resize (ClutterStageWindow *stage_window,
|
|||||||
stage_x11->xwin,
|
stage_x11->xwin,
|
||||||
stage_x11->xwin_width,
|
stage_x11->xwin_width,
|
||||||
stage_x11->xwin_height);
|
stage_x11->xwin_height);
|
||||||
|
|
||||||
|
/* If the viewport hasn't previously been initialized then even
|
||||||
|
* though we can't guarantee that the server will honour our request
|
||||||
|
* we need to ensure a valid viewport is set before our first paint.
|
||||||
|
*/
|
||||||
|
if (G_UNLIKELY (!stage_x11->viewport_initialized))
|
||||||
|
{
|
||||||
|
ClutterPerspective perspective;
|
||||||
|
clutter_stage_get_perspective (stage, &perspective);
|
||||||
|
_cogl_setup_viewport (stage_x11->xwin_width,
|
||||||
|
stage_x11->xwin_height,
|
||||||
|
perspective.fovy,
|
||||||
|
perspective.aspect,
|
||||||
|
perspective.z_near,
|
||||||
|
perspective.z_far);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!resize)
|
if (!resize)
|
||||||
@ -654,6 +671,7 @@ clutter_stage_x11_init (ClutterStageX11 *stage)
|
|||||||
stage->is_foreign_xwin = FALSE;
|
stage->is_foreign_xwin = FALSE;
|
||||||
stage->fullscreen_on_map = FALSE;
|
stage->fullscreen_on_map = FALSE;
|
||||||
stage->is_cursor_visible = TRUE;
|
stage->is_cursor_visible = TRUE;
|
||||||
|
stage->viewport_initialized = FALSE;
|
||||||
|
|
||||||
stage->title = NULL;
|
stage->title = NULL;
|
||||||
|
|
||||||
|
@ -50,9 +50,10 @@ struct _ClutterStageX11
|
|||||||
{
|
{
|
||||||
ClutterGroup parent_instance;
|
ClutterGroup parent_instance;
|
||||||
|
|
||||||
guint is_foreign_xwin : 1;
|
guint is_foreign_xwin : 1;
|
||||||
guint fullscreen_on_map : 1;
|
guint fullscreen_on_map : 1;
|
||||||
guint is_cursor_visible : 1;
|
guint is_cursor_visible : 1;
|
||||||
|
guint viewport_initialized : 1;
|
||||||
|
|
||||||
Window xwin;
|
Window xwin;
|
||||||
gint xwin_width;
|
gint xwin_width;
|
||||||
|
@ -35,6 +35,10 @@ test_conformance_SOURCES = \
|
|||||||
test-materials.c \
|
test-materials.c \
|
||||||
test-group.c \
|
test-group.c \
|
||||||
test-actor-size.c \
|
test-actor-size.c \
|
||||||
|
test-texture-fbo.c \
|
||||||
|
test-cogl-viewport.c \
|
||||||
|
test-cogl-offscreen.c \
|
||||||
|
test-cogl-readpixels.c \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
# For convenience, this provides a way to easily run individual unit tests:
|
# For convenience, this provides a way to easily run individual unit tests:
|
||||||
|
@ -5,8 +5,6 @@
|
|||||||
|
|
||||||
#include "test-conform-common.h"
|
#include "test-conform-common.h"
|
||||||
|
|
||||||
static const ClutterColor stage_color = { 0x0, 0x0, 0x0, 0xff };
|
|
||||||
|
|
||||||
#ifdef CLUTTER_COGL_HAS_GL
|
#ifdef CLUTTER_COGL_HAS_GL
|
||||||
|
|
||||||
/* Size the texture so that it is just off a power of two to enourage
|
/* Size the texture so that it is just off a power of two to enourage
|
||||||
@ -31,24 +29,31 @@ static const ClutterColor stage_color = { 0x0, 0x0, 0x0, 0xff };
|
|||||||
|
|
||||||
typedef struct _TestState
|
typedef struct _TestState
|
||||||
{
|
{
|
||||||
guint frame;
|
|
||||||
CoglHandle texture;
|
CoglHandle texture;
|
||||||
|
CoglHandle offscreen;
|
||||||
|
CoglHandle offscreen_tex;
|
||||||
} TestState;
|
} TestState;
|
||||||
|
|
||||||
|
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
validate_part (int xnum, int ynum, gboolean shown)
|
validate_part (int xnum, int ynum, gboolean shown)
|
||||||
{
|
{
|
||||||
guchar *pixels, *p;
|
guchar *pixels, *p;
|
||||||
ClutterActor *stage = clutter_stage_get_default ();
|
|
||||||
gboolean ret = TRUE;
|
gboolean ret = TRUE;
|
||||||
|
|
||||||
|
pixels = g_malloc0 ((TEXTURE_RENDER_SIZE - TEST_INSET * 2)
|
||||||
|
* (TEXTURE_RENDER_SIZE - TEST_INSET * 2) * 4);
|
||||||
|
|
||||||
/* Read the appropriate part but skip out a few pixels around the
|
/* Read the appropriate part but skip out a few pixels around the
|
||||||
edges */
|
edges */
|
||||||
pixels = clutter_stage_read_pixels (CLUTTER_STAGE (stage),
|
cogl_read_pixels (xnum * TEXTURE_RENDER_SIZE + TEST_INSET,
|
||||||
xnum * TEXTURE_RENDER_SIZE + TEST_INSET,
|
ynum * TEXTURE_RENDER_SIZE + TEST_INSET,
|
||||||
ynum * TEXTURE_RENDER_SIZE + TEST_INSET,
|
TEXTURE_RENDER_SIZE - TEST_INSET * 2,
|
||||||
TEXTURE_RENDER_SIZE - TEST_INSET * 2,
|
TEXTURE_RENDER_SIZE - TEST_INSET * 2,
|
||||||
TEXTURE_RENDER_SIZE - TEST_INSET * 2);
|
COGL_READ_PIXELS_COLOR_BUFFER,
|
||||||
|
COGL_PIXEL_FORMAT_RGBA_8888,
|
||||||
|
pixels);
|
||||||
|
|
||||||
/* Make sure every pixels is the appropriate color */
|
/* Make sure every pixels is the appropriate color */
|
||||||
for (p = pixels;
|
for (p = pixels;
|
||||||
@ -70,47 +75,9 @@ validate_part (int xnum, int ynum, gboolean shown)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
validate_result (TestState *state)
|
do_test_backface_culling (TestState *state)
|
||||||
{
|
|
||||||
/* Front-facing texture */
|
|
||||||
g_assert (validate_part (0, 0, TRUE));
|
|
||||||
/* Front-facing texture with flipped tex coords */
|
|
||||||
g_assert (validate_part (1, 0, TRUE));
|
|
||||||
/* Back-facing texture */
|
|
||||||
g_assert (validate_part (2, 0, FALSE));
|
|
||||||
/* Front-facing texture polygon */
|
|
||||||
g_assert (validate_part (3, 0, TRUE));
|
|
||||||
/* Back-facing texture polygon */
|
|
||||||
g_assert (validate_part (4, 0, FALSE));
|
|
||||||
/* Regular rectangle */
|
|
||||||
g_assert (validate_part (5, 0, TRUE));
|
|
||||||
|
|
||||||
/* Backface culling disabled - everything should be shown */
|
|
||||||
|
|
||||||
/* Front-facing texture */
|
|
||||||
g_assert (validate_part (0, 1, TRUE));
|
|
||||||
/* Front-facing texture with flipped tex coords */
|
|
||||||
g_assert (validate_part (1, 1, TRUE));
|
|
||||||
/* Back-facing texture */
|
|
||||||
g_assert (validate_part (2, 1, TRUE));
|
|
||||||
/* Front-facing texture polygon */
|
|
||||||
g_assert (validate_part (3, 1, TRUE));
|
|
||||||
/* Back-facing texture polygon */
|
|
||||||
g_assert (validate_part (4, 1, TRUE));
|
|
||||||
/* Regular rectangle */
|
|
||||||
g_assert (validate_part (5, 1, TRUE));
|
|
||||||
|
|
||||||
/* Comment this out if you want visual feedback of what this test
|
|
||||||
* paints.
|
|
||||||
*/
|
|
||||||
clutter_main_quit ();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
on_paint (ClutterActor *actor, TestState *state)
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int frame_num;
|
|
||||||
CoglHandle material = cogl_material_new ();
|
CoglHandle material = cogl_material_new ();
|
||||||
|
|
||||||
cogl_material_set_layer_filters (material, 0,
|
cogl_material_set_layer_filters (material, 0,
|
||||||
@ -197,21 +164,91 @@ on_paint (ClutterActor *actor, TestState *state)
|
|||||||
cogl_set_backface_culling_enabled (FALSE);
|
cogl_set_backface_culling_enabled (FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
cogl_pop_matrix ();
|
|
||||||
|
|
||||||
cogl_handle_unref (material);
|
cogl_handle_unref (material);
|
||||||
|
|
||||||
/* XXX: Experiments have shown that for some buggy drivers, when using
|
cogl_pop_matrix ();
|
||||||
* glReadPixels there is some kind of race, so we delay our test for a
|
|
||||||
* few frames and a few seconds:
|
/* Front-facing texture */
|
||||||
|
g_assert (validate_part (0, 0, TRUE));
|
||||||
|
/* Front-facing texture with flipped tex coords */
|
||||||
|
g_assert (validate_part (1, 0, TRUE));
|
||||||
|
/* Back-facing texture */
|
||||||
|
g_assert (validate_part (2, 0, FALSE));
|
||||||
|
/* Front-facing texture polygon */
|
||||||
|
g_assert (validate_part (3, 0, TRUE));
|
||||||
|
/* Back-facing texture polygon */
|
||||||
|
g_assert (validate_part (4, 0, FALSE));
|
||||||
|
/* Regular rectangle */
|
||||||
|
g_assert (validate_part (5, 0, TRUE));
|
||||||
|
|
||||||
|
/* Backface culling disabled - everything should be shown */
|
||||||
|
|
||||||
|
/* Front-facing texture */
|
||||||
|
g_assert (validate_part (0, 1, TRUE));
|
||||||
|
/* Front-facing texture with flipped tex coords */
|
||||||
|
g_assert (validate_part (1, 1, TRUE));
|
||||||
|
/* Back-facing texture */
|
||||||
|
g_assert (validate_part (2, 1, TRUE));
|
||||||
|
/* Front-facing texture polygon */
|
||||||
|
g_assert (validate_part (3, 1, TRUE));
|
||||||
|
/* Back-facing texture polygon */
|
||||||
|
g_assert (validate_part (4, 1, TRUE));
|
||||||
|
/* Regular rectangle */
|
||||||
|
g_assert (validate_part (5, 1, TRUE));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_paint (ClutterActor *actor, TestState *state)
|
||||||
|
{
|
||||||
|
CoglColor clr;
|
||||||
|
float stage_viewport[4];
|
||||||
|
CoglMatrix stage_projection;
|
||||||
|
CoglMatrix stage_modelview;
|
||||||
|
|
||||||
|
cogl_color_set_from_4ub (&clr, 0x00, 0x00, 0x00, 0xff);
|
||||||
|
|
||||||
|
do_test_backface_culling (state);
|
||||||
|
|
||||||
|
/* Since we are going to repeat the test rendering offscreen we clear the
|
||||||
|
* stage, just to minimize the chance of a some other bug causing us
|
||||||
|
* mistakenly reading back the results from the stage and giving a false
|
||||||
|
* posistive. */
|
||||||
|
cogl_clear (&clr, COGL_BUFFER_BIT_COLOR|COGL_BUFFER_BIT_STENCIL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now repeat the test but rendered to an offscreen draw buffer...
|
||||||
*/
|
*/
|
||||||
/* Need to increment frame first because clutter_stage_read_pixels
|
|
||||||
fires a redraw */
|
cogl_get_viewport (stage_viewport);
|
||||||
frame_num = state->frame++;
|
cogl_get_projection_matrix (&stage_projection);
|
||||||
if (frame_num == 2)
|
cogl_get_modelview_matrix (&stage_modelview);
|
||||||
validate_result (state);
|
|
||||||
else if (frame_num < 2)
|
cogl_push_draw_buffer ();
|
||||||
g_usleep (G_USEC_PER_SEC);
|
cogl_set_draw_buffer (0 /* unused */, state->offscreen);
|
||||||
|
|
||||||
|
cogl_clear (&clr, COGL_BUFFER_BIT_COLOR|COGL_BUFFER_BIT_STENCIL);
|
||||||
|
|
||||||
|
cogl_set_viewport (stage_viewport[0],
|
||||||
|
stage_viewport[1],
|
||||||
|
stage_viewport[2],
|
||||||
|
stage_viewport[3]);
|
||||||
|
cogl_set_projection_matrix (&stage_projection);
|
||||||
|
cogl_set_modelview_matrix (&stage_modelview);
|
||||||
|
|
||||||
|
do_test_backface_culling (state);
|
||||||
|
|
||||||
|
cogl_pop_draw_buffer ();
|
||||||
|
|
||||||
|
/* Incase we want feedback of what was drawn offscreen we draw it
|
||||||
|
* to the stage... */
|
||||||
|
cogl_set_source_texture (state->offscreen_tex);
|
||||||
|
cogl_rectangle (0, 0, stage_viewport[2], stage_viewport[3]);
|
||||||
|
|
||||||
|
/* Comment this out if you want visual feedback of what this test
|
||||||
|
* paints.
|
||||||
|
*/
|
||||||
|
clutter_main_quit ();
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -256,15 +293,26 @@ test_backface_culling (TestConformSimpleFixture *fixture,
|
|||||||
gconstpointer data)
|
gconstpointer data)
|
||||||
{
|
{
|
||||||
TestState state;
|
TestState state;
|
||||||
|
CoglHandle tex;
|
||||||
ClutterActor *stage;
|
ClutterActor *stage;
|
||||||
|
float stage_width;
|
||||||
|
float stage_height;
|
||||||
|
const ClutterColor stage_color = { 0x0, 0x0, 0x0, 0xff };
|
||||||
ClutterActor *group;
|
ClutterActor *group;
|
||||||
guint idle_source;
|
guint idle_source;
|
||||||
|
|
||||||
state.frame = 0;
|
stage = clutter_stage_get_default ();
|
||||||
|
clutter_actor_get_size (stage, &stage_width, &stage_height);
|
||||||
|
|
||||||
|
state.offscreen = COGL_INVALID_HANDLE;
|
||||||
|
|
||||||
state.texture = make_texture ();
|
state.texture = make_texture ();
|
||||||
|
|
||||||
stage = clutter_stage_get_default ();
|
tex = cogl_texture_new_with_size (stage_width, stage_height,
|
||||||
|
COGL_TEXTURE_NO_SLICING,
|
||||||
|
COGL_PIXEL_FORMAT_ANY); /* internal fmt */
|
||||||
|
state.offscreen = cogl_offscreen_new_to_texture (tex);
|
||||||
|
state.offscreen_tex = tex;
|
||||||
|
|
||||||
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
|
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
|
||||||
|
|
||||||
@ -284,6 +332,8 @@ test_backface_culling (TestConformSimpleFixture *fixture,
|
|||||||
|
|
||||||
g_source_remove (idle_source);
|
g_source_remove (idle_source);
|
||||||
|
|
||||||
|
cogl_handle_unref (state.offscreen);
|
||||||
|
cogl_handle_unref (state.offscreen_tex);
|
||||||
cogl_handle_unref (state.texture);
|
cogl_handle_unref (state.texture);
|
||||||
|
|
||||||
if (g_test_verbose ())
|
if (g_test_verbose ())
|
||||||
|
169
tests/conform/test-cogl-offscreen.c
Normal file
169
tests/conform/test-cogl-offscreen.c
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
|
||||||
|
#include <clutter/clutter.h>
|
||||||
|
#include <cogl/cogl.h>
|
||||||
|
|
||||||
|
#include "test-conform-common.h"
|
||||||
|
|
||||||
|
#define RED 0
|
||||||
|
#define GREEN 1
|
||||||
|
#define BLUE 2
|
||||||
|
|
||||||
|
#define DRAW_BUFFER_WIDTH 640
|
||||||
|
#define DRAW_BUFFER_HEIGHT 480
|
||||||
|
|
||||||
|
static const ClutterColor stage_color = { 0x0, 0x0, 0x0, 0xff };
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_paint (ClutterActor *actor, void *state)
|
||||||
|
{
|
||||||
|
float saved_viewport[4];
|
||||||
|
CoglMatrix saved_projection;
|
||||||
|
CoglMatrix projection;
|
||||||
|
CoglMatrix modelview;
|
||||||
|
guchar *data;
|
||||||
|
CoglHandle tex;
|
||||||
|
CoglHandle offscreen;
|
||||||
|
guint8 pixel[4];
|
||||||
|
|
||||||
|
/* Save the Clutter viewport/matrices and load identity matrices */
|
||||||
|
|
||||||
|
cogl_get_viewport (saved_viewport);
|
||||||
|
cogl_get_projection_matrix (&saved_projection);
|
||||||
|
cogl_push_matrix ();
|
||||||
|
|
||||||
|
cogl_matrix_init_identity (&projection);
|
||||||
|
cogl_matrix_init_identity (&modelview);
|
||||||
|
|
||||||
|
cogl_set_projection_matrix (&projection);
|
||||||
|
cogl_set_modelview_matrix (&modelview);
|
||||||
|
|
||||||
|
data = g_malloc (DRAW_BUFFER_WIDTH * 4 * DRAW_BUFFER_HEIGHT);
|
||||||
|
tex = cogl_texture_new_from_data (DRAW_BUFFER_WIDTH, DRAW_BUFFER_HEIGHT,
|
||||||
|
COGL_TEXTURE_NO_SLICING,
|
||||||
|
COGL_PIXEL_FORMAT_RGBA_8888, /* data fmt */
|
||||||
|
COGL_PIXEL_FORMAT_ANY, /* internal fmt */
|
||||||
|
DRAW_BUFFER_WIDTH * 4, /* rowstride */
|
||||||
|
data);
|
||||||
|
g_free (data);
|
||||||
|
offscreen = cogl_offscreen_new_to_texture (tex);
|
||||||
|
|
||||||
|
/* Set a scale and translate transform on the window draw buffer before
|
||||||
|
* switching to the offscreen draw buffer so we can verify it gets restored
|
||||||
|
* when we switch back
|
||||||
|
*
|
||||||
|
* The test is going to draw a grid of 4 colors to a texture which we
|
||||||
|
* subsequently draw to the window with a fullscreen rectangle. This
|
||||||
|
* transform will flip the texture left to right, scale it to a quater of the
|
||||||
|
* window size and slide it to the top right of the window.
|
||||||
|
*/
|
||||||
|
cogl_translate (0.5, 0.5, 0);
|
||||||
|
cogl_scale (-0.5, 0.5, 1);
|
||||||
|
|
||||||
|
cogl_push_draw_buffer ();
|
||||||
|
cogl_set_draw_buffer (0 /* unused */, offscreen);
|
||||||
|
|
||||||
|
/* Cogl should release the last reference when we call cogl_pop_draw_buffer()
|
||||||
|
*/
|
||||||
|
cogl_handle_unref (offscreen);
|
||||||
|
|
||||||
|
/* Setup something other than the identity matrix for the modelview so we can
|
||||||
|
* verify it gets restored when we call cogl_pop_draw_buffer () */
|
||||||
|
cogl_scale (2, 2, 1);
|
||||||
|
|
||||||
|
/* red, top left */
|
||||||
|
cogl_set_source_color4ub (0xff, 0x00, 0x00, 0xff);
|
||||||
|
cogl_rectangle (-0.5, 0.5, 0, 0);
|
||||||
|
/* green, top right */
|
||||||
|
cogl_set_source_color4ub (0x00, 0xff, 0x00, 0xff);
|
||||||
|
cogl_rectangle (0, 0.5, 0.5, 0);
|
||||||
|
/* blue, bottom left */
|
||||||
|
cogl_set_source_color4ub (0x00, 0x00, 0xff, 0xff);
|
||||||
|
cogl_rectangle (-0.5, 0, 0, -0.5);
|
||||||
|
/* white, bottom right */
|
||||||
|
cogl_set_source_color4ub (0xff, 0xff, 0xff, 0xff);
|
||||||
|
cogl_rectangle (0, 0, 0.5, -0.5);
|
||||||
|
|
||||||
|
cogl_pop_draw_buffer ();
|
||||||
|
|
||||||
|
cogl_set_source_texture (tex);
|
||||||
|
cogl_rectangle (-1, 1, 1, -1);
|
||||||
|
|
||||||
|
cogl_handle_unref (tex);
|
||||||
|
|
||||||
|
/* NB: The texture is drawn flipped horizontally and scaled to fit in the
|
||||||
|
* top right corner of the window. */
|
||||||
|
|
||||||
|
/* red, top right */
|
||||||
|
cogl_read_pixels (DRAW_BUFFER_WIDTH - 1, 0, 1, 1,
|
||||||
|
COGL_READ_PIXELS_COLOR_BUFFER,
|
||||||
|
COGL_PIXEL_FORMAT_RGBA_8888,
|
||||||
|
pixel);
|
||||||
|
g_assert (pixel[RED] == 0xff && pixel[GREEN] == 0x00 && pixel[BLUE] == 0x00);
|
||||||
|
|
||||||
|
/* green, top left */
|
||||||
|
cogl_read_pixels ((DRAW_BUFFER_WIDTH/2), 0, 1, 1,
|
||||||
|
COGL_READ_PIXELS_COLOR_BUFFER,
|
||||||
|
COGL_PIXEL_FORMAT_RGBA_8888,
|
||||||
|
pixel);
|
||||||
|
g_assert (pixel[RED] == 0x00 && pixel[GREEN] == 0xff && pixel[BLUE] == 0x00);
|
||||||
|
|
||||||
|
/* blue, bottom right */
|
||||||
|
cogl_read_pixels (DRAW_BUFFER_WIDTH - 1, (DRAW_BUFFER_HEIGHT/2) - 1, 1, 1,
|
||||||
|
COGL_READ_PIXELS_COLOR_BUFFER,
|
||||||
|
COGL_PIXEL_FORMAT_RGBA_8888,
|
||||||
|
pixel);
|
||||||
|
g_assert (pixel[RED] == 0x00 && pixel[GREEN] == 0x00 && pixel[BLUE] == 0xff);
|
||||||
|
|
||||||
|
/* white, bottom left */
|
||||||
|
cogl_read_pixels ((DRAW_BUFFER_WIDTH/2), (DRAW_BUFFER_HEIGHT/2) - 1, 1, 1,
|
||||||
|
COGL_READ_PIXELS_COLOR_BUFFER,
|
||||||
|
COGL_PIXEL_FORMAT_RGBA_8888,
|
||||||
|
pixel);
|
||||||
|
g_assert (pixel[RED] == 0xff && pixel[GREEN] == 0xff && pixel[BLUE] == 0xff);
|
||||||
|
|
||||||
|
/* Comment this out if you want visual feedback of what this test
|
||||||
|
* paints.
|
||||||
|
*/
|
||||||
|
clutter_main_quit ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
queue_redraw (gpointer stage)
|
||||||
|
{
|
||||||
|
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test_cogl_offscreen (TestConformSimpleFixture *fixture,
|
||||||
|
gconstpointer data)
|
||||||
|
{
|
||||||
|
guint idle_source;
|
||||||
|
ClutterActor *stage;
|
||||||
|
|
||||||
|
stage = clutter_stage_get_default ();
|
||||||
|
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
|
||||||
|
clutter_actor_set_size (stage, DRAW_BUFFER_WIDTH, DRAW_BUFFER_HEIGHT);
|
||||||
|
|
||||||
|
/* We force continuous redrawing of the stage, since we need to skip
|
||||||
|
* the first few frames, and we wont be doing anything else that
|
||||||
|
* will trigger redrawing. */
|
||||||
|
idle_source = g_idle_add (queue_redraw, stage);
|
||||||
|
g_signal_connect_after (stage, "paint", G_CALLBACK (on_paint), NULL);
|
||||||
|
|
||||||
|
clutter_actor_show (stage);
|
||||||
|
clutter_main ();
|
||||||
|
|
||||||
|
g_source_remove (idle_source);
|
||||||
|
|
||||||
|
/* Remove all of the actors from the stage */
|
||||||
|
clutter_container_foreach (CLUTTER_CONTAINER (stage),
|
||||||
|
(ClutterCallback) clutter_actor_destroy,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (g_test_verbose ())
|
||||||
|
g_print ("OK\n");
|
||||||
|
}
|
||||||
|
|
153
tests/conform/test-cogl-readpixels.c
Normal file
153
tests/conform/test-cogl-readpixels.c
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
|
||||||
|
#include <clutter/clutter.h>
|
||||||
|
#include <cogl/cogl.h>
|
||||||
|
|
||||||
|
#include "test-conform-common.h"
|
||||||
|
|
||||||
|
#define RED 0
|
||||||
|
#define GREEN 1
|
||||||
|
#define BLUE 2
|
||||||
|
|
||||||
|
#define DRAW_BUFFER_WIDTH 640
|
||||||
|
#define DRAW_BUFFER_HEIGHT 480
|
||||||
|
|
||||||
|
static const ClutterColor stage_color = { 0x0, 0x0, 0x0, 0xff };
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_paint (ClutterActor *actor, void *state)
|
||||||
|
{
|
||||||
|
float saved_viewport[4];
|
||||||
|
CoglMatrix saved_projection;
|
||||||
|
CoglMatrix projection;
|
||||||
|
CoglMatrix modelview;
|
||||||
|
guchar *data;
|
||||||
|
CoglHandle tex;
|
||||||
|
CoglHandle offscreen;
|
||||||
|
guint32 *pixels;
|
||||||
|
|
||||||
|
/* Save the Clutter viewport/matrices and load identity matrices */
|
||||||
|
|
||||||
|
cogl_get_viewport (saved_viewport);
|
||||||
|
cogl_get_projection_matrix (&saved_projection);
|
||||||
|
cogl_push_matrix ();
|
||||||
|
|
||||||
|
cogl_matrix_init_identity (&projection);
|
||||||
|
cogl_matrix_init_identity (&modelview);
|
||||||
|
|
||||||
|
cogl_set_projection_matrix (&projection);
|
||||||
|
cogl_set_modelview_matrix (&modelview);
|
||||||
|
|
||||||
|
/* All offscreen rendering is done upside down so the first thing we
|
||||||
|
* verify is reading back grid of colors from a CoglOffscreen draw buffer
|
||||||
|
*/
|
||||||
|
|
||||||
|
data = g_malloc (DRAW_BUFFER_WIDTH * 4 * DRAW_BUFFER_HEIGHT);
|
||||||
|
tex = cogl_texture_new_from_data (DRAW_BUFFER_WIDTH, DRAW_BUFFER_HEIGHT,
|
||||||
|
COGL_TEXTURE_NO_SLICING,
|
||||||
|
COGL_PIXEL_FORMAT_RGBA_8888, /* data fmt */
|
||||||
|
COGL_PIXEL_FORMAT_ANY, /* internal fmt */
|
||||||
|
DRAW_BUFFER_WIDTH * 4, /* rowstride */
|
||||||
|
data);
|
||||||
|
g_free (data);
|
||||||
|
offscreen = cogl_offscreen_new_to_texture (tex);
|
||||||
|
|
||||||
|
cogl_push_draw_buffer ();
|
||||||
|
cogl_set_draw_buffer (0 /* unused */, offscreen);
|
||||||
|
|
||||||
|
/* red, top left */
|
||||||
|
cogl_set_source_color4ub (0xff, 0x00, 0x00, 0xff);
|
||||||
|
cogl_rectangle (-1, 1, 0, 0);
|
||||||
|
/* green, top right */
|
||||||
|
cogl_set_source_color4ub (0x00, 0xff, 0x00, 0xff);
|
||||||
|
cogl_rectangle (0, 1, 1, 0);
|
||||||
|
/* blue, bottom left */
|
||||||
|
cogl_set_source_color4ub (0x00, 0x00, 0xff, 0xff);
|
||||||
|
cogl_rectangle (-1, 0, 0, -1);
|
||||||
|
/* white, bottom right */
|
||||||
|
cogl_set_source_color4ub (0xff, 0xff, 0xff, 0xff);
|
||||||
|
cogl_rectangle (0, 0, 1, -1);
|
||||||
|
|
||||||
|
pixels = g_malloc0 (DRAW_BUFFER_WIDTH * 4 * DRAW_BUFFER_HEIGHT);
|
||||||
|
cogl_read_pixels (0, 0, DRAW_BUFFER_WIDTH, DRAW_BUFFER_HEIGHT,
|
||||||
|
COGL_READ_PIXELS_COLOR_BUFFER,
|
||||||
|
COGL_PIXEL_FORMAT_RGBA_8888,
|
||||||
|
(guchar *)pixels);
|
||||||
|
|
||||||
|
g_assert (pixels[0] == 0xff0000ff);
|
||||||
|
g_assert (pixels[DRAW_BUFFER_WIDTH - 1] == 0xff00ff00);
|
||||||
|
g_assert (pixels[(DRAW_BUFFER_HEIGHT - 1) * DRAW_BUFFER_WIDTH] == 0xffff0000);
|
||||||
|
g_assert (pixels[(DRAW_BUFFER_HEIGHT - 1) * DRAW_BUFFER_WIDTH +
|
||||||
|
DRAW_BUFFER_WIDTH - 1] == 0xffffffff);
|
||||||
|
g_free (pixels);
|
||||||
|
|
||||||
|
cogl_pop_draw_buffer ();
|
||||||
|
cogl_handle_unref (offscreen);
|
||||||
|
|
||||||
|
/* Now verify reading back from an onscreen draw buffer...
|
||||||
|
*/
|
||||||
|
|
||||||
|
cogl_set_source_texture (tex);
|
||||||
|
cogl_rectangle (-1, 1, 1, -1);
|
||||||
|
|
||||||
|
pixels = g_malloc0 (DRAW_BUFFER_WIDTH * 4 * DRAW_BUFFER_HEIGHT);
|
||||||
|
cogl_read_pixels (0, 0, DRAW_BUFFER_WIDTH, DRAW_BUFFER_HEIGHT,
|
||||||
|
COGL_READ_PIXELS_COLOR_BUFFER,
|
||||||
|
COGL_PIXEL_FORMAT_RGBA_8888,
|
||||||
|
(guchar *)pixels);
|
||||||
|
|
||||||
|
g_assert (pixels[0] == 0xff0000ff);
|
||||||
|
g_assert (pixels[DRAW_BUFFER_WIDTH - 1] == 0xff00ff00);
|
||||||
|
g_assert (pixels[(DRAW_BUFFER_HEIGHT - 1) * DRAW_BUFFER_WIDTH] == 0xffff0000);
|
||||||
|
g_assert (pixels[(DRAW_BUFFER_HEIGHT - 1) * DRAW_BUFFER_WIDTH +
|
||||||
|
DRAW_BUFFER_WIDTH - 1] == 0xffffffff);
|
||||||
|
g_free (pixels);
|
||||||
|
|
||||||
|
cogl_handle_unref (tex);
|
||||||
|
|
||||||
|
|
||||||
|
/* Comment this out if you want visual feedback of what this test
|
||||||
|
* paints.
|
||||||
|
*/
|
||||||
|
clutter_main_quit ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
queue_redraw (gpointer stage)
|
||||||
|
{
|
||||||
|
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test_cogl_readpixels (TestConformSimpleFixture *fixture,
|
||||||
|
gconstpointer data)
|
||||||
|
{
|
||||||
|
guint idle_source;
|
||||||
|
ClutterActor *stage;
|
||||||
|
|
||||||
|
stage = clutter_stage_get_default ();
|
||||||
|
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
|
||||||
|
clutter_actor_set_size (stage, DRAW_BUFFER_WIDTH, DRAW_BUFFER_HEIGHT);
|
||||||
|
|
||||||
|
/* We force continuous redrawing of the stage, since we need to skip
|
||||||
|
* the first few frames, and we wont be doing anything else that
|
||||||
|
* will trigger redrawing. */
|
||||||
|
idle_source = g_idle_add (queue_redraw, stage);
|
||||||
|
g_signal_connect_after (stage, "paint", G_CALLBACK (on_paint), NULL);
|
||||||
|
|
||||||
|
clutter_actor_show (stage);
|
||||||
|
clutter_main ();
|
||||||
|
|
||||||
|
g_source_remove (idle_source);
|
||||||
|
|
||||||
|
/* Remove all of the actors from the stage */
|
||||||
|
clutter_container_foreach (CLUTTER_CONTAINER (stage),
|
||||||
|
(ClutterCallback) clutter_actor_destroy,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (g_test_verbose ())
|
||||||
|
g_print ("OK\n");
|
||||||
|
}
|
||||||
|
|
417
tests/conform/test-cogl-viewport.c
Normal file
417
tests/conform/test-cogl-viewport.c
Normal file
@ -0,0 +1,417 @@
|
|||||||
|
|
||||||
|
#include <clutter/clutter.h>
|
||||||
|
#include <cogl/cogl.h>
|
||||||
|
|
||||||
|
#include "test-conform-common.h"
|
||||||
|
|
||||||
|
#define RED 0
|
||||||
|
#define GREEN 1
|
||||||
|
#define BLUE 2
|
||||||
|
#define ALPHA 3
|
||||||
|
|
||||||
|
#define DRAW_BUFFER_WIDTH 640
|
||||||
|
#define DRAW_BUFFER_HEIGHT 480
|
||||||
|
|
||||||
|
static const ClutterColor stage_color = { 0x0, 0x0, 0x0, 0xff };
|
||||||
|
|
||||||
|
static void
|
||||||
|
assert_region_color (int x,
|
||||||
|
int y,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
guint8 red,
|
||||||
|
guint8 green,
|
||||||
|
guint8 blue,
|
||||||
|
guint8 alpha)
|
||||||
|
{
|
||||||
|
guint8 *data = g_malloc0 (width * height * 4);
|
||||||
|
cogl_read_pixels (x, y, width, height,
|
||||||
|
COGL_READ_PIXELS_COLOR_BUFFER,
|
||||||
|
COGL_PIXEL_FORMAT_RGBA_8888,
|
||||||
|
data);
|
||||||
|
for (y = 0; y < height; y++)
|
||||||
|
for (x = 0; x < width; x++)
|
||||||
|
{
|
||||||
|
guint8 *pixel = &data[y*width*4 + x*4];
|
||||||
|
#if 1
|
||||||
|
g_assert (pixel[RED] == red &&
|
||||||
|
pixel[GREEN] == green &&
|
||||||
|
pixel[BLUE] == blue &&
|
||||||
|
pixel[ALPHA] == alpha);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
g_free (data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
assert_rectangle_color_and_black_border (int x,
|
||||||
|
int y,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
guint8 red,
|
||||||
|
guint8 green,
|
||||||
|
guint8 blue)
|
||||||
|
{
|
||||||
|
/* check the rectangle itself... */
|
||||||
|
assert_region_color (x, y, width, height, red, green, blue, 0xff);
|
||||||
|
/* black to left of the rectangle */
|
||||||
|
assert_region_color (x-10, y-10, 10, height+20, 0x00, 0x00, 0x00, 0xff);
|
||||||
|
/* black to right of the rectangle */
|
||||||
|
assert_region_color (x+width, y-10, 10, height+20, 0x00, 0x00, 0x00, 0xff);
|
||||||
|
/* black above the rectangle */
|
||||||
|
assert_region_color (x-10, y-10, width+20, 10, 0x00, 0x00, 0x00, 0xff);
|
||||||
|
/* and black below the rectangle */
|
||||||
|
assert_region_color (x-10, y+height, width+20, 10, 0x00, 0x00, 0x00, 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_paint (ClutterActor *actor, void *state)
|
||||||
|
{
|
||||||
|
float saved_viewport[4];
|
||||||
|
CoglMatrix saved_projection;
|
||||||
|
CoglMatrix projection;
|
||||||
|
CoglMatrix modelview;
|
||||||
|
guchar *data;
|
||||||
|
CoglHandle tex;
|
||||||
|
CoglHandle offscreen;
|
||||||
|
CoglColor black;
|
||||||
|
float x0;
|
||||||
|
float y0;
|
||||||
|
float width;
|
||||||
|
float height;
|
||||||
|
|
||||||
|
/* for clearing the offscreen draw buffer to black... */
|
||||||
|
cogl_color_set_from_4ub (&black, 0x00, 0x00, 0x00, 0xff);
|
||||||
|
|
||||||
|
cogl_get_viewport (saved_viewport);
|
||||||
|
cogl_get_projection_matrix (&saved_projection);
|
||||||
|
cogl_push_matrix ();
|
||||||
|
|
||||||
|
cogl_matrix_init_identity (&projection);
|
||||||
|
cogl_matrix_init_identity (&modelview);
|
||||||
|
|
||||||
|
cogl_set_projection_matrix (&projection);
|
||||||
|
cogl_set_modelview_matrix (&modelview);
|
||||||
|
|
||||||
|
/* - Create a 100x200 viewport (i.e. smaller than the onscreen draw buffer)
|
||||||
|
* and position it a (20, 10) inside the draw buffer.
|
||||||
|
* - Fill the whole viewport with a purple rectangle
|
||||||
|
* - Verify that the draw buffer is black with a 100x200 purple rectangle at
|
||||||
|
* (20, 10)
|
||||||
|
*/
|
||||||
|
cogl_set_viewport (20, /* x */
|
||||||
|
10, /* y */
|
||||||
|
100, /* width */
|
||||||
|
200); /* height */
|
||||||
|
/* clear everything... */
|
||||||
|
cogl_clear (&black, COGL_BUFFER_BIT_COLOR);
|
||||||
|
/* fill the viewport with purple.. */
|
||||||
|
cogl_set_source_color4ub (0xff, 0x00, 0xff, 0xff);
|
||||||
|
cogl_rectangle (-1, 1, 1, -1);
|
||||||
|
assert_rectangle_color_and_black_border (20, 10, 100, 200,
|
||||||
|
0xff, 0x00, 0xff);
|
||||||
|
|
||||||
|
|
||||||
|
/* - Create a viewport twice the size of the onscreen draw buffer with
|
||||||
|
* a negative offset positioning it at (-20, -10) relative to the
|
||||||
|
* buffer itself.
|
||||||
|
* - Draw a 100x200 green rectangle at (40, 20) within the viewport (which
|
||||||
|
* is (20, 10) within the draw buffer)
|
||||||
|
* - Verify that the draw buffer is black with a 100x200 green rectangle at
|
||||||
|
* (20, 10)
|
||||||
|
*/
|
||||||
|
cogl_set_viewport (-20, /* x */
|
||||||
|
-10, /* y */
|
||||||
|
DRAW_BUFFER_WIDTH * 2, /* width */
|
||||||
|
DRAW_BUFFER_HEIGHT * 2); /* height */
|
||||||
|
/* clear everything... */
|
||||||
|
cogl_clear (&black, COGL_BUFFER_BIT_COLOR);
|
||||||
|
/* draw a 100x200 green rectangle offset into the viewport such that its
|
||||||
|
* top left corner should be found at (20, 10) in the offscreen buffer */
|
||||||
|
/* (offset 40 pixels right from the left of the viewport) */
|
||||||
|
x0 = -1.0f + (1.0f / DRAW_BUFFER_WIDTH) * 40.f;
|
||||||
|
/* (offset 20 pixels down from the top of the viewport) */
|
||||||
|
y0 = 1.0f - (1.0f / DRAW_BUFFER_HEIGHT) * 20.0f;
|
||||||
|
width = (1.0f / DRAW_BUFFER_WIDTH) * 100;
|
||||||
|
height = (1.0f / DRAW_BUFFER_HEIGHT) * 200;
|
||||||
|
cogl_set_source_color4ub (0x00, 0xff, 0x00, 0xff);
|
||||||
|
cogl_rectangle (x0, y0, x0 + width, y0 - height);
|
||||||
|
assert_rectangle_color_and_black_border (20, 10, 100, 200,
|
||||||
|
0x00, 0xff, 0x00);
|
||||||
|
|
||||||
|
|
||||||
|
/* - Create a 200x400 viewport and position it a (20, 10) inside the draw
|
||||||
|
* buffer.
|
||||||
|
* - Push a 100x200 window space clip rectangle at (20, 10)
|
||||||
|
* - Fill the whole viewport with a blue rectangle
|
||||||
|
* - Verify that the draw buffer is black with a 100x200 blue rectangle at
|
||||||
|
* (20, 10)
|
||||||
|
*/
|
||||||
|
cogl_set_viewport (20, /* x */
|
||||||
|
10, /* y */
|
||||||
|
200, /* width */
|
||||||
|
400); /* height */
|
||||||
|
/* clear everything... */
|
||||||
|
cogl_clear (&black, COGL_BUFFER_BIT_COLOR);
|
||||||
|
cogl_clip_push_window_rect (20, 10, 100, 200);
|
||||||
|
/* fill the viewport with blue.. */
|
||||||
|
cogl_set_source_color4ub (0x00, 0x00, 0xff, 0xff);
|
||||||
|
cogl_rectangle (-1, 1, 1, -1);
|
||||||
|
cogl_clip_pop ();
|
||||||
|
assert_rectangle_color_and_black_border (20, 10, 100, 200,
|
||||||
|
0x00, 0x00, 0xff);
|
||||||
|
|
||||||
|
|
||||||
|
/* - Create a 200x400 viewport and position it a (20, 10) inside the draw
|
||||||
|
* buffer.
|
||||||
|
* - Push a 100x200 model space clip rectangle at (20, 10) in the viewport
|
||||||
|
* (i.e. (40, 20) inside the draw buffer)
|
||||||
|
* - Fill the whole viewport with a green rectangle
|
||||||
|
* - Verify that the draw buffer is black with a 100x200 green rectangle at
|
||||||
|
* (40, 20)
|
||||||
|
*/
|
||||||
|
cogl_set_viewport (20, /* x */
|
||||||
|
10, /* y */
|
||||||
|
200, /* width */
|
||||||
|
400); /* height */
|
||||||
|
/* clear everything... */
|
||||||
|
cogl_clear (&black, COGL_BUFFER_BIT_COLOR);
|
||||||
|
/* figure out where to position our clip rectangle in model space
|
||||||
|
* coordinates... */
|
||||||
|
/* (offset 40 pixels right from the left of the viewport) */
|
||||||
|
x0 = -1.0f + (2.0f / 200) * 20.f;
|
||||||
|
/* (offset 20 pixels down from the top of the viewport) */
|
||||||
|
y0 = 1.0f - (2.0f / 400) * 10.0f;
|
||||||
|
width = (2.0f / 200) * 100;
|
||||||
|
height = (2.0f / 400) * 200;
|
||||||
|
/* add the clip rectangle... */
|
||||||
|
cogl_push_matrix ();
|
||||||
|
cogl_translate (x0 + (width/2.0), y0 - (height/2.0), 0);
|
||||||
|
/* XXX: Rotate just enough to stop Cogl from converting our model space
|
||||||
|
* rectangle into a window space rectangle.. */
|
||||||
|
cogl_rotate (0.1, 0, 0, 1);
|
||||||
|
cogl_clip_push (-(width/2.0), -(height/2.0), width, height);
|
||||||
|
cogl_pop_matrix ();
|
||||||
|
/* fill the viewport with green.. */
|
||||||
|
cogl_set_source_color4ub (0x00, 0xff, 0x00, 0xff);
|
||||||
|
cogl_rectangle (-1, 1, 1, -1);
|
||||||
|
cogl_clip_pop ();
|
||||||
|
assert_rectangle_color_and_black_border (40, 20, 100, 200,
|
||||||
|
0x00, 0xff, 0x00);
|
||||||
|
|
||||||
|
|
||||||
|
/* Set the viewport to something specific so we can verify that it gets
|
||||||
|
* restored after we are done testing with an offscreen draw buffer... */
|
||||||
|
cogl_set_viewport (20, 10, 100, 200);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Next test offscreen drawing...
|
||||||
|
*/
|
||||||
|
cogl_push_draw_buffer ();
|
||||||
|
|
||||||
|
data = g_malloc (DRAW_BUFFER_WIDTH * 4 * DRAW_BUFFER_HEIGHT);
|
||||||
|
tex = cogl_texture_new_from_data (DRAW_BUFFER_WIDTH, DRAW_BUFFER_HEIGHT,
|
||||||
|
COGL_TEXTURE_NO_SLICING,
|
||||||
|
COGL_PIXEL_FORMAT_RGBA_8888, /* data fmt */
|
||||||
|
COGL_PIXEL_FORMAT_ANY, /* internal fmt */
|
||||||
|
DRAW_BUFFER_WIDTH * 4, /* rowstride */
|
||||||
|
data);
|
||||||
|
g_free (data);
|
||||||
|
offscreen = cogl_offscreen_new_to_texture (tex);
|
||||||
|
|
||||||
|
cogl_set_draw_buffer (0 /* unused */, offscreen);
|
||||||
|
|
||||||
|
|
||||||
|
/* - Create a 100x200 viewport (i.e. smaller than the offscreen draw buffer)
|
||||||
|
* and position it a (20, 10) inside the draw buffer.
|
||||||
|
* - Fill the whole viewport with a blue rectangle
|
||||||
|
* - Verify that the draw buffer is black with a 100x200 blue rectangle at
|
||||||
|
* (20, 10)
|
||||||
|
*/
|
||||||
|
cogl_set_viewport (20, /* x */
|
||||||
|
10, /* y */
|
||||||
|
100, /* width */
|
||||||
|
200); /* height */
|
||||||
|
/* clear everything... */
|
||||||
|
cogl_clear (&black, COGL_BUFFER_BIT_COLOR);
|
||||||
|
/* fill the viewport with blue.. */
|
||||||
|
cogl_set_source_color4ub (0x00, 0x00, 0xff, 0xff);
|
||||||
|
cogl_rectangle (-1, 1, 1, -1);
|
||||||
|
assert_rectangle_color_and_black_border (20, 10, 100, 200,
|
||||||
|
0x00, 0x00, 0xff);
|
||||||
|
|
||||||
|
|
||||||
|
/* - Create a viewport twice the size of the offscreen draw buffer with
|
||||||
|
* a negative offset positioning it at (-20, -10) relative to the
|
||||||
|
* buffer itself.
|
||||||
|
* - Draw a 100x200 red rectangle at (40, 20) within the viewport (which
|
||||||
|
* is (20, 10) within the draw buffer)
|
||||||
|
* - Verify that the draw buffer is black with a 100x200 red rectangle at
|
||||||
|
* (20, 10)
|
||||||
|
*/
|
||||||
|
cogl_set_viewport (-20, /* x */
|
||||||
|
-10, /* y */
|
||||||
|
DRAW_BUFFER_WIDTH * 2, /* width */
|
||||||
|
DRAW_BUFFER_HEIGHT * 2); /* height */
|
||||||
|
/* clear everything... */
|
||||||
|
cogl_clear (&black, COGL_BUFFER_BIT_COLOR);
|
||||||
|
/* draw a 100x200 red rectangle offset into the viewport such that its
|
||||||
|
* top left corner should be found at (20, 10) in the offscreen buffer */
|
||||||
|
/* (offset 40 pixels right from the left of the viewport) */
|
||||||
|
x0 = -1.0f + (1.0f / DRAW_BUFFER_WIDTH) * 40.f;
|
||||||
|
/* (offset 20 pixels down from the top of the viewport) */
|
||||||
|
y0 = 1.0f - (1.0f / DRAW_BUFFER_HEIGHT) * 20.0f;
|
||||||
|
width = (1.0f / DRAW_BUFFER_WIDTH) * 100;
|
||||||
|
height = (1.0f / DRAW_BUFFER_HEIGHT) * 200;
|
||||||
|
cogl_set_source_color4ub (0xff, 0x00, 0x00, 0xff);
|
||||||
|
cogl_rectangle (x0, y0, x0 + width, y0 - height);
|
||||||
|
assert_rectangle_color_and_black_border (20, 10, 100, 200,
|
||||||
|
0xff, 0x00, 0x00);
|
||||||
|
|
||||||
|
|
||||||
|
/* - Create a 200x400 viewport and position it a (20, 10) inside the draw
|
||||||
|
* buffer.
|
||||||
|
* - Push a 100x200 window space clip rectangle at (20, 10)
|
||||||
|
* - Fill the whole viewport with a blue rectangle
|
||||||
|
* - Verify that the draw buffer is black with a 100x200 blue rectangle at
|
||||||
|
* (20, 10)
|
||||||
|
*/
|
||||||
|
cogl_set_viewport (20, /* x */
|
||||||
|
10, /* y */
|
||||||
|
200, /* width */
|
||||||
|
400); /* height */
|
||||||
|
/* clear everything... */
|
||||||
|
cogl_clear (&black, COGL_BUFFER_BIT_COLOR);
|
||||||
|
cogl_clip_push_window_rect (20, 10, 100, 200);
|
||||||
|
/* fill the viewport with blue.. */
|
||||||
|
cogl_set_source_color4ub (0x00, 0x00, 0xff, 0xff);
|
||||||
|
cogl_rectangle (-1, 1, 1, -1);
|
||||||
|
cogl_clip_pop ();
|
||||||
|
assert_rectangle_color_and_black_border (20, 10, 100, 200,
|
||||||
|
0x00, 0x00, 0xff);
|
||||||
|
|
||||||
|
|
||||||
|
/* - Create a 200x400 viewport and position it a (20, 10) inside the draw
|
||||||
|
* buffer.
|
||||||
|
* - Push a 100x200 model space clip rectangle at (20, 10) in the viewport
|
||||||
|
* (i.e. (40, 20) inside the draw buffer)
|
||||||
|
* - Fill the whole viewport with a green rectangle
|
||||||
|
* - Verify that the draw buffer is black with a 100x200 green rectangle at
|
||||||
|
* (40, 20)
|
||||||
|
*/
|
||||||
|
cogl_set_viewport (20, /* x */
|
||||||
|
10, /* y */
|
||||||
|
200, /* width */
|
||||||
|
400); /* height */
|
||||||
|
/* clear everything... */
|
||||||
|
cogl_clear (&black, COGL_BUFFER_BIT_COLOR);
|
||||||
|
/* figure out where to position our clip rectangle in model space
|
||||||
|
* coordinates... */
|
||||||
|
/* (offset 40 pixels right from the left of the viewport) */
|
||||||
|
x0 = -1.0f + (2.0f / 200) * 20.f;
|
||||||
|
/* (offset 20 pixels down from the top of the viewport) */
|
||||||
|
y0 = 1.0f - (2.0f / 400) * 10.0f;
|
||||||
|
width = (2.0f / 200) * 100;
|
||||||
|
height = (2.0f / 400) * 200;
|
||||||
|
/* add the clip rectangle... */
|
||||||
|
cogl_push_matrix ();
|
||||||
|
cogl_translate (x0 + (width/2.0), y0 - (height/2.0), 0);
|
||||||
|
/* XXX: Rotate just enough to stop Cogl from converting our model space
|
||||||
|
* rectangle into a window space rectangle.. */
|
||||||
|
cogl_rotate (0.1, 0, 0, 1);
|
||||||
|
cogl_clip_push (-(width/2.0), -(height/2.0), width, height);
|
||||||
|
cogl_pop_matrix ();
|
||||||
|
/* fill the viewport with green.. */
|
||||||
|
cogl_set_source_color4ub (0x00, 0xff, 0x00, 0xff);
|
||||||
|
cogl_rectangle (-1, 1, 1, -1);
|
||||||
|
cogl_clip_pop ();
|
||||||
|
assert_rectangle_color_and_black_border (40, 20, 100, 200,
|
||||||
|
0x00, 0xff, 0x00);
|
||||||
|
|
||||||
|
|
||||||
|
/* Set the viewport to something obscure to verify that it gets
|
||||||
|
* replace when we switch back to the onscreen draw buffer... */
|
||||||
|
cogl_set_viewport (0, 0, 10, 10);
|
||||||
|
|
||||||
|
cogl_pop_draw_buffer ();
|
||||||
|
cogl_handle_unref (offscreen);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Verify that the previous onscreen draw buffer's viewport was restored
|
||||||
|
* by drawing a white rectangle across the whole viewport. This should
|
||||||
|
* draw a 100x200 rectangle at (20,10) relative to the onscreen draw
|
||||||
|
* buffer...
|
||||||
|
*/
|
||||||
|
cogl_clear (&black, COGL_BUFFER_BIT_COLOR);
|
||||||
|
cogl_set_source_color4ub (0xff, 0xff, 0xff, 0xff);
|
||||||
|
cogl_rectangle (-1, 1, 1, -1);
|
||||||
|
assert_rectangle_color_and_black_border (20, 10, 100, 200,
|
||||||
|
0xff, 0xff, 0xff);
|
||||||
|
|
||||||
|
|
||||||
|
/* Uncomment to display the last contents of the offscreen draw buffer */
|
||||||
|
#if 1
|
||||||
|
cogl_matrix_init_identity (&projection);
|
||||||
|
cogl_matrix_init_identity (&modelview);
|
||||||
|
cogl_set_viewport (0, 0, DRAW_BUFFER_WIDTH, DRAW_BUFFER_HEIGHT);
|
||||||
|
cogl_set_projection_matrix (&projection);
|
||||||
|
cogl_set_modelview_matrix (&modelview);
|
||||||
|
cogl_set_source_texture (tex);
|
||||||
|
cogl_rectangle (-1, 1, 1, -1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
cogl_handle_unref (tex);
|
||||||
|
|
||||||
|
/* Finally restore the stage's original state... */
|
||||||
|
cogl_pop_matrix ();
|
||||||
|
cogl_set_projection_matrix (&saved_projection);
|
||||||
|
cogl_set_viewport (saved_viewport[0], saved_viewport[1],
|
||||||
|
saved_viewport[2], saved_viewport[3]);
|
||||||
|
|
||||||
|
|
||||||
|
/* Comment this out if you want visual feedback of what this test
|
||||||
|
* paints.
|
||||||
|
*/
|
||||||
|
clutter_main_quit ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
queue_redraw (gpointer stage)
|
||||||
|
{
|
||||||
|
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test_cogl_viewport (TestConformSimpleFixture *fixture,
|
||||||
|
gconstpointer data)
|
||||||
|
{
|
||||||
|
guint idle_source;
|
||||||
|
ClutterActor *stage;
|
||||||
|
|
||||||
|
stage = clutter_stage_get_default ();
|
||||||
|
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
|
||||||
|
clutter_actor_set_size (stage, DRAW_BUFFER_WIDTH, DRAW_BUFFER_HEIGHT);
|
||||||
|
|
||||||
|
/* We force continuous redrawing of the stage, since we need to skip
|
||||||
|
* the first few frames, and we wont be doing anything else that
|
||||||
|
* will trigger redrawing. */
|
||||||
|
idle_source = g_idle_add (queue_redraw, stage);
|
||||||
|
g_signal_connect_after (stage, "paint", G_CALLBACK (on_paint), NULL);
|
||||||
|
|
||||||
|
clutter_actor_show (stage);
|
||||||
|
clutter_main ();
|
||||||
|
|
||||||
|
g_source_remove (idle_source);
|
||||||
|
|
||||||
|
/* Remove all of the actors from the stage */
|
||||||
|
clutter_container_foreach (CLUTTER_CONTAINER (stage),
|
||||||
|
(ClutterCallback) clutter_actor_destroy,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (g_test_verbose ())
|
||||||
|
g_print ("OK\n");
|
||||||
|
}
|
||||||
|
|
@ -147,6 +147,7 @@ main (int argc, char **argv)
|
|||||||
TEST_CONFORM_SIMPLE ("/texture", test_backface_culling);
|
TEST_CONFORM_SIMPLE ("/texture", test_backface_culling);
|
||||||
TEST_CONFORM_SIMPLE ("/texture", test_npot_texture);
|
TEST_CONFORM_SIMPLE ("/texture", test_npot_texture);
|
||||||
TEST_CONFORM_SIMPLE ("/texture", test_premult);
|
TEST_CONFORM_SIMPLE ("/texture", test_premult);
|
||||||
|
TEST_CONFORM_SIMPLE ("/texture", test_texture_fbo);
|
||||||
|
|
||||||
TEST_CONFORM_SIMPLE ("/path", test_path);
|
TEST_CONFORM_SIMPLE ("/path", test_path);
|
||||||
|
|
||||||
@ -174,5 +175,9 @@ main (int argc, char **argv)
|
|||||||
TEST_CONFORM_SIMPLE ("/sizing", test_fixed_size);
|
TEST_CONFORM_SIMPLE ("/sizing", test_fixed_size);
|
||||||
TEST_CONFORM_SIMPLE ("/sizing", test_preferred_size);
|
TEST_CONFORM_SIMPLE ("/sizing", test_preferred_size);
|
||||||
|
|
||||||
|
TEST_CONFORM_SIMPLE ("/cogl", test_cogl_viewport);
|
||||||
|
TEST_CONFORM_SIMPLE ("/cogl", test_cogl_offscreen);
|
||||||
|
TEST_CONFORM_SIMPLE ("/cogl", test_cogl_readpixels);
|
||||||
|
|
||||||
return g_test_run ();
|
return g_test_run ();
|
||||||
}
|
}
|
||||||
|
255
tests/conform/test-texture-fbo.c
Normal file
255
tests/conform/test-texture-fbo.c
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
|
||||||
|
#include <clutter/clutter.h>
|
||||||
|
#include <cogl/cogl.h>
|
||||||
|
|
||||||
|
#include "test-conform-common.h"
|
||||||
|
|
||||||
|
#define SOURCE_SIZE 32
|
||||||
|
#define SOURCE_DIVISIONS_X 2
|
||||||
|
#define SOURCE_DIVISIONS_Y 2
|
||||||
|
#define DIVISION_WIDTH (SOURCE_SIZE / SOURCE_DIVISIONS_X)
|
||||||
|
#define DIVISION_HEIGHT (SOURCE_SIZE / SOURCE_DIVISIONS_Y)
|
||||||
|
|
||||||
|
static const ClutterColor
|
||||||
|
corner_colors[SOURCE_DIVISIONS_X * SOURCE_DIVISIONS_Y] =
|
||||||
|
{
|
||||||
|
{ 0xff, 0x00, 0x00, 0xff }, /* red top left */
|
||||||
|
{ 0x00, 0xff, 0x00, 0xff }, /* green top right */
|
||||||
|
{ 0x00, 0x00, 0xff, 0xff }, /* blue bottom left */
|
||||||
|
{ 0xff, 0x00, 0xff, 0xff } /* purple bottom right */
|
||||||
|
};
|
||||||
|
|
||||||
|
static const ClutterColor stage_color = { 0x0, 0x0, 0x0, 0xff };
|
||||||
|
|
||||||
|
typedef struct _TestState
|
||||||
|
{
|
||||||
|
ClutterActor *stage;
|
||||||
|
guint frame;
|
||||||
|
} TestState;
|
||||||
|
|
||||||
|
static ClutterActor *
|
||||||
|
create_source (void)
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
ClutterActor *group = clutter_group_new ();
|
||||||
|
|
||||||
|
/* Create a group with a different coloured rectangle at each
|
||||||
|
corner */
|
||||||
|
for (y = 0; y < SOURCE_DIVISIONS_Y; y++)
|
||||||
|
for (x = 0; x < SOURCE_DIVISIONS_X; x++)
|
||||||
|
{
|
||||||
|
ClutterActor *rect = clutter_rectangle_new ();
|
||||||
|
clutter_actor_set_size (rect, DIVISION_WIDTH, DIVISION_HEIGHT);
|
||||||
|
clutter_actor_set_position (rect,
|
||||||
|
DIVISION_WIDTH * x,
|
||||||
|
DIVISION_HEIGHT * y);
|
||||||
|
clutter_rectangle_set_color (CLUTTER_RECTANGLE (rect),
|
||||||
|
corner_colors +
|
||||||
|
(y * SOURCE_DIVISIONS_X + x));
|
||||||
|
clutter_container_add (CLUTTER_CONTAINER (group), rect, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pre_paint_clip_cb (void)
|
||||||
|
{
|
||||||
|
/* Generate a clip path that clips out the top left division */
|
||||||
|
cogl_path_move_to (DIVISION_WIDTH, 0);
|
||||||
|
cogl_path_line_to (SOURCE_SIZE, 0);
|
||||||
|
cogl_path_line_to (SOURCE_SIZE, SOURCE_SIZE);
|
||||||
|
cogl_path_line_to (0, SOURCE_SIZE);
|
||||||
|
cogl_path_line_to (0, DIVISION_HEIGHT);
|
||||||
|
cogl_path_line_to (DIVISION_WIDTH, DIVISION_HEIGHT);
|
||||||
|
cogl_path_close ();
|
||||||
|
cogl_clip_push_from_path ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
post_paint_clip_cb (void)
|
||||||
|
{
|
||||||
|
cogl_clip_pop ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
validate_part (TestState *state,
|
||||||
|
int xpos, int ypos,
|
||||||
|
int clip_flags)
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
gboolean pass = TRUE;
|
||||||
|
|
||||||
|
/* Check whether the center of each division is the right color */
|
||||||
|
for (y = 0; y < SOURCE_DIVISIONS_Y; y++)
|
||||||
|
for (x = 0; x < SOURCE_DIVISIONS_X; x++)
|
||||||
|
{
|
||||||
|
guchar *pixels;
|
||||||
|
const ClutterColor *correct_color;
|
||||||
|
|
||||||
|
/* Read the center pixels of this division */
|
||||||
|
pixels = clutter_stage_read_pixels (CLUTTER_STAGE (state->stage),
|
||||||
|
x * DIVISION_WIDTH +
|
||||||
|
DIVISION_WIDTH / 2 + xpos,
|
||||||
|
y * DIVISION_HEIGHT +
|
||||||
|
DIVISION_HEIGHT / 2 + ypos,
|
||||||
|
1, 1);
|
||||||
|
|
||||||
|
/* If this division is clipped then it should be the stage
|
||||||
|
color */
|
||||||
|
if ((clip_flags & (1 << ((y * SOURCE_DIVISIONS_X) + x))))
|
||||||
|
correct_color = &stage_color;
|
||||||
|
else
|
||||||
|
/* Otherwise it should be the color for this division */
|
||||||
|
correct_color = corner_colors + (y * SOURCE_DIVISIONS_X) + x;
|
||||||
|
|
||||||
|
if (pixels == NULL ||
|
||||||
|
pixels[0] != correct_color->red ||
|
||||||
|
pixels[1] != correct_color->green ||
|
||||||
|
pixels[2] != correct_color->blue)
|
||||||
|
pass = FALSE;
|
||||||
|
|
||||||
|
g_free (pixels);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pass;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
validate_result (TestState *state)
|
||||||
|
{
|
||||||
|
int ypos = 0;
|
||||||
|
|
||||||
|
if (g_test_verbose ())
|
||||||
|
g_print ("Testing onscreen clone...\n");
|
||||||
|
g_assert (validate_part (state, SOURCE_SIZE, ypos * SOURCE_SIZE, 0));
|
||||||
|
ypos++;
|
||||||
|
|
||||||
|
#if 0 /* this doesn't work */
|
||||||
|
if (g_test_verbose ())
|
||||||
|
g_print ("Testing offscreen clone...\n");
|
||||||
|
g_assert (validate_part (state, SOURCE_SIZE, ypos * SOURCE_SIZE, 0));
|
||||||
|
#endif
|
||||||
|
ypos++;
|
||||||
|
|
||||||
|
if (g_test_verbose ())
|
||||||
|
g_print ("Testing onscreen clone with rectangular clip...\n");
|
||||||
|
g_assert (validate_part (state, SOURCE_SIZE, ypos * SOURCE_SIZE, ~1));
|
||||||
|
ypos++;
|
||||||
|
|
||||||
|
if (g_test_verbose ())
|
||||||
|
g_print ("Testing onscreen clone with path clip...\n");
|
||||||
|
g_assert (validate_part (state, SOURCE_SIZE, ypos * SOURCE_SIZE, 1));
|
||||||
|
ypos++;
|
||||||
|
|
||||||
|
/* Comment this out if you want visual feedback of what this test
|
||||||
|
* paints.
|
||||||
|
*/
|
||||||
|
clutter_main_quit ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_paint (ClutterActor *actor, TestState *state)
|
||||||
|
{
|
||||||
|
int frame_num;
|
||||||
|
|
||||||
|
/* XXX: Experiments have shown that for some buggy drivers, when using
|
||||||
|
* glReadPixels there is some kind of race, so we delay our test for a
|
||||||
|
* few frames and a few seconds:
|
||||||
|
*/
|
||||||
|
/* Need to increment frame first because clutter_stage_read_pixels
|
||||||
|
fires a redraw */
|
||||||
|
frame_num = state->frame++;
|
||||||
|
if (frame_num == 2)
|
||||||
|
validate_result (state);
|
||||||
|
else if (frame_num < 2)
|
||||||
|
g_usleep (G_USEC_PER_SEC);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
queue_redraw (gpointer stage)
|
||||||
|
{
|
||||||
|
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test_texture_fbo (TestConformSimpleFixture *fixture,
|
||||||
|
gconstpointer data)
|
||||||
|
{
|
||||||
|
TestState state;
|
||||||
|
guint idle_source;
|
||||||
|
ClutterActor *actor;
|
||||||
|
int ypos = 0;
|
||||||
|
|
||||||
|
state.frame = 0;
|
||||||
|
|
||||||
|
state.stage = clutter_stage_get_default ();
|
||||||
|
|
||||||
|
clutter_stage_set_color (CLUTTER_STAGE (state.stage), &stage_color);
|
||||||
|
|
||||||
|
/* Onscreen source with clone next to it */
|
||||||
|
actor = create_source ();
|
||||||
|
clutter_container_add (CLUTTER_CONTAINER (state.stage), actor, NULL);
|
||||||
|
clutter_actor_set_position (actor, 0, ypos * SOURCE_SIZE);
|
||||||
|
actor = clutter_texture_new_from_actor (actor);
|
||||||
|
clutter_actor_set_position (actor, SOURCE_SIZE, ypos * SOURCE_SIZE);
|
||||||
|
clutter_container_add (CLUTTER_CONTAINER (state.stage), actor, NULL);
|
||||||
|
ypos++;
|
||||||
|
|
||||||
|
/* Offscreen source with clone */
|
||||||
|
#if 0 /* this doesn't work */
|
||||||
|
actor = create_source ();
|
||||||
|
actor = clutter_texture_new_from_actor (actor);
|
||||||
|
clutter_actor_set_position (actor, SOURCE_SIZE, ypos * SOURCE_SIZE);
|
||||||
|
clutter_container_add (CLUTTER_CONTAINER (state.stage), actor, NULL);
|
||||||
|
#endif
|
||||||
|
ypos++;
|
||||||
|
|
||||||
|
/* Source clipped to the top left division */
|
||||||
|
actor = create_source ();
|
||||||
|
clutter_container_add (CLUTTER_CONTAINER (state.stage), actor, NULL);
|
||||||
|
clutter_actor_set_position (actor, 0, ypos * SOURCE_SIZE);
|
||||||
|
clutter_actor_set_clip (actor, 0, 0, DIVISION_WIDTH, DIVISION_HEIGHT);
|
||||||
|
actor = clutter_texture_new_from_actor (actor);
|
||||||
|
clutter_actor_set_position (actor, SOURCE_SIZE, ypos * SOURCE_SIZE);
|
||||||
|
clutter_container_add (CLUTTER_CONTAINER (state.stage), actor, NULL);
|
||||||
|
ypos++;
|
||||||
|
|
||||||
|
/* Source clipped to everything but top left division using a
|
||||||
|
path */
|
||||||
|
actor = create_source ();
|
||||||
|
clutter_container_add (CLUTTER_CONTAINER (state.stage), actor, NULL);
|
||||||
|
clutter_actor_set_position (actor, 0, ypos * SOURCE_SIZE);
|
||||||
|
g_signal_connect (actor, "paint",
|
||||||
|
G_CALLBACK (pre_paint_clip_cb), NULL);
|
||||||
|
g_signal_connect_after (actor, "paint",
|
||||||
|
G_CALLBACK (post_paint_clip_cb), NULL);
|
||||||
|
actor = clutter_texture_new_from_actor (actor);
|
||||||
|
clutter_actor_set_position (actor, SOURCE_SIZE, ypos * SOURCE_SIZE);
|
||||||
|
clutter_container_add (CLUTTER_CONTAINER (state.stage), actor, NULL);
|
||||||
|
ypos++;
|
||||||
|
|
||||||
|
/* We force continuous redrawing of the stage, since we need to skip
|
||||||
|
* the first few frames, and we wont be doing anything else that
|
||||||
|
* will trigger redrawing. */
|
||||||
|
idle_source = g_idle_add (queue_redraw, state.stage);
|
||||||
|
|
||||||
|
g_signal_connect_after (state.stage, "paint", G_CALLBACK (on_paint), &state);
|
||||||
|
|
||||||
|
clutter_actor_show_all (state.stage);
|
||||||
|
|
||||||
|
clutter_main ();
|
||||||
|
|
||||||
|
g_source_remove (idle_source);
|
||||||
|
|
||||||
|
/* Remove all of the actors from the stage */
|
||||||
|
clutter_container_foreach (CLUTTER_CONTAINER (state.stage),
|
||||||
|
(ClutterCallback) clutter_actor_destroy,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (g_test_verbose ())
|
||||||
|
g_print ("OK\n");
|
||||||
|
}
|
||||||
|
|
@ -1,25 +1,4 @@
|
|||||||
|
|
||||||
/*#define TEST_GROUP */
|
|
||||||
|
|
||||||
/* These variables are used instead of the standard GLSL variables on
|
|
||||||
GLES 2 */
|
|
||||||
#ifdef HAVE_COGL_GLES2
|
|
||||||
|
|
||||||
#define GLES2_VARS \
|
|
||||||
"precision mediump float;\n" \
|
|
||||||
"varying vec2 tex_coord;\n" \
|
|
||||||
"varying vec4 frag_color;\n"
|
|
||||||
#define TEX_COORD "tex_coord"
|
|
||||||
#define COLOR_VAR "frag_color"
|
|
||||||
|
|
||||||
#else /* HAVE_COGL_GLES2 */
|
|
||||||
|
|
||||||
#define GLES2_VARS ""
|
|
||||||
#define TEX_COORD "gl_TexCoord[0]"
|
|
||||||
#define COLOR_VAR "gl_Color"
|
|
||||||
|
|
||||||
#endif /* HAVE_COGL_GLES2 */
|
|
||||||
|
|
||||||
#include <clutter/clutter.h>
|
#include <clutter/clutter.h>
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@ -27,13 +6,16 @@
|
|||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <gmodule.h>
|
#include <gmodule.h>
|
||||||
|
|
||||||
ClutterActor*
|
#define STAGE_WIDTH 800
|
||||||
make_source(void)
|
#define STAGE_HEIGHT 600
|
||||||
{
|
|
||||||
ClutterActor *source, *actor;
|
|
||||||
GError *error = NULL;
|
|
||||||
|
|
||||||
ClutterColor yellow = {0xff, 0xff, 0x00, 0xff};
|
ClutterActor *
|
||||||
|
make_source (void)
|
||||||
|
{
|
||||||
|
ClutterActor *source, *actor;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
ClutterColor yellow = {0xff, 0xff, 0x00, 0xff};
|
||||||
|
|
||||||
source = clutter_group_new();
|
source = clutter_group_new();
|
||||||
actor = clutter_texture_new_from_file ("redhand.png", &error);
|
actor = clutter_texture_new_from_file ("redhand.png", &error);
|
||||||
@ -51,65 +33,17 @@ make_source(void)
|
|||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClutterShader*
|
G_MODULE_EXPORT int
|
||||||
make_shader(void)
|
test_fbo_main (int argc, char *argv[])
|
||||||
{
|
|
||||||
ClutterShader *shader;
|
|
||||||
GError *error = NULL;
|
|
||||||
|
|
||||||
shader = clutter_shader_new ();
|
|
||||||
clutter_shader_set_fragment_source (shader,
|
|
||||||
|
|
||||||
GLES2_VARS
|
|
||||||
"uniform float radius ;"
|
|
||||||
"uniform sampler2D rectTexture;"
|
|
||||||
"uniform float x_step, y_step;"
|
|
||||||
""
|
|
||||||
"void main()"
|
|
||||||
"{"
|
|
||||||
" vec4 color = texture2D(rectTexture, " TEX_COORD ".st);"
|
|
||||||
" float u;"
|
|
||||||
" float v;"
|
|
||||||
" int count = 1;"
|
|
||||||
" for (u=-radius;u<radius;u++)"
|
|
||||||
" for (v=-radius;v<radius;v++)"
|
|
||||||
" {"
|
|
||||||
" color += texture2D(rectTexture, "
|
|
||||||
" vec2(" TEX_COORD ".s + u"
|
|
||||||
" * 2.0 * x_step,"
|
|
||||||
" " TEX_COORD ".t + v"
|
|
||||||
" * 2.0 * y_step));"
|
|
||||||
" count ++;"
|
|
||||||
" }"
|
|
||||||
""
|
|
||||||
" gl_FragColor = color / float(count);"
|
|
||||||
" gl_FragColor = gl_FragColor * " COLOR_VAR ";"
|
|
||||||
"}",
|
|
||||||
-1
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!clutter_shader_compile (shader, &error))
|
|
||||||
{
|
|
||||||
fprintf (stderr, "shader compilation failed:\n%s", error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
return shader;
|
|
||||||
}
|
|
||||||
|
|
||||||
G_MODULE_EXPORT gint
|
|
||||||
test_fbo_main (gint argc, gchar *argv[])
|
|
||||||
{
|
{
|
||||||
ClutterColor blue = {0x33, 0x44, 0x55, 0xff};
|
ClutterColor blue = {0x33, 0x44, 0x55, 0xff};
|
||||||
|
|
||||||
ClutterActor *fbo;
|
ClutterActor *fbo;
|
||||||
ClutterActor *onscreen_source, *offscreen_source, *trans_source;
|
ClutterActor *onscreen_source;
|
||||||
ClutterActor *foo_source;
|
|
||||||
ClutterActor *stage;
|
ClutterActor *stage;
|
||||||
ClutterActor *clone;
|
ClutterAnimation *animation;
|
||||||
ClutterShader *shader;
|
int x_pos = 200;
|
||||||
gint padx, pady;
|
int y_pos = 100;
|
||||||
gint fbo_width, fbo_height;
|
|
||||||
|
|
||||||
clutter_init (&argc, &argv);
|
clutter_init (&argc, &argv);
|
||||||
|
|
||||||
@ -117,6 +51,7 @@ test_fbo_main (gint argc, gchar *argv[])
|
|||||||
g_error("This test requires CLUTTER_FEATURE_OFFSCREEN");
|
g_error("This test requires CLUTTER_FEATURE_OFFSCREEN");
|
||||||
|
|
||||||
stage = clutter_stage_get_default ();
|
stage = clutter_stage_get_default ();
|
||||||
|
clutter_actor_set_size (stage, STAGE_WIDTH, STAGE_HEIGHT);
|
||||||
clutter_stage_set_color (CLUTTER_STAGE (stage), &blue);
|
clutter_stage_set_color (CLUTTER_STAGE (stage), &blue);
|
||||||
|
|
||||||
/* Create the first source */
|
/* Create the first source */
|
||||||
@ -124,93 +59,34 @@ test_fbo_main (gint argc, gchar *argv[])
|
|||||||
clutter_actor_show_all (onscreen_source);
|
clutter_actor_show_all (onscreen_source);
|
||||||
clutter_group_add (stage, onscreen_source);
|
clutter_group_add (stage, onscreen_source);
|
||||||
|
|
||||||
/* Basic sizing for alignment */
|
y_pos = (STAGE_HEIGHT/2.0) -
|
||||||
fbo_width = clutter_actor_get_width (onscreen_source);
|
(clutter_actor_get_height (onscreen_source)/2.0);
|
||||||
fbo_height = clutter_actor_get_height (onscreen_source);
|
clutter_actor_set_position (onscreen_source, x_pos, y_pos);
|
||||||
padx = fbo_width + 10;
|
x_pos += clutter_actor_get_width (onscreen_source);
|
||||||
pady = fbo_height + 10;
|
|
||||||
clutter_actor_set_size (stage, padx*4, pady*2);
|
|
||||||
|
|
||||||
/* Second hand from fbo onscreen */
|
animation = clutter_actor_animate (onscreen_source,
|
||||||
|
CLUTTER_LINEAR,
|
||||||
|
5000, /* 1 second duration */
|
||||||
|
"rotation-angle-y", 360.0f,
|
||||||
|
NULL);
|
||||||
|
clutter_animation_set_loop (animation, TRUE);
|
||||||
|
|
||||||
|
/* Second hand = actor from onscreen_source */
|
||||||
if ((fbo = clutter_texture_new_from_actor (onscreen_source)) == NULL)
|
if ((fbo = clutter_texture_new_from_actor (onscreen_source)) == NULL)
|
||||||
g_error("onscreen fbo creation failed");
|
g_error("onscreen fbo creation failed");
|
||||||
|
|
||||||
clutter_actor_set_position (fbo, padx, 0);
|
clutter_actor_set_position (fbo, x_pos, y_pos);
|
||||||
|
x_pos += clutter_actor_get_width (fbo);
|
||||||
clutter_group_add (stage, fbo);
|
clutter_group_add (stage, fbo);
|
||||||
|
|
||||||
/* apply a shader to it */
|
/* Third hand = actor from Second hand */
|
||||||
shader = make_shader();
|
if ((fbo = clutter_texture_new_from_actor (fbo)) == NULL)
|
||||||
clutter_actor_set_shader (fbo, shader);
|
g_error("fbo from fbo creation failed");
|
||||||
clutter_actor_set_shader_param_float (fbo, "radius", 2.0);
|
|
||||||
clutter_actor_set_shader_param_float (fbo, "x_step",
|
|
||||||
1.0f / clutter_util_next_p2 (fbo_width));
|
|
||||||
clutter_actor_set_shader_param_float (fbo, "y_step",
|
|
||||||
1.0f / clutter_util_next_p2 (fbo_height));
|
|
||||||
|
|
||||||
/* Third from cloning the fbo texture */
|
clutter_actor_set_position (fbo, x_pos, y_pos);
|
||||||
clone = clutter_clone_new (fbo);
|
x_pos += clutter_actor_get_width (fbo);
|
||||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), clone);
|
|
||||||
clutter_actor_set_position (clone, padx*2, 0);
|
|
||||||
|
|
||||||
|
|
||||||
/* Forth - an offscreen source */
|
|
||||||
offscreen_source = make_source();
|
|
||||||
clutter_actor_show_all (offscreen_source); /* need to show() offscreen */
|
|
||||||
if ((fbo = clutter_texture_new_from_actor (offscreen_source)) == NULL)
|
|
||||||
g_error("offscreen fbo creation failed");
|
|
||||||
|
|
||||||
clutter_actor_set_position (fbo, padx*3, 0);
|
|
||||||
clutter_group_add (stage, fbo);
|
clutter_group_add (stage, fbo);
|
||||||
|
|
||||||
|
|
||||||
/* 5th transformed */
|
|
||||||
trans_source = make_source();
|
|
||||||
clutter_actor_show_all (trans_source); /* need to show() offscreen */
|
|
||||||
|
|
||||||
clutter_actor_set_scale (trans_source, 2.5, 2.5);
|
|
||||||
|
|
||||||
if ((fbo = clutter_texture_new_from_actor (trans_source)) == NULL)
|
|
||||||
g_error("transformed fbo creation failed");
|
|
||||||
|
|
||||||
clutter_actor_set_position (fbo, 0, pady);
|
|
||||||
clutter_group_add (stage, fbo);
|
|
||||||
|
|
||||||
|
|
||||||
/* 6th resized bigger, but after fbo creation */
|
|
||||||
trans_source = make_source();
|
|
||||||
clutter_actor_show_all (trans_source); /* need to show() offscreen */
|
|
||||||
|
|
||||||
if ((fbo = clutter_texture_new_from_actor (trans_source)) == NULL)
|
|
||||||
g_error("transformed fbo creation failed");
|
|
||||||
|
|
||||||
/* rotate after */
|
|
||||||
clutter_actor_move_anchor_point_from_gravity (trans_source,
|
|
||||||
CLUTTER_GRAVITY_CENTER);
|
|
||||||
clutter_actor_set_rotation (trans_source, CLUTTER_Z_AXIS, 90.0, 0, 0, 0);
|
|
||||||
|
|
||||||
clutter_actor_set_position (fbo, padx, pady);
|
|
||||||
clutter_group_add (stage, fbo);
|
|
||||||
|
|
||||||
|
|
||||||
/* non visual breaks */
|
|
||||||
foo_source = make_source();
|
|
||||||
g_object_ref_sink (foo_source);
|
|
||||||
|
|
||||||
clutter_actor_show_all (foo_source);
|
|
||||||
if ((fbo = clutter_texture_new_from_actor (foo_source)) == NULL)
|
|
||||||
g_error("foo fbo creation failed");
|
|
||||||
|
|
||||||
g_object_unref (foo_source); /* fbo should keep it around */
|
|
||||||
|
|
||||||
clutter_actor_set_position (fbo, padx*3, pady);
|
|
||||||
clutter_group_add (stage, fbo);
|
|
||||||
|
|
||||||
/* TODO:
|
|
||||||
* Check realize/unrealize
|
|
||||||
* get_pixbuf()
|
|
||||||
* set_rgba on fbo texture.
|
|
||||||
*/
|
|
||||||
|
|
||||||
clutter_actor_show_all (stage);
|
clutter_actor_show_all (stage);
|
||||||
clutter_main ();
|
clutter_main ();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user