Move NSGlView into libgtkmm2ext
authorRobin Gareus <robin@gareus.org>
Mon, 20 Mar 2017 03:21:08 +0000 (04:21 +0100)
committerRobin Gareus <robin@gareus.org>
Mon, 20 Mar 2017 03:35:05 +0000 (04:35 +0100)
This allows to re-use the concept with CairoWidget

libs/canvas/canvas.cc
libs/canvas/canvas/canvas.h
libs/canvas/canvas/nsglview.h [deleted file]
libs/canvas/nsglview.mm [deleted file]
libs/canvas/wscript
libs/gtkmm2ext/gtkmm2ext/cairo_canvas.h [new file with mode: 0644]
libs/gtkmm2ext/gtkmm2ext/nsglview.h [new file with mode: 0644]
libs/gtkmm2ext/nsglview.mm [new file with mode: 0644]
libs/gtkmm2ext/wscript

index cdd2fbfeee8c240a1c092dda706886bd1baf0422..6ad4200cc12f2a06c92c40b48efda32ee526242a 100644 (file)
@@ -46,7 +46,7 @@
 
 #ifdef __APPLE__
 #include <gdk/gdk.h>
-#include "canvas/nsglview.h"
+#include "gtkmm2ext/nsglview.h"
 #endif
 
 using namespace std;
@@ -404,7 +404,7 @@ GtkCanvas::GtkCanvas ()
 
 #ifdef ARDOUR_CANVAS_NSVIEW_TAG // patched gdkquartz.h
 # ifndef __ppc__ // would need to flip RGBA <> RGBA
-       _nsglview = nsglview_create (this);
+       _nsglview = Gtkmm2ext::nsglview_create (this);
 # endif
 #endif
 }
@@ -773,7 +773,7 @@ GtkCanvas::on_realize ()
        Gtk::EventBox::on_realize();
 #ifdef __APPLE__
        if (_nsglview) {
-               nsglview_overlay (_nsglview, get_window()->gobj());
+               Gtkmm2ext::nsglview_overlay (_nsglview, get_window()->gobj());
        }
 #endif
 }
@@ -802,7 +802,7 @@ GtkCanvas::on_size_allocate (Gtk::Allocation& a)
                                GTK_WIDGET(gobj()),
                                GTK_WIDGET(get_toplevel()->gobj()),
                                0, 0, &xx, &yy);
-               nsglview_resize (_nsglview, xx, yy, a.get_width(), a.get_height());
+               Gtkmm2ext::nsglview_resize (_nsglview, xx, yy, a.get_width(), a.get_height());
        }
 #endif
 
@@ -820,7 +820,7 @@ GtkCanvas::on_expose_event (GdkEventExpose* ev)
        }
 #ifdef __APPLE__
        if (_nsglview) {
-               nsglview_queue_draw (_nsglview, ev->area.x, ev->area.y, ev->area.width, ev->area.height);
+               Gtkmm2ext::nsglview_queue_draw (_nsglview, ev->area.x, ev->area.y, ev->area.width, ev->area.height);
                return true;
        }
 #endif
@@ -878,7 +878,7 @@ GtkCanvas::on_expose_event (GdkEventExpose* ev)
        /* render canvas */
        if ( _single_exposure ) {
 
-               render (Rect (ev->area.x, ev->area.y, ev->area.x + ev->area.width, ev->area.y + ev->area.height), draw_context);
+               Canvas::render (Rect (ev->area.x, ev->area.y, ev->area.x + ev->area.width, ev->area.y + ev->area.height), draw_context);
 
        } else {
                GdkRectangle* rects;
@@ -887,7 +887,7 @@ GtkCanvas::on_expose_event (GdkEventExpose* ev)
                gdk_region_get_rectangles (ev->region, &rects, &nrects);
                for (gint n = 0; n < nrects; ++n) {
                        draw_context->set_identity_matrix();  //reset the cairo matrix, just in case someone left it transformed after drawing ( cough )
-                       render (Rect (rects[n].x, rects[n].y, rects[n].x + rects[n].width, rects[n].y + rects[n].height), draw_context);
+                       Canvas::render (Rect (rects[n].x, rects[n].y, rects[n].x + rects[n].width, rects[n].y + rects[n].height), draw_context);
                }
                g_free (rects);
        }
