VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedOpenGL/render/renderspu_agl.c@ 51442

Last change on this file since 51442 was 51442, checked in by vboxsync, 10 years ago

crOpenGL: fix flickering on osx

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 33.7 KB
Line 
1/* Copyright (c) 2001, Stanford University
2 * All rights reserved
3 *
4 * See the file LICENSE.txt for information on redistributing this software.
5 */
6
7#include <Carbon/Carbon.h>
8#include <AGL/agl.h>
9#include <OpenGL/OpenGL.h>
10
11#include <iprt/time.h>
12#include <iprt/assert.h>
13#include <iprt/semaphore.h>
14
15#include <stdio.h>
16
17#include "cr_environment.h"
18#include "cr_error.h"
19#include "cr_string.h"
20#include "cr_mem.h"
21#include "renderspu.h"
22
23#ifdef __LP64__ /** @todo port to 64-bit darwin. */
24# define renderspuSetWindowContext(w, c) \
25 AssertFailed()
26# define renderspuGetWindowContext(w) \
27 ( (ContextInfo *) GetWRefCon( ((w)->nativeWindow ? (w)->nativeWindow : (w)->window) ) )
28#else
29# define renderspuSetWindowContext(w, c) \
30 ( SetWRefCon( (w), (unsigned long) (c) ) )
31# define renderspuGetWindowContext(w) \
32 ( (ContextInfo *) GetWRefCon( ((w)->nativeWindow ? (w)->nativeWindow : (w)->window) ) )
33#endif
34
35/* Debug macros */
36#ifdef DEBUG_poetzsch
37#define DEBUG_MSG_POETZSCH(text) \
38 printf text
39#else
40#define DEBUG_MSG_POETZSCH(text) \
41 do {} while (0)
42#endif
43
44#define DEBUG_MSG_RESULT(result, text) \
45 crDebug(text" (%d; %s:%d)", (int)(result), __FILE__, __LINE__)
46
47#define CHECK_CARBON_RC(result, text) \
48 if((result) != noErr) \
49 DEBUG_MSG_RESULT(result, text);
50
51#define CHECK_CARBON_RC_RETURN(result, text, ret) \
52 if((result) != noErr) \
53 { \
54 DEBUG_MSG_RESULT(result, text); \
55 return ret; \
56 }
57
58#define CHECK_CARBON_RC_RETURN_VOID(result, text) \
59 CHECK_CARBON_RC_RETURN(result, text,)
60
61#define CHECK_AGL_RC(result, text) \
62 if(!(result)) \
63 { \
64 GLenum error = render_spu.ws.aglGetError(); \
65 DEBUG_MSG_RESULT(result, text); \
66 }
67
68static void renderspu_SystemWindowApplyVisibleRegion(WindowInfo *window);
69static void renderspu_SystemSetRootVisibleRegion(GLint cRects, GLint *pRects);
70
71/* In some case (like compiz which doesn't provide us with clipping regions) we
72 * have to make sure that *all* open OpenGL windows are clipped to the main
73 * application window. This is done here when called from the event handler
74 * which monitor bounding changes of the main window. */
75static void crClipRootHelper(unsigned long key, void *data1, void *data2)
76{
77 /* The window with id zero is the base window, which isn't displayed at
78 * all. So ignore it. */
79 if (key > 0)
80 {
81 /* Fetch the actually window info & the user data */
82 WindowInfo *pWin = (WindowInfo *) data1;
83 /* We need to assign the context with this window */
84 ContextInfo *context = renderspuGetWindowContext(pWin);
85 if (context &&
86 context->context)
87 {
88 RTSemFastMutexRequest(render_spu.syncMutex);
89 GLboolean result = render_spu.ws.aglSetCurrentContext(context->context);
90 CHECK_AGL_RC (result, "Render SPU (crClipRootHelper): SetCurrentContext Failed");
91 if (result)
92 {
93 result = render_spu.ws.aglUpdateContext(context->context);
94 CHECK_AGL_RC (result, "Render SPU (crClipRootHelper): UpdateContext Failed");
95 /* Update the clipping region */
96 renderspu_SystemWindowApplyVisibleRegion(pWin);
97 }
98 RTSemFastMutexRelease(render_spu.syncMutex);
99 /* Make sure that the position is updated relative to the Qt main
100 * view */
101 renderspu_SystemWindowPosition(pWin, pWin->x, pWin->y);
102 }
103 }
104}
105
106/* Window event handler */
107pascal OSStatus
108windowEvtHndlr(EventHandlerCallRef myHandler, EventRef event, void* userData)
109{
110 WindowRef window = NULL;
111 OSStatus eventResult = eventNotHandledErr;
112 UInt32 class = GetEventClass (event);
113 UInt32 kind = GetEventKind (event);
114
115 /* If we aren't initialized or even deinitialized already (as on VM
116 * shutdown) do nothing. */
117 if (!render_spu.fInit)
118 return eventNotHandledErr;
119
120 /* Fetch the sender of the event */
121 GetEventParameter(event, kEventParamDirectObject, typeWindowRef,
122 NULL, sizeof(WindowRef), NULL, &window);
123 switch (class)
124 {
125 case kEventClassVBox:
126 {
127 switch (kind)
128 {
129 case kEventVBoxUpdateContext:
130 {
131#ifndef __LP64__ /** @todo port to 64-bit darwin! Need to check if this event is generated or not (it probably isn't). */
132 WindowInfo *wi1;
133 GetEventParameter(event, kEventParamUserData, typeVoidPtr,
134 NULL, sizeof(wi1), NULL, &wi1);
135 ContextInfo *context = renderspuGetWindowContext(wi1);
136 if (context &&
137 context->context)
138 {
139 AGLContext tmpContext = render_spu.ws.aglGetCurrentContext();
140 DEBUG_MSG_POETZSCH (("kEventVBoxUpdateContext %x %x\n", wi1, context->context));
141 RTSemFastMutexRequest(render_spu.syncMutex);
142 GLboolean result = render_spu.ws.aglSetCurrentContext(context->context);
143 if (result)
144 {
145 result = render_spu.ws.aglUpdateContext(context->context);
146 CHECK_AGL_RC (result, "Render SPU (windowEvtHndlr): UpdateContext Failed");
147 renderspu_SystemWindowApplyVisibleRegion(wi1);
148 /* Reapply the last active context */
149 if (tmpContext)
150 {
151 result = render_spu.ws.aglSetCurrentContext(tmpContext);
152 CHECK_AGL_RC (result, "Render SPU (windowEvtHndlr): SetCurrentContext Failed");
153 if (result)
154 {
155 result = render_spu.ws.aglUpdateContext(tmpContext);
156 CHECK_AGL_RC (result, "Render SPU (windowEvtHndlr): UpdateContext Failed");
157 }
158 }
159 }
160 RTSemFastMutexRelease(render_spu.syncMutex);
161 }
162 eventResult = noErr;
163#endif
164 break;
165 }
166 case kEventVBoxBoundsChanged:
167 {
168#ifndef __LP64__ /** @todo port to 64-bit darwin! Need to check if this event is generated or not (it probably isn't). */
169 HIPoint p;
170 GetEventParameter(event, kEventParamOrigin, typeHIPoint,
171 NULL, sizeof(p), NULL, &p);
172 HISize s;
173 GetEventParameter(event, kEventParamDimensions, typeHISize,
174 NULL, sizeof(s), NULL, &s);
175 HIRect r = CGRectMake (0, 0, s.width, s.height);
176 DEBUG_MSG_POETZSCH (("kEventVBoxBoundsChanged %f %f %f %f\n", p.x, p.y, s.width, s.height));
177 GLint l[4] = { 0,
178 0,
179 r.size.width,
180 r.size.height };
181 /* Update the root window clip region */
182 renderspu_SystemSetRootVisibleRegion(1, l);
183 /* Temporary save the current active context */
184 AGLContext tmpContext = render_spu.ws.aglGetCurrentContext();
185 crHashtableWalk(render_spu.windowTable, crClipRootHelper, NULL);
186 /* Reapply the last active context */
187 if (tmpContext)
188 {
189 RTSemFastMutexRequest(render_spu.syncMutex);
190 GLboolean result = render_spu.ws.aglSetCurrentContext(tmpContext);
191 CHECK_AGL_RC (result, "Render SPU (windowEvtHndlr): SetCurrentContext Failed");
192 /* Doesn't work with DirectX; Anyway doesn't */
193/* if (result)*/
194/* {*/
195/* result = render_spu.ws.aglUpdateContext(tmpContext);*/
196/* CHECK_AGL_RC (result, "Render SPU (windowEvtHndlr): UpdateContext Failed");*/
197/* }*/
198 RTSemFastMutexRelease(render_spu.syncMutex);
199 }
200 eventResult = noErr;
201#endif
202 break;
203 }
204 };
205 break;
206 }
207 break;
208 };
209
210 return eventResult;
211}
212
213GLboolean
214renderspu_SystemInitVisual(VisualInfo *visual)
215{
216 if(visual->visAttribs & CR_PBUFFER_BIT)
217 crWarning("Render SPU (renderspu_SystemInitVisual): PBuffers not support on Darwin/AGL yet.");
218
219 return GL_TRUE;
220}
221
222GLboolean
223renderspuChoosePixelFormat(ContextInfo *context, AGLPixelFormat *pix)
224{
225 GLbitfield visAttribs = context->visual->visAttribs;
226 GLint attribs[32];
227 GLint ind = 0;
228
229#define ATTR_ADD(s) ( attribs[ind++] = (s) )
230#define ATTR_ADDV(s,v) ( ATTR_ADD((s)), ATTR_ADD((v)) )
231
232 CRASSERT(render_spu.ws.aglChoosePixelFormat);
233
234 ATTR_ADD(AGL_RGBA);
235/* ATTR_ADDV(AGL_RED_SIZE, 1);
236 ATTR_ADDV(AGL_GREEN_SIZE, 1);
237 ATTR_ADDV(AGL_BLUE_SIZE, 1); */
238
239/* if( render_spu.fullscreen )*/
240/* ATTR_ADD(AGL_FULLSCREEN);*/
241
242 if( visAttribs & CR_ALPHA_BIT )
243 ATTR_ADDV(AGL_ALPHA_SIZE, 1);
244
245 if( visAttribs & CR_DOUBLE_BIT )
246 ATTR_ADD(AGL_DOUBLEBUFFER);
247
248 if( visAttribs & CR_STEREO_BIT )
249 ATTR_ADD(AGL_STEREO);
250
251 if( visAttribs & CR_DEPTH_BIT )
252 ATTR_ADDV(AGL_DEPTH_SIZE, 1);
253
254 if( visAttribs & CR_STENCIL_BIT )
255 ATTR_ADDV(AGL_STENCIL_SIZE, 1);
256
257 if( visAttribs & CR_ACCUM_BIT ) {
258 ATTR_ADDV(AGL_ACCUM_RED_SIZE, 1);
259 ATTR_ADDV(AGL_ACCUM_GREEN_SIZE, 1);
260 ATTR_ADDV(AGL_ACCUM_BLUE_SIZE, 1);
261 if( visAttribs & CR_ALPHA_BIT )
262 ATTR_ADDV(AGL_ACCUM_ALPHA_SIZE, 1);
263 }
264
265 if( visAttribs & CR_MULTISAMPLE_BIT ) {
266 ATTR_ADDV(AGL_SAMPLE_BUFFERS_ARB, 1);
267 ATTR_ADDV(AGL_SAMPLES_ARB, 4);
268 }
269
270 if( visAttribs & CR_OVERLAY_BIT )
271 ATTR_ADDV(AGL_LEVEL, 1);
272
273 ATTR_ADD(AGL_NONE);
274
275 *pix = render_spu.ws.aglChoosePixelFormat( NULL, 0, attribs );
276
277 return (*pix != NULL);
278}
279
280void
281renderspuDestroyPixelFormat(ContextInfo *context, AGLPixelFormat *pix)
282{
283 render_spu.ws.aglDestroyPixelFormat( *pix );
284 *pix = NULL;
285}
286
287GLboolean
288renderspu_SystemCreateContext(VisualInfo *visual, ContextInfo *context, ContextInfo *sharedContext)
289{
290 AGLPixelFormat pix;
291
292 (void) sharedContext;
293 CRASSERT(visual);
294 CRASSERT(context);
295
296 context->visual = visual;
297
298 if( !renderspuChoosePixelFormat(context, &pix) ) {
299 crError( "Render SPU (renderspu_SystemCreateContext): Unable to create pixel format" );
300 return GL_FALSE;
301 }
302
303 context->context = render_spu.ws.aglCreateContext( pix, NULL );
304 renderspuDestroyPixelFormat( context, &pix );
305
306 if( !context->context ) {
307 crError( "Render SPU (renderspu_SystemCreateContext): Could not create rendering context" );
308 return GL_FALSE;
309 }
310
311 return GL_TRUE;
312}
313
314void
315renderspu_SystemDestroyContext(ContextInfo *context)
316{
317 if(!context)
318 return;
319
320 render_spu.ws.aglSetDrawable(context->context, NULL);
321 render_spu.ws.aglSetCurrentContext(NULL);
322 if(context->context)
323 {
324 render_spu.ws.aglDestroyContext(context->context);
325 context->context = NULL;
326 }
327
328 context->visual = NULL;
329}
330
331void
332renderspuFullscreen(WindowInfo *window, GLboolean fullscreen)
333{
334 /* Real fullscreen isn't supported by VirtualBox */
335}
336
337GLboolean
338renderspuWindowAttachContext(WindowInfo *wi, WindowRef window,
339 ContextInfo *context)
340{
341 GLboolean result;
342
343 if(!context || !wi)
344 return render_spu.ws.aglSetCurrentContext( NULL );
345
346/* DEBUG_MSG_POETZSCH (("WindowAttachContext %d\n", wi->BltInfo.Base.id));*/
347
348 /* Flush old context first */
349 if (context->currentWindow->window != window)
350 render_spu.self.Flush();
351 /* If the window buffer name is uninitialized we have to create a new
352 * dummy context. */
353 if (wi->bufferName == -1)
354 {
355 DEBUG_MSG_POETZSCH (("WindowAttachContext: create context %d\n", wi->BltInfo.Base.id));
356 /* Use the same visual bits as those in the context structure */
357 AGLPixelFormat pix;
358 if( !renderspuChoosePixelFormat(context, &pix) )
359 {
360 crError( "Render SPU (renderspuWindowAttachContext): Unable to create pixel format" );
361 return GL_FALSE;
362 }
363 /* Create the dummy context */
364 wi->dummyContext = render_spu.ws.aglCreateContext( pix, NULL );
365 renderspuDestroyPixelFormat( context, &pix );
366 if( !wi->dummyContext )
367 {
368 crError( "Render SPU (renderspuWindowAttachContext): Could not create rendering context" );
369 return GL_FALSE;
370 }
371 AGLDrawable drawable;
372#ifdef __LP64__ /** @todo port to 64-bit darwin. */
373 drawable = NULL;
374#else
375 drawable = (AGLDrawable) GetWindowPort(window);
376#endif
377 /* New global buffer name */
378 wi->bufferName = render_spu.currentBufferName++;
379 /* Set the new buffer name to the dummy context. This enable the
380 * sharing of the same hardware buffer afterwards. */
381 result = render_spu.ws.aglSetInteger(wi->dummyContext, AGL_BUFFER_NAME, &wi->bufferName);
382 CHECK_AGL_RC (result, "Render SPU (renderspuWindowAttachContext): SetInteger Failed");
383 /* Assign the dummy context to the window */
384 result = render_spu.ws.aglSetDrawable(wi->dummyContext, drawable);
385 CHECK_AGL_RC (result, "Render SPU (renderspuWindowAttachContext): SetDrawable Failed");
386 }
387
388 AGLDrawable oldDrawable;
389 AGLDrawable newDrawable;
390
391 oldDrawable = render_spu.ws.aglGetDrawable(context->context);
392#ifdef __LP64__ /** @todo port to 64-bit darwin. */
393 newDrawable = oldDrawable;
394#else
395 newDrawable = (AGLDrawable) GetWindowPort(window);
396#endif
397 RTSemFastMutexRequest(render_spu.syncMutex);
398 /* Only switch the context if the drawable has changed */
399 if (oldDrawable != newDrawable)
400 {
401 /* Reset the current context */
402 result = render_spu.ws.aglSetDrawable(context->context, NULL);
403 CHECK_AGL_RC (result, "Render SPU (renderspuWindowAttachContext): SetDrawable Failed");
404 /* Set the buffer name of the dummy context to the current context
405 * also. After that both share the same hardware buffer. */
406 render_spu.ws.aglSetInteger (context->context, AGL_BUFFER_NAME, &wi->bufferName);
407 CHECK_AGL_RC (result, "Render SPU (renderspuWindowAttachContext): SetInteger Failed");
408 /* Set the new drawable */
409#ifdef __LP64__ /** @todo port to 64-bit darwin. */
410 result = -1;
411#else
412 result = render_spu.ws.aglSetDrawable(context->context, newDrawable);
413#endif
414 CHECK_AGL_RC (result, "Render SPU (renderspuWindowAttachContext): SetDrawable Failed");
415 renderspuSetWindowContext(window, context);
416 }
417 result = render_spu.ws.aglSetCurrentContext(context->context);
418 CHECK_AGL_RC (result, "Render SPU (renderspuWindowAttachContext): SetCurrentContext Failed");
419 result = render_spu.ws.aglUpdateContext(context->context);
420 CHECK_AGL_RC (result, "Render SPU (renderspuWindowAttachContext): UpdateContext Failed");
421 RTSemFastMutexRelease(render_spu.syncMutex);
422
423 return result;
424}
425
426GLboolean
427renderspu_SystemCreateWindow(VisualInfo *visual, GLboolean showIt,
428 WindowInfo *window)
429{
430 return GL_TRUE;
431}
432
433void renderspu_SystemReparentWindow(WindowInfo *)
434{
435 /* stub only */
436}
437
438void
439renderspu_SystemDestroyWindow(WindowInfo *window)
440{
441 CRASSERT(window);
442 CRASSERT(window->visual);
443
444 if(!window->nativeWindow)
445 {
446 EventRef evt;
447 OSStatus status = CreateEvent(NULL, kEventClassVBox, kEventVBoxDisposeWindow, 0, kEventAttributeNone, &evt);
448 CHECK_CARBON_RC_RETURN_VOID (status, "Render SPU (renderspu_SystemDestroyWindow): CreateEvent Failed");
449 status = SetEventParameter(evt, kEventParamWindowRef, typeWindowRef, sizeof (window->window), &window->window);
450 CHECK_CARBON_RC_RETURN_VOID (status, "Render SPU (renderspu_SystemDestroyWindow): SetEventParameter Failed");
451 status = PostEventToQueue(GetMainEventQueue(), evt, kEventPriorityStandard);
452 CHECK_CARBON_RC_RETURN_VOID (status, "Render SPU (renderspu_SystemDestroyWindow): PostEventToQueue Failed");
453 }
454
455 /* Delete the dummy context */
456 if(window->dummyContext)
457 {
458 render_spu.ws.aglSetDrawable(window->dummyContext, NULL);
459 render_spu.ws.aglDestroyContext(window->dummyContext);
460 window->dummyContext = NULL;
461 }
462
463 /* Reset some values */
464 window->bufferName = -1;
465 window->visual = NULL;
466 window->window = NULL;
467
468 if (window->hVisibleRegion)
469 {
470 DisposeRgn(window->hVisibleRegion);
471 window->hVisibleRegion = 0;
472 }
473}
474
475void
476renderspu_SystemWindowPosition(WindowInfo *window,
477 GLint x, GLint y)
478{
479 CRASSERT(window);
480 CRASSERT(window->window);
481
482 OSStatus status = noErr;
483 /* Send a event to the main thread, cause some function of Carbon aren't
484 * thread safe */
485 EventRef evt;
486 status = CreateEvent(NULL, kEventClassVBox, kEventVBoxMoveWindow, 0, kEventAttributeNone, &evt);
487 CHECK_CARBON_RC_RETURN_VOID (status, "Render SPU (renderspu_SystemWindowPosition): CreateEvent Failed");
488 status = SetEventParameter(evt, kEventParamWindowRef, typeWindowRef, sizeof(window->window), &window->window);
489 CHECK_CARBON_RC_RETURN_VOID (status, "Render SPU (renderspu_SystemWindowPosition): SetEventParameter Failed");
490 HIPoint p = CGPointMake (x, y);
491 status = SetEventParameter(evt, kEventParamOrigin, typeHIPoint, sizeof (p), &p);
492 CHECK_CARBON_RC_RETURN_VOID (status, "Render SPU (renderspu_SystemWindowPosition): SetEventParameter Failed");
493 status = SetEventParameter(evt, kEventParamUserData, typeVoidPtr, sizeof (window), &window);
494 CHECK_CARBON_RC_RETURN_VOID (status, "Render SPU (renderspu_SystemWindowPosition): SetEventParameter Failed");
495 status = PostEventToQueue(GetMainEventQueue(), evt, kEventPriorityStandard);
496 CHECK_CARBON_RC_RETURN_VOID (status, "Render SPU (renderspu_SystemWindowPosition): PostEventToQueue Failed");
497
498 /* save the new pos */
499 window->x = x;
500 window->y = y;
501}
502
503void
504renderspu_SystemWindowSize(WindowInfo *window, GLint w, GLint h)
505{
506 CRASSERT(window);
507 CRASSERT(window->window);
508
509 OSStatus status = noErr;
510 /* Send a event to the main thread, cause some function of Carbon aren't
511 * thread safe */
512 EventRef evt;
513 status = CreateEvent(NULL, kEventClassVBox, kEventVBoxResizeWindow, 0, kEventAttributeNone, &evt);
514 CHECK_CARBON_RC_RETURN_VOID (status, "Render SPU (renderspu_SystemWindowSize): CreateEvent Failed ");
515 status = SetEventParameter(evt, kEventParamWindowRef, typeWindowRef, sizeof(window->window), &window->window);
516 CHECK_CARBON_RC_RETURN_VOID (status, "Render SPU (renderspu_SystemWindowSize): SetEventParameter Failed");
517 HISize s = CGSizeMake (w, h);
518 status = SetEventParameter(evt, kEventParamDimensions, typeHISize, sizeof (s), &s);
519 CHECK_CARBON_RC_RETURN_VOID (status, "Render SPU (renderspu_SystemWindowSize): SetEventParameter Failed");
520 status = SetEventParameter(evt, kEventParamUserData, typeVoidPtr, sizeof (window), &window);
521 CHECK_CARBON_RC_RETURN_VOID (status, "Render SPU (renderspu_SystemWindowSize): SetEventParameter Failed");
522 status = PostEventToQueue(GetMainEventQueue(), evt, kEventPriorityStandard);
523 CHECK_CARBON_RC_RETURN_VOID (status, "Render SPU (renderspu_SystemWindowSize): SendEventToEventTarget Failed");
524
525 DEBUG_MSG_POETZSCH (("Size %d visible %d\n", window->BltInfo.Base.id, IsWindowVisible (window->window)));
526 /* save the new size */
527 window->BltInfo.width = w;
528 window->BltInfo.height = h;
529}
530
531void
532renderspu_SystemGetWindowGeometry(WindowInfo *window,
533 GLint *x, GLint *y,
534 GLint *w, GLint *h)
535{
536 CRASSERT(window);
537 CRASSERT(window->window);
538
539 OSStatus status = noErr;
540 Rect r;
541 status = GetWindowBounds(window->window, kWindowStructureRgn, &r);
542 CHECK_CARBON_RC_RETURN_VOID (status, "Render SPU (renderspu_SystemGetWindowGeometry): GetWindowBounds Failed");
543
544 *x = (int) r.left;
545 *y = (int) r.top;
546 *w = (int) (r.right - r.left);
547 *h = (int) (r.bottom - r.top);
548}
549
550void
551renderspu_SystemGetMaxWindowSize(WindowInfo *window,
552 GLint *w, GLint *h)
553{
554 CRASSERT(window);
555 CRASSERT(window->window);
556
557 OSStatus status = noErr;
558 HISize s;
559#ifdef __LP64__ /** @todo port to 64-bit darwin. */
560 status = -1;
561#else
562 status = GetWindowResizeLimits (window->window, NULL, &s);
563#endif
564 CHECK_CARBON_RC_RETURN_VOID (status, "Render SPU (renderspu_SystemGetMaxWindowSize): GetWindowResizeLimits Failed");
565
566 *w = s.width;
567 *h = s.height;
568}
569
570/* Either show or hide the render SPU's window. */
571void
572renderspu_SystemShowWindow(WindowInfo *window, GLboolean showIt)
573{
574 CRASSERT(window);
575 CRASSERT(window->window);
576
577 if (!IsValidWindowPtr(window->window))
578 return;
579
580 if(showIt)
581 {
582 /* Force moving the win to the right position before we show it */
583 renderspu_SystemWindowPosition (window, window->x, window->y);
584 OSStatus status = noErr;
585 /* Send a event to the main thread, cause some function of Carbon
586 * aren't thread safe */
587 EventRef evt;
588 status = CreateEvent(NULL, kEventClassVBox, kEventVBoxShowWindow, 0, kEventAttributeNone, &evt);
589 CHECK_CARBON_RC_RETURN_VOID (status, "Render SPU (renderspu_SystemShowWindow): CreateEvent Failed");
590 status = SetEventParameter(evt, kEventParamWindowRef, typeWindowRef, sizeof (window->window), &window->window);
591 CHECK_CARBON_RC_RETURN_VOID (status, "Render SPU (renderspu_SystemShowWindow): SetEventParameter Failed");
592 status = SetEventParameter(evt, kEventParamUserData, typeVoidPtr, sizeof (window), &window);
593 CHECK_CARBON_RC_RETURN_VOID (status, "Render SPU (renderspu_SystemWindowShow): SetEventParameter Failed");
594 //status = SendEventToEventTarget (evt, GetWindowEventTarget (HIViewGetWindow ((HIViewRef)render_spu_parent_window_id)));
595 status = PostEventToQueue(GetMainEventQueue(), evt, kEventPriorityStandard);
596 CHECK_CARBON_RC_RETURN_VOID (status, "Render SPU (renderspu_SystemShowWindow): PostEventToQueue Failed");
597 }
598 else
599 {
600 EventRef evt;
601 OSStatus status = CreateEvent(NULL, kEventClassVBox, kEventVBoxHideWindow, 0, kEventAttributeNone, &evt);
602 CHECK_CARBON_RC_RETURN_VOID (status, "Render SPU (renderspu_SystemShowWindow): CreateEvent Failed");
603 status = SetEventParameter(evt, kEventParamWindowRef, typeWindowRef, sizeof (window->window), &window->window);
604 CHECK_CARBON_RC_RETURN_VOID (status, "Render SPU (renderspu_SystemShowWindow): SetEventParameter Failed");
605 status = PostEventToQueue(GetMainEventQueue(), evt, kEventPriorityStandard);
606 CHECK_CARBON_RC_RETURN_VOID (status, "Render SPU (renderspu_SystemShowWindow): PostEventToQueue Failed");
607 }
608}
609
610void renderspu_SystemVBoxPresentComposition( WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR * pCompositor, const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry )
611{
612 renderspuVBoxPresentCompositionGeneric(window, pCompositor, pChangedEntry, 0, false);
613}
614
615void
616renderspu_SystemMakeCurrent(WindowInfo *window, GLint nativeWindow,
617 ContextInfo *context)
618{
619 Boolean result;
620/* DEBUG_MSG_POETZSCH (("makecurrent %d: \n", window->BltInfo.Base.id));*/
621
622 CRASSERT(render_spu.ws.aglSetCurrentContext);
623 //crDebug( "renderspu_SystemMakeCurrent( %x, %i, %x )", window, nativeWindow, context );
624
625 nativeWindow = 0;
626
627 if(window && context)
628 {
629 CRASSERT(window->window);
630 CRASSERT(context->context);
631
632 if(window->visual != context->visual)
633 {
634 crDebug("Render SPU (renderspu_SystemMakeCurrent): MakeCurrent visual mismatch (0x%x != 0x%x); remaking window.",
635 (uint)window->visual->visAttribs, (uint)context->visual->visAttribs);
636 /*
637 * XXX have to revisit this issue!!!
638 *
639 * But for now we destroy the current window
640 * and re-create it with the context's visual abilities
641 */
642 renderspu_SystemDestroyWindow(window);
643 renderspu_SystemCreateWindow(context->visual, window->visible,
644 window);
645 }
646
647 /* This is the normal case: rendering to the render SPU's own window */
648 result = renderspuWindowAttachContext(window, window->window,
649 context);
650 /* XXX this is a total hack to work around an NVIDIA driver bug */
651 if(render_spu.self.GetFloatv && context->haveWindowPosARB)
652 {
653 GLfloat f[4];
654 render_spu.self.GetFloatv(GL_CURRENT_RASTER_POSITION, f);
655 if (!window->everCurrent || f[1] < 0.0)
656 {
657 crDebug("Render SPU (renderspu_SystemMakeCurrent): Resetting raster pos");
658 render_spu.self.WindowPos2iARB(0, 0);
659 }
660 }
661 /* Reapply the visible regions */
662 renderspu_SystemWindowApplyVisibleRegion(window);
663 }
664 else
665 renderspuWindowAttachContext (0, 0, 0);
666}
667
668void
669renderspu_SystemSwapBuffers(WindowInfo *window, GLint flags)
670{
671 CRASSERT(window);
672 CRASSERT(window->window);
673
674 ContextInfo *context = renderspuGetWindowContext(window);
675
676 if(!context)
677 crError("Render SPU (renderspu_SystemSwapBuffers): SwapBuffers got a null context from the window");
678
679 RTSemFastMutexRequest(render_spu.syncMutex);
680// DEBUG_MSG_POETZSCH (("Swapped %d context %x visible: %d\n", window->BltInfo.Base.id, context->context, IsWindowVisible (window->window)));
681 if (context->visual &&
682 context->visual->visAttribs & CR_DOUBLE_BIT)
683 render_spu.ws.aglSwapBuffers(context->context);
684 else
685 glFlush();
686 RTSemFastMutexRelease(render_spu.syncMutex);
687
688 /* This method seems called very often. To prevent the dock using all free
689 * resources we update the dock only two times per second. */
690 uint64_t curTS = RTTimeMilliTS();
691 if ((curTS - render_spu.uiDockUpdateTS) > 500)
692 {
693 OSStatus status = noErr;
694 /* Send a event to the main thread, cause some function of Carbon aren't
695 * thread safe */
696 EventRef evt;
697 status = CreateEvent(NULL, kEventClassVBox, kEventVBoxUpdateDock, 0, kEventAttributeNone, &evt);
698 CHECK_CARBON_RC_RETURN_VOID (status, "Render SPU (renderspu_SystemSwapBuffers): CreateEvent Failed");
699 status = PostEventToQueue(GetMainEventQueue(), evt, kEventPriorityStandard);
700 CHECK_CARBON_RC_RETURN_VOID (status, "Render SPU (renderspu_SystemSwapBuffers): PostEventToQueue Failed");
701
702 render_spu.uiDockUpdateTS = curTS;
703 }
704}
705
706GLboolean renderspu_SystemWindowNeedEmptyPresent(WindowInfo *window)
707{
708 return GL_FALSE;
709}
710
711void renderspu_SystemWindowVisibleRegion(WindowInfo *window, GLint cRects, const GLint* pRects)
712{
713 CRASSERT(window);
714 CRASSERT(window->window);
715
716 /* Remember any additional clipping stuff e.g. seamless regions */
717 if (window->hVisibleRegion)
718 {
719 DisposeRgn(window->hVisibleRegion);
720 window->hVisibleRegion = 0;
721 }
722
723 if (cRects>0)
724 {
725 int i;
726 /* Create some temporary regions */
727 RgnHandle rgn = NewRgn();
728 SetEmptyRgn (rgn);
729 RgnHandle tmpRgn = NewRgn();
730 for (i=0; i<cRects; ++i)
731 {
732 SetRectRgn (tmpRgn,
733 pRects[4*i] , pRects[4*i+1],
734 pRects[4*i+2], pRects[4*i+3]);
735 //DEBUG_MSG_POETZSCH (("visible rect %d %d %d %d\n", pRects[4*i] , pRects[4*i+1],
736 // pRects[4*i+2], pRects[4*i+3]));
737 UnionRgn (rgn, tmpRgn, rgn);
738 }
739 DisposeRgn (tmpRgn);
740 window->hVisibleRegion = rgn;
741 }
742
743 renderspu_SystemWindowApplyVisibleRegion(window);
744}
745
746static void renderspu_SystemSetRootVisibleRegion(GLint cRects, GLint *pRects)
747{
748 /* Remember the visible region of the root window if there is one */
749 if (render_spu.hRootVisibleRegion)
750 {
751 DisposeRgn(render_spu.hRootVisibleRegion);
752 render_spu.hRootVisibleRegion = 0;
753 }
754
755 if (cRects>0)
756 {
757 int i;
758 render_spu.hRootVisibleRegion = NewRgn();
759 SetEmptyRgn (render_spu.hRootVisibleRegion);
760 RgnHandle tmpRgn = NewRgn();
761 for (i=0; i<cRects; ++i)
762 {
763 SetRectRgn (tmpRgn,
764 pRects[4*i] , pRects[4*i+1],
765 pRects[4*i+2], pRects[4*i+3]);
766 UnionRgn (render_spu.hRootVisibleRegion, tmpRgn, render_spu.hRootVisibleRegion);
767 }
768 DisposeRgn (tmpRgn);
769 }
770}
771
772/*Assumes that all regions are in the guest coordinates system*/
773static void renderspu_SystemWindowApplyVisibleRegion(WindowInfo *window)
774{
775 ContextInfo *c = renderspuGetWindowContext(window);
776 RgnHandle rgn;
777 GLboolean result = true;
778
779 DEBUG_MSG_POETZSCH (("ApplyVisibleRegion %x\n", window));
780
781 if (!c || !c->context) return;
782
783 rgn = NewRgn();
784 SetEmptyRgn(rgn);
785
786 if (render_spu.hRootVisibleRegion)
787 {
788 /* The render_spu.hRootVisibleRegion has coordinates from the root
789 * window. We intersect it with the rect of the OpenGL window we
790 * currently process. */
791 SetRectRgn(rgn,
792 window->x, window->y,
793 window->x + window->BltInfo.width,
794 window->y + window->BltInfo.height);
795 SectRgn(render_spu.hRootVisibleRegion, rgn, rgn);
796 /* Because the clipping is done in the coordinate space of the OpenGL
797 * window we have to remove the x/y position from the newly created
798 * region. */
799 OffsetRgn (rgn, -window->x, -window->y);
800 }
801 else
802 {
803 /* If there is not root clipping region is available, create a base
804 * region with the size of the target window. This covers all
805 * needed/possible space. */
806 SetRectRgn(rgn, 0, 0, window->BltInfo.width, window->BltInfo.height);
807 }
808
809 /* Now intersect the window clipping region with a additional region e.g.
810 * for the seamless mode. */
811 if (window->hVisibleRegion)
812 SectRgn(rgn, window->hVisibleRegion, rgn);
813
814 if (rgn && !EmptyRgn(rgn))
815 {
816 /* Set the clip region to the context */
817 result = render_spu.ws.aglSetInteger(c->context, AGL_CLIP_REGION, (const GLint*)rgn);
818 CHECK_AGL_RC (result, "Render SPU (renderspu_SystemWindowVisibleRegion): SetInteger Failed");
819 result = render_spu.ws.aglEnable(c->context, AGL_CLIP_REGION);
820 CHECK_AGL_RC (result, "Render SPU (renderspu_SystemWindowVisibleRegion): Enable Failed");
821 }
822 /* Clear the region structure */
823 DisposeRgn (rgn);
824}
825
826GLboolean
827renderspu_SystemVBoxCreateWindow(VisualInfo *visual, GLboolean showIt,
828 WindowInfo *window)
829{
830 CRASSERT(visual);
831 CRASSERT(window);
832
833 WindowAttributes winAttr = kWindowNoShadowAttribute | kWindowCompositingAttribute | kWindowIgnoreClicksAttribute | kWindowStandardHandlerAttribute | kWindowLiveResizeAttribute;
834 WindowClass winClass = kOverlayWindowClass;
835 Rect windowRect;
836 OSStatus status = noErr;
837
838 window->visual = visual;
839 window->nativeWindow = NULL;
840
841 if(window->window && IsValidWindowPtr(window->window))
842 {
843 EventRef evt;
844 status = CreateEvent(NULL, kEventClassVBox, kEventVBoxDisposeWindow, 0, kEventAttributeNone, &evt);
845 CHECK_CARBON_RC_RETURN (status, "Render SPU (renderspu_SystemVBoxCreateWindow): CreateEvent Failed", false);
846 status = SetEventParameter(evt, kEventParamWindowRef, typeWindowRef, sizeof (window->window), &window->window);
847 CHECK_CARBON_RC_RETURN (status, "Render SPU (renderspu_SystemVBoxCreateWindow): SetEventParameter Failed", false);
848 status = PostEventToQueue(GetMainEventQueue(), evt, kEventPriorityStandard);
849 CHECK_CARBON_RC_RETURN (status, "Render SPU (renderspu_SystemVBoxCreateWindow): PostEventToQueue Failed", false);
850 }
851
852 windowRect.left = window->x;
853 windowRect.top = window->y;
854 windowRect.right = window->x + window->BltInfo.width;
855 windowRect.bottom = window->y + window->BltInfo.height;
856
857 status = CreateNewWindow(winClass, winAttr, &windowRect, &window->window);
858 CHECK_CARBON_RC_RETURN (status, "Render SPU (renderspu_SystemVBoxCreateWindow): CreateNewWindow Failed", GL_FALSE);
859
860 /* We set a title for debugging purposes */
861 CFStringRef title_string;
862 title_string = CFStringCreateWithCStringNoCopy(NULL, window->title,
863 kCFStringEncodingMacRoman, NULL);
864 SetWindowTitleWithCFString(window->BltInfo.window, title_string);
865 CFRelease(title_string);
866
867 /* The parent has to be in its own group */
868 WindowRef parent = NULL;
869 if (render_spu_parent_window_id)
870 {
871 parent = HIViewGetWindow ((HIViewRef)render_spu_parent_window_id);
872 SetWindowGroup (parent, render_spu.pParentGroup);
873
874 }
875
876 /* Add the new window to the master group */
877 SetWindowGroup(window->window, render_spu.pMasterGroup);
878
879 /* This will be initialized on the first attempt to attach the global
880 * context to this new window */
881 window->bufferName = -1;
882 window->dummyContext = NULL;
883 window->hVisibleRegion = 0;
884
885 if(showIt)
886 renderspu_SystemShowWindow(window, GL_TRUE);
887
888 crDebug("Render SPU (renderspu_SystemVBoxCreateWindow): actual window (x, y, width, height): %d, %d, %d, %d",
889 window->x, window->y, window->BltInfo.width, window->BltInfo.height);
890
891 return GL_TRUE;
892}
893
894int renderspu_SystemInit()
895{
896 return VINF_SUCCESS;
897}
898
899int renderspu_SystemTerm()
900{
901 return VINF_SUCCESS;
902}
903
904void renderspu_SystemDefaultSharedContextChanged(ContextInfo *fromContext, ContextInfo *toContext)
905{
906
907}
Note: See TracBrowser for help on using the repository browser.

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