VirtualBox

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

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

crOpenGL/win: fix redraw concurrency

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id
檔案大小: 33.3 KB
 
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->BltInfo.Base.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->BltInfo.Base.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->BltInfo.Base.id, IsWindowVisible (window->window)));
523 /* save the new size */
524 window->BltInfo.width = w;
525 window->BltInfo.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 renderspu_SystemVBoxPresentComposition( WindowInfo *window, struct VBOXVR_SCR_COMPOSITOR * pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry )
610{
611 renderspuVBoxPresentCompositionGeneric(window, pCompositor, pChangedEntry, 0);
612}
613
614void
615renderspu_SystemMakeCurrent(WindowInfo *window, GLint nativeWindow,
616 ContextInfo *context)
617{
618 Boolean result;
619/* DEBUG_MSG_POETZSCH (("makecurrent %d: \n", window->BltInfo.Base.id));*/
620
621 CRASSERT(render_spu.ws.aglSetCurrentContext);
622 //crDebug( "renderspu_SystemMakeCurrent( %x, %i, %x )", window, nativeWindow, context );
623
624 nativeWindow = 0;
625
626 if(window && context)
627 {
628 CRASSERT(window->window);
629 CRASSERT(context->context);
630
631 if(window->visual != context->visual)
632 {
633 crDebug("Render SPU (renderspu_SystemMakeCurrent): MakeCurrent visual mismatch (0x%x != 0x%x); remaking window.",
634 (uint)window->visual->visAttribs, (uint)context->visual->visAttribs);
635 /*
636 * XXX have to revisit this issue!!!
637 *
638 * But for now we destroy the current window
639 * and re-create it with the context's visual abilities
640 */
641 renderspu_SystemDestroyWindow(window);
642 renderspu_SystemCreateWindow(context->visual, window->visible,
643 window);
644 }
645
646 /* This is the normal case: rendering to the render SPU's own window */
647 result = renderspuWindowAttachContext(window, window->window,
648 context);
649 /* XXX this is a total hack to work around an NVIDIA driver bug */
650 if(render_spu.self.GetFloatv && context->haveWindowPosARB)
651 {
652 GLfloat f[4];
653 render_spu.self.GetFloatv(GL_CURRENT_RASTER_POSITION, f);
654 if (!window->everCurrent || f[1] < 0.0)
655 {
656 crDebug("Render SPU (renderspu_SystemMakeCurrent): Resetting raster pos");
657 render_spu.self.WindowPos2iARB(0, 0);
658 }
659 }
660 /* Reapply the visible regions */
661 renderspu_SystemWindowApplyVisibleRegion(window);
662 }
663 else
664 renderspuWindowAttachContext (0, 0, 0);
665}
666
667void
668renderspu_SystemSwapBuffers(WindowInfo *window, GLint flags)
669{
670 CRASSERT(window);
671 CRASSERT(window->window);
672
673 ContextInfo *context = renderspuGetWindowContext(window);
674
675 if(!context)
676 crError("Render SPU (renderspu_SystemSwapBuffers): SwapBuffers got a null context from the window");
677
678 RTSemFastMutexRequest(render_spu.syncMutex);
679// DEBUG_MSG_POETZSCH (("Swapped %d context %x visible: %d\n", window->BltInfo.Base.id, context->context, IsWindowVisible (window->window)));
680 if (context->visual &&
681 context->visual->visAttribs & CR_DOUBLE_BIT)
682 render_spu.ws.aglSwapBuffers(context->context);
683 else
684 glFlush();
685 RTSemFastMutexRelease(render_spu.syncMutex);
686
687 /* This method seems called very often. To prevent the dock using all free
688 * resources we update the dock only two times per second. */
689 uint64_t curTS = RTTimeMilliTS();
690 if ((curTS - render_spu.uiDockUpdateTS) > 500)
691 {
692 OSStatus status = noErr;
693 /* Send a event to the main thread, cause some function of Carbon aren't
694 * thread safe */
695 EventRef evt;
696 status = CreateEvent(NULL, kEventClassVBox, kEventVBoxUpdateDock, 0, kEventAttributeNone, &evt);
697 CHECK_CARBON_RC_RETURN_VOID (status, "Render SPU (renderspu_SystemSwapBuffers): CreateEvent Failed");
698 status = PostEventToQueue(GetMainEventQueue(), evt, kEventPriorityStandard);
699 CHECK_CARBON_RC_RETURN_VOID (status, "Render SPU (renderspu_SystemSwapBuffers): PostEventToQueue Failed");
700
701 render_spu.uiDockUpdateTS = curTS;
702 }
703}
704
705void renderspu_SystemWindowVisibleRegion(WindowInfo *window, GLint cRects, GLint* pRects)
706{
707 CRASSERT(window);
708 CRASSERT(window->window);
709
710 /* Remember any additional clipping stuff e.g. seamless regions */
711 if (window->hVisibleRegion)
712 {
713 DisposeRgn(window->hVisibleRegion);
714 window->hVisibleRegion = 0;
715 }
716
717 if (cRects>0)
718 {
719 int i;
720 /* Create some temporary regions */
721 RgnHandle rgn = NewRgn();
722 SetEmptyRgn (rgn);
723 RgnHandle tmpRgn = NewRgn();
724 for (i=0; i<cRects; ++i)
725 {
726 SetRectRgn (tmpRgn,
727 pRects[4*i] , pRects[4*i+1],
728 pRects[4*i+2], pRects[4*i+3]);
729 //DEBUG_MSG_POETZSCH (("visible rect %d %d %d %d\n", pRects[4*i] , pRects[4*i+1],
730 // pRects[4*i+2], pRects[4*i+3]));
731 UnionRgn (rgn, tmpRgn, rgn);
732 }
733 DisposeRgn (tmpRgn);
734 window->hVisibleRegion = rgn;
735 }
736
737 renderspu_SystemWindowApplyVisibleRegion(window);
738}
739
740void renderspu_SystemSetRootVisibleRegion(GLint cRects, GLint *pRects)
741{
742 /* Remember the visible region of the root window if there is one */
743 if (render_spu.hRootVisibleRegion)
744 {
745 DisposeRgn(render_spu.hRootVisibleRegion);
746 render_spu.hRootVisibleRegion = 0;
747 }
748
749 if (cRects>0)
750 {
751 int i;
752 render_spu.hRootVisibleRegion = NewRgn();
753 SetEmptyRgn (render_spu.hRootVisibleRegion);
754 RgnHandle tmpRgn = NewRgn();
755 for (i=0; i<cRects; ++i)
756 {
757 SetRectRgn (tmpRgn,
758 pRects[4*i] , pRects[4*i+1],
759 pRects[4*i+2], pRects[4*i+3]);
760 UnionRgn (render_spu.hRootVisibleRegion, tmpRgn, render_spu.hRootVisibleRegion);
761 }
762 DisposeRgn (tmpRgn);
763 }
764}
765
766/*Assumes that all regions are in the guest coordinates system*/
767void renderspu_SystemWindowApplyVisibleRegion(WindowInfo *window)
768{
769 ContextInfo *c = renderspuGetWindowContext(window);
770 RgnHandle rgn;
771 GLboolean result = true;
772
773 DEBUG_MSG_POETZSCH (("ApplyVisibleRegion %x\n", window));
774
775 if (!c || !c->context) return;
776
777 rgn = NewRgn();
778 SetEmptyRgn(rgn);
779
780 if (render_spu.hRootVisibleRegion)
781 {
782 /* The render_spu.hRootVisibleRegion has coordinates from the root
783 * window. We intersect it with the rect of the OpenGL window we
784 * currently process. */
785 SetRectRgn(rgn,
786 window->x, window->y,
787 window->x + window->BltInfo.width,
788 window->y + window->BltInfo.height);
789 SectRgn(render_spu.hRootVisibleRegion, rgn, rgn);
790 /* Because the clipping is done in the coordinate space of the OpenGL
791 * window we have to remove the x/y position from the newly created
792 * region. */
793 OffsetRgn (rgn, -window->x, -window->y);
794 }
795 else
796 {
797 /* If there is not root clipping region is available, create a base
798 * region with the size of the target window. This covers all
799 * needed/possible space. */
800 SetRectRgn(rgn, 0, 0, window->BltInfo.width, window->BltInfo.height);
801 }
802
803 /* Now intersect the window clipping region with a additional region e.g.
804 * for the seamless mode. */
805 if (window->hVisibleRegion)
806 SectRgn(rgn, window->hVisibleRegion, rgn);
807
808 if (rgn && !EmptyRgn(rgn))
809 {
810 /* Set the clip region to the context */
811 result = render_spu.ws.aglSetInteger(c->context, AGL_CLIP_REGION, (const GLint*)rgn);
812 CHECK_AGL_RC (result, "Render SPU (renderspu_SystemWindowVisibleRegion): SetInteger Failed");
813 result = render_spu.ws.aglEnable(c->context, AGL_CLIP_REGION);
814 CHECK_AGL_RC (result, "Render SPU (renderspu_SystemWindowVisibleRegion): Enable Failed");
815 }
816 /* Clear the region structure */
817 DisposeRgn (rgn);
818}
819
820GLboolean
821renderspu_SystemVBoxCreateWindow(VisualInfo *visual, GLboolean showIt,
822 WindowInfo *window)
823{
824 CRASSERT(visual);
825 CRASSERT(window);
826
827 WindowAttributes winAttr = kWindowNoShadowAttribute | kWindowCompositingAttribute | kWindowIgnoreClicksAttribute | kWindowStandardHandlerAttribute | kWindowLiveResizeAttribute;
828 WindowClass winClass = kOverlayWindowClass;
829 Rect windowRect;
830 OSStatus status = noErr;
831
832 window->visual = visual;
833 window->nativeWindow = NULL;
834
835 if(window->window && IsValidWindowPtr(window->window))
836 {
837 EventRef evt;
838 status = CreateEvent(NULL, kEventClassVBox, kEventVBoxDisposeWindow, 0, kEventAttributeNone, &evt);
839 CHECK_CARBON_RC_RETURN (status, "Render SPU (renderspu_SystemVBoxCreateWindow): CreateEvent Failed", false);
840 status = SetEventParameter(evt, kEventParamWindowRef, typeWindowRef, sizeof (window->window), &window->window);
841 CHECK_CARBON_RC_RETURN (status, "Render SPU (renderspu_SystemVBoxCreateWindow): SetEventParameter Failed", false);
842 status = PostEventToQueue(GetMainEventQueue(), evt, kEventPriorityStandard);
843 CHECK_CARBON_RC_RETURN (status, "Render SPU (renderspu_SystemVBoxCreateWindow): PostEventToQueue Failed", false);
844 }
845
846 windowRect.left = window->x;
847 windowRect.top = window->y;
848 windowRect.right = window->x + window->BltInfo.width;
849 windowRect.bottom = window->y + window->BltInfo.height;
850
851 status = CreateNewWindow(winClass, winAttr, &windowRect, &window->window);
852 CHECK_CARBON_RC_RETURN (status, "Render SPU (renderspu_SystemVBoxCreateWindow): CreateNewWindow Failed", GL_FALSE);
853
854 /* We set a title for debugging purposes */
855 CFStringRef title_string;
856 title_string = CFStringCreateWithCStringNoCopy(NULL, window->title,
857 kCFStringEncodingMacRoman, NULL);
858 SetWindowTitleWithCFString(window->BltInfo.window, title_string);
859 CFRelease(title_string);
860
861 /* The parent has to be in its own group */
862 WindowRef parent = NULL;
863 if (render_spu_parent_window_id)
864 {
865 parent = HIViewGetWindow ((HIViewRef)render_spu_parent_window_id);
866 SetWindowGroup (parent, render_spu.pParentGroup);
867
868 }
869
870 /* Add the new window to the master group */
871 SetWindowGroup(window->window, render_spu.pMasterGroup);
872
873 /* This will be initialized on the first attempt to attach the global
874 * context to this new window */
875 window->bufferName = -1;
876 window->dummyContext = NULL;
877 window->hVisibleRegion = 0;
878
879 if(showIt)
880 renderspu_SystemShowWindow(window, GL_TRUE);
881
882 crDebug("Render SPU (renderspu_SystemVBoxCreateWindow): actual window (x, y, width, height): %d, %d, %d, %d",
883 window->x, window->y, window->BltInfo.width, window->BltInfo.height);
884
885 return GL_TRUE;
886}
887
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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