mirror of
https://github.com/brl/mutter.git
synced 2025-01-23 09:59:03 +00:00
Moves all EGL code down from Clutter to Cogl
As was recently done for the GLX window system code, this commit moves the EGL window system code down from the Clutter backend code into a Cogl winsys. Note: currently the cogl/configure.ac is hard coded to only build the GLX winsys so currently this is only available when building Cogl as part of Clutter.
This commit is contained in:
parent
ce0dc2160c
commit
c55cffbb6b
@ -471,8 +471,6 @@ evdev_h_priv = \
|
|||||||
$(srcdir)/evdev/clutter-input-device-evdev.h \
|
$(srcdir)/evdev/clutter-input-device-evdev.h \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
egl_cex_c_priv = $(srcdir)/egl/clutter-backend-cex100.c
|
|
||||||
egl_cex_h_priv = $(srcdir)/egl/clutter-backend-cex100.h
|
|
||||||
egl_cex_h = $(srcdir)/egl/clutter-cex100.h
|
egl_cex_h = $(srcdir)/egl/clutter-cex100.h
|
||||||
|
|
||||||
if SUPPORT_EGL
|
if SUPPORT_EGL
|
||||||
@ -487,8 +485,6 @@ egl_source_h_priv += $(evdev_h_priv)
|
|||||||
endif # SUPPORT_EVDEV
|
endif # SUPPORT_EVDEV
|
||||||
|
|
||||||
if SUPPORT_CEX100
|
if SUPPORT_CEX100
|
||||||
egl_source_c_priv += $(egl_cex_c_priv)
|
|
||||||
egl_source_h_priv += $(egl_cex_h_priv)
|
|
||||||
egl_source_h += $(egl_cex_h)
|
egl_source_h += $(egl_cex_h)
|
||||||
endif # SUPPORT_CEX100
|
endif # SUPPORT_CEX100
|
||||||
|
|
||||||
|
@ -332,18 +332,15 @@ cogl_sources_c += \
|
|||||||
endif
|
endif
|
||||||
if SUPPORT_EGL_PLATFORM_POWERVR_X11
|
if SUPPORT_EGL_PLATFORM_POWERVR_X11
|
||||||
cogl_sources_c += \
|
cogl_sources_c += \
|
||||||
$(srcdir)/winsys/cogl-winsys-egl.c \
|
$(srcdir)/winsys/cogl-winsys-egl.c
|
||||||
$(srcdir)/winsys/cogl-winsys-stub.c
|
|
||||||
endif
|
endif
|
||||||
if SUPPORT_EGL_PLATFORM_POWERVR_NULL
|
if SUPPORT_EGL_PLATFORM_POWERVR_NULL
|
||||||
cogl_sources_c += \
|
cogl_sources_c += \
|
||||||
$(srcdir)/winsys/cogl-winsys-egl.c \
|
$(srcdir)/winsys/cogl-winsys-egl.c
|
||||||
$(srcdir)/winsys/cogl-winsys-stub.c
|
|
||||||
endif
|
endif
|
||||||
if SUPPORT_EGL_PLATFORM_POWERVR_GDL
|
if SUPPORT_EGL_PLATFORM_POWERVR_GDL
|
||||||
cogl_sources_c += \
|
cogl_sources_c += \
|
||||||
$(srcdir)/winsys/cogl-winsys-egl.c \
|
$(srcdir)/winsys/cogl-winsys-egl.c
|
||||||
$(srcdir)/winsys/cogl-winsys-stub.c
|
|
||||||
endif
|
endif
|
||||||
if SUPPORT_WIN32
|
if SUPPORT_WIN32
|
||||||
cogl_sources_c += \
|
cogl_sources_c += \
|
||||||
|
@ -475,3 +475,12 @@ cogl_set_default_context (CoglContext *context)
|
|||||||
cogl_object_unref (_context);
|
cogl_object_unref (_context);
|
||||||
_context = context;
|
_context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef COGL_HAS_EGL_SUPPORT
|
||||||
|
EGLDisplay
|
||||||
|
cogl_context_egl_get_egl_display (CoglContext *context)
|
||||||
|
{
|
||||||
|
return _cogl_winsys_context_egl_get_egl_display (context);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@ -33,6 +33,17 @@
|
|||||||
|
|
||||||
#include <cogl/cogl-display.h>
|
#include <cogl/cogl-display.h>
|
||||||
|
|
||||||
|
#ifdef COGL_HAS_EGL_SUPPORT
|
||||||
|
#ifdef COGL_HAS_GLES1
|
||||||
|
#include <GLES/gl.h>
|
||||||
|
#include <GLES/egl.h>
|
||||||
|
#else
|
||||||
|
#include <EGL/egl.h>
|
||||||
|
#define NativeDisplayType EGLNativeDisplayType
|
||||||
|
#define NativeWindowType EGLNativeWindowType
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -61,6 +72,12 @@ cogl_context_new (CoglDisplay *display,
|
|||||||
void
|
void
|
||||||
cogl_set_default_context (CoglContext *context);
|
cogl_set_default_context (CoglContext *context);
|
||||||
|
|
||||||
|
#ifdef COGL_HAS_EGL_SUPPORT
|
||||||
|
#define cogl_context_egl_get_egl_display cogl_context_egl_get_egl_display_EXP
|
||||||
|
EGLDisplay
|
||||||
|
cogl_context_egl_get_egl_display (CoglContext *context);
|
||||||
|
#endif
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __COGL_CONTEXT_H__ */
|
#endif /* __COGL_CONTEXT_H__ */
|
||||||
|
57
clutter/cogl/cogl/winsys/cogl-winsys-egl-feature-functions.h
Normal file
57
clutter/cogl/cogl/winsys/cogl-winsys-egl-feature-functions.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* Cogl
|
||||||
|
*
|
||||||
|
* An object oriented GL/GLES Abstraction/Utility Layer
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 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/>.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This can be included multiple times with different definitions for
|
||||||
|
* the COGL_WINSYS_FEATURE_* functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Macro prototypes:
|
||||||
|
* COGL_WINSYS_FEATURE_BEGIN (name, namespaces, extension_names,
|
||||||
|
* implied_public_feature_flags,
|
||||||
|
* implied_private_feature_flags,
|
||||||
|
* implied_winsys_feature)
|
||||||
|
* COGL_WINSYS_FEATURE_FUNCTION (return_type, function_name,
|
||||||
|
* (arguments))
|
||||||
|
* ...
|
||||||
|
* COGL_WINSYS_FEATURE_END ()
|
||||||
|
*
|
||||||
|
* Note: You can list multiple namespace and extension names if the
|
||||||
|
* corresponding _FEATURE_FUNCTIONS have the same semantics accross
|
||||||
|
* the different extension variants.
|
||||||
|
*
|
||||||
|
* XXX: NB: Don't add a trailing semicolon when using these macros
|
||||||
|
*/
|
||||||
|
|
||||||
|
COGL_WINSYS_FEATURE_BEGIN (swap_region,
|
||||||
|
"NOK\0",
|
||||||
|
"swap_region\0",
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
COGL_WINSYS_FEATURE_SWAP_REGION)
|
||||||
|
COGL_WINSYS_FEATURE_FUNCTION (EGLBoolean, eglSwapBuffersRegion,
|
||||||
|
(EGLDisplay dpy,
|
||||||
|
EGLSurface surface,
|
||||||
|
EGLint numRects,
|
||||||
|
const EGLint *rects))
|
||||||
|
COGL_WINSYS_FEATURE_END ()
|
File diff suppressed because it is too large
Load Diff
@ -71,6 +71,11 @@ _cogl_winsys_context_init (CoglContext *context, GError **error);
|
|||||||
void
|
void
|
||||||
_cogl_winsys_context_deinit (CoglContext *context);
|
_cogl_winsys_context_deinit (CoglContext *context);
|
||||||
|
|
||||||
|
#ifdef COGL_HAS_EGL_SUPPORT
|
||||||
|
EGLDisplay
|
||||||
|
_cogl_winsys_context_egl_get_egl_display (CoglContext *context);
|
||||||
|
#endif
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
_cogl_winsys_has_feature (CoglWinsysFeature feature);
|
_cogl_winsys_has_feature (CoglWinsysFeature feature);
|
||||||
|
|
||||||
|
@ -1,369 +0,0 @@
|
|||||||
/*
|
|
||||||
* Clutter.
|
|
||||||
*
|
|
||||||
* An OpenGL based 'interactive canvas' library.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2010 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:
|
|
||||||
* Tao Zhao <tao.zhao@intel.com>
|
|
||||||
* Damien Lespiau <damien.lespiau@intel.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
#include "clutter-debug.h"
|
|
||||||
#include "clutter-main.h"
|
|
||||||
|
|
||||||
#include "clutter-backend-cex100.h"
|
|
||||||
#include "clutter-cex100.h"
|
|
||||||
|
|
||||||
static gdl_plane_id_t gdl_plane = GDL_PLANE_ID_UPP_C;
|
|
||||||
static guint gdl_n_buffers = CLUTTER_CEX100_TRIPLE_BUFFERING;
|
|
||||||
|
|
||||||
G_DEFINE_TYPE (ClutterBackendCex100,
|
|
||||||
clutter_backend_cex100,
|
|
||||||
CLUTTER_TYPE_BACKEND_EGL)
|
|
||||||
|
|
||||||
#ifdef CLUTTER_ENABLE_DEBUG
|
|
||||||
static const gchar *
|
|
||||||
gdl_get_plane_name (gdl_plane_id_t plane)
|
|
||||||
{
|
|
||||||
switch (plane)
|
|
||||||
{
|
|
||||||
case GDL_PLANE_ID_UPP_A:
|
|
||||||
return "UPP_A";
|
|
||||||
case GDL_PLANE_ID_UPP_B:
|
|
||||||
return "UPP_B";
|
|
||||||
case GDL_PLANE_ID_UPP_C:
|
|
||||||
return "UPP_C";
|
|
||||||
case GDL_PLANE_ID_UPP_D:
|
|
||||||
return "UPP_D";
|
|
||||||
case GDL_PLANE_ID_UPP_E:
|
|
||||||
return "UPP_E";
|
|
||||||
default:
|
|
||||||
g_assert_not_reached ();
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL; /* never reached */
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gdl_plane_init (gdl_display_id_t dpy,
|
|
||||||
gdl_plane_id_t plane,
|
|
||||||
gdl_pixel_format_t pixfmt)
|
|
||||||
{
|
|
||||||
gboolean ret = TRUE;
|
|
||||||
|
|
||||||
gdl_color_space_t colorSpace = GDL_COLOR_SPACE_RGB;
|
|
||||||
gdl_rectangle_t dstRect;
|
|
||||||
gdl_display_info_t display_info;
|
|
||||||
gdl_ret_t rc = GDL_SUCCESS;
|
|
||||||
|
|
||||||
if (GDL_DISPLAY_ID_0 != dpy && GDL_DISPLAY_ID_1 != dpy)
|
|
||||||
{
|
|
||||||
g_warning ("Invalid display ID, must be GDL_DISPLAY_ID_0 or "
|
|
||||||
"GDL_DISPLAY_ID_1.");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Init GDL library */
|
|
||||||
rc = gdl_init (NULL);
|
|
||||||
if (rc != GDL_SUCCESS)
|
|
||||||
{
|
|
||||||
g_warning ("GDL initialize failed. %s", gdl_get_error_string (rc));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = gdl_get_display_info (dpy, &display_info);
|
|
||||||
if (rc != GDL_SUCCESS)
|
|
||||||
{
|
|
||||||
g_warning ("GDL failed to get display infomation: %s",
|
|
||||||
gdl_get_error_string (rc));
|
|
||||||
gdl_close ();
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
dstRect.origin.x = 0;
|
|
||||||
dstRect.origin.y = 0;
|
|
||||||
dstRect.width = display_info.tvmode.width;
|
|
||||||
dstRect.height = display_info.tvmode.height;
|
|
||||||
|
|
||||||
/* Configure the plane attribute. */
|
|
||||||
rc = gdl_plane_reset (plane);
|
|
||||||
if (rc == GDL_SUCCESS)
|
|
||||||
rc = gdl_plane_config_begin (plane);
|
|
||||||
|
|
||||||
if (rc == GDL_SUCCESS)
|
|
||||||
rc = gdl_plane_set_attr (GDL_PLANE_SRC_COLOR_SPACE, &colorSpace);
|
|
||||||
|
|
||||||
if (rc == GDL_SUCCESS)
|
|
||||||
rc = gdl_plane_set_attr (GDL_PLANE_PIXEL_FORMAT, &pixfmt);
|
|
||||||
|
|
||||||
if (rc == GDL_SUCCESS)
|
|
||||||
rc = gdl_plane_set_attr (GDL_PLANE_DST_RECT, &dstRect);
|
|
||||||
|
|
||||||
if (rc == GDL_SUCCESS)
|
|
||||||
rc = gdl_plane_set_uint (GDL_PLANE_NUM_GFX_SURFACES, gdl_n_buffers);
|
|
||||||
|
|
||||||
if (rc == GDL_SUCCESS)
|
|
||||||
rc = gdl_plane_config_end (GDL_FALSE);
|
|
||||||
else
|
|
||||||
gdl_plane_config_end (GDL_TRUE);
|
|
||||||
|
|
||||||
if (rc != GDL_SUCCESS)
|
|
||||||
{
|
|
||||||
g_warning ("GDL configuration failed: %s.", gdl_get_error_string (rc));
|
|
||||||
ret = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
gdl_close ();
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ClutterBackendEGL implementation
|
|
||||||
*/
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
clutter_backend_cex100_create_context (ClutterBackend *backend,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
|
|
||||||
EGLConfig configs[2];
|
|
||||||
EGLint config_count;
|
|
||||||
EGLBoolean status;
|
|
||||||
NativeWindowType window;
|
|
||||||
EGLint cfg_attribs[] = {
|
|
||||||
EGL_BUFFER_SIZE, EGL_DONT_CARE,
|
|
||||||
EGL_RED_SIZE, 8,
|
|
||||||
EGL_GREEN_SIZE, 8,
|
|
||||||
EGL_BLUE_SIZE, 8,
|
|
||||||
EGL_DEPTH_SIZE, 16,
|
|
||||||
EGL_ALPHA_SIZE, 8,
|
|
||||||
EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE,
|
|
||||||
EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE,
|
|
||||||
#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
|
|
||||||
};
|
|
||||||
|
|
||||||
if (backend_egl->egl_context != EGL_NO_CONTEXT)
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
CLUTTER_NOTE (BACKEND, "Using the %s plane", gdl_get_plane_name (gdl_plane));
|
|
||||||
|
|
||||||
/* Start by initializing the GDL plane */
|
|
||||||
if (!gdl_plane_init (GDL_DISPLAY_ID_0, gdl_plane, GDL_PF_ARGB_32))
|
|
||||||
{
|
|
||||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
|
||||||
CLUTTER_INIT_ERROR_BACKEND,
|
|
||||||
"Could not initialize the GDL plane");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
window = (NativeWindowType) gdl_plane;
|
|
||||||
|
|
||||||
status = eglGetConfigs (backend_egl->edpy,
|
|
||||||
configs,
|
|
||||||
2,
|
|
||||||
&config_count);
|
|
||||||
|
|
||||||
if (status != EGL_TRUE)
|
|
||||||
{
|
|
||||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
|
||||||
CLUTTER_INIT_ERROR_BACKEND,
|
|
||||||
"No EGL configurations found");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = eglChooseConfig (backend_egl->edpy,
|
|
||||||
cfg_attribs,
|
|
||||||
configs,
|
|
||||||
G_N_ELEMENTS (configs),
|
|
||||||
&config_count);
|
|
||||||
|
|
||||||
if (status != EGL_TRUE)
|
|
||||||
{
|
|
||||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
|
||||||
CLUTTER_INIT_ERROR_BACKEND,
|
|
||||||
"Unable to select a valid EGL configuration");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
CLUTTER_NOTE (BACKEND, "Got %i configs", config_count);
|
|
||||||
|
|
||||||
if (status != EGL_TRUE)
|
|
||||||
{
|
|
||||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
|
||||||
CLUTTER_INIT_ERROR_BACKEND,
|
|
||||||
"Unable to Make Current Context for NULL");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (G_UNLIKELY (backend_egl->egl_surface != EGL_NO_SURFACE))
|
|
||||||
{
|
|
||||||
eglDestroySurface (backend_egl->edpy, backend_egl->egl_surface);
|
|
||||||
backend_egl->egl_surface = EGL_NO_SURFACE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (G_UNLIKELY (backend_egl->egl_context != NULL))
|
|
||||||
{
|
|
||||||
eglDestroyContext (backend_egl->edpy, backend_egl->egl_context);
|
|
||||||
backend_egl->egl_context = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
backend_egl->egl_surface = eglCreateWindowSurface (backend_egl->edpy,
|
|
||||||
configs[0],
|
|
||||||
window,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (backend_egl->egl_surface == EGL_NO_SURFACE)
|
|
||||||
{
|
|
||||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
|
||||||
CLUTTER_INIT_ERROR_BACKEND,
|
|
||||||
"Unable to create EGL window surface");
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#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_set_error (error, CLUTTER_INIT_ERROR,
|
|
||||||
CLUTTER_INIT_ERROR_BACKEND,
|
|
||||||
"Unable to create a suitable EGL context");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
CLUTTER_NOTE (GL, "Created EGL Context");
|
|
||||||
|
|
||||||
CLUTTER_NOTE (BACKEND, "Setting context");
|
|
||||||
|
|
||||||
/*
|
|
||||||
* eglnative can have only one stage, so we store the EGL surface in the
|
|
||||||
* backend itself, instead of the StageWindow implementation, and we make it
|
|
||||||
* current immediately to make sure the Cogl and Clutter can query the EGL
|
|
||||||
* context for features.
|
|
||||||
*/
|
|
||||||
status = eglMakeCurrent (backend_egl->edpy,
|
|
||||||
backend_egl->egl_surface,
|
|
||||||
backend_egl->egl_surface,
|
|
||||||
backend_egl->egl_context);
|
|
||||||
|
|
||||||
eglQuerySurface (backend_egl->edpy,
|
|
||||||
backend_egl->egl_surface,
|
|
||||||
EGL_WIDTH,
|
|
||||||
&backend_egl->surface_width);
|
|
||||||
|
|
||||||
eglQuerySurface (backend_egl->edpy,
|
|
||||||
backend_egl->egl_surface,
|
|
||||||
EGL_HEIGHT,
|
|
||||||
&backend_egl->surface_height);
|
|
||||||
|
|
||||||
CLUTTER_NOTE (BACKEND, "EGL surface is %ix%i",
|
|
||||||
backend_egl->surface_width,
|
|
||||||
backend_egl->surface_height);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For EGL backend, it needs to clear all the back buffers of the window
|
|
||||||
* surface before drawing anything, otherwise the image will be blinking
|
|
||||||
* heavily. The default eglWindowSurface has 3 gdl surfaces as the back
|
|
||||||
* buffer, that's why glClear should be called 3 times.
|
|
||||||
*/
|
|
||||||
glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
|
|
||||||
glClear (GL_COLOR_BUFFER_BIT);
|
|
||||||
eglSwapBuffers (backend_egl->edpy, backend_egl->egl_surface);
|
|
||||||
|
|
||||||
glClear (GL_COLOR_BUFFER_BIT);
|
|
||||||
eglSwapBuffers (backend_egl->edpy, backend_egl->egl_surface);
|
|
||||||
|
|
||||||
glClear (GL_COLOR_BUFFER_BIT);
|
|
||||||
eglSwapBuffers (backend_egl->edpy, backend_egl->egl_surface);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* GObject implementation
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_backend_cex100_class_init (ClutterBackendCex100Class *klass)
|
|
||||||
{
|
|
||||||
ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass);
|
|
||||||
|
|
||||||
backend_class->create_context = clutter_backend_cex100_create_context;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_backend_cex100_init (ClutterBackendCex100 *self)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* every backend must implement this function */
|
|
||||||
GType
|
|
||||||
_clutter_backend_impl_get_type (void)
|
|
||||||
{
|
|
||||||
return clutter_backend_cex100_get_type ();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
clutter_cex100_set_plane (gdl_plane_id_t plane)
|
|
||||||
{
|
|
||||||
g_return_if_fail (plane >= GDL_PLANE_ID_UPP_A && plane <= GDL_PLANE_ID_UPP_E);
|
|
||||||
|
|
||||||
gdl_plane = plane;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
clutter_cex100_set_buffering_mode (ClutterCex100BufferingMode mode)
|
|
||||||
{
|
|
||||||
g_return_if_fail (mode == CLUTTER_CEX100_DOUBLE_BUFFERING ||
|
|
||||||
mode == CLUTTER_CEX100_TRIPLE_BUFFERING);
|
|
||||||
|
|
||||||
gdl_n_buffers = mode;
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
/*
|
|
||||||
* Clutter.
|
|
||||||
*
|
|
||||||
* An OpenGL based 'interactive canvas' library.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2010 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/>.
|
|
||||||
*
|
|
||||||
* Author:
|
|
||||||
* Damien Lespiau <damien.lespiau@intel.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __CLUTTER_BACKEND_CEX100_H__
|
|
||||||
#define __CLUTTER_BACKEND_CEX100_H__
|
|
||||||
|
|
||||||
#include <libgdl.h>
|
|
||||||
|
|
||||||
#include <glib-object.h>
|
|
||||||
|
|
||||||
#include <clutter/egl/clutter-backend-egl.h>
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
|
||||||
|
|
||||||
#define CLUTTER_TYPE_BACKEND_CEX100 (clutter_backend_cex100_get_type())
|
|
||||||
#define CLUTTER_BACKEND_CEX100(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BACKEND_CEX100, ClutterBackendCex100))
|
|
||||||
#define CLUTTER_BACKEND_CEX100_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BACKEND_CEX100, ClutterBackendCex100Class))
|
|
||||||
#define CLUTTER_IS_BACKEND_CEX100(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BACKEND_CEX100))
|
|
||||||
#define CLUTTER_IS_BACKEND_CEX100_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BACKEND_CEX100))
|
|
||||||
#define CLUTTER_BACKEND_CEX100_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BACKEND_CEX100, ClutterBackendCex100Class))
|
|
||||||
|
|
||||||
typedef struct _ClutterBackendCex100 ClutterBackendCex100;
|
|
||||||
typedef struct _ClutterBackendCex100Class ClutterBackendCex100Class;
|
|
||||||
|
|
||||||
struct _ClutterBackendCex100
|
|
||||||
{
|
|
||||||
ClutterBackendEGL parent;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _ClutterBackendCex100Class
|
|
||||||
{
|
|
||||||
ClutterBackendEGLClass parent_class;
|
|
||||||
};
|
|
||||||
|
|
||||||
GType clutter_backend_cex100_get_type (void) G_GNUC_CONST;
|
|
||||||
|
|
||||||
G_END_DECLS
|
|
||||||
|
|
||||||
#endif /* __CLUTTER_BACKEND_CEX100_H__ */
|
|
@ -48,12 +48,20 @@
|
|||||||
#include "clutter-private.h"
|
#include "clutter-private.h"
|
||||||
#include "clutter-main.h"
|
#include "clutter-main.h"
|
||||||
#include "clutter-stage-private.h"
|
#include "clutter-stage-private.h"
|
||||||
|
/* FIXME: We should have CLUTTER_ define for this... */
|
||||||
|
#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_GDL_SUPPORT
|
||||||
|
#include "clutter-cex100.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
static ClutterBackendEGL *backend_singleton = NULL;
|
static ClutterBackendEGL *backend_singleton = NULL;
|
||||||
|
|
||||||
static const gchar *clutter_fb_device = NULL;
|
static gchar *clutter_vblank = NULL;
|
||||||
|
|
||||||
static gchar *clutter_vblank_name = NULL;
|
/* FIXME: We should have CLUTTER_ define for this... */
|
||||||
|
#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_GDL_SUPPORT
|
||||||
|
static gdl_plane_id_t gdl_plane = GDL_PLANE_ID_UPP_C;
|
||||||
|
static guint gdl_n_buffers = CLUTTER_CEX100_TRIPLE_BUFFERING;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef COGL_HAS_X11_SUPPORT
|
#ifdef COGL_HAS_X11_SUPPORT
|
||||||
G_DEFINE_TYPE (ClutterBackendEGL, _clutter_backend_egl, CLUTTER_TYPE_BACKEND_X11);
|
G_DEFINE_TYPE (ClutterBackendEGL, _clutter_backend_egl, CLUTTER_TYPE_BACKEND_X11);
|
||||||
@ -68,30 +76,35 @@ clutter_backend_at_exit (void)
|
|||||||
g_object_run_dispose (G_OBJECT (backend_singleton));
|
g_object_run_dispose (G_OBJECT (backend_singleton));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
G_CONST_RETURN gchar*
|
||||||
|
_clutter_backend_egl_get_vblank (void)
|
||||||
|
{
|
||||||
|
if (clutter_vblank && strcmp (clutter_vblank, "0") == 0)
|
||||||
|
return "none";
|
||||||
|
else
|
||||||
|
return clutter_vblank;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
clutter_backend_egl_pre_parse (ClutterBackend *backend,
|
clutter_backend_egl_pre_parse (ClutterBackend *backend,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
const gchar *env_string;
|
const gchar *env_string;
|
||||||
#ifdef COGL_HAS_X11_SUPPORT
|
#ifdef COGL_HAS_X11_SUPPORT
|
||||||
ClutterBackendClass *backend_x11_class =
|
ClutterBackendClass *parent_class =
|
||||||
CLUTTER_BACKEND_CLASS (_clutter_backend_egl_parent_class);
|
CLUTTER_BACKEND_CLASS (_clutter_backend_egl_parent_class);
|
||||||
|
|
||||||
if (!backend_x11_class->pre_parse (backend, error))
|
if (!parent_class->pre_parse (backend, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
env_string = g_getenv ("CLUTTER_VBLANK");
|
env_string = g_getenv ("CLUTTER_VBLANK");
|
||||||
if (env_string)
|
if (env_string)
|
||||||
{
|
{
|
||||||
clutter_vblank_name = g_strdup (env_string);
|
clutter_vblank = g_strdup (env_string);
|
||||||
env_string = NULL;
|
env_string = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
env_string = g_getenv ("CLUTTER_FB_DEVICE");
|
|
||||||
if (env_string != NULL && env_string[0] != '\0')
|
|
||||||
clutter_fb_device = g_strdup (env_string);
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,411 +112,21 @@ static gboolean
|
|||||||
clutter_backend_egl_post_parse (ClutterBackend *backend,
|
clutter_backend_egl_post_parse (ClutterBackend *backend,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
|
|
||||||
#ifdef COGL_HAS_X11_SUPPORT
|
#ifdef COGL_HAS_X11_SUPPORT
|
||||||
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
ClutterBackendClass *parent_class =
|
||||||
ClutterBackendClass *backend_x11_class =
|
|
||||||
CLUTTER_BACKEND_CLASS (_clutter_backend_egl_parent_class);
|
CLUTTER_BACKEND_CLASS (_clutter_backend_egl_parent_class);
|
||||||
#endif
|
|
||||||
EGLBoolean status;
|
|
||||||
|
|
||||||
#ifdef COGL_HAS_X11_SUPPORT
|
if (!parent_class->post_parse (backend, error))
|
||||||
if (!backend_x11_class->post_parse (backend, error))
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
#ifndef COGL_HAS_XLIB_SUPPORT
|
return TRUE;
|
||||||
#error "Clutter's EGL on X11 support currently only works with xlib Displays"
|
|
||||||
#endif
|
|
||||||
backend_egl->edpy =
|
|
||||||
eglGetDisplay ((NativeDisplayType) backend_x11->xdpy);
|
|
||||||
|
|
||||||
status = eglInitialize (backend_egl->edpy,
|
|
||||||
&backend_egl->egl_version_major,
|
|
||||||
&backend_egl->egl_version_minor);
|
|
||||||
#else
|
|
||||||
backend_egl->edpy = eglGetDisplay (EGL_DEFAULT_DISPLAY);
|
|
||||||
|
|
||||||
status = eglInitialize (backend_egl->edpy,
|
|
||||||
&backend_egl->egl_version_major,
|
|
||||||
&backend_egl->egl_version_minor);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
g_atexit (clutter_backend_at_exit);
|
g_atexit (clutter_backend_at_exit);
|
||||||
|
|
||||||
if (status != EGL_TRUE)
|
|
||||||
{
|
|
||||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
|
||||||
CLUTTER_INIT_ERROR_BACKEND,
|
|
||||||
"Unable to Initialize EGL");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
CLUTTER_NOTE (BACKEND, "EGL Reports version %i.%i",
|
|
||||||
backend_egl->egl_version_major,
|
|
||||||
backend_egl->egl_version_minor);
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
_clutter_backend_egl_blit_sub_buffer (ClutterBackendEGL *backend_egl,
|
|
||||||
EGLSurface drawable,
|
|
||||||
int x, int y, int width, int height)
|
|
||||||
{
|
|
||||||
if (backend_egl->swap_buffers_region)
|
|
||||||
{
|
|
||||||
EGLint rect[4] = {
|
|
||||||
x, y, width, height
|
|
||||||
};
|
|
||||||
backend_egl->swap_buffers_region (backend_egl->edpy,
|
|
||||||
drawable,
|
|
||||||
1,
|
|
||||||
rect);
|
|
||||||
}
|
|
||||||
#if 0 /* XXX need GL_ARB_draw_buffers */
|
|
||||||
else if (backend_egl->blit_framebuffer)
|
|
||||||
{
|
|
||||||
glDrawBuffer (GL_FRONT);
|
|
||||||
backend_egl->blit_framebuffer (x, y, x + width, y + height,
|
|
||||||
x, y, x + width, y + height,
|
|
||||||
GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
|
||||||
glDrawBuffer (GL_BACK);
|
|
||||||
glFlush();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
clutter_backend_egl_create_context (ClutterBackend *backend,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
|
|
||||||
#ifdef COGL_HAS_X11_SUPPORT
|
|
||||||
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
|
||||||
#endif
|
|
||||||
EGLConfig config;
|
|
||||||
EGLint config_count = 0;
|
|
||||||
EGLBoolean status;
|
|
||||||
EGLint cfg_attribs[] = {
|
|
||||||
/* NB: This must be the first attribute, since we may
|
|
||||||
* try and fallback to no stencil buffer */
|
|
||||||
EGL_STENCIL_SIZE, 2,
|
|
||||||
|
|
||||||
EGL_RED_SIZE, 1,
|
|
||||||
EGL_GREEN_SIZE, 1,
|
|
||||||
EGL_BLUE_SIZE, 1,
|
|
||||||
EGL_ALPHA_SIZE, EGL_DONT_CARE,
|
|
||||||
|
|
||||||
EGL_DEPTH_SIZE, 1,
|
|
||||||
|
|
||||||
EGL_BUFFER_SIZE, EGL_DONT_CARE,
|
|
||||||
|
|
||||||
#if defined (HAVE_COGL_GL)
|
|
||||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
|
|
||||||
#elif defined (HAVE_COGL_GLES2)
|
|
||||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
|
||||||
#else
|
|
||||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
|
|
||||||
#endif
|
|
||||||
|
|
||||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
|
||||||
|
|
||||||
EGL_NONE
|
|
||||||
};
|
|
||||||
EGLDisplay edpy;
|
|
||||||
gint retry_cookie = 0;
|
|
||||||
const char *error_message = NULL;
|
|
||||||
#ifdef COGL_HAS_XLIB_SUPPORT
|
|
||||||
XVisualInfo *xvisinfo;
|
|
||||||
XSetWindowAttributes attrs;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (backend_egl->egl_context != EGL_NO_CONTEXT)
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
edpy = clutter_egl_get_egl_display ();
|
|
||||||
|
|
||||||
/* XXX: we should get rid of this goto yukkyness, there is a fail:
|
|
||||||
* goto at the end and this retry: goto at the top, but we should just
|
|
||||||
* have a try_create_context() function and call it in a loop that
|
|
||||||
* tries a different fallback each iteration */
|
|
||||||
retry:
|
|
||||||
/* Here we can change the attributes depending on the fallback count... */
|
|
||||||
|
|
||||||
/* Some GLES hardware can't support a stencil buffer: */
|
|
||||||
if (retry_cookie == 1)
|
|
||||||
{
|
|
||||||
g_warning ("Trying with stencil buffer disabled...");
|
|
||||||
cfg_attribs[1 /* EGL_STENCIL_SIZE */] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XXX: at this point we only have one fallback */
|
|
||||||
|
|
||||||
status = eglChooseConfig (edpy,
|
|
||||||
cfg_attribs,
|
|
||||||
&config, 1,
|
|
||||||
&config_count);
|
|
||||||
if (status != EGL_TRUE || config_count == 0)
|
|
||||||
{
|
|
||||||
error_message = "Unable to select a valid EGL configuration";
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_COGL_GL
|
|
||||||
eglBindAPI (EGL_OPENGL_API);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (backend_egl->egl_context == EGL_NO_CONTEXT)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_COGL_GLES2
|
|
||||||
static const EGLint attribs[] =
|
|
||||||
{ EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
|
|
||||||
|
|
||||||
backend_egl->egl_context = eglCreateContext (edpy,
|
|
||||||
config,
|
|
||||||
EGL_NO_CONTEXT,
|
|
||||||
attribs);
|
|
||||||
|
|
||||||
#else
|
|
||||||
backend_egl->egl_context = eglCreateContext (edpy,
|
|
||||||
config,
|
|
||||||
EGL_NO_CONTEXT,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
if (backend_egl->egl_context == EGL_NO_CONTEXT)
|
|
||||||
{
|
|
||||||
error_message = "Unable to create a suitable EGL context";
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef COGL_HAS_XLIB_SUPPORT
|
|
||||||
backend_egl->egl_config = config;
|
|
||||||
#endif
|
|
||||||
CLUTTER_NOTE (GL, "Created EGL Context");
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef COGL_HAS_XLIB_SUPPORT
|
|
||||||
/* COGL assumes that there is always a GL context selected; in order
|
|
||||||
* to make sure that an EGL context exists and is made current, we use
|
|
||||||
* a dummy, offscreen override-redirect window to which we can always
|
|
||||||
* fall back if no stage is available */
|
|
||||||
|
|
||||||
xvisinfo = _clutter_backend_x11_get_visual_info (backend_x11);
|
|
||||||
if (xvisinfo == NULL)
|
|
||||||
{
|
|
||||||
g_critical ("Unable to find suitable GL visual.");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
attrs.override_redirect = True;
|
|
||||||
attrs.colormap = XCreateColormap (backend_x11->xdpy,
|
|
||||||
backend_x11->xwin_root,
|
|
||||||
xvisinfo->visual,
|
|
||||||
AllocNone);
|
|
||||||
attrs.border_pixel = 0;
|
|
||||||
|
|
||||||
backend_egl->dummy_xwin = XCreateWindow (backend_x11->xdpy,
|
|
||||||
backend_x11->xwin_root,
|
|
||||||
-100, -100, 1, 1,
|
|
||||||
0,
|
|
||||||
xvisinfo->depth,
|
|
||||||
CopyFromParent,
|
|
||||||
xvisinfo->visual,
|
|
||||||
CWOverrideRedirect |
|
|
||||||
CWColormap |
|
|
||||||
CWBorderPixel,
|
|
||||||
&attrs);
|
|
||||||
|
|
||||||
XFree (xvisinfo);
|
|
||||||
|
|
||||||
backend_egl->dummy_surface =
|
|
||||||
eglCreateWindowSurface (edpy,
|
|
||||||
backend_egl->egl_config,
|
|
||||||
(NativeWindowType) backend_egl->dummy_xwin,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (backend_egl->dummy_surface == EGL_NO_SURFACE)
|
|
||||||
{
|
|
||||||
g_critical ("Unable to create an EGL surface");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
eglMakeCurrent (edpy,
|
|
||||||
backend_egl->dummy_surface,
|
|
||||||
backend_egl->dummy_surface,
|
|
||||||
backend_egl->egl_context);
|
|
||||||
|
|
||||||
#else /* COGL_HAS_XLIB_SUPPORT */
|
|
||||||
|
|
||||||
if (clutter_fb_device != NULL)
|
|
||||||
{
|
|
||||||
int fd = open (clutter_fb_device, O_RDWR);
|
|
||||||
|
|
||||||
if (fd < 0)
|
|
||||||
{
|
|
||||||
int errno_save = errno;
|
|
||||||
|
|
||||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
|
||||||
CLUTTER_INIT_ERROR_BACKEND,
|
|
||||||
"Unable to open the framebuffer device '%s': %s",
|
|
||||||
clutter_fb_device,
|
|
||||||
g_strerror (errno_save));
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
backend_egl->fb_device_id = fd;
|
|
||||||
|
|
||||||
backend_egl->egl_surface =
|
|
||||||
eglCreateWindowSurface (edpy,
|
|
||||||
config,
|
|
||||||
(NativeWindowType) backend_egl->fb_device_id,
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
backend_egl->egl_surface =
|
|
||||||
eglCreateWindowSurface (edpy,
|
|
||||||
config,
|
|
||||||
(NativeWindowType) NULL,
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (backend_egl->egl_surface == EGL_NO_SURFACE)
|
|
||||||
{
|
|
||||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
|
||||||
CLUTTER_INIT_ERROR_BACKEND,
|
|
||||||
"Unable to create EGL window surface");
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
CLUTTER_NOTE (BACKEND, "Setting context");
|
|
||||||
|
|
||||||
/* Without X we assume we can have only one stage, so we
|
|
||||||
* store the EGL surface in the backend itself, instead
|
|
||||||
* of the StageWindow implementation, and we make it
|
|
||||||
* current immediately to make sure the Cogl and Clutter
|
|
||||||
* can query the EGL context for features.
|
|
||||||
*/
|
|
||||||
status = eglMakeCurrent (backend_egl->edpy,
|
|
||||||
backend_egl->egl_surface,
|
|
||||||
backend_egl->egl_surface,
|
|
||||||
backend_egl->egl_context);
|
|
||||||
|
|
||||||
eglQuerySurface (backend_egl->edpy,
|
|
||||||
backend_egl->egl_surface,
|
|
||||||
EGL_WIDTH,
|
|
||||||
&backend_egl->surface_width);
|
|
||||||
|
|
||||||
eglQuerySurface (backend_egl->edpy,
|
|
||||||
backend_egl->egl_surface,
|
|
||||||
EGL_HEIGHT,
|
|
||||||
&backend_egl->surface_height);
|
|
||||||
|
|
||||||
CLUTTER_NOTE (BACKEND, "EGL surface is %ix%i",
|
|
||||||
backend_egl->surface_width,
|
|
||||||
backend_egl->surface_height);
|
|
||||||
|
|
||||||
#endif /* COGL_HAS_XLIB_SUPPORT */
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
|
|
||||||
/* NB: We currently only support a single fallback option */
|
|
||||||
if (retry_cookie == 0)
|
|
||||||
{
|
|
||||||
retry_cookie = 1;
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
|
||||||
CLUTTER_INIT_ERROR_BACKEND,
|
|
||||||
"%s", error_message);
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_backend_egl_ensure_context (ClutterBackend *backend,
|
|
||||||
ClutterStage *stage)
|
|
||||||
{
|
|
||||||
#ifndef COGL_HAS_XLIB_SUPPORT
|
|
||||||
/* Without X we only have one EGL surface to worry about
|
|
||||||
* so we can assume it is permanently made current and
|
|
||||||
* don't have to do anything here. */
|
|
||||||
#else
|
|
||||||
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
|
|
||||||
ClutterStageWindow *impl;
|
|
||||||
|
|
||||||
if (stage == NULL ||
|
|
||||||
CLUTTER_ACTOR_IN_DESTRUCTION (stage) ||
|
|
||||||
((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);
|
|
||||||
}
|
|
||||||
#endif /* COGL_HAS_XLIB_SUPPORT */
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef COGL_HAS_XLIB_SUPPORT
|
#ifndef COGL_HAS_XLIB_SUPPORT
|
||||||
static ClutterDeviceManager *
|
static ClutterDeviceManager *
|
||||||
clutter_backend_egl_get_device_manager (ClutterBackend *backend)
|
clutter_backend_egl_get_device_manager (ClutterBackend *backend)
|
||||||
@ -553,72 +176,26 @@ clutter_backend_egl_finalize (GObject *gobject)
|
|||||||
static void
|
static void
|
||||||
clutter_backend_egl_dispose (GObject *gobject)
|
clutter_backend_egl_dispose (GObject *gobject)
|
||||||
{
|
{
|
||||||
|
ClutterBackend *backend = CLUTTER_BACKEND (gobject);
|
||||||
|
#ifdef HAVE_TSLIB
|
||||||
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (gobject);
|
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (gobject);
|
||||||
#ifdef COGL_HAS_X11_SUPPORT
|
|
||||||
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (gobject);
|
|
||||||
#else
|
|
||||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (backend_egl->stage);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* We chain up before disposing our own resources so that
|
/* We chain up before disposing our CoglContext so that we will
|
||||||
ClutterBackendX11 will destroy all of the stages before we
|
* destroy all of the stages first. Otherwise the actors may try to
|
||||||
destroy the egl context. Otherwise the actors may try to make GL
|
* make Cogl calls during destruction which would cause a crash */
|
||||||
calls during destruction which causes a crash */
|
|
||||||
G_OBJECT_CLASS (_clutter_backend_egl_parent_class)->dispose (gobject);
|
G_OBJECT_CLASS (_clutter_backend_egl_parent_class)->dispose (gobject);
|
||||||
|
|
||||||
|
if (backend->cogl_context)
|
||||||
|
{
|
||||||
|
cogl_object_unref (backend->cogl_context);
|
||||||
|
backend->cogl_context = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_TSLIB
|
#ifdef HAVE_TSLIB
|
||||||
/* XXX: This should be renamed to _clutter_events_tslib_uninit */
|
/* XXX: This should be renamed to _clutter_events_tslib_uninit */
|
||||||
_clutter_events_egl_uninit (backend_egl);
|
_clutter_events_egl_uninit (backend_egl);
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef COGL_HAS_XLIB_SUPPORT
|
|
||||||
if (backend_egl->dummy_surface != EGL_NO_SURFACE)
|
|
||||||
{
|
|
||||||
eglDestroySurface (backend_egl->edpy, backend_egl->dummy_surface);
|
|
||||||
backend_egl->dummy_surface = EGL_NO_SURFACE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (backend_egl->dummy_xwin)
|
|
||||||
{
|
|
||||||
XDestroyWindow (backend_x11->xdpy, backend_egl->dummy_xwin);
|
|
||||||
backend_egl->dummy_xwin = None;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* COGL_HAS_XLIB_SUPPORT */
|
|
||||||
|
|
||||||
if (backend_egl->egl_surface != EGL_NO_SURFACE)
|
|
||||||
{
|
|
||||||
eglDestroySurface (backend_egl->edpy, backend_egl->egl_surface);
|
|
||||||
backend_egl->egl_surface = EGL_NO_SURFACE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (backend_egl->stage != NULL)
|
|
||||||
{
|
|
||||||
clutter_actor_destroy (CLUTTER_ACTOR (stage_egl->wrapper));
|
|
||||||
backend_egl->stage = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (backend_egl->fb_device_id != -1)
|
|
||||||
{
|
|
||||||
close (backend_egl->fb_device_id);
|
|
||||||
backend_egl->fb_device_id = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* COGL_HAS_XLIB_SUPPORT */
|
|
||||||
|
|
||||||
if (backend_egl->egl_context)
|
|
||||||
{
|
|
||||||
eglDestroyContext (backend_egl->edpy, backend_egl->egl_context);
|
|
||||||
backend_egl->egl_context = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (backend_egl->edpy)
|
|
||||||
{
|
|
||||||
eglTerminate (backend_egl->edpy);
|
|
||||||
backend_egl->edpy = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_TSLIB
|
|
||||||
if (backend_egl->event_timer != NULL)
|
if (backend_egl->event_timer != NULL)
|
||||||
{
|
{
|
||||||
g_timer_destroy (backend_egl->event_timer);
|
g_timer_destroy (backend_egl->event_timer);
|
||||||
@ -651,87 +228,149 @@ clutter_backend_egl_constructor (GType gtype,
|
|||||||
return g_object_ref (backend_singleton);
|
return g_object_ref (backend_singleton);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
check_vblank_env (const char *name)
|
|
||||||
{
|
|
||||||
if (clutter_vblank_name && !g_ascii_strcasecmp (clutter_vblank_name, name))
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ClutterFeatureFlags
|
static ClutterFeatureFlags
|
||||||
clutter_backend_egl_get_features (ClutterBackend *backend)
|
clutter_backend_egl_get_features (ClutterBackend *backend)
|
||||||
{
|
{
|
||||||
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
|
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
|
||||||
const gchar *egl_extensions = NULL;
|
#ifdef COGL_HAS_XLIB_SUPPORT
|
||||||
const gchar *gl_extensions = NULL;
|
ClutterBackendClass *parent_class;
|
||||||
ClutterFeatureFlags flags;
|
#endif
|
||||||
|
ClutterFeatureFlags flags = 0;
|
||||||
g_assert (backend_egl->egl_context != NULL);
|
|
||||||
|
|
||||||
#ifdef COGL_HAS_XLIB_SUPPORT
|
#ifdef COGL_HAS_XLIB_SUPPORT
|
||||||
{
|
parent_class = CLUTTER_BACKEND_CLASS (_clutter_backend_egl_parent_class);
|
||||||
ClutterBackendClass *parent_class;
|
|
||||||
|
|
||||||
parent_class = CLUTTER_BACKEND_CLASS (_clutter_backend_egl_parent_class);
|
flags = parent_class->get_features (backend);
|
||||||
flags = parent_class->get_features (backend);
|
|
||||||
flags |= CLUTTER_FEATURE_STAGE_MULTIPLE;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
flags = CLUTTER_FEATURE_STAGE_STATIC;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* First check for explicit disabling or it set elsewhere (eg NVIDIA) */
|
if (cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN))
|
||||||
if (check_vblank_env ("none"))
|
{
|
||||||
backend_egl->vblank_type = CLUTTER_VBLANK_NONE;
|
CLUTTER_NOTE (BACKEND, "Cogl supports multiple onscreen framebuffers");
|
||||||
|
flags |= CLUTTER_FEATURE_STAGE_MULTIPLE;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
backend_egl->vblank_type = CLUTTER_VBLANK_SWAP_INTERVAL;
|
|
||||||
|
|
||||||
egl_extensions = eglQueryString (backend_egl->edpy, EGL_EXTENSIONS);
|
|
||||||
|
|
||||||
if (cogl_clutter_check_extension ("EGL_NOK_swap_region", egl_extensions))
|
|
||||||
{
|
{
|
||||||
CLUTTER_NOTE (BACKEND,
|
CLUTTER_NOTE (BACKEND, "Cogl only supports one onscreen framebuffer");
|
||||||
"Using EGL_NOK_swap_region for sub_buffer copies");
|
flags |= CLUTTER_FEATURE_STAGE_STATIC;
|
||||||
backend_egl->swap_buffers_region =
|
|
||||||
(void *)cogl_get_proc_address ("eglSwapBuffersRegionNOK");
|
|
||||||
backend_egl->can_blit_sub_buffer = TRUE;
|
|
||||||
backend_egl->blit_sub_buffer_is_synchronized = TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gl_extensions = (const gchar *)glGetString (GL_EXTENSIONS);
|
if (cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_THROTTLE))
|
||||||
|
|
||||||
#if 0 /* XXX need GL_ARB_draw_buffers */
|
|
||||||
if (!backend_egl->swap_buffers_region &&
|
|
||||||
cogl_clutter_check_extension ("GL_EXT_framebuffer_blit", gl_extensions))
|
|
||||||
{
|
{
|
||||||
CLUTTER_NOTE (BACKEND,
|
CLUTTER_NOTE (BACKEND, "Cogl supports swap buffers throttling");
|
||||||
"Using glBlitFramebuffer fallback for sub_buffer copies");
|
flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK;
|
||||||
backend_egl->blit_framebuffer =
|
|
||||||
(BlitFramebufferProc) cogl_get_proc_address ("glBlitFramebuffer");
|
|
||||||
backend_egl->can_blit_sub_buffer = TRUE;
|
|
||||||
backend_egl->blit_sub_buffer_is_synchronized = FALSE;
|
|
||||||
}
|
}
|
||||||
#endif
|
else
|
||||||
|
CLUTTER_NOTE (BACKEND, "Cogl doesn't support swap buffers throttling");
|
||||||
|
|
||||||
CLUTTER_NOTE (BACKEND, "Checking features\n"
|
if (cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_BUFFERS_EVENT))
|
||||||
"GL_VENDOR: %s\n"
|
{
|
||||||
"GL_RENDERER: %s\n"
|
CLUTTER_NOTE (BACKEND, "Cogl supports swap buffers complete events");
|
||||||
"GL_VERSION: %s\n"
|
flags |= CLUTTER_FEATURE_SWAP_EVENTS;
|
||||||
"EGL_VENDOR: %s\n"
|
}
|
||||||
"EGL_VERSION: %s\n"
|
|
||||||
"EGL_EXTENSIONS: %s\n",
|
if (cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_REGION))
|
||||||
glGetString (GL_VENDOR),
|
{
|
||||||
glGetString (GL_RENDERER),
|
CLUTTER_NOTE (BACKEND, "Cogl supports swapping buffer regions");
|
||||||
glGetString (GL_VERSION),
|
backend_egl->can_blit_sub_buffer = TRUE;
|
||||||
eglQueryString (backend_egl->edpy, EGL_VENDOR),
|
}
|
||||||
eglQueryString (backend_egl->edpy, EGL_VERSION),
|
|
||||||
eglQueryString (backend_egl->edpy, EGL_EXTENSIONS));
|
|
||||||
|
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef COGL_HAS_XLIB_SUPPORT
|
||||||
|
static XVisualInfo *
|
||||||
|
clutter_backend_egl_get_visual_info (ClutterBackendX11 *backend_x11)
|
||||||
|
{
|
||||||
|
return cogl_clutter_winsys_xlib_get_visual_info ();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
clutter_backend_egl_create_context (ClutterBackend *backend,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
#ifdef COGL_HAS_XLIB_SUPPORT
|
||||||
|
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
||||||
|
#endif
|
||||||
|
CoglSwapChain *swap_chain = NULL;
|
||||||
|
CoglOnscreenTemplate *onscreen_template = NULL;
|
||||||
|
|
||||||
|
if (backend->cogl_context)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
backend->cogl_renderer = cogl_renderer_new ();
|
||||||
|
#ifdef COGL_HAS_XLIB_SUPPORT
|
||||||
|
cogl_renderer_xlib_set_foreign_display (backend->cogl_renderer,
|
||||||
|
backend_x11->xdpy);
|
||||||
|
#endif
|
||||||
|
if (!cogl_renderer_connect (backend->cogl_renderer, error))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
swap_chain = cogl_swap_chain_new ();
|
||||||
|
#ifdef COGL_HAS_XLIB_SUPPORT
|
||||||
|
cogl_swap_chain_set_has_alpha (swap_chain,
|
||||||
|
clutter_x11_get_use_argb_visual ());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_GDL_SUPPORT
|
||||||
|
cogl_swap_chain_set_length (swap_chain, gdl_n_buffers);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
onscreen_template = cogl_onscreen_template_new (swap_chain);
|
||||||
|
cogl_object_unref (swap_chain);
|
||||||
|
|
||||||
|
/* XXX: I have some doubts that this is a good design.
|
||||||
|
* Conceptually should we be able to check an onscreen_template
|
||||||
|
* without more details about the CoglDisplay configuration?
|
||||||
|
*/
|
||||||
|
if (!cogl_renderer_check_onscreen_template (backend->cogl_renderer,
|
||||||
|
onscreen_template,
|
||||||
|
error))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
backend->cogl_display = cogl_display_new (backend->cogl_renderer,
|
||||||
|
onscreen_template);
|
||||||
|
|
||||||
|
#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_GDL_SUPPORT
|
||||||
|
cogl_display_cex100_set_gdl_plane (backend->cogl_display, gdl_plane);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
cogl_object_unref (backend->cogl_renderer);
|
||||||
|
cogl_object_unref (onscreen_template);
|
||||||
|
|
||||||
|
if (!cogl_display_setup (backend->cogl_display, error))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
backend->cogl_context = cogl_context_new (backend->cogl_display, error);
|
||||||
|
if (!backend->cogl_context)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
/* XXX: eventually this should go away but a lot of Cogl code still
|
||||||
|
* depends on a global default context. */
|
||||||
|
cogl_set_default_context (backend->cogl_context);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (backend->cogl_display)
|
||||||
|
{
|
||||||
|
cogl_object_unref (backend->cogl_display);
|
||||||
|
backend->cogl_display = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (onscreen_template)
|
||||||
|
cogl_object_unref (onscreen_template);
|
||||||
|
if (swap_chain)
|
||||||
|
cogl_object_unref (swap_chain);
|
||||||
|
|
||||||
|
if (backend->cogl_renderer)
|
||||||
|
{
|
||||||
|
cogl_object_unref (backend->cogl_renderer);
|
||||||
|
backend->cogl_renderer = NULL;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static ClutterStageWindow *
|
static ClutterStageWindow *
|
||||||
clutter_backend_egl_create_stage (ClutterBackend *backend,
|
clutter_backend_egl_create_stage (ClutterBackend *backend,
|
||||||
ClutterStage *wrapper,
|
ClutterStage *wrapper,
|
||||||
@ -768,7 +407,8 @@ clutter_backend_egl_create_stage (ClutterBackend *backend,
|
|||||||
{
|
{
|
||||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
g_set_error (error, CLUTTER_INIT_ERROR,
|
||||||
CLUTTER_INIT_ERROR_BACKEND,
|
CLUTTER_INIT_ERROR_BACKEND,
|
||||||
"The EGL native backend does not support multiple stages");
|
"The Cogl backend does not support multiple "
|
||||||
|
"onscreen windows");
|
||||||
return backend_egl->stage;
|
return backend_egl->stage;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -785,57 +425,15 @@ clutter_backend_egl_create_stage (ClutterBackend *backend,
|
|||||||
return stage;
|
return stage;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef COGL_HAS_XLIB_SUPPORT
|
static void
|
||||||
static XVisualInfo *
|
clutter_backend_egl_ensure_context (ClutterBackend *backend,
|
||||||
clutter_backend_egl_get_visual_info (ClutterBackendX11 *backend_x11)
|
ClutterStage *stage)
|
||||||
{
|
{
|
||||||
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend_x11);
|
ClutterStageEGL *stage_egl =
|
||||||
XVisualInfo visinfo_template;
|
CLUTTER_STAGE_EGL (_clutter_stage_get_window (stage));
|
||||||
int template_mask = 0;
|
|
||||||
XVisualInfo *visinfo = NULL;
|
|
||||||
int visinfos_count;
|
|
||||||
EGLint visualid, red_size, green_size, blue_size, alpha_size;
|
|
||||||
|
|
||||||
if (!clutter_backend_egl_create_context (CLUTTER_BACKEND (backend_x11), NULL))
|
cogl_set_framebuffer (COGL_FRAMEBUFFER (stage_egl->onscreen));
|
||||||
return NULL;
|
|
||||||
|
|
||||||
visinfo_template.screen = backend_x11->xscreen_num;
|
|
||||||
template_mask |= VisualScreenMask;
|
|
||||||
|
|
||||||
eglGetConfigAttrib (backend_egl->edpy, backend_egl->egl_config,
|
|
||||||
EGL_NATIVE_VISUAL_ID, &visualid);
|
|
||||||
|
|
||||||
if (visualid != 0)
|
|
||||||
{
|
|
||||||
visinfo_template.visualid = visualid;
|
|
||||||
template_mask |= VisualIDMask;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* some EGL drivers don't implement the EGL_NATIVE_VISUAL_ID
|
|
||||||
* attribute, so attempt to find the closest match. */
|
|
||||||
|
|
||||||
eglGetConfigAttrib (backend_egl->edpy, backend_egl->egl_config,
|
|
||||||
EGL_RED_SIZE, &red_size);
|
|
||||||
eglGetConfigAttrib (backend_egl->edpy, backend_egl->egl_config,
|
|
||||||
EGL_GREEN_SIZE, &green_size);
|
|
||||||
eglGetConfigAttrib (backend_egl->edpy, backend_egl->egl_config,
|
|
||||||
EGL_BLUE_SIZE, &blue_size);
|
|
||||||
eglGetConfigAttrib (backend_egl->edpy, backend_egl->egl_config,
|
|
||||||
EGL_ALPHA_SIZE, &alpha_size);
|
|
||||||
|
|
||||||
visinfo_template.depth = red_size + green_size + blue_size + alpha_size;
|
|
||||||
template_mask |= VisualDepthMask;
|
|
||||||
}
|
|
||||||
|
|
||||||
visinfo = XGetVisualInfo (backend_x11->xdpy,
|
|
||||||
template_mask,
|
|
||||||
&visinfo_template,
|
|
||||||
&visinfos_count);
|
|
||||||
|
|
||||||
return visinfo;
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_clutter_backend_egl_class_init (ClutterBackendEGLClass *klass)
|
_clutter_backend_egl_class_init (ClutterBackendEGLClass *klass)
|
||||||
@ -869,29 +467,16 @@ _clutter_backend_egl_class_init (ClutterBackendEGLClass *klass)
|
|||||||
static void
|
static void
|
||||||
_clutter_backend_egl_init (ClutterBackendEGL *backend_egl)
|
_clutter_backend_egl_init (ClutterBackendEGL *backend_egl)
|
||||||
{
|
{
|
||||||
#ifndef COGL_HAS_XLIB_SUPPORT
|
|
||||||
|
|
||||||
#ifdef HAVE_TSLIB
|
#ifdef HAVE_TSLIB
|
||||||
backend_egl->event_timer = g_timer_new ();
|
backend_egl->event_timer = g_timer_new ();
|
||||||
#endif
|
|
||||||
|
|
||||||
backend_egl->fb_device_id = -1;
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
backend_egl->egl_context = EGL_NO_CONTEXT;
|
|
||||||
backend_egl->dummy_surface = EGL_NO_SURFACE;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CLUTTER_EGL_BACKEND_GENERIC
|
|
||||||
GType
|
GType
|
||||||
_clutter_backend_impl_get_type (void)
|
_clutter_backend_impl_get_type (void)
|
||||||
{
|
{
|
||||||
return _clutter_backend_egl_get_type ();
|
return _clutter_backend_egl_get_type ();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
EGLDisplay
|
EGLDisplay
|
||||||
clutter_eglx_display (void)
|
clutter_eglx_display (void)
|
||||||
@ -914,5 +499,25 @@ clutter_egl_get_egl_display (void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return backend_singleton->edpy;
|
return cogl_context_egl_get_egl_display (backend_singleton->cogl_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME we should have a CLUTTER_ define for this */
|
||||||
|
#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_GDL_SUPPORT
|
||||||
|
void
|
||||||
|
clutter_cex100_set_plane (gdl_plane_id_t plane)
|
||||||
|
{
|
||||||
|
g_return_if_fail (plane >= GDL_PLANE_ID_UPP_A && plane <= GDL_PLANE_ID_UPP_E);
|
||||||
|
|
||||||
|
gdl_plane = plane;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_cex100_set_buffering_mode (ClutterCex100BufferingMode mode)
|
||||||
|
{
|
||||||
|
g_return_if_fail (mode == CLUTTER_CEX100_DOUBLE_BUFFERING ||
|
||||||
|
mode == CLUTTER_CEX100_TRIPLE_BUFFERING);
|
||||||
|
|
||||||
|
gdl_n_buffers = mode;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
@ -57,52 +57,14 @@ G_BEGIN_DECLS
|
|||||||
typedef struct _ClutterBackendEGL ClutterBackendEGL;
|
typedef struct _ClutterBackendEGL ClutterBackendEGL;
|
||||||
typedef struct _ClutterBackendEGLClass ClutterBackendEGLClass;
|
typedef struct _ClutterBackendEGLClass ClutterBackendEGLClass;
|
||||||
|
|
||||||
typedef enum ClutterEGLVBlankType {
|
|
||||||
CLUTTER_VBLANK_NONE = 0,
|
|
||||||
CLUTTER_VBLANK_SWAP_INTERVAL
|
|
||||||
} ClutterEGLVBlankType;
|
|
||||||
|
|
||||||
typedef void (*BlitFramebufferProc) (GLint srcX0,
|
|
||||||
GLint srcY0,
|
|
||||||
GLint srcX1,
|
|
||||||
GLint srcY1,
|
|
||||||
GLint dstX0,
|
|
||||||
GLint dstY0,
|
|
||||||
GLint dstX1,
|
|
||||||
GLint dstY1,
|
|
||||||
GLbitfield mask,
|
|
||||||
GLenum filter);
|
|
||||||
|
|
||||||
typedef EGLBoolean (*SwapBuffersRegionProc) (EGLDisplay dpy,
|
|
||||||
EGLSurface surface,
|
|
||||||
EGLint numRects,
|
|
||||||
const EGLint *rects);
|
|
||||||
struct _ClutterBackendEGL
|
struct _ClutterBackendEGL
|
||||||
{
|
{
|
||||||
#ifdef COGL_HAS_XLIB_SUPPORT
|
#ifdef COGL_HAS_XLIB_SUPPORT
|
||||||
ClutterBackendX11 parent_instance;
|
ClutterBackendX11 parent_instance;
|
||||||
|
|
||||||
/* EGL Specific */
|
|
||||||
EGLDisplay edpy;
|
|
||||||
EGLContext egl_context;
|
|
||||||
EGLConfig egl_config;
|
|
||||||
|
|
||||||
Window dummy_xwin;
|
|
||||||
EGLSurface dummy_surface;
|
|
||||||
|
|
||||||
#else /* COGL_HAS_X11_SUPPORT */
|
#else /* COGL_HAS_X11_SUPPORT */
|
||||||
|
|
||||||
ClutterBackend parent_instance;
|
ClutterBackend parent_instance;
|
||||||
|
|
||||||
/* EGL Specific */
|
|
||||||
EGLDisplay edpy;
|
|
||||||
EGLSurface egl_surface;
|
|
||||||
EGLContext egl_context;
|
|
||||||
|
|
||||||
/* from the backend */
|
|
||||||
gint surface_width;
|
|
||||||
gint surface_height;
|
|
||||||
|
|
||||||
/* main stage singleton */
|
/* main stage singleton */
|
||||||
ClutterStageWindow *stage;
|
ClutterStageWindow *stage;
|
||||||
|
|
||||||
@ -115,20 +77,11 @@ struct _ClutterBackendEGL
|
|||||||
/* event timer */
|
/* event timer */
|
||||||
GTimer *event_timer;
|
GTimer *event_timer;
|
||||||
|
|
||||||
/* FB device */
|
|
||||||
gint fb_device_id;
|
|
||||||
|
|
||||||
#endif /* COGL_HAS_X11_SUPPORT */
|
#endif /* COGL_HAS_X11_SUPPORT */
|
||||||
|
|
||||||
gint egl_version_major;
|
CoglContext *cogl_context;
|
||||||
gint egl_version_minor;
|
|
||||||
|
|
||||||
ClutterEGLVBlankType vblank_type;
|
gboolean can_blit_sub_buffer;
|
||||||
|
|
||||||
gboolean can_blit_sub_buffer;
|
|
||||||
BlitFramebufferProc blit_framebuffer;
|
|
||||||
SwapBuffersRegionProc swap_buffers_region;
|
|
||||||
gboolean blit_sub_buffer_is_synchronized;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _ClutterBackendEGLClass
|
struct _ClutterBackendEGLClass
|
||||||
@ -145,10 +98,8 @@ GType _clutter_backend_egl_get_type (void) G_GNUC_CONST;
|
|||||||
void _clutter_events_egl_init (ClutterBackendEGL *backend);
|
void _clutter_events_egl_init (ClutterBackendEGL *backend);
|
||||||
void _clutter_events_egl_uninit (ClutterBackendEGL *backend);
|
void _clutter_events_egl_uninit (ClutterBackendEGL *backend);
|
||||||
|
|
||||||
void
|
G_CONST_RETURN gchar*
|
||||||
_clutter_backend_egl_blit_sub_buffer (ClutterBackendEGL *backend_egl,
|
_clutter_backend_egl_get_vblank (void);
|
||||||
EGLSurface drawable,
|
|
||||||
int x, int y, int width, int height);
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
@ -32,41 +32,36 @@ G_DEFINE_TYPE_WITH_CODE (ClutterStageEGL,
|
|||||||
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW,
|
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW,
|
||||||
clutter_stage_window_iface_init));
|
clutter_stage_window_iface_init));
|
||||||
|
|
||||||
#ifdef COGL_HAS_XLIB_SUPPORT
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_stage_egl_unrealize (ClutterStageWindow *stage_window)
|
clutter_stage_egl_unrealize (ClutterStageWindow *stage_window)
|
||||||
{
|
{
|
||||||
ClutterBackend *backend = clutter_get_default_backend ();
|
|
||||||
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
|
||||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
|
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
|
||||||
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
|
|
||||||
|
|
||||||
CLUTTER_NOTE (BACKEND, "Unrealizing EGL stage [%p]", stage_egl);
|
CLUTTER_NOTE (BACKEND, "Unrealizing EGL stage [%p]", stage_egl);
|
||||||
|
|
||||||
clutter_x11_trap_x_errors ();
|
#ifdef COGL_HAS_XLIB_SUPPORT
|
||||||
|
/* chain up to the StageX11 implementation */
|
||||||
|
clutter_stage_window_parent_iface->unrealize (stage_window);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (stage_egl->egl_surface != EGL_NO_SURFACE)
|
cogl_object_unref (stage_egl->onscreen);
|
||||||
{
|
stage_egl->onscreen = NULL;
|
||||||
eglDestroySurface (clutter_egl_get_egl_display (), stage_egl->egl_surface);
|
|
||||||
stage_egl->egl_surface = EGL_NO_SURFACE;
|
|
||||||
}
|
|
||||||
|
|
||||||
_clutter_stage_x11_destroy_window_untrapped (stage_x11);
|
|
||||||
|
|
||||||
XSync (backend_x11->xdpy, False);
|
|
||||||
|
|
||||||
clutter_x11_untrap_x_errors ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
clutter_stage_egl_realize (ClutterStageWindow *stage_window)
|
clutter_stage_egl_realize (ClutterStageWindow *stage_window)
|
||||||
{
|
{
|
||||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
|
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
|
||||||
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
|
#ifdef COGL_HAS_XLIB_SUPPORT
|
||||||
ClutterBackend *backend;
|
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
|
||||||
|
#endif
|
||||||
|
ClutterBackend *backend;
|
||||||
ClutterBackendEGL *backend_egl;
|
ClutterBackendEGL *backend_egl;
|
||||||
EGLDisplay edpy;
|
CoglFramebuffer *framebuffer;
|
||||||
|
GError *error = NULL;
|
||||||
|
gfloat width = 800;
|
||||||
|
gfloat height = 600;
|
||||||
|
const char *clutter_vblank;
|
||||||
|
|
||||||
CLUTTER_NOTE (BACKEND, "Realizing stage '%s' [%p]",
|
CLUTTER_NOTE (BACKEND, "Realizing stage '%s' [%p]",
|
||||||
G_OBJECT_TYPE_NAME (stage_egl),
|
G_OBJECT_TYPE_NAME (stage_egl),
|
||||||
@ -75,40 +70,49 @@ clutter_stage_egl_realize (ClutterStageWindow *stage_window)
|
|||||||
backend = clutter_get_default_backend ();
|
backend = clutter_get_default_backend ();
|
||||||
backend_egl = CLUTTER_BACKEND_EGL (backend);
|
backend_egl = CLUTTER_BACKEND_EGL (backend);
|
||||||
|
|
||||||
edpy = clutter_egl_get_egl_display ();
|
#ifdef COGL_HAS_XLIB_SUPPORT
|
||||||
|
clutter_actor_get_size (CLUTTER_ACTOR (stage_x11->wrapper), &width, &height);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!_clutter_stage_x11_create_window (stage_x11))
|
stage_egl->onscreen = cogl_onscreen_new (backend->cogl_context,
|
||||||
return FALSE;
|
width, height);
|
||||||
|
#ifdef COGL_HAS_XLIB_SUPPORT
|
||||||
|
if (stage_x11->xwin != None)
|
||||||
|
cogl_onscreen_x11_set_foreign_window_xid (stage_egl->onscreen,
|
||||||
|
stage_x11->xwin);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (stage_egl->egl_surface == EGL_NO_SURFACE)
|
clutter_vblank = _clutter_backend_egl_get_vblank ();
|
||||||
|
if (clutter_vblank && strcmp (clutter_vblank, "none") == 0)
|
||||||
|
cogl_onscreen_set_swap_throttled (stage_egl->onscreen, FALSE);
|
||||||
|
|
||||||
|
framebuffer = COGL_FRAMEBUFFER (stage_egl->onscreen);
|
||||||
|
if (!cogl_framebuffer_allocate (framebuffer, &error))
|
||||||
{
|
{
|
||||||
stage_egl->egl_surface =
|
g_warning ("Failed to allocate stage: %s", error->message);
|
||||||
eglCreateWindowSurface (edpy,
|
g_error_free (error);
|
||||||
backend_egl->egl_config,
|
cogl_object_unref (stage_egl->onscreen);
|
||||||
(NativeWindowType) stage_x11->xwin,
|
stage_egl->onscreen = NULL;
|
||||||
NULL);
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
/* FIXME: for fullscreen EGL platforms then the size we gave above
|
||||||
|
* will be ignored, so we need to make sure the stage size is
|
||||||
|
* updated to this size. */
|
||||||
|
|
||||||
if (stage_egl->egl_surface == EGL_NO_SURFACE)
|
#ifdef COGL_HAS_XLIB_SUPPORT
|
||||||
g_warning ("Unable to create an EGL surface");
|
if (stage_x11->xwin == None)
|
||||||
|
stage_x11->xwin = cogl_onscreen_x11_get_window_xid (stage_egl->onscreen);
|
||||||
|
|
||||||
return clutter_stage_egl_parent_iface->realize (stage_window);
|
return clutter_stage_egl_parent_iface->realize (stage_window);
|
||||||
}
|
#else
|
||||||
|
|
||||||
#else /* COGL_HAS_XLIB_SUPPORT */
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_stage_egl_unrealize (ClutterStageWindow *stage_window)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
clutter_stage_egl_realize (ClutterStageWindow *stage_window)
|
|
||||||
{
|
|
||||||
/* the EGL surface is created by the backend */
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef COGL_HAS_XLIB_SUPPORT
|
||||||
|
|
||||||
|
/* FIXME: Move this warnings up into clutter-stage.c */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_stage_egl_set_fullscreen (ClutterStageWindow *stage_window,
|
clutter_stage_egl_set_fullscreen (ClutterStageWindow *stage_window,
|
||||||
gboolean fullscreen)
|
gboolean fullscreen)
|
||||||
@ -161,14 +165,25 @@ clutter_stage_egl_get_geometry (ClutterStageWindow *stage_window,
|
|||||||
ClutterGeometry *geometry)
|
ClutterGeometry *geometry)
|
||||||
{
|
{
|
||||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
|
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
|
||||||
ClutterBackendEGL *backend_egl = stage_egl->backend;
|
|
||||||
|
|
||||||
if (geometry)
|
if (geometry)
|
||||||
{
|
{
|
||||||
geometry->x = geometry->y = 0;
|
if (stage_egl->onscreen)
|
||||||
|
{
|
||||||
|
CoglFramebuffer *framebuffer =
|
||||||
|
COGL_FRAMEBUFFER (stage_egl->onscreen);
|
||||||
|
|
||||||
geometry->width = backend_egl->surface_width;
|
geometry->x = geometry->y = 0;
|
||||||
geometry->height = backend_egl->surface_height;
|
|
||||||
|
geometry->width = cogl_framebuffer_get_width (framebuffer);
|
||||||
|
geometry->height = cogl_framebuffer_get_height (framebuffer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
geometry->x = geometry->y = 0;
|
||||||
|
geometry->width = 800;
|
||||||
|
geometry->height = 600;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,30 +283,51 @@ clutter_stage_egl_add_redraw_clip (ClutterStageWindow *stage_window,
|
|||||||
stage_egl->initialized_redraw_clip = TRUE;
|
stage_egl->initialized_redraw_clip = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* XXX: This is basically identical to clutter_stage_glx_redraw */
|
||||||
static void
|
static void
|
||||||
clutter_stage_egl_redraw (ClutterStageWindow *stage_window)
|
clutter_stage_egl_redraw (ClutterStageWindow *stage_window)
|
||||||
{
|
{
|
||||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
|
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
|
||||||
ClutterBackend *backend = clutter_get_default_backend ();
|
|
||||||
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
|
|
||||||
ClutterActor *wrapper;
|
ClutterActor *wrapper;
|
||||||
EGLSurface egl_surface;
|
ClutterBackend *backend;
|
||||||
|
ClutterBackendEGL *backend_egl;
|
||||||
gboolean may_use_clipped_redraw;
|
gboolean may_use_clipped_redraw;
|
||||||
gboolean use_clipped_redraw;
|
gboolean use_clipped_redraw;
|
||||||
|
|
||||||
|
CLUTTER_STATIC_TIMER (painting_timer,
|
||||||
|
"Redrawing", /* parent */
|
||||||
|
"Painting actors",
|
||||||
|
"The time spent painting actors",
|
||||||
|
0 /* no application private data */);
|
||||||
|
CLUTTER_STATIC_TIMER (swapbuffers_timer,
|
||||||
|
"Redrawing", /* parent */
|
||||||
|
"eglSwapBuffers",
|
||||||
|
"The time spent blocked by eglSwapBuffers",
|
||||||
|
0 /* no application private data */);
|
||||||
|
CLUTTER_STATIC_TIMER (blit_sub_buffer_timer,
|
||||||
|
"Redrawing", /* parent */
|
||||||
|
"egl_blit_sub_buffer",
|
||||||
|
"The time spent in _egl_blit_sub_buffer",
|
||||||
|
0 /* no application private data */);
|
||||||
|
|
||||||
#ifdef COGL_HAS_X11_SUPPORT
|
#ifdef COGL_HAS_X11_SUPPORT
|
||||||
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_egl);
|
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_egl);
|
||||||
|
|
||||||
wrapper = CLUTTER_ACTOR (stage_x11->wrapper);
|
wrapper = CLUTTER_ACTOR (stage_x11->wrapper);
|
||||||
egl_surface = stage_egl->egl_surface;
|
|
||||||
#else
|
#else
|
||||||
wrapper = CLUTTER_ACTOR (stage_egl->wrapper);
|
wrapper = CLUTTER_ACTOR (stage_egl->wrapper);
|
||||||
/* Without X we only support one surface and that is associated
|
|
||||||
* with the backend directly instead of the stage */
|
|
||||||
egl_surface = backend_egl->egl_surface;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (!stage_egl->onscreen)
|
||||||
|
return;
|
||||||
|
|
||||||
|
backend = clutter_get_default_backend ();
|
||||||
|
backend_egl = CLUTTER_BACKEND_EGL (backend);
|
||||||
|
|
||||||
|
CLUTTER_TIMER_START (_clutter_uprof_context, painting_timer);
|
||||||
|
|
||||||
if (G_LIKELY (backend_egl->can_blit_sub_buffer) &&
|
if (G_LIKELY (backend_egl->can_blit_sub_buffer) &&
|
||||||
/* NB: a zero width clip == full stage redraw */
|
/* NB: a zero width redraw clip == full stage redraw */
|
||||||
stage_egl->bounding_redraw_clip.width != 0 &&
|
stage_egl->bounding_redraw_clip.width != 0 &&
|
||||||
/* some drivers struggle to get going and produce some junk
|
/* some drivers struggle to get going and produce some junk
|
||||||
* frames when starting up... */
|
* frames when starting up... */
|
||||||
@ -303,7 +339,9 @@ clutter_stage_egl_redraw (ClutterStageWindow *stage_window)
|
|||||||
&& G_LIKELY (stage_x11->clipped_redraws_cool_off == 0)
|
&& G_LIKELY (stage_x11->clipped_redraws_cool_off == 0)
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
may_use_clipped_redraw = TRUE;
|
{
|
||||||
|
may_use_clipped_redraw = TRUE;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
may_use_clipped_redraw = FALSE;
|
may_use_clipped_redraw = FALSE;
|
||||||
|
|
||||||
@ -327,11 +365,12 @@ clutter_stage_egl_redraw (ClutterStageWindow *stage_window)
|
|||||||
else
|
else
|
||||||
_clutter_stage_do_paint (CLUTTER_STAGE (wrapper), NULL);
|
_clutter_stage_do_paint (CLUTTER_STAGE (wrapper), NULL);
|
||||||
|
|
||||||
if (clutter_paint_debug_flags & CLUTTER_DEBUG_REDRAWS &&
|
if (may_use_clipped_redraw &&
|
||||||
may_use_clipped_redraw)
|
G_UNLIKELY ((clutter_paint_debug_flags & CLUTTER_DEBUG_REDRAWS)))
|
||||||
{
|
{
|
||||||
ClutterGeometry *clip = &stage_egl->bounding_redraw_clip;
|
|
||||||
static CoglMaterial *outline = NULL;
|
static CoglMaterial *outline = NULL;
|
||||||
|
ClutterGeometry *clip = &stage_egl->bounding_redraw_clip;
|
||||||
|
ClutterActor *actor = CLUTTER_ACTOR (wrapper);
|
||||||
CoglHandle vbo;
|
CoglHandle vbo;
|
||||||
float x_1 = clip->x;
|
float x_1 = clip->x;
|
||||||
float x_2 = clip->x + clip->width;
|
float x_2 = clip->x + clip->width;
|
||||||
@ -363,7 +402,7 @@ clutter_stage_egl_redraw (ClutterStageWindow *stage_window)
|
|||||||
|
|
||||||
cogl_push_matrix ();
|
cogl_push_matrix ();
|
||||||
cogl_matrix_init_identity (&modelview);
|
cogl_matrix_init_identity (&modelview);
|
||||||
_clutter_actor_apply_modelview_transform (wrapper, &modelview);
|
_clutter_actor_apply_modelview_transform (actor, &modelview);
|
||||||
cogl_set_modelview_matrix (&modelview);
|
cogl_set_modelview_matrix (&modelview);
|
||||||
cogl_set_source (outline);
|
cogl_set_source (outline);
|
||||||
cogl_vertex_buffer_draw (vbo, COGL_VERTICES_MODE_LINE_LOOP,
|
cogl_vertex_buffer_draw (vbo, COGL_VERTICES_MODE_LINE_LOOP,
|
||||||
@ -372,46 +411,52 @@ clutter_stage_egl_redraw (ClutterStageWindow *stage_window)
|
|||||||
cogl_object_unref (vbo);
|
cogl_object_unref (vbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
cogl_flush ();
|
CLUTTER_TIMER_STOP (_clutter_uprof_context, painting_timer);
|
||||||
|
|
||||||
/* push on the screen */
|
/* push on the screen */
|
||||||
if (use_clipped_redraw)
|
if (use_clipped_redraw)
|
||||||
{
|
{
|
||||||
ClutterGeometry *clip = &stage_egl->bounding_redraw_clip;
|
ClutterGeometry *clip = &stage_egl->bounding_redraw_clip;
|
||||||
ClutterGeometry copy_area;
|
int copy_area[4];
|
||||||
|
ClutterActor *actor;
|
||||||
|
|
||||||
|
/* XXX: It seems there will be a race here in that the stage
|
||||||
|
* window may be resized before the cogl_framebuffer_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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
actor = CLUTTER_ACTOR (wrapper);
|
||||||
|
copy_area[0] = clip->x;
|
||||||
|
copy_area[1] = clutter_actor_get_height (actor) - clip->y - clip->height;
|
||||||
|
copy_area[2] = clip->width;
|
||||||
|
copy_area[3] = clip->height;
|
||||||
|
|
||||||
CLUTTER_NOTE (BACKEND,
|
CLUTTER_NOTE (BACKEND,
|
||||||
"_egl_blit_sub_buffer (surface: %p, "
|
"cogl_framebuffer_swap_region (onscreen: %p, "
|
||||||
"x: %d, y: %d, "
|
"x: %d, y: %d, "
|
||||||
"width: %d, height: %d)",
|
"width: %d, height: %d)",
|
||||||
egl_surface,
|
stage_egl->onscreen,
|
||||||
stage_egl->bounding_redraw_clip.x,
|
copy_area[0], copy_area[1], copy_area[2], copy_area[3]);
|
||||||
stage_egl->bounding_redraw_clip.y,
|
|
||||||
stage_egl->bounding_redraw_clip.width,
|
|
||||||
stage_egl->bounding_redraw_clip.height);
|
|
||||||
|
|
||||||
copy_area.x = clip->x;
|
|
||||||
copy_area.y = clip->y;
|
|
||||||
copy_area.width = clip->width;
|
|
||||||
copy_area.height = clip->height;
|
|
||||||
|
|
||||||
CLUTTER_TIMER_START (_clutter_uprof_context, blit_sub_buffer_timer);
|
CLUTTER_TIMER_START (_clutter_uprof_context, blit_sub_buffer_timer);
|
||||||
_clutter_backend_egl_blit_sub_buffer (backend_egl,
|
|
||||||
egl_surface,
|
cogl_framebuffer_swap_region (COGL_FRAMEBUFFER (stage_egl->onscreen),
|
||||||
copy_area.x,
|
copy_area, 1);
|
||||||
copy_area.y,
|
|
||||||
copy_area.width,
|
|
||||||
copy_area.height);
|
|
||||||
CLUTTER_TIMER_STOP (_clutter_uprof_context, blit_sub_buffer_timer);
|
CLUTTER_TIMER_STOP (_clutter_uprof_context, blit_sub_buffer_timer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CLUTTER_NOTE (BACKEND, "eglwapBuffers (display: %p, surface: %p)",
|
CLUTTER_NOTE (BACKEND, "cogl_framebuffer_swap_buffers (onscreen: %p)",
|
||||||
backend_egl->edpy,
|
stage_egl->onscreen);
|
||||||
egl_surface);
|
|
||||||
|
|
||||||
CLUTTER_TIMER_START (_clutter_uprof_context, swapbuffers_timer);
|
CLUTTER_TIMER_START (_clutter_uprof_context, swapbuffers_timer);
|
||||||
eglSwapBuffers (backend_egl->edpy, egl_surface);
|
cogl_framebuffer_swap_buffers (COGL_FRAMEBUFFER (stage_egl->onscreen));
|
||||||
CLUTTER_TIMER_STOP (_clutter_uprof_context, swapbuffers_timer);
|
CLUTTER_TIMER_STOP (_clutter_uprof_context, swapbuffers_timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -467,25 +512,14 @@ _clutter_stage_egl_class_init (ClutterStageEGLClass *klass)
|
|||||||
|
|
||||||
gobject_class->dispose = clutter_stage_egl_dispose;
|
gobject_class->dispose = clutter_stage_egl_dispose;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
static void
|
|
||||||
_clutter_stage_egl_init (ClutterStageEGL *stage)
|
|
||||||
{
|
|
||||||
stage->egl_surface = EGL_NO_SURFACE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* COGL_HAS_X11_SUPPORT */
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_clutter_stage_egl_class_init (ClutterStageEGLClass *klass)
|
_clutter_stage_egl_class_init (ClutterStageEGLClass *klass)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
#endif /* COGL_HAS_X11_SUPPORT */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_clutter_stage_egl_init (ClutterStageEGL *stage)
|
_clutter_stage_egl_init (ClutterStageEGL *stage)
|
||||||
{
|
{
|
||||||
/* Without X we only support one surface and that is associated
|
|
||||||
* with the backend directly instead of the stage */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* COGL_HAS_X11_SUPPORT */
|
|
||||||
|
@ -36,8 +36,6 @@ struct _ClutterStageEGL
|
|||||||
|
|
||||||
ClutterStageX11 parent_instance;
|
ClutterStageX11 parent_instance;
|
||||||
|
|
||||||
EGLSurface egl_surface;
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
GObject parent_instance;
|
GObject parent_instance;
|
||||||
@ -50,6 +48,8 @@ struct _ClutterStageEGL
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
CoglOnscreen *onscreen;
|
||||||
|
|
||||||
/* We only enable clipped redraws after 2 frames, since we've seen
|
/* We only enable clipped redraws after 2 frames, since we've seen
|
||||||
* a lot of drivers can struggle to get going and may output some
|
* a lot of drivers can struggle to get going and may output some
|
||||||
* junk frames to start with. */
|
* junk frames to start with. */
|
||||||
|
@ -56,16 +56,9 @@ struct _ClutterBackendGLX
|
|||||||
{
|
{
|
||||||
ClutterBackendX11 parent_instance;
|
ClutterBackendX11 parent_instance;
|
||||||
|
|
||||||
int error_base;
|
CoglContext *cogl_context;
|
||||||
int event_base;
|
|
||||||
|
|
||||||
CoglContext *cogl_context;
|
gboolean can_blit_sub_buffer;
|
||||||
|
|
||||||
/* Vblank stuff */
|
|
||||||
ClutterGLXVBlankType vblank_type;
|
|
||||||
unsigned int last_video_sync_count;
|
|
||||||
|
|
||||||
gboolean can_blit_sub_buffer;
|
|
||||||
|
|
||||||
/* props */
|
/* props */
|
||||||
Atom atom_WM_STATE;
|
Atom atom_WM_STATE;
|
||||||
|
@ -1358,111 +1358,6 @@ clutter_x11_set_stage_foreign (ClutterStage *stage,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
_clutter_stage_x11_destroy_window_untrapped (ClutterStageX11 *stage_x11)
|
|
||||||
{
|
|
||||||
Window xwin = stage_x11->xwin;
|
|
||||||
|
|
||||||
if (clutter_stages_by_xid != NULL)
|
|
||||||
{
|
|
||||||
CLUTTER_NOTE (BACKEND, "Removing X11 stage 0x%x [%p]",
|
|
||||||
(unsigned int) xwin,
|
|
||||||
stage_x11);
|
|
||||||
|
|
||||||
g_hash_table_remove (clutter_stages_by_xid, GINT_TO_POINTER (xwin));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!stage_x11->is_foreign_xwin && xwin != None)
|
|
||||||
{
|
|
||||||
ClutterBackendX11 *backend_x11 = stage_x11->backend;
|
|
||||||
|
|
||||||
g_assert (clutter_stages_by_xid != NULL);
|
|
||||||
|
|
||||||
XDestroyWindow (backend_x11->xdpy, xwin);
|
|
||||||
stage_x11->xwin = None;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
stage_x11->xwin = None;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
_clutter_stage_x11_destroy_window (ClutterStageX11 *stage_x11)
|
|
||||||
{
|
|
||||||
if (stage_x11->xwin == None)
|
|
||||||
return;
|
|
||||||
|
|
||||||
clutter_x11_trap_x_errors ();
|
|
||||||
|
|
||||||
_clutter_stage_x11_destroy_window_untrapped (stage_x11);
|
|
||||||
|
|
||||||
clutter_x11_untrap_x_errors ();
|
|
||||||
}
|
|
||||||
|
|
||||||
gboolean
|
|
||||||
_clutter_stage_x11_create_window (ClutterStageX11 *stage_x11)
|
|
||||||
{
|
|
||||||
ClutterBackendX11 *backend_x11 = stage_x11->backend;
|
|
||||||
XSetWindowAttributes xattr;
|
|
||||||
XVisualInfo *xvisinfo;
|
|
||||||
unsigned long mask;
|
|
||||||
gfloat width, height;
|
|
||||||
|
|
||||||
if (stage_x11->xwin != None)
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
CLUTTER_NOTE (MISC, "Creating stage X window");
|
|
||||||
|
|
||||||
xvisinfo = _clutter_backend_x11_get_visual_info (backend_x11);
|
|
||||||
if (xvisinfo == NULL)
|
|
||||||
{
|
|
||||||
g_critical ("Unable to find suitable GL visual.");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* window attributes */
|
|
||||||
xattr.background_pixel = WhitePixel (backend_x11->xdpy,
|
|
||||||
backend_x11->xscreen_num);
|
|
||||||
xattr.border_pixel = 0;
|
|
||||||
xattr.colormap = XCreateColormap (backend_x11->xdpy,
|
|
||||||
backend_x11->xwin_root,
|
|
||||||
xvisinfo->visual,
|
|
||||||
AllocNone);
|
|
||||||
mask = CWBorderPixel | CWColormap;
|
|
||||||
|
|
||||||
/* Call get_size - this will either get the geometry size (which
|
|
||||||
* before we create the window is set to 640x480), or if a size
|
|
||||||
* is set, it will get that. This lets you set a size on the
|
|
||||||
* stage before it's realized.
|
|
||||||
*
|
|
||||||
* we also round to the nearest integer because stage sizes
|
|
||||||
* should always be in pixels
|
|
||||||
*/
|
|
||||||
clutter_actor_get_size (CLUTTER_ACTOR (stage_x11->wrapper), &width, &height);
|
|
||||||
stage_x11->xwin_width = floorf (width + 0.5);
|
|
||||||
stage_x11->xwin_height = floorf (height + 0.5);
|
|
||||||
|
|
||||||
stage_x11->xwin = XCreateWindow (backend_x11->xdpy,
|
|
||||||
backend_x11->xwin_root,
|
|
||||||
0, 0,
|
|
||||||
stage_x11->xwin_width,
|
|
||||||
stage_x11->xwin_height,
|
|
||||||
0,
|
|
||||||
xvisinfo->depth,
|
|
||||||
InputOutput,
|
|
||||||
xvisinfo->visual,
|
|
||||||
mask, &xattr);
|
|
||||||
|
|
||||||
CLUTTER_NOTE (BACKEND, "Stage [%p], window: 0x%x, size: %dx%d",
|
|
||||||
stage_x11,
|
|
||||||
(unsigned int) stage_x11->xwin,
|
|
||||||
stage_x11->xwin_width,
|
|
||||||
stage_x11->xwin_height);
|
|
||||||
|
|
||||||
XFree (xvisinfo);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_clutter_stage_x11_set_user_time (ClutterStageX11 *stage_x11,
|
_clutter_stage_x11_set_user_time (ClutterStageX11 *stage_x11,
|
||||||
guint32 user_time)
|
guint32 user_time)
|
||||||
|
@ -81,9 +81,6 @@ struct _ClutterStageX11Class
|
|||||||
GType _clutter_stage_x11_get_type (void) G_GNUC_CONST;
|
GType _clutter_stage_x11_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
/* Private to subclasses */
|
/* Private to subclasses */
|
||||||
gboolean _clutter_stage_x11_create_window (ClutterStageX11 *stage_x11);
|
|
||||||
void _clutter_stage_x11_destroy_window_untrapped (ClutterStageX11 *stage_x11);
|
|
||||||
void _clutter_stage_x11_destroy_window (ClutterStageX11 *stage_x11);
|
|
||||||
void _clutter_stage_x11_set_user_time (ClutterStageX11 *stage_x11,
|
void _clutter_stage_x11_set_user_time (ClutterStageX11 *stage_x11,
|
||||||
guint32 user_time);
|
guint32 user_time);
|
||||||
gboolean _clutter_stage_x11_get_root_coords (ClutterStageX11 *stage_x11,
|
gboolean _clutter_stage_x11_get_root_coords (ClutterStageX11 *stage_x11,
|
||||||
|
@ -459,6 +459,8 @@ AS_IF([test "x$SUPPORT_GLX" = "x1"],
|
|||||||
|
|
||||||
AC_DEFINE([HAVE_CLUTTER_GLX], [1], [Have the GLX backend])
|
AC_DEFINE([HAVE_CLUTTER_GLX], [1], [Have the GLX backend])
|
||||||
|
|
||||||
|
AC_DEFINE([COGL_HAS_FULL_WINSYS], [1], [Cogl can create its own OpenGL context])
|
||||||
|
|
||||||
AC_CHECK_HEADERS([GL/glx.h],
|
AC_CHECK_HEADERS([GL/glx.h],
|
||||||
[],
|
[],
|
||||||
[AC_MSG_ERROR([Unable to locate required GLX headers])])
|
[AC_MSG_ERROR([Unable to locate required GLX headers])])
|
||||||
@ -489,12 +491,14 @@ AS_IF([test "x$SUPPORT_EGL_PLATFORM_POWERVR_X11" = "x1"],
|
|||||||
[
|
[
|
||||||
AC_DEFINE([COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT], [1],
|
AC_DEFINE([COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT], [1],
|
||||||
[Cogl supports OpenGL[ES] using the EGL API with PowerVR X11 platform typedefs])
|
[Cogl supports OpenGL[ES] using the EGL API with PowerVR X11 platform typedefs])
|
||||||
|
AC_DEFINE([COGL_HAS_FULL_WINSYS], [1], [Cogl can create its own OpenGL context])
|
||||||
])
|
])
|
||||||
|
|
||||||
AS_IF([test "x$SUPPORT_EGL_PLATFORM_POWERVR_NULL" = "x1"],
|
AS_IF([test "x$SUPPORT_EGL_PLATFORM_POWERVR_NULL" = "x1"],
|
||||||
[
|
[
|
||||||
AC_DEFINE([COGL_HAS_EGL_PLATFORM_POWERVR_NULL_SUPPORT], [1],
|
AC_DEFINE([COGL_HAS_EGL_PLATFORM_POWERVR_NULL_SUPPORT], [1],
|
||||||
[Cogl supports OpenGL[ES] using the EGL API with PowerVR NULL platform typedefs])
|
[Cogl supports OpenGL[ES] using the EGL API with PowerVR NULL platform typedefs])
|
||||||
|
AC_DEFINE([COGL_HAS_FULL_WINSYS], [1], [Cogl can create its own OpenGL context])
|
||||||
])
|
])
|
||||||
|
|
||||||
AS_IF([test "x$SUPPORT_EGL_PLATFORM_POWERVR_GDL" = "x1"],
|
AS_IF([test "x$SUPPORT_EGL_PLATFORM_POWERVR_GDL" = "x1"],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user