VirtualBox

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

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

crOpenGL: fix flickering on osx

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 59.2 KB
 
1/* $Id: renderspu_cocoa_helper.m 51442 2014-05-28 11:09:30Z vboxsync $ */
2/** @file
3 * VirtualBox OpenGL Cocoa Window System Helper Implementation.
4 */
5
6/*
7 * Copyright (C) 2009-2012 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#import <Cocoa/Cocoa.h>
21#undef PVM
22
23#include "chromium.h" /* For the visual bits of chromium */
24
25#include <iprt/thread.h>
26#include <iprt/string.h>
27#include <iprt/mem.h>
28#include <iprt/time.h>
29#include <iprt/assert.h>
30
31#include <cr_vreg.h>
32#include <cr_error.h>
33#include <cr_blitter.h>
34#ifdef VBOX_WITH_CRDUMPER_THUMBNAIL
35# include <cr_pixeldata.h>
36#endif
37
38
39#include "renderspu.h"
40
41/** @page pg_opengl_cocoa OpenGL - Cocoa Window System Helper
42 *
43 * How this works:
44 * In general it is not so easy like on the other platforms, cause Cocoa
45 * doesn't support any clipping of already painted stuff. In Mac OS X there is
46 * the concept of translucent canvas's e.g. windows and there it is just
47 * painted what should be visible to the user. Unfortunately this isn't the
48 * concept of chromium. Therefor I reroute all OpenGL operation from the guest
49 * to a frame buffer object (FBO). This is a OpenGL extension, which is
50 * supported by all OS X versions we support (AFAIC tell). Of course the guest
51 * doesn't know that and we have to make sure that the OpenGL state always is
52 * in the right state to paint into the FBO and not to the front/back buffer.
53 * Several functions below (like cocoaBindFramebufferEXT, cocoaGetIntegerv,
54 * ...) doing this. When a swap or finish is triggered by the guest, the
55 * content (which is already bound to an texture) is painted on the screen
56 * within a separate OpenGL context. This allows the usage of the same
57 * resources (texture ids, buffers ...) but at the same time having an
58 * different internal OpenGL state. Another advantage is that we can paint a
59 * thumbnail of the current output in a much more smaller (GPU accelerated
60 * scale) version on a third context and use glReadPixels to get the actual
61 * data. glReadPixels is a very slow operation, but as we just use a much more
62 * smaller image, we can handle it (anyway this is only done 5 times per
63 * second).
64 *
65 * Other things to know:
66 * - If the guest request double buffering, we have to make sure there are two
67 * buffers. We use the same FBO with 2 color attachments. Also glDrawBuffer
68 * and glReadBuffer is intercepted to make sure it is painted/read to/from
69 * the correct buffers. On swap our buffers are swapped and not the
70 * front/back buffer.
71 * - If the guest request a depth/stencil buffer, a combined render buffer for
72 * this is created.
73 * - If the size of the guest OpenGL window changes, all FBO's, textures, ...
74 * need to be recreated.
75 * - We need to track any changes to the parent window
76 * (create/destroy/move/resize). The various classes like OverlayHelperView,
77 * OverlayWindow, ... are there for.
78 * - The HGCM service runs on a other thread than the Main GUI. Keeps this
79 * always in mind (see e.g. performSelectorOnMainThread in renderFBOToView)
80 * - We make heavy use of late binding. We can not be sure that the GUI (or any
81 * other third party GUI), overwrite our NSOpenGLContext. So we always ask if
82 * this is our own one, before use. Really neat concept of Objective-C/Cocoa
83 * ;)
84 */
85
86/* Debug macros */
87#define FBO 1 /* Disable this to see how the output is without the FBO in the middle of the processing chain. */
88#if 0
89# define CR_RENDER_FORCE_PRESENT_MAIN_THREAD /* force present schedule to main thread */
90# define SHOW_WINDOW_BACKGROUND 1 /* Define this to see the window background even if the window is clipped */
91# define DEBUG_VERBOSE /* Define this to get some debug info about the messages flow. */
92#endif
93
94#ifdef DEBUG_misha
95# define DEBUG_MSG(text) \
96 printf text
97# define DEBUG_WARN(text) do { \
98 crWarning text ; \
99 Assert(0); \
100 } while (0)
101#else
102# define DEBUG_MSG(text) \
103 do {} while (0)
104# define DEBUG_WARN(text) do { \
105 crWarning text ; \
106 } while (0)
107#endif
108
109#ifdef DEBUG_VERBOSE
110# define DEBUG_MSG_1(text) \
111 DEBUG_MSG(text)
112#else
113# define DEBUG_MSG_1(text) \
114 do {} while (0)
115#endif
116
117#ifdef DEBUG_poetzsch
118# define CHECK_GL_ERROR()\
119 do \
120 { \
121 checkGLError(__FILE__, __LINE__); \
122 }while (0);
123
124 static void checkGLError(char *file, int line)
125 {
126 GLenum g = glGetError();
127 if (g != GL_NO_ERROR)
128 {
129 char *errStr;
130 switch (g)
131 {
132 case GL_INVALID_ENUM: errStr = RTStrDup("GL_INVALID_ENUM"); break;
133 case GL_INVALID_VALUE: errStr = RTStrDup("GL_INVALID_VALUE"); break;
134 case GL_INVALID_OPERATION: errStr = RTStrDup("GL_INVALID_OPERATION"); break;
135 case GL_STACK_OVERFLOW: errStr = RTStrDup("GL_STACK_OVERFLOW"); break;
136 case GL_STACK_UNDERFLOW: errStr = RTStrDup("GL_STACK_UNDERFLOW"); break;
137 case GL_OUT_OF_MEMORY: errStr = RTStrDup("GL_OUT_OF_MEMORY"); break;
138 case GL_TABLE_TOO_LARGE: errStr = RTStrDup("GL_TABLE_TOO_LARGE"); break;
139 default: errStr = RTStrDup("UNKNOWN"); break;
140 }
141 DEBUG_MSG(("%s:%d: glError %d (%s)\n", file, line, g, errStr));
142 RTMemFree(errStr);
143 }
144 }
145#else
146# define CHECK_GL_ERROR()\
147 do {} while (0)
148#endif
149
150#define GL_SAVE_STATE \
151 do \
152 { \
153 glPushAttrib(GL_ALL_ATTRIB_BITS); \
154 glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS); \
155 glMatrixMode(GL_PROJECTION); \
156 glPushMatrix(); \
157 glMatrixMode(GL_TEXTURE); \
158 glPushMatrix(); \
159 glMatrixMode(GL_COLOR); \
160 glPushMatrix(); \
161 glMatrixMode(GL_MODELVIEW); \
162 glPushMatrix(); \
163 } \
164 while(0);
165
166#define GL_RESTORE_STATE \
167 do \
168 { \
169 glMatrixMode(GL_MODELVIEW); \
170 glPopMatrix(); \
171 glMatrixMode(GL_COLOR); \
172 glPopMatrix(); \
173 glMatrixMode(GL_TEXTURE); \
174 glPopMatrix(); \
175 glMatrixMode(GL_PROJECTION); \
176 glPopMatrix(); \
177 glPopClientAttrib(); \
178 glPopAttrib(); \
179 } \
180 while(0);
181
182static NSOpenGLContext * vboxCtxGetCurrent()
183{
184 GET_CONTEXT(pCtxInfo);
185 if (pCtxInfo)
186 {
187 Assert(pCtxInfo->context);
188 return pCtxInfo->context;
189 }
190
191 return nil;
192}
193
194static bool vboxCtxSyncCurrentInfo()
195{
196 GET_CONTEXT(pCtxInfo);
197 NSOpenGLContext *pCtx = [NSOpenGLContext currentContext];
198 NSView *pView = pCtx ? [pCtx view] : nil;
199 bool fAdjusted = false;
200 if (pCtxInfo)
201 {
202 WindowInfo *pWinInfo = pCtxInfo->currentWindow;
203 Assert(pWinInfo);
204 if (pCtxInfo->context != pCtx
205 || pWinInfo->window != pView)
206 {
207 renderspu_SystemMakeCurrent(pWinInfo, 0, pCtxInfo);
208 fAdjusted = true;
209 }
210 }
211 else
212 {
213 if (pCtx)
214 {
215 [NSOpenGLContext clearCurrentContext];
216 fAdjusted = true;
217 }
218 }
219
220 return fAdjusted;
221}
222
223typedef struct VBOX_CR_RENDER_CTX_INFO
224{
225 bool fIsValid;
226 NSOpenGLContext *pCtx;
227 NSView *pView;
228} VBOX_CR_RENDER_CTX_INFO, *PVBOX_CR_RENDER_CTX_INFO;
229
230static void vboxCtxEnter(NSOpenGLContext*pCtx, PVBOX_CR_RENDER_CTX_INFO pCtxInfo)
231{
232 NSOpenGLContext *pOldCtx = vboxCtxGetCurrent();
233 NSView *pOldView = (pOldCtx ? [pOldCtx view] : nil);
234 NSView *pView = [pCtx view];
235 bool fNeedCtxSwitch = (pOldCtx != pCtx || pOldView != pView);
236 Assert(pCtx);
237 // Assert(pOldCtx == m_pGLCtx);
238 // Assert(pOldView == self);
239 // Assert(fNeedCtxSwitch);
240 if (fNeedCtxSwitch)
241 {
242 if(pOldCtx != nil)
243 glFlush();
244
245 [pCtx makeCurrentContext];
246
247 pCtxInfo->fIsValid = true;
248 pCtxInfo->pCtx = pOldCtx;
249 pCtxInfo->pView = pView;
250 }
251 else
252 {
253 pCtxInfo->fIsValid = false;
254 }
255}
256
257static void vboxCtxLeave(PVBOX_CR_RENDER_CTX_INFO pCtxInfo)
258{
259 if (pCtxInfo->fIsValid)
260 {
261 NSOpenGLContext *pOldCtx = pCtxInfo->pCtx;
262 NSView *pOldView = pCtxInfo->pView;
263
264 glFlush();
265 if (pOldCtx != nil)
266 {
267 if ([pOldCtx view] != pOldView)
268 {
269 [pOldCtx setView: pOldView];
270 }
271
272 [pOldCtx makeCurrentContext];
273
274#ifdef DEBUG
275 {
276 NSOpenGLContext *pTstOldCtx = [NSOpenGLContext currentContext];
277 NSView *pTstOldView = (pTstOldCtx ? [pTstOldCtx view] : nil);
278 Assert(pTstOldCtx == pOldCtx);
279 Assert(pTstOldView == pOldView);
280 }
281#endif
282 }
283 else
284 {
285 [NSOpenGLContext clearCurrentContext];
286 }
287 }
288}
289
290/** Custom OpenGL context class.
291 *
292 * This implementation doesn't allow to set a view to the
293 * context, but save the view for later use. Also it saves a copy of the
294 * pixel format used to create that context for later use. */
295@interface OverlayOpenGLContext: NSOpenGLContext
296{
297@private
298 NSOpenGLPixelFormat *m_pPixelFormat;
299 NSView *m_pView;
300}
301- (NSOpenGLPixelFormat*)openGLPixelFormat;
302@end
303
304@class DockOverlayView;
305
306/** The custom view class.
307 * This is the main class of the cocoa OpenGL implementation. It
308 * manages an frame buffer object for the rendering of the guest
309 * applications. The guest applications render in this frame buffer which
310 * is bind to an OpenGL texture. To display the guest content, an secondary
311 * shared OpenGL context of the main OpenGL context is created. The secondary
312 * context is marked as non opaque & the texture is displayed on an object
313 * which is composed out of the several visible region rectangles. */
314@interface OverlayView: NSView
315{
316@private
317 NSView *m_pParentView;
318 NSWindow *m_pOverlayWin;
319
320 NSOpenGLContext *m_pGLCtx;
321 NSOpenGLContext *m_pSharedGLCtx;
322 RTTHREAD mThread;
323
324 GLuint m_FBOId;
325
326 /** The corresponding dock tile view of this OpenGL view & all helper
327 * members. */
328 DockOverlayView *m_DockTileView;
329
330 GLfloat m_FBOThumbScaleX;
331 GLfloat m_FBOThumbScaleY;
332 uint64_t m_uiDockUpdateTime;
333
334 /* For clipping */
335 GLint m_cClipRects;
336 GLint *m_paClipRects;
337
338 /* Position/Size tracking */
339 NSPoint m_Pos;
340 NSSize m_Size;
341
342 /** This is necessary for clipping on the root window */
343 NSRect m_RootRect;
344 float m_yInvRootOffset;
345
346 CR_BLITTER *m_pBlitter;
347 WindowInfo *m_pWinInfo;
348 bool m_fNeedViewportUpdate;
349 bool m_fNeedCtxUpdate;
350 bool m_fDataVisible;
351 bool m_fCleanupNeeded;
352 bool m_fEverSized;
353}
354- (id)initWithFrame:(NSRect)frame thread:(RTTHREAD)aThread parentView:(NSView*)pParentView winInfo:(WindowInfo*)pWinInfo;
355- (void)setGLCtx:(NSOpenGLContext*)pCtx;
356- (NSOpenGLContext*)glCtx;
357
358- (void)setParentView: (NSView*)view;
359- (NSView*)parentView;
360- (void)setOverlayWin: (NSWindow*)win;
361- (NSWindow*)overlayWin;
362
363- (void)setPos:(NSPoint)pos;
364- (NSPoint)pos;
365- (bool)isEverSized;
366- (void)setSize:(NSSize)size;
367- (NSSize)size;
368- (void)updateViewportCS;
369- (void)vboxReshapePerform;
370- (void)vboxReshapeOnResizePerform;
371- (void)vboxReshapeOnReparentPerform;
372
373- (void)createDockTile;
374- (void)deleteDockTile;
375
376- (void)makeCurrentFBO;
377- (void)swapFBO;
378- (void)vboxTryDraw;
379- (void)vboxTryDrawUI;
380- (void)vboxPresent:(const VBOXVR_SCR_COMPOSITOR*)pCompositor;
381- (void)vboxPresentCS:(const VBOXVR_SCR_COMPOSITOR*)pCompositor;
382- (void)vboxPresentToDockTileCS:(const VBOXVR_SCR_COMPOSITOR*)pCompositor;
383- (void)vboxPresentToViewCS:(const VBOXVR_SCR_COMPOSITOR*)pCompositor;
384- (void)presentComposition:(const VBOXVR_SCR_COMPOSITOR_ENTRY*)pChangedEntry;
385- (void)vboxBlitterSyncWindow;
386
387- (void)clearVisibleRegions;
388- (void)setVisibleRegions:(GLint)cRects paRects:(const GLint*)paRects;
389- (GLboolean)vboxNeedsEmptyPresent;
390
391- (NSView*)dockTileScreen;
392- (void)reshapeDockTile;
393- (void)cleanupData;
394@end
395
396/** Helper view.
397 *
398 * This view is added as a sub view of the parent view to track
399 * main window changes. Whenever the main window is changed
400 * (which happens on fullscreen/seamless entry/exit) the overlay
401 * window is informed & can add them self as a child window
402 * again. */
403@class OverlayWindow;
404@interface OverlayHelperView: NSView
405{
406@private
407 OverlayWindow *m_pOverlayWindow;
408}
409-(id)initWithOverlayWindow:(OverlayWindow*)pOverlayWindow;
410@end
411
412/** Custom window class.
413 *
414 * This is the overlay window which contains our custom NSView.
415 * Its a direct child of the Qt Main window. It marks its background
416 * transparent & non opaque to make clipping possible. It also disable mouse
417 * events and handle frame change events of the parent view. */
418@interface OverlayWindow: NSWindow
419{
420@private
421 NSView *m_pParentView;
422 OverlayView *m_pOverlayView;
423 OverlayHelperView *m_pOverlayHelperView;
424 NSThread *m_Thread;
425}
426- (id)initWithParentView:(NSView*)pParentView overlayView:(OverlayView*)pOverlayView;
427- (void)parentWindowFrameChanged:(NSNotification *)note;
428- (void)parentWindowChanged:(NSWindow*)pWindow;
429@end
430
431@interface DockOverlayView: NSView
432{
433 NSBitmapImageRep *m_ThumbBitmap;
434 NSImage *m_ThumbImage;
435 NSLock *m_Lock;
436}
437- (void)dealloc;
438- (void)cleanup;
439- (void)lock;
440- (void)unlock;
441- (void)setFrame:(NSRect)frame;
442- (void)drawRect:(NSRect)aRect;
443- (NSBitmapImageRep*)thumbBitmap;
444- (NSImage*)thumbImage;
445@end
446
447@implementation DockOverlayView
448- (id)init
449{
450 self = [super init];
451
452 if (self)
453 {
454 /* We need a lock cause the thumb image could be accessed from the main
455 * thread when someone is calling display on the dock tile & from the
456 * OpenGL thread when the thumbnail is updated. */
457 m_Lock = [[NSLock alloc] init];
458 }
459
460 return self;
461}
462
463- (void)dealloc
464{
465 [self cleanup];
466 [m_Lock release];
467
468 [super dealloc];
469}
470
471- (void)cleanup
472{
473 if (m_ThumbImage != nil)
474 {
475 [m_ThumbImage release];
476 m_ThumbImage = nil;
477 }
478 if (m_ThumbBitmap != nil)
479 {
480 [m_ThumbBitmap release];
481 m_ThumbBitmap = nil;
482 }
483}
484
485- (void)lock
486{
487 [m_Lock lock];
488}
489
490- (void)unlock
491{
492 [m_Lock unlock];
493}
494
495- (void)setFrame:(NSRect)frame
496{
497 [super setFrame:frame];
498
499 [self lock];
500 [self cleanup];
501
502 if ( frame.size.width > 0
503 && frame.size.height > 0)
504 {
505 /* Create a buffer for our thumbnail image. Its in the size of this view. */
506 m_ThumbBitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
507 pixelsWide:frame.size.width
508 pixelsHigh:frame.size.height
509 bitsPerSample:8
510 samplesPerPixel:4
511 hasAlpha:YES
512 isPlanar:NO
513 colorSpaceName:NSDeviceRGBColorSpace
514 bitmapFormat:NSAlphaFirstBitmapFormat
515 bytesPerRow:frame.size.width * 4
516 bitsPerPixel:8 * 4];
517 m_ThumbImage = [[NSImage alloc] initWithSize:[m_ThumbBitmap size]];
518 [m_ThumbImage addRepresentation:m_ThumbBitmap];
519 }
520 [self unlock];
521}
522
523- (BOOL)isFlipped
524{
525 return YES;
526}
527
528- (void)drawRect:(NSRect)aRect
529{
530 NSRect frame;
531
532 [self lock];
533#ifdef SHOW_WINDOW_BACKGROUND
534 [[NSColor colorWithCalibratedRed:1.0 green:0.0 blue:0.0 alpha:0.7] set];
535 frame = [self frame];
536 [NSBezierPath fillRect:NSMakeRect(0, 0, frame.size.width, frame.size.height)];
537#endif /* SHOW_WINDOW_BACKGROUND */
538 if (m_ThumbImage != nil)
539 [m_ThumbImage drawAtPoint:NSMakePoint(0, 0) fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
540 [self unlock];
541}
542
543- (NSBitmapImageRep*)thumbBitmap
544{
545 return m_ThumbBitmap;
546}
547
548- (NSImage*)thumbImage
549{
550 return m_ThumbImage;
551}
552@end
553
554/********************************************************************************
555*
556* OverlayOpenGLContext class implementation
557*
558********************************************************************************/
559@implementation OverlayOpenGLContext
560
561-(id)initWithFormat:(NSOpenGLPixelFormat*)format shareContext:(NSOpenGLContext*)share
562{
563 m_pPixelFormat = NULL;
564 m_pView = NULL;
565
566 self = [super initWithFormat:format shareContext:share];
567 if (self)
568 m_pPixelFormat = format;
569
570 DEBUG_MSG(("OCTX(%p): init OverlayOpenGLContext\n", (void*)self));
571
572 return self;
573}
574
575- (void)dealloc
576{
577 DEBUG_MSG(("OCTX(%p): dealloc OverlayOpenGLContext\n", (void*)self));
578
579 [m_pPixelFormat release];
580
581 [super dealloc];
582}
583
584-(bool)isDoubleBuffer
585{
586 GLint val;
587 [m_pPixelFormat getValues:&val forAttribute:NSOpenGLPFADoubleBuffer forVirtualScreen:0];
588 return val == GL_TRUE ? YES : NO;
589}
590
591-(void)setView:(NSView*)view
592{
593 DEBUG_MSG(("OCTX(%p): setView: new view: %p\n", (void*)self, (void*)view));
594
595#if 1 /* def FBO */
596 m_pView = view;;
597#else
598 [super setView: view];
599#endif
600}
601
602-(NSView*)view
603{
604#if 1 /* def FBO */
605 return m_pView;
606#else
607 return [super view];
608#endif
609}
610
611-(void)clearDrawable
612{
613 DEBUG_MSG(("OCTX(%p): clearDrawable\n", (void*)self));
614
615 m_pView = NULL;;
616 [super clearDrawable];
617}
618
619-(NSOpenGLPixelFormat*)openGLPixelFormat
620{
621 return m_pPixelFormat;
622}
623
624@end
625
626/********************************************************************************
627*
628* OverlayHelperView class implementation
629*
630********************************************************************************/
631@implementation OverlayHelperView
632
633-(id)initWithOverlayWindow:(OverlayWindow*)pOverlayWindow
634{
635 self = [super initWithFrame:NSZeroRect];
636
637 m_pOverlayWindow = pOverlayWindow;
638
639 DEBUG_MSG(("OHVW(%p): init OverlayHelperView\n", (void*)self));
640
641 return self;
642}
643
644-(void)viewDidMoveToWindow
645{
646 DEBUG_MSG(("OHVW(%p): viewDidMoveToWindow: new win: %p\n", (void*)self, (void*)[self window]));
647
648 [m_pOverlayWindow parentWindowChanged:[self window]];
649}
650
651@end
652
653/********************************************************************************
654*
655* OverlayWindow class implementation
656*
657********************************************************************************/
658@implementation OverlayWindow
659
660- (id)initWithParentView:(NSView*)pParentView overlayView:(OverlayView*)pOverlayView
661{
662 NSWindow *pParentWin = nil;
663
664 if((self = [super initWithContentRect:NSZeroRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]))
665 {
666 m_pParentView = pParentView;
667 m_pOverlayView = pOverlayView;
668 m_Thread = [NSThread currentThread];
669
670 [m_pOverlayView setOverlayWin: self];
671
672 m_pOverlayHelperView = [[OverlayHelperView alloc] initWithOverlayWindow:self];
673 /* Add the helper view as a child of the parent view to get notifications */
674 [pParentView addSubview:m_pOverlayHelperView];
675
676 /* Make sure this window is transparent */
677#ifdef SHOW_WINDOW_BACKGROUND
678 /* For debugging */
679 [self setBackgroundColor:[NSColor colorWithCalibratedRed:1.0 green:0.0 blue:0.0 alpha:0.7]];
680#else
681 [self setBackgroundColor:[NSColor clearColor]];
682#endif
683 [self setOpaque:NO];
684 [self setAlphaValue:.999];
685 /* Disable mouse events for this window */
686 [self setIgnoresMouseEvents:YES];
687
688 pParentWin = [m_pParentView window];
689
690 /* Initial set the position to the parents view top/left (Compiz fix). */
691 [self setFrameOrigin:
692 [pParentWin convertBaseToScreen:
693 [m_pParentView convertPoint:NSZeroPoint toView:nil]]];
694
695 /* Set the overlay view as our content view */
696 [self setContentView:m_pOverlayView];
697
698 /* Add ourself as a child to the parent views window. Note: this has to
699 * be done last so that everything else is setup in
700 * parentWindowChanged. */
701 [pParentWin addChildWindow:self ordered:NSWindowAbove];
702 }
703 DEBUG_MSG(("OWIN(%p): init OverlayWindow\n", (void*)self));
704
705 return self;
706}
707
708- (void)dealloc
709{
710 DEBUG_MSG(("OWIN(%p): dealloc OverlayWindow\n", (void*)self));
711
712 [[NSNotificationCenter defaultCenter] removeObserver:self];
713
714 [m_pOverlayHelperView removeFromSuperview];
715 [m_pOverlayHelperView release];
716
717 [super dealloc];
718}
719
720- (void)parentWindowFrameChanged:(NSNotification*)pNote
721{
722 DEBUG_MSG(("OWIN(%p): parentWindowFrameChanged\n", (void*)self));
723
724 /* Reposition this window with the help of the OverlayView. Perform the
725 * call in the OpenGL thread. */
726 /*
727 [m_pOverlayView performSelector:@selector(vboxReshapePerform) onThread:m_Thread withObject:nil waitUntilDone:YES];
728 */
729
730 if ([m_pOverlayView isEverSized])
731 {
732 if([NSThread isMainThread])
733 [m_pOverlayView vboxReshapePerform];
734 else
735 [self performSelectorOnMainThread:@selector(vboxReshapePerform) withObject:nil waitUntilDone:NO];
736 }
737}
738
739- (void)parentWindowChanged:(NSWindow*)pWindow
740{
741 DEBUG_MSG(("OWIN(%p): parentWindowChanged\n", (void*)self));
742
743 [[NSNotificationCenter defaultCenter] removeObserver:self];
744
745 if(pWindow != nil)
746 {
747 /* Ask to get notifications when our parent window frame changes. */
748 [[NSNotificationCenter defaultCenter]
749 addObserver:self
750 selector:@selector(parentWindowFrameChanged:)
751 name:NSWindowDidResizeNotification
752 object:pWindow];
753 /* Add us self as child window */
754 [pWindow addChildWindow:self ordered:NSWindowAbove];
755 /* Reshape the overlay view after a short waiting time to let the main
756 * window resize itself properly. */
757 /*
758 [m_pOverlayView performSelector:@selector(vboxReshapePerform) withObject:nil afterDelay:0.2];
759 [NSTimer scheduledTimerWithTimeInterval:0.2 target:m_pOverlayView selector:@selector(vboxReshapePerform) userInfo:nil repeats:NO];
760 */
761
762 if ([m_pOverlayView isEverSized])
763 {
764 if([NSThread isMainThread])
765 [m_pOverlayView vboxReshapePerform];
766 else
767 [self performSelectorOnMainThread:@selector(vboxReshapePerform) withObject:nil waitUntilDone:NO];
768 }
769 }
770}
771
772@end
773
774/********************************************************************************
775*
776* OverlayView class implementation
777*
778********************************************************************************/
779@implementation OverlayView
780
781- (id)initWithFrame:(NSRect)frame thread:(RTTHREAD)aThread parentView:(NSView*)pParentView winInfo:(WindowInfo*)pWinInfo
782{
783 m_pParentView = pParentView;
784 /* Make some reasonable defaults */
785 m_pGLCtx = nil;
786 m_pSharedGLCtx = nil;
787 mThread = aThread;
788 m_FBOId = 0;
789 m_cClipRects = 0;
790 m_paClipRects = NULL;
791 m_Pos = NSZeroPoint;
792 m_Size = NSMakeSize(1, 1);
793 m_RootRect = NSMakeRect(0, 0, m_Size.width, m_Size.height);
794 m_yInvRootOffset = 0;
795 m_pBlitter = nil;
796 m_pWinInfo = pWinInfo;
797 m_fNeedViewportUpdate = true;
798 m_fNeedCtxUpdate = true;
799 m_fDataVisible = false;
800 m_fCleanupNeeded = false;
801 m_fEverSized = false;
802
803 self = [super initWithFrame:frame];
804
805 DEBUG_MSG(("OVIW(%p): init OverlayView\n", (void*)self));
806
807 return self;
808}
809
810- (void)cleanupData
811{
812 [self deleteDockTile];
813
814 [self setGLCtx:nil];
815
816 if (m_pSharedGLCtx)
817 {
818 if ([m_pSharedGLCtx view] == self)
819 [m_pSharedGLCtx clearDrawable];
820
821 [m_pSharedGLCtx release];
822
823 m_pSharedGLCtx = nil;
824
825 CrBltTerm(m_pBlitter);
826
827 RTMemFree(m_pBlitter);
828
829 m_pBlitter = nil;
830 }
831
832 [self clearVisibleRegions];
833}
834
835- (void)dealloc
836{
837 DEBUG_MSG(("OVIW(%p): dealloc OverlayView\n", (void*)self));
838
839 [self cleanupData];
840
841 [super dealloc];
842}
843
844- (void)drawRect:(NSRect)aRect
845{
846 [self vboxTryDrawUI];
847}
848
849- (void)setGLCtx:(NSOpenGLContext*)pCtx
850{
851 DEBUG_MSG(("OVIW(%p): setGLCtx: new ctx: %p\n", (void*)self, (void*)pCtx));
852 if (m_pGLCtx == pCtx)
853 return;
854
855 /* ensure the context drawable is cleared to avoid holding a reference to inexistent view */
856 if (m_pGLCtx)
857 {
858 [m_pGLCtx clearDrawable];
859 [m_pGLCtx release];
860 /*[m_pGLCtx performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO];*/
861 }
862
863 m_pGLCtx = pCtx;
864 if (pCtx)
865 [pCtx retain];
866}
867
868- (NSOpenGLContext*)glCtx
869{
870 return m_pGLCtx;
871}
872
873- (NSView*)parentView
874{
875 return m_pParentView;
876}
877
878- (void)setParentView:(NSView*)pView
879{
880 DEBUG_MSG(("OVIW(%p): setParentView: new view: %p\n", (void*)self, (void*)pView));
881
882 m_pParentView = pView;
883}
884
885- (void)setOverlayWin:(NSWindow*)pWin
886{
887 DEBUG_MSG(("OVIW(%p): setOverlayWin: new win: %p\n", (void*)self, (void*)pWin));
888
889 m_pOverlayWin = pWin;
890}
891
892- (NSWindow*)overlayWin
893{
894 return m_pOverlayWin;
895}
896
897- (void)setPos:(NSPoint)pos
898{
899 DEBUG_MSG(("OVIW(%p): setPos: new pos: %d, %d\n", (void*)self, (int)pos.x, (int)pos.y));
900
901 m_Pos = pos;
902
903 if (m_fEverSized)
904 [self performSelectorOnMainThread:@selector(vboxReshapePerform) withObject:nil waitUntilDone:NO];
905}
906
907- (NSPoint)pos
908{
909 return m_Pos;
910}
911
912- (bool)isEverSized
913{
914 return m_fEverSized;
915}
916
917- (void)setSize:(NSSize)size
918{
919 NSOpenGLContext *pCurCtx;
920 NSView *pCurView;
921 m_Size = size;
922
923 m_fEverSized = true;
924
925 DEBUG_MSG(("OVIW(%p): setSize: new size: %dx%d\n", (void*)self, (int)size.width, (int)size.height));
926 [self performSelectorOnMainThread:@selector(vboxReshapeOnResizePerform) withObject:nil waitUntilDone:NO];
927}
928
929- (NSSize)size
930{
931 return m_Size;
932}
933
934- (void)updateViewportCS
935{
936 DEBUG_MSG(("OVIW(%p): updateViewport\n", (void*)self));
937
938 /* Update the viewport for our OpenGL view */
939 [m_pSharedGLCtx update];
940
941 [self vboxBlitterSyncWindow];
942
943 /* Clear background to transparent */
944 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
945}
946
947- (void)vboxReshapeOnResizePerform
948{
949 [self vboxReshapePerform];
950
951 [self createDockTile];
952 /* have to rebind GL_TEXTURE_RECTANGLE_ARB as m_FBOTexId could be changed in updateFBO call */
953 m_fNeedViewportUpdate = true;
954#if 0
955 pCurCtx = [NSOpenGLContext currentContext];
956 if (pCurCtx && pCurCtx == m_pGLCtx && (pCurView = [pCurCtx view]) == self)
957 {
958 [m_pGLCtx update];
959 m_fNeedCtxUpdate = false;
960 }
961 else
962 {
963 /* do it in a lazy way */
964 m_fNeedCtxUpdate = true;
965 }
966#endif
967}
968
969- (void)vboxReshapeOnReparentPerform
970{
971 [self createDockTile];
972}
973
974- (void)vboxReshapePerform
975{
976 NSRect parentFrame = NSZeroRect;
977 NSPoint parentPos = NSZeroPoint;
978 NSPoint childPos = NSZeroPoint;
979 NSRect childFrame = NSZeroRect;
980 NSRect newFrame = NSZeroRect;
981
982 DEBUG_MSG(("OVIW(%p): vboxReshapePerform\n", (void*)self));
983
984 parentFrame = [m_pParentView frame];
985 DEBUG_MSG(("FIXED parentFrame [%f:%f], [%f:%f]\n", parentFrame.origin.x, parentFrame.origin.y, parentFrame.size.width, parentFrame.size.height));
986 parentPos = parentFrame.origin;
987 parentPos.y += parentFrame.size.height;
988 DEBUG_MSG(("FIXED(view) parentPos [%f:%f]\n", parentPos.x, parentPos.y));
989 parentPos = [m_pParentView convertPoint:parentPos toView:nil];
990 DEBUG_MSG(("FIXED parentPos(win) [%f:%f]\n", parentPos.x, parentPos.y));
991 parentPos = [[m_pParentView window] convertBaseToScreen:parentPos];
992 DEBUG_MSG(("FIXED parentPos(screen) [%f:%f]\n", parentPos.x, parentPos.y));
993 parentFrame.origin = parentPos;
994
995 childPos = NSMakePoint(m_Pos.x, m_Pos.y + m_Size.height);
996 DEBUG_MSG(("FIXED(view) childPos [%f:%f]\n", childPos.x, childPos.y));
997 childPos = [m_pParentView convertPoint:childPos toView:nil];
998 DEBUG_MSG(("FIXED(win) childPos [%f:%f]\n", childPos.x, childPos.y));
999 childPos = [[m_pParentView window] convertBaseToScreen:childPos];
1000 DEBUG_MSG(("FIXED childPos(screen) [%f:%f]\n", childPos.x, childPos.y));
1001 childFrame = NSMakeRect(childPos.x, childPos.y, m_Size.width, m_Size.height);
1002 DEBUG_MSG(("FIXED childFrame [%f:%f], [%f:%f]\n", childFrame.origin.x, childFrame.origin.y, childFrame.size.width, childFrame.size.height));
1003
1004 /* We have to make sure that the overlay window will not be displayed out
1005 * of the parent window. So intersect both frames & use the result as the new
1006 * frame for the window. */
1007 newFrame = NSIntersectionRect(parentFrame, childFrame);
1008
1009 DEBUG_MSG(("[%#p]: parentFrame pos[%f : %f] size[%f : %f]\n",
1010 (void*)self,
1011 parentFrame.origin.x, parentFrame.origin.y,
1012 parentFrame.size.width, parentFrame.size.height));
1013 DEBUG_MSG(("[%#p]: childFrame pos[%f : %f] size[%f : %f]\n",
1014 (void*)self,
1015 childFrame.origin.x, childFrame.origin.y,
1016 childFrame.size.width, childFrame.size.height));
1017
1018 DEBUG_MSG(("[%#p]: newFrame pos[%f : %f] size[%f : %f]\n",
1019 (void*)self,
1020 newFrame.origin.x, newFrame.origin.y,
1021 newFrame.size.width, newFrame.size.height));
1022
1023 /* Later we have to correct the texture position in the case the window is
1024 * out of the parents window frame. So save the shift values for later use. */
1025 m_RootRect.origin.x = newFrame.origin.x - childFrame.origin.x;
1026 m_RootRect.origin.y = childFrame.size.height + childFrame.origin.y - (newFrame.size.height + newFrame.origin.y);
1027 m_RootRect.size = newFrame.size;
1028 m_yInvRootOffset = newFrame.origin.y - childFrame.origin.y;
1029
1030 DEBUG_MSG(("[%#p]: m_RootRect pos[%f : %f] size[%f : %f]\n",
1031 (void*)self,
1032 m_RootRect.origin.x, m_RootRect.origin.y,
1033 m_RootRect.size.width, m_RootRect.size.height));
1034
1035
1036 /*
1037 NSScrollView *pScrollView = [[[m_pParentView window] contentView] enclosingScrollView];
1038 if (pScrollView)
1039 {
1040 NSRect scrollRect = [pScrollView documentVisibleRect];
1041 NSRect scrollRect = [m_pParentView visibleRect];
1042 printf ("sc rect: %d %d %d %d\n", (int) scrollRect.origin.x,(int) scrollRect.origin.y,(int) scrollRect.size.width,(int) scrollRect.size.height);
1043 NSRect b = [[m_pParentView superview] bounds];
1044 printf ("bound rect: %d %d %d %d\n", (int) b.origin.x,(int) b.origin.y,(int) b.size.width,(int) b.size.height);
1045 newFrame.origin.x += scrollRect.origin.x;
1046 newFrame.origin.y += scrollRect.origin.y;
1047 }
1048 */
1049
1050 /* Set the new frame. */
1051 [[self window] setFrame:newFrame display:YES];
1052
1053 /* Inform the dock tile view as well */
1054 [self reshapeDockTile];
1055
1056 /* Make sure the context is updated according */
1057 /* [self updateViewport]; */
1058 if (m_pSharedGLCtx)
1059 {
1060 VBOX_CR_RENDER_CTX_INFO CtxInfo;
1061 vboxCtxEnter(m_pSharedGLCtx, &CtxInfo);
1062
1063 [self updateViewportCS];
1064
1065 vboxCtxLeave(&CtxInfo);
1066 }
1067}
1068
1069- (void)createDockTile
1070{
1071 NSView *pDockScreen = nil;
1072 [self deleteDockTile];
1073
1074 /* Is there a dock tile preview enabled in the GUI? If so setup a
1075 * additional thumbnail view for the dock tile. */
1076 pDockScreen = [self dockTileScreen];
1077 if (pDockScreen)
1078 {
1079 m_DockTileView = [[DockOverlayView alloc] init];
1080 [self reshapeDockTile];
1081 [pDockScreen addSubview:m_DockTileView];
1082 }
1083}
1084
1085- (void)deleteDockTile
1086{
1087 if (m_DockTileView != nil)
1088 {
1089 [m_DockTileView removeFromSuperview];
1090 [m_DockTileView release];
1091 m_DockTileView = nil;
1092 }
1093}
1094
1095- (void)makeCurrentFBO
1096{
1097 DEBUG_MSG(("OVIW(%p): makeCurrentFBO\n", (void*)self));
1098
1099 if (m_pGLCtx)
1100 {
1101 if ([m_pGLCtx view] != self)
1102 {
1103 /* We change the active view, so flush first */
1104 if([NSOpenGLContext currentContext] != 0)
1105 glFlush();
1106 [m_pGLCtx setView: self];
1107 CHECK_GL_ERROR();
1108 }
1109 /*
1110 if ([NSOpenGLContext currentContext] != m_pGLCtx)
1111 */
1112 {
1113 [m_pGLCtx makeCurrentContext];
1114 CHECK_GL_ERROR();
1115 if (m_fNeedCtxUpdate == true)
1116 {
1117 [m_pGLCtx update];
1118 m_fNeedCtxUpdate = false;
1119 }
1120 }
1121
1122 if (!m_FBOId)
1123 {
1124 glGenFramebuffersEXT(1, &m_FBOId);
1125 Assert(m_FBOId);
1126 }
1127
1128 }
1129}
1130
1131- (bool)vboxSharedCtxCreate
1132{
1133 if (m_pSharedGLCtx)
1134 return true;
1135
1136 Assert(!m_pBlitter);
1137 m_pBlitter = RTMemAlloc(sizeof (*m_pBlitter));
1138 if (!m_pBlitter)
1139 {
1140 DEBUG_WARN(("m_pBlitter allocation failed"));
1141 return false;
1142 }
1143
1144 int rc = CrBltInit(m_pBlitter, NULL, false, false, &render_spu.GlobalShaders, &render_spu.blitterDispatch);
1145 if (RT_SUCCESS(rc))
1146 {
1147 DEBUG_MSG(("blitter created successfully for view 0x%p\n", (void*)self));
1148 }
1149 else
1150 {
1151 DEBUG_WARN(("CrBltInit failed, rc %d", rc));
1152 RTMemFree(m_pBlitter);
1153 m_pBlitter = NULL;
1154 return false;
1155 }
1156
1157 GLint opaque = 0;
1158 /* Create a shared context out of the main context. Use the same pixel format. */
1159 NSOpenGLContext *pSharedGLCtx = [[NSOpenGLContext alloc] initWithFormat:[(OverlayOpenGLContext*)m_pGLCtx openGLPixelFormat] shareContext:m_pGLCtx];
1160
1161 /* Set the new context as non opaque */
1162 [pSharedGLCtx setValues:&opaque forParameter:NSOpenGLCPSurfaceOpacity];
1163 /* Set this view as the drawable for the new context */
1164 [pSharedGLCtx setView: self];
1165 m_fNeedViewportUpdate = true;
1166
1167 m_pSharedGLCtx = pSharedGLCtx;
1168
1169 return true;
1170}
1171
1172- (void)vboxTryDraw
1173{
1174 glFlush();
1175
1176 /* issue to the gui thread */
1177 [self setNeedsDisplay:YES];
1178}
1179
1180- (void)vboxTryDrawUI
1181{
1182 const VBOXVR_SCR_COMPOSITOR *pCompositor;
1183 int rc = renderspuVBoxCompositorLock(m_pWinInfo, &pCompositor);
1184 if (RT_FAILURE(rc))
1185 {
1186 DEBUG_WARN(("renderspuVBoxCompositorLock failed\n"));
1187 return;
1188 }
1189
1190 if (!pCompositor && !m_fCleanupNeeded)
1191 {
1192 renderspuVBoxCompositorUnlock(m_pWinInfo);
1193 return;
1194 }
1195
1196 VBOXVR_SCR_COMPOSITOR TmpCompositor;
1197
1198 if (pCompositor)
1199 {
1200 if (!m_pSharedGLCtx)
1201 {
1202 Assert(!m_fDataVisible);
1203 Assert(!m_fCleanupNeeded);
1204 renderspuVBoxCompositorRelease(m_pWinInfo);
1205 if (![self vboxSharedCtxCreate])
1206 {
1207 DEBUG_WARN(("vboxSharedCtxCreate failed\n"));
1208 return;
1209 }
1210
1211 Assert(m_pSharedGLCtx);
1212
1213 pCompositor = renderspuVBoxCompositorAcquire(m_pWinInfo);
1214 Assert(!m_fDataVisible);
1215 Assert(!m_fCleanupNeeded);
1216 if (!pCompositor)
1217 return;
1218 }
1219 }
1220 else
1221 {
1222 Assert(m_fCleanupNeeded);
1223 CrVrScrCompositorInit(&TmpCompositor, NULL);
1224 pCompositor = &TmpCompositor;
1225 }
1226
1227 if ([self lockFocusIfCanDraw])
1228 {
1229 [self vboxPresent:pCompositor];
1230 [self unlockFocus];
1231 }
1232 else
1233 {
1234 [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(vboxTryDrawUI) userInfo:nil repeats:NO];
1235 }
1236
1237 renderspuVBoxCompositorUnlock(m_pWinInfo);
1238}
1239
1240- (void)swapFBO
1241{
1242 [m_pGLCtx flushBuffer];
1243}
1244
1245- (void)vboxPresent:(const VBOXVR_SCR_COMPOSITOR*)pCompositor
1246{
1247 VBOX_CR_RENDER_CTX_INFO CtxInfo;
1248
1249 DEBUG_MSG(("OVIW(%p): renderFBOToView\n", (void*)self));
1250
1251 Assert(pCompositor);
1252
1253 vboxCtxEnter(m_pSharedGLCtx, &CtxInfo);
1254
1255 [self vboxPresentCS:pCompositor];
1256
1257 vboxCtxLeave(&CtxInfo);
1258}
1259
1260- (void)vboxPresentCS:(const VBOXVR_SCR_COMPOSITOR*)pCompositor
1261{
1262 {
1263 if ([m_pSharedGLCtx view] != self)
1264 {
1265 DEBUG_MSG(("OVIW(%p): not current view of shared ctx! Switching ...\n", (void*)self));
1266 [m_pSharedGLCtx setView: self];
1267 m_fNeedViewportUpdate = true;
1268 }
1269
1270 if (m_fNeedViewportUpdate)
1271 {
1272 [self updateViewportCS];
1273 m_fNeedViewportUpdate = false;
1274 }
1275
1276 /* Render FBO content to the dock tile when necessary. */
1277 [self vboxPresentToDockTileCS:pCompositor];
1278 /* change to #if 0 to see thumbnail image */
1279#if 1
1280 [self vboxPresentToViewCS:pCompositor];
1281#else
1282 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1283 [m_pSharedGLCtx flushBuffer];
1284#endif
1285
1286 }
1287}
1288
1289DECLINLINE(void) vboxNSRectToRect(const NSRect *pR, RTRECT *pRect)
1290{
1291 pRect->xLeft = (int)pR->origin.x;
1292 pRect->yTop = (int)pR->origin.y;
1293 pRect->xRight = (int)(pR->origin.x + pR->size.width);
1294 pRect->yBottom = (int)(pR->origin.y + pR->size.height);
1295}
1296
1297DECLINLINE(void) vboxNSRectToRectUnstretched(const NSRect *pR, RTRECT *pRect, float xStretch, float yStretch)
1298{
1299 pRect->xLeft = (int)(pR->origin.x / xStretch);
1300 pRect->yTop = (int)(pR->origin.y / yStretch);
1301 pRect->xRight = (int)((pR->origin.x + pR->size.width) / xStretch);
1302 pRect->yBottom = (int)((pR->origin.y + pR->size.height) / yStretch);
1303}
1304
1305DECLINLINE(void) vboxNSRectToRectStretched(const NSRect *pR, RTRECT *pRect, float xStretch, float yStretch)
1306{
1307 pRect->xLeft = (int)(pR->origin.x * xStretch);
1308 pRect->yTop = (int)(pR->origin.y * yStretch);
1309 pRect->xRight = (int)((pR->origin.x + pR->size.width) * xStretch);
1310 pRect->yBottom = (int)((pR->origin.y + pR->size.height) * yStretch);
1311}
1312
1313- (void)vboxPresentToViewCS:(const VBOXVR_SCR_COMPOSITOR*)pCompositor
1314{
1315 NSRect r = [self frame];
1316 float xStretch, yStretch;
1317 DEBUG_MSG(("OVIW(%p): rF2V frame: [%i, %i, %i, %i]\n", (void*)self, (int)r.origin.x, (int)r.origin.y, (int)r.size.width, (int)r.size.height));
1318
1319#if 1 /* Set to 0 to see the docktile instead of the real output */
1320 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR CIter;
1321 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
1322
1323 CrVrScrCompositorConstIterInit(pCompositor, &CIter);
1324
1325 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
1326 glDrawBuffer(GL_BACK);
1327
1328 /* Clear background to transparent */
1329 glClear(GL_COLOR_BUFFER_BIT);
1330
1331 m_fDataVisible = false;
1332
1333 CrVrScrCompositorGetStretching(pCompositor, &xStretch, &yStretch);
1334
1335 while ((pEntry = CrVrScrCompositorConstIterNext(&CIter)) != NULL)
1336 {
1337 uint32_t cRegions;
1338 const RTRECT *paSrcRegions, *paDstRegions;
1339 int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRegions, &paSrcRegions, &paDstRegions, NULL);
1340 uint32_t fFlags = CrVrScrCompositorEntryFlagsCombinedGet(pCompositor, pEntry);
1341 if (RT_SUCCESS(rc))
1342 {
1343 uint32_t i;
1344 int rc = CrBltEnter(m_pBlitter);
1345 if (RT_SUCCESS(rc))
1346 {
1347 for (i = 0; i < cRegions; ++i)
1348 {
1349 const RTRECT * pSrcRect = &paSrcRegions[i];
1350 const RTRECT * pDstRect = &paDstRegions[i];
1351 RTRECT DstRect, RestrictDstRect;
1352 RTRECT SrcRect, RestrictSrcRect;
1353
1354 vboxNSRectToRect(&m_RootRect, &RestrictDstRect);
1355 VBoxRectIntersected(&RestrictDstRect, pDstRect, &DstRect);
1356
1357 if (VBoxRectIsZero(&DstRect))
1358 continue;
1359
1360 VBoxRectTranslate(&DstRect, -RestrictDstRect.xLeft, -RestrictDstRect.yTop);
1361
1362 vboxNSRectToRectUnstretched(&m_RootRect, &RestrictSrcRect, xStretch, yStretch);
1363 VBoxRectTranslate(&RestrictSrcRect, -CrVrScrCompositorEntryRectGet(pEntry)->xLeft, -CrVrScrCompositorEntryRectGet(pEntry)->yTop);
1364 VBoxRectIntersected(&RestrictSrcRect, pSrcRect, &SrcRect);
1365
1366 if (VBoxRectIsZero(&SrcRect))
1367 continue;
1368
1369 pSrcRect = &SrcRect;
1370 pDstRect = &DstRect;
1371
1372 const CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
1373
1374 CrBltBlitTexMural(m_pBlitter, true, CrTdTexGet(pTexData), pSrcRect, pDstRect, 1, fFlags | CRBLT_F_NOALPHA);
1375
1376 m_fDataVisible = true;
1377 }
1378 CrBltLeave(m_pBlitter);
1379 }
1380 else
1381 {
1382 DEBUG_WARN(("CrBltEnter failed rc %d", rc));
1383 }
1384 }
1385 else
1386 {
1387 Assert(0);
1388 DEBUG_MSG_1(("BlitStretched: CrVrScrCompositorEntryRegionsGet failed rc %d\n", rc));
1389 }
1390 }
1391#endif
1392 /*
1393 glFinish();
1394 */
1395 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1396 [m_pSharedGLCtx flushBuffer];
1397}
1398
1399- (void)presentComposition:(const VBOXVR_SCR_COMPOSITOR_ENTRY*)pChangedEntry
1400{
1401 [self vboxTryDraw];
1402}
1403
1404- (void)vboxBlitterSyncWindow
1405{
1406 CR_BLITTER_WINDOW WinInfo;
1407 NSRect r;
1408
1409 if (!m_pBlitter)
1410 return;
1411
1412 memset(&WinInfo, 0, sizeof (WinInfo));
1413
1414 r = [self frame];
1415 WinInfo.width = r.size.width;
1416 WinInfo.height = r.size.height;
1417
1418 Assert(WinInfo.width == m_RootRect.size.width);
1419 Assert(WinInfo.height == m_RootRect.size.height);
1420
1421 /*CrBltMuralSetCurrentInfo(m_pBlitter, NULL);*/
1422
1423 CrBltMuralSetCurrentInfo(m_pBlitter, &WinInfo);
1424 CrBltCheckUpdateViewport(m_pBlitter);
1425}
1426
1427#ifdef VBOX_WITH_CRDUMPER_THUMBNAIL
1428static int g_cVBoxTgaCtr = 0;
1429#endif
1430- (void)vboxPresentToDockTileCS:(const VBOXVR_SCR_COMPOSITOR*)pCompositor
1431{
1432 NSRect r = [self frame];
1433 NSRect rr = NSZeroRect;
1434 GLint i = 0;
1435 NSDockTile *pDT = nil;
1436 float xStretch, yStretch;
1437
1438 if ([m_DockTileView thumbBitmap] != nil)
1439 {
1440 /* Only update after at least 200 ms, cause glReadPixels is
1441 * heavy performance wise. */
1442 uint64_t uiNewTime = RTTimeMilliTS();
1443 VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR CIter;
1444 const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
1445
1446 if (uiNewTime - m_uiDockUpdateTime > 200)
1447 {
1448 m_uiDockUpdateTime = uiNewTime;
1449#if 0
1450 /* todo: check this for optimization */
1451 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, myTextureName);
1452 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE,
1453 GL_STORAGE_SHARED_APPLE);
1454 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
1455 glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
1456 sizex, sizey, 0, GL_BGRA,
1457 GL_UNSIGNED_INT_8_8_8_8_REV, myImagePtr);
1458 glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB,
1459 0, 0, 0, 0, 0, image_width, image_height);
1460 glFlush();
1461 /* Do other work processing here, using a double or triple buffer */
1462 glGetTexImage(GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGRA,
1463 GL_UNSIGNED_INT_8_8_8_8_REV, pixels);
1464#endif
1465 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
1466 glDrawBuffer(GL_BACK);
1467
1468 /* Clear background to transparent */
1469 glClear(GL_COLOR_BUFFER_BIT);
1470
1471 rr = [m_DockTileView frame];
1472
1473 CrVrScrCompositorGetStretching(pCompositor, &xStretch, &yStretch);
1474
1475 CrVrScrCompositorConstIterInit(pCompositor, &CIter);
1476 while ((pEntry = CrVrScrCompositorConstIterNext(&CIter)) != NULL)
1477 {
1478 uint32_t cRegions;
1479 const RTRECT *paSrcRegions, *paDstRegions;
1480 int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRegions, &paSrcRegions, &paDstRegions, NULL);
1481 uint32_t fFlags = CrVrScrCompositorEntryFlagsCombinedGet(pCompositor, pEntry);
1482 if (RT_SUCCESS(rc))
1483 {
1484 uint32_t i;
1485 int rc = CrBltEnter(m_pBlitter);
1486 if (RT_SUCCESS(rc))
1487 {
1488 for (i = 0; i < cRegions; ++i)
1489 {
1490 const RTRECT * pSrcRect = &paSrcRegions[i];
1491 const RTRECT * pDstRect = &paDstRegions[i];
1492 RTRECT SrcRect, DstRect, RestrictSrcRect, RestrictDstRect;
1493
1494 vboxNSRectToRect(&m_RootRect, &RestrictDstRect);
1495 VBoxRectIntersected(&RestrictDstRect, pDstRect, &DstRect);
1496
1497 VBoxRectTranslate(&DstRect, -RestrictDstRect.xLeft, -RestrictDstRect.yTop);
1498
1499 VBoxRectScale(&DstRect, m_FBOThumbScaleX, m_FBOThumbScaleY);
1500
1501 if (VBoxRectIsZero(&DstRect))
1502 continue;
1503
1504 vboxNSRectToRectUnstretched(&m_RootRect, &RestrictSrcRect, xStretch, yStretch);
1505 VBoxRectTranslate(&RestrictSrcRect, -CrVrScrCompositorEntryRectGet(pEntry)->xLeft, -CrVrScrCompositorEntryRectGet(pEntry)->yTop);
1506 VBoxRectIntersected(&RestrictSrcRect, pSrcRect, &SrcRect);
1507
1508 if (VBoxRectIsZero(&SrcRect))
1509 continue;
1510
1511 pSrcRect = &SrcRect;
1512 pDstRect = &DstRect;
1513
1514 const CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
1515
1516 CrBltBlitTexMural(m_pBlitter, true, CrTdTexGet(pTexData), pSrcRect, pDstRect, 1, fFlags);
1517 }
1518 CrBltLeave(m_pBlitter);
1519 }
1520 else
1521 {
1522 DEBUG_WARN(("CrBltEnter failed rc %d", rc));
1523 }
1524 }
1525 else
1526 {
1527 Assert(0);
1528 DEBUG_MSG_1(("BlitStretched: CrVrScrCompositorEntryRegionsGet failed rc %d\n", rc));
1529 }
1530 }
1531
1532 glFinish();
1533
1534 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
1535 glReadBuffer(GL_BACK);
1536 /* Here the magic of reading the FBO content in our own buffer
1537 * happens. We have to lock this access, in the case the dock
1538 * is updated currently. */
1539 [m_DockTileView lock];
1540 glReadPixels(0, m_RootRect.size.height - rr.size.height, rr.size.width, rr.size.height,
1541 GL_BGRA,
1542 GL_UNSIGNED_INT_8_8_8_8,
1543 [[m_DockTileView thumbBitmap] bitmapData]);
1544 [m_DockTileView unlock];
1545
1546#ifdef VBOX_WITH_CRDUMPER_THUMBNAIL
1547 ++g_cVBoxTgaCtr;
1548 crDumpNamedTGAF((GLint)rr.size.width, (GLint)rr.size.height,
1549 [[m_DockTileView thumbBitmap] bitmapData], "/Users/leo/vboxdumps/dump%d.tga", g_cVBoxTgaCtr);
1550#endif
1551
1552 pDT = [[NSApplication sharedApplication] dockTile];
1553
1554 /* Send a display message to the dock tile in the main thread */
1555 [[[NSApplication sharedApplication] dockTile] performSelectorOnMainThread:@selector(display) withObject:nil waitUntilDone:NO];
1556 }
1557 }
1558}
1559
1560- (void)clearVisibleRegions
1561{
1562 if(m_paClipRects)
1563 {
1564 RTMemFree(m_paClipRects);
1565 m_paClipRects = NULL;
1566 }
1567 m_cClipRects = 0;
1568}
1569
1570- (GLboolean)vboxNeedsEmptyPresent
1571{
1572 if (m_fDataVisible)
1573 {
1574 m_fCleanupNeeded = true;
1575 return GL_TRUE;
1576 }
1577
1578 return GL_FALSE;
1579}
1580
1581- (void)setVisibleRegions:(GLint)cRects paRects:(const GLint*)paRects
1582{
1583 GLint cOldRects = m_cClipRects;
1584
1585 DEBUG_MSG_1(("OVIW(%p): setVisibleRegions: cRects=%d\n", (void*)self, cRects));
1586
1587 [self clearVisibleRegions];
1588
1589 if (cRects > 0)
1590 {
1591#ifdef DEBUG_poetzsch
1592 int i =0;
1593 for (i = 0; i < cRects; ++i)
1594 DEBUG_MSG_1(("OVIW(%p): setVisibleRegions: %d - %d %d %d %d\n", (void*)self, i, paRects[i * 4], paRects[i * 4 + 1], paRects[i * 4 + 2], paRects[i * 4 + 3]));
1595#endif
1596
1597 m_paClipRects = (GLint*)RTMemAlloc(sizeof(GLint) * 4 * cRects);
1598 m_cClipRects = cRects;
1599 memcpy(m_paClipRects, paRects, sizeof(GLint) * 4 * cRects);
1600 }
1601}
1602
1603- (NSView*)dockTileScreen
1604{
1605 NSView *contentView = [[[NSApplication sharedApplication] dockTile] contentView];
1606 NSView *screenContent = nil;
1607 /* First try the new variant which checks if this window is within the
1608 screen which is previewed in the dock. */
1609 if ([contentView respondsToSelector:@selector(screenContentWithParentView:)])
1610 screenContent = [contentView performSelector:@selector(screenContentWithParentView:) withObject:(id)m_pParentView];
1611 /* If it fails, fall back to the old variant (VBox...) */
1612 else if ([contentView respondsToSelector:@selector(screenContent)])
1613 screenContent = [contentView performSelector:@selector(screenContent)];
1614 return screenContent;
1615}
1616
1617- (void)reshapeDockTile
1618{
1619 NSRect newFrame = NSZeroRect;
1620
1621 NSView *pView = [self dockTileScreen];
1622 if (pView != nil)
1623 {
1624 NSRect dockFrame = [pView frame];
1625 /* todo: this is not correct, we should use framebuffer size here, while parent view frame size may differ in case of scrolling */
1626 NSRect parentFrame = [m_pParentView frame];
1627
1628 m_FBOThumbScaleX = (float)dockFrame.size.width / parentFrame.size.width;
1629 m_FBOThumbScaleY = (float)dockFrame.size.height / parentFrame.size.height;
1630 newFrame = NSMakeRect((int)(m_Pos.x * m_FBOThumbScaleX), (int)(dockFrame.size.height - (m_Pos.y + m_Size.height - m_yInvRootOffset) * m_FBOThumbScaleY), (int)(m_Size.width * m_FBOThumbScaleX), (int)(m_Size.height * m_FBOThumbScaleY));
1631 /*
1632 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));
1633 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));
1634 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);
1635 */
1636 [m_DockTileView setFrame: newFrame];
1637 }
1638}
1639
1640@end
1641
1642/********************************************************************************
1643*
1644* OpenGL context management
1645*
1646********************************************************************************/
1647void cocoaGLCtxCreate(NativeNSOpenGLContextRef *ppCtx, GLbitfield fVisParams, NativeNSOpenGLContextRef pSharedCtx)
1648{
1649 NSOpenGLPixelFormat *pFmt = nil;
1650
1651 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1652
1653 NSOpenGLPixelFormatAttribute attribs[24] =
1654 {
1655 NSOpenGLPFAWindow,
1656 NSOpenGLPFAAccelerated,
1657 NSOpenGLPFAColorSize, (NSOpenGLPixelFormatAttribute)24
1658 };
1659
1660 int i = 4;
1661
1662 if (fVisParams & CR_ALPHA_BIT)
1663 {
1664 DEBUG_MSG(("CR_ALPHA_BIT requested\n"));
1665 attribs[i++] = NSOpenGLPFAAlphaSize;
1666 attribs[i++] = 8;
1667 }
1668 if (fVisParams & CR_DEPTH_BIT)
1669 {
1670 DEBUG_MSG(("CR_DEPTH_BIT requested\n"));
1671 attribs[i++] = NSOpenGLPFADepthSize;
1672 attribs[i++] = 24;
1673 }
1674 if (fVisParams & CR_STENCIL_BIT)
1675 {
1676 DEBUG_MSG(("CR_STENCIL_BIT requested\n"));
1677 attribs[i++] = NSOpenGLPFAStencilSize;
1678 attribs[i++] = 8;
1679 }
1680 if (fVisParams & CR_ACCUM_BIT)
1681 {
1682 DEBUG_MSG(("CR_ACCUM_BIT requested\n"));
1683 attribs[i++] = NSOpenGLPFAAccumSize;
1684 if (fVisParams & CR_ALPHA_BIT)
1685 attribs[i++] = 32;
1686 else
1687 attribs[i++] = 24;
1688 }
1689 if (fVisParams & CR_MULTISAMPLE_BIT)
1690 {
1691 DEBUG_MSG(("CR_MULTISAMPLE_BIT requested\n"));
1692 attribs[i++] = NSOpenGLPFASampleBuffers;
1693 attribs[i++] = 1;
1694 attribs[i++] = NSOpenGLPFASamples;
1695 attribs[i++] = 4;
1696 }
1697 if (fVisParams & CR_DOUBLE_BIT)
1698 {
1699 DEBUG_MSG(("CR_DOUBLE_BIT requested\n"));
1700 attribs[i++] = NSOpenGLPFADoubleBuffer;
1701 }
1702 if (fVisParams & CR_STEREO_BIT)
1703 {
1704 /* We don't support that.
1705 DEBUG_MSG(("CR_STEREO_BIT requested\n"));
1706 attribs[i++] = NSOpenGLPFAStereo;
1707 */
1708 }
1709
1710 /* Mark the end */
1711 attribs[i++] = 0;
1712
1713 /* Choose a pixel format */
1714 pFmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
1715
1716 if (pFmt)
1717 {
1718 *ppCtx = [[OverlayOpenGLContext alloc] initWithFormat:pFmt shareContext:pSharedCtx];
1719
1720 /* Enable multi threaded OpenGL engine */
1721 /*
1722 CGLContextObj cglCtx = [*ppCtx CGLContextObj];
1723 CGLError err = CGLEnable(cglCtx, kCGLCEMPEngine);
1724 if (err != kCGLNoError)
1725 printf ("Couldn't enable MT OpenGL engine!\n");
1726 */
1727
1728 DEBUG_MSG(("New context %X\n", (uint)*ppCtx));
1729 }
1730
1731 [pPool release];
1732}
1733
1734void cocoaGLCtxDestroy(NativeNSOpenGLContextRef pCtx)
1735{
1736 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1737
1738 [pCtx release];
1739 /*[pCtx performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO];*/
1740
1741 [pPool release];
1742}
1743
1744/********************************************************************************
1745*
1746* View management
1747*
1748********************************************************************************/
1749void cocoaViewCreate(NativeNSViewRef *ppView, WindowInfo *pWinInfo, NativeNSViewRef pParentView, GLbitfield fVisParams)
1750{
1751 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1752
1753 /* Create our worker view */
1754 OverlayView* pView = [[OverlayView alloc] initWithFrame:NSZeroRect thread:RTThreadSelf() parentView:pParentView winInfo:pWinInfo];
1755
1756 if (pView)
1757 {
1758 /* We need a real window as container for the view */
1759 [[OverlayWindow alloc] initWithParentView:pParentView overlayView:pView];
1760 /* Return the freshly created overlay view */
1761 *ppView = pView;
1762 }
1763
1764 [pPool release];
1765}
1766
1767void cocoaViewReparent(NativeNSViewRef pView, NativeNSViewRef pParentView)
1768{
1769 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1770
1771 OverlayView* pOView = (OverlayView*)pView;
1772
1773 if (pOView)
1774 {
1775 /* Make sure the window is removed from any previous parent window. */
1776 if ([[pOView overlayWin] parentWindow] != nil)
1777 {
1778 [[[pOView overlayWin] parentWindow] removeChildWindow:[pOView overlayWin]];
1779 }
1780
1781 /* Set the new parent view */
1782 [pOView setParentView: pParentView];
1783
1784 /* Add the overlay window as a child to the new parent window */
1785 if (pParentView != nil)
1786 {
1787 [[pParentView window] addChildWindow:[pOView overlayWin] ordered:NSWindowAbove];
1788 if ([pOView isEverSized])
1789 [pOView performSelectorOnMainThread:@selector(vboxReshapeOnReparentPerform) withObject:nil waitUntilDone:NO];
1790 }
1791 }
1792
1793 [pPool release];
1794}
1795
1796void cocoaViewDestroy(NativeNSViewRef pView)
1797{
1798 NSWindow *pWin = nil;
1799
1800 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1801
1802 /* Hide the view early */
1803 [pView setHidden: YES];
1804
1805 pWin = [pView window];
1806 [[NSNotificationCenter defaultCenter] removeObserver:pWin];
1807 [pWin setContentView: nil];
1808 [[pWin parentWindow] removeChildWindow: pWin];
1809
1810 /*
1811 a = [pWin retainCount];
1812 for (; a > 1; --a)
1813 [pWin performSelector:@selector(release)]
1814 */
1815 /* We can NOT run synchronously with the main thread since this may lead to a deadlock,
1816 caused by main thread waiting xpcom thread, xpcom thread waiting to main hgcm thread,
1817 and main hgcm thread waiting for us, this is why use waitUntilDone:NO,
1818 which should cause no harm */
1819 [pWin performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO];
1820 /*
1821 [pWin release];
1822 */
1823
1824 /* We can NOT run synchronously with the main thread since this may lead to a deadlock,
1825 caused by main thread waiting xpcom thread, xpcom thread waiting to main hgcm thread,
1826 and main hgcm thread waiting for us, this is why use waitUntilDone:NO.
1827 We need to avoid concurrency though, so we cleanup some data right away via a cleanupData call */
1828 [(OverlayView*)pView cleanupData];
1829
1830 /* There seems to be a bug in the performSelector method which is called in
1831 * parentWindowChanged above. The object is retained but not released. This
1832 * results in an unbalanced reference count, which is here manually
1833 * decremented. */
1834 /*
1835 a = [pView retainCount];
1836 for (; a > 1; --a)
1837 */
1838 [pView performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO];
1839 /*
1840 [pView release];
1841 */
1842
1843 [pPool release];
1844}
1845
1846void cocoaViewShow(NativeNSViewRef pView, GLboolean fShowIt)
1847{
1848 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1849
1850 [pView setHidden: fShowIt==GL_TRUE?NO:YES];
1851
1852 [pPool release];
1853}
1854
1855void cocoaViewDisplay(NativeNSViewRef pView)
1856{
1857 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1858
1859 DEBUG_MSG_1(("cocoaViewDisplay %p\n", (void*)pView));
1860 [(OverlayView*)pView swapFBO];
1861
1862 [pPool release];
1863
1864}
1865
1866void cocoaViewSetPosition(NativeNSViewRef pView, NativeNSViewRef pParentView, int x, int y)
1867{
1868 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1869
1870 [(OverlayView*)pView setPos:NSMakePoint(x, y)];
1871
1872 [pPool release];
1873}
1874
1875void cocoaViewSetSize(NativeNSViewRef pView, int w, int h)
1876{
1877 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1878
1879 [(OverlayView*)pView setSize:NSMakeSize(w, h)];
1880
1881 [pPool release];
1882}
1883
1884void cocoaViewGetGeometry(NativeNSViewRef pView, int *pX, int *pY, int *pW, int *pH)
1885{
1886 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1887
1888 NSRect frame = [[pView window] frame];
1889 *pX = frame.origin.x;
1890 *pY = frame.origin.y;
1891 *pW = frame.size.width;
1892 *pH = frame.size.height;
1893
1894 [pPool release];
1895}
1896
1897void cocoaViewPresentComposition(NativeNSViewRef pView, const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry)
1898{
1899 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1900 NSOpenGLContext *pCtx;
1901
1902 /* view should not necesserily have a context set */
1903 pCtx = [(OverlayView*)pView glCtx];
1904 if (!pCtx)
1905 {
1906 ContextInfo * pCtxInfo = renderspuDefaultSharedContextAcquire();
1907 if (!pCtxInfo)
1908 {
1909 DEBUG_WARN(("renderspuDefaultSharedContextAcquire returned NULL"));
1910
1911 [pPool release];
1912 return;
1913 }
1914
1915 pCtx = pCtxInfo->context;
1916
1917 [(OverlayView*)pView setGLCtx:pCtx];
1918 }
1919
1920 [(OverlayView*)pView presentComposition:pChangedEntry];
1921
1922 [pPool release];
1923}
1924
1925void cocoaViewMakeCurrentContext(NativeNSViewRef pView, NativeNSOpenGLContextRef pCtx)
1926{
1927 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1928
1929 DEBUG_MSG(("cocoaViewMakeCurrentContext(%p, %p)\n", (void*)pView, (void*)pCtx));
1930
1931 if (pView)
1932 {
1933 [(OverlayView*)pView setGLCtx:pCtx];
1934 [(OverlayView*)pView makeCurrentFBO];
1935 }
1936 else
1937 {
1938 [NSOpenGLContext clearCurrentContext];
1939 }
1940
1941 [pPool release];
1942}
1943
1944GLboolean cocoaViewNeedsEmptyPresent(NativeNSViewRef pView)
1945{
1946 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1947
1948 [(OverlayView*)pView vboxNeedsEmptyPresent];
1949
1950 [pPool release];
1951}
1952
1953void cocoaViewSetVisibleRegion(NativeNSViewRef pView, GLint cRects, const GLint* paRects)
1954{
1955 NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
1956
1957 [(OverlayView*)pView setVisibleRegions:cRects paRects:paRects];
1958
1959 [pPool release];
1960}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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