diff options
-rw-r--r-- | pugl/detail/cairo_gl.h | 103 | ||||
-rw-r--r-- | pugl/detail/mac.m | 142 |
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) |