mirror of
https://github.com/brl/mutter.git
synced 2024-11-26 18:11:05 -05:00
win32: Use a dummy window to support delayed stage creation
The Win32 backend now implements the create_context method which creates a context and binds it to a 1x1 invisible window. That way there will always be a context bound and the features can be retrieved without creating the default stage. This reflects the changes in 1c6ffc8..b245d55 to the GLX backend.
This commit is contained in:
parent
479fdffc7d
commit
ae188d203c
@ -156,10 +156,23 @@ clutter_backend_win32_dispose (GObject *gobject)
|
|||||||
|
|
||||||
if (backend_win32->gl_context)
|
if (backend_win32->gl_context)
|
||||||
{
|
{
|
||||||
|
wglMakeCurrent (NULL, NULL);
|
||||||
wglDeleteContext (backend_win32->gl_context);
|
wglDeleteContext (backend_win32->gl_context);
|
||||||
backend_win32->gl_context = NULL;
|
backend_win32->gl_context = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (backend_win32->dummy_dc)
|
||||||
|
{
|
||||||
|
ReleaseDC (backend_win32->dummy_hwnd, backend_win32->dummy_dc);
|
||||||
|
backend_win32->dummy_dc = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (backend_win32->dummy_hwnd)
|
||||||
|
{
|
||||||
|
DestroyWindow (backend_win32->dummy_hwnd);
|
||||||
|
backend_win32->dummy_hwnd = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
G_OBJECT_CLASS (clutter_backend_win32_parent_class)->dispose (gobject);
|
G_OBJECT_CLASS (clutter_backend_win32_parent_class)->dispose (gobject);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,21 +214,20 @@ clutter_backend_win32_get_features (ClutterBackend *backend)
|
|||||||
SwapIntervalProc swap_interval;
|
SwapIntervalProc swap_interval;
|
||||||
ClutterBackendWin32 *backend_win32;
|
ClutterBackendWin32 *backend_win32;
|
||||||
|
|
||||||
/* FIXME: we really need to check if gl context is set */
|
|
||||||
|
|
||||||
extensions = (const gchar *) glGetString (GL_EXTENSIONS);
|
|
||||||
|
|
||||||
/* this will make sure that the GL context exists and is bound to a
|
/* this will make sure that the GL context exists and is bound to a
|
||||||
drawable */
|
drawable */
|
||||||
backend_win32 = CLUTTER_BACKEND_WIN32 (backend);
|
backend_win32 = CLUTTER_BACKEND_WIN32 (backend);
|
||||||
g_return_val_if_fail (backend_win32->gl_context != NULL, 0);
|
g_return_val_if_fail (backend_win32->gl_context != NULL, 0);
|
||||||
g_return_val_if_fail (wglGetCurrentDC () != NULL, 0);
|
g_return_val_if_fail (wglGetCurrentDC () != NULL, 0);
|
||||||
|
|
||||||
CLUTTER_NOTE (BACKEND, "Checking features\n"
|
extensions = (const gchar *) glGetString (GL_EXTENSIONS);
|
||||||
"GL_VENDOR: %s\n"
|
|
||||||
"GL_RENDERER: %s\n"
|
CLUTTER_NOTE (BACKEND,
|
||||||
"GL_VERSION: %s\n"
|
"Checking features\n"
|
||||||
"GL_EXTENSIONS: %s\n",
|
" GL_VENDOR: %s\n"
|
||||||
|
" GL_RENDERER: %s\n"
|
||||||
|
" GL_VERSION: %s\n"
|
||||||
|
" GL_EXTENSIONS: %s\n",
|
||||||
glGetString (GL_VENDOR),
|
glGetString (GL_VENDOR),
|
||||||
glGetString (GL_RENDERER),
|
glGetString (GL_RENDERER),
|
||||||
glGetString (GL_VERSION),
|
glGetString (GL_VERSION),
|
||||||
@ -261,9 +273,166 @@ clutter_backend_win32_get_features (ClutterBackend *backend)
|
|||||||
else
|
else
|
||||||
CLUTTER_NOTE (BACKEND, "no use-able vblank mechanism found");
|
CLUTTER_NOTE (BACKEND, "no use-able vblank mechanism found");
|
||||||
|
|
||||||
|
CLUTTER_NOTE (BACKEND, "backend features checked");
|
||||||
|
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ATOM
|
||||||
|
clutter_backend_win32_get_dummy_window_class ()
|
||||||
|
{
|
||||||
|
static ATOM klass = 0;
|
||||||
|
|
||||||
|
if (klass == 0)
|
||||||
|
{
|
||||||
|
WNDCLASSW wndclass;
|
||||||
|
memset (&wndclass, 0, sizeof (wndclass));
|
||||||
|
wndclass.lpfnWndProc = DefWindowProc;
|
||||||
|
wndclass.hInstance = GetModuleHandleW (NULL);
|
||||||
|
wndclass.lpszClassName = L"ClutterBackendWin32DummyWindow";
|
||||||
|
klass = RegisterClassW (&wndclass);
|
||||||
|
}
|
||||||
|
|
||||||
|
return klass;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
clutter_backend_win32_pixel_format_is_better (const PIXELFORMATDESCRIPTOR *pfa,
|
||||||
|
const PIXELFORMATDESCRIPTOR *pfb)
|
||||||
|
{
|
||||||
|
/* Always prefer a format with a stencil buffer */
|
||||||
|
if (pfa->cStencilBits == 0)
|
||||||
|
{
|
||||||
|
if (pfb->cStencilBits > 0)
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else if (pfb->cStencilBits == 0)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* Prefer a bigger color buffer */
|
||||||
|
if (pfb->cColorBits > pfa->cColorBits)
|
||||||
|
return TRUE;
|
||||||
|
else if (pfb->cColorBits < pfa->cColorBits)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* Prefer a bigger depth buffer */
|
||||||
|
return pfb->cDepthBits > pfa->cDepthBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
clutter_backend_win32_choose_pixel_format (HDC dc, PIXELFORMATDESCRIPTOR *pfd)
|
||||||
|
{
|
||||||
|
int i, num_formats, best_pf = 0;
|
||||||
|
PIXELFORMATDESCRIPTOR best_pfd;
|
||||||
|
|
||||||
|
num_formats = DescribePixelFormat (dc, 0, sizeof (best_pfd), NULL);
|
||||||
|
|
||||||
|
for (i = 1; i <= num_formats; i++)
|
||||||
|
{
|
||||||
|
memset (pfd, 0, sizeof (*pfd));
|
||||||
|
|
||||||
|
if (DescribePixelFormat (dc, i, sizeof (best_pfd), pfd)
|
||||||
|
/* Check whether this format is useable by Clutter */
|
||||||
|
&& ((pfd->dwFlags & (PFD_SUPPORT_OPENGL
|
||||||
|
| PFD_DRAW_TO_WINDOW
|
||||||
|
| PFD_DOUBLEBUFFER
|
||||||
|
| PFD_GENERIC_FORMAT))
|
||||||
|
== (PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW))
|
||||||
|
&& pfd->iPixelType == PFD_TYPE_RGBA
|
||||||
|
&& pfd->cColorBits >= 16 && pfd->cColorBits <= 32
|
||||||
|
&& pfd->cDepthBits >= 16 && pfd->cDepthBits <= 32
|
||||||
|
/* Check whether this is a better format than one we've
|
||||||
|
already found */
|
||||||
|
&& (best_pf == 0
|
||||||
|
|| clutter_backend_win32_pixel_format_is_better (&best_pfd, pfd)))
|
||||||
|
{
|
||||||
|
best_pf = i;
|
||||||
|
best_pfd = *pfd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*pfd = best_pfd;
|
||||||
|
|
||||||
|
return best_pf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
clutter_backend_win32_create_context (ClutterBackend *backend,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
ClutterBackendWin32 *backend_win32 = CLUTTER_BACKEND_WIN32 (backend);
|
||||||
|
|
||||||
|
/* COGL assumes that there is always a GL context selected; in order
|
||||||
|
* to make sure that a WGL context exists and is made current, we
|
||||||
|
* use a small dummy window that never gets shown to which we can
|
||||||
|
* always fall back if no stage is available
|
||||||
|
*/
|
||||||
|
if (backend_win32->dummy_hwnd == NULL)
|
||||||
|
{
|
||||||
|
ATOM window_class = clutter_backend_win32_get_dummy_window_class ();
|
||||||
|
|
||||||
|
if (window_class == 0)
|
||||||
|
{
|
||||||
|
g_critical ("Unable to register window class");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
backend_win32->dummy_hwnd =
|
||||||
|
CreateWindowW ((LPWSTR) MAKEINTATOM (window_class),
|
||||||
|
L".",
|
||||||
|
WS_OVERLAPPEDWINDOW,
|
||||||
|
CW_USEDEFAULT,
|
||||||
|
CW_USEDEFAULT,
|
||||||
|
1, 1,
|
||||||
|
NULL, NULL,
|
||||||
|
GetModuleHandle (NULL),
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (backend_win32->dummy_hwnd == NULL)
|
||||||
|
{
|
||||||
|
g_critical ("Unable to create dummy window");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (backend_win32->dummy_dc == NULL)
|
||||||
|
{
|
||||||
|
PIXELFORMATDESCRIPTOR pfd;
|
||||||
|
int pf;
|
||||||
|
|
||||||
|
backend_win32->dummy_dc = GetDC (backend_win32->dummy_hwnd);
|
||||||
|
|
||||||
|
pf = clutter_backend_win32_choose_pixel_format (backend_win32->dummy_dc,
|
||||||
|
&pfd);
|
||||||
|
|
||||||
|
if (pf == 0 || !SetPixelFormat (backend_win32->dummy_dc, pf, &pfd))
|
||||||
|
{
|
||||||
|
g_critical ("Unable to find suitable GL pixel format");
|
||||||
|
ReleaseDC (backend_win32->dummy_hwnd, backend_win32->dummy_dc);
|
||||||
|
backend_win32->dummy_dc = NULL;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (backend_win32->gl_context == NULL)
|
||||||
|
{
|
||||||
|
backend_win32->gl_context = wglCreateContext (backend_win32->dummy_dc);
|
||||||
|
|
||||||
|
if (backend_win32->gl_context == NULL)
|
||||||
|
{
|
||||||
|
g_critical ("Unable to create suitable GL context");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CLUTTER_NOTE (BACKEND, "Selecting dummy 0x%x for the WGL context",
|
||||||
|
(unsigned int) backend_win32->dummy_hwnd);
|
||||||
|
|
||||||
|
wglMakeCurrent (backend_win32->dummy_dc, backend_win32->gl_context);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_backend_win32_ensure_context (ClutterBackend *backend,
|
clutter_backend_win32_ensure_context (ClutterBackend *backend,
|
||||||
ClutterStage *stage)
|
ClutterStage *stage)
|
||||||
@ -304,7 +473,11 @@ clutter_backend_win32_ensure_context (ClutterBackend *backend,
|
|||||||
CLUTTER_NOTE (MULTISTAGE,
|
CLUTTER_NOTE (MULTISTAGE,
|
||||||
"Received a stale stage, clearing all context");
|
"Received a stale stage, clearing all context");
|
||||||
|
|
||||||
wglMakeCurrent (NULL, NULL);
|
if (backend_win32->dummy_dc != NULL)
|
||||||
|
wglMakeCurrent (backend_win32->dummy_dc,
|
||||||
|
backend_win32->gl_context);
|
||||||
|
else
|
||||||
|
wglMakeCurrent (NULL, NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -380,6 +553,7 @@ clutter_backend_win32_class_init (ClutterBackendWin32Class *klass)
|
|||||||
backend_class->add_options = clutter_backend_win32_add_options;
|
backend_class->add_options = clutter_backend_win32_add_options;
|
||||||
backend_class->get_features = clutter_backend_win32_get_features;
|
backend_class->get_features = clutter_backend_win32_get_features;
|
||||||
backend_class->redraw = clutter_backend_win32_redraw;
|
backend_class->redraw = clutter_backend_win32_redraw;
|
||||||
|
backend_class->create_context = clutter_backend_win32_create_context;
|
||||||
backend_class->ensure_context = clutter_backend_win32_ensure_context;
|
backend_class->ensure_context = clutter_backend_win32_ensure_context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,6 +46,8 @@ struct _ClutterBackendWin32
|
|||||||
ClutterBackend parent_instance;
|
ClutterBackend parent_instance;
|
||||||
|
|
||||||
HGLRC gl_context;
|
HGLRC gl_context;
|
||||||
|
HWND dummy_hwnd;
|
||||||
|
HDC dummy_dc;
|
||||||
gboolean no_event_retrieval;
|
gboolean no_event_retrieval;
|
||||||
|
|
||||||
HCURSOR invisible_cursor;
|
HCURSOR invisible_cursor;
|
||||||
|
@ -384,66 +384,6 @@ clutter_stage_win32_get_window_class ()
|
|||||||
|
|
||||||
return klass;
|
return klass;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
clutter_stage_win32_pixel_format_is_better (const PIXELFORMATDESCRIPTOR *pfa,
|
|
||||||
const PIXELFORMATDESCRIPTOR *pfb)
|
|
||||||
{
|
|
||||||
/* Always prefer a format with a stencil buffer */
|
|
||||||
if (pfa->cStencilBits == 0)
|
|
||||||
{
|
|
||||||
if (pfb->cStencilBits > 0)
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
else if (pfb->cStencilBits == 0)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* Prefer a bigger color buffer */
|
|
||||||
if (pfb->cColorBits > pfa->cColorBits)
|
|
||||||
return TRUE;
|
|
||||||
else if (pfb->cColorBits < pfa->cColorBits)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* Prefer a bigger depth buffer */
|
|
||||||
return pfb->cDepthBits > pfa->cDepthBits;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
clutter_stage_win32_choose_pixel_format (HDC dc, PIXELFORMATDESCRIPTOR *pfd)
|
|
||||||
{
|
|
||||||
int i, num_formats, best_pf = 0;
|
|
||||||
PIXELFORMATDESCRIPTOR best_pfd;
|
|
||||||
|
|
||||||
num_formats = DescribePixelFormat (dc, 0, sizeof (best_pfd), NULL);
|
|
||||||
|
|
||||||
for (i = 1; i <= num_formats; i++)
|
|
||||||
{
|
|
||||||
memset (pfd, 0, sizeof (*pfd));
|
|
||||||
|
|
||||||
if (DescribePixelFormat (dc, i, sizeof (best_pfd), pfd)
|
|
||||||
/* Check whether this format is useable by Clutter */
|
|
||||||
&& ((pfd->dwFlags & (PFD_SUPPORT_OPENGL
|
|
||||||
| PFD_DRAW_TO_WINDOW
|
|
||||||
| PFD_DOUBLEBUFFER
|
|
||||||
| PFD_GENERIC_FORMAT))
|
|
||||||
== (PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW))
|
|
||||||
&& pfd->iPixelType == PFD_TYPE_RGBA
|
|
||||||
&& pfd->cColorBits >= 16 && pfd->cColorBits <= 32
|
|
||||||
&& pfd->cDepthBits >= 16 && pfd->cDepthBits <= 32
|
|
||||||
/* Check whether this is a better format than one we've
|
|
||||||
already found */
|
|
||||||
&& (best_pf == 0
|
|
||||||
|| clutter_stage_win32_pixel_format_is_better (&best_pfd, pfd)))
|
|
||||||
{
|
|
||||||
best_pf = i;
|
|
||||||
best_pfd = *pfd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*pfd = best_pfd;
|
|
||||||
|
|
||||||
return best_pf;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
clutter_stage_win32_realize (ClutterStageWindow *stage_window)
|
clutter_stage_win32_realize (ClutterStageWindow *stage_window)
|
||||||
@ -452,6 +392,7 @@ clutter_stage_win32_realize (ClutterStageWindow *stage_window)
|
|||||||
ClutterBackendWin32 *backend_win32;
|
ClutterBackendWin32 *backend_win32;
|
||||||
PIXELFORMATDESCRIPTOR pfd;
|
PIXELFORMATDESCRIPTOR pfd;
|
||||||
int pf;
|
int pf;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
CLUTTER_NOTE (MISC, "Realizing main stage");
|
CLUTTER_NOTE (MISC, "Realizing main stage");
|
||||||
|
|
||||||
@ -518,23 +459,22 @@ clutter_stage_win32_realize (ClutterStageWindow *stage_window)
|
|||||||
|
|
||||||
stage_win32->client_dc = GetDC (stage_win32->hwnd);
|
stage_win32->client_dc = GetDC (stage_win32->hwnd);
|
||||||
|
|
||||||
pf = clutter_stage_win32_choose_pixel_format (stage_win32->client_dc, &pfd);
|
/* Create a context. This will be a no-op if we already have one */
|
||||||
|
if (!_clutter_backend_create_context (CLUTTER_BACKEND (backend_win32),
|
||||||
if (pf == 0 || !SetPixelFormat (stage_win32->client_dc, pf, &pfd))
|
&error))
|
||||||
{
|
{
|
||||||
g_critical ("Unable to find suitable GL pixel format");
|
g_critical ("Unable to realize stage: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (backend_win32->gl_context == NULL)
|
/* Use the same pixel format as the dummy DC */
|
||||||
|
pf = GetPixelFormat (backend_win32->dummy_dc);
|
||||||
|
DescribePixelFormat (backend_win32->dummy_dc, pf, sizeof (pfd), &pfd);
|
||||||
|
if (!SetPixelFormat (stage_win32->client_dc, pf, &pfd))
|
||||||
{
|
{
|
||||||
backend_win32->gl_context = wglCreateContext (stage_win32->client_dc);
|
g_critical ("Unable to find suitable GL pixel format");
|
||||||
|
goto fail;
|
||||||
if (backend_win32->gl_context == NULL)
|
|
||||||
{
|
|
||||||
g_critical ("Unable to create suitable GL context");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CLUTTER_NOTE (BACKEND, "Successfully realized stage");
|
CLUTTER_NOTE (BACKEND, "Successfully realized stage");
|
||||||
|
Loading…
Reference in New Issue
Block a user