Merge branch 'wip/chergert/gdk-macos-gl-renderer' into 'master'

macos: implement GL rendering on with Cairo renderer

See merge request GNOME/gtk!2759
This commit is contained in:
Matthias Clasen 2020-10-29 18:33:13 +00:00
commit 6142238237
11 changed files with 528 additions and 239 deletions

View File

@ -57,12 +57,6 @@
return self; return self;
} }
-(void)setNeedsDisplay:(BOOL)needsDisplay
{
for (id child in [self subviews])
[child setNeedsDisplay:needsDisplay];
}
-(void)setOpaqueRegion:(cairo_region_t *)region -(void)setOpaqueRegion:(cairo_region_t *)region
{ {
/* Do nothing */ /* Do nothing */

View File

@ -53,6 +53,12 @@
return YES; return YES;
} }
-(void)setNeedsDisplay:(BOOL)needsDisplay
{
for (id child in [self subviews])
[child setNeedsDisplay:needsDisplay];
}
-(void)setCairoSurface:(cairo_surface_t *)cairoSurface -(void)setCairoSurface:(cairo_surface_t *)cairoSurface
withDamage:(cairo_region_t *)cairoRegion withDamage:(cairo_region_t *)cairoRegion
{ {

View File

@ -1,157 +0,0 @@
/* GdkMacosGLLayer.c
*
* Copyright © 2020 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/* Based on Chromium image_transport_surface_calayer_mac.mm
* See the BSD-style license above.
*/
#include "config.h"
#include <OpenGL/gl.h>
#import "GdkMacosGLLayer.h"
@implementation GdkMacosGLLayer
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-(id)initWithContext:(NSOpenGLContext *)shared
{
[super init];
_shared = [shared retain];
return self;
}
-(void)dealloc
{
[_shared release];
_shared = nil;
[super dealloc];
}
-(void)setContentsRect:(NSRect)bounds
{
_pixelSize = bounds.size;
[super setContentsRect:bounds];
}
-(CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask
{
return CGLRetainPixelFormat ([[_shared pixelFormat] CGLPixelFormatObj]);
}
-(CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat
{
CGLContextObj context = NULL;
CGLCreateContext (pixelFormat, [_shared CGLContextObj], &context);
return context;
}
-(BOOL)canDrawInCGLContext:(CGLContextObj)glContext
pixelFormat:(CGLPixelFormatObj)pixelFormat
forLayerTime:(CFTimeInterval)timeInterval
displayTime:(const CVTimeStamp*)timeStamp
{
return YES;
}
-(void)drawInCGLContext:(CGLContextObj)glContext
pixelFormat:(CGLPixelFormatObj)pixelFormat
forLayerTime:(CFTimeInterval)timeInterval
displayTime:(const CVTimeStamp*)timeStamp
{
if (_texture == 0)
return;
glClearColor (1, 0, 1, 1);
glClear (GL_COLOR_BUFFER_BIT);
GLint viewport[4] = {0, 0, 0, 0};
glGetIntegerv (GL_VIEWPORT, viewport);
NSSize viewportSize = NSMakeSize (viewport[2], viewport[3]);
/* Set the coordinate system to be one-to-one with pixels. */
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glOrtho (0, viewportSize.width, 0, viewportSize.height, -1, 1);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
/* Draw a fullscreen quad. */
glColor4f (1, 1, 1, 1);
glEnable (GL_TEXTURE_RECTANGLE_ARB);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, _texture);
glBegin (GL_QUADS);
{
glTexCoord2f (0, 0);
glVertex2f (0, 0);
glTexCoord2f (0, _pixelSize.height);
glVertex2f (0, _pixelSize.height);
glTexCoord2f (_pixelSize.width, _pixelSize.height);
glVertex2f (_pixelSize.width, _pixelSize.height);
glTexCoord2f (_pixelSize.width, 0);
glVertex2f (_pixelSize.width, 0);
}
glEnd ();
glBindTexture (0, _texture);
glDisable (GL_TEXTURE_RECTANGLE_ARB);
[super drawInCGLContext:glContext
pixelFormat:pixelFormat
forLayerTime:timeInterval
displayTime:timeStamp];
}
-(void)setTexture:(GLuint)texture
{
_texture = texture;
[self setNeedsDisplay];
}
G_GNUC_END_IGNORE_DEPRECATIONS
@end

124
gdk/macos/GdkMacosGLView.c Normal file
View File

@ -0,0 +1,124 @@
/* GdkMacosGLView.c
*
* Copyright 2020 Christian Hergert <chergert@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "config.h"
#include <CoreGraphics/CoreGraphics.h>
#include <OpenGL/gl.h>
#include "gdkinternals.h"
#include "gdkmacossurface-private.h"
#import "GdkMacosGLView.h"
@implementation GdkMacosGLView
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-(void)lockFocus
{
NSOpenGLContext *context;
[super lockFocus];
context = [self openGLContext];
if ([context view] != self)
[context setView: self];
}
-(void)drawRect:(NSRect)rect
{
}
-(void)clearGLContext
{
if (_openGLContext != nil)
[_openGLContext clearDrawable];
_openGLContext = nil;
}
-(void)setOpenGLContext:(NSOpenGLContext*)context
{
if (_openGLContext != context)
{
if (_openGLContext != nil)
[_openGLContext clearDrawable];
_openGLContext = context;
if (_openGLContext != nil)
{
[_openGLContext setView:self];
[self setWantsLayer:YES];
[self.layer setContentsGravity:kCAGravityBottomLeft];
[_openGLContext update];
}
}
}
-(NSOpenGLContext *)openGLContext
{
return _openGLContext;
}
-(BOOL)isOpaque
{
return NO;
}
-(BOOL)isFlipped
{
return YES;
}
-(BOOL)acceptsFirstMouse
{
return YES;
}
-(BOOL)mouseDownCanMoveWindow
{
return NO;
}
-(void)invalidateRegion:(const cairo_region_t *)region
{
if (region != NULL)
{
guint n_rects = cairo_region_num_rectangles (region);
for (guint i = 0; i < n_rects; i++)
{
cairo_rectangle_int_t rect;
NSRect nsrect;
cairo_region_get_rectangle (region, i, &rect);
nsrect = NSMakeRect (rect.x, rect.y, rect.width, rect.height);
[self setNeedsDisplayInRect:nsrect];
}
}
}
G_GNUC_END_IGNORE_DEPRECATIONS
@end

View File

@ -1,6 +1,7 @@
/* GdkMacosGLLayer.h /* GdkMacosGLView.h
* *
* Copyright © 2020 Red Hat, Inc. * Copyright © 2020 Red Hat, Inc.
* Copyright © 2005-2007 Imendio AB
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -18,23 +19,23 @@
* SPDX-License-Identifier: LGPL-2.1-or-later * SPDX-License-Identifier: LGPL-2.1-or-later
*/ */
#include <AppKit/AppKit.h> #include <cairo.h>
#include <glib.h>
#define GDK_IS_MACOS_GL_LAYER(obj) ((obj) && [obj isKindOfClass:[GdkMacosGLLayer class]]) #import "GdkMacosBaseView.h"
#define GDK_IS_MACOS_GL_VIEW(obj) ((obj) && [obj isKindOfClass:[GdkMacosGLView class]])
G_GNUC_BEGIN_IGNORE_DEPRECATIONS G_GNUC_BEGIN_IGNORE_DEPRECATIONS
@interface GdkMacosGLLayer : CAOpenGLLayer @interface GdkMacosGLView : GdkMacosBaseView
{ {
NSOpenGLContext *_shared; NSOpenGLContext *_openGLContext;
GLuint _texture;
NSSize _pixelSize;
} }
-(id)initWithContext:(NSOpenGLContext *)shared; -(void)setOpenGLContext:(NSOpenGLContext*)context;
-(void)setTexture:(GLuint)texture; -(NSOpenGLContext *)openGLContext;
-(void)invalidateRegion:(const cairo_region_t *)region;
@end
G_GNUC_END_IGNORE_DEPRECATIONS G_GNUC_END_IGNORE_DEPRECATIONS
@end

View File

@ -25,6 +25,7 @@
#import "GdkMacosBaseView.h" #import "GdkMacosBaseView.h"
#import "GdkMacosCairoView.h" #import "GdkMacosCairoView.h"
#import "GdkMacosGLView.h"
#import "GdkMacosWindow.h" #import "GdkMacosWindow.h"
#include "gdkmacosdisplay-private.h" #include "gdkmacosdisplay-private.h"
@ -140,6 +141,10 @@
_gdk_macos_display_break_all_grabs (GDK_MACOS_DISPLAY (display), time); _gdk_macos_display_break_all_grabs (GDK_MACOS_DISPLAY (display), time);
/* Reset gravity */
if (GDK_IS_MACOS_GL_VIEW ([self contentView]))
[[[self contentView] layer] setContentsGravity:kCAGravityBottomLeft];
break; break;
} }
@ -543,6 +548,43 @@
inManualResize = YES; inManualResize = YES;
resizeEdge = edge; resizeEdge = edge;
if (GDK_IS_MACOS_GL_VIEW ([self contentView]))
{
CALayerContentsGravity gravity = kCAGravityBottomLeft;
switch (edge)
{
default:
case GDK_SURFACE_EDGE_NORTH:
gravity = kCAGravityTopLeft;
break;
case GDK_SURFACE_EDGE_NORTH_WEST:
gravity = kCAGravityTopRight;
break;
case GDK_SURFACE_EDGE_SOUTH_WEST:
case GDK_SURFACE_EDGE_WEST:
gravity = kCAGravityBottomRight;
break;
case GDK_SURFACE_EDGE_SOUTH:
case GDK_SURFACE_EDGE_SOUTH_EAST:
gravity = kCAGravityBottomLeft;
break;
case GDK_SURFACE_EDGE_EAST:
gravity = kCAGravityBottomLeft;
break;
case GDK_SURFACE_EDGE_NORTH_EAST:
gravity = kCAGravityTopLeft;
break;
}
[[[self contentView] layer] setContentsGravity:gravity];
}
initialResizeFrame = [self frame]; initialResizeFrame = [self frame];
initialResizeLocation = [self convertPointToScreen:[self mouseLocationOutsideOfEventStream]]; initialResizeLocation = [self convertPointToScreen:[self mouseLocationOutsideOfEventStream]];
} }