index 20adfa4c458c0123fed72fb632f0cb0ed3956030..3e554cacf2e9a061852beff0f81f9d101da4e3f8 100644 (file)
@@ -34,8 +34,9 @@
 
 #include "pbd/signals.h"
 
-#include "canvas/visibility.h"
+#include "gtkmm2ext/cairo_canvas.h"
 
+#include "canvas/visibility.h"
 #include "canvas/root_group.h"
 
 namespace Gtk {
@@ -174,7 +175,7 @@ public:
 };
 
 /** A canvas which renders onto a GTK EventBox */
-class LIBCANVAS_API GtkCanvas : public Canvas, public Gtk::EventBox
+class LIBCANVAS_API GtkCanvas : public Canvas, public Gtk::EventBox, public Gtkmm2ext::CairoCanvas
 {
 public:
        GtkCanvas ();
@@ -203,6 +204,14 @@ public:
 
        Glib::RefPtr<Pango::Context> get_pango_context();
 
+       void render (Cairo::RefPtr<Cairo::Context> const & ctx, cairo_rectangle_t* r)
+       {
+               ArdourCanvas::Rect rect (r->x, r->y, r->width + r->x, r->height + r->y);
+               Canvas::render (rect, ctx);
+       }
+
+       uint32_t background_color() { return Canvas::background_color (); }
+
   protected:
        void on_size_allocate (Gtk::Allocation&);
        bool on_scroll_event (GdkEventScroll *);
diff --git a/libs/canvas/canvas/nsglview.h b/libs/canvas/canvas/nsglview.h
deleted file mode 100644 (file)
index e18a0f6..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef __CANVAS_NSGLVIEW_H__
-#define __CANVAS_NSGLVIEW_H__
-
-#include <gdk/gdk.h>
-
-namespace ArdourCanvas
-{
-       class GtkCanvas;
-
-       void* nsglview_create (GtkCanvas*);
-       void  nsglview_overlay (void*, GdkWindow*);
-       void  nsglview_resize (void*, int x, int y, int w, int h);
-       void  nsglview_queue_draw (void*, int x, int y, int w, int h);
-}
-#endif
diff --git a/libs/canvas/nsglview.mm b/libs/canvas/nsglview.mm
deleted file mode 100644 (file)
index b4fea99..0000000
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
-    Copyright (C) 2011 Paul Davis
-    Copyright (C) 2012 David Robillard <http://drobilla.net>
-    Copyright (C) 2017 Robin Gareus <robin@gareus.org>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program 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 General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-/* include order matter due to apple defines */
-#include <gtkmm/window.h>
-
-#include "canvas/canvas.h"
-#include "canvas/utils.h"
-#include "canvas/nsglview.h"
-
-#include <gdk/gdkquartz.h>
-
-#include <OpenGL/gl.h>
-#import  <Cocoa/Cocoa.h>
-
-#ifndef ARDOUR_CANVAS_NSVIEW_TAG
-#define ARDOUR_CANVAS_NSVIEW_TAG 0xa2d0c2c4
-#endif
-
-__attribute__ ((visibility ("hidden")))
-@interface ArdourCanvasOpenGLView : NSOpenGLView
-{
-@private
-       unsigned int _texture_id;
-       int _width;
-       int _height;
-       Cairo::RefPtr<Cairo::ImageSurface> surf;
-       ArdourCanvas::GtkCanvas *gtkcanvas;
-}
-
-@property (readwrite) NSInteger tag;
-
-- (id) initWithFrame:(NSRect)frame;
-- (void) dealloc;
-- (void) setArdourCanvas:(ArdourCanvas::GtkCanvas*)c;
-- (void) reshape;
-- (void) drawRect:(NSRect)rect;
-- (BOOL) canBecomeKeyWindow:(id)sender;
-- (BOOL) acceptsFirstResponder:(id)sender;
-
-@end
-
-@implementation ArdourCanvasOpenGLView
-
-@synthesize tag = _tag;
-
-- (id) initWithFrame:(NSRect)frame
-{
-       NSOpenGLPixelFormatAttribute pixelAttribs[16] = {
-               NSOpenGLPFADoubleBuffer,
-               NSOpenGLPFAAccelerated,
-               NSOpenGLPFAColorSize, 32,
-               NSOpenGLPFADepthSize, 32,
-               NSOpenGLPFAMultisample,
-               NSOpenGLPFASampleBuffers, 1,
-               NSOpenGLPFASamples, 4,
-               0
-       };
-
-       NSOpenGLPixelFormat* pixelFormat =
-               [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelAttribs];
-
-       if (pixelFormat) {
-               self = [super initWithFrame:frame pixelFormat:pixelFormat];
-               [pixelFormat release];
-       } else {
-               self = [super initWithFrame:frame];
-       }
-
-       _texture_id = 0;
-       _width = 0;
-       _height = 0;
-
-       if (self) {
-               self.tag = ARDOUR_CANVAS_NSVIEW_TAG;
-               [[self openGLContext] makeCurrentContext];
-               glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
-               glDisable (GL_DEPTH_TEST);
-               glEnable (GL_BLEND);
-               glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-               glEnable (GL_TEXTURE_RECTANGLE_ARB);
-               [NSOpenGLContext clearCurrentContext];
-
-               [self reshape];
-       }
-
-       return self;
-}
-
-- (void) dealloc {
-       [[self openGLContext] makeCurrentContext];
-       glDeleteTextures (1, &_texture_id);
-       [NSOpenGLContext clearCurrentContext];
-
-       [super dealloc];
-}
-
-- (void) setArdourCanvas:(ArdourCanvas::GtkCanvas*)c
-{
-       gtkcanvas = c;
-}
-
-- (BOOL) canBecomeKeyWindow:(id)sender{
-       return NO;
-}
-
-- (BOOL) acceptsFirstResponder:(id)sender{
-       return NO;
-}
-
-- (void) reshape
-{
-       [[self openGLContext] update];
-
-       NSRect bounds = [self bounds];
-       int    width  = bounds.size.width;
-       int    height = bounds.size.height;
-
-       if (_width == width && _height == height) {
-               return;
-       }
-
-       [[self openGLContext] makeCurrentContext];
-
-       glViewport (0, 0, width, height);
-       glMatrixMode (GL_PROJECTION);
-       glLoadIdentity ();
-       glOrtho (-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);
-
-       glClear (GL_COLOR_BUFFER_BIT);
-
-       glDeleteTextures (1, &_texture_id);
-       glGenTextures (1, &_texture_id);
-       glBindTexture (GL_TEXTURE_RECTANGLE_ARB, _texture_id);
-       glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
-                       width, height, 0,
-                       GL_BGRA, GL_UNSIGNED_BYTE, NULL);
-       glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
-
-       glMatrixMode(GL_MODELVIEW);
-       glLoadIdentity();
-
-       [NSOpenGLContext clearCurrentContext];
-
-       _width  = width;
-       _height = height;
-}
-
-- (void) drawRect:(NSRect)rect
-{
-       [[self openGLContext] makeCurrentContext];
-
-       glMatrixMode(GL_MODELVIEW);
-       glLoadIdentity();
-       glClear(GL_COLOR_BUFFER_BIT);
-
-       /* call back into GtkCanvas */
-
-       ArdourCanvas::Rect crect (rect.origin.x, rect.origin.y,
-       rect.size.width + rect.origin.x,
-       rect.size.height + rect.origin.y);
-
-       if (!surf || surf->get_width () != _width || surf->get_height() != _height) {
-               surf = Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, _width, _height);
-
-               crect.x0 = crect.y0 = 0;
-               crect.x1 = _width;
-               crect.y1 = _height;
-       }
-
-       Cairo::RefPtr<Cairo::Context> ctx = Cairo::Context::create (surf);
-
-       // TODO: check retina screen, scaling factor.
-       // cairo_surface_get_device_scale () or explicit scale
-
-       ctx->rectangle (crect.x0, crect.y0, crect.width(), crect.height());
-       ctx->clip_preserve ();
-       /* draw background color */
-       ArdourCanvas::set_source_rgba (ctx, gtkcanvas->background_color ());
-       ctx->fill ();
-
-       gtkcanvas->render (crect, ctx);
-
-       surf->flush ();
-       uint8_t* imgdata = surf->get_data ();
-
-       /* NOTE for big-endian (PPC), we'd need to flip byte-order
-        * RGBA <> RGBA for the texture.
-        * GtkCanvas does not use this nsview for PPC builds, yet
-        */
-
-       /* continue OpenGL */
-       glPushMatrix ();
-
-       glEnable(GL_TEXTURE_2D);
-       glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _texture_id);
-       glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
-                       _width, _height, /*border*/ 0,
-                       GL_BGRA, GL_UNSIGNED_BYTE, imgdata);
-
-       glBegin(GL_QUADS);
-       glTexCoord2f(           0.0f, (GLfloat) _height);
-       glVertex2f(-1.0f, -1.0f);
-
-       glTexCoord2f((GLfloat) _width, (GLfloat) _height);
-       glVertex2f( 1.0f, -1.0f);
-
-       glTexCoord2f((GLfloat) _width, 0.0f);
-       glVertex2f( 1.0f,  1.0f);
-
-       glTexCoord2f(            0.0f, 0.0f);
-       glVertex2f(-1.0f,  1.0f);
-       glEnd();
-
-       glDisable(GL_TEXTURE_2D);
-       glPopMatrix();
-
-       ///
-
-       glFlush();
-       glSwapAPPLE();
-       [NSOpenGLContext clearCurrentContext];
-}
-
-@end
-
-
-void*
-ArdourCanvas::nsglview_create (GtkCanvas* canvas)
-{
-       ArdourCanvasOpenGLView* gl_view = [ArdourCanvasOpenGLView new];
-       if (!gl_view) {
-               return 0;
-       }
-       [gl_view setArdourCanvas:canvas];
-       return gl_view;
-}
-
-void
-ArdourCanvas::nsglview_overlay (void* glv, GdkWindow* window)
-{
-       ArdourCanvasOpenGLView* gl_view = (ArdourCanvasOpenGLView*) glv;
-       NSView* view = gdk_quartz_window_get_nsview (window);
-       [view addSubview:gl_view];
-}
-
-void
-ArdourCanvas::nsglview_resize (void* glv, int x, int y, int w, int h)
-{
-       ArdourCanvasOpenGLView* gl_view = (ArdourCanvasOpenGLView*) glv;
-       [gl_view setFrame:NSMakeRect(x, y, w, h)];
-}
-
-void
-ArdourCanvas::nsglview_queue_draw (void* glv, int x, int y, int w, int h)
-{
-       ArdourCanvasOpenGLView* gl_view = (ArdourCanvasOpenGLView*) glv;
-       [gl_view setNeedsDisplayInRect:NSMakeRect(x, y, w, h)];
-}
index cdb6156f15e84a134df74292677ad4db2653f4a4..6294fe0d051f4fd93d1dbe9e94a58f84cc59eed7 100644 (file)
@@ -3,7 +3,6 @@ from waflib.extras import autowaf as autowaf
 from waflib import Options
 from waflib import TaskGen
 import os
