VirtualBox

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

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

crOpenGL-OSX: better fix for r54567

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 43.5 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 if([NSOpenGLContext currentContext] != 0)
900 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FBOId);
901#endif
902 if (m_pGLCtx)
903 {
904 if ([m_pGLCtx view] != self)
905 {
906 /* We change the active view, so flush first */
907 if([NSOpenGLContext currentContext] != 0)
908 glFlush();
909 [m_pGLCtx setView: self];
910 CHECK_GL_ERROR();
911 }
912// if ([NSOpenGLContext currentContext] != m_pGLCtx)
913 {
914 [m_pGLCtx makeCurrentContext];
915 CHECK_GL_ERROR();
916// [m_pGLCtx update];
917 }
918 }
919#ifdef FBO
920 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FBOId);
921#endif
922}
923
924- (void)swapFBO
925{
926 DEBUG_MSG_1(("SwapCurrent called %X\n", self));
927
928#ifdef FBO
929 GLint tmpFB;
930 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &tmpFB);
931 DEBUG_MSG_1(("Swap GetINT %d\n", tmpFB));
932 [m_pGLCtx flushBuffer];
933// glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
934 if (tmpFB == m_FBOId)
935 {
936 if ([self lockFocusIfCanDraw])
937 {
938 [self renderFBOToView];
939 [self unlockFocus];
940 }
941 }
942// glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FBOId);
943#else
944 [m_pGLCtx flushBuffer];
945#endif
946}
947
948- (void)flushFBO
949{
950 GLint tmpFB;
951 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &tmpFB);
952 glFlush();
953// glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
954 DEBUG_MSG_1 (("Flusj GetINT %d\n", tmpFB));
955 if (tmpFB == m_FBOId)
956 {
957 if ([self lockFocusIfCanDraw])
958 {
959 [self renderFBOToView];
960 [self unlockFocus];
961 }
962 }
963// glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FBOId);
964}
965
966- (void)finishFBO
967{
968 GLint tmpFB;
969 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &tmpFB);
970 glFinish();
971 // glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
972 DEBUG_MSG_1 (("Finish GetINT %d\n", tmpFB));
973 if (tmpFB == m_FBOId)
974 {
975 if ([self lockFocusIfCanDraw])
976 {
977 [self renderFBOToView];
978 [self unlockFocus];
979 }
980 }
981// glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FBOId);
982}
983
984- (void)bindFBO
985{
986 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FBOId);
987}
988
989- (void)renderFBOToView
990{
991 if (!m_pSharedGLCtx)
992 {
993 /* Create a shared context out of the main context. Use the same pixel format. */
994 m_pSharedGLCtx = [[NSOpenGLContext alloc] initWithFormat:[(OverlayOpenGLContext*)m_pGLCtx openGLPixelFormat] shareContext:m_pGLCtx];
995
996 /* Set the new context as non opaque */
997 GLint opaque = 0;
998 [m_pSharedGLCtx setValues:&opaque forParameter:NSOpenGLCPSurfaceOpacity];
999 /* Only swap on screen refresh */
1000// GLint swap = 1;
1001// [m_pSharedGLCtx setValues:&swap forParameter:NSOpenGLCPSwapInterval];
1002 /* Set this view as the drawable for the new context */
1003 [m_pSharedGLCtx setView: self];
1004 [self updateViewport];
1005 }
1006
1007 if (m_pSharedGLCtx)
1008 {
1009 NSRect r = [self frame];
1010
1011 if (m_FBOTexId > 0)
1012 {
1013 [m_pSharedGLCtx makeCurrentContext];
1014
1015 if (m_FBOThumbTexId > 0 &&
1016 [m_DockTileView thumbBitmap] != nil)
1017 {
1018#if 0
1019 /* todo: check this for optimization */
1020 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, myTextureName);
1021 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE,
1022 GL_STORAGE_SHARED_APPLE);
1023 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
1024 glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
1025 sizex, sizey, 0, GL_BGRA,
1026 GL_UNSIGNED_INT_8_8_8_8_REV, myImagePtr);
1027 glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB,
1028 0, 0, 0, 0, 0, image_width, image_height);
1029 glFlush();
1030 // Do other work processing here, using a double or triple buffer
1031 glGetTexImage(GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGRA,
1032 GL_UNSIGNED_INT_8_8_8_8_REV, pixels);
1033#endif
1034
1035 GL_SAVE_STATE;
1036 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FBOThumbId);
1037
1038 /* We like to read from the primary color buffer */
1039 glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
1040
1041 NSRect rr = [m_DockTileView frame];
1042
1043 /* Setup all matrices */
1044 glMatrixMode(GL_PROJECTION);
1045 glLoadIdentity();
1046 glViewport(0, 0, rr.size.width, rr.size.height);
1047 glOrtho(0, rr.size.width, 0, rr.size.height, -1, 1);
1048 glScalef(m_FBOThumbScaleX, m_FBOThumbScaleY, 1.0f);
1049 glMatrixMode(GL_TEXTURE);
1050 glLoadIdentity();
1051 glTranslatef(0.0f, m_RootShift.y, 0.0f);
1052 glMatrixMode(GL_MODELVIEW);
1053 glLoadIdentity();
1054
1055 /* Clear background to transparent */
1056 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
1057 glClear(GL_COLOR_BUFFER_BIT);
1058
1059 glEnable(GL_TEXTURE_RECTANGLE_ARB);
1060 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_FBOTexId);
1061 GLint i;
1062 for (i = 0; i < m_cClipRects; ++i)
1063 {
1064 GLint x1 = m_paClipRects[4*i];
1065 GLint y1 = (r.size.height - m_paClipRects[4*i+1]);
1066 GLint x2 = m_paClipRects[4*i+2];
1067 GLint y2 = (r.size.height - m_paClipRects[4*i+3]);
1068 glBegin(GL_QUADS);
1069 {
1070 glTexCoord2i(x1, y1); glVertex2i(x1, y1);
1071 glTexCoord2i(x1, y2); glVertex2i(x1, y2);
1072 glTexCoord2i(x2, y2); glVertex2i(x2, y2);
1073 glTexCoord2i(x2, y1); glVertex2i(x2, y1);
1074 }
1075 glEnd();
1076 }
1077 glFinish();
1078
1079 /* Here the magic of reading the FBO content in our own buffer
1080 * happens. We have to lock this access, in the case the dock
1081 * is updated currently. */
1082 [m_DockTileView lock];
1083 glReadPixels(0, 0, rr.size.width, rr.size.height,
1084 GL_RGBA,
1085 GL_UNSIGNED_BYTE,
1086 [[m_DockTileView thumbBitmap] bitmapData]);
1087 [m_DockTileView unlock];
1088
1089 NSDockTile *pDT = [[NSApplication sharedApplication] dockTile];
1090
1091 /* Send a display message to the dock tile in the main thread */
1092 [[[NSApplication sharedApplication] dockTile] performSelectorOnMainThread:@selector(display) withObject:nil waitUntilDone:NO];
1093
1094 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1095 GL_RESTORE_STATE;
1096 }
1097
1098 /* Clear background to transparent */
1099 glClear(GL_COLOR_BUFFER_BIT);
1100
1101 /* Blit the content of the FBO to the screen. todo: check for
1102 * optimization with display lists. */
1103 GLint i;
1104 for (i = 0; i < m_cClipRects; ++i)
1105 {
1106 GLint x1 = m_paClipRects[4*i];
1107 GLint y1 = r.size.height - m_paClipRects[4*i+1];
1108 GLint x2 = m_paClipRects[4*i+2];
1109 GLint y2 = r.size.height - m_paClipRects[4*i+3];
1110 glBegin(GL_QUADS);
1111 {
1112 glTexCoord2i(x1, y1); glVertex2i(x1, y1);
1113 glTexCoord2i(x1, y2); glVertex2i(x1, y2);
1114 glTexCoord2i(x2, y2); glVertex2i(x2, y2);
1115 glTexCoord2i(x2, y1); glVertex2i(x2, y1);
1116 }
1117 glEnd();
1118 }
1119 [m_pSharedGLCtx flushBuffer];
1120 [m_pGLCtx makeCurrentContext];
1121 }
1122 }
1123}
1124
1125- (void)clearVisibleRegions
1126{
1127 if(m_paClipRects)
1128 {
1129 RTMemFree(m_paClipRects);
1130 m_paClipRects = NULL;
1131 }
1132 m_cClipRects = 0;
1133}
1134
1135- (void)setVisibleRegions:(GLint)cRects paRects:(GLint*)paRects
1136{
1137 DEBUG_MSG_1(("New region recieved\n"));
1138
1139 [self clearVisibleRegions];
1140
1141 if (cRects>0)
1142 {
1143 m_paClipRects = (GLint*)RTMemAlloc(sizeof(GLint) * 4 * cRects);
1144 m_cClipRects = cRects;
1145 memcpy(m_paClipRects, paRects, sizeof(GLint) * 4 * cRects);
1146 }
1147}
1148
1149- (NSView*)dockTileScreen
1150{
1151 NSView *contentView = [[[NSApplication sharedApplication] dockTile] contentView];
1152 NSView *screenContent = nil;
1153 if ([contentView respondsToSelector:@selector(screenContent)])
1154 screenContent = [contentView performSelector:@selector(screenContent)];
1155 return screenContent;
1156}
1157
1158- (void)reshapeDockTile
1159{
1160 NSRect dockFrame = [[self dockTileScreen] frame];
1161 NSRect parentFrame = [m_pParentView frame];
1162
1163 m_FBOThumbScaleX = (float)dockFrame.size.width / parentFrame.size.width;
1164 m_FBOThumbScaleY = (float)dockFrame.size.height / parentFrame.size.height;
1165 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));
1166// 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));
1167// 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));
1168// 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);
1169 [m_DockTileView setFrame: newFrame];
1170}
1171
1172@end
1173
1174/********************************************************************************
1175*
1176* OpenGL context management
1177*
1178********************************************************************************/
1179void cocoaGLCtxCreate(NativeGLCtxRef *ppCtx, GLbitfield fVisParams)
1180{
1181 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1182
1183 NSOpenGLPixelFormatAttribute attribs[24] =
1184 {
1185 NSOpenGLPFAWindow,
1186 NSOpenGLPFAAccelerated,
1187 NSOpenGLPFAColorSize, (NSOpenGLPixelFormatAttribute)24
1188 };
1189
1190 int i = 4;
1191 if (fVisParams & CR_ALPHA_BIT)
1192 {
1193 DEBUG_MSG(("CR_ALPHA_BIT requested\n"));
1194 attribs[i++] = NSOpenGLPFAAlphaSize;
1195 attribs[i++] = 8;
1196 }
1197 if (fVisParams & CR_DEPTH_BIT)
1198 {
1199 DEBUG_MSG(("CR_DEPTH_BIT requested\n"));
1200 attribs[i++] = NSOpenGLPFADepthSize;
1201 attribs[i++] = 24;
1202 }
1203 if (fVisParams & CR_STENCIL_BIT)
1204 {
1205 DEBUG_MSG(("CR_STENCIL_BIT requested\n"));
1206 attribs[i++] = NSOpenGLPFAStencilSize;
1207 attribs[i++] = 8;
1208 }
1209 if (fVisParams & CR_ACCUM_BIT)
1210 {
1211 DEBUG_MSG(("CR_ACCUM_BIT requested\n"));
1212 attribs[i++] = NSOpenGLPFAAccumSize;
1213 if (fVisParams & CR_ALPHA_BIT)
1214 attribs[i++] = 32;
1215 else
1216 attribs[i++] = 24;
1217 }
1218 if (fVisParams & CR_MULTISAMPLE_BIT)
1219 {
1220 DEBUG_MSG(("CR_MULTISAMPLE_BIT requested\n"));
1221 attribs[i++] = NSOpenGLPFASampleBuffers;
1222 attribs[i++] = 1;
1223 attribs[i++] = NSOpenGLPFASamples;
1224 attribs[i++] = 4;
1225 }
1226 if (fVisParams & CR_DOUBLE_BIT)
1227 {
1228 DEBUG_MSG(("CR_DOUBLE_BIT requested\n"));
1229 attribs[i++] = NSOpenGLPFADoubleBuffer;
1230 }
1231 if (fVisParams & CR_STEREO_BIT)
1232 {
1233 DEBUG_MSG(("CR_DOUBLE_BIT requested\n"));
1234 attribs[i++] = NSOpenGLPFAStereo;
1235 }
1236
1237 /* Mark the end */
1238 attribs[i++] = 0;
1239
1240 /* Choose a pixel format */
1241 NSOpenGLPixelFormat* pFmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
1242
1243 if (pFmt)
1244 {
1245 *ppCtx = [[OverlayOpenGLContext alloc] initWithFormat:pFmt shareContext:nil];
1246
1247 /* Enable multi threaded OpenGL engine */
1248// CGLContextObj cglCtx = [*ppCtx CGLContextObj];
1249// CGLError err = CGLEnable(cglCtx, kCGLCEMPEngine);
1250// if (err != kCGLNoError)
1251// printf ("Couldn't enable MT OpenGL engine!\n");
1252
1253 DEBUG_MSG(("New context %X\n", (uint)*ppCtx));
1254 }
1255
1256 [pPool release];
1257}
1258
1259void cocoaGLCtxDestroy(NativeGLCtxRef pCtx)
1260{
1261 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1262
1263// [pCtx release];
1264
1265 [pPool release];
1266}
1267
1268/********************************************************************************
1269*
1270* View management
1271*
1272********************************************************************************/
1273void cocoaViewCreate(NativeViewRef *ppView, NativeViewRef pParentView, GLbitfield fVisParams)
1274{
1275 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1276
1277 /* Create our worker view */
1278 OverlayView* pView = [[OverlayView alloc] initWithFrame:NSZeroRect thread:RTThreadSelf() parentView:pParentView];
1279
1280 if (pView)
1281 {
1282 /* We need a real window as container for the view */
1283 [[OverlayWindow alloc] initWithParentView:pParentView overlayView:pView];
1284 /* Return the freshly created overlay view */
1285 *ppView = pView;
1286 }
1287
1288 [pPool release];
1289}
1290
1291void cocoaViewDestroy(NativeViewRef pView)
1292{
1293 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1294
1295 /* Hide the view early */
1296 [pView setHidden: YES];
1297
1298 NSWindow *win = [pView window];
1299 [[NSNotificationCenter defaultCenter] removeObserver:win];
1300 [win setContentView: nil];
1301 [[win parentWindow] removeChildWindow: win];
1302 int b = [win retainCount];
1303 for (; b > 1; --b)
1304 [win release];
1305
1306 /* There seems to be a bug in the performSelector method which is called in
1307 * parentWindowChanged above. The object is retained but not released. This
1308 * results in an unbalanced reference count, which is here manually
1309 * decremented. */
1310 int a = [pView retainCount];
1311 for (; a > 1; --a)
1312 [pView release];
1313
1314 [pPool release];
1315}
1316
1317void cocoaViewShow(NativeViewRef pView, GLboolean fShowIt)
1318{
1319 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1320
1321 [pView setHidden: fShowIt==GL_TRUE?NO:YES];
1322
1323 [pPool release];
1324}
1325
1326void cocoaViewDisplay(NativeViewRef pView)
1327{
1328 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1329
1330 [(OverlayView*)pView swapFBO];
1331
1332 [pPool release];
1333
1334}
1335
1336void cocoaViewSetPosition(NativeViewRef pView, NativeViewRef pParentView, int x, int y)
1337{
1338 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1339
1340 [(OverlayView*)pView setPos:NSMakePoint(x, y)];
1341
1342 [pPool release];
1343}
1344
1345void cocoaViewSetSize(NativeViewRef pView, int w, int h)
1346{
1347 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1348
1349 [(OverlayView*)pView setSize:NSMakeSize(w, h)];
1350
1351 [pPool release];
1352}
1353
1354void cocoaViewGetGeometry(NativeViewRef pView, int *pX, int *pY, int *pW, int *pH)
1355{
1356 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1357
1358 NSRect frame = [[pView window] frame];
1359 *pX = frame.origin.x;
1360 *pY = frame.origin.y;
1361 *pW = frame.size.width;
1362 *pH = frame.size.height;
1363
1364 [pPool release];
1365}
1366
1367void cocoaViewMakeCurrentContext(NativeViewRef pView, NativeGLCtxRef pCtx)
1368{
1369 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1370
1371 [(OverlayView*)pView setGLCtx:pCtx];
1372 [(OverlayView*)pView makeCurrentFBO];
1373
1374 [pPool release];
1375}
1376
1377void cocoaViewSetVisibleRegion(NativeViewRef pView, GLint cRects, GLint* paRects)
1378{
1379 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1380
1381 [(OverlayView*)pView setVisibleRegions:cRects paRects:paRects];
1382
1383 [pPool release];
1384}
1385
1386/********************************************************************************
1387*
1388* Additional OpenGL wrapper
1389*
1390********************************************************************************/
1391void cocoaFlush()
1392{
1393 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1394
1395// glFlush();
1396// return;
1397
1398 DEBUG_MSG_1(("glFlush called\n"));
1399
1400#ifdef FBO
1401# if 0
1402 NSOpenGLContext *pCtx = [NSOpenGLContext currentContext];
1403 if (pCtx)
1404 {
1405 NSView *pView = [pCtx view];
1406 if (pView)
1407 {
1408 if ([pView respondsToSelector:@selector(flushFBO)])
1409 [pView performSelector:@selector(flushFBO)];
1410 }
1411 }
1412# endif
1413#else
1414 glFlush();
1415#endif
1416
1417 [pPool release];
1418}
1419
1420void cocoaFinish()
1421{
1422 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1423
1424 DEBUG_MSG_1(("glFinish called\n"));
1425
1426#ifdef FBO
1427 NSOpenGLContext *pCtx = [NSOpenGLContext currentContext];
1428 if (pCtx)
1429 {
1430 NSView *pView = [pCtx view];
1431 if (pView)
1432 {
1433 if ([pView respondsToSelector:@selector(finishFBO)])
1434 [pView performSelector:@selector(finishFBO)];
1435 }
1436 }
1437#else
1438 glFinish();
1439#endif
1440
1441 [pPool release];
1442}
1443
1444void cocoaBindFramebufferEXT(GLenum target, GLuint framebuffer)
1445{
1446 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1447
1448 DEBUG_MSG_1(("glRenderspuBindFramebufferEXT called %d\n", framebuffer));
1449
1450#ifdef FBO
1451 if (framebuffer != 0)
1452 glBindFramebufferEXT(target, framebuffer);
1453 else
1454 {
1455 NSOpenGLContext *pCtx = [NSOpenGLContext currentContext];
1456 if (pCtx)
1457 {
1458 NSView *pView = [pCtx view];
1459 if (pView)
1460 {
1461 if ([pView respondsToSelector:@selector(bindFBO)])
1462 [pView performSelector:@selector(bindFBO)];
1463 }
1464 }
1465 }
1466#else
1467 glBindFramebufferEXT(target, framebuffer);
1468#endif
1469
1470 [pPool release];
1471}
1472
Note: See TracBrowser for help on using the repository browser.

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