VirtualBox

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

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

crOpenGl;FE/Qt4: added initial 3D support on OSX for the mutli-monitor case (the dock still needs some work)

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