mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-10 00:34:59 +01:00
Move NSGlView into libgtkmm2ext
This allows to re-use the concept with CairoWidget
This commit is contained in:
parent
b726255007
commit
b5e613d453
7 changed files with 91 additions and 41 deletions
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 *);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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)];
|
||||
}
|
||||
|
|
@ -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')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue