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 66int getNumPixelFormats(){ 67 int size; 68 NSOpenGLPixelFormatAttribute** attrib_lists = getPixelFormatsAttributes(&size); 69 return size; 70} 71 72void* getPixelFormat(int i){ 73 int size; 74 NSOpenGLPixelFormatAttribute** attrib_lists = getPixelFormatsAttributes(&size); 75 return [[NSOpenGLPixelFormat alloc] initWithAttributes:attrib_lists[i]]; 76} 77 78void getPixelFormatAttrib(void* pixelFormat,int attrib,int* val){ 79 NSOpenGLPixelFormat *frmt = (NSOpenGLPixelFormat *)pixelFormat; 80 [frmt getValues:val forAttribute:attrib forVirtualScreen:0]; 81} 82 83void* nsCreateContext(void* format,void* share){ 84 NSOpenGLPixelFormat* frmt = (NSOpenGLPixelFormat*)format; 85 return [[EmuGLContext alloc] initWithFormat:frmt shareContext:share]; 86} 87 88void nsPBufferMakeCurrent(void* context,void* nativePBuffer,int level){ 89 EmuGLContext* ctx = (EmuGLContext *)context; 90 NSOpenGLPixelBuffer* pbuff = (NSOpenGLPixelBuffer *)nativePBuffer; 91 if(ctx == nil){ 92 [NSOpenGLContext clearCurrentContext]; 93 } else { 94 if(pbuff != nil){ 95 [ctx preBind:1]; 96 [ctx setPixelBuffer:pbuff cubeMapFace:0 mipMapLevel:level currentVirtualScreen:0]; 97 [ctx makeCurrentContext]; 98 } 99 } 100} 101 102void nsWindowMakeCurrent(void* context,void* nativeWin){ 103 EmuGLContext* ctx = (EmuGLContext *)context; 104 NSView* win = (NSView *)nativeWin; 105 if(ctx == nil){ 106 [NSOpenGLContext clearCurrentContext]; 107 } else if (win != nil) { 108 [ctx preBind:0]; 109 [ctx setView: win]; 110 [ctx makeCurrentContext]; 111 } 112} 113 114void nsSwapBuffers(){ 115 NSOpenGLContext* ctx = [NSOpenGLContext currentContext]; 116 if(ctx != nil){ 117 [ctx flushBuffer]; 118 } 119} 120 121void nsSwapInterval(int *interval){ 122 NSOpenGLContext* ctx = [NSOpenGLContext currentContext]; 123 if( ctx != nil){ 124 [ctx setValues:interval forParameter:NSOpenGLCPSwapInterval]; 125 } 126} 127 128 129void nsDestroyContext(void* context){ 130 EmuGLContext *ctx = (EmuGLContext*)context; 131 if(ctx != nil){ 132 [ctx release]; 133 } 134} 135 136 137void* nsCreatePBuffer(GLenum target,GLenum format,int maxMip,int width,int height){ 138 return [[NSOpenGLPixelBuffer alloc] initWithTextureTarget:target 139 textureInternalFormat:format 140 textureMaxMipMapLevel:maxMip 141 pixelsWide:width pixelsHigh:height]; 142 143} 144 145void nsDestroyPBuffer(void* pbuffer){ 146 NSOpenGLPixelBuffer *pbuf = (NSOpenGLPixelBuffer*)pbuffer; 147 if(pbuf != nil){ 148 [pbuf release]; 149 } 150} 151 152bool nsGetWinDims(void* win,unsigned int* width,unsigned int* height){ 153 NSView* view = (NSView*)win; 154 if(view != nil){ 155 NSRect rect = [view bounds]; 156 *width = rect.size.width; 157 *height = rect.size.height; 158 return true; 159 } 160 return false; 161} 162 163bool nsCheckColor(void* win,int colorSize){ 164 NSView* view = (NSView*)win; 165 if(view != nil){ 166 NSWindow* wnd = [view window]; 167 if(wnd != nil){ 168 NSWindowDepth limit = [wnd depthLimit]; 169 NSWindowDepth defaultLimit = [NSWindow defaultDepthLimit]; 170 171 int depth = (limit != 0) ? NSBitsPerPixelFromDepth(limit): 172 NSBitsPerPixelFromDepth(defaultLimit); 173 return depth >= colorSize; 174 175 } 176 } 177 return false; 178 179} 180