2011-05-08 23:27:10 +00:00
|
|
|
/*
|
|
|
|
* Clutter.
|
|
|
|
*
|
|
|
|
* An OpenGL based 'interactive canvas' library.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2007,2008,2009,2010,2011 Intel Corporation.
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
* Authors:
|
|
|
|
* Matthew Allum
|
|
|
|
* Robert Bragg
|
|
|
|
* Neil Roberts
|
|
|
|
* Emmanuele Bassi
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2007-10-12 08:17:00 +00:00
|
|
|
#ifdef HAVE_CONFIG_H
|
2007-07-06 13:56:01 +00:00
|
|
|
#include "config.h"
|
2007-10-12 08:17:00 +00:00
|
|
|
#endif
|
2007-07-06 13:56:01 +00:00
|
|
|
|
2012-02-21 13:22:17 +00:00
|
|
|
#define CLUTTER_ENABLE_EXPERIMENTAL_API
|
|
|
|
|
Add a new GDK backend
This commit introduces a new flavour for Clutter, that uses GDK
for handling all window system specific interactions (except for
creating the cogl context, as cogl does not know about GDK), including
in particular events. This is not compatible with the X11 (glx)
flavour, and this is reflected by the different soname (libclutter-gdk-1.0.so),
as all X11 specific functions and classes are not available. If you
wish to be compatible, you should check for CLUTTER_WINDOWING_X11.
Other than that, this backend should be on feature parity with X11,
including XInput 2, XSettings and EMWH (with much, much less code)
https://bugzilla.gnome.org/show_bug.cgi?id=657434
2011-08-26 01:09:18 +00:00
|
|
|
#include "clutter-config.h"
|
|
|
|
|
2011-05-08 23:27:10 +00:00
|
|
|
#include "clutter-stage-cogl.h"
|
2007-07-06 13:56:01 +00:00
|
|
|
|
2011-11-04 16:52:44 +00:00
|
|
|
#include "clutter-actor-private.h"
|
|
|
|
#include "clutter-backend-private.h"
|
2010-10-21 10:29:09 +00:00
|
|
|
#include "clutter-debug.h"
|
|
|
|
#include "clutter-event.h"
|
|
|
|
#include "clutter-enum-types.h"
|
|
|
|
#include "clutter-feature.h"
|
|
|
|
#include "clutter-main.h"
|
|
|
|
#include "clutter-private.h"
|
|
|
|
#include "clutter-stage-private.h"
|
2007-07-06 13:56:01 +00:00
|
|
|
|
2008-04-23 17:20:59 +00:00
|
|
|
static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface);
|
|
|
|
|
2011-05-08 23:27:10 +00:00
|
|
|
G_DEFINE_TYPE_WITH_CODE (ClutterStageCogl,
|
|
|
|
_clutter_stage_cogl,
|
2010-02-27 09:42:42 +00:00
|
|
|
G_TYPE_OBJECT,
|
2008-04-23 17:20:59 +00:00
|
|
|
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW,
|
|
|
|
clutter_stage_window_iface_init));
|
2007-07-06 13:56:01 +00:00
|
|
|
|
2011-08-26 22:16:12 +00:00
|
|
|
enum {
|
|
|
|
PROP_0,
|
|
|
|
PROP_WRAPPER,
|
|
|
|
PROP_BACKEND,
|
|
|
|
PROP_LAST
|
|
|
|
};
|
|
|
|
|
2007-07-06 13:56:01 +00:00
|
|
|
static void
|
2011-05-08 23:27:10 +00:00
|
|
|
clutter_stage_cogl_unrealize (ClutterStageWindow *stage_window)
|
2010-06-17 21:26:12 +00:00
|
|
|
{
|
2011-05-08 23:27:10 +00:00
|
|
|
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
2010-06-17 21:26:12 +00:00
|
|
|
|
2011-05-08 23:27:10 +00:00
|
|
|
CLUTTER_NOTE (BACKEND, "Unrealizing Cogl stage [%p]", stage_cogl);
|
2010-06-17 21:26:12 +00:00
|
|
|
|
2011-09-09 12:52:55 +00:00
|
|
|
if (stage_cogl->onscreen != NULL)
|
|
|
|
{
|
2012-11-08 17:42:24 +00:00
|
|
|
cogl_onscreen_remove_frame_callback (stage_cogl->onscreen,
|
|
|
|
stage_cogl->frame_closure);
|
|
|
|
stage_cogl->frame_closure = NULL;
|
|
|
|
|
2011-09-09 12:52:55 +00:00
|
|
|
cogl_object_unref (stage_cogl->onscreen);
|
|
|
|
stage_cogl->onscreen = NULL;
|
|
|
|
}
|
2015-09-14 23:32:05 +00:00
|
|
|
|
|
|
|
stage_cogl->pending_swaps = 0;
|
2011-05-08 23:27:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-11-08 17:42:24 +00:00
|
|
|
frame_cb (CoglOnscreen *onscreen,
|
|
|
|
CoglFrameEvent event,
|
|
|
|
CoglFrameInfo *info,
|
|
|
|
void *user_data)
|
2011-05-08 23:27:10 +00:00
|
|
|
{
|
|
|
|
ClutterStageCogl *stage_cogl = user_data;
|
|
|
|
|
2012-11-08 17:42:24 +00:00
|
|
|
if (event == COGL_FRAME_EVENT_SYNC)
|
|
|
|
{
|
|
|
|
/* Early versions of the swap_event implementation in Mesa
|
|
|
|
* deliver BufferSwapComplete event when not selected for,
|
|
|
|
* so if we get a swap event we aren't expecting, just ignore it.
|
|
|
|
*
|
|
|
|
* https://bugs.freedesktop.org/show_bug.cgi?id=27962
|
|
|
|
*
|
|
|
|
* FIXME: This issue can be hidden inside Cogl so we shouldn't
|
|
|
|
* need to care about this bug here.
|
|
|
|
*/
|
|
|
|
if (stage_cogl->pending_swaps > 0)
|
|
|
|
stage_cogl->pending_swaps--;
|
|
|
|
}
|
|
|
|
else if (event == COGL_FRAME_EVENT_COMPLETE)
|
|
|
|
{
|
|
|
|
gint64 presentation_time_cogl = cogl_frame_info_get_presentation_time (info);
|
|
|
|
|
|
|
|
if (presentation_time_cogl != 0)
|
|
|
|
{
|
|
|
|
CoglContext *context = cogl_framebuffer_get_context (COGL_FRAMEBUFFER (onscreen));
|
|
|
|
gint64 current_time_cogl = cogl_get_clock_time (context);
|
|
|
|
gint64 now = g_get_monotonic_time ();
|
|
|
|
|
|
|
|
stage_cogl->last_presentation_time =
|
|
|
|
now + (presentation_time_cogl - current_time_cogl) / 1000;
|
|
|
|
}
|
|
|
|
|
|
|
|
stage_cogl->refresh_rate = cogl_frame_info_get_refresh_rate (info);
|
|
|
|
}
|
2010-06-17 21:26:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2011-05-08 23:27:10 +00:00
|
|
|
clutter_stage_cogl_realize (ClutterStageWindow *stage_window)
|
2007-07-06 13:56:01 +00:00
|
|
|
{
|
2011-05-08 23:27:10 +00:00
|
|
|
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
2011-02-25 00:31:41 +00:00
|
|
|
ClutterBackend *backend;
|
|
|
|
CoglFramebuffer *framebuffer;
|
|
|
|
GError *error = NULL;
|
|
|
|
gfloat width = 800;
|
|
|
|
gfloat height = 600;
|
2010-06-17 21:26:12 +00:00
|
|
|
|
2011-01-18 14:16:11 +00:00
|
|
|
CLUTTER_NOTE (BACKEND, "Realizing stage '%s' [%p]",
|
2011-05-08 23:27:10 +00:00
|
|
|
G_OBJECT_TYPE_NAME (stage_cogl),
|
|
|
|
stage_cogl);
|
2010-06-17 21:26:12 +00:00
|
|
|
|
2011-06-17 11:03:21 +00:00
|
|
|
backend = clutter_get_default_backend ();
|
2010-06-17 21:26:12 +00:00
|
|
|
|
2015-03-17 13:47:08 +00:00
|
|
|
if (backend->cogl_context == NULL)
|
|
|
|
{
|
|
|
|
g_warning ("Failed to realize stage: missing Cogl context");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2011-08-26 22:16:12 +00:00
|
|
|
if (stage_cogl->onscreen == NULL)
|
2011-05-09 00:09:39 +00:00
|
|
|
{
|
2011-08-26 22:16:12 +00:00
|
|
|
stage_cogl->onscreen = cogl_onscreen_new (backend->cogl_context,
|
|
|
|
width, height);
|
2011-05-09 00:09:39 +00:00
|
|
|
}
|
2011-02-25 00:31:41 +00:00
|
|
|
|
2011-11-04 16:39:52 +00:00
|
|
|
cogl_onscreen_set_swap_throttled (stage_cogl->onscreen,
|
|
|
|
_clutter_get_sync_to_vblank ());
|
2010-06-17 21:26:12 +00:00
|
|
|
|
2011-05-08 23:27:10 +00:00
|
|
|
framebuffer = COGL_FRAMEBUFFER (stage_cogl->onscreen);
|
2011-02-25 00:31:41 +00:00
|
|
|
if (!cogl_framebuffer_allocate (framebuffer, &error))
|
2010-06-17 21:26:12 +00:00
|
|
|
{
|
2011-02-25 00:31:41 +00:00
|
|
|
g_warning ("Failed to allocate stage: %s", error->message);
|
|
|
|
g_error_free (error);
|
2011-05-08 23:27:10 +00:00
|
|
|
cogl_object_unref (stage_cogl->onscreen);
|
|
|
|
stage_cogl->onscreen = NULL;
|
2011-02-25 00:31:41 +00:00
|
|
|
return FALSE;
|
2010-06-17 21:26:12 +00:00
|
|
|
}
|
2011-06-17 11:03:21 +00:00
|
|
|
|
2011-08-26 22:16:12 +00:00
|
|
|
/* FIXME: for fullscreen Cogl platforms then the size we gave
|
2011-02-25 00:31:41 +00:00
|
|
|
* will be ignored, so we need to make sure the stage size is
|
|
|
|
* updated to this size. */
|
2010-06-17 21:26:12 +00:00
|
|
|
|
2012-11-08 17:42:24 +00:00
|
|
|
stage_cogl->frame_closure =
|
2013-08-14 10:27:48 +00:00
|
|
|
cogl_onscreen_add_frame_callback (stage_cogl->onscreen,
|
|
|
|
frame_cb,
|
|
|
|
stage_cogl,
|
|
|
|
NULL);
|
2012-11-08 17:42:24 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
clutter_stage_cogl_schedule_update (ClutterStageWindow *stage_window,
|
|
|
|
gint sync_delay)
|
|
|
|
{
|
|
|
|
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
|
|
|
gint64 now;
|
|
|
|
float refresh_rate;
|
|
|
|
gint64 refresh_interval;
|
|
|
|
|
|
|
|
if (stage_cogl->update_time != -1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
now = g_get_monotonic_time ();
|
|
|
|
|
|
|
|
if (sync_delay < 0)
|
2011-05-08 23:27:10 +00:00
|
|
|
{
|
2012-11-08 17:42:24 +00:00
|
|
|
stage_cogl->update_time = now;
|
|
|
|
return;
|
2011-05-08 23:27:10 +00:00
|
|
|
}
|
|
|
|
|
2012-11-08 17:42:24 +00:00
|
|
|
/* We only extrapolate presentation times for 150ms - this is somewhat
|
|
|
|
* arbitrary. The reasons it might not be accurate for larger times are
|
|
|
|
* that the refresh interval might be wrong or the vertical refresh
|
|
|
|
* might be downclocked if nothing is going on onscreen.
|
|
|
|
*/
|
|
|
|
if (stage_cogl->last_presentation_time == 0||
|
|
|
|
stage_cogl->last_presentation_time < now - 150000)
|
|
|
|
{
|
|
|
|
stage_cogl->update_time = now;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
refresh_rate = stage_cogl->refresh_rate;
|
|
|
|
if (refresh_rate == 0.0)
|
|
|
|
refresh_rate = 60.0;
|
|
|
|
|
|
|
|
refresh_interval = (gint64) (0.5 + 1000000 / refresh_rate);
|
|
|
|
if (refresh_interval == 0)
|
|
|
|
refresh_interval = 16667; /* 1/60th second */
|
|
|
|
|
|
|
|
stage_cogl->update_time = stage_cogl->last_presentation_time + 1000 * sync_delay;
|
|
|
|
|
|
|
|
while (stage_cogl->update_time < now)
|
|
|
|
stage_cogl->update_time += refresh_interval;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint64
|
|
|
|
clutter_stage_cogl_get_update_time (ClutterStageWindow *stage_window)
|
|
|
|
{
|
|
|
|
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
|
|
|
|
|
|
|
if (stage_cogl->pending_swaps)
|
|
|
|
return -1; /* in the future, indefinite */
|
|
|
|
|
|
|
|
return stage_cogl->update_time;
|
2010-06-17 21:26:12 +00:00
|
|
|
}
|
|
|
|
|
2012-11-08 17:42:24 +00:00
|
|
|
static void
|
|
|
|
clutter_stage_cogl_clear_update_time (ClutterStageWindow *stage_window)
|
2011-05-08 23:27:10 +00:00
|
|
|
{
|
|
|
|
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
|
|
|
|
2012-11-08 17:42:24 +00:00
|
|
|
stage_cogl->update_time = -1;
|
2011-05-08 23:27:10 +00:00
|
|
|
}
|
|
|
|
|
2010-02-27 09:42:42 +00:00
|
|
|
static ClutterActor *
|
2011-05-08 23:27:10 +00:00
|
|
|
clutter_stage_cogl_get_wrapper (ClutterStageWindow *stage_window)
|
2010-02-27 09:42:42 +00:00
|
|
|
{
|
2011-05-08 23:27:10 +00:00
|
|
|
return CLUTTER_ACTOR (CLUTTER_STAGE_COGL (stage_window)->wrapper);
|
2007-07-06 13:56:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2011-05-08 23:27:10 +00:00
|
|
|
clutter_stage_cogl_show (ClutterStageWindow *stage_window,
|
2011-08-26 22:16:12 +00:00
|
|
|
gboolean do_raise)
|
2007-07-06 13:56:01 +00:00
|
|
|
{
|
2011-05-08 23:27:10 +00:00
|
|
|
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
2008-06-11 10:19:02 +00:00
|
|
|
|
2011-05-08 23:27:10 +00:00
|
|
|
clutter_actor_map (CLUTTER_ACTOR (stage_cogl->wrapper));
|
2008-06-11 10:19:02 +00:00
|
|
|
}
|
|
|
|
|
2007-07-06 13:56:01 +00:00
|
|
|
static void
|
2011-05-08 23:27:10 +00:00
|
|
|
clutter_stage_cogl_hide (ClutterStageWindow *stage_window)
|
2007-07-06 13:56:01 +00:00
|
|
|
{
|
2011-05-08 23:27:10 +00:00
|
|
|
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
2007-07-06 13:56:01 +00:00
|
|
|
|
2011-05-08 23:27:10 +00:00
|
|
|
clutter_actor_unmap (CLUTTER_ACTOR (stage_cogl->wrapper));
|
2007-07-06 13:56:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2011-08-16 15:01:22 +00:00
|
|
|
clutter_stage_cogl_get_geometry (ClutterStageWindow *stage_window,
|
|
|
|
cairo_rectangle_int_t *geometry)
|
2007-07-06 13:56:01 +00:00
|
|
|
{
|
2011-05-08 23:27:10 +00:00
|
|
|
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
2013-08-14 10:27:48 +00:00
|
|
|
int window_scale;
|
2007-07-06 13:56:01 +00:00
|
|
|
|
2013-08-14 10:27:48 +00:00
|
|
|
window_scale = _clutter_stage_window_get_scale_factor (stage_window);
|
|
|
|
|
|
|
|
if (geometry != NULL)
|
2010-02-27 09:42:42 +00:00
|
|
|
{
|
2011-05-08 23:27:10 +00:00
|
|
|
if (stage_cogl->onscreen)
|
2011-02-25 00:31:41 +00:00
|
|
|
{
|
|
|
|
CoglFramebuffer *framebuffer =
|
2011-05-08 23:27:10 +00:00
|
|
|
COGL_FRAMEBUFFER (stage_cogl->onscreen);
|
2011-02-25 00:31:41 +00:00
|
|
|
|
|
|
|
geometry->x = geometry->y = 0;
|
2008-04-23 17:20:59 +00:00
|
|
|
|
2013-08-14 10:27:48 +00:00
|
|
|
geometry->width = cogl_framebuffer_get_width (framebuffer) / window_scale;
|
|
|
|
geometry->height = cogl_framebuffer_get_height (framebuffer) / window_scale;
|
2011-02-25 00:31:41 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
geometry->x = geometry->y = 0;
|
|
|
|
geometry->width = 800;
|
|
|
|
geometry->height = 600;
|
|
|
|
}
|
2010-02-27 09:42:42 +00:00
|
|
|
}
|
2007-07-06 13:56:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2011-05-08 23:27:10 +00:00
|
|
|
clutter_stage_cogl_resize (ClutterStageWindow *stage_window,
|
2013-08-14 10:27:48 +00:00
|
|
|
gint width,
|
|
|
|
gint height)
|
2007-07-06 13:56:01 +00:00
|
|
|
{
|
2008-04-25 13:37:36 +00:00
|
|
|
}
|
|
|
|
|
2010-11-16 13:54:15 +00:00
|
|
|
static gboolean
|
2011-05-08 23:27:10 +00:00
|
|
|
clutter_stage_cogl_has_redraw_clips (ClutterStageWindow *stage_window)
|
2010-11-16 13:54:15 +00:00
|
|
|
{
|
2011-05-08 23:27:10 +00:00
|
|
|
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
2010-11-16 13:54:15 +00:00
|
|
|
|
2010-11-23 16:05:44 +00:00
|
|
|
/* NB: at the start of each new frame there is an implied clip that
|
|
|
|
* clips everything (i.e. nothing would be drawn) so we need to make
|
|
|
|
* sure we return True in the un-initialized case here.
|
|
|
|
*
|
|
|
|
* NB: a clip width of 0 means a full stage redraw has been queued
|
|
|
|
* so we effectively don't have any redraw clips in that case.
|
|
|
|
*/
|
2011-05-08 23:27:10 +00:00
|
|
|
if (!stage_cogl->initialized_redraw_clip ||
|
|
|
|
(stage_cogl->initialized_redraw_clip &&
|
|
|
|
stage_cogl->bounding_redraw_clip.width != 0))
|
2010-11-16 13:54:15 +00:00
|
|
|
return TRUE;
|
|
|
|
else
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2011-05-08 23:27:10 +00:00
|
|
|
clutter_stage_cogl_ignoring_redraw_clips (ClutterStageWindow *stage_window)
|
2010-11-16 13:54:15 +00:00
|
|
|
{
|
2011-05-08 23:27:10 +00:00
|
|
|
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
2010-11-16 13:54:15 +00:00
|
|
|
|
2010-11-23 16:05:44 +00:00
|
|
|
/* NB: a clip width of 0 means a full stage redraw is required */
|
2011-05-08 23:27:10 +00:00
|
|
|
if (stage_cogl->initialized_redraw_clip &&
|
|
|
|
stage_cogl->bounding_redraw_clip.width == 0)
|
2010-11-16 13:54:15 +00:00
|
|
|
return TRUE;
|
|
|
|
else
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* A redraw clip represents (in stage coordinates) the bounding box of
|
|
|
|
* something that needs to be redraw. Typically they are added to the
|
|
|
|
* StageWindow as a result of clutter_actor_queue_clipped_redraw() by
|
2011-05-08 23:27:10 +00:00
|
|
|
* actors such as ClutterGLXTexturePixmap. All redraw clips are
|
2010-11-16 13:54:15 +00:00
|
|
|
* discarded after the next paint.
|
|
|
|
*
|
|
|
|
* A NULL stage_clip means the whole stage needs to be redrawn.
|
|
|
|
*
|
|
|
|
* What we do with this information:
|
|
|
|
* - we keep track of the bounding box for all redraw clips
|
|
|
|
* - when we come to redraw; we scissor the redraw to that box and use
|
|
|
|
* glBlitFramebuffer to present the redraw to the front
|
|
|
|
* buffer.
|
|
|
|
*/
|
|
|
|
static void
|
2011-08-16 15:01:22 +00:00
|
|
|
clutter_stage_cogl_add_redraw_clip (ClutterStageWindow *stage_window,
|
|
|
|
cairo_rectangle_int_t *stage_clip)
|
2010-11-16 13:54:15 +00:00
|
|
|
{
|
2011-05-08 23:27:10 +00:00
|
|
|
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
2010-11-16 13:54:15 +00:00
|
|
|
|
|
|
|
/* If we are already forced to do a full stage redraw then bail early */
|
2011-05-08 23:27:10 +00:00
|
|
|
if (clutter_stage_cogl_ignoring_redraw_clips (stage_window))
|
2010-11-16 13:54:15 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
/* A NULL stage clip means a full stage redraw has been queued and
|
2010-11-23 16:05:44 +00:00
|
|
|
* we keep track of this by setting a zero width
|
2011-05-08 23:27:10 +00:00
|
|
|
* stage_cogl->bounding_redraw_clip */
|
2010-11-16 13:54:15 +00:00
|
|
|
if (stage_clip == NULL)
|
|
|
|
{
|
2011-05-08 23:27:10 +00:00
|
|
|
stage_cogl->bounding_redraw_clip.width = 0;
|
|
|
|
stage_cogl->initialized_redraw_clip = TRUE;
|
2010-11-16 13:54:15 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Ignore requests to add degenerate/empty clip rectangles */
|
|
|
|
if (stage_clip->width == 0 || stage_clip->height == 0)
|
|
|
|
return;
|
|
|
|
|
2011-05-08 23:27:10 +00:00
|
|
|
if (!stage_cogl->initialized_redraw_clip)
|
2010-11-16 13:54:15 +00:00
|
|
|
{
|
2011-08-16 15:01:22 +00:00
|
|
|
stage_cogl->bounding_redraw_clip = *stage_clip;
|
2010-11-16 13:54:15 +00:00
|
|
|
}
|
2011-05-08 23:27:10 +00:00
|
|
|
else if (stage_cogl->bounding_redraw_clip.width > 0)
|
2010-11-16 13:54:15 +00:00
|
|
|
{
|
2011-08-16 15:01:22 +00:00
|
|
|
_clutter_util_rectangle_union (&stage_cogl->bounding_redraw_clip,
|
|
|
|
stage_clip,
|
|
|
|
&stage_cogl->bounding_redraw_clip);
|
2010-11-16 13:54:15 +00:00
|
|
|
}
|
|
|
|
|
2011-05-08 23:27:10 +00:00
|
|
|
stage_cogl->initialized_redraw_clip = TRUE;
|
2010-11-16 13:54:15 +00:00
|
|
|
}
|
|
|
|
|
2011-07-12 16:16:43 +00:00
|
|
|
static gboolean
|
2011-08-16 15:01:22 +00:00
|
|
|
clutter_stage_cogl_get_redraw_clip_bounds (ClutterStageWindow *stage_window,
|
2011-07-12 16:16:43 +00:00
|
|
|
cairo_rectangle_int_t *stage_clip)
|
|
|
|
{
|
|
|
|
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
|
|
|
|
|
|
|
if (stage_cogl->using_clipped_redraw)
|
|
|
|
{
|
2011-08-16 15:01:22 +00:00
|
|
|
*stage_clip = stage_cogl->bounding_redraw_clip;
|
2011-07-12 16:16:43 +00:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2015-01-28 22:08:03 +00:00
|
|
|
static inline gboolean
|
|
|
|
valid_buffer_age (ClutterStageCogl *stage_cogl, int age)
|
|
|
|
{
|
|
|
|
if (age <= 0 || stage_cogl->dirty_backbuffer)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return age < MIN (stage_cogl->damage_index, DAMAGE_HISTORY_MAX);
|
|
|
|
}
|
|
|
|
|
2011-02-25 00:31:41 +00:00
|
|
|
/* XXX: This is basically identical to clutter_stage_glx_redraw */
|
2011-02-04 15:09:41 +00:00
|
|
|
static void
|
2011-05-08 23:27:10 +00:00
|
|
|
clutter_stage_cogl_redraw (ClutterStageWindow *stage_window)
|
2010-06-17 21:26:12 +00:00
|
|
|
{
|
2011-05-08 23:27:10 +00:00
|
|
|
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
2013-12-05 04:54:27 +00:00
|
|
|
cairo_rectangle_int_t geom;
|
|
|
|
gboolean have_clip;
|
2011-02-04 15:09:41 +00:00
|
|
|
gboolean may_use_clipped_redraw;
|
|
|
|
gboolean use_clipped_redraw;
|
2011-11-04 16:13:04 +00:00
|
|
|
gboolean can_blit_sub_buffer;
|
2013-02-06 10:05:58 +00:00
|
|
|
gboolean has_buffer_age;
|
2011-11-04 16:13:04 +00:00
|
|
|
ClutterActor *wrapper;
|
2013-02-06 10:05:58 +00:00
|
|
|
cairo_rectangle_int_t *clip_region;
|
2015-03-02 12:11:30 +00:00
|
|
|
int damage[4], ndamage;
|
2013-02-06 10:05:58 +00:00
|
|
|
gboolean force_swap;
|
2013-08-14 10:27:48 +00:00
|
|
|
int window_scale;
|
2011-02-25 00:31:41 +00:00
|
|
|
|
2013-07-04 15:12:27 +00:00
|
|
|
wrapper = CLUTTER_ACTOR (stage_cogl->wrapper);
|
|
|
|
|
2011-05-08 23:27:10 +00:00
|
|
|
if (!stage_cogl->onscreen)
|
2011-02-25 00:31:41 +00:00
|
|
|
return;
|
|
|
|
|
2013-07-04 15:12:27 +00:00
|
|
|
can_blit_sub_buffer =
|
|
|
|
cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_REGION);
|
2011-11-04 16:13:04 +00:00
|
|
|
|
2013-07-04 15:12:27 +00:00
|
|
|
has_buffer_age = cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_BUFFER_AGE);
|
2013-02-06 10:05:58 +00:00
|
|
|
|
2013-12-05 04:54:27 +00:00
|
|
|
_clutter_stage_window_get_geometry (stage_window, &geom);
|
|
|
|
|
|
|
|
/* NB: a zero width redraw clip == full stage redraw */
|
|
|
|
have_clip = (stage_cogl->bounding_redraw_clip.width != 0 &&
|
|
|
|
!(stage_cogl->bounding_redraw_clip.x == 0 &&
|
|
|
|
stage_cogl->bounding_redraw_clip.y == 0 &&
|
|
|
|
stage_cogl->bounding_redraw_clip.width == geom.width &&
|
|
|
|
stage_cogl->bounding_redraw_clip.height == geom.height));
|
|
|
|
|
2011-09-21 17:05:03 +00:00
|
|
|
may_use_clipped_redraw = FALSE;
|
2011-09-30 12:58:40 +00:00
|
|
|
if (_clutter_stage_window_can_clip_redraws (stage_window) &&
|
2014-03-14 09:41:57 +00:00
|
|
|
(can_blit_sub_buffer || has_buffer_age) &&
|
2013-12-05 04:54:27 +00:00
|
|
|
have_clip &&
|
2010-11-16 13:54:15 +00:00
|
|
|
/* some drivers struggle to get going and produce some junk
|
|
|
|
* frames when starting up... */
|
2011-11-04 16:13:04 +00:00
|
|
|
stage_cogl->frame_count > 3)
|
2011-09-21 17:05:03 +00:00
|
|
|
{
|
2011-09-30 12:58:40 +00:00
|
|
|
may_use_clipped_redraw = TRUE;
|
2013-02-06 10:05:58 +00:00
|
|
|
clip_region = &stage_cogl->bounding_redraw_clip;
|
2011-02-25 00:31:41 +00:00
|
|
|
}
|
2014-12-03 12:05:37 +00:00
|
|
|
else
|
|
|
|
clip_region = NULL;
|
2010-11-16 13:54:15 +00:00
|
|
|
|
|
|
|
if (may_use_clipped_redraw &&
|
2013-08-14 10:27:48 +00:00
|
|
|
G_LIKELY (!(clutter_paint_debug_flags & CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS)))
|
2010-11-16 13:54:15 +00:00
|
|
|
use_clipped_redraw = TRUE;
|
|
|
|
else
|
|
|
|
use_clipped_redraw = FALSE;
|
|
|
|
|
2013-02-06 10:05:58 +00:00
|
|
|
force_swap = FALSE;
|
|
|
|
|
2013-08-14 10:27:48 +00:00
|
|
|
window_scale = _clutter_stage_window_get_scale_factor (stage_window);
|
|
|
|
|
2015-01-28 22:08:03 +00:00
|
|
|
if (has_buffer_age)
|
2013-02-06 10:05:58 +00:00
|
|
|
{
|
2015-01-28 22:08:03 +00:00
|
|
|
cairo_rectangle_int_t *current_damage =
|
|
|
|
&stage_cogl->damage_history[DAMAGE_HISTORY (stage_cogl->damage_index++)];
|
|
|
|
|
|
|
|
if (use_clipped_redraw)
|
|
|
|
{
|
|
|
|
int age = cogl_onscreen_get_buffer_age (stage_cogl->onscreen), i;
|
|
|
|
|
|
|
|
*current_damage = *clip_region;
|
|
|
|
|
|
|
|
if (valid_buffer_age (stage_cogl, age))
|
|
|
|
{
|
|
|
|
for (i = 1; i <= age; i++)
|
|
|
|
_clutter_util_rectangle_union (clip_region,
|
|
|
|
&stage_cogl->damage_history[DAMAGE_HISTORY (stage_cogl->damage_index - i - 1)],
|
|
|
|
clip_region);
|
|
|
|
|
|
|
|
CLUTTER_NOTE (CLIPPING, "Reusing back buffer(age=%d) - repairing region: x=%d, y=%d, width=%d, height=%d\n",
|
|
|
|
age,
|
|
|
|
clip_region->x,
|
|
|
|
clip_region->y,
|
|
|
|
clip_region->width,
|
|
|
|
clip_region->height);
|
|
|
|
force_swap = TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CLUTTER_NOTE (CLIPPING, "Invalid back buffer(age=%d): forcing full redraw\n", age);
|
|
|
|
use_clipped_redraw = FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
current_damage->x = 0;
|
|
|
|
current_damage->y = 0;
|
|
|
|
current_damage->width = geom.width;
|
|
|
|
current_damage->height = geom.height;
|
|
|
|
}
|
2013-02-06 10:05:58 +00:00
|
|
|
}
|
|
|
|
|
2010-11-16 13:54:15 +00:00
|
|
|
if (use_clipped_redraw)
|
|
|
|
{
|
2013-12-03 12:12:52 +00:00
|
|
|
CoglFramebuffer *fb = COGL_FRAMEBUFFER (stage_cogl->onscreen);
|
|
|
|
|
2011-05-08 23:27:10 +00:00
|
|
|
CLUTTER_NOTE (CLIPPING,
|
|
|
|
"Stage clip pushed: x=%d, y=%d, width=%d, height=%d\n",
|
2013-02-06 10:05:58 +00:00
|
|
|
clip_region->x,
|
|
|
|
clip_region->y,
|
|
|
|
clip_region->width,
|
|
|
|
clip_region->height);
|
2011-07-12 16:16:43 +00:00
|
|
|
|
|
|
|
stage_cogl->using_clipped_redraw = TRUE;
|
|
|
|
|
2013-12-05 12:57:17 +00:00
|
|
|
cogl_framebuffer_push_scissor_clip (fb,
|
|
|
|
clip_region->x * window_scale,
|
|
|
|
clip_region->y * window_scale,
|
|
|
|
clip_region->width * window_scale,
|
|
|
|
clip_region->height * window_scale);
|
2013-08-14 10:27:48 +00:00
|
|
|
_clutter_stage_do_paint (CLUTTER_STAGE (wrapper), clip_region);
|
2013-12-03 12:12:52 +00:00
|
|
|
cogl_framebuffer_pop_clip (fb);
|
2011-07-12 16:16:43 +00:00
|
|
|
|
|
|
|
stage_cogl->using_clipped_redraw = FALSE;
|
2010-11-16 13:54:15 +00:00
|
|
|
}
|
|
|
|
else
|
2011-05-08 23:27:10 +00:00
|
|
|
{
|
|
|
|
CLUTTER_NOTE (CLIPPING, "Unclipped stage paint\n");
|
|
|
|
|
|
|
|
/* If we are trying to debug redraw issues then we want to pass
|
|
|
|
* the bounding_redraw_clip so it can be visualized */
|
2013-08-14 10:27:48 +00:00
|
|
|
if (G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS) &&
|
2011-05-08 23:27:10 +00:00
|
|
|
may_use_clipped_redraw)
|
|
|
|
{
|
2014-12-03 12:05:37 +00:00
|
|
|
_clutter_stage_do_paint (CLUTTER_STAGE (wrapper), clip_region);
|
2011-05-08 23:27:10 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
_clutter_stage_do_paint (CLUTTER_STAGE (wrapper), NULL);
|
|
|
|
}
|
2010-11-16 13:54:15 +00:00
|
|
|
|
2011-02-25 00:31:41 +00:00
|
|
|
if (may_use_clipped_redraw &&
|
|
|
|
G_UNLIKELY ((clutter_paint_debug_flags & CLUTTER_DEBUG_REDRAWS)))
|
2010-11-16 13:54:15 +00:00
|
|
|
{
|
2012-04-20 16:11:47 +00:00
|
|
|
CoglFramebuffer *fb = COGL_FRAMEBUFFER (stage_cogl->onscreen);
|
|
|
|
CoglContext *ctx = cogl_framebuffer_get_context (fb);
|
2012-02-21 13:22:17 +00:00
|
|
|
static CoglPipeline *outline = NULL;
|
2011-08-16 15:01:22 +00:00
|
|
|
cairo_rectangle_int_t *clip = &stage_cogl->bounding_redraw_clip;
|
2011-02-25 00:31:41 +00:00
|
|
|
ClutterActor *actor = CLUTTER_ACTOR (wrapper);
|
2013-08-14 10:27:48 +00:00
|
|
|
float x_1 = clip->x * window_scale;
|
|
|
|
float x_2 = clip->x + clip->width * window_scale;
|
|
|
|
float y_1 = clip->y * window_scale;
|
|
|
|
float y_2 = clip->y + clip->height * window_scale;
|
2012-04-20 16:11:47 +00:00
|
|
|
CoglVertexP2 quad[4] = {
|
|
|
|
{ x_1, y_1 },
|
|
|
|
{ x_2, y_1 },
|
|
|
|
{ x_2, y_2 },
|
|
|
|
{ x_1, y_2 }
|
2010-11-16 13:54:15 +00:00
|
|
|
};
|
2012-04-20 16:11:47 +00:00
|
|
|
CoglPrimitive *prim;
|
2010-11-16 13:54:15 +00:00
|
|
|
CoglMatrix modelview;
|
|
|
|
|
|
|
|
if (outline == NULL)
|
|
|
|
{
|
2012-02-21 13:22:17 +00:00
|
|
|
outline = cogl_pipeline_new (ctx);
|
|
|
|
cogl_pipeline_set_color4ub (outline, 0xff, 0x00, 0x00, 0xff);
|
2010-11-16 13:54:15 +00:00
|
|
|
}
|
|
|
|
|
2012-04-20 16:11:47 +00:00
|
|
|
prim = cogl_primitive_new_p2 (ctx,
|
|
|
|
COGL_VERTICES_MODE_LINE_LOOP,
|
|
|
|
4, /* n_vertices */
|
|
|
|
quad);
|
|
|
|
|
|
|
|
cogl_framebuffer_push_matrix (fb);
|
2010-11-16 13:54:15 +00:00
|
|
|
cogl_matrix_init_identity (&modelview);
|
2011-02-25 00:31:41 +00:00
|
|
|
_clutter_actor_apply_modelview_transform (actor, &modelview);
|
2012-04-20 16:11:47 +00:00
|
|
|
cogl_framebuffer_set_modelview_matrix (fb, &modelview);
|
|
|
|
cogl_framebuffer_draw_primitive (COGL_FRAMEBUFFER (stage_cogl->onscreen),
|
|
|
|
outline,
|
|
|
|
prim);
|
|
|
|
cogl_framebuffer_pop_matrix (fb);
|
|
|
|
cogl_object_unref (prim);
|
2010-11-16 13:54:15 +00:00
|
|
|
}
|
|
|
|
|
2015-03-02 12:11:30 +00:00
|
|
|
/* XXX: It seems there will be a race here in that the stage
|
|
|
|
* window may be resized before the cogl_onscreen_swap_region
|
|
|
|
* is handled and so we may copy the wrong region. I can't
|
|
|
|
* really see how we can handle this with the current state of X
|
|
|
|
* but at least in this case a full redraw should be queued by
|
|
|
|
* the resize anyway so it should only exhibit temporary
|
|
|
|
* artefacts.
|
|
|
|
*/
|
|
|
|
if (use_clipped_redraw || force_swap)
|
|
|
|
{
|
|
|
|
damage[0] = clip_region->x * window_scale;
|
|
|
|
damage[1] = clip_region->y * window_scale;
|
|
|
|
damage[2] = clip_region->width * window_scale;
|
|
|
|
damage[3] = clip_region->height * window_scale;
|
|
|
|
ndamage = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-04-28 23:05:55 +00:00
|
|
|
ndamage = 0;
|
2015-03-02 12:11:30 +00:00
|
|
|
}
|
|
|
|
|
2010-11-16 13:54:15 +00:00
|
|
|
/* push on the screen */
|
2013-02-06 10:05:58 +00:00
|
|
|
if (use_clipped_redraw && !force_swap)
|
2010-11-16 13:54:15 +00:00
|
|
|
{
|
|
|
|
CLUTTER_NOTE (BACKEND,
|
2012-02-21 13:37:55 +00:00
|
|
|
"cogl_onscreen_swap_region (onscreen: %p, "
|
|
|
|
"x: %d, y: %d, "
|
|
|
|
"width: %d, height: %d)",
|
2011-05-08 23:27:10 +00:00
|
|
|
stage_cogl->onscreen,
|
2015-03-02 12:11:30 +00:00
|
|
|
damage[0], damage[1], damage[2], damage[3]);
|
2010-11-16 13:54:15 +00:00
|
|
|
|
2015-03-02 12:11:30 +00:00
|
|
|
cogl_onscreen_swap_region (stage_cogl->onscreen,
|
|
|
|
damage, ndamage);
|
2010-11-16 13:54:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-02-21 13:37:55 +00:00
|
|
|
CLUTTER_NOTE (BACKEND, "cogl_onscreen_swap_buffers (onscreen: %p)",
|
2011-05-08 23:27:10 +00:00
|
|
|
stage_cogl->onscreen);
|
|
|
|
|
2012-02-21 13:37:55 +00:00
|
|
|
/* If we have swap buffer events then cogl_onscreen_swap_buffers
|
|
|
|
* will return immediately and we need to track that there is a
|
|
|
|
* swap in progress... */
|
2011-05-08 23:27:10 +00:00
|
|
|
if (clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS))
|
|
|
|
stage_cogl->pending_swaps++;
|
2010-11-16 13:54:15 +00:00
|
|
|
|
2015-03-02 12:11:30 +00:00
|
|
|
cogl_onscreen_swap_buffers_with_damage (stage_cogl->onscreen,
|
|
|
|
damage, ndamage);
|
2010-11-16 13:54:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* reset the redraw clipping for the next paint... */
|
2011-05-08 23:27:10 +00:00
|
|
|
stage_cogl->initialized_redraw_clip = FALSE;
|
|
|
|
|
2013-02-03 10:51:19 +00:00
|
|
|
/* We have repaired the backbuffer */
|
|
|
|
stage_cogl->dirty_backbuffer = FALSE;
|
|
|
|
|
2011-05-08 23:27:10 +00:00
|
|
|
stage_cogl->frame_count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
static CoglFramebuffer *
|
|
|
|
clutter_stage_cogl_get_active_framebuffer (ClutterStageWindow *stage_window)
|
|
|
|
{
|
|
|
|
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
2010-11-16 13:54:15 +00:00
|
|
|
|
2011-05-08 23:27:10 +00:00
|
|
|
return COGL_FRAMEBUFFER (stage_cogl->onscreen);
|
2008-04-23 17:20:59 +00:00
|
|
|
}
|
2011-02-09 16:16:57 +00:00
|
|
|
|
2013-02-03 10:51:19 +00:00
|
|
|
static void
|
|
|
|
clutter_stage_cogl_dirty_back_buffer (ClutterStageWindow *stage_window)
|
|
|
|
{
|
|
|
|
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
|
|
|
|
|
|
|
stage_cogl->dirty_backbuffer = TRUE;
|
|
|
|
}
|
|
|
|
|
2013-02-06 10:05:58 +00:00
|
|
|
static void
|
|
|
|
clutter_stage_cogl_get_dirty_pixel (ClutterStageWindow *stage_window,
|
2013-08-14 10:27:48 +00:00
|
|
|
int *x,
|
|
|
|
int *y)
|
2013-02-06 10:05:58 +00:00
|
|
|
{
|
2013-08-14 10:27:48 +00:00
|
|
|
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
|
|
|
gboolean has_buffer_age = cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_BUFFER_AGE);
|
|
|
|
|
2015-01-28 22:08:03 +00:00
|
|
|
if (!has_buffer_age)
|
2013-08-14 10:27:48 +00:00
|
|
|
{
|
|
|
|
*x = 0;
|
|
|
|
*y = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cairo_rectangle_int_t *rect;
|
2015-01-28 22:08:03 +00:00
|
|
|
|
|
|
|
rect = &stage_cogl->damage_history[DAMAGE_HISTORY (stage_cogl->damage_index-1)];
|
2013-08-14 10:27:48 +00:00
|
|
|
*x = rect->x;
|
|
|
|
*y = rect->y;
|
|
|
|
}
|
2013-02-06 10:05:58 +00:00
|
|
|
}
|
|
|
|
|
2011-02-09 16:16:57 +00:00
|
|
|
static void
|
|
|
|
clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
|
|
|
|
{
|
2011-05-08 23:27:10 +00:00
|
|
|
iface->realize = clutter_stage_cogl_realize;
|
|
|
|
iface->unrealize = clutter_stage_cogl_unrealize;
|
|
|
|
iface->get_wrapper = clutter_stage_cogl_get_wrapper;
|
|
|
|
iface->get_geometry = clutter_stage_cogl_get_geometry;
|
|
|
|
iface->resize = clutter_stage_cogl_resize;
|
|
|
|
iface->show = clutter_stage_cogl_show;
|
|
|
|
iface->hide = clutter_stage_cogl_hide;
|
2012-11-08 17:42:24 +00:00
|
|
|
iface->schedule_update = clutter_stage_cogl_schedule_update;
|
|
|
|
iface->get_update_time = clutter_stage_cogl_get_update_time;
|
|
|
|
iface->clear_update_time = clutter_stage_cogl_clear_update_time;
|
2011-05-08 23:27:10 +00:00
|
|
|
iface->add_redraw_clip = clutter_stage_cogl_add_redraw_clip;
|
|
|
|
iface->has_redraw_clips = clutter_stage_cogl_has_redraw_clips;
|
|
|
|
iface->ignoring_redraw_clips = clutter_stage_cogl_ignoring_redraw_clips;
|
2011-07-12 16:16:43 +00:00
|
|
|
iface->get_redraw_clip_bounds = clutter_stage_cogl_get_redraw_clip_bounds;
|
2011-05-08 23:27:10 +00:00
|
|
|
iface->redraw = clutter_stage_cogl_redraw;
|
|
|
|
iface->get_active_framebuffer = clutter_stage_cogl_get_active_framebuffer;
|
2013-02-03 10:51:19 +00:00
|
|
|
iface->dirty_back_buffer = clutter_stage_cogl_dirty_back_buffer;
|
2013-02-06 10:05:58 +00:00
|
|
|
iface->get_dirty_pixel = clutter_stage_cogl_get_dirty_pixel;
|
2011-02-09 16:16:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2011-08-26 22:16:12 +00:00
|
|
|
clutter_stage_cogl_set_property (GObject *gobject,
|
|
|
|
guint prop_id,
|
|
|
|
const GValue *value,
|
|
|
|
GParamSpec *pspec)
|
2011-02-09 16:16:57 +00:00
|
|
|
{
|
2011-08-26 22:16:12 +00:00
|
|
|
ClutterStageCogl *self = CLUTTER_STAGE_COGL (gobject);
|
|
|
|
|
|
|
|
switch (prop_id)
|
|
|
|
{
|
|
|
|
case PROP_WRAPPER:
|
2011-11-04 16:52:44 +00:00
|
|
|
self->wrapper = g_value_get_object (value);
|
2011-08-26 22:16:12 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PROP_BACKEND:
|
2011-11-04 16:52:44 +00:00
|
|
|
self->backend = g_value_get_object (value);
|
2011-08-26 22:16:12 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
2011-02-09 16:16:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2011-05-08 23:27:10 +00:00
|
|
|
_clutter_stage_cogl_class_init (ClutterStageCoglClass *klass)
|
2011-02-09 16:16:57 +00:00
|
|
|
{
|
|
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
|
|
|
2011-08-26 22:16:12 +00:00
|
|
|
gobject_class->set_property = clutter_stage_cogl_set_property;
|
|
|
|
|
2011-11-04 18:50:46 +00:00
|
|
|
g_object_class_override_property (gobject_class, PROP_WRAPPER, "wrapper");
|
|
|
|
g_object_class_override_property (gobject_class, PROP_BACKEND, "backend");
|
2011-02-09 16:16:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2011-05-08 23:27:10 +00:00
|
|
|
_clutter_stage_cogl_init (ClutterStageCogl *stage)
|
2011-02-09 16:16:57 +00:00
|
|
|
{
|
2012-11-08 17:42:24 +00:00
|
|
|
stage->last_presentation_time = 0;
|
|
|
|
stage->refresh_rate = 0.0;
|
|
|
|
|
|
|
|
stage->update_time = -1;
|
2011-02-09 16:16:57 +00:00
|
|
|
}
|