View File

@ -649,7 +649,10 @@ gdk_macos_display_make_gl_context_current (GdkDisplay *display,
GdkGLContext *gl_context) GdkGLContext *gl_context)
{ {
g_assert (GDK_IS_MACOS_DISPLAY (display)); g_assert (GDK_IS_MACOS_DISPLAY (display));
g_assert (GDK_IS_MACOS_GL_CONTEXT (gl_context)); g_assert (!gl_context || GDK_IS_MACOS_GL_CONTEXT (gl_context));
if (gl_context == NULL)
return FALSE;
return _gdk_macos_gl_context_make_current (GDK_MACOS_GL_CONTEXT (gl_context)); return _gdk_macos_gl_context_make_current (GDK_MACOS_GL_CONTEXT (gl_context));
} }

View File

@ -41,7 +41,11 @@ struct _GdkMacosGLContext
NSOpenGLContext *gl_context; NSOpenGLContext *gl_context;
G_GNUC_END_IGNORE_DEPRECATIONS G_GNUC_END_IGNORE_DEPRECATIONS
gboolean is_attached; NSWindow *dummy_window;
NSView *dummy_view;
guint is_attached : 1;
guint needs_resize : 1;
}; };
struct _GdkMacosGLContextClass struct _GdkMacosGLContextClass

