VirtualBox

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

最後變更 在這個檔案從22473是 21785,由 vboxsync 提交於 15 年 前

OpenGL-OSX: Disable update context, cause it doesn't work with DirectX apps. (Seems not necessary anyway)

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

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