VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa_helper.m@ 24483

Last change on this file since 24483 was 24483, checked in by vboxsync, 15 years ago

crOpenGL-OSX: make sure a valid context is set

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 43.4 KB
Line 
1/** @file
2 *
3 * VirtualBox OpenGL Cocoa Window System Helper implementation
4 */
5
6/*
7 * Copyright (C) 2009 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22#include "renderspu_cocoa_helper.h"
23
24#include "chromium.h" /* For the visual bits of chromium */
25
26#include <iprt/thread.h>
27#include <iprt/string.h>
28
29/* Debug macros */
30#define FBO 1 /* Disable this to see how the output is without the FBO in the middle of the processing chain. */
31//#define SHOW_WINDOW_BACKGROUND 1 /* Define this to see the window background even if the window is clipped */
32//#define DEBUG_VERBOSE /* Define this could get some debug info about the messages flow. */
33
34#ifdef DEBUG_poetzsch
35#define DEBUG_MSG(text) \
36 printf text
37#else
38#define DEBUG_MSG(text) \
39 do {} while (0)
40#endif
41
42#ifdef DEBUG_VERBOSE
43#define DEBUG_MSG_1(text) \
44 DEBUG_MSG(text)
45#else
46#define DEBUG_MSG_1(text) \
47 do {} while (0)
48#endif
49
50#ifdef DEBUG_poetzsch
51#define CHECK_GL_ERROR()\
52 do \
53 { \
54 checkGLError(__FILE__, __LINE__); \
55 }while (0);
56
57 static void checkGLError(char *file, int line)
58 {
59 GLenum g = glGetError();
60 if (g != GL_NO_ERROR)
61 {
62 char *errStr;
63 switch (g)
64 {
65 case GL_INVALID_ENUM: errStr = RTStrDup("GL_INVALID_ENUM"); break;
66 case GL_INVALID_VALUE: errStr = RTStrDup("GL_INVALID_VALUE"); break;
67 case GL_INVALID_OPERATION: errStr = RTStrDup("GL_INVALID_OPERATION"); break;
68 case GL_STACK_OVERFLOW: errStr = RTStrDup("GL_STACK_OVERFLOW"); break;
69 case GL_STACK_UNDERFLOW: errStr = RTStrDup("GL_STACK_UNDERFLOW"); break;
70 case GL_OUT_OF_MEMORY: errStr = RTStrDup("GL_OUT_OF_MEMORY"); break;
71 case GL_TABLE_TOO_LARGE: errStr = RTStrDup("GL_TABLE_TOO_LARGE"); break;
72 default: errStr = RTStrDup("UNKOWN"); break;
73 }
74 DEBUG_MSG(("%s:%d: glError %d (%s)\n", file, line, g, errStr));
75 RTMemFree(errStr);
76 }
77 }
78#else
79#define CHECK_GL_ERROR()\
80 do {} while (0)
81#endif
82
83#define GL_SAVE_STATE \
84do \
85{ \
86 glPushAttrib(GL_ALL_ATTRIB_BITS); \
87 glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS); \
88 glMatrixMode(GL_PROJECTION); \
89 glPushMatrix(); \
90 glMatrixMode(GL_TEXTURE); \
91 glPushMatrix(); \
92 glMatrixMode(GL_COLOR); \
93 glPushMatrix(); \
94 glMatrixMode(GL_MODELVIEW); \
95 glPushMatrix(); \
96} \
97while(0);
98
99#define GL_RESTORE_STATE \
100do \
101{ \
102 glMatrixMode(GL_MODELVIEW); \
103 glPopMatrix(); \
104 glMatrixMode(GL_COLOR); \
105 glPopMatrix(); \
106 glMatrixMode(GL_TEXTURE); \
107 glPopMatrix(); \
108 glMatrixMode(GL_PROJECTION); \
109 glPopMatrix(); \
110 glPopClientAttrib(); \
111 glPopAttrib(); \
112} \
113while(0);
114
115/* Custom OpenGL context class. This implementation doesn't allow to set a view
116 * to the context, but save the view for later use. Also it saves a copy of the
117 * pixel format used to create that context for later use. */
118@interface OverlayOpenGLContext: NSOpenGLContext
119{
120@private
121 NSOpenGLPixelFormat *m_pPixelFormat;
122 NSView *m_pView;
123}
124- (NSOpenGLPixelFormat*)openGLPixelFormat;
125@end
126
127@class DockOverlayView;
128
129/* The custom view class. This is the main class of the cocoa OpenGL
130 * implementation. It manages an frame buffer object for the rendering of the
131 * guest applications. The guest applications render in this frame buffer which
132 * is bind to an OpenGL texture. To display the guest content, an secondary
133 * shared OpenGL context of the main OpenGL context is created. The secondary
134 * context is marked as non opaque & the texture is displayed on an object
135 * which is composed out of the several visible region rectangles. */
136@interface OverlayView: NSView
137{
138@private
139 NSView *m_pParentView;
140
141 NSOpenGLContext *m_pGLCtx;
142 NSOpenGLContext *m_pSharedGLCtx;
143 RTTHREAD mThread;
144
145 /* FBO handling */
146 GLuint m_FBOId;
147 GLuint m_FBOTexId;
148 NSSize m_FBOTexSize;
149 GLuint m_FBODepthStencilPackedId;
150
151 /* The corresponding dock tile view of this OpenGL view & all helper
152 * members. */
153 DockOverlayView *m_DockTileView;
154 GLuint m_FBOThumbId;
155 GLuint m_FBOThumbTexId;
156 GLfloat m_FBOThumbScaleX;
157 GLfloat m_FBOThumbScaleY;
158
159 /* For clipping */
160 GLint m_cClipRects;
161 GLint *m_paClipRects;
162
163 /* Position/Size tracking */
164 NSPoint m_Pos;
165 NSSize m_Size;
166
167 /* This is necessary for clipping on the root window */
168 NSPoint m_RootShift;
169}
170- (id)initWithFrame:(NSRect)frame thread:(RTTHREAD)aThread parentView:(NSView*)pParentView;
171- (void)setGLCtx:(NSOpenGLContext*)pCtx;
172- (NSOpenGLContext*)glCtx;
173
174- (void)setPos:(NSPoint)pos;
175- (NSPoint)pos;
176- (void)setSize:(NSSize)size;
177- (NSSize)size;
178- (void)updateViewport;
179- (void)reshape;
180
181- (void)createFBO;
182- (void)deleteFBO;
183
184- (void)updateFBO;
185- (void)makeCurrentFBO;
186- (void)swapFBO;
187- (void)flushFBO;
188- (void)finishFBO;
189- (void)bindFBO;
190- (void)renderFBOToView;
191
192- (void)clearVisibleRegions;
193- (void)setVisibleRegions:(GLint)cRects paRects:(GLint*)paRects;
194
195- (NSView*)dockTileScreen;
196- (void)reshapeDockTile;
197@end
198
199/* Helper view. This view is added as a sub view of the parent view to track
200 * main window changes. Whenever the main window is changed (which happens on
201 * fullscreen/seamless entry/exit) the overlay window is informed & can add
202 * them self as a child window again. */
203@class OverlayWindow;
204@interface OverlayHelperView: NSView
205{
206@private
207 OverlayWindow *m_pOverlayWindow;
208}
209-(id)initWithOverlayWindow:(OverlayWindow*)pOverlayWindow;
210@end
211
212/* Custom window class. This is the overlay window which contains our custom
213 * NSView. Its a direct child of the Qt Main window. It marks its background
214 * transparent & non opaque to make clipping possible. It also disable mouse
215 * events and handle frame change events of the parent view. */
216@interface OverlayWindow: NSWindow
217{
218@private
219 NSView *m_pParentView;
220 OverlayView *m_pOverlayView;
221 OverlayHelperView *m_pOverlayHelperView;
222 NSThread *m_Thread;
223}
224- (id)initWithParentView:(NSView*)pParentView overlayView:(OverlayView*)pOverlayView;
225- (void)parentWindowFrameChanged:(NSNotification *)note;
226- (void)parentWindowChanged:(NSWindow*)pWindow;
227@end
228
229@interface DockOverlayView: NSView
230{
231 NSBitmapImageRep *m_ThumbBitmap;
232 NSImage *m_ThumbImage;
233 NSLock *m_Lock;
234}
235- (void)dealloc;
236- (void)cleanup;
237- (void)lock;
238- (void)unlock;
239- (void)setFrame:(NSRect)frame;
240- (void)drawRect:(NSRect)aRect;
241- (NSBitmapImageRep*)thumbBitmap;
242- (NSImage*)thumbImage;
243@end
244
245@implementation DockOverlayView
246- (id)init
247{
248 self = [super init];
249
250 if (self)
251 {
252 /* We need a lock cause the thumb image could be accessed from the main
253 * thread when someone is calling display on the dock tile & from the
254 * OpenGL thread when the thumbnail is updated. */
255 m_Lock = [[NSLock alloc] init];
256 }
257
258 return self;
259}
260
261- (void)dealloc
262{
263 [self cleanup];
264 [m_Lock release];
265
266 [super dealloc];
267}
268
269- (void)cleanup
270{
271 if (m_ThumbImage != nil)
272 {
273 [m_ThumbImage release];
274 m_ThumbImage = nil;
275 }
276 if (m_ThumbBitmap != nil)
277 {
278 [m_ThumbBitmap release];
279 m_ThumbBitmap = nil;
280 }
281}
282
283- (void)lock
284{
285 [m_Lock lock];
286}
287
288- (void)unlock
289{
290 [m_Lock unlock];
291}
292
293- (void)setFrame:(NSRect)frame
294{
295 [super setFrame:frame];
296
297 [self lock];
298 [self cleanup];
299
300 /* Create a buffer for our thumbnail image. Its in the size of this view. */
301 m_ThumbBitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
302 pixelsWide:frame.size.width
303 pixelsHigh:frame.size.height
304 bitsPerSample:8
305 samplesPerPixel:4
306 hasAlpha:YES
307 isPlanar:NO
308 colorSpaceName:NSDeviceRGBColorSpace
309 bytesPerRow:frame.size.width * 4
310 bitsPerPixel:8 * 4];
311 m_ThumbImage = [[NSImage alloc] initWithSize:[m_ThumbBitmap size]];
312 [m_ThumbImage addRepresentation:m_ThumbBitmap];
313 [self unlock];
314}
315
316- (BOOL)isFlipped
317{
318 return YES;
319}
320
321- (void)drawRect:(NSRect)aRect
322{
323 [self lock];
324#ifdef SHOW_WINDOW_BACKGROUND
325 [[NSColor colorWithCalibratedRed:1.0 green:0.0 blue:0.0 alpha:0.7] set];
326 NSRect frame = [self frame];
327 [NSBezierPath fillRect:NSMakeRect(0, 0, frame.size.width, frame.size.height)];
328#endif /* SHOW_WINDOW_BACKGROUND */
329 if (m_ThumbImage != nil)
330 [m_ThumbImage drawAtPoint:NSMakePoint(0, 0) fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
331 [self unlock];
332}
333
334- (NSBitmapImageRep*)thumbBitmap
335{
336 return m_ThumbBitmap;
337}
338
339- (NSImage*)thumbImage
340{
341 return m_ThumbImage;
342}
343@end
344
345/********************************************************************************
346*
347* OverlayOpenGLContext class implementation
348*
349********************************************************************************/
350@implementation OverlayOpenGLContext
351
352-(id)initWithFormat:(NSOpenGLPixelFormat*)format shareContext:(NSOpenGLContext*)share
353{
354 m_pPixelFormat = NULL;
355 m_pView = NULL;
356
357 self = [super initWithFormat:format shareContext:share];
358 if (self)
359 m_pPixelFormat = format;
360
361 return self;
362}
363
364- (void)dealloc
365{
366 DEBUG_MSG(("Dealloc context %X\n", (uint)self));
367
368 [m_pPixelFormat release];
369
370 [super dealloc];
371}
372
373-(void)setView:(NSView*)view
374{
375#ifdef FBO
376 m_pView = view;;
377#else
378 [super setView: view];
379#endif
380}
381
382-(NSView*)view
383{
384#ifdef FBO
385 return m_pView;
386#else
387 return [super view];
388#endif
389}
390
391-(void)clearDrawable
392{
393 m_pView = NULL;;
394 [super clearDrawable];
395}
396
397-(NSOpenGLPixelFormat*)openGLPixelFormat
398{
399 return m_pPixelFormat;
400}
401
402@end;
403
404/********************************************************************************
405*
406* OverlayHelperView class implementation
407*
408********************************************************************************/
409@implementation OverlayHelperView
410
411-(id)initWithOverlayWindow:(OverlayWindow*)pOverlayWindow
412{
413 self = [super initWithFrame:NSZeroRect];
414
415 m_pOverlayWindow = pOverlayWindow;
416
417 return self;
418}
419
420-(void)viewDidMoveToWindow
421{
422 [m_pOverlayWindow parentWindowChanged:[self window]];
423}
424
425@end
426
427/********************************************************************************
428*
429* OverlayWindow class implementation
430*
431********************************************************************************/
432@implementation OverlayWindow
433
434- (id)initWithParentView:(NSView*)pParentView overlayView:(OverlayView*)pOverlayView
435{
436 if(self = [super initWithContentRect:NSZeroRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO])
437 {
438 m_pParentView = pParentView;
439 m_pOverlayView = pOverlayView;
440 m_Thread = [NSThread currentThread];
441
442 m_pOverlayHelperView = [[OverlayHelperView alloc] initWithOverlayWindow:self];
443 /* Add the helper view as a child of the parent view to get notifications */
444 [pParentView addSubview:m_pOverlayHelperView];
445
446 /* Make sure this window is transparent */
447#ifdef SHOW_WINDOW_BACKGROUND
448 /* For debugging */
449 [self setBackgroundColor:[NSColor colorWithCalibratedRed:1.0 green:0.0 blue:0.0 alpha:0.7]];
450#else
451 [self setBackgroundColor:[NSColor clearColor]];
452#endif
453 [self setOpaque:NO];
454 [self setAlphaValue:.999];
455 /* Disable mouse events for this window */
456 [self setIgnoresMouseEvents:YES];
457
458 NSWindow *pParentWin = [m_pParentView window];
459
460 /* Initial set the position to the parents view top/left (Compiz fix). */
461 [self setFrameOrigin:
462 [pParentWin convertBaseToScreen:
463 [m_pParentView convertPoint:NSZeroPoint toView:nil]]];
464
465 /* Set the overlay view as our content view */
466 [self setContentView:m_pOverlayView];
467
468 /* Add ourself as a child to the parent views window. Note: this has to
469 * be done last so that everything else is setup in
470 * parentWindowChanged. */
471 [pParentWin addChildWindow:self ordered:NSWindowAbove];
472 }
473 return self;
474}
475
476- (void)dealloc
477{
478 DEBUG_MSG(("Dealloc window %X\n", (uint)self));
479
480 [[NSNotificationCenter defaultCenter] removeObserver:self];
481
482 [m_pOverlayHelperView removeFromSuperview];
483 [m_pOverlayHelperView release];
484
485 [super dealloc];
486}
487
488- (void)parentWindowFrameChanged:(NSNotification*)pNote
489{
490 /* Reposition this window with the help of the OverlayView. Perform the
491 * call in the OpenGL thread. */
492// [m_pOverlayView performSelector:@selector(reshape) onThread:m_Thread withObject:nil waitUntilDone:YES];
493 [m_pOverlayView reshape];
494}
495
496- (void)parentWindowChanged:(NSWindow*)pWindow
497{
498 [[NSNotificationCenter defaultCenter] removeObserver:self];
499 if(pWindow != nil)
500 {
501 /* Ask to get notifications when our parent window frame changes. */
502 [[NSNotificationCenter defaultCenter]
503 addObserver:self
504 selector:@selector(parentWindowFrameChanged:)
505 name:NSWindowDidResizeNotification
506 object:pWindow];
507 /* Add us self as child window */
508 [pWindow addChildWindow:self ordered:NSWindowAbove];
509 /* Reshape the overlay view after a short waiting time to let the main
510 * window resize itself properly. */
511// [m_pOverlayView performSelector:@selector(reshape) withObject:nil afterDelay:0.2];
512// [NSTimer scheduledTimerWithTimeInterval:0.2 target:m_pOverlayView selector:@selector(reshape) userInfo:nil repeats:NO];
513 [m_pOverlayView reshape];
514
515 }
516}
517
518@end
519
520/********************************************************************************
521*
522* OverlayView class implementation
523*
524********************************************************************************/
525@implementation OverlayView
526
527- (id)initWithFrame:(NSRect)frame thread:(RTTHREAD)aThread parentView:(NSView*)pParentView
528{
529 m_pParentView = pParentView;
530 /* Make some reasonable defaults */
531 m_pGLCtx = NULL;
532 m_pSharedGLCtx = NULL;
533 mThread = aThread;
534 m_FBOId = 0;
535 m_FBOTexId = 0;
536 m_FBOTexSize = NSZeroSize;
537 m_FBODepthStencilPackedId = 0;
538 m_cClipRects = 0;
539 m_paClipRects = NULL;
540 m_Pos = NSZeroPoint;
541 m_Size = NSZeroSize;
542 m_RootShift = NSZeroPoint;
543
544 DEBUG_MSG(("Init view %X (%X)\n", (uint)self, (uint)mThread));
545
546 self = [super initWithFrame:frame];
547
548 return self;
549}
550
551- (void)dealloc
552{
553 DEBUG_MSG(("Dealloc view %X\n", (uint)self));
554
555 [self deleteFBO];
556
557 if (m_pGLCtx)
558 {
559 if ([m_pGLCtx view] == self)
560 [m_pGLCtx clearDrawable];
561 }
562 if (m_pSharedGLCtx)
563 {
564 if ([m_pSharedGLCtx view] == self)
565 [m_pSharedGLCtx clearDrawable];
566
567 [m_pSharedGLCtx release];
568 }
569
570 [self clearVisibleRegions];
571
572 [super dealloc];
573}
574
575- (void)drawRect:(NSRect)aRect
576{
577// NSGraphicsContext*pC = [NSGraphicsContext currentContext];
578// [[NSColor blueColor] set];
579// NSBezierPath *p = [[NSBezierPath alloc] bezierPathWithOvalInRect:[self frame]];
580// [p fill];
581// [[NSColor greenColor] set];
582// [p stroke];
583// if ([self lockFocusIfCanDraw])
584// {
585// [self renderFBOToView];
586// [self unlockFocus];
587// }
588}
589
590- (void)setGLCtx:(NSOpenGLContext*)pCtx
591{
592 m_pGLCtx = pCtx;
593}
594
595- (NSOpenGLContext*)glCtx
596{
597 return m_pGLCtx;
598}
599
600- (void)setPos:(NSPoint)pos
601{
602 m_Pos = pos;
603 [self reshape];
604}
605
606- (NSPoint)pos
607{
608 return m_Pos;
609}
610
611- (void)setSize:(NSSize)size
612{
613 m_Size = size;
614 [self reshape];
615 [self updateFBO];
616}
617
618- (NSSize)size
619{
620 return m_Size;
621}
622
623- (void)updateViewport
624{
625 if (m_pSharedGLCtx)
626 {
627 /* Update the viewport for our OpenGL view */
628 [m_pSharedGLCtx makeCurrentContext];
629 [m_pSharedGLCtx update];
630
631 NSRect r = [self frame];
632 /* Setup all matrices */
633 glMatrixMode(GL_PROJECTION);
634 glLoadIdentity();
635 glViewport(0, 0, r.size.width, r.size.height);
636 glOrtho(0, r.size.width, 0, r.size.height, -1, 1);
637 glMatrixMode(GL_TEXTURE);
638 glLoadIdentity();
639 glTranslatef(0.0f, m_RootShift.y, 0.0f);
640 glMatrixMode(GL_MODELVIEW);
641 glLoadIdentity();
642 glTranslatef(-m_RootShift.x, 0.0f, 0.0f);
643
644 /* Clear background to transparent */
645 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
646
647 glEnable(GL_TEXTURE_RECTANGLE_ARB);
648 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_FBOTexId);
649
650 [m_pGLCtx makeCurrentContext];
651 }
652}
653
654- (void)reshape
655{
656 /* Getting the right screen coordinates of the parents frame is a little bit
657 * complicated. */
658 NSRect parentFrame = [m_pParentView frame];
659 NSPoint parentPos = [[m_pParentView window] convertBaseToScreen:[[m_pParentView superview] convertPointToBase:NSMakePoint(parentFrame.origin.x, parentFrame.origin.y + parentFrame.size.height)]];
660 parentFrame.origin.x = parentPos.x;
661 parentFrame.origin.y = parentPos.y;
662
663 /* Calculate the new screen coordinates of the overlay window. */
664 NSPoint childPos = NSMakePoint(m_Pos.x, m_Pos.y + m_Size.height);
665 childPos = [[m_pParentView window] convertBaseToScreen:[[m_pParentView superview] convertPointToBase:childPos]];
666
667 /* Make a frame out of it. */
668 NSRect childFrame = NSMakeRect(childPos.x, childPos.y, m_Size.width, m_Size.height);
669
670 /* We have to make sure that the overlay window will not be displayed out
671 * of the parent window. So intersect both frames & use the result as the new
672 * frame for the window. */
673 NSRect newFrame = NSIntersectionRect(parentFrame, childFrame);
674
675 /* Later we have to correct the texture position in the case the window is
676 * out of the parents window frame. So save the shift values for later use. */
677 if (parentFrame.origin.x > childFrame.origin.x)
678 m_RootShift.x = parentFrame.origin.x - childFrame.origin.x;
679 else
680 m_RootShift.x = 0;
681 if (parentFrame.origin.y > childFrame.origin.y)
682 m_RootShift.y = parentFrame.origin.y - childFrame.origin.y;
683 else
684 m_RootShift.y = 0;
685
686// NSScrollView *pScrollView = [[[m_pParentView window] contentView] enclosingScrollView];
687// if (pScrollView)
688// {
689// NSRect scrollRect = [pScrollView documentVisibleRect];
690// NSRect scrollRect = [m_pParentView visibleRect];
691// printf ("sc rect: %d %d %d %d\n", (int) scrollRect.origin.x,(int) scrollRect.origin.y,(int) scrollRect.size.width,(int) scrollRect.size.height);
692// NSRect b = [[m_pParentView superview] bounds];
693// printf ("bound rect: %d %d %d %d\n", (int) b.origin.x,(int) b.origin.y,(int) b.size.width,(int) b.size.height);
694// newFrame.origin.x += scrollRect.origin.x;
695// newFrame.origin.y += scrollRect.origin.y;
696// }
697
698 /* Set the new frame. */
699 [[self window] setFrame:newFrame display:YES];
700
701 /* Inform the dock tile view as well */
702 [self reshapeDockTile];
703
704 /* Make sure the context is updated according */
705 [self updateViewport];
706}
707
708- (void)createFBO
709{
710 [self deleteFBO];
711
712 GL_SAVE_STATE;
713
714 /* If not previously setup generate IDs for FBO and its associated texture. */
715 if (!m_FBOId)
716 {
717 /* Make sure the framebuffer extension is supported */
718 const GLubyte* strExt;
719 GLboolean isFBO;
720 /* Get the extension name string. It is a space-delimited list of the
721 * OpenGL extensions that are supported by the current renderer. */
722 strExt = glGetString(GL_EXTENSIONS);
723 isFBO = gluCheckExtension((const GLubyte*)"GL_EXT_framebuffer_object", strExt);
724 if (!isFBO)
725 {
726 DEBUG_MSG(("Your system does not support framebuffer extension\n"));
727 }
728
729 /* Create FBO object */
730 glGenFramebuffersEXT(1, &m_FBOId);
731 /* & the texture as well the depth/stencil render buffer */
732 glGenTextures(1, &m_FBOTexId);
733 DEBUG_MSG_1(("Create FBO %d %d\n", m_FBOId, m_FBOTexId));
734
735 glGenRenderbuffersEXT(1, &m_FBODepthStencilPackedId);
736 }
737
738 m_FBOTexSize = m_Size;
739 /* Bind to FBO */
740 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FBOId);
741
742 glEnable(GL_TEXTURE_RECTANGLE_ARB);
743
744 GLfloat imageAspectRatio = m_FBOTexSize.width / m_FBOTexSize.height;
745
746 /* Sanity check against maximum OpenGL texture size. If bigger adjust to
747 * maximum possible size while maintain the aspect ratio. */
748 GLint maxTexSize;
749 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize);
750// maxTexSize = 150;
751 GLint filter = GL_NEAREST;
752 if (m_FBOTexSize.width > maxTexSize || m_FBOTexSize.height > maxTexSize)
753 {
754 filter = GL_NICEST;
755 if (imageAspectRatio > 1)
756 {
757 m_FBOTexSize.width = maxTexSize;
758 m_FBOTexSize.height = maxTexSize / imageAspectRatio;
759 }
760 else
761 {
762 m_FBOTexSize.width = maxTexSize * imageAspectRatio;
763 m_FBOTexSize.height = maxTexSize;
764 }
765 }
766
767 /* Initialize FBO Texture */
768 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_FBOTexId);
769 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, filter);
770 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, filter);
771 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
772 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
773
774 /* The GPUs like the GL_BGRA / GL_UNSIGNED_INT_8_8_8_8_REV combination
775 * others are also valid, but might incur a costly software translation. */
776 glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, m_FBOTexSize.width, m_FBOTexSize.height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
777
778 /* Now attach texture to the FBO as its color destination */
779 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, m_FBOTexId, 0);
780
781 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_FBODepthStencilPackedId);
782 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT, m_FBOTexSize.width, m_FBOTexSize.height);
783 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_FBODepthStencilPackedId);
784 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_FBODepthStencilPackedId);
785
786 /* Make sure the FBO was created succesfully. */
787 if (GL_FRAMEBUFFER_COMPLETE_EXT != glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT))
788 DEBUG_MSG(("Framebuffer Object creation or update failed!\n"));
789
790 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
791 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
792
793 /* Is there a dock tile preview enabled in the GUI? If so setup a
794 * additional thumbnail view for the dock tile. */
795 NSView *dockScreen = [self dockTileScreen];
796 if (dockScreen)
797 {
798 if (!m_FBOThumbId)
799 {
800 glGenFramebuffersEXT(1, &m_FBOThumbId);
801 glGenTextures(1, &m_FBOThumbTexId);
802 }
803
804 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FBOThumbId);
805 /* Initialize FBO Texture */
806 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_FBOThumbTexId);
807 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NICEST);
808 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NICEST);
809 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
810 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
811
812 /* The GPUs like the GL_BGRA / GL_UNSIGNED_INT_8_8_8_8_REV combination
813 * others are also valid, but might incur a costly software translation. */
814 glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, m_FBOTexSize.width * m_FBOThumbScaleX, m_FBOTexSize.height * m_FBOThumbScaleY, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
815
816 /* Now attach texture to the FBO as its color destination */
817 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, m_FBOThumbTexId, 0);
818
819 /* Make sure the FBO was created succesfully. */
820 if (GL_FRAMEBUFFER_COMPLETE_EXT != glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT))
821 DEBUG_MSG(("Framebuffer Thumb Object creation or update failed!\n"));
822
823 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
824 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
825
826 m_DockTileView = [[DockOverlayView alloc] init];
827 [self reshapeDockTile];
828 [dockScreen addSubview:m_DockTileView];
829 }
830
831 /* Initialize with one big visual region over the full size */
832 [self clearVisibleRegions];
833 m_cClipRects = 1;
834 m_paClipRects = (GLint*)RTMemAlloc(sizeof(GLint) * 4);
835 m_paClipRects[0] = 0;
836 m_paClipRects[1] = 0;
837 m_paClipRects[2] = m_FBOTexSize.width;
838 m_paClipRects[3] = m_FBOTexSize.height;
839
840 GL_RESTORE_STATE;
841}
842
843- (void)deleteFBO
844{
845 if ([NSOpenGLContext currentContext] != nil)
846 {
847 GL_SAVE_STATE;
848
849 if (m_FBODepthStencilPackedId > 0)
850 {
851 glDeleteRenderbuffersEXT(1, &m_FBODepthStencilPackedId);
852 m_FBODepthStencilPackedId = 0;
853 }
854 if (m_FBOTexId > 0)
855 {
856 glEnable(GL_TEXTURE_RECTANGLE_ARB);
857 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
858 glDeleteTextures(1, &m_FBOTexId);
859 m_FBOTexId = 0;
860 }
861 if (m_FBOId > 0)
862 {
863 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
864
865 glDeleteFramebuffersEXT(1, &m_FBOId);
866 m_FBOId = 0;
867 }
868
869 GL_RESTORE_STATE;
870 }
871 if (m_DockTileView != nil)
872 {
873 [m_DockTileView removeFromSuperview];
874 [m_DockTileView release];
875 m_DockTileView = nil;
876 }
877}
878
879- (void)updateFBO
880{
881 [self makeCurrentFBO];
882
883 if (m_pGLCtx)
884 {
885#ifdef FBO
886 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
887 [self createFBO];
888 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FBOId);
889#endif
890 [m_pGLCtx update];
891 }
892}
893
894- (void)makeCurrentFBO
895{
896 DEBUG_MSG_1(("MakeCurrent called %X\n", self));
897
898#ifdef FBO
899 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FBOId);
900#endif
901 if (m_pGLCtx)
902 {
903 if ([m_pGLCtx view] != self)
904 {
905 /* We change the active view, so flush first */
906 glFlush();
907 [m_pGLCtx setView: self];
908 CHECK_GL_ERROR();
909 }
910// if ([NSOpenGLContext currentContext] != m_pGLCtx)
911 {
912 [m_pGLCtx makeCurrentContext];
913 CHECK_GL_ERROR();
914// [m_pGLCtx update];
915 }
916 }
917#ifdef FBO
918 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FBOId);
919#endif
920}
921
922- (void)swapFBO
923{
924 DEBUG_MSG_1(("SwapCurrent called %X\n", self));
925
926#ifdef FBO
927 GLint tmpFB;
928 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &tmpFB);
929 DEBUG_MSG_1(("Swap GetINT %d\n", tmpFB));
930 [m_pGLCtx flushBuffer];
931// glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
932 if (tmpFB == m_FBOId)
933 {
934 if ([self lockFocusIfCanDraw])
935 {
936 [self renderFBOToView];
937 [self unlockFocus];
938 }
939 }
940// glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FBOId);
941#else
942 [m_pGLCtx flushBuffer];
943#endif
944}
945
946- (void)flushFBO
947{
948 GLint tmpFB;
949 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &tmpFB);
950 glFlush();
951// glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
952 DEBUG_MSG_1 (("Flusj GetINT %d\n", tmpFB));
953 if (tmpFB == m_FBOId)
954 {
955 if ([self lockFocusIfCanDraw])
956 {
957 [self renderFBOToView];
958 [self unlockFocus];
959 }
960 }
961// glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FBOId);
962}
963
964- (void)finishFBO
965{
966 GLint tmpFB;
967 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &tmpFB);
968 glFinish();
969 // glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
970 DEBUG_MSG_1 (("Finish GetINT %d\n", tmpFB));
971 if (tmpFB == m_FBOId)
972 {
973 if ([self lockFocusIfCanDraw])
974 {
975 [self renderFBOToView];
976 [self unlockFocus];
977 }
978 }
979// glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FBOId);
980}
981
982- (void)bindFBO
983{
984 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FBOId);
985}
986
987- (void)renderFBOToView
988{
989 if (!m_pSharedGLCtx)
990 {
991 /* Create a shared context out of the main context. Use the same pixel format. */
992 m_pSharedGLCtx = [[NSOpenGLContext alloc] initWithFormat:[(OverlayOpenGLContext*)m_pGLCtx openGLPixelFormat] shareContext:m_pGLCtx];
993
994 /* Set the new context as non opaque */
995 GLint opaque = 0;
996 [m_pSharedGLCtx setValues:&opaque forParameter:NSOpenGLCPSurfaceOpacity];
997 /* Only swap on screen refresh */
998// GLint swap = 1;
999// [m_pSharedGLCtx setValues:&swap forParameter:NSOpenGLCPSwapInterval];
1000 /* Set this view as the drawable for the new context */
1001 [m_pSharedGLCtx setView: self];
1002 [self updateViewport];
1003 }
1004
1005 if (m_pSharedGLCtx)
1006 {
1007 NSRect r = [self frame];
1008
1009 if (m_FBOTexId > 0)
1010 {
1011 [m_pSharedGLCtx makeCurrentContext];
1012
1013 if (m_FBOThumbTexId > 0 &&
1014 [m_DockTileView thumbBitmap] != nil)
1015 {
1016#if 0
1017 /* todo: check this for optimization */
1018 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, myTextureName);
1019 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE,
1020 GL_STORAGE_SHARED_APPLE);
1021 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
1022 glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
1023 sizex, sizey, 0, GL_BGRA,
1024 GL_UNSIGNED_INT_8_8_8_8_REV, myImagePtr);
1025 glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB,
1026 0, 0, 0, 0, 0, image_width, image_height);
1027 glFlush();
1028 // Do other work processing here, using a double or triple buffer
1029 glGetTexImage(GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGRA,
1030 GL_UNSIGNED_INT_8_8_8_8_REV, pixels);
1031#endif
1032
1033 GL_SAVE_STATE;
1034 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FBOThumbId);
1035
1036 /* We like to read from the primary color buffer */
1037 glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
1038
1039 NSRect rr = [m_DockTileView frame];
1040
1041 /* Setup all matrices */
1042 glMatrixMode(GL_PROJECTION);
1043 glLoadIdentity();
1044 glViewport(0, 0, rr.size.width, rr.size.height);
1045 glOrtho(0, rr.size.width, 0, rr.size.height, -1, 1);
1046 glScalef(m_FBOThumbScaleX, m_FBOThumbScaleY, 1.0f);
1047 glMatrixMode(GL_TEXTURE);
1048 glLoadIdentity();
1049 glTranslatef(0.0f, m_RootShift.y, 0.0f);
1050 glMatrixMode(GL_MODELVIEW);
1051 glLoadIdentity();
1052
1053 /* Clear background to transparent */
1054 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
1055 glClear(GL_COLOR_BUFFER_BIT);
1056
1057 glEnable(GL_TEXTURE_RECTANGLE_ARB);
1058 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_FBOTexId);
1059 GLint i;
1060 for (i = 0; i < m_cClipRects; ++i)
1061 {
1062 GLint x1 = m_paClipRects[4*i];
1063 GLint y1 = (r.size.height - m_paClipRects[4*i+1]);
1064 GLint x2 = m_paClipRects[4*i+2];
1065 GLint y2 = (r.size.height - m_paClipRects[4*i+3]);
1066 glBegin(GL_QUADS);
1067 {
1068 glTexCoord2i(x1, y1); glVertex2i(x1, y1);
1069 glTexCoord2i(x1, y2); glVertex2i(x1, y2);
1070 glTexCoord2i(x2, y2); glVertex2i(x2, y2);
1071 glTexCoord2i(x2, y1); glVertex2i(x2, y1);
1072 }
1073 glEnd();
1074 }
1075 glFinish();
1076
1077 /* Here the magic of reading the FBO content in our own buffer
1078 * happens. We have to lock this access, in the case the dock
1079 * is updated currently. */
1080 [m_DockTileView lock];
1081 glReadPixels(0, 0, rr.size.width, rr.size.height,
1082 GL_RGBA,
1083 GL_UNSIGNED_BYTE,
1084 [[m_DockTileView thumbBitmap] bitmapData]);
1085 [m_DockTileView unlock];
1086
1087 NSDockTile *pDT = [[NSApplication sharedApplication] dockTile];
1088
1089 /* Send a display message to the dock tile in the main thread */
1090 [[[NSApplication sharedApplication] dockTile] performSelectorOnMainThread:@selector(display) withObject:nil waitUntilDone:NO];
1091
1092 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1093 GL_RESTORE_STATE;
1094 }
1095
1096 /* Clear background to transparent */
1097 glClear(GL_COLOR_BUFFER_BIT);
1098
1099 /* Blit the content of the FBO to the screen. todo: check for
1100 * optimization with display lists. */
1101 GLint i;
1102 for (i = 0; i < m_cClipRects; ++i)
1103 {
1104 GLint x1 = m_paClipRects[4*i];
1105 GLint y1 = r.size.height - m_paClipRects[4*i+1];
1106 GLint x2 = m_paClipRects[4*i+2];
1107 GLint y2 = r.size.height - m_paClipRects[4*i+3];
1108 glBegin(GL_QUADS);
1109 {
1110 glTexCoord2i(x1, y1); glVertex2i(x1, y1);
1111 glTexCoord2i(x1, y2); glVertex2i(x1, y2);
1112 glTexCoord2i(x2, y2); glVertex2i(x2, y2);
1113 glTexCoord2i(x2, y1); glVertex2i(x2, y1);
1114 }
1115 glEnd();
1116 }
1117 [m_pSharedGLCtx flushBuffer];
1118 [m_pGLCtx makeCurrentContext];
1119 }
1120 }
1121}
1122
1123- (void)clearVisibleRegions
1124{
1125 if(m_paClipRects)
1126 {
1127 RTMemFree(m_paClipRects);
1128 m_paClipRects = NULL;
1129 }
1130 m_cClipRects = 0;
1131}
1132
1133- (void)setVisibleRegions:(GLint)cRects paRects:(GLint*)paRects
1134{
1135 DEBUG_MSG_1(("New region recieved\n"));
1136
1137 [self clearVisibleRegions];
1138
1139 if (cRects>0)
1140 {
1141 m_paClipRects = (GLint*)RTMemAlloc(sizeof(GLint) * 4 * cRects);
1142 m_cClipRects = cRects;
1143 memcpy(m_paClipRects, paRects, sizeof(GLint) * 4 * cRects);
1144 }
1145}
1146
1147- (NSView*)dockTileScreen
1148{
1149 NSView *contentView = [[[NSApplication sharedApplication] dockTile] contentView];
1150 NSView *screenContent = nil;
1151 if ([contentView respondsToSelector:@selector(screenContent)])
1152 screenContent = [contentView performSelector:@selector(screenContent)];
1153 return screenContent;
1154}
1155
1156- (void)reshapeDockTile
1157{
1158 NSRect dockFrame = [[self dockTileScreen] frame];
1159 NSRect parentFrame = [m_pParentView frame];
1160
1161 m_FBOThumbScaleX = (float)dockFrame.size.width / parentFrame.size.width;
1162 m_FBOThumbScaleY = (float)dockFrame.size.height / parentFrame.size.height;
1163 NSRect newFrame = NSMakeRect ((int)(m_Pos.x * m_FBOThumbScaleX), (int)(dockFrame.size.height - (m_Pos.y + m_Size.height - m_RootShift.y) * m_FBOThumbScaleY), (int)(m_Size.width * m_FBOThumbScaleX), (int)(m_Size.height * m_FBOThumbScaleY));
1164// NSRect newFrame = NSMakeRect ((int)roundf(m_Pos.x * m_FBOThumbScaleX), (int)roundf(dockFrame.size.height - (m_Pos.y + m_Size.height) * m_FBOThumbScaleY), (int)roundf(m_Size.width * m_FBOThumbScaleX), (int)roundf(m_Size.height * m_FBOThumbScaleY));
1165// NSRect newFrame = NSMakeRect ((m_Pos.x * m_FBOThumbScaleX), (dockFrame.size.height - (m_Pos.y + m_Size.height) * m_FBOThumbScaleY), (m_Size.width * m_FBOThumbScaleX), (m_Size.height * m_FBOThumbScaleY));
1166// printf ("%f %f %f %f - %f %f\n", newFrame.origin.x, newFrame.origin.y, newFrame.size.width, newFrame.size.height, m_Size.height, m_FBOThumbScaleY);
1167 [m_DockTileView setFrame: newFrame];
1168}
1169
1170@end
1171
1172/********************************************************************************
1173*
1174* OpenGL context management
1175*
1176********************************************************************************/
1177void cocoaGLCtxCreate(NativeGLCtxRef *ppCtx, GLbitfield fVisParams)
1178{
1179 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1180
1181 NSOpenGLPixelFormatAttribute attribs[24] =
1182 {
1183 NSOpenGLPFAWindow,
1184 NSOpenGLPFAAccelerated,
1185 NSOpenGLPFAColorSize, (NSOpenGLPixelFormatAttribute)24
1186 };
1187
1188 int i = 4;
1189 if (fVisParams & CR_ALPHA_BIT)
1190 {
1191 DEBUG_MSG(("CR_ALPHA_BIT requested\n"));
1192 attribs[i++] = NSOpenGLPFAAlphaSize;
1193 attribs[i++] = 8;
1194 }
1195 if (fVisParams & CR_DEPTH_BIT)
1196 {
1197 DEBUG_MSG(("CR_DEPTH_BIT requested\n"));
1198 attribs[i++] = NSOpenGLPFADepthSize;
1199 attribs[i++] = 24;
1200 }
1201 if (fVisParams & CR_STENCIL_BIT)
1202 {
1203 DEBUG_MSG(("CR_STENCIL_BIT requested\n"));
1204 attribs[i++] = NSOpenGLPFAStencilSize;
1205 attribs[i++] = 8;
1206 }
1207 if (fVisParams & CR_ACCUM_BIT)
1208 {
1209 DEBUG_MSG(("CR_ACCUM_BIT requested\n"));
1210 attribs[i++] = NSOpenGLPFAAccumSize;
1211 if (fVisParams & CR_ALPHA_BIT)
1212 attribs[i++] = 32;
1213 else
1214 attribs[i++] = 24;
1215 }
1216 if (fVisParams & CR_MULTISAMPLE_BIT)
1217 {
1218 DEBUG_MSG(("CR_MULTISAMPLE_BIT requested\n"));
1219 attribs[i++] = NSOpenGLPFASampleBuffers;
1220 attribs[i++] = 1;
1221 attribs[i++] = NSOpenGLPFASamples;
1222 attribs[i++] = 4;
1223 }
1224 if (fVisParams & CR_DOUBLE_BIT)
1225 {
1226 DEBUG_MSG(("CR_DOUBLE_BIT requested\n"));
1227 attribs[i++] = NSOpenGLPFADoubleBuffer;
1228 }
1229 if (fVisParams & CR_STEREO_BIT)
1230 {
1231 DEBUG_MSG(("CR_DOUBLE_BIT requested\n"));
1232 attribs[i++] = NSOpenGLPFAStereo;
1233 }
1234
1235 /* Mark the end */
1236 attribs[i++] = 0;
1237
1238 /* Choose a pixel format */
1239 NSOpenGLPixelFormat* pFmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
1240
1241 if (pFmt)
1242 {
1243 *ppCtx = [[OverlayOpenGLContext alloc] initWithFormat:pFmt shareContext:nil];
1244
1245 /* Enable multi threaded OpenGL engine */
1246// CGLContextObj cglCtx = [*ppCtx CGLContextObj];
1247// CGLError err = CGLEnable(cglCtx, kCGLCEMPEngine);
1248// if (err != kCGLNoError)
1249// printf ("Couldn't enable MT OpenGL engine!\n");
1250
1251 DEBUG_MSG(("New context %X\n", (uint)*ppCtx));
1252 }
1253
1254 [pPool release];
1255}
1256
1257void cocoaGLCtxDestroy(NativeGLCtxRef pCtx)
1258{
1259 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1260
1261// [pCtx release];
1262
1263 [pPool release];
1264}
1265
1266/********************************************************************************
1267*
1268* View management
1269*
1270********************************************************************************/
1271void cocoaViewCreate(NativeViewRef *ppView, NativeViewRef pParentView, GLbitfield fVisParams)
1272{
1273 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1274
1275 /* Create our worker view */
1276 OverlayView* pView = [[OverlayView alloc] initWithFrame:NSZeroRect thread:RTThreadSelf() parentView:pParentView];
1277
1278 if (pView)
1279 {
1280 /* We need a real window as container for the view */
1281 [[OverlayWindow alloc] initWithParentView:pParentView overlayView:pView];
1282 /* Return the freshly created overlay view */
1283 *ppView = pView;
1284 }
1285
1286 [pPool release];
1287}
1288
1289void cocoaViewDestroy(NativeViewRef pView)
1290{
1291 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1292
1293 /* Hide the view early */
1294 [pView setHidden: YES];
1295
1296 NSWindow *win = [pView window];
1297 [[NSNotificationCenter defaultCenter] removeObserver:win];
1298 [win setContentView: nil];
1299 [[win parentWindow] removeChildWindow: win];
1300 int b = [win retainCount];
1301 for (; b > 1; --b)
1302 [win release];
1303
1304 /* There seems to be a bug in the performSelector method which is called in
1305 * parentWindowChanged above. The object is retained but not released. This
1306 * results in an unbalanced reference count, which is here manually
1307 * decremented. */
1308 int a = [pView retainCount];
1309 for (; a > 1; --a)
1310 [pView release];
1311
1312 [pPool release];
1313}
1314
1315void cocoaViewShow(NativeViewRef pView, GLboolean fShowIt)
1316{
1317 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1318
1319 [pView setHidden: fShowIt==GL_TRUE?NO:YES];
1320
1321 [pPool release];
1322}
1323
1324void cocoaViewDisplay(NativeViewRef pView)
1325{
1326 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1327
1328 [(OverlayView*)pView swapFBO];
1329
1330 [pPool release];
1331
1332}
1333
1334void cocoaViewSetPosition(NativeViewRef pView, NativeViewRef pParentView, int x, int y)
1335{
1336 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1337
1338 [(OverlayView*)pView setPos:NSMakePoint(x, y)];
1339
1340 [pPool release];
1341}
1342
1343void cocoaViewSetSize(NativeViewRef pView, int w, int h)
1344{
1345 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1346
1347 [(OverlayView*)pView setSize:NSMakeSize(w, h)];
1348
1349 [pPool release];
1350}
1351
1352void cocoaViewGetGeometry(NativeViewRef pView, int *pX, int *pY, int *pW, int *pH)
1353{
1354 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1355
1356 NSRect frame = [[pView window] frame];
1357 *pX = frame.origin.x;
1358 *pY = frame.origin.y;
1359 *pW = frame.size.width;
1360 *pH = frame.size.height;
1361
1362 [pPool release];
1363}
1364
1365void cocoaViewMakeCurrentContext(NativeViewRef pView, NativeGLCtxRef pCtx)
1366{
1367 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1368
1369 if ([NSOpenGLContext currentContext] != pCtx)
1370 [pCtx makeCurrentContext];
1371
1372 [(OverlayView*)pView setGLCtx:pCtx];
1373 [(OverlayView*)pView makeCurrentFBO];
1374
1375 [pPool release];
1376}
1377
1378void cocoaViewSetVisibleRegion(NativeViewRef pView, GLint cRects, GLint* paRects)
1379{
1380 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1381
1382 [(OverlayView*)pView setVisibleRegions:cRects paRects:paRects];
1383
1384 [pPool release];
1385}
1386
1387/********************************************************************************
1388*
1389* Additional OpenGL wrapper
1390*
1391********************************************************************************/
1392void cocoaFlush()
1393{
1394 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1395
1396// glFlush();
1397// return;
1398
1399 DEBUG_MSG_1(("glFlush called\n"));
1400
1401#ifdef FBO
1402# if 0
1403 NSOpenGLContext *pCtx = [NSOpenGLContext currentContext];
1404 if (pCtx)
1405 {
1406 NSView *pView = [pCtx view];
1407 if (pView)
1408 {
1409 if ([pView respondsToSelector:@selector(flushFBO)])
1410 [pView performSelector:@selector(flushFBO)];
1411 }
1412 }
1413# endif
1414#else
1415 glFlush();
1416#endif
1417
1418 [pPool release];
1419}
1420
1421void cocoaFinish()
1422{
1423 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1424
1425 DEBUG_MSG_1(("glFinish called\n"));
1426
1427#ifdef FBO
1428 NSOpenGLContext *pCtx = [NSOpenGLContext currentContext];
1429 if (pCtx)
1430 {
1431 NSView *pView = [pCtx view];
1432 if (pView)
1433 {
1434 if ([pView respondsToSelector:@selector(finishFBO)])
1435 [pView performSelector:@selector(finishFBO)];
1436 }
1437 }
1438#else
1439 glFinish();
1440#endif
1441
1442 [pPool release];
1443}
1444
1445void cocoaBindFramebufferEXT(GLenum target, GLuint framebuffer)
1446{
1447 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1448
1449 DEBUG_MSG_1(("glRenderspuBindFramebufferEXT called %d\n", framebuffer));
1450
1451#ifdef FBO
1452 if (framebuffer != 0)
1453 glBindFramebufferEXT(target, framebuffer);
1454 else
1455 {
1456 NSOpenGLContext *pCtx = [NSOpenGLContext currentContext];
1457 if (pCtx)
1458 {
1459 NSView *pView = [pCtx view];
1460 if (pView)
1461 {
1462 if ([pView respondsToSelector:@selector(bindFBO)])
1463 [pView performSelector:@selector(bindFBO)];
1464 }
1465 }
1466 }
1467#else
1468 glBindFramebufferEXT(target, framebuffer);
1469#endif
1470
1471 [pPool release];
1472}
1473
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette