• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 getAttrListLength(const NSOpenGLPixelFormatAttribute* list) {
67    int count = 0;
68    while (list[count++] != 0);
69    return count ? (count - 1) : 0;
70}
71
72static const NSOpenGLPixelFormatAttribute core32TestProfile[] = {
73    NSOpenGLPFAAccelerated,
74    NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
75    NSOpenGLPFADoubleBuffer,
76    NSOpenGLPFAColorSize   ,32,
77    NSOpenGLPFADepthSize   ,24,
78    NSOpenGLPFAStencilSize ,8,
79    0
80};
81
82static const NSOpenGLPixelFormatAttribute core41TestProfile[] = {
83    NSOpenGLPFAAccelerated,
84    NSOpenGLPFANoRecovery,
85    NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core,
86    NSOpenGLPFADoubleBuffer,
87    NSOpenGLPFAColorSize   ,32,
88    NSOpenGLPFADepthSize   ,24,
89    NSOpenGLPFAStencilSize ,8,
90    0
91};
92
93int setupCoreProfileNativeFormats() {
94
95    NSOpenGLPixelFormat* core41Supported =
96        [[NSOpenGLPixelFormat alloc] initWithAttributes: core41TestProfile];
97
98    if (core41Supported) {
99        setCoreProfileLevel(NSOpenGLProfileVersion4_1Core);
100        [core41Supported release];
101        return (int)NSOpenGLProfileVersion4_1Core;
102    }
103
104    NSOpenGLPixelFormat* core32Supported =
105        [[NSOpenGLPixelFormat alloc] initWithAttributes: core32TestProfile];
106
107    if (core32Supported) {
108        setCoreProfileLevel(NSOpenGLProfileVersion3_2Core);
109        [core32Supported release];
110        return (int)NSOpenGLProfileVersion3_2Core;
111    }
112
113    return (int)NSOpenGLProfileVersionLegacy;
114}
115
116int getNumPixelFormats(){
117    int size;
118    const NSOpenGLPixelFormatAttribute* const* attrib_lists =
119        getPixelFormatsAttributes(&size);
120    return size;
121}
122
123void* finalizePixelFormat(bool coreProfile,
124                          int attribsId) {
125    int size;
126    const NSOpenGLPixelFormatAttribute* const* attrib_lists =
127        getPixelFormatsAttributes(&size);
128
129    assert(attribsId < size);
130
131    const NSOpenGLPixelFormatAttribute*  attrs =
132        attrib_lists[attribsId];
133
134    const NSOpenGLPixelFormatAttribute* selected_variant =
135        coreProfile ?
136        getCoreProfileAttributes() :
137        getLegacyProfileAttributes();
138
139    // Format it as |variant| |attribs|
140    int variant_size =
141        getAttrListLength(selected_variant);
142    int attrib_size = getAttrListLength(attrs);
143    int numAttribsTotal = attrib_size + variant_size + 1; // for trailing 0
144
145    NSOpenGLPixelFormatAttribute* newAttrs =
146        malloc(sizeof(NSOpenGLPixelFormatAttribute) * numAttribsTotal);
147
148    int variant_part_bytes =
149        sizeof(NSOpenGLPixelFormatAttribute) * variant_size;
150    int attribs_part_bytes =
151        sizeof(NSOpenGLPixelFormatAttribute) * attrib_size;
152
153    memcpy(newAttrs, selected_variant, variant_part_bytes);
154    memcpy((char*)newAttrs + variant_part_bytes,
155           attrs, attribs_part_bytes);
156    newAttrs[numAttribsTotal - 1] = 0;
157
158    void* finalizedFormat =
159        [[NSOpenGLPixelFormat alloc] initWithAttributes: newAttrs];
160
161    free(newAttrs);
162
163    return finalizedFormat;
164}
165
166static bool sIsKeyValueAttrib(NSOpenGLPixelFormatAttribute attrib) {
167    switch (attrib) {
168        // These are the ones that take a value, according to the current
169        // NSOpenGLPixelFormat docs
170        case NSOpenGLPFAOpenGLProfile:
171        case NSOpenGLPFAAuxBuffers:
172        case NSOpenGLPFAColorSize:
173        case NSOpenGLPFAAlphaSize:
174        case NSOpenGLPFADepthSize:
175        case NSOpenGLPFAStencilSize:
176        case NSOpenGLPFAAccumSize:
177        case NSOpenGLPFARendererID:
178        case NSOpenGLPFAScreenMask:
179            return true;
180        default:
181            return false;
182    }
183}
184
185int getPixelFormatAttrib(int i, int _query) {
186    NSOpenGLPixelFormatAttribute query =
187        (NSOpenGLPixelFormatAttribute)_query;
188    int size;
189    const NSOpenGLPixelFormatAttribute* const* attrib_lists = getPixelFormatsAttributes(&size);
190    int attributes_num = i % size;
191    const NSOpenGLPixelFormatAttribute* attribs = attrib_lists[attributes_num];
192    int res = 0;
193    while (*attribs) {
194        if (sIsKeyValueAttrib(*attribs)) {
195            if (query == *attribs) {
196                return attribs[1];
197            }
198            attribs += 2;
199        } else {
200            // these are boolean attribs.
201            // their mere presence signals
202            // that the query should return true.
203            if (query == *attribs) {
204                return 1;
205            }
206            attribs++;
207        }
208    }
209    // return 0 if key not found---takes care of all boolean attribs,
210    // and we depend on returning alpha=0 to make the default
211    // config for GLSurfaceView happy.
212    return 0;
213}
214
215void* nsCreateContext(void* format,void* share){
216    NSOpenGLPixelFormat* frmt = (NSOpenGLPixelFormat*)format;
217    return [[EmuGLContext alloc] initWithFormat:frmt shareContext:share];
218}
219
220void  nsPBufferMakeCurrent(void* context,void* nativePBuffer,int level){
221    EmuGLContext* ctx = (EmuGLContext *)context;
222    NSOpenGLPixelBuffer* pbuff = (NSOpenGLPixelBuffer *)nativePBuffer;
223    if(ctx == nil){
224        [NSOpenGLContext clearCurrentContext];
225    } else {
226        if(pbuff != nil){
227            [ctx preBind:1];
228            [ctx setPixelBuffer:pbuff cubeMapFace:0 mipMapLevel:level currentVirtualScreen:0];
229            [ctx makeCurrentContext];
230        } else {
231            // in this case, pbuffers deprecated and disabled.
232            [ctx preBind:0];
233            [ctx makeCurrentContext];
234        }
235    }
236}
237
238void nsWindowMakeCurrent(void* context,void* nativeWin){
239    EmuGLContext* ctx = (EmuGLContext *)context;
240    NSView* win = (NSView *)nativeWin;
241    if(ctx == nil){
242        [NSOpenGLContext clearCurrentContext];
243    } else if (win != nil) {
244        [ctx preBind:0];
245        [ctx setView: win];
246        [ctx makeCurrentContext];
247    }
248}
249
250void nsSwapBuffers(){
251    NSOpenGLContext* ctx = [NSOpenGLContext currentContext];
252    if(ctx != nil){
253        [ctx flushBuffer];
254    }
255}
256
257void nsSwapInterval(int *interval){
258    NSOpenGLContext* ctx = [NSOpenGLContext currentContext];
259    if( ctx != nil){
260        [ctx setValues:interval forParameter:NSOpenGLCPSwapInterval];
261    }
262}
263
264
265void nsDestroyContext(void* context){
266    EmuGLContext *ctx = (EmuGLContext*)context;
267    if(ctx != nil){
268        [ctx release];
269    }
270}
271
272
273void* nsCreatePBuffer(GLenum target,GLenum format,int maxMip,int width,int height){
274    return [[NSOpenGLPixelBuffer alloc] initWithTextureTarget:target
275                                        textureInternalFormat:format
276                                        textureMaxMipMapLevel:maxMip
277                                        pixelsWide:width pixelsHigh:height];
278
279}
280
281void nsDestroyPBuffer(void* pbuffer){
282    NSOpenGLPixelBuffer *pbuf = (NSOpenGLPixelBuffer*)pbuffer;
283    if(pbuf != nil){
284        [pbuf release];
285    }
286}
287
288bool nsGetWinDims(void* win,unsigned int* width,unsigned int* height){
289    NSView* view = (NSView*)win;
290    if(view != nil){
291        NSRect rect = [view bounds];
292        *width  = rect.size.width;
293        *height = rect.size.height;
294        return true;
295    }
296    return false;
297}
298
299bool  nsCheckColor(void* win,int colorSize){
300    NSView* view = (NSView*)win;
301   if(view != nil){
302       NSWindow* wnd = [view window];
303       if(wnd != nil){
304           NSWindowDepth limit = [wnd depthLimit];
305           NSWindowDepth defaultLimit = [NSWindow defaultDepthLimit];
306
307           int depth = (limit != 0) ? NSBitsPerPixelFromDepth(limit):
308                                      NSBitsPerPixelFromDepth(defaultLimit);
309           return depth >= colorSize;
310
311       }
312   }
313   return false;
314
315}
316