15d7a86621
The only backend that tried to implement offscreen stages was the GLX backend and even this has apparently be broken for some time without anyone noticing. The property still remains and since the property already clearly states that it may not work I don't expect anyone to notice. This simplifies quite a bit of the GLX code which is very desireable from the POV that we want to start migrating window system code down to Cogl and the simpler the code is the more straight forward this work will be. In the future when Cogl has a nicely designed API for framebuffer objects then re-implementing offscreen stages cleanly for *all* backends should be quite straightforward.
259 lines
7.6 KiB
C
259 lines
7.6 KiB
C
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include "clutter-stage-fruity.h"
|
|
#include "clutter-fruity.h"
|
|
#include "clutter-backend-fruity.h"
|
|
|
|
#include "../clutter-main.h"
|
|
#include "../clutter-feature.h"
|
|
#include "../clutter-color.h"
|
|
#include "../clutter-util.h"
|
|
#include "../clutter-event.h"
|
|
#include "../clutter-enum-types.h"
|
|
#include "../clutter-private.h"
|
|
#include "../clutter-debug.h"
|
|
#include "../clutter-units.h"
|
|
#include "../clutter-stage.h"
|
|
#include "../clutter-stage-window.h"
|
|
|
|
static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface);
|
|
|
|
G_DEFINE_TYPE_WITH_CODE (ClutterStageEGL,
|
|
clutter_stage_egl,
|
|
CLUTTER_TYPE_ACTOR,
|
|
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW,
|
|
clutter_stage_window_iface_init));
|
|
|
|
static void
|
|
clutter_stage_egl_show (ClutterActor *actor)
|
|
{
|
|
CLUTTER_ACTOR_SET_FLAGS (actor, CLUTTER_ACTOR_MAPPED);
|
|
}
|
|
|
|
static void
|
|
clutter_stage_egl_hide (ClutterActor *actor)
|
|
{
|
|
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_MAPPED);
|
|
}
|
|
|
|
static void
|
|
clutter_stage_egl_unrealize (ClutterActor *actor)
|
|
{
|
|
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (actor);
|
|
|
|
CLUTTER_MARK();
|
|
|
|
if (CLUTTER_ACTOR_CLASS (clutter_stage_egl_parent_class)->unrealize != NULL)
|
|
CLUTTER_ACTOR_CLASS (clutter_stage_egl_parent_class)->unrealize (actor);
|
|
|
|
if (stage_egl->egl_surface)
|
|
{
|
|
eglDestroySurface (clutter_egl_display (), stage_egl->egl_surface);
|
|
stage_egl->egl_surface = EGL_NO_SURFACE;
|
|
}
|
|
}
|
|
|
|
static void
|
|
clutter_stage_egl_realize (ClutterActor *actor)
|
|
{
|
|
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (actor);
|
|
ClutterBackendEGL *backend_egl;
|
|
EGLConfig configs[2];
|
|
EGLint config_count;
|
|
EGLBoolean status;
|
|
EGLint cfg_attribs[] = {
|
|
EGL_BUFFER_SIZE, EGL_DONT_CARE,
|
|
EGL_RED_SIZE, 5,
|
|
EGL_GREEN_SIZE, 6,
|
|
EGL_BLUE_SIZE, 5,
|
|
EGL_DEPTH_SIZE, 16,
|
|
EGL_ALPHA_SIZE, EGL_DONT_CARE,
|
|
EGL_STENCIL_SIZE, 2,
|
|
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
|
EGL_NONE };
|
|
|
|
CLUTTER_NOTE (BACKEND, "Realizing main stage");
|
|
|
|
backend_egl = CLUTTER_BACKEND_EGL (clutter_get_default_backend ());
|
|
|
|
status = eglGetConfigs (backend_egl->edpy,
|
|
configs,
|
|
2,
|
|
&config_count);
|
|
|
|
if (status != EGL_TRUE)
|
|
g_warning ("eglGetConfigs failed");
|
|
|
|
status = eglChooseConfig (backend_egl->edpy,
|
|
cfg_attribs,
|
|
configs,
|
|
G_N_ELEMENTS (configs),
|
|
&config_count);
|
|
|
|
if (status != EGL_TRUE)
|
|
{
|
|
g_critical ("eglChooseConfig failed");
|
|
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
|
return;
|
|
}
|
|
|
|
if (stage_egl->egl_surface != EGL_NO_SURFACE)
|
|
{
|
|
eglDestroySurface (backend_egl->edpy, stage_egl->egl_surface);
|
|
stage_egl->egl_surface = EGL_NO_SURFACE;
|
|
}
|
|
|
|
if (backend_egl->egl_context)
|
|
{
|
|
eglDestroyContext (backend_egl->edpy, backend_egl->egl_context);
|
|
backend_egl->egl_context = NULL;
|
|
}
|
|
|
|
stage_egl->egl_surface =
|
|
eglCreateWindowSurface (backend_egl->edpy,
|
|
configs[0],
|
|
NULL,
|
|
NULL);
|
|
|
|
|
|
|
|
if (stage_egl->egl_surface == EGL_NO_SURFACE)
|
|
{
|
|
g_critical ("Unable to create an EGL surface");
|
|
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
|
return;
|
|
}
|
|
|
|
eglQuerySurface (backend_egl->edpy,
|
|
stage_egl->egl_surface,
|
|
EGL_WIDTH,
|
|
&stage_egl->surface_width);
|
|
|
|
eglQuerySurface (backend_egl->edpy,
|
|
stage_egl->egl_surface,
|
|
EGL_HEIGHT,
|
|
&stage_egl->surface_height);
|
|
|
|
CLUTTER_NOTE (BACKEND, "EGL surface is %ix%i",
|
|
stage_egl->surface_width,
|
|
stage_egl->surface_height);
|
|
|
|
|
|
if (G_UNLIKELY (backend_egl->egl_context == NULL))
|
|
{
|
|
CLUTTER_NOTE (GL, "Creating EGL Context");
|
|
|
|
backend_egl->egl_context = eglCreateContext (backend_egl->edpy,
|
|
configs[0],
|
|
EGL_NO_CONTEXT,
|
|
NULL);
|
|
|
|
if (backend_egl->egl_context == EGL_NO_CONTEXT)
|
|
{
|
|
g_critical ("Unable to create a suitable EGL context");
|
|
|
|
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* this will make sure to set the current context */
|
|
CLUTTER_NOTE (BACKEND, "Setting context");
|
|
|
|
/* this should be done in ClutterBackend::ensure_context */
|
|
status = eglMakeCurrent (backend_egl->edpy,
|
|
stage_egl->egl_surface,
|
|
stage_egl->egl_surface,
|
|
backend_egl->egl_context);
|
|
|
|
if (status != EGL_TRUE)
|
|
{
|
|
g_critical ("eglMakeCurrent failed");
|
|
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
|
return;
|
|
}
|
|
}
|
|
|
|
static void
|
|
clutter_stage_egl_get_preferred_width (ClutterActor *self,
|
|
gfloat for_height,
|
|
gfloat *min_width_p,
|
|
gfloat *natural_width_p)
|
|
{
|
|
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (self);
|
|
|
|
if (min_width_p)
|
|
*min_width_p = CLUTTER_UNITS_FROM_DEVICE (stage_egl->surface_width);
|
|
|
|
if (natural_width_p)
|
|
*natural_width_p = CLUTTER_UNITS_FROM_DEVICE (stage_egl->surface_width);
|
|
}
|
|
|
|
static void
|
|
clutter_stage_egl_get_preferred_height (ClutterActor *self,
|
|
gfloat for_width,
|
|
gfloat *min_height_p,
|
|
gfloat *natural_height_p)
|
|
{
|
|
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (self);
|
|
|
|
if (min_height_p)
|
|
*min_height_p = CLUTTER_UNITS_FROM_DEVICE (stage_egl->surface_height);
|
|
|
|
if (natural_height_p)
|
|
*natural_height_p = CLUTTER_UNITS_FROM_DEVICE (stage_egl->surface_height);
|
|
}
|
|
|
|
static void
|
|
clutter_stage_egl_dispose (GObject *gobject)
|
|
{
|
|
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (gobject);
|
|
|
|
G_OBJECT_CLASS (clutter_stage_egl_parent_class)->dispose (gobject);
|
|
}
|
|
|
|
static void
|
|
clutter_stage_egl_class_init (ClutterStageEGLClass *klass)
|
|
{
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
|
|
|
gobject_class->dispose = clutter_stage_egl_dispose;
|
|
|
|
actor_class->show = clutter_stage_egl_show;
|
|
actor_class->hide = clutter_stage_egl_hide;
|
|
actor_class->realize = clutter_stage_egl_realize;
|
|
actor_class->unrealize = clutter_stage_egl_unrealize;
|
|
actor_class->get_preferred_width = clutter_stage_egl_get_preferred_width;
|
|
actor_class->get_preferred_height = clutter_stage_egl_get_preferred_height;
|
|
}
|
|
|
|
static void
|
|
clutter_stage_egl_set_fullscreen (ClutterStageWindow *stage_window,
|
|
gboolean fullscreen)
|
|
{
|
|
g_warning ("Stage of type '%s' do not support ClutterStage::set_fullscreen",
|
|
G_OBJECT_TYPE_NAME (stage_window));
|
|
}
|
|
|
|
static ClutterActor *
|
|
clutter_stage_egl_get_wrapper (ClutterStageWindow *stage_window)
|
|
{
|
|
return CLUTTER_ACTOR (CLUTTER_STAGE_EGL (stage_window)->wrapper);
|
|
}
|
|
|
|
static void
|
|
clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
|
|
{
|
|
iface->set_fullscreen = clutter_stage_egl_set_fullscreen;
|
|
iface->set_title = NULL;
|
|
iface->get_wrapper = clutter_stage_egl_get_wrapper;
|
|
}
|
|
|
|
static void
|
|
clutter_stage_egl_init (ClutterStageEGL *stage)
|
|
{
|
|
}
|