VirtualBox

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

Last change on this file since 20175 was 18830, checked in by vboxsync, 16 years ago

crOpenGL-OSX: Do an additional check if we are initialized when we get messages from the Qt thread.

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