-import sys
 
 # Version of this package (even if built as a child)
 MAJOR = '0'
@@ -97,9 +96,6 @@ def build(bld):
     obj.install_path = bld.env['LIBDIR']
     obj.defines      += [ 'PACKAGE="' + I18N_PACKAGE + '"' ]
 
-    if sys.platform == 'darwin':
-        obj.source += [ 'nsglview.mm']
-
     # canvas unit-tests are outdated
     if False and bld.env['BUILD_TESTS'] and bld.is_defined('HAVE_CPPUNIT'):
             unit_testobj              = bld(features = 'cxx cxxprogram')
diff --git a/libs/gtkmm2ext/gtkmm2ext/cairo_canvas.h b/libs/gtkmm2ext/gtkmm2ext/cairo_canvas.h
new file mode 100644 (file)
index 0000000..7dd9d44
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+    Copyright (C) 2009 Paul Davis
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program 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 General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __gtk2_ardour_cairo_canvas_h__
+#define __gtk2_ardour_cairo_canvas_h__
+
+#include <cairomm/context.h>
+#include "gtkmm2ext/visibility.h"
+
+namespace Gtkmm2ext {
+
+class LIBGTKMM2EXT_API CairoCanvas
+{
+public:
+       virtual ~CairoCanvas () {}
+
+       virtual void render (Cairo::RefPtr<Cairo::Context> const&, cairo_rectangle_t*) = 0;
+       virtual uint32_t background_color () = 0;
+};
+
+} /* namespace */
+#endif
diff --git a/libs/gtkmm2ext/gtkmm2ext/nsglview.h b/libs/gtkmm2ext/gtkmm2ext/nsglview.h
new file mode 100644 (file)
index 0000000..8a175f3
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef __CANVAS_NSGLVIEW_H__
+#define __CANVAS_NSGLVIEW_H__
+
+#include <gdk/gdk.h>
+
+namespace Gtkmm2ext
+{
+       class CairoCanvas;
+
+       void* nsglview_create (CairoCanvas*);
+       void  nsglview_overlay (void*, GdkWindow*);
+       void  nsglview_resize (void*, int x, int y, int w, int h);
+       void  nsglview_queue_draw (void*, int x, int y, int w, int h);
+}
+#endif
diff --git a/libs/gtkmm2ext/nsglview.mm b/libs/gtkmm2ext/nsglview.mm
new file mode 100644 (file)
index 0000000..a984293
--- /dev/null
@@ -0,0 +1,284 @@
+/*
+    Copyright (C) 2011 Paul Davis
+    Copyright (C) 2012 David Robillard <http://drobilla.net>
+    Copyright (C) 2017 Robin Gareus <robin@gareus.org>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program 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 General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/* include order matter due to apple defines */
+#include <gtkmm/window.h>
+
+#include "gtkmm2ext/cairo_canvas.h"
+#include "gtkmm2ext/nsglview.h"
+#include "gtkmm2ext/rgb_macros.h"
+
+#include <gdk/gdkquartz.h>
+
+#include <OpenGL/gl.h>
+#import  <Cocoa/Cocoa.h>
+
+#ifndef ARDOUR_CANVAS_NSVIEW_TAG
+#define ARDOUR_CANVAS_NSVIEW_TAG 0xa2d0c2c4
+#endif
+
+__attribute__ ((visibility ("hidden")))
+@interface ArdourCanvasOpenGLView : NSOpenGLView
+{
+@private
+       unsigned int _texture_id;
+       int _width;
+       int _height;
+       Cairo::RefPtr<Cairo::ImageSurface> surf;
+       Gtkmm2ext::CairoCanvas *cairo_canvas;
+}
+
+@property (readwrite) NSInteger tag;
+
+- (id) initWithFrame:(NSRect)frame;
+- (void) dealloc;
+- (void) setCairoCanvas:(Gtkmm2ext::CairoCanvas*)c;
+- (void) reshape;
+- (void) drawRect:(NSRect)rect;
+- (BOOL) canBecomeKeyWindow:(id)sender;
+- (BOOL) acceptsFirstResponder:(id)sender;
+
+@end
+
+@implementation ArdourCanvasOpenGLView
+
+@synthesize tag = _tag;
+
+- (id) initWithFrame:(NSRect)frame
+{
+       NSOpenGLPixelFormatAttribute pixelAttribs[16] = {
+               NSOpenGLPFADoubleBuffer,
+               NSOpenGLPFAAccelerated,
+               NSOpenGLPFAColorSize, 32,
+               NSOpenGLPFADepthSize, 32,
+               NSOpenGLPFAMultisample,
+               NSOpenGLPFASampleBuffers, 1,
+               NSOpenGLPFASamples, 4,
+               0
+       };
+
+       NSOpenGLPixelFormat* pixelFormat =
+               [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelAttribs];
+
+       if (pixelFormat) {
+               self = [super initWithFrame:frame pixelFormat:pixelFormat];
+               [pixelFormat release];
+       } else {
+               self = [super initWithFrame:frame];
+       }
+
+       _texture_id = 0;
+       _width = 0;
+       _height = 0;
+
+       if (self) {
+               self.tag = ARDOUR_CANVAS_NSVIEW_TAG;
+               [[self openGLContext] makeCurrentContext];
+               glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
+               glDisable (GL_DEPTH_TEST);
+               glEnable (GL_BLEND);
+               glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+               glEnable (GL_TEXTURE_RECTANGLE_ARB);
+               [NSOpenGLContext clearCurrentContext];
+
+               [self reshape];
+       }
+
+       return self;
+}
+
+- (void) dealloc {
+       [[self openGLContext] makeCurrentContext];
+       glDeleteTextures (1, &_texture_id);
+       [NSOpenGLContext clearCurrentContext];
+
+       [super dealloc];
+}
+
+- (void) setCairoCanvas:(Gtkmm2ext::CairoCanvas*)c
+{
+       cairo_canvas = c;
+}
+
+- (BOOL) canBecomeKeyWindow:(id)sender{
+       return NO;
+}
+
+- (BOOL) acceptsFirstResponder:(id)sender{
+       return NO;
+}
+
+- (void) reshape
+{
+       [[self openGLContext] update];
+
+       NSRect bounds = [self bounds];
+       int    width  = bounds.size.width;
+       int    height = bounds.size.height;
+
+       if (_width == width && _height == height) {
+               return;
+       }
+
+       [[self openGLContext] makeCurrentContext];
+
+       glViewport (0, 0, width, height);
+       glMatrixMode (GL_PROJECTION);
+       glLoadIdentity ();
+       glOrtho (-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);
+
+       glClear (GL_COLOR_BUFFER_BIT);
+
+       glDeleteTextures (1, &_texture_id);
+       glGenTextures (1, &_texture_id);
+       glBindTexture (GL_TEXTURE_RECTANGLE_ARB, _texture_id);
+       glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
+                       width, height, 0,
+                       GL_BGRA, GL_UNSIGNED_BYTE, NULL);
+       glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
+
+       glMatrixMode(GL_MODELVIEW);
+       glLoadIdentity();
+
+       [NSOpenGLContext clearCurrentContext];
+
+       _width  = width;
+       _height = height;
+}
+
+- (void) drawRect:(NSRect)rect
+{
+       [[self openGLContext] makeCurrentContext];
+
+       glMatrixMode(GL_MODELVIEW);
+       glLoadIdentity();
+       glClear(GL_COLOR_BUFFER_BIT);
+
+       /* call back into CairoCanvas */
+       cairo_rectangle_t cairo_rect;
+
+       cairo_rect.x = rect.origin.x;
+       cairo_rect.y = rect.origin.y;
+       cairo_rect.width = rect.size.width;
+       cairo_rect.height = rect.size.height;
+
+       if (!surf || surf->get_width () != _width || surf->get_height() != _height) {
+               surf = Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, _width, _height);
+
+               cairo_rect.x = 0;
+               cairo_rect.y = 0;
+               cairo_rect.width = _width;
+               cairo_rect.height = _height;
+       }
+
+       Cairo::RefPtr<Cairo::Context> ctx = Cairo::Context::create (surf);
+
+       // TODO: check retina screen, scaling factor.
+       // cairo_surface_get_device_scale () or explicit scale
+
+       ctx->rectangle (cairo_rect.x, cairo_rect.y, cairo_rect.width, cairo_rect.height);
+       ctx->clip_preserve ();
+       {
+               /* draw background color */
+               uint32_t col = cairo_canvas->background_color ();
+               int r, g, b, a;
+               UINT_TO_RGBA (col, &r, &g, &b, &a);
+               ctx->set_source_rgba (r/255.0, g/255.0, b/255.0, a/255.0);
+       }
+       ctx->fill ();
+
+       cairo_canvas->render (ctx, &cairo_rect);
+
+       surf->flush ();
+       uint8_t* imgdata = surf->get_data ();
+
+       /* NOTE for big-endian (PPC), we'd need to flip byte-order
+        * RGBA <> RGBA for the texture.
+        * GtkCanvas does not use this nsview for PPC builds, yet
+        */
+
+       /* continue OpenGL */
+       glPushMatrix ();
+
+       glEnable(GL_TEXTURE_2D);
+       glBindTexture(GL_TEXTURE_RECTANGLE_ARB, _texture_id);
+       glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
+                       _width, _height, /*border*/ 0,
+                       GL_BGRA, GL_UNSIGNED_BYTE, imgdata);
+
+       glBegin(GL_QUADS);
+       glTexCoord2f(           0.0f, (GLfloat) _height);
+       glVertex2f(-1.0f, -1.0f);
+
+       glTexCoord2f((GLfloat) _width, (GLfloat) _height);
+       glVertex2f( 1.0f, -1.0f);
+
+       glTexCoord2f((GLfloat) _width, 0.0f);
+       glVertex2f( 1.0f,  1.0f);
+
+       glTexCoord2f(            0.0f, 0.0f);
+       glVertex2f(-1.0f,  1.0f);
+       glEnd();
+
+       glDisable(GL_TEXTURE_2D);
+       glPopMatrix();
+
+       ///
+
+       glFlush();
+       glSwapAPPLE();
+       [NSOpenGLContext clearCurrentContext];
+}
+@end
+
+
+void*
+Gtkmm2ext::nsglview_create (Gtkmm2ext::CairoCanvas* canvas)
+{
+       ArdourCanvasOpenGLView* gl_view = [ArdourCanvasOpenGLView new];
+       if (!gl_view) {
+               return 0;
+       }
+       [gl_view setCairoCanvas:canvas];
+       return gl_view;
+}
+
+void
+Gtkmm2ext::nsglview_overlay (void* glv, GdkWindow* window)
+{
+       ArdourCanvasOpenGLView* gl_view = (ArdourCanvasOpenGLView*) glv;
+       NSView* view = gdk_quartz_window_get_nsview (window);
+       [view addSubview:gl_view];
+}
+
+void
+Gtkmm2ext::nsglview_resize (void* glv, int x, int y, int w, int h)
+{
+       ArdourCanvasOpenGLView* gl_view = (ArdourCanvasOpenGLView*) glv;
+       [gl_view setFrame:NSMakeRect(x, y, w, h)];
+}
+
+void
+Gtkmm2ext::nsglview_queue_draw (void* glv, int x, int y, int w, int h)
+{
+       ArdourCanvasOpenGLView* gl_view = (ArdourCanvasOpenGLView*) glv;
+       [gl_view setNeedsDisplayInRect:NSMakeRect(x, y, w, h)];
+}
index 4e1a03190676a0e2c44e97d8624cae5a40cbe96c..ef13e600717a772bb6ead9d04d12c5114fea70a6 100644 (file)
@@ -118,7 +118,7 @@ def build(bld):
                     'LOCALEDIR="' + os.path.join(
                             os.path.normpath(bld.env['DATADIR']), 'locale') + '"']
     if sys.platform == 'darwin':
-        obj.source += ['gtkapplication_quartz.mm']
+        obj.source += ['gtkapplication_quartz.mm', 'nsglview.mm']
     else:
         obj.source += ['gtkapplication_x11.c']