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
78int 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
106void getPixelFormatAttrib(void* pixelFormat,int attrib,int* val){
107    NSOpenGLPixelFormat *frmt = (NSOpenGLPixelFormat *)pixelFormat;
108    [frmt getValues:val forAttribute:attrib forVirtualScreen:0];
109}
110
111void* nsCreateContext(void* format,void* share){
112    NSOpenGLPixelFormat* frmt = (NSOpenGLPixelFormat*)format;
113    return [[EmuGLContext alloc] initWithFormat:frmt shareContext:share];
114}
115
116void  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
130void 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
142void nsSwapBuffers(){
143    NSOpenGLContext* ctx = [NSOpenGLContext currentContext];
144    if(ctx != nil){
145        [ctx flushBuffer];
146    }
147}
148
149void nsSwapInterval(int *interval){
150    NSOpenGLContext* ctx = [NSOpenGLContext currentContext];
151    if( ctx != nil){
152        [ctx setValues:interval forParameter:NSOpenGLCPSwapInterval];
153    }
154}
155
156
157void nsDestroyContext(void* context){
158    EmuGLContext *ctx = (EmuGLContext*)context;
159    if(ctx != nil){
160        [ctx release];
161    }
162}
163
164
165void* 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
173void nsDestroyPBuffer(void* pbuffer){
174    NSOpenGLPixelBuffer *pbuf = (NSOpenGLPixelBuffer*)pbuffer;
175    if(pbuf != nil){
176        [pbuf release];
177    }
178}
179
180bool 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
191bool  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