From 7de27eb6f7a2b2632c2e92b4e98dd14a8a46f7a9 Mon Sep 17 00:00:00 2001
From: Tommi Komulainen <tommi.komulainen@iki.fi>
Date: Sat, 29 Mar 2008 11:26:03 +0200
Subject: [PATCH] OSX: add multistage support

	* clutter/osx/clutter-backend-osx.{c,h}
	(clutter_backend_osx_init_stage, clutter_backend_osx_get_stage,
	clutter_backend_osx_redraw, clutter_backend_osx_create_stage,
	clutter_backend_osx_ensure_context): Adapt to new multistage
	backend API

	* clutter/osx/clutter-stage-osx.{c,h} (clutter_stage_osx_realize):
	Move from singleton GL context to one GL context per stage.
	(clutter_backend_osx_dispose): Removed as redundant

	* clutter/osx/clutter-event-osx.c (clutter_event_osx_translate,
	clutter_stage_osx_state_update, ClutterGLWindow:windowShouldClose:):
	Fill in ClutterEventAny::stage
---
 clutter/clutter/osx/clutter-backend-osx.c |   85 ++++++++++-------------------
 clutter/clutter/osx/clutter-backend-osx.h |    5 --
 clutter/clutter/osx/clutter-event-osx.c   |   26 +++++++++
 clutter/clutter/osx/clutter-stage-osx.c   |   20 +++----
 clutter/clutter/osx/clutter-stage-osx.h   |    5 ++-
 5 files changed, 67 insertions(+), 74 deletions(-)

diff --git a/clutter/clutter/osx/clutter-backend-osx.c b/clutter/clutter/osx/clutter-backend-osx.c
index 0efe58f..cf3c7a5 100644
--- a/clutter/clutter/osx/clutter-backend-osx.c
+++ b/clutter/clutter/osx/clutter-backend-osx.c
@@ -69,41 +69,34 @@ clutter_backend_osx_post_parse (ClutterBackend  *backend,
 static ClutterFeatureFlags
 clutter_backend_osx_get_features (ClutterBackend *backend)
 {
-  return CLUTTER_FEATURE_STAGE_USER_RESIZE;
+  return CLUTTER_FEATURE_STAGE_MULTIPLE|CLUTTER_FEATURE_STAGE_USER_RESIZE;
 }
 
-static gboolean
-clutter_backend_osx_init_stage (ClutterBackend  *backend,
-                                GError         **error)
+static ClutterActor*
+clutter_backend_osx_create_stage (ClutterBackend  *backend,
+                                  GError         **error)
 {
-  ClutterBackendOSX *self = CLUTTER_BACKEND_OSX (backend);
   ClutterActor *stage;
 
   CLUTTER_NOTE (BACKEND, "init_stage");
 
   CLUTTER_OSX_POOL_ALLOC();
 
-  g_assert (self->stage == NULL);
-
-  /* Allocate ourselves a GL context. We need one this early for clutter to
-   * manage textures.
-   */
-  NSOpenGLPixelFormatAttribute attrs[] = {
-    NSOpenGLPFADoubleBuffer,
-    0
-  };
-  self->pixel_format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
-  self->context = [[NSOpenGLContext alloc]
-                   initWithFormat: self->pixel_format
-                     shareContext: nil];
-  [self->context makeCurrentContext];
-
   stage = clutter_stage_osx_new (backend);
-  self->stage = g_object_ref_sink (stage);
+
+  clutter_actor_realize (stage);    /* Why is this in backend? */
+  if (!CLUTTER_ACTOR_IS_REALIZED (stage))
+    {
+      g_set_error (error, CLUTTER_INIT_ERROR,
+                   CLUTTER_INIT_ERROR_INTERNAL,
+                   "Unable to realize stage");
+      g_object_unref (stage);
+      stage = NULL;
+    }
 
   CLUTTER_OSX_POOL_RELEASE();
 
-  return TRUE;
+  return stage;
 }
 
 static void
@@ -114,21 +107,24 @@ clutter_backend_osx_init_events (ClutterBackend *backend)
   _clutter_events_osx_init ();
 }
 
