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 ClutterActor * clutter_backend_egl_create_stage (ClutterBackend *backend, ClutterStage *wrapper, GError **error) { ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend); ClutterStageEGL *stage_egl; ClutterActor *stage; if (backend_egl->stage) { g_warning ("The EGL native backend does not support multiple stages"); return backend_egl->stage; } stage = g_object_new (CLUTTER_TYPE_STAGE_FRUITY, NULL); stage_egl = CLUTTER_STAGE_EGL (stage); stage_egl->backend = backend_egl; stage_egl->wrapper = wrapper; backend_egl->stage = CLUTTER_ACTOR (stage_egl); return stage; }
static void clutter_stage_egl_hide (ClutterActor *actor) { CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_MAPPED); CLUTTER_ACTOR_UNSET_FLAGS (CLUTTER_STAGE_EGL (actor)->wrapper, CLUTTER_ACTOR_MAPPED); }
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_backend_egl_redraw (ClutterBackend *backend, ClutterStage *stage) { ClutterStageWindow *impl; impl = _clutter_stage_get_window (stage); if (!impl) return; g_assert (CLUTTER_IS_STAGE_EGL (impl)); clutter_stage_egl_redraw (CLUTTER_STAGE_EGL (impl), stage); }
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_backend_egl_redraw (ClutterBackend *backend, ClutterStage *stage) { ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend); ClutterStageEGL *stage_egl; ClutterStageWindow *impl; impl = _clutter_stage_get_window (stage); if (!impl) return; g_assert (CLUTTER_IS_STAGE_EGL (impl)); stage_egl = CLUTTER_STAGE_EGL (impl); eglWaitNative (EGL_CORE_NATIVE_ENGINE); clutter_actor_paint (CLUTTER_ACTOR (stage)); cogl_flush (); eglWaitGL(); eglSwapBuffers (backend_egl->edpy, stage_egl->egl_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; gboolean is_offscreen; CLUTTER_NOTE (BACKEND, "Realizing main stage"); g_object_get (stage_egl->wrapper, "offscreen", &is_offscreen, NULL); backend_egl = CLUTTER_BACKEND_EGL (clutter_get_default_backend ()); if (G_LIKELY (!is_offscreen)) { 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 }; 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; } } else { g_warning("EGL Backend does not yet support offscreen rendering\n"); CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED); } }
static ClutterActor * clutter_stage_egl_get_wrapper (ClutterStageWindow *stage_window) { return CLUTTER_ACTOR (CLUTTER_STAGE_EGL (stage_window)->wrapper); }
static void clutter_backend_egl_ensure_context (ClutterBackend *backend, ClutterStage *stage) { ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend); ClutterStageWindow *impl; if (stage == NULL || (CLUTTER_PRIVATE_FLAGS (stage) & CLUTTER_ACTOR_IN_DESTRUCTION) || ((impl = _clutter_stage_get_window (stage)) == NULL)) { CLUTTER_NOTE (BACKEND, "Clearing EGL context"); eglMakeCurrent (backend_egl->edpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); } else { ClutterStageEGL *stage_egl; ClutterStageX11 *stage_x11; g_assert (impl != NULL); CLUTTER_NOTE (MULTISTAGE, "Setting context for stage of type %s [%p]", g_type_name (G_OBJECT_TYPE (impl)), impl); stage_egl = CLUTTER_STAGE_EGL (impl); stage_x11 = CLUTTER_STAGE_X11 (impl); if (backend_egl->egl_context == EGL_NO_CONTEXT) return; clutter_x11_trap_x_errors (); /* we might get here inside the final dispose cycle, so we * need to handle this gracefully */ if (stage_x11->xwin == None || stage_egl->egl_surface == EGL_NO_SURFACE) { CLUTTER_NOTE (MULTISTAGE, "Received a stale stage, clearing all context"); if (backend_egl->dummy_surface == EGL_NO_SURFACE) eglMakeCurrent (backend_egl->edpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); else eglMakeCurrent (backend_egl->edpy, backend_egl->dummy_surface, backend_egl->dummy_surface, backend_egl->egl_context); } else { CLUTTER_NOTE (MULTISTAGE, "Setting real surface current"); eglMakeCurrent (backend_egl->edpy, stage_egl->egl_surface, stage_egl->egl_surface, backend_egl->egl_context); } if (clutter_x11_untrap_x_errors ()) g_critical ("Unable to make the stage window 0x%x the current " "EGLX drawable", (int) stage_x11->xwin); } }
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; gboolean is_offscreen; CLUTTER_NOTE (BACKEND, "Realizing main stage"); g_object_get (stage_egl->wrapper, "offscreen", &is_offscreen, NULL); backend_egl = CLUTTER_BACKEND_EGL (clutter_get_default_backend ()); if (G_LIKELY (!is_offscreen)) { 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, #ifdef HAVE_COGL_GLES2 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, #else /* HAVE_COGL_GLES2 */ EGL_SURFACE_TYPE, EGL_WINDOW_BIT, #endif /* HAVE_COGL_GLES2 */ EGL_NONE }; status = eglGetConfigs (backend_egl->edpy, configs, 2, &config_count); if (status != EGL_TRUE) { g_critical ("eglGetConfigs failed"); CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED); return; } 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; } CLUTTER_NOTE (BACKEND, "Got %i configs", config_count); 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)) { #ifdef HAVE_COGL_GLES2 static const EGLint attribs[3] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; backend_egl->egl_context = eglCreateContext (backend_egl->edpy, configs[0], EGL_NO_CONTEXT, attribs); #else /* Seems some GLES implementations 1.x do not like attribs... */ backend_egl->egl_context = eglCreateContext (backend_egl->edpy, configs[0], EGL_NO_CONTEXT, NULL); #endif 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; } CLUTTER_NOTE (GL, "Created EGL Context"); } CLUTTER_NOTE (BACKEND, "Setting context"); /* eglnative can have only one stage */ 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; } /* since we only have one size and it cannot change, we * just need to update the GL viewport now that we have * been realized */ CLUTTER_SET_PRIVATE_FLAGS (actor, CLUTTER_ACTOR_SYNC_MATRICES); } else { g_warning ("EGL Backend does not yet support offscreen rendering\n"); CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED); return; } }