VirtualBox

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

最後變更 在這個檔案從29447是 29447,由 vboxsync 提交於 15 年 前

crOpenGL: macos some debug output

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

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