aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pugl/detail/cairo_gl.h103
-rw-r--r--pugl/detail/mac.m142
2 files changed, 113 insertions, 132 deletions
diff --git a/pugl/detail/cairo_gl.h b/pugl/detail/cairo_gl.h
deleted file mode 100644
index b6e8566..0000000
--- a/pugl/detail/cairo_gl.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- Copyright 2016-2019 David Robillard <http://drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-/**
- @file cairo_gl.h Generic Cairo to OpenGL drawing support.
-*/
-
-#include "pugl/gl.h"
-
-#include <cairo.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-typedef struct {
- unsigned texture_id;
- uint8_t* buffer;
-} PuglCairoGL;
-
-static cairo_surface_t*
-pugl_cairo_gl_create(PuglCairoGL* ctx, int width, int height, int bpp)
-{
- free(ctx->buffer);
- ctx->buffer = (uint8_t*)calloc(bpp * width * height, sizeof(uint8_t));
- if (!ctx->buffer) {
- return NULL;
- }
-
- glDeleteTextures(1, &ctx->texture_id);
- glGenTextures(1, &ctx->texture_id);
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ctx->texture_id);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
-
- return cairo_image_surface_create_for_data(
- ctx->buffer, CAIRO_FORMAT_ARGB32, width, height, bpp * width);
-}
-
-static void
-pugl_cairo_gl_free(PuglCairoGL* ctx)
-{
- free(ctx->buffer);
- ctx->buffer = NULL;
-}
-
-static void
-pugl_cairo_gl_configure(PuglCairoGL* ctx, int width, int height)
-{
- (void)ctx;
- (void)width;
- (void)height;
- glDisable(GL_DEPTH_TEST);
- glEnable(GL_TEXTURE_RECTANGLE_ARB);
-
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);
-}
-
-static void
-pugl_cairo_gl_draw(PuglCairoGL* ctx, int width, int height)
-{
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- glViewport(0, 0, width, height);
-
- glPushMatrix();
- glEnable(GL_TEXTURE_RECTANGLE_ARB);
- glEnable(GL_TEXTURE_2D);
-
- glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
- width, height, 0,
- GL_BGRA, GL_UNSIGNED_BYTE, ctx->buffer);
-
- 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);
- glDisable(GL_TEXTURE_RECTANGLE_ARB);
- glPopMatrix();
-}
diff --git a/pugl/detail/mac.m b/pugl/detail/mac.m
index 6bbe4fb..2316ca3 100644
--- a/pugl/detail/mac.m
+++ b/pugl/detail/mac.m
@@ -27,8 +27,9 @@
#include "pugl/pugl_gl_backend.h"
#ifdef PUGL_HAVE_CAIRO
-#include "pugl/detail/cairo_gl.h"
#include "pugl/pugl_cairo_backend.h"
+
+#include <cairo-quartz.h>
#endif
#import <Cocoa/Cocoa.h>
@@ -45,6 +46,7 @@ typedef NSUInteger NSWindowStyleMask;
@class PuglWrapperView;
@class PuglOpenGLView;
+@class PuglCairoView;
struct PuglInternalsImpl {
NSApplication* app;
@@ -53,11 +55,6 @@ struct PuglInternalsImpl {
id window;
NSEvent* nextEvent;
uint32_t mods;
-#ifdef PUGL_HAVE_CAIRO
- cairo_surface_t* surface;
- cairo_t* cr;
- PuglCairoGL cairo_gl;
-#endif
};
@interface PuglWindow : NSWindow
@@ -675,6 +672,59 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type)
@end
+@interface PuglCairoView : NSView
+{
+@public
+ PuglView* puglview;
+ cairo_surface_t* surface;
+ cairo_t* cr;
+}
+
+@end
+
+@implementation PuglCairoView
+
+- (id) initWithFrame:(NSRect)frame
+{
+ return (self = [super initWithFrame:frame]);
+}
+
+- (void) resizeWithOldSuperviewSize:(NSSize)oldSize
+{
+ [super resizeWithOldSuperviewSize:oldSize];
+
+ const NSRect bounds = [self bounds];
+ puglview->backend->resize(puglview, bounds.size.width, bounds.size.height);
+
+ const PuglEventConfigure ev = {
+ PUGL_CONFIGURE,
+ 0,
+ bounds.origin.x,
+ bounds.origin.y,
+ bounds.size.width,
+ bounds.size.height,
+ };
+
+ puglDispatchEvent(puglview, (const PuglEvent*)&ev);
+}
+
+- (void) drawRect:(NSRect)rect
+{
+ const PuglEventExpose ev = {
+ PUGL_EXPOSE,
+ 0,
+ rect.origin.x,
+ rect.origin.y,
+ rect.size.width,
+ rect.size.height,
+ 0
+ };
+
+ puglDispatchEvent(puglview, (const PuglEvent*)&ev);
+}
+
+@end
+
@interface PuglWindowDelegate : NSObject<NSWindowDelegate>
{
PuglWindow* window;
@@ -1051,22 +1101,54 @@ const PuglBackend* puglGlBackend(void)
static int
puglMacCairoCreate(PuglView* view)
{
- return puglMacGlCreate(view);
+ PuglInternals* impl = view->impl;
+ PuglCairoView* drawView = [PuglCairoView alloc];
+
+ drawView->puglview = view;
+ [drawView initWithFrame:NSMakeRect(0, 0, view->width, view->height)];
+ if (view->hints.resizable) {
+ [drawView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
+ } else {
+ [drawView setAutoresizingMask:NSViewNotSizable];
+ }
+
+ impl->drawView = drawView;
+ return 0;
}
static int
puglMacCairoDestroy(PuglView* view)
{
- pugl_cairo_gl_free(&view->impl->cairo_gl);
- return puglMacGlDestroy(view);
+ PuglCairoView* const drawView = (PuglCairoView*)view->impl->drawView;
+
+ [drawView removeFromSuperview];
+ [drawView release];
+
+ view->impl->drawView = nil;
+ return 0;
}
static int
-puglMacCairoEnter(PuglView* view, bool PUGL_UNUSED(drawing))
+puglMacCairoEnter(PuglView* view, bool drawing)
{
- PuglOpenGLView* const drawView = (PuglOpenGLView*)view->impl->drawView;
+ PuglCairoView* const drawView = (PuglCairoView*)view->impl->drawView;
+ if (!drawing) {
+ return 0;
+ }
- [[drawView openGLContext] makeCurrentContext];
+ // Get Quartz context and transform to Cairo coordinates (TL origin)
+ CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];
+ CGContextTranslateCTM(context, 0.0, view->height);
+ CGContextScaleCTM(context, 1.0, -1.0);
+
+ // Create a Cairo surface and context for drawing to Quartz
+ assert(!drawView->surface);
+ assert(!drawView->cr);
+
+ drawView->surface = cairo_quartz_surface_create_for_cg_context(
+ context, view->width, view->height);
+
+ drawView->cr = cairo_create(drawView->surface);
return 0;
}
@@ -1074,37 +1156,39 @@ puglMacCairoEnter(PuglView* view, bool PUGL_UNUSED(drawing))
static int
puglMacCairoLeave(PuglView* view, bool drawing)
{
- PuglOpenGLView* const drawView = (PuglOpenGLView*)view->impl->drawView;
-
- if (drawing) {
- pugl_cairo_gl_draw(&view->impl->cairo_gl, view->width, view->height);
- [[drawView openGLContext] flushBuffer];
+ PuglCairoView* const drawView = (PuglCairoView*)view->impl->drawView;
+ if (!drawing) {
+ return 0;
}
- [NSOpenGLContext clearCurrentContext];
+ CGContextRef context = cairo_quartz_surface_get_cg_context(drawView->surface);
+
+ cairo_destroy(drawView->cr);
+ cairo_surface_destroy(drawView->surface);
+
+ CGContextFlush(context);
+
+ drawView->cr = NULL;
+ drawView->surface = NULL;
return 0;
}
-
static int
-puglMacCairoResize(PuglView* view, int width, int height)
+puglMacCairoResize(PuglView* PUGL_UNUSED(view),
+ int PUGL_UNUSED(width),
+ int PUGL_UNUSED(height))
{
- PuglInternals* impl = view->impl;
-
- cairo_surface_destroy(impl->surface);
- cairo_destroy(impl->cr);
- impl->surface = pugl_cairo_gl_create(&impl->cairo_gl, width, height, 4);
- impl->cr = cairo_create(impl->surface);
- pugl_cairo_gl_configure(&impl->cairo_gl, width, height);
-
+ // No need to resize, the surface is created for the drawing context
return 0;
}
static void*
puglMacCairoGetContext(PuglView* view)
{
- return view->impl->cr;
+ PuglCairoView* const drawView = (PuglCairoView*)view->impl->drawView;
+
+ return drawView->cr;
}
const PuglBackend* puglCairoBackend(void)