-static ClutterActor *
-clutter_backend_osx_get_stage (ClutterBackend *backend)
+static void
+clutter_backend_osx_ensure_context (ClutterBackend *backend,
+                                    ClutterStage   *stage)
 {
-  ClutterBackendOSX *self = CLUTTER_BACKEND_OSX (backend);
+  ClutterStageOSX *stage_osx = CLUTTER_STAGE_OSX (stage);
+
+  CLUTTER_OSX_POOL_ALLOC();
+
+  [stage_osx->context makeCurrentContext];
 
-  return self->stage;
+  CLUTTER_OSX_POOL_RELEASE();
 }
 
 static void
-clutter_backend_osx_redraw (ClutterBackend *backend)
+clutter_backend_osx_redraw (ClutterBackend *backend, ClutterStage *stage)
 {
-  ClutterBackendOSX *self = CLUTTER_BACKEND_OSX (backend);
-  ClutterStageOSX *stage_osx;
+  ClutterStageOSX *stage_osx = CLUTTER_STAGE_OSX (stage);
 
-  stage_osx = CLUTTER_STAGE_OSX (self->stage);
   [stage_osx->view setNeedsDisplay: YES];
 }
 
@@ -140,40 +136,15 @@ clutter_backend_osx_init (ClutterBackendOSX *self)
 }
 
 static void
-clutter_backend_osx_dispose (GObject *object)
-{
-  ClutterBackendOSX *self = CLUTTER_BACKEND_OSX (object);
-
-  if (self->stage)
-    {
-      CLUTTER_UNSET_PRIVATE_FLAGS (self->stage, CLUTTER_ACTOR_IS_TOPLEVEL);
-      clutter_actor_destroy (self->stage);
-      self->stage = NULL;
-    }
-
-  [self->context release];
-  self->context = NULL;
-
-  [self->pixel_format release];
-  self->pixel_format = NULL;
-
-
-  G_OBJECT_CLASS (clutter_backend_osx_parent_class)->dispose (object);
-}
-
-static void
 clutter_backend_osx_class_init (ClutterBackendOSXClass *klass)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
   ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass);
 
-  object_class->dispose = clutter_backend_osx_dispose;
-
   backend_class->post_parse   = clutter_backend_osx_post_parse;
   backend_class->get_features = clutter_backend_osx_get_features;
-  backend_class->init_stage  = clutter_backend_osx_init_stage;
+  backend_class->create_stage = clutter_backend_osx_create_stage;
+  backend_class->ensure_context = clutter_backend_osx_ensure_context;
   backend_class->init_events = clutter_backend_osx_init_events;
-  backend_class->get_stage   = clutter_backend_osx_get_stage;
   backend_class->redraw      = clutter_backend_osx_redraw;
 }
 
diff --git a/clutter/clutter/osx/clutter-backend-osx.h b/clutter/clutter/osx/clutter-backend-osx.h
index c403657..f83d9e7 100644
--- a/clutter/clutter/osx/clutter-backend-osx.h
+++ b/clutter/clutter/osx/clutter-backend-osx.h
@@ -41,11 +41,6 @@ typedef struct _ClutterBackendOSXClass ClutterBackendOSXClass;
 struct _ClutterBackendOSX
 {
   ClutterBackend parent;
-
-  NSOpenGLPixelFormat *pixel_format;
-  NSOpenGLContext     *context;
-
-  ClutterActor *stage;
 };
 
 struct _ClutterBackendOSXClass
diff --git a/clutter/clutter/osx/clutter-event-osx.c b/clutter/clutter/osx/clutter-event-osx.c
index ec08e48..94f2507 100644
--- a/clutter/clutter/osx/clutter-event-osx.c
+++ b/clutter/clutter/osx/clutter-event-osx.c
@@ -22,6 +22,7 @@
 #include "config.h"
 
 #include "clutter-osx.h"
+#include "clutter-stage-osx.h"
 
 #import <AppKit/AppKit.h>
 #include <glib/gmain.h>
@@ -37,6 +38,7 @@ static GPollFunc old_poll_func = NULL;
 
 /*************************************************************************/
 @interface NSEvent (Clutter)
+- (ClutterStage*)clutterStage;
 - (gint)clutterTime;
 - (gint)clutterButton;
 - (void)clutterX:(gint*)ptrX y:(gint*)ptrY;
@@ -45,6 +47,29 @@ static GPollFunc old_poll_func = NULL;
 @end
 
 @implementation NSEvent (Clutter)
