blob: a2cea93cbd1210163af094e6397d0b566e5e3587 [file] [log] [blame]
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <Cocoa/Cocoa.h>
#include <OpenGL/OpenGL.h>
#include "MacPixelFormatsAttribs.h"
//
// EmuGLContext inherit from NSOpenGLContext
// and adds binding state for the context to know
// if it was last bounded to a pbuffer or a window.
// This is because after the context was bounded to
// a Pbuffer, before we bind it to a window we must
// release it form the pbuffer by calling the
// clearDrawable method. We do not want to call clearDrawable
// more than really needed since when it is called at a time
// that a window is bounded to the context it will clear the
// window content causing flickering effect.
// Thererfore we call clearDrawable only when we bind the context
// to a window and it was previously bound to a Pbuffer.
//
@interface EmuGLContext : NSOpenGLContext {
@private
int boundToPbuffer;
int boundToWin;
}
- (id) initWithFormat:(NSOpenGLPixelFormat *)pixelFormat shareContext:(NSOpenGLContext *)share;
- (void) preBind:(int)forPbuffer;
@end
@implementation EmuGLContext
- (id) initWithFormat:(NSOpenGLPixelFormat *)pixelFormat shareContext:(NSOpenGLContext *)share
{
self = [super initWithFormat:pixelFormat shareContext:share];
if (self != nil) {
boundToPbuffer = 0;
boundToWin = 0;
}
return self;
}
- (void) preBind:(int)forPbuffer
{
if ((!forPbuffer && boundToPbuffer)) {
[self clearDrawable];
}
boundToPbuffer = forPbuffer;
boundToWin = !boundToPbuffer;
}
@end
int getNumPixelFormats(){
int size;
NSOpenGLPixelFormatAttribute** attrib_lists = getPixelFormatsAttributes(&size);
return size;
}
void* getPixelFormat(int i){
int size;
NSOpenGLPixelFormatAttribute** attrib_lists = getPixelFormatsAttributes(&size);
return [[NSOpenGLPixelFormat alloc] initWithAttributes:attrib_lists[i]];
}
int getPixelFormatDefinitionAlpha(int i) {
int size;
NSOpenGLPixelFormatAttribute** attrib_lists = getPixelFormatsAttributes(&size);
NSOpenGLPixelFormatAttribute* attribs = attrib_lists[i];
while (*attribs) {
switch (*attribs) {
// These are the ones that take a value, according to the current
// NSOpenGLPixelFormat docs
case NSOpenGLPFAAuxBuffers:
case NSOpenGLPFAColorSize:
case NSOpenGLPFADepthSize:
case NSOpenGLPFAStencilSize:
case NSOpenGLPFAAccumSize:
case NSOpenGLPFARendererID:
case NSOpenGLPFAScreenMask:
attribs += 2;
break;
case NSOpenGLPFAAlphaSize:
return attribs[1];
break;
// All other attributes are boolean attributes that don't take a value
default:
attribs++;
}
}
return 0;
}
void getPixelFormatAttrib(void* pixelFormat,int attrib,int* val){
NSOpenGLPixelFormat *frmt = (NSOpenGLPixelFormat *)pixelFormat;
[frmt getValues:val forAttribute:attrib forVirtualScreen:0];
}
void* nsCreateContext(void* format,void* share){
NSOpenGLPixelFormat* frmt = (NSOpenGLPixelFormat*)format;
return [[EmuGLContext alloc] initWithFormat:frmt shareContext:share];
}
void nsPBufferMakeCurrent(void* context,void* nativePBuffer,int level){
EmuGLContext* ctx = (EmuGLContext *)context;
NSOpenGLPixelBuffer* pbuff = (NSOpenGLPixelBuffer *)nativePBuffer;
if(ctx == nil){
[NSOpenGLContext clearCurrentContext];
} else {
if(pbuff != nil){
[ctx preBind:1];
[ctx setPixelBuffer:pbuff cubeMapFace:0 mipMapLevel:level currentVirtualScreen:0];
[ctx makeCurrentContext];
}
}
}
void nsWindowMakeCurrent(void* context,void* nativeWin){
EmuGLContext* ctx = (EmuGLContext *)context;
NSView* win = (NSView *)nativeWin;
if(ctx == nil){
[NSOpenGLContext clearCurrentContext];
} else if (win != nil) {
[ctx preBind:0];
[ctx setView: win];
[ctx makeCurrentContext];
}
}
void nsSwapBuffers(){
NSOpenGLContext* ctx = [NSOpenGLContext currentContext];
if(ctx != nil){
[ctx flushBuffer];
}
}
void nsSwapInterval(int *interval){
NSOpenGLContext* ctx = [NSOpenGLContext currentContext];
if( ctx != nil){
[ctx setValues:interval forParameter:NSOpenGLCPSwapInterval];
}
}
void nsDestroyContext(void* context){
EmuGLContext *ctx = (EmuGLContext*)context;
if(ctx != nil){
[ctx release];
}
}
void* nsCreatePBuffer(GLenum target,GLenum format,int maxMip,int width,int height){
return [[NSOpenGLPixelBuffer alloc] initWithTextureTarget:target
textureInternalFormat:format
textureMaxMipMapLevel:maxMip
pixelsWide:width pixelsHigh:height];
}
void nsDestroyPBuffer(void* pbuffer){
NSOpenGLPixelBuffer *pbuf = (NSOpenGLPixelBuffer*)pbuffer;
if(pbuf != nil){
[pbuf release];
}
}
bool nsGetWinDims(void* win,unsigned int* width,unsigned int* height){
NSView* view = (NSView*)win;
if(view != nil){
NSRect rect = [view bounds];
*width = rect.size.width;
*height = rect.size.height;
return true;
}
return false;
}
bool nsCheckColor(void* win,int colorSize){
NSView* view = (NSView*)win;
if(view != nil){
NSWindow* wnd = [view window];
if(wnd != nil){
NSWindowDepth limit = [wnd depthLimit];
NSWindowDepth defaultLimit = [NSWindow defaultDepthLimit];
int depth = (limit != 0) ? NSBitsPerPixelFromDepth(limit):
NSBitsPerPixelFromDepth(defaultLimit);
return depth >= colorSize;
}
}
return false;
}