VirtualBox

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

Last change on this file since 18735 was 18721, checked in by vboxsync, 16 years ago

crOpenGL-OSX: more clipping updates

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