1f75b84e94b1ca1540295584421de0158d87a9b52bsalomon@google.com/* 2f75b84e94b1ca1540295584421de0158d87a9b52bsalomon@google.com * Copyright 2011 Google Inc. 3f75b84e94b1ca1540295584421de0158d87a9b52bsalomon@google.com * 4f75b84e94b1ca1540295584421de0158d87a9b52bsalomon@google.com * Use of this source code is governed by a BSD-style license that can be 5f75b84e94b1ca1540295584421de0158d87a9b52bsalomon@google.com * found in the LICENSE file. 6f75b84e94b1ca1540295584421de0158d87a9b52bsalomon@google.com */ 7f75b84e94b1ca1540295584421de0158d87a9b52bsalomon@google.com 85b5bba36dcbc69b0033c2acc9981734956394816robertphillips@google.com#import "SkNSView.h" 912d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com#include "SkCanvas.h" 100397e9f3415b4646797f1b17e9a38b5deb864ff0reed#include "SkSurface.h" 1112d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com#include "SkCGUtils.h" 1212d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com#include "SkEvent.h" 132e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.comSK_COMPILE_ASSERT(SK_SUPPORT_GPU, not_implemented_for_non_gpu_build); 146a18079de8a39cf8438d60e51b3de2cd3a7edf00commit-bot@chromium.org#include <OpenGL/gl.h> 1512d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com 1612d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com//#define FORCE_REDRAW 17b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com// Can be dropped when we no longer support 10.6. 18b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com#define RETINA_API_AVAILABLE (defined(MAC_OS_X_VERSION_10_7) && \ 19b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7) 2012d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com@implementation SkNSView 212e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com@synthesize fWind, fTitle, fOptionsDelegate, fGLContext; 2212d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com 2312d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com- (id)initWithCoder:(NSCoder*)coder { 2412d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com if ((self = [super initWithCoder:coder])) { 25a8540416f65b55aadbe68cdef9fece5a23257d5eyangsu@google.com self = [self initWithDefaults]; 26a8540416f65b55aadbe68cdef9fece5a23257d5eyangsu@google.com [self setUpWindow]; 2712d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com } 2812d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com return self; 2912d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com} 3012d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com 3112d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com- (id)initWithFrame:(NSRect)frameRect { 32679ab317cd4b434e19904b71cabd8e801a629bb1caryclark@google.com if ((self = [super initWithFrame:frameRect])) { 33a8540416f65b55aadbe68cdef9fece5a23257d5eyangsu@google.com self = [self initWithDefaults]; 34a8540416f65b55aadbe68cdef9fece5a23257d5eyangsu@google.com [self setUpWindow]; 3512d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com } 3612d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com return self; 3712d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com} 3812d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com 39a8540416f65b55aadbe68cdef9fece5a23257d5eyangsu@google.com- (id)initWithDefaults { 40b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com#if RETINA_API_AVAILABLE 41b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com [self setWantsBestResolutionOpenGLSurface:YES]; 42b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com#endif 4312d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com fRedrawRequestPending = false; 44a8540416f65b55aadbe68cdef9fece5a23257d5eyangsu@google.com fWind = NULL; 4512d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com return self; 4612d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com} 4712d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com 48a8540416f65b55aadbe68cdef9fece5a23257d5eyangsu@google.com- (void)setUpWindow { 49b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com [[NSNotificationCenter defaultCenter] addObserver:self 50b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com selector:@selector(backingPropertiesChanged:) 51b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com name:@"NSWindowDidChangeBackingPropertiesNotification" 52b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com object:[self window]]; 5349f085dddff10473b6ebf832a974288300224e60bsalomon if (fWind) { 54a8540416f65b55aadbe68cdef9fece5a23257d5eyangsu@google.com fWind->setVisibleP(true); 55b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com NSSize size = self.frame.size; 56b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com#if RETINA_API_AVAILABLE 57b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com size = [self convertSizeToBacking:self.frame.size]; 58b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com#endif 59b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com fWind->resize((int) size.width, (int) size.height, 6028fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org kN32_SkColorType); 61a8540416f65b55aadbe68cdef9fece5a23257d5eyangsu@google.com } 62a8540416f65b55aadbe68cdef9fece5a23257d5eyangsu@google.com} 63a8540416f65b55aadbe68cdef9fece5a23257d5eyangsu@google.com 6412d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com-(BOOL) isFlipped { 6512d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com return YES; 6612d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com} 6712d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com 6812d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com- (BOOL)acceptsFirstResponder { 6912d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com return YES; 7012d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com} 7112d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com 72b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com- (float)scaleFactor { 73b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com NSWindow *window = [self window]; 74b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com#if RETINA_API_AVAILABLE 75b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com if (window) { 76b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com return [window backingScaleFactor]; 77b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com } 78b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com return [[NSScreen mainScreen] backingScaleFactor]; 79b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com#else 80b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com if (window) { 81b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com return [window userSpaceScaleFactor]; 82b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com } 83b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com return [[NSScreen mainScreen] userSpaceScaleFactor]; 84b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com#endif 85b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com} 86b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com 87b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com- (void)backingPropertiesChanged:(NSNotification *)notification { 8844fb1faefec69561b11a4ddaca6fa89a6dcb3ac6bungeman@google.com CGFloat oldBackingScaleFactor = (CGFloat)[ 89b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com [notification.userInfo objectForKey:@"NSBackingPropertyOldScaleFactorKey"] doubleValue 90b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com ]; 91b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com CGFloat newBackingScaleFactor = [self scaleFactor]; 92b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com if (oldBackingScaleFactor == newBackingScaleFactor) { 93b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com return; 94b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com } 95b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com 96b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com // TODO: need a better way to force a refresh (that works). 97b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com // [fGLContext update] does not appear to update if the point size has not changed, 98b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com // even if the backing size has changed. 99b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com [self setFrameSize:NSMakeSize(self.frame.size.width + 1, self.frame.size.height + 1)]; 100b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com} 101b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com 102bb3f4a8d0a58a8857050a7b6a907b190d261681dsuyang- (void)resizeSkView:(NSSize)newSize { 103b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com#if RETINA_API_AVAILABLE 104b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com newSize = [self convertSizeToBacking:newSize]; 105b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com#endif 10649f085dddff10473b6ebf832a974288300224e60bsalomon if (fWind && (fWind->width() != newSize.width || fWind->height() != newSize.height)) { 107679ab317cd4b434e19904b71cabd8e801a629bb1caryclark@google.com fWind->resize((int) newSize.width, (int) newSize.height); 10849f085dddff10473b6ebf832a974288300224e60bsalomon if (fGLContext) { 109594dd3cd78e2f970d53bb0934fbbb63b41e1d40ccaryclark@google.com glClear(GL_STENCIL_BUFFER_BIT); 110b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com [fGLContext update]; 111594dd3cd78e2f970d53bb0934fbbb63b41e1d40ccaryclark@google.com } 11212d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com } 11312d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com} 11412d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com 115bb3f4a8d0a58a8857050a7b6a907b190d261681dsuyang- (void) setFrameSize:(NSSize)newSize { 116bb3f4a8d0a58a8857050a7b6a907b190d261681dsuyang [super setFrameSize:newSize]; 117bb3f4a8d0a58a8857050a7b6a907b190d261681dsuyang [self resizeSkView:newSize]; 118bb3f4a8d0a58a8857050a7b6a907b190d261681dsuyang} 119bb3f4a8d0a58a8857050a7b6a907b190d261681dsuyang 12012d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com- (void)dealloc { 121d3ce6b44e582c1a4c73a90b4314a387db8624ca2reed [self freeNativeWind]; 12212d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com self.fGLContext = nil; 12312d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com self.fTitle = nil; 12412d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com [super dealloc]; 12512d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com} 12612d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com 127d3ce6b44e582c1a4c73a90b4314a387db8624ca2reed- (void)freeNativeWind { 128d3ce6b44e582c1a4c73a90b4314a387db8624ca2reed delete fWind; 129d3ce6b44e582c1a4c73a90b4314a387db8624ca2reed fWind = nil; 130d3ce6b44e582c1a4c73a90b4314a387db8624ca2reed} 131d3ce6b44e582c1a4c73a90b4314a387db8624ca2reed 132bb3f4a8d0a58a8857050a7b6a907b190d261681dsuyang//////////////////////////////////////////////////////////////////////////////// 13312d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com 134f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com- (void)drawSkia { 13512d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com fRedrawRequestPending = false; 13649f085dddff10473b6ebf832a974288300224e60bsalomon if (fWind) { 1370397e9f3415b4646797f1b17e9a38b5deb864ff0reed SkAutoTUnref<SkSurface> surface(fWind->createSurface()); 1380397e9f3415b4646797f1b17e9a38b5deb864ff0reed fWind->draw(surface->getCanvas()); 13912d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com#ifdef FORCE_REDRAW 140a8540416f65b55aadbe68cdef9fece5a23257d5eyangsu@google.com fWind->inval(NULL); 14112d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com#endif 142a8540416f65b55aadbe68cdef9fece5a23257d5eyangsu@google.com } 14312d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com} 14412d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com 145f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com- (void)setSkTitle:(const char *)title { 146f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com self.fTitle = [NSString stringWithUTF8String:title]; 147f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com [[self window] setTitle:self.fTitle]; 148f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com} 149f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com 150f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com- (BOOL)onHandleEvent:(const SkEvent&)evt { 151f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com return false; 152f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com} 153f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com 154f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com#include "SkOSMenu.h" 155f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com- (void)onAddMenu:(const SkOSMenu*)menu { 156f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com [self.fOptionsDelegate view:self didAddMenu:menu]; 157f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com} 158f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com 159f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com- (void)onUpdateMenu:(const SkOSMenu*)menu { 160f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com [self.fOptionsDelegate view:self didUpdateMenu:menu]; 161f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com} 162f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com 163f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com- (void)postInvalWithRect:(const SkIRect*)r { 164f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com if (!fRedrawRequestPending) { 165f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com fRedrawRequestPending = true; 166a8540416f65b55aadbe68cdef9fece5a23257d5eyangsu@google.com [self setNeedsDisplay:YES]; 167f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com [self performSelector:@selector(drawSkia) withObject:nil afterDelay:0]; 168f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com } 16912d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com} 17012d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com/////////////////////////////////////////////////////////////////////////////// 17112d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com 17212d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com#include "SkKey.h" 17312d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.comenum { 1742e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com SK_MacReturnKey = 36, 1752e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com SK_MacDeleteKey = 51, 1762e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com SK_MacEndKey = 119, 1772e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com SK_MacLeftKey = 123, 1782e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com SK_MacRightKey = 124, 1792e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com SK_MacDownKey = 125, 1802e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com SK_MacUpKey = 126, 18112d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com SK_Mac0Key = 0x52, 18212d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com SK_Mac1Key = 0x53, 18312d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com SK_Mac2Key = 0x54, 18412d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com SK_Mac3Key = 0x55, 18512d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com SK_Mac4Key = 0x56, 18612d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com SK_Mac5Key = 0x57, 18712d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com SK_Mac6Key = 0x58, 18812d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com SK_Mac7Key = 0x59, 18912d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com SK_Mac8Key = 0x5b, 19012d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com SK_Mac9Key = 0x5c 19112d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com}; 19212d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com 19312d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.comstatic SkKey raw2key(UInt32 raw) 19412d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com{ 1952e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com static const struct { 1962e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com UInt32 fRaw; 1972e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com SkKey fKey; 1982e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com } gKeys[] = { 1992e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com { SK_MacUpKey, kUp_SkKey }, 2002e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com { SK_MacDownKey, kDown_SkKey }, 2012e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com { SK_MacLeftKey, kLeft_SkKey }, 2022e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com { SK_MacRightKey, kRight_SkKey }, 2032e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com { SK_MacReturnKey, kOK_SkKey }, 2042e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com { SK_MacDeleteKey, kBack_SkKey }, 2052e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com { SK_MacEndKey, kEnd_SkKey }, 20612d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com { SK_Mac0Key, k0_SkKey }, 20712d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com { SK_Mac1Key, k1_SkKey }, 20812d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com { SK_Mac2Key, k2_SkKey }, 20912d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com { SK_Mac3Key, k3_SkKey }, 210f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com { SK_Mac4Key, k4_SkKey }, 21112d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com { SK_Mac5Key, k5_SkKey }, 21212d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com { SK_Mac6Key, k6_SkKey }, 21312d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com { SK_Mac7Key, k7_SkKey }, 21412d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com { SK_Mac8Key, k8_SkKey }, 21512d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com { SK_Mac9Key, k9_SkKey } 2162e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com }; 21712d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com 2182e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com for (unsigned i = 0; i < SK_ARRAY_COUNT(gKeys); i++) 2192e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com if (gKeys[i].fRaw == raw) 2202e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com return gKeys[i].fKey; 2212e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com return kNONE_SkKey; 22212d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com} 22312d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com 22412d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com- (void)keyDown:(NSEvent *)event { 225849ad5af851fc5bfe75e76cdd0bac44e5f9ec6ddyangsu@google.com if (NULL == fWind) 226a8540416f65b55aadbe68cdef9fece5a23257d5eyangsu@google.com return; 227a8540416f65b55aadbe68cdef9fece5a23257d5eyangsu@google.com 22812d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com SkKey key = raw2key([event keyCode]); 22912d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com if (kNONE_SkKey != key) 23012d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com fWind->handleKey(key); 23112d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com else{ 23212d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com unichar c = [[event characters] characterAtIndex:0]; 23312d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com fWind->handleChar((SkUnichar)c); 23412d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com } 23512d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com} 23612d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com 23712d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com- (void)keyUp:(NSEvent *)event { 238849ad5af851fc5bfe75e76cdd0bac44e5f9ec6ddyangsu@google.com if (NULL == fWind) 239a8540416f65b55aadbe68cdef9fece5a23257d5eyangsu@google.com return; 240a8540416f65b55aadbe68cdef9fece5a23257d5eyangsu@google.com 24112d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com SkKey key = raw2key([event keyCode]); 24212d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com if (kNONE_SkKey != key) 24312d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com fWind->handleKeyUp(key); 244679ab317cd4b434e19904b71cabd8e801a629bb1caryclark@google.com // else 245679ab317cd4b434e19904b71cabd8e801a629bb1caryclark@google.com // unichar c = [[event characters] characterAtIndex:0]; 24612d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com} 24712d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com 2484d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.comstatic const struct { 2494d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com unsigned fNSModifierMask; 2504d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com unsigned fSkModifierMask; 2514d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com} gModifierMasks[] = { 2524d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com { NSAlphaShiftKeyMask, kShift_SkModifierKey }, 2534d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com { NSShiftKeyMask, kShift_SkModifierKey }, 2544d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com { NSControlKeyMask, kControl_SkModifierKey }, 2554d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com { NSAlternateKeyMask, kOption_SkModifierKey }, 2564d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com { NSCommandKeyMask, kCommand_SkModifierKey }, 2574d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com}; 2584d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com 2594d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.comstatic unsigned convertNSModifiersToSk(NSUInteger nsModi) { 2604d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com unsigned skModi = 0; 2614d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com for (size_t i = 0; i < SK_ARRAY_COUNT(gModifierMasks); ++i) { 2624d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com if (nsModi & gModifierMasks[i].fNSModifierMask) { 2634d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com skModi |= gModifierMasks[i].fSkModifierMask; 2644d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com } 2654d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com } 2664d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com return skModi; 2674d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com} 2684d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com 26912d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com- (void)mouseDown:(NSEvent *)event { 27012d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com NSPoint p = [event locationInWindow]; 2714d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com unsigned modi = convertNSModifiersToSk([event modifierFlags]); 2724d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com 27349f085dddff10473b6ebf832a974288300224e60bsalomon if ([self mouse:p inRect:[self bounds]] && fWind) { 27412d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com NSPoint loc = [self convertPoint:p fromView:nil]; 275b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com#if RETINA_API_AVAILABLE 276b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com loc = [self convertPointToBacking:loc]; //y-up 277b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com loc.y = -loc.y; 278b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com#endif 2794d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com fWind->handleClick((int) loc.x, (int) loc.y, 2804d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com SkView::Click::kDown_State, self, modi); 28112d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com } 28212d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com} 28312d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com 28412d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com- (void)mouseDragged:(NSEvent *)event { 28512d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com NSPoint p = [event locationInWindow]; 2864d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com unsigned modi = convertNSModifiersToSk([event modifierFlags]); 2874d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com 28849f085dddff10473b6ebf832a974288300224e60bsalomon if ([self mouse:p inRect:[self bounds]] && fWind) { 28912d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com NSPoint loc = [self convertPoint:p fromView:nil]; 290b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com#if RETINA_API_AVAILABLE 291b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com loc = [self convertPointToBacking:loc]; //y-up 292b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com loc.y = -loc.y; 293b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com#endif 2944d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com fWind->handleClick((int) loc.x, (int) loc.y, 2954d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com SkView::Click::kMoved_State, self, modi); 29612d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com } 297bb3f4a8d0a58a8857050a7b6a907b190d261681dsuyang} 298bb3f4a8d0a58a8857050a7b6a907b190d261681dsuyang 299bb3f4a8d0a58a8857050a7b6a907b190d261681dsuyang- (void)mouseMoved:(NSEvent *)event { 300bb3f4a8d0a58a8857050a7b6a907b190d261681dsuyang NSPoint p = [event locationInWindow]; 3014d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com unsigned modi = convertNSModifiersToSk([event modifierFlags]); 3024d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com 30349f085dddff10473b6ebf832a974288300224e60bsalomon if ([self mouse:p inRect:[self bounds]] && fWind) { 304bb3f4a8d0a58a8857050a7b6a907b190d261681dsuyang NSPoint loc = [self convertPoint:p fromView:nil]; 305b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com#if RETINA_API_AVAILABLE 306b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com loc = [self convertPointToBacking:loc]; //y-up 307b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com loc.y = -loc.y; 308b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com#endif 3094d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com fWind->handleClick((int) loc.x, (int) loc.y, 3104d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com SkView::Click::kMoved_State, self, modi); 311bb3f4a8d0a58a8857050a7b6a907b190d261681dsuyang } 31212d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com} 31312d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com 31412d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com- (void)mouseUp:(NSEvent *)event { 31512d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com NSPoint p = [event locationInWindow]; 3164d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com unsigned modi = convertNSModifiersToSk([event modifierFlags]); 3174d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com 31849f085dddff10473b6ebf832a974288300224e60bsalomon if ([self mouse:p inRect:[self bounds]] && fWind) { 31912d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com NSPoint loc = [self convertPoint:p fromView:nil]; 320b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com#if RETINA_API_AVAILABLE 321b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com loc = [self convertPointToBacking:loc]; //y-up 322b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com loc.y = -loc.y; 323b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com#endif 3244d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com fWind->handleClick((int) loc.x, (int) loc.y, 3254d5c26de0a24f86c37c1da8b0e30d11a550ea67breed@google.com SkView::Click::kUp_State, self, modi); 32612d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com } 32712d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com} 32812d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com 32912d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com/////////////////////////////////////////////////////////////////////////////// 33012d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com#include <OpenGL/OpenGL.h> 3312e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com 332ed164836f3268e4cd7cea916b4876f6e1c81849absalomon@google.comnamespace { 3331195925b05ee9d666ea8a8f68fde5d8ca7e49b04bsalomon@google.comCGLContextObj createGLContext(int msaaSampleCount) { 33412d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com GLint major, minor; 33512d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com CGLGetVersion(&major, &minor); 33612d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com 3371195925b05ee9d666ea8a8f68fde5d8ca7e49b04bsalomon@google.com static const CGLPixelFormatAttribute attributes[] = { 3381195925b05ee9d666ea8a8f68fde5d8ca7e49b04bsalomon@google.com kCGLPFAStencilSize, (CGLPixelFormatAttribute) 8, 33912d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com kCGLPFAAccelerated, 34012d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com kCGLPFADoubleBuffer, 34112d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com (CGLPixelFormatAttribute)0 34212d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com }; 34312d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com 34412d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com CGLPixelFormatObj format; 3451195925b05ee9d666ea8a8f68fde5d8ca7e49b04bsalomon@google.com GLint npix = 0; 3461195925b05ee9d666ea8a8f68fde5d8ca7e49b04bsalomon@google.com if (msaaSampleCount > 0) { 3471195925b05ee9d666ea8a8f68fde5d8ca7e49b04bsalomon@google.com static int kAttributeCount = SK_ARRAY_COUNT(attributes); 3481195925b05ee9d666ea8a8f68fde5d8ca7e49b04bsalomon@google.com CGLPixelFormatAttribute msaaAttributes[kAttributeCount + 5]; 3491195925b05ee9d666ea8a8f68fde5d8ca7e49b04bsalomon@google.com memcpy(msaaAttributes, attributes, sizeof(attributes)); 3501195925b05ee9d666ea8a8f68fde5d8ca7e49b04bsalomon@google.com SkASSERT(0 == msaaAttributes[kAttributeCount - 1]); 3511195925b05ee9d666ea8a8f68fde5d8ca7e49b04bsalomon@google.com msaaAttributes[kAttributeCount - 1] = kCGLPFASampleBuffers; 3521195925b05ee9d666ea8a8f68fde5d8ca7e49b04bsalomon@google.com msaaAttributes[kAttributeCount + 0] = (CGLPixelFormatAttribute)1; 3531195925b05ee9d666ea8a8f68fde5d8ca7e49b04bsalomon@google.com msaaAttributes[kAttributeCount + 1] = kCGLPFAMultisample; 3541195925b05ee9d666ea8a8f68fde5d8ca7e49b04bsalomon@google.com msaaAttributes[kAttributeCount + 2] = kCGLPFASamples; 3551195925b05ee9d666ea8a8f68fde5d8ca7e49b04bsalomon@google.com msaaAttributes[kAttributeCount + 3] = 3561195925b05ee9d666ea8a8f68fde5d8ca7e49b04bsalomon@google.com (CGLPixelFormatAttribute)msaaSampleCount; 3571195925b05ee9d666ea8a8f68fde5d8ca7e49b04bsalomon@google.com msaaAttributes[kAttributeCount + 4] = (CGLPixelFormatAttribute)0; 3581195925b05ee9d666ea8a8f68fde5d8ca7e49b04bsalomon@google.com CGLChoosePixelFormat(msaaAttributes, &format, &npix); 3591195925b05ee9d666ea8a8f68fde5d8ca7e49b04bsalomon@google.com } 3601195925b05ee9d666ea8a8f68fde5d8ca7e49b04bsalomon@google.com if (!npix) { 3611195925b05ee9d666ea8a8f68fde5d8ca7e49b04bsalomon@google.com CGLChoosePixelFormat(attributes, &format, &npix); 3621195925b05ee9d666ea8a8f68fde5d8ca7e49b04bsalomon@google.com } 363ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com CGLContextObj ctx; 36412d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com CGLCreateContext(format, NULL, &ctx); 36512d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com CGLDestroyPixelFormat(format); 36612d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com 36712d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com static const GLint interval = 1; 36812d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com CGLSetParameter(ctx, kCGLCPSwapInterval, &interval); 36912d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com CGLSetCurrentContext(ctx); 37012d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com return ctx; 37112d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com} 372ed164836f3268e4cd7cea916b4876f6e1c81849absalomon@google.com} 37312d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com 37412d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com- (void)viewDidMoveToWindow { 37512d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com [super viewDidMoveToWindow]; 37612d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com 37712d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com //Attaching view to fGLContext requires that the view to be part of a window, 37812d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com //and that the NSWindow instance must have a CoreGraphics counterpart (or 37912d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com //it must NOT be deferred or should have been on screen at least once) 38012d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com if ([fGLContext view] != self && nil != self.window) { 38112d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com [fGLContext setView:self]; 38212d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com } 38312d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com} 3842e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com- (bool)attach:(SkOSWindow::SkBackEndTypes)attachType 38564cc810ad165724f9c666a75bd52e41c67f13564bsalomon@google.com withMSAASampleCount:(int) sampleCount 38664cc810ad165724f9c666a75bd52e41c67f13564bsalomon@google.com andGetInfo:(SkOSWindow::AttachmentInfo*) info { 3872e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com if (nil == fGLContext) { 3882e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com CGLContextObj ctx = createGLContext(sampleCount); 389789e327ad9c9f7d25b2368b4f3f9812bf9f0a3a2reed SkASSERT(ctx); 3902e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com fGLContext = [[NSOpenGLContext alloc] initWithCGLContextObj:ctx]; 3912e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com CGLReleaseContext(ctx); 3922e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com if (NULL == fGLContext) { 3932e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com return false; 3944ee8aea2a77d2d22d56afe68699179e5a02ac4f4caryclark@google.com } 3952e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com [fGLContext setView:self]; 396cf8fb1f6f03fc77f9927564f9ef9abeeeec508d2bsalomon@google.com } 39764cc810ad165724f9c666a75bd52e41c67f13564bsalomon@google.com 3982e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com [fGLContext makeCurrentContext]; 39964cc810ad165724f9c666a75bd52e41c67f13564bsalomon@google.com CGLPixelFormatObj format = CGLGetPixelFormat((CGLContextObj)[fGLContext CGLContextObj]); 40064cc810ad165724f9c666a75bd52e41c67f13564bsalomon@google.com CGLDescribePixelFormat(format, 0, kCGLPFASamples, &info->fSampleCount); 40164cc810ad165724f9c666a75bd52e41c67f13564bsalomon@google.com CGLDescribePixelFormat(format, 0, kCGLPFAStencilSize, &info->fStencilBits); 402b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com NSSize size = self.bounds.size; 403b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com#if RETINA_API_AVAILABLE 404b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com size = [self convertSizeToBacking:size]; 405b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com#endif 406b20a1b56a08d59d44eb8f7d423fccf88375c2c73bungeman@google.com glViewport(0, 0, (int) size.width, (int) size.height); 4072e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com glClearColor(0, 0, 0, 0); 4082e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com glClearStencil(0); 4092e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 4102e40173c95116f3546a1ebf5689df707d17cb7b4bsalomon@google.com return true; 41112d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com} 41212d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com 413d5b05ef06b0f2082400a29c34a1692728f53b349robertphillips@google.com- (void)detach { 414ed164836f3268e4cd7cea916b4876f6e1c81849absalomon@google.com [fGLContext release]; 415ed164836f3268e4cd7cea916b4876f6e1c81849absalomon@google.com fGLContext = nil; 41612d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com} 41712d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com 418d5b05ef06b0f2082400a29c34a1692728f53b349robertphillips@google.com- (void)present { 419ed164836f3268e4cd7cea916b4876f6e1c81849absalomon@google.com if (nil != fGLContext) { 420ed164836f3268e4cd7cea916b4876f6e1c81849absalomon@google.com [fGLContext flushBuffer]; 421ed164836f3268e4cd7cea916b4876f6e1c81849absalomon@google.com } 42212d177d1f3b61851c782930d5bd7cce80525deb3yangsu@google.com} 423d5b05ef06b0f2082400a29c34a1692728f53b349robertphillips@google.com@end 424