1a263dca5c
* clutter/win32/clutter-win32.h: * clutter/win32/clutter-stage-win32.h: * clutter/win32/clutter-stage-win32.c: * clutter/win32/clutter-event-win32.c: * clutter/win32/clutter-backend-win32.h: * clutter/win32/clutter-backend-win32.c: Upgraded for multi-stage support. * clutter/win32/clutter-stage-win32.c (clutter_stage_win32_request_coords): Fixed so that it doesn't set the position or size if it hasn't changed. This was causing problems when the window was resized using the top left corner. In that case the window receives resize and move messages separately which caused the window to flash at a different size or position while one message was handled before the other. (clutter_stage_win32_realize): Added PFD_GENERIC_ACCELERATED to the list of pixel format flags to force it to use hardware acceleration. 2008-03-30 Neil Roberts <neil@o-hand.com> * clutter-sections.txt: Added clutter_win32_get_stage_from_window
309 lines
8.7 KiB
C
309 lines
8.7 KiB
C
/* Clutter.
|
|
* An OpenGL based 'interactive canvas' library.
|
|
* Authored By Matthew Allum <mallum@openedhand.com>
|
|
* Copyright (C) 2006-2007 OpenedHand
|
|
*
|
|
* 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, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
* Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <windows.h>
|
|
|
|
#include "clutter-backend-win32.h"
|
|
#include "clutter-stage-win32.h"
|
|
#include "clutter-win32.h"
|
|
|
|
#include "../clutter-event.h"
|
|
#include "../clutter-main.h"
|
|
#include "../clutter-debug.h"
|
|
#include "../clutter-private.h"
|
|
|
|
#include "cogl.h"
|
|
|
|
G_DEFINE_TYPE (ClutterBackendWin32, clutter_backend_win32,
|
|
CLUTTER_TYPE_BACKEND);
|
|
|
|
typedef int (* SwapIntervalProc) (int interval);
|
|
|
|
/* singleton object */
|
|
static ClutterBackendWin32 *backend_singleton = NULL;
|
|
|
|
static gchar *clutter_vblank_name = NULL;
|
|
|
|
gboolean
|
|
clutter_backend_win32_pre_parse (ClutterBackend *backend,
|
|
GError **error)
|
|
{
|
|
const gchar *env_string;
|
|
|
|
if ((env_string = g_getenv ("CLUTTER_VBLANK")))
|
|
clutter_vblank_name = g_strdup (env_string);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
clutter_backend_win32_init_events (ClutterBackend *backend)
|
|
{
|
|
CLUTTER_NOTE (EVENT, "initialising the event loop");
|
|
|
|
_clutter_backend_win32_events_init (backend);
|
|
}
|
|
|
|
static const GOptionEntry entries[] =
|
|
{
|
|
{
|
|
"vblank", 0,
|
|
0,
|
|
G_OPTION_ARG_STRING, &clutter_vblank_name,
|
|
"VBlank method to be used (none, default or wgl)", "METHOD"
|
|
},
|
|
{ NULL }
|
|
};
|
|
|
|
void
|
|
clutter_backend_win32_add_options (ClutterBackend *backend,
|
|
GOptionGroup *group)
|
|
{
|
|
g_option_group_add_entries (group, entries);
|
|
}
|
|
|
|
static void
|
|
clutter_backend_win32_finalize (GObject *gobject)
|
|
{
|
|
backend_singleton = NULL;
|
|
|
|
G_OBJECT_CLASS (clutter_backend_win32_parent_class)->finalize (gobject);
|
|
}
|
|
|
|
static void
|
|
clutter_backend_win32_dispose (GObject *gobject)
|
|
{
|
|
ClutterBackendWin32 *backend_win32 = CLUTTER_BACKEND_WIN32 (gobject);
|
|
ClutterMainContext *context;
|
|
ClutterStageManager *stage_manager;
|
|
GSList *l;
|
|
|
|
CLUTTER_NOTE (BACKEND, "Disposing the of stages");
|
|
|
|
context = clutter_context_get_default ();
|
|
stage_manager = context->stage_manager;
|
|
|
|
for (l = stage_manager->stages; l; l = l->next)
|
|
{
|
|
ClutterActor *stage = CLUTTER_ACTOR (l->data);
|
|
clutter_actor_destroy (stage);
|
|
}
|
|
|
|
CLUTTER_NOTE (BACKEND, "Removing the event source");
|
|
_clutter_backend_win32_events_uninit (CLUTTER_BACKEND (backend_win32));
|
|
|
|
G_OBJECT_CLASS (clutter_backend_win32_parent_class)->dispose (gobject);
|
|
}
|
|
|
|
static GObject *
|
|
clutter_backend_win32_constructor (GType gtype,
|
|
guint n_params,
|
|
GObjectConstructParam *params)
|
|
{
|
|
GObjectClass *parent_class;
|
|
GObject *retval;
|
|
|
|
if (!backend_singleton)
|
|
{
|
|
parent_class = G_OBJECT_CLASS (clutter_backend_win32_parent_class);
|
|
retval = parent_class->constructor (gtype, n_params, params);
|
|
|
|
backend_singleton = CLUTTER_BACKEND_WIN32 (retval);
|
|
|
|
return retval;
|
|
}
|
|
|
|
g_warning ("Attempting to create a new backend object. This should "
|
|
"never happen, so we return the singleton instance.");
|
|
|
|
return g_object_ref (backend_singleton);
|
|
}
|
|
|
|
static gboolean
|
|
check_vblank_env (const char *name)
|
|
{
|
|
return clutter_vblank_name && !strcasecmp (clutter_vblank_name, name);
|
|
}
|
|
|
|
ClutterFeatureFlags
|
|
clutter_backend_win32_get_features (ClutterBackend *backend)
|
|
{
|
|
ClutterFeatureFlags flags;
|
|
const gchar *extensions;
|
|
SwapIntervalProc swap_interval;
|
|
|
|
/* FIXME: we really need to check if gl context is set */
|
|
|
|
extensions = glGetString (GL_EXTENSIONS);
|
|
|
|
CLUTTER_NOTE (BACKEND, "Checking features\n"
|
|
"GL_VENDOR: %s\n"
|
|
"GL_RENDERER: %s\n"
|
|
"GL_VERSION: %s\n"
|
|
"GL_EXTENSIONS: %s\n",
|
|
glGetString (GL_VENDOR),
|
|
glGetString (GL_RENDERER),
|
|
glGetString (GL_VERSION),
|
|
extensions);
|
|
|
|
flags = CLUTTER_FEATURE_STAGE_USER_RESIZE
|
|
| CLUTTER_FEATURE_STAGE_CURSOR
|
|
| CLUTTER_FEATURE_STAGE_MULTIPLE;
|
|
|
|
/* If the VBlank should be left at the default or it has been
|
|
disabled elsewhere (eg NVIDIA) then don't bother trying to check
|
|
for the swap control extension */
|
|
if (getenv ("__GL_SYNC_TO_VBLANK") || check_vblank_env ("default"))
|
|
CLUTTER_NOTE (BACKEND, "vblank sync: left at default at user request");
|
|
else if (cogl_check_extension ("WGL_EXT_swap_control", extensions)
|
|
&& (swap_interval = (SwapIntervalProc)
|
|
cogl_get_proc_address ("wglSwapIntervalEXT")))
|
|
{
|
|
/* According to the specification for the WGL_EXT_swap_control
|
|
extension the default swap interval is 1 anyway, so if no
|
|
vblank is requested then we should explicitly set it to
|
|
zero */
|
|
if (check_vblank_env ("none"))
|
|
{
|
|
if (swap_interval (0))
|
|
CLUTTER_NOTE (BACKEND, "vblank sync: successfully disabled");
|
|
else
|
|
CLUTTER_NOTE (BACKEND, "vblank sync: disabling failed");
|
|
}
|
|
else
|
|
{
|
|
if (swap_interval (1))
|
|
{
|
|
flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK;
|
|
CLUTTER_NOTE (BACKEND, "vblank sync: wglSwapIntervalEXT "
|
|
"vblank setup success");
|
|
}
|
|
else
|
|
CLUTTER_NOTE (BACKEND, "vblank sync: wglSwapIntervalEXT "
|
|
"vblank setup failed");
|
|
}
|
|
}
|
|
else
|
|
CLUTTER_NOTE (BACKEND, "no use-able vblank mechanism found");
|
|
|
|
return flags;
|
|
}
|
|
|
|
static void
|
|
clutter_backend_win32_ensure_context (ClutterBackend *backend,
|
|
ClutterStage *stage)
|
|
{
|
|
ClutterBackendWin32 *backend_win32;
|
|
ClutterStageWin32 *stage_win32;
|
|
|
|
stage_win32 = CLUTTER_STAGE_WIN32 (stage);
|
|
backend_win32 = CLUTTER_BACKEND_WIN32 (backend);
|
|
|
|
CLUTTER_NOTE (MULTISTAGE, "setting context for stage:%p", stage );
|
|
|
|
wglMakeCurrent (stage_win32->client_dc,
|
|
backend_win32->gl_context);
|
|
}
|
|
|
|
static void
|
|
clutter_backend_win32_redraw (ClutterBackend *backend,
|
|
ClutterStage *stage)
|
|
{
|
|
ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (stage);
|
|
|
|
clutter_actor_paint (CLUTTER_ACTOR (stage));
|
|
|
|
if (stage_win32->client_dc)
|
|
SwapBuffers (stage_win32->client_dc);
|
|
}
|
|
|
|
static ClutterActor *
|
|
clutter_backend_win32_create_stage (ClutterBackend *backend,
|
|
GError **error)
|
|
{
|
|
ClutterBackendWin32 *backend_win32 = CLUTTER_BACKEND_WIN32 (backend);
|
|
ClutterStageWin32 *stage_win32;
|
|
ClutterActor *stage;
|
|
|
|
stage = g_object_new (CLUTTER_TYPE_STAGE_WIN32, NULL);
|
|
|
|
/* copy backend data into the stage */
|
|
stage_win32 = CLUTTER_STAGE_WIN32 (stage);
|
|
stage_win32->backend = backend_win32;
|
|
|
|
/* needed ? */
|
|
g_object_set_data (G_OBJECT (stage), "clutter-backend", backend);
|
|
|
|
clutter_actor_realize (stage);
|
|
|
|
if (!CLUTTER_ACTOR_IS_REALIZED (stage))
|
|
{
|
|
g_set_error (error, CLUTTER_INIT_ERROR,
|
|
CLUTTER_INIT_ERROR_INTERNAL,
|
|
"Unable to realize the main stage");
|
|
return NULL;
|
|
}
|
|
|
|
return stage;
|
|
}
|
|
|
|
static void
|
|
clutter_backend_win32_class_init (ClutterBackendWin32Class *klass)
|
|
{
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass);
|
|
|
|
gobject_class->constructor = clutter_backend_win32_constructor;
|
|
gobject_class->dispose = clutter_backend_win32_dispose;
|
|
gobject_class->finalize = clutter_backend_win32_finalize;
|
|
|
|
backend_class->pre_parse = clutter_backend_win32_pre_parse;
|
|
backend_class->init_events = clutter_backend_win32_init_events;
|
|
backend_class->create_stage = clutter_backend_win32_create_stage;
|
|
backend_class->add_options = clutter_backend_win32_add_options;
|
|
backend_class->get_features = clutter_backend_win32_get_features;
|
|
backend_class->redraw = clutter_backend_win32_redraw;
|
|
backend_class->ensure_context = clutter_backend_win32_ensure_context;
|
|
}
|
|
|
|
static void
|
|
clutter_backend_win32_init (ClutterBackendWin32 *backend_win32)
|
|
{
|
|
ClutterBackend *backend = CLUTTER_BACKEND (backend_win32);
|
|
|
|
backend_win32->gl_context = NULL;
|
|
|
|
/* FIXME: get from GetSystemMetric? */
|
|
clutter_backend_set_double_click_time (backend, 250);
|
|
clutter_backend_set_double_click_distance (backend, 5);
|
|
clutter_backend_set_resolution (backend, 96.0);
|
|
}
|
|
|
|
GType
|
|
_clutter_backend_impl_get_type (void)
|
|
{
|
|
return clutter_backend_win32_get_type ();
|
|
}
|