1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #include <stdio.h> 17 #include <Cocoa/Cocoa.h> 18 #include <OpenGL/OpenGL.h> 19 #include "MacPixelFormatsAttribs.h" 20 21 // 22 // EmuGLContext inherit from NSOpenGLContext 23 // and adds binding state for the context to know 24 // if it was last bounded to a pbuffer or a window. 25 // This is because after the context was bounded to 26 // a Pbuffer, before we bind it to a window we must 27 // release it form the pbuffer by calling the 28 // clearDrawable method. We do not want to call clearDrawable 29 // more than really needed since when it is called at a time 30 // that a window is bounded to the context it will clear the 31 // window content causing flickering effect. 32 // Thererfore we call clearDrawable only when we bind the context 33 // to a window and it was previously bound to a Pbuffer. 34 // 35 @interface EmuGLContext : NSOpenGLContext { 36 @private 37 int boundToPbuffer; 38 int boundToWin; 39 } 40 41 - (id) initWithFormat:(NSOpenGLPixelFormat *)pixelFormat shareContext:(NSOpenGLContext *)share; 42 - (void) preBind:(int)forPbuffer; 43 @end 44 45 @implementation EmuGLContext 46 - (id) initWithFormat:(NSOpenGLPixelFormat *)pixelFormat shareContext:(NSOpenGLContext *)share 47 { 48 self = [super initWithFormat:pixelFormat shareContext:share]; 49 if (self != nil) { 50 boundToPbuffer = 0; 51 boundToWin = 0; 52 } 53 return self; 54 } 55 56 - (void) preBind:(int)forPbuffer 57 { 58 if ((!forPbuffer && boundToPbuffer)) { 59 [self clearDrawable]; 60 } 61 boundToPbuffer = forPbuffer; 62 boundToWin = !boundToPbuffer; 63 } 64 @end 65 66 int getNumPixelFormats(){ 67 int size; 68 NSOpenGLPixelFormatAttribute** attrib_lists = getPixelFormatsAttributes(&size); 69 return size; 70 } 71 72 void* getPixelFormat(int i){ 73 int size; 74 NSOpenGLPixelFormatAttribute** attrib_lists = getPixelFormatsAttributes(&size); 75 return [[NSOpenGLPixelFormat alloc] initWithAttributes:attrib_lists[i]]; 76 } 77 78 int getPixelFormatDefinitionAlpha(int i) { 79 int size; 80 NSOpenGLPixelFormatAttribute** attrib_lists = getPixelFormatsAttributes(&size); 81 NSOpenGLPixelFormatAttribute* attribs = attrib_lists[i]; 82 while (*attribs) { 83 switch (*attribs) { 84 // These are the ones that take a value, according to the current 85 // NSOpenGLPixelFormat docs 86 case NSOpenGLPFAAuxBuffers: 87 case NSOpenGLPFAColorSize: 88 case NSOpenGLPFADepthSize: 89 case NSOpenGLPFAStencilSize: 90 case NSOpenGLPFAAccumSize: 91 case NSOpenGLPFARendererID: 92 case NSOpenGLPFAScreenMask: 93 attribs += 2; 94 break; 95 case NSOpenGLPFAAlphaSize: 96 return attribs[1]; 97 break; 98 // All other attributes are boolean attributes that don't take a value 99 default: 100 attribs++; 101 } 102 } 103 return 0; 104 } 105 106 void getPixelFormatAttrib(void* pixelFormat,int attrib,int* val){ 107 NSOpenGLPixelFormat *frmt = (NSOpenGLPixelFormat *)pixelFormat; 108 [frmt getValues:val forAttribute:attrib forVirtualScreen:0]; 109 } 110 111 void* nsCreateContext(void* format,void* share){ 112 NSOpenGLPixelFormat* frmt = (NSOpenGLPixelFormat*)format; 113 return [[EmuGLContext alloc] initWithFormat:frmt shareContext:share]; 114 } 115 116 void nsPBufferMakeCurrent(void* context,void* nativePBuffer,int level){ 117 EmuGLContext* ctx = (EmuGLContext *)context; 118 NSOpenGLPixelBuffer* pbuff = (NSOpenGLPixelBuffer *)nativePBuffer; 119 if(ctx == nil){ 120 [NSOpenGLContext clearCurrentContext]; 121 } else { 122 if(pbuff != nil){ 123 [ctx preBind:1]; 124 [ctx setPixelBuffer:pbuff cubeMapFace:0 mipMapLevel:level currentVirtualScreen:0]; 125 [ctx makeCurrentContext]; 126 } 127 } 128 } 129 130 void nsWindowMakeCurrent(void* context,void* nativeWin){ 131 EmuGLContext* ctx = (EmuGLContext *)context; 132 NSView* win = (NSView *)nativeWin; 133 if(ctx == nil){ 134 [NSOpenGLContext clearCurrentContext]; 135 } else if (win != nil) { 136 [ctx preBind:0]; 137 [ctx setView: win]; 138 [ctx makeCurrentContext]; 139 } 140 } 141 142 void nsSwapBuffers(){ 143 NSOpenGLContext* ctx = [NSOpenGLContext currentContext]; 144 if(ctx != nil){ 145 [ctx flushBuffer]; 146 } 147 } 148 149 void nsSwapInterval(int *interval){ 150 NSOpenGLContext* ctx = [NSOpenGLContext currentContext]; 151 if( ctx != nil){ 152 [ctx setValues:interval forParameter:NSOpenGLCPSwapInterval]; 153 } 154 } 155 156 157 void nsDestroyContext(void* context){ 158 EmuGLContext *ctx = (EmuGLContext*)context; 159 if(ctx != nil){ 160 [ctx release]; 161 } 162 } 163 164 165 void* nsCreatePBuffer(GLenum target,GLenum format,int maxMip,int width,int height){ 166 return [[NSOpenGLPixelBuffer alloc] initWithTextureTarget:target 167 textureInternalFormat:format 168 textureMaxMipMapLevel:maxMip 169 pixelsWide:width pixelsHigh:height]; 170 171 } 172 173 void nsDestroyPBuffer(void* pbuffer){ 174 NSOpenGLPixelBuffer *pbuf = (NSOpenGLPixelBuffer*)pbuffer; 175 if(pbuf != nil){ 176 [pbuf release]; 177 } 178 } 179 180 bool nsGetWinDims(void* win,unsigned int* width,unsigned int* height){ 181 NSView* view = (NSView*)win; 182 if(view != nil){ 183 NSRect rect = [view bounds]; 184 *width = rect.size.width; 185 *height = rect.size.height; 186 return true; 187 } 188 return false; 189 } 190 191 bool nsCheckColor(void* win,int colorSize){ 192 NSView* view = (NSView*)win; 193 if(view != nil){ 194 NSWindow* wnd = [view window]; 195 if(wnd != nil){ 196 NSWindowDepth limit = [wnd depthLimit]; 197 NSWindowDepth defaultLimit = [NSWindow defaultDepthLimit]; 198 199 int depth = (limit != 0) ? NSBitsPerPixelFromDepth(limit): 200 NSBitsPerPixelFromDepth(defaultLimit); 201 return depth >= colorSize; 202 203 } 204 } 205 return false; 206 207 } 208