View File

@ -25,31 +25,343 @@
#include "gdkinternals.h" #include "gdkinternals.h"
#include "gdkintl.h" #include "gdkintl.h"
#include <OpenGL/gl.h>
#import "GdkMacosGLView.h"
G_GNUC_BEGIN_IGNORE_DEPRECATIONS G_GNUC_BEGIN_IGNORE_DEPRECATIONS
G_DEFINE_TYPE (GdkMacosGLContext, gdk_macos_gl_context, GDK_TYPE_GL_CONTEXT) G_DEFINE_TYPE (GdkMacosGLContext, gdk_macos_gl_context, GDK_TYPE_GL_CONTEXT)
static const char *
get_renderer_name (GLint id)
{
static char renderer_name[32];
switch (id & kCGLRendererIDMatchingMask)
{
case kCGLRendererGenericID: return "Generic";
case kCGLRendererGenericFloatID: return "Generic Float";
case kCGLRendererAppleSWID: return "Apple Software Renderer";
case kCGLRendererATIRage128ID: return "ATI Rage 128";
case kCGLRendererATIRadeonID: return "ATI Radeon";
case kCGLRendererATIRageProID: return "ATI Rage Pro";
case kCGLRendererATIRadeon8500ID: return "ATI Radeon 8500";
case kCGLRendererATIRadeon9700ID: return "ATI Radeon 9700";
case kCGLRendererATIRadeonX1000ID: return "ATI Radeon X1000";
case kCGLRendererATIRadeonX2000ID: return "ATI Radeon X2000";
case kCGLRendererATIRadeonX3000ID: return "ATI Radeon X3000";
case kCGLRendererATIRadeonX4000ID: return "ATI Radeon X4000";
case kCGLRendererGeForce2MXID: return "GeForce 2 MX";
case kCGLRendererGeForce3ID: return "GeForce 3";
case kCGLRendererGeForceFXID: return "GeForce FX";
case kCGLRendererGeForce8xxxID: return "GeForce 8xxx";
case kCGLRendererGeForceID: return "GeForce";
case kCGLRendererVTBladeXP2ID: return "VT Blade XP 2";
case kCGLRendererIntel900ID: return "Intel 900";
case kCGLRendererIntelX3100ID: return "Intel X3100";
case kCGLRendererIntelHDID: return "Intel HD";
case kCGLRendererIntelHD4000ID: return "Intel HD 4000";
case kCGLRendererIntelHD5000ID: return "Intel HD 5000";
case kCGLRendererMesa3DFXID: return "Mesa 3DFX";
default:
snprintf (renderer_name, sizeof renderer_name, "0x%08x", id & kCGLRendererIDMatchingMask);
renderer_name[sizeof renderer_name-1] = 0;
return renderer_name;
}
}
static NSOpenGLContext *
get_ns_open_gl_context (GdkMacosGLContext *self,
GError **error)
{
g_assert (GDK_IS_MACOS_GL_CONTEXT (self));
if (self->gl_context == nil)
{
g_set_error_literal (error,
GDK_GL_ERROR,
GDK_GL_ERROR_NOT_AVAILABLE,
"Cannot access NSOpenGLContext for surface");
return NULL;
}
return self->gl_context;
}
static NSOpenGLPixelFormat *
create_pixel_format (int major,
int minor,
GError **error)
{
NSOpenGLPixelFormatAttribute attrs[] = {
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersionLegacy,
NSOpenGLPFAAccelerated,
NSOpenGLPFADoubleBuffer,
(NSOpenGLPixelFormatAttribute)nil
};
if (major == 3 && minor == 2)
attrs[1] = NSOpenGLProfileVersion3_2Core;
else if (major == 4 && minor == 1)
attrs[1] = NSOpenGLProfileVersion4_1Core;
NSOpenGLPixelFormat *format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
if (format == NULL)
g_set_error (error,
GDK_GL_ERROR,
GDK_GL_ERROR_NOT_AVAILABLE,
"Failed to create pixel format");
return g_steal_pointer (&format);
}
static NSView *
ensure_gl_view (GdkMacosGLContext *self)
{
GdkMacosSurface *surface;
NSWindow *nswindow;
NSView *nsview;
g_assert (GDK_IS_MACOS_GL_CONTEXT (self));
surface = GDK_MACOS_SURFACE (gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (self)));
nsview = _gdk_macos_surface_get_view (surface);
nswindow = _gdk_macos_surface_get_native (surface);
if (!GDK_IS_MACOS_GL_VIEW (nsview))
{
NSRect frame;
frame = [[nswindow contentView] bounds];
nsview = [[GdkMacosGLView alloc] initWithFrame:frame];
[nsview setWantsBestResolutionOpenGLSurface:YES];
[nsview setPostsFrameChangedNotifications: YES];
[nsview setNeedsDisplay:YES];
[nswindow setContentView:nsview];
[nsview release];
}
return [nswindow contentView];
}
static gboolean
gdk_macos_gl_context_real_realize (GdkGLContext *context,
GError **error)
{
GdkMacosGLContext *self = (GdkMacosGLContext *)context;
GdkSurface *surface;
NSOpenGLContext *shared_gl_context = nil;
NSOpenGLContext *gl_context;
NSOpenGLPixelFormat *pixelFormat;
GdkGLContext *shared;
GdkGLContext *shared_data;
GdkGLContext *existing;
GLint sync_to_framerate = 1;
GLint opaque = 0;
GLint validate = 0;
int major, minor;
g_assert (GDK_IS_MACOS_GL_CONTEXT (self));
if (self->gl_context != nil)
return TRUE;
existing = gdk_gl_context_get_current ();
gdk_gl_context_get_required_version (context, &major, &minor);
surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (context));
shared = gdk_gl_context_get_shared_context (context);
shared_data = gdk_surface_get_shared_data_gl_context (surface);
if (shared != NULL)
{
if (!(shared_gl_context = get_ns_open_gl_context (GDK_MACOS_GL_CONTEXT (shared), error)))
return FALSE;
}
else if (shared_data != NULL)
{
if (!(shared_gl_context = get_ns_open_gl_context (GDK_MACOS_GL_CONTEXT (shared_data), error)))
return FALSE;
}
GDK_DISPLAY_NOTE (gdk_draw_context_get_display (GDK_DRAW_CONTEXT (context)),
OPENGL,
g_message ("Creating NSOpenGLContext (version %d.%d)",
major, minor));
if (!(pixelFormat = create_pixel_format (major, minor, error)))
return FALSE;
gl_context = [[NSOpenGLContext alloc] initWithFormat:pixelFormat
shareContext:shared_gl_context];
[pixelFormat release];
if (gl_context == nil)
{
g_set_error_literal (error,
GDK_GL_ERROR,
GDK_GL_ERROR_NOT_AVAILABLE,
"Failed to create NSOpenGLContext");
return FALSE;
}
[gl_context setValues:&sync_to_framerate forParameter:NSOpenGLCPSwapInterval];
[gl_context setValues:&opaque forParameter:NSOpenGLCPSurfaceOpacity];
[gl_context setValues:&validate forParameter:NSOpenGLContextParameterStateValidation];
if (self->is_attached || shared == NULL)
{
NSRect frame = NSMakeRect (0, 0, 1, 1);
self->dummy_window = [[NSWindow alloc] initWithContentRect:frame
styleMask:0
backing:NSBackingStoreBuffered
defer:NO
screen:nil];
self->dummy_view = [[NSView alloc] initWithFrame:frame];
[self->dummy_window setContentView:self->dummy_view];
[gl_context setView:self->dummy_view];
}
[gl_context makeCurrentContext];
GLint renderer_id = 0;
[gl_context getValues:&renderer_id forParameter:NSOpenGLContextParameterCurrentRendererID];
GDK_DISPLAY_NOTE (gdk_draw_context_get_display (GDK_DRAW_CONTEXT (context)),
OPENGL,
g_message ("Created NSOpenGLContext[%p] using %s",
gl_context,
get_renderer_name (renderer_id)));
[NSOpenGLContext clearCurrentContext];
self->gl_context = g_steal_pointer (&gl_context);
if (existing != NULL)
[GDK_MACOS_GL_CONTEXT (existing)->gl_context makeCurrentContext];
return TRUE;
}
static void
gdk_macos_gl_context_begin_frame (GdkDrawContext *context,
cairo_region_t *painted)
{
GdkMacosGLContext *self = (GdkMacosGLContext *)context;
g_assert (GDK_IS_MACOS_GL_CONTEXT (self));
/* If begin frame is called, that means we are trying to draw to
* the NSWindow using our view. That might be a GdkMacosCairoView
* but we need it to be a GL view.
*/
if (!self->is_attached &&
gdk_gl_context_get_shared_context (GDK_GL_CONTEXT (context)))
ensure_gl_view (self);
if (self->needs_resize)
{
self->needs_resize = FALSE;
if (self->dummy_view != NULL)
{
GdkSurface *surface = gdk_draw_context_get_surface (context);
GLint vals[2] = { surface->width, surface->height };
[self->gl_context setValues:vals forParameter:NSOpenGLContextParameterSurfaceBackingSize];
}
[self->gl_context update];
}
GDK_DRAW_CONTEXT_CLASS (gdk_macos_gl_context_parent_class)->begin_frame (context, painted);
if (!self->is_attached)
{
GdkMacosSurface *surface = GDK_MACOS_SURFACE (gdk_draw_context_get_surface (context));
NSView *nsview = _gdk_macos_surface_get_view (surface);
g_assert (self->gl_context != NULL);
g_assert (GDK_IS_MACOS_GL_VIEW (nsview));
[(GdkMacosGLView *)nsview setOpenGLContext:self->gl_context];
}
}
static void static void
gdk_macos_gl_context_end_frame (GdkDrawContext *context, gdk_macos_gl_context_end_frame (GdkDrawContext *context,
cairo_region_t *painted) cairo_region_t *painted)
{ {
GdkMacosGLContext *self = GDK_MACOS_GL_CONTEXT (context); GdkMacosGLContext *self = GDK_MACOS_GL_CONTEXT (context);
GdkMacosSurface *surface;
NSView *nsview;
cairo_rectangle_int_t extents;
g_assert (GDK_IS_MACOS_GL_CONTEXT (self));
g_assert (self->gl_context != nil);
surface = GDK_MACOS_SURFACE (gdk_draw_context_get_surface (context));
nsview = self->dummy_view ?
self->dummy_view :
_gdk_macos_surface_get_view (surface);
GDK_DRAW_CONTEXT_CLASS (gdk_macos_gl_context_parent_class)->end_frame (context, painted);
G_STATIC_ASSERT (sizeof (GLint) == sizeof (int));
cairo_region_get_extents (painted, &extents);
[self->gl_context
setValues:(GLint *)&extents
forParameter:NSOpenGLCPSwapRectangle];
[self->gl_context flushBuffer];
}
static void
gdk_macos_gl_context_surface_resized (GdkDrawContext *draw_context)
{
GdkMacosGLContext *self = (GdkMacosGLContext *)draw_context;
g_assert (GDK_IS_MACOS_GL_CONTEXT (self)); g_assert (GDK_IS_MACOS_GL_CONTEXT (self));
[self->gl_context flushBuffer]; self->needs_resize = TRUE;
} }
static void static void
gdk_macos_gl_context_dispose (GObject *gobject) gdk_macos_gl_context_dispose (GObject *gobject)
{ {
GdkMacosGLContext *context_macos = GDK_MACOS_GL_CONTEXT (gobject); GdkMacosGLContext *self = GDK_MACOS_GL_CONTEXT (gobject);
if (context_macos->gl_context != NULL) if (self->dummy_view != nil)
{ {
[context_macos->gl_context clearDrawable]; NSView *nsview = g_steal_pointer (&self->dummy_view);
[context_macos->gl_context release];
context_macos->gl_context = NULL; if (GDK_IS_MACOS_GL_VIEW (nsview))
[(GdkMacosGLView *)nsview setOpenGLContext:nil];
[nsview release];
}
if (self->dummy_window != nil)
{
NSWindow *nswindow = g_steal_pointer (&self->dummy_window);
[nswindow release];
}
if (self->gl_context != nil)
{
NSOpenGLContext *gl_context = g_steal_pointer (&self->gl_context);
if (gl_context == [NSOpenGLContext currentContext])
[NSOpenGLContext clearCurrentContext];
[gl_context clearDrawable];
[gl_context release];
} }
G_OBJECT_CLASS (gdk_macos_gl_context_parent_class)->dispose (gobject); G_OBJECT_CLASS (gdk_macos_gl_context_parent_class)->dispose (gobject);
@ -60,10 +372,15 @@ gdk_macos_gl_context_class_init (GdkMacosGLContextClass *klass)
{ {
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
GdkDrawContextClass *draw_context_class = GDK_DRAW_CONTEXT_CLASS (klass); GdkDrawContextClass *draw_context_class = GDK_DRAW_CONTEXT_CLASS (klass);
GdkGLContextClass *gl_class = GDK_GL_CONTEXT_CLASS (klass);
object_class->dispose = gdk_macos_gl_context_dispose; object_class->dispose = gdk_macos_gl_context_dispose;
draw_context_class->begin_frame = gdk_macos_gl_context_begin_frame;
draw_context_class->end_frame = gdk_macos_gl_context_end_frame; draw_context_class->end_frame = gdk_macos_gl_context_end_frame;
draw_context_class->surface_resized = gdk_macos_gl_context_surface_resized;
gl_class->realize = gdk_macos_gl_context_real_realize;
} }
static void static void
@ -77,65 +394,17 @@ _gdk_macos_gl_context_new (GdkMacosSurface *surface,
GdkGLContext *share, GdkGLContext *share,
GError **error) GError **error)
{ {
static const NSOpenGLPixelFormatAttribute attrs[] = { GdkMacosGLContext *context;
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAColorSize, 24,
NSOpenGLPFAAlphaSize, 8,
0
};
NSOpenGLPixelFormat *format;
GdkMacosGLContext *context = NULL;
NSOpenGLContext *ctx;
GdkDisplay *display;
NSView *nsview;
GLint sync_to_framerate = 1;
g_return_val_if_fail (GDK_IS_MACOS_SURFACE (surface), NULL); g_return_val_if_fail (GDK_IS_MACOS_SURFACE (surface), NULL);
g_return_val_if_fail (!share || GDK_IS_MACOS_GL_CONTEXT (share), NULL); g_return_val_if_fail (!share || GDK_IS_MACOS_GL_CONTEXT (share), NULL);
display = gdk_surface_get_display (GDK_SURFACE (surface));
if (!(format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs]))
{
g_set_error_literal (error,
GDK_GL_ERROR,
GDK_GL_ERROR_NOT_AVAILABLE,
_("Unable to create a GL pixel format"));
goto failure;
}
ctx = [[NSOpenGLContext alloc] initWithFormat:format
shareContext:share ? GDK_MACOS_GL_CONTEXT (share)->gl_context : nil];
if (ctx == NULL)
{
g_set_error_literal (error,
GDK_GL_ERROR,
GDK_GL_ERROR_NOT_AVAILABLE,
_("Unable to create a GL context"));
goto failure;
}
nsview = _gdk_macos_surface_get_view (surface);
[nsview setWantsBestResolutionOpenGLSurface:YES];
[ctx setValues:&sync_to_framerate forParameter:NSOpenGLCPSwapInterval];
[ctx setView:nsview];
GDK_NOTE (OPENGL,
g_print ("Created NSOpenGLContext[%p]\n", ctx));
context = g_object_new (GDK_TYPE_MACOS_GL_CONTEXT, context = g_object_new (GDK_TYPE_MACOS_GL_CONTEXT,
"surface", surface, "surface", surface,
"shared-context", share, "shared-context", share,
NULL); NULL);
context->gl_context = ctx; context->is_attached = !!attached;
context->is_attached = attached;
failure:
if (format != NULL)
[format release];
return GDK_GL_CONTEXT (context); return GDK_GL_CONTEXT (context);
} }
@ -145,9 +414,13 @@ _gdk_macos_gl_context_make_current (GdkMacosGLContext *self)
{ {
g_return_val_if_fail (GDK_IS_MACOS_GL_CONTEXT (self), FALSE); g_return_val_if_fail (GDK_IS_MACOS_GL_CONTEXT (self), FALSE);
if (self->gl_context != nil)
{
[self->gl_context makeCurrentContext]; [self->gl_context makeCurrentContext];
return TRUE; return TRUE;
} }
return FALSE;
}
G_GNUC_END_IGNORE_DEPRECATIONS G_GNUC_END_IGNORE_DEPRECATIONS

View File

@ -23,7 +23,7 @@ gdk_macos_sources = files([
'GdkMacosBaseView.c', 'GdkMacosBaseView.c',
'GdkMacosCairoView.c', 'GdkMacosCairoView.c',
'GdkMacosCairoSubview.c', 'GdkMacosCairoSubview.c',
'GdkMacosGLLayer.c', 'GdkMacosGLView.c',
'GdkMacosWindow.c', 'GdkMacosWindow.c',
]) ])

View File

@ -5,10 +5,9 @@ uniform float u_alpha;// = 1.0;
uniform vec4 u_viewport; uniform vec4 u_viewport;
uniform vec4[3] u_clip_rect; uniform vec4[3] u_clip_rect;
#if GSK_GLES #if defined(GSK_LEGACY)
#elif GSK_LEGACY
_OUT_ vec4 outputColor; _OUT_ vec4 outputColor;
#else #elif !defined(GSK_GLES)
_OUT_ vec4 outputColor; _OUT_ vec4 outputColor;
#endif #endif