blob: 9e25f2e7b41bdb2cd4231703052568b0f49ad796 [file] [log] [blame]
bsalomon@google.comf75b84e2011-09-29 14:58:28 +00001/*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
robertphillips@google.com5b5bba32012-09-24 14:20:00 +00008#import "SkNSView.h"
yangsu@google.com12d177d2011-08-01 17:07:12 +00009#include "SkCanvas.h"
reed0397e9f2014-09-18 11:29:01 -070010#include "SkSurface.h"
yangsu@google.com12d177d2011-08-01 17:07:12 +000011#include "SkCGUtils.h"
12#include "SkEvent.h"
bungeman99fe8222015-08-20 07:57:51 -070013static_assert(SK_SUPPORT_GPU, "not_implemented_for_non_gpu_build");
commit-bot@chromium.org6a180792014-01-15 21:39:18 +000014#include <OpenGL/gl.h>
yangsu@google.com12d177d2011-08-01 17:07:12 +000015
Ben Wagner55963bc2017-07-24 15:00:35 +000016//#define FORCE_REDRAW
bungeman@google.comb20a1b52013-06-28 16:44:55 +000017// Can be dropped when we no longer support 10.6.
Mike Klein04ef48c2017-03-15 09:43:04 -070018#if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
19 #define RETINA_API_AVAILABLE 1
20#else
21 #define RETINA_API_AVAILABLE 0
22#endif
23
yangsu@google.com12d177d2011-08-01 17:07:12 +000024@implementation SkNSView
bsalomon@google.com2e401732012-08-03 19:25:10 +000025@synthesize fWind, fTitle, fOptionsDelegate, fGLContext;
yangsu@google.com12d177d2011-08-01 17:07:12 +000026
Jim Van Verth57a98fc2016-10-28 13:35:50 -040027BOOL fRedrawRequestPending;
28
yangsu@google.com12d177d2011-08-01 17:07:12 +000029- (id)initWithCoder:(NSCoder*)coder {
30 if ((self = [super initWithCoder:coder])) {
yangsu@google.coma8540412011-08-30 14:40:49 +000031 self = [self initWithDefaults];
32 [self setUpWindow];
yangsu@google.com12d177d2011-08-01 17:07:12 +000033 }
34 return self;
35}
36
37- (id)initWithFrame:(NSRect)frameRect {
caryclark@google.com679ab312012-06-06 12:04:00 +000038 if ((self = [super initWithFrame:frameRect])) {
yangsu@google.coma8540412011-08-30 14:40:49 +000039 self = [self initWithDefaults];
40 [self setUpWindow];
yangsu@google.com12d177d2011-08-01 17:07:12 +000041 }
42 return self;
43}
44
yangsu@google.coma8540412011-08-30 14:40:49 +000045- (id)initWithDefaults {
bungeman@google.comb20a1b52013-06-28 16:44:55 +000046#if RETINA_API_AVAILABLE
47 [self setWantsBestResolutionOpenGLSurface:YES];
48#endif
yangsu@google.com12d177d2011-08-01 17:07:12 +000049 fRedrawRequestPending = false;
yangsu@google.coma8540412011-08-30 14:40:49 +000050 fWind = NULL;
yangsu@google.com12d177d2011-08-01 17:07:12 +000051 return self;
52}
53
Yuqian Li6e3d9952017-09-27 13:25:36 -040054- (void)setNSViewSize:(NSSize)size {
55 NSWindow* w = [self window];
Chris Dalton1fbb07a2017-10-06 11:33:36 -060056 NSRect f = w.frame;
Yuqian Li6e3d9952017-09-27 13:25:36 -040057 f.size = size;
58 [w setFrame:f display:YES];
59}
60
yangsu@google.coma8540412011-08-30 14:40:49 +000061- (void)setUpWindow {
bungeman@google.comb20a1b52013-06-28 16:44:55 +000062 [[NSNotificationCenter defaultCenter] addObserver:self
63 selector:@selector(backingPropertiesChanged:)
64 name:@"NSWindowDidChangeBackingPropertiesNotification"
65 object:[self window]];
bsalomon49f085d2014-09-05 13:34:00 -070066 if (fWind) {
yangsu@google.coma8540412011-08-30 14:40:49 +000067 fWind->setVisibleP(true);
bungeman@google.comb20a1b52013-06-28 16:44:55 +000068 NSSize size = self.frame.size;
69#if RETINA_API_AVAILABLE
70 size = [self convertSizeToBacking:self.frame.size];
71#endif
kkinnunen973d92c2016-01-18 01:18:34 -080072 fWind->resize((int) size.width, (int) size.height);
bsalomon84195912015-06-23 14:03:47 -070073 [[self window] setAcceptsMouseMovedEvents:YES];
yangsu@google.coma8540412011-08-30 14:40:49 +000074 }
75}
76
yangsu@google.com12d177d2011-08-01 17:07:12 +000077-(BOOL) isFlipped {
78 return YES;
79}
80
81- (BOOL)acceptsFirstResponder {
82 return YES;
83}
84
bungeman@google.comb20a1b52013-06-28 16:44:55 +000085- (float)scaleFactor {
86 NSWindow *window = [self window];
87#if RETINA_API_AVAILABLE
88 if (window) {
89 return [window backingScaleFactor];
90 }
91 return [[NSScreen mainScreen] backingScaleFactor];
92#else
93 if (window) {
94 return [window userSpaceScaleFactor];
95 }
96 return [[NSScreen mainScreen] userSpaceScaleFactor];
97#endif
98}
99
100- (void)backingPropertiesChanged:(NSNotification *)notification {
bungeman@google.com44fb1fa2013-06-28 17:21:35 +0000101 CGFloat oldBackingScaleFactor = (CGFloat)[
bungeman@google.comb20a1b52013-06-28 16:44:55 +0000102 [notification.userInfo objectForKey:@"NSBackingPropertyOldScaleFactorKey"] doubleValue
103 ];
104 CGFloat newBackingScaleFactor = [self scaleFactor];
105 if (oldBackingScaleFactor == newBackingScaleFactor) {
106 return;
107 }
Yuqian Li6e3d9952017-09-27 13:25:36 -0400108
bungeman@google.comb20a1b52013-06-28 16:44:55 +0000109 // TODO: need a better way to force a refresh (that works).
110 // [fGLContext update] does not appear to update if the point size has not changed,
111 // even if the backing size has changed.
112 [self setFrameSize:NSMakeSize(self.frame.size.width + 1, self.frame.size.height + 1)];
113}
114
suyang1bb3f4a82011-10-10 16:38:58 +0000115- (void)resizeSkView:(NSSize)newSize {
bungeman@google.comb20a1b52013-06-28 16:44:55 +0000116#if RETINA_API_AVAILABLE
117 newSize = [self convertSizeToBacking:newSize];
118#endif
bsalomon49f085d2014-09-05 13:34:00 -0700119 if (fWind && (fWind->width() != newSize.width || fWind->height() != newSize.height)) {
caryclark@google.com679ab312012-06-06 12:04:00 +0000120 fWind->resize((int) newSize.width, (int) newSize.height);
bsalomon49f085d2014-09-05 13:34:00 -0700121 if (fGLContext) {
caryclark@google.com594dd3c2012-09-24 19:33:57 +0000122 glClear(GL_STENCIL_BUFFER_BIT);
bungeman@google.comb20a1b52013-06-28 16:44:55 +0000123 [fGLContext update];
caryclark@google.com594dd3c2012-09-24 19:33:57 +0000124 }
yangsu@google.com12d177d2011-08-01 17:07:12 +0000125 }
yangsu@google.com12d177d2011-08-01 17:07:12 +0000126}
127
suyang1bb3f4a82011-10-10 16:38:58 +0000128- (void) setFrameSize:(NSSize)newSize {
129 [super setFrameSize:newSize];
130 [self resizeSkView:newSize];
131}
132
yangsu@google.com12d177d2011-08-01 17:07:12 +0000133- (void)dealloc {
reedd3ce6b42014-10-07 06:42:09 -0700134 [self freeNativeWind];
yangsu@google.com12d177d2011-08-01 17:07:12 +0000135 self.fGLContext = nil;
136 self.fTitle = nil;
yangsu@google.com12d177d2011-08-01 17:07:12 +0000137 [super dealloc];
138}
139
reedd3ce6b42014-10-07 06:42:09 -0700140- (void)freeNativeWind {
141 delete fWind;
142 fWind = nil;
143}
144
suyang1bb3f4a82011-10-10 16:38:58 +0000145////////////////////////////////////////////////////////////////////////////////
yangsu@google.com12d177d2011-08-01 17:07:12 +0000146
yangsu@google.comf3493f02011-08-08 15:12:05 +0000147- (void)drawSkia {
yangsu@google.com12d177d2011-08-01 17:07:12 +0000148 fRedrawRequestPending = false;
bsalomon49f085d2014-09-05 13:34:00 -0700149 if (fWind) {
Ben Wagner55963bc2017-07-24 15:00:35 +0000150 sk_sp<SkSurface> surface(fWind->makeSurface());
151 fWind->draw(surface->getCanvas());
152#ifdef FORCE_REDRAW
153 fWind->inval(NULL);
154#endif
yangsu@google.coma8540412011-08-30 14:40:49 +0000155 }
yangsu@google.com12d177d2011-08-01 17:07:12 +0000156}
157
yangsu@google.comf3493f02011-08-08 15:12:05 +0000158- (void)setSkTitle:(const char *)title {
159 self.fTitle = [NSString stringWithUTF8String:title];
160 [[self window] setTitle:self.fTitle];
161}
162
163- (BOOL)onHandleEvent:(const SkEvent&)evt {
164 return false;
165}
166
167#include "SkOSMenu.h"
168- (void)onAddMenu:(const SkOSMenu*)menu {
169 [self.fOptionsDelegate view:self didAddMenu:menu];
170}
171
172- (void)onUpdateMenu:(const SkOSMenu*)menu {
173 [self.fOptionsDelegate view:self didUpdateMenu:menu];
174}
175
176- (void)postInvalWithRect:(const SkIRect*)r {
177 if (!fRedrawRequestPending) {
178 fRedrawRequestPending = true;
yangsu@google.coma8540412011-08-30 14:40:49 +0000179 [self setNeedsDisplay:YES];
yangsu@google.comf3493f02011-08-08 15:12:05 +0000180 [self performSelector:@selector(drawSkia) withObject:nil afterDelay:0];
181 }
yangsu@google.com12d177d2011-08-01 17:07:12 +0000182}
183///////////////////////////////////////////////////////////////////////////////
184
185#include "SkKey.h"
186enum {
robertphillipsecf3dbe2016-07-28 15:17:34 -0700187 SK_MacReturnKey = 36,
188 SK_MacDeleteKey = 51,
189 SK_MacEndKey = 119,
190 SK_MacLeftKey = 123,
191 SK_MacRightKey = 124,
192 SK_MacDownKey = 125,
193 SK_MacUpKey = 126,
yangsu@google.com12d177d2011-08-01 17:07:12 +0000194 SK_Mac0Key = 0x52,
195 SK_Mac1Key = 0x53,
196 SK_Mac2Key = 0x54,
197 SK_Mac3Key = 0x55,
198 SK_Mac4Key = 0x56,
199 SK_Mac5Key = 0x57,
200 SK_Mac6Key = 0x58,
201 SK_Mac7Key = 0x59,
202 SK_Mac8Key = 0x5b,
203 SK_Mac9Key = 0x5c
204};
205
206static SkKey raw2key(UInt32 raw)
207{
robertphillipsecf3dbe2016-07-28 15:17:34 -0700208 static const struct {
209 UInt32 fRaw;
210 SkKey fKey;
211 } gKeys[] = {
212 { SK_MacUpKey, kUp_SkKey },
213 { SK_MacDownKey, kDown_SkKey },
214 { SK_MacLeftKey, kLeft_SkKey },
215 { SK_MacRightKey, kRight_SkKey },
216 { SK_MacReturnKey, kOK_SkKey },
217 { SK_MacDeleteKey, kBack_SkKey },
218 { SK_MacEndKey, kEnd_SkKey },
yangsu@google.com12d177d2011-08-01 17:07:12 +0000219 { SK_Mac0Key, k0_SkKey },
220 { SK_Mac1Key, k1_SkKey },
221 { SK_Mac2Key, k2_SkKey },
222 { SK_Mac3Key, k3_SkKey },
yangsu@google.comf3493f02011-08-08 15:12:05 +0000223 { SK_Mac4Key, k4_SkKey },
yangsu@google.com12d177d2011-08-01 17:07:12 +0000224 { SK_Mac5Key, k5_SkKey },
225 { SK_Mac6Key, k6_SkKey },
226 { SK_Mac7Key, k7_SkKey },
227 { SK_Mac8Key, k8_SkKey },
228 { SK_Mac9Key, k9_SkKey }
robertphillipsecf3dbe2016-07-28 15:17:34 -0700229 };
Yuqian Li6e3d9952017-09-27 13:25:36 -0400230
robertphillipsecf3dbe2016-07-28 15:17:34 -0700231 for (unsigned i = 0; i < SK_ARRAY_COUNT(gKeys); i++)
232 if (gKeys[i].fRaw == raw)
233 return gKeys[i].fKey;
234 return kNONE_SkKey;
yangsu@google.com12d177d2011-08-01 17:07:12 +0000235}
236
237- (void)keyDown:(NSEvent *)event {
yangsu@google.com849ad5a2011-08-30 15:27:57 +0000238 if (NULL == fWind)
yangsu@google.coma8540412011-08-30 14:40:49 +0000239 return;
Yuqian Li6e3d9952017-09-27 13:25:36 -0400240
yangsu@google.com12d177d2011-08-01 17:07:12 +0000241 SkKey key = raw2key([event keyCode]);
242 if (kNONE_SkKey != key)
243 fWind->handleKey(key);
244 else{
245 unichar c = [[event characters] characterAtIndex:0];
246 fWind->handleChar((SkUnichar)c);
247 }
248}
249
250- (void)keyUp:(NSEvent *)event {
yangsu@google.com849ad5a2011-08-30 15:27:57 +0000251 if (NULL == fWind)
yangsu@google.coma8540412011-08-30 14:40:49 +0000252 return;
Yuqian Li6e3d9952017-09-27 13:25:36 -0400253
yangsu@google.com12d177d2011-08-01 17:07:12 +0000254 SkKey key = raw2key([event keyCode]);
255 if (kNONE_SkKey != key)
256 fWind->handleKeyUp(key);
caryclark@google.com679ab312012-06-06 12:04:00 +0000257 // else
258 // unichar c = [[event characters] characterAtIndex:0];
yangsu@google.com12d177d2011-08-01 17:07:12 +0000259}
260
reed@google.com4d5c26d2013-01-08 16:17:50 +0000261static const struct {
262 unsigned fNSModifierMask;
263 unsigned fSkModifierMask;
264} gModifierMasks[] = {
265 { NSAlphaShiftKeyMask, kShift_SkModifierKey },
266 { NSShiftKeyMask, kShift_SkModifierKey },
267 { NSControlKeyMask, kControl_SkModifierKey },
268 { NSAlternateKeyMask, kOption_SkModifierKey },
269 { NSCommandKeyMask, kCommand_SkModifierKey },
270};
271
272static unsigned convertNSModifiersToSk(NSUInteger nsModi) {
273 unsigned skModi = 0;
274 for (size_t i = 0; i < SK_ARRAY_COUNT(gModifierMasks); ++i) {
275 if (nsModi & gModifierMasks[i].fNSModifierMask) {
276 skModi |= gModifierMasks[i].fSkModifierMask;
277 }
278 }
279 return skModi;
280}
281
yangsu@google.com12d177d2011-08-01 17:07:12 +0000282- (void)mouseDown:(NSEvent *)event {
283 NSPoint p = [event locationInWindow];
reed@google.com4d5c26d2013-01-08 16:17:50 +0000284 unsigned modi = convertNSModifiersToSk([event modifierFlags]);
285
bsalomon49f085d2014-09-05 13:34:00 -0700286 if ([self mouse:p inRect:[self bounds]] && fWind) {
yangsu@google.com12d177d2011-08-01 17:07:12 +0000287 NSPoint loc = [self convertPoint:p fromView:nil];
bungeman@google.comb20a1b52013-06-28 16:44:55 +0000288#if RETINA_API_AVAILABLE
289 loc = [self convertPointToBacking:loc]; //y-up
290 loc.y = -loc.y;
291#endif
reed@google.com4d5c26d2013-01-08 16:17:50 +0000292 fWind->handleClick((int) loc.x, (int) loc.y,
293 SkView::Click::kDown_State, self, modi);
yangsu@google.com12d177d2011-08-01 17:07:12 +0000294 }
295}
296
297- (void)mouseDragged:(NSEvent *)event {
298 NSPoint p = [event locationInWindow];
reed@google.com4d5c26d2013-01-08 16:17:50 +0000299 unsigned modi = convertNSModifiersToSk([event modifierFlags]);
300
bsalomon49f085d2014-09-05 13:34:00 -0700301 if ([self mouse:p inRect:[self bounds]] && fWind) {
yangsu@google.com12d177d2011-08-01 17:07:12 +0000302 NSPoint loc = [self convertPoint:p fromView:nil];
bungeman@google.comb20a1b52013-06-28 16:44:55 +0000303#if RETINA_API_AVAILABLE
304 loc = [self convertPointToBacking:loc]; //y-up
305 loc.y = -loc.y;
306#endif
reed@google.com4d5c26d2013-01-08 16:17:50 +0000307 fWind->handleClick((int) loc.x, (int) loc.y,
308 SkView::Click::kMoved_State, self, modi);
yangsu@google.com12d177d2011-08-01 17:07:12 +0000309 }
310}
311
suyang1bb3f4a82011-10-10 16:38:58 +0000312- (void)mouseMoved:(NSEvent *)event {
313 NSPoint p = [event locationInWindow];
reed@google.com4d5c26d2013-01-08 16:17:50 +0000314 unsigned modi = convertNSModifiersToSk([event modifierFlags]);
Yuqian Li6e3d9952017-09-27 13:25:36 -0400315
bsalomon49f085d2014-09-05 13:34:00 -0700316 if ([self mouse:p inRect:[self bounds]] && fWind) {
suyang1bb3f4a82011-10-10 16:38:58 +0000317 NSPoint loc = [self convertPoint:p fromView:nil];
bungeman@google.comb20a1b52013-06-28 16:44:55 +0000318#if RETINA_API_AVAILABLE
319 loc = [self convertPointToBacking:loc]; //y-up
320 loc.y = -loc.y;
321#endif
reed@google.com4d5c26d2013-01-08 16:17:50 +0000322 fWind->handleClick((int) loc.x, (int) loc.y,
323 SkView::Click::kMoved_State, self, modi);
suyang1bb3f4a82011-10-10 16:38:58 +0000324 }
325}
326
yangsu@google.com12d177d2011-08-01 17:07:12 +0000327- (void)mouseUp:(NSEvent *)event {
328 NSPoint p = [event locationInWindow];
reed@google.com4d5c26d2013-01-08 16:17:50 +0000329 unsigned modi = convertNSModifiersToSk([event modifierFlags]);
Yuqian Li6e3d9952017-09-27 13:25:36 -0400330
bsalomon49f085d2014-09-05 13:34:00 -0700331 if ([self mouse:p inRect:[self bounds]] && fWind) {
yangsu@google.com12d177d2011-08-01 17:07:12 +0000332 NSPoint loc = [self convertPoint:p fromView:nil];
bungeman@google.comb20a1b52013-06-28 16:44:55 +0000333#if RETINA_API_AVAILABLE
334 loc = [self convertPointToBacking:loc]; //y-up
335 loc.y = -loc.y;
336#endif
reed@google.com4d5c26d2013-01-08 16:17:50 +0000337 fWind->handleClick((int) loc.x, (int) loc.y,
338 SkView::Click::kUp_State, self, modi);
yangsu@google.com12d177d2011-08-01 17:07:12 +0000339 }
340}
341
yangsu@google.com12d177d2011-08-01 17:07:12 +0000342///////////////////////////////////////////////////////////////////////////////
343#include <OpenGL/OpenGL.h>
bsalomon@google.com2e401732012-08-03 19:25:10 +0000344
bsalomon241b56d2015-06-18 11:49:42 -0700345static CGLContextObj createGLContext(int msaaSampleCount) {
yangsu@google.com12d177d2011-08-01 17:07:12 +0000346 GLint major, minor;
yangsu@google.com12d177d2011-08-01 17:07:12 +0000347 CGLGetVersion(&major, &minor);
Yuqian Li6e3d9952017-09-27 13:25:36 -0400348
bsalomon@google.com11959252012-04-06 20:13:38 +0000349 static const CGLPixelFormatAttribute attributes[] = {
350 kCGLPFAStencilSize, (CGLPixelFormatAttribute) 8,
yangsu@google.com12d177d2011-08-01 17:07:12 +0000351 kCGLPFAAccelerated,
352 kCGLPFADoubleBuffer,
ethannicholas28ef4452016-03-25 09:26:03 -0700353 kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute) kCGLOGLPVersion_3_2_Core,
yangsu@google.com12d177d2011-08-01 17:07:12 +0000354 (CGLPixelFormatAttribute)0
355 };
Yuqian Li6e3d9952017-09-27 13:25:36 -0400356
yangsu@google.com12d177d2011-08-01 17:07:12 +0000357 CGLPixelFormatObj format;
bsalomon@google.com11959252012-04-06 20:13:38 +0000358 GLint npix = 0;
359 if (msaaSampleCount > 0) {
dvonbeck115e9252016-06-15 09:13:50 -0700360 static const int kAttributeCount = SK_ARRAY_COUNT(attributes);
bsalomon@google.com11959252012-04-06 20:13:38 +0000361 CGLPixelFormatAttribute msaaAttributes[kAttributeCount + 5];
362 memcpy(msaaAttributes, attributes, sizeof(attributes));
363 SkASSERT(0 == msaaAttributes[kAttributeCount - 1]);
364 msaaAttributes[kAttributeCount - 1] = kCGLPFASampleBuffers;
365 msaaAttributes[kAttributeCount + 0] = (CGLPixelFormatAttribute)1;
366 msaaAttributes[kAttributeCount + 1] = kCGLPFAMultisample;
367 msaaAttributes[kAttributeCount + 2] = kCGLPFASamples;
368 msaaAttributes[kAttributeCount + 3] =
369 (CGLPixelFormatAttribute)msaaSampleCount;
370 msaaAttributes[kAttributeCount + 4] = (CGLPixelFormatAttribute)0;
371 CGLChoosePixelFormat(msaaAttributes, &format, &npix);
372 }
373 if (!npix) {
374 CGLChoosePixelFormat(attributes, &format, &npix);
375 }
yangsu@google.comef7bdfa2011-08-12 14:27:47 +0000376 CGLContextObj ctx;
yangsu@google.com12d177d2011-08-01 17:07:12 +0000377 CGLCreateContext(format, NULL, &ctx);
yangsu@google.com12d177d2011-08-01 17:07:12 +0000378 CGLDestroyPixelFormat(format);
Yuqian Li6e3d9952017-09-27 13:25:36 -0400379
yangsu@google.com12d177d2011-08-01 17:07:12 +0000380 static const GLint interval = 1;
381 CGLSetParameter(ctx, kCGLCPSwapInterval, &interval);
382 CGLSetCurrentContext(ctx);
383 return ctx;
384}
385
386- (void)viewDidMoveToWindow {
387 [super viewDidMoveToWindow];
Yuqian Li6e3d9952017-09-27 13:25:36 -0400388
yangsu@google.com12d177d2011-08-01 17:07:12 +0000389 //Attaching view to fGLContext requires that the view to be part of a window,
Yuqian Li6e3d9952017-09-27 13:25:36 -0400390 //and that the NSWindow instance must have a CoreGraphics counterpart (or
yangsu@google.com12d177d2011-08-01 17:07:12 +0000391 //it must NOT be deferred or should have been on screen at least once)
392 if ([fGLContext view] != self && nil != self.window) {
393 [fGLContext setView:self];
yangsu@google.com12d177d2011-08-01 17:07:12 +0000394 }
395}
bsalomon@google.com2e401732012-08-03 19:25:10 +0000396- (bool)attach:(SkOSWindow::SkBackEndTypes)attachType
bsalomon@google.com64cc8102013-03-05 20:06:05 +0000397 withMSAASampleCount:(int) sampleCount
398 andGetInfo:(SkOSWindow::AttachmentInfo*) info {
bsalomon@google.com2e401732012-08-03 19:25:10 +0000399 if (nil == fGLContext) {
400 CGLContextObj ctx = createGLContext(sampleCount);
reed789e3272014-10-30 11:29:08 -0700401 SkASSERT(ctx);
bsalomon@google.com2e401732012-08-03 19:25:10 +0000402 fGLContext = [[NSOpenGLContext alloc] initWithCGLContextObj:ctx];
403 CGLReleaseContext(ctx);
404 if (NULL == fGLContext) {
405 return false;
caryclark@google.com4ee8aea2011-11-23 14:54:19 +0000406 }
bsalomon@google.com2e401732012-08-03 19:25:10 +0000407 [fGLContext setView:self];
caryclark@google.com4ee8aea2011-11-23 14:54:19 +0000408 }
bsalomon@google.com64cc8102013-03-05 20:06:05 +0000409
bsalomon@google.com2e401732012-08-03 19:25:10 +0000410 [fGLContext makeCurrentContext];
bsalomon@google.com64cc8102013-03-05 20:06:05 +0000411 CGLPixelFormatObj format = CGLGetPixelFormat((CGLContextObj)[fGLContext CGLContextObj]);
412 CGLDescribePixelFormat(format, 0, kCGLPFASamples, &info->fSampleCount);
413 CGLDescribePixelFormat(format, 0, kCGLPFAStencilSize, &info->fStencilBits);
bungeman@google.comb20a1b52013-06-28 16:44:55 +0000414 NSSize size = self.bounds.size;
415#if RETINA_API_AVAILABLE
416 size = [self convertSizeToBacking:size];
417#endif
418 glViewport(0, 0, (int) size.width, (int) size.height);
bsalomon@google.com2e401732012-08-03 19:25:10 +0000419 glClearColor(0, 0, 0, 0);
420 glClearStencil(0);
421 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
422 return true;
yangsu@google.com12d177d2011-08-01 17:07:12 +0000423}
424
robertphillips@google.comd5b05ef2012-04-02 20:19:28 +0000425- (void)detach {
bsalomon@google.comed164832012-04-03 18:06:20 +0000426 [fGLContext release];
427 fGLContext = nil;
yangsu@google.com12d177d2011-08-01 17:07:12 +0000428}
429
robertphillips@google.comd5b05ef2012-04-02 20:19:28 +0000430- (void)present {
bsalomon@google.comed164832012-04-03 18:06:20 +0000431 if (nil != fGLContext) {
432 [fGLContext flushBuffer];
433 }
yangsu@google.com12d177d2011-08-01 17:07:12 +0000434}
bsalomon241b56d2015-06-18 11:49:42 -0700435
436- (void)setVSync:(bool)enable {
437 if (fGLContext) {
438 GLint interval = enable ? 1 : 0;
439 CGLContextObj ctx = (CGLContextObj)[fGLContext CGLContextObj];
440 CGLSetParameter(ctx, kCGLCPSwapInterval, &interval);
441 }
442}
robertphillips@google.comd5b05ef2012-04-02 20:19:28 +0000443@end