+- (ClutterStage*)clutterStage
+{
+  ClutterStageManager *manager;
+  GSList *stages, *l;
+  ClutterStage *stage = NULL;;
+
+  manager = clutter_stage_manager_get_default ();
+  stages = clutter_stage_manager_list_stages (manager);
+  for (l = stages; l != NULL; l = l->next)
+    {
+      ClutterStageOSX *stage_osx = l->data;
+
+      if (stage_osx->window == [self window])
+        {
+          stage = CLUTTER_STAGE (stage_osx);
+          break;
+        }
+    }
+  g_slist_free (stages);
+
+  return stage;
+}
+
 - (gint)clutterTime
 {
   return [self timestamp] * 1000;
@@ -160,6 +185,7 @@ static GPollFunc old_poll_func = NULL;
 static gboolean
 clutter_event_osx_translate (NSEvent *nsevent, ClutterEvent *event)
 {
+  event->any.stage = [nsevent clutterStage];
   event->any.time = [nsevent clutterTime];
 
   switch ([nsevent type])
diff --git a/clutter/clutter/osx/clutter-stage-osx.c b/clutter/clutter/osx/clutter-stage-osx.c
index 898890b..d8ca25e 100644
--- a/clutter/clutter/osx/clutter-stage-osx.c
+++ b/clutter/clutter/osx/clutter-stage-osx.c
@@ -69,6 +69,7 @@ clutter_stage_osx_state_update (ClutterStageOSX   *self,
 
   ClutterEvent event;
   event.type = CLUTTER_DELETE;
+  event.any.stage = CLUTTER_STAGE (self->stage);
   clutter_event_put (&event);
 
   return NO;
@@ -209,6 +210,7 @@ clutter_stage_osx_state_update (ClutterStageOSX   *self,
   self->stage_state = event.new_state;
 
   event.type = CLUTTER_STAGE_STATE;
+  event.stage = CLUTTER_STAGE (self);
   clutter_event_put ((ClutterEvent*)&event);
 }
 
@@ -283,10 +285,16 @@ clutter_stage_osx_realize (ClutterActor *actor)
 
   NSRect rect = NSMakeRect(0, 0, self->requisition_width, self->requisition_height);
 
+  NSOpenGLPixelFormatAttribute attrs[] = {
+    NSOpenGLPFADoubleBuffer,
+    0
+  };
+  NSOpenGLPixelFormat *pixel_format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
   self->view = [[ClutterGLView alloc]
                 initWithFrame: rect
-                  pixelFormat: backend_osx->pixel_format
+                  pixelFormat: pixel_format
                         stage: actor];
+  self->context = [self->view openGLContext];
 
   self->window = [[ClutterGLWindow alloc]
                   initWithView: self->view
@@ -296,16 +304,6 @@ clutter_stage_osx_realize (ClutterActor *actor)
   /* looks better than positioning to 0,0 (bottom right) */
   [self->window center];
 
-  /* To not miss all textures created with the context created in the backend
-   * make sure we share the context. (By default NSOpenGLView creates its own
-   * context.)
-   */
-  NSOpenGLContext *context = backend_osx->context;
-
-  [self->view setOpenGLContext: context];
-  [context setView: self->view];
-
-
   CLUTTER_OSX_POOL_RELEASE();
 
   CLUTTER_SET_PRIVATE_FLAGS(self, CLUTTER_ACTOR_SYNC_MATRICES);
diff --git a/clutter/clutter/osx/clutter-stage-osx.h b/clutter/clutter/osx/clutter-stage-osx.h
index 0e5d29d..1a75aa0 100644
--- a/clutter/clutter/osx/clutter-stage-osx.h
+++ b/clutter/clutter/osx/clutter-stage-osx.h
@@ -26,7 +26,7 @@
 #include <clutter/clutter-backend.h>
 
 #import <Foundation/Foundation.h>
-@class NSOpenGLView, NSWindow;
+@class NSOpenGLView, NSWindow, NSOpenGLPixelFormat, NSOpenGLContext;
 
 G_BEGIN_DECLS
 
@@ -50,6 +50,9 @@ struct _ClutterStageOSX
   NSWindow *window;
   NSOpenGLView *view;
 
+  NSOpenGLPixelFormat *pixel_format;
+  NSOpenGLContext     *context;
+
   gboolean haveNormalFrame;
   NSRect normalFrame;
 
-- 
1.5.4.4

