VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_window.c@ 45132

Last change on this file since 45132 was 45132, checked in by vboxsync, 12 years ago

crOpenGL: seamles mode support impl; bugfizes & cleanup

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 26.7 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 "server.h"
8#include "server_dispatch.h"
9#include "cr_mem.h"
10#include "cr_rand.h"
11#include "cr_string.h"
12
13GLint SERVER_DISPATCH_APIENTRY
14crServerDispatchWindowCreate(const char *dpyName, GLint visBits)
15{
16 return crServerDispatchWindowCreateEx(dpyName, visBits, -1);
17}
18
19GLint crServerMuralInit(CRMuralInfo *mural, const char *dpyName, GLint visBits, GLint preloadWinID)
20{
21 CRMuralInfo *defaultMural;
22 GLint dims[2];
23 GLint windowID = -1;
24 GLint spuWindow;
25 VBOXVR_TEXTURE Tex = {0};
26 RTRECT Rect;
27 int rc;
28
29 crMemset(mural, 0, sizeof (*mural));
30
31 rc = CrVrScrCompositorInit(&mural->Compositor);
32 if (!RT_SUCCESS(rc))
33 {
34 crWarning("CrVrScrCompositorInit failed, rc %d", rc);
35 return -1;
36 }
37
38 if (cr_server.fRootVrOn)
39 {
40 rc = CrVrScrCompositorInit(&mural->RootVrCompositor);
41 if (!RT_SUCCESS(rc))
42 {
43 crWarning("CrVrScrCompositorInit failed, rc %d", rc);
44 return -1;
45 }
46 }
47
48 /*
49 * Have first SPU make a new window.
50 */
51 spuWindow = cr_server.head_spu->dispatch_table.WindowCreate( dpyName, visBits );
52 if (spuWindow < 0) {
53 CrVrScrCompositorTerm(&mural->Compositor);
54 if (cr_server.fRootVrOn)
55 CrVrScrCompositorTerm(&mural->RootVrCompositor);
56 return spuWindow;
57 }
58
59 /* get initial window size */
60 cr_server.head_spu->dispatch_table.GetChromiumParametervCR(GL_WINDOW_SIZE_CR, spuWindow, GL_INT, 2, dims);
61
62 Tex.width = dims[0];
63 Tex.height = dims[1];
64 Tex.target = GL_TEXTURE_2D;
65 Tex.hwid = 0;
66 CrVrScrCompositorEntryInit(&mural->CEntry, &Tex);
67
68 if (cr_server.fRootVrOn)
69 {
70 CrVrScrCompositorEntryInit(&mural->RootVrCEntry, &Tex);
71 mural->fRootVrOn = GL_TRUE;
72 }
73
74 defaultMural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, 0);
75 CRASSERT(defaultMural);
76 mural->gX = 0;
77 mural->gY = 0;
78 mural->width = dims[0];
79 mural->height = dims[1];
80
81 cr_server.head_spu->dispatch_table.GetChromiumParametervCR(GL_WINDOW_VISIBILITY_CR, spuWindow, GL_INT, 1, dims);
82
83 mural->spuWindow = spuWindow;
84 mural->screenId = 0;
85 mural->bVisible = !!dims[0];
86 mural->fUseFBO = CR_SERVER_REDIR_NONE;
87
88 mural->cVisibleRects = 0;
89 mural->pVisibleRects = NULL;
90 mural->bReceivedRects = GL_FALSE;
91
92 mural->pvOutputRedirectInstance = NULL;
93
94 /* generate ID for this new window/mural (special-case for file conns) */
95 if (cr_server.curClient && cr_server.curClient->conn->type == CR_FILE)
96 windowID = spuWindow;
97 else
98 windowID = preloadWinID<0 ? (GLint)crHashtableAllocKeys( cr_server.muralTable, 1 ) : preloadWinID;
99
100 mural->CreateInfo.visualBits = visBits;
101 mural->CreateInfo.externalID = windowID;
102 mural->CreateInfo.pszDpyName = dpyName ? crStrdup(dpyName) : NULL;
103
104 CR_STATE_SHAREDOBJ_USAGE_INIT(mural);
105
106 crServerSetupOutputRedirect(mural);
107
108 Rect.xLeft = 0;
109 Rect.xRight = mural->width;
110 Rect.yTop = 0;
111 Rect.yBottom = mural->height;
112 rc = CrVrScrCompositorEntryRegionsSet(&mural->Compositor, &mural->CEntry, NULL, 1, &Rect, NULL);
113 if (!RT_SUCCESS(rc))
114 {
115 crWarning("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc);
116 return -1;
117 }
118
119 if (mural->fRootVrOn)
120 {
121 uint32_t cRects;
122 const RTRECT *pRects;
123 int rc = crServerMuralSynchRootVr(mural, &cRects, &pRects);
124 if (RT_SUCCESS(rc))
125 {
126 if (cRects != 1
127 || pRects[0].xLeft != 0 || pRects[0].yTop != 0
128 || pRects[0].xRight != mural->width || pRects[0].yBottom != mural->height)
129 {
130 /* do visible rects only ig they differ from the default */
131 cr_server.head_spu->dispatch_table.WindowVisibleRegion(mural->spuWindow, cRects, pRects);
132
133 if (mural->pvOutputRedirectInstance)
134 {
135 /* @todo the code assumes that RTRECT == four GLInts. */
136 cr_server.outputRedirect.CRORVisibleRegion(mural->pvOutputRedirectInstance,
137 cRects, pRects);
138 }
139 }
140 }
141 }
142
143 return windowID;
144}
145
146GLint
147crServerDispatchWindowCreateEx(const char *dpyName, GLint visBits, GLint preloadWinID)
148{
149 CRMuralInfo *mural;
150 GLint windowID = -1;
151
152 dpyName = "";
153
154 if (cr_server.sharedWindows) {
155 int pos, j;
156
157 /* find empty position in my (curclient) windowList */
158 for (pos = 0; pos < CR_MAX_WINDOWS; pos++) {
159 if (cr_server.curClient->windowList[pos] == 0) {
160 break;
161 }
162 }
163 if (pos == CR_MAX_WINDOWS) {
164 crWarning("Too many windows in crserver!");
165 return -1;
166 }
167
168 /* Look if any other client has a window for this slot */
169 for (j = 0; j < cr_server.numClients; j++) {
170 if (cr_server.clients[j]->windowList[pos] != 0) {
171 /* use that client's window */
172 windowID = cr_server.clients[j]->windowList[pos];
173 cr_server.curClient->windowList[pos] = windowID;
174 crServerReturnValue( &windowID, sizeof(windowID) ); /* real return value */
175 crDebug("CRServer: client %p sharing window %d",
176 cr_server.curClient, windowID);
177 return windowID;
178 }
179 }
180 }
181
182
183 /*
184 * Create a new mural for the new window.
185 */
186 mural = (CRMuralInfo *) crCalloc(sizeof(CRMuralInfo));
187 if (!mural)
188 {
189 crWarning("crCalloc failed!");
190 return -1;
191 }
192
193 windowID = crServerMuralInit(mural, dpyName, visBits, preloadWinID);
194 if (windowID < 0)
195 {
196 crWarning("crServerMuralInit failed!");
197 crServerReturnValue( &windowID, sizeof(windowID) );
198 crFree(mural);
199 return windowID;
200 }
201
202 crHashtableAdd(cr_server.muralTable, windowID, mural);
203
204 crDebug("CRServer: client %p created new window %d (SPU window %d)",
205 cr_server.curClient, windowID, mural->spuWindow);
206
207 if (windowID != -1 && !cr_server.bIsInLoadingState) {
208 int pos;
209 for (pos = 0; pos < CR_MAX_WINDOWS; pos++) {
210 if (cr_server.curClient->windowList[pos] == 0) {
211 cr_server.curClient->windowList[pos] = windowID;
212 break;
213 }
214 }
215 }
216
217 /* ensure we have a dummy mural created right away to avoid potential deadlocks on VM shutdown */
218 crServerGetDummyMural(mural->CreateInfo.visualBits);
219
220 crServerReturnValue( &windowID, sizeof(windowID) );
221 return windowID;
222}
223
224static bool crServerVBoxTranslateIntersectRect(CRMuralInfo *mural, const RTRECT *pSrcRect, PRTRECT pDstRect)
225{
226 int32_t xLeft = RT_MAX(mural->gX, pSrcRect->xRight);
227 int32_t yTop = RT_MAX(mural->gY, pSrcRect->yBottom);
228 int32_t xRight = RT_MIN(mural->gX + mural->width, pSrcRect->xLeft);
229 int32_t yBottom = RT_MIN(mural->gY + mural->height, pSrcRect->yTop);
230
231 if (xLeft < xRight && yTop < yBottom)
232 {
233 pDstRect->xLeft = xLeft;
234 pDstRect->yTop = yTop;
235 pDstRect->xRight = xRight;
236 pDstRect->yBottom = yBottom;
237 return true;
238 }
239
240 return false;
241}
242
243static void crServerVBoxRootVrTranslateForMural(CRMuralInfo *mural)
244{
245 int32_t dx = cr_server.RootVrCurPoint.x - mural->gX;
246 int32_t dy = cr_server.RootVrCurPoint.y - mural->gY;
247
248 VBoxVrListTranslate(&cr_server.RootVr, dx, dy);
249}
250
251static int crServerRemoveClientWindow(CRClient *pClient, GLint window)
252{
253 int pos;
254
255 for (pos = 0; pos < CR_MAX_WINDOWS; ++pos)
256 {
257 if (pClient->windowList[pos] == window)
258 {
259 pClient->windowList[pos] = 0;
260 return true;
261 }
262 }
263
264 return false;
265}
266
267void crServerMuralTerm(CRMuralInfo *mural)
268{
269 if (mural->pvOutputRedirectInstance)
270 {
271 cr_server.outputRedirect.CROREnd(mural->pvOutputRedirectInstance);
272 mural->pvOutputRedirectInstance = NULL;
273 }
274
275 crServerRedirMuralFBO(mural, CR_SERVER_REDIR_NONE);
276 crServerDeleteMuralFBO(mural);
277
278 if (cr_server.currentMural == mural)
279 {
280 CRMuralInfo *dummyMural = crServerGetDummyMural(cr_server.MainContextInfo.CreateInfo.visualBits);
281 /* reset the current context to some dummy values to ensure render spu does not switch to a default "0" context,
282 * which might lead to muralFBO (offscreen rendering) gl entities being created in a scope of that context */
283 cr_server.head_spu->dispatch_table.MakeCurrent(dummyMural->spuWindow, 0, cr_server.MainContextInfo.SpuContext);
284 cr_server.currentWindow = -1;
285 cr_server.currentMural = NULL;
286 }
287 else
288 {
289 CRASSERT(cr_server.currentWindow != mural->CreateInfo.externalID);
290 }
291
292
293 cr_server.head_spu->dispatch_table.WindowDestroy( mural->spuWindow );
294
295 if (mural->pVisibleRects)
296 {
297 crFree(mural->pVisibleRects);
298 }
299
300 if (mural->CreateInfo.pszDpyName)
301 crFree(mural->CreateInfo.pszDpyName);
302}
303
304static void crServerCleanupCtxMuralRefsCB(unsigned long key, void *data1, void *data2)
305{
306 CRContextInfo *ctxInfo = (CRContextInfo *) data1;
307 CRMuralInfo *mural = (CRMuralInfo *) data2;
308
309 if (ctxInfo->currentMural == mural)
310 ctxInfo->currentMural = NULL;
311}
312
313void SERVER_DISPATCH_APIENTRY
314crServerDispatchWindowDestroy( GLint window )
315{
316 CRMuralInfo *mural;
317 int32_t client;
318 CRClientNode *pNode;
319 int found=false;
320
321 if (!window)
322 {
323 crWarning("Unexpected attempt to delete default mural, ignored!");
324 return;
325 }
326
327 mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window);
328 if (!mural) {
329 crWarning("CRServer: invalid window %d passed to WindowDestroy()", window);
330 return;
331 }
332
333 crDebug("CRServer: Destroying window %d (spu window %d)", window, mural->spuWindow);
334
335 crHashtableWalk(cr_server.contextTable, crServerCleanupCtxMuralRefsCB, mural);
336
337 crServerMuralTerm(mural);
338
339 CRASSERT(cr_server.currentWindow != window);
340
341 if (cr_server.curClient)
342 {
343 if (cr_server.curClient->currentMural == mural)
344 {
345 cr_server.curClient->currentMural = NULL;
346 cr_server.curClient->currentWindow = -1;
347 }
348
349 found = crServerRemoveClientWindow(cr_server.curClient, window);
350
351 /*Same as with contexts, some apps destroy it not in a thread where it was created*/
352 if (!found)
353 {
354 for (client=0; client<cr_server.numClients; ++client)
355 {
356 if (cr_server.clients[client]==cr_server.curClient)
357 continue;
358
359 found = crServerRemoveClientWindow(cr_server.clients[client], window);
360
361 if (found) break;
362 }
363 }
364
365 if (!found)
366 {
367 pNode=cr_server.pCleanupClient;
368
369 while (pNode && !found)
370 {
371 found = crServerRemoveClientWindow(pNode->pClient, window);
372 pNode = pNode->next;
373 }
374 }
375
376 CRASSERT(found);
377 }
378
379 /*Make sure this window isn't active in other clients*/
380 for (client=0; client<cr_server.numClients; ++client)
381 {
382 if (cr_server.clients[client]->currentMural == mural)
383 {
384 cr_server.clients[client]->currentMural = NULL;
385 cr_server.clients[client]->currentWindow = -1;
386 }
387 }
388
389 pNode=cr_server.pCleanupClient;
390 while (pNode)
391 {
392 if (pNode->pClient->currentMural == mural)
393 {
394 pNode->pClient->currentMural = NULL;
395 pNode->pClient->currentWindow = -1;
396 }
397 pNode = pNode->next;
398 }
399
400 CrVrScrCompositorTerm(&mural->Compositor);
401
402 if (mural->fRootVrOn)
403 CrVrScrCompositorTerm(&mural->RootVrCompositor);
404
405 crHashtableDelete(cr_server.muralTable, window, crFree);
406}
407
408int crServerMuralSynchRootVr(CRMuralInfo *mural, uint32_t *pcRects, const RTRECT **ppRects)
409{
410 int rc;
411
412 rc = CrVrScrCompositorEntryRegionsGet(&mural->Compositor, &mural->CEntry, pcRects, NULL, ppRects);
413 if (!RT_SUCCESS(rc))
414 {
415 crWarning("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc);
416 return rc;
417 }
418
419 rc = CrVrScrCompositorEntryRegionsSet(&mural->RootVrCompositor, &mural->RootVrCEntry, NULL, *pcRects, *ppRects, NULL);
420 if (!RT_SUCCESS(rc))
421 {
422 crWarning("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc);
423 return rc;
424 }
425
426 crServerVBoxRootVrTranslateForMural(mural);
427 rc = CrVrScrCompositorEntryListIntersect(&mural->RootVrCompositor, &mural->RootVrCEntry, &cr_server.RootVr, NULL);
428 if (!RT_SUCCESS(rc))
429 {
430 crWarning("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc);
431 return rc;
432 }
433
434 rc = CrVrScrCompositorEntryRegionsGet(&mural->RootVrCompositor, &mural->RootVrCEntry, pcRects, NULL, ppRects);
435 if (!RT_SUCCESS(rc))
436 {
437 crWarning("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc);
438 return rc;
439 }
440
441 return VINF_SUCCESS;
442}
443
444void crServerMuralSize(CRMuralInfo *mural, GLint width, GLint height)
445{
446 if (mural->width != width || mural->height != height)
447 {
448 uint32_t cRects;
449 const RTRECT *pRects;
450 RTRECT Rect;
451 VBOXVR_TEXTURE Tex;
452 int rc = VINF_SUCCESS;
453 Tex.width = width;
454 Tex.height = height;
455 Tex.target = GL_TEXTURE_2D;
456 Tex.hwid = 0;
457
458
459 /* since we're going to change the current compositor & the window we need to avoid
460 * renderspu fron dealing with inconsistent data, i.e. modified compositor and
461 * still unmodified window.
462 * So what we do is:
463 * 1. tell renderspu to stop using the current compositor -> renderspu would do necessary synchronization with its redraw thread to ensure compositor is no longer used
464 * 2. do necessary modifications
465 * 3. (so far not needed for resize, but in case it is in the future) re-set the compositor */
466
467 /* 1. tell renderspu to stop using the current compositor (see above comment) */
468 crServerVBoxCompositionDisable(mural);
469
470 /* 2. do necessary modifications (see above comment) */
471 /* NOTE: we can do it even if mural->fUseFBO == CR_SERVER_REDIR_NONE to make sure the compositor data is always up to date */
472 /* the compositor lock is not needed actually since we have prevented renderspu from using the compositor */
473 /* CrVrScrCompositorLock(&mural->Compositor); */
474 rc = CrVrScrCompositorEntryRemove(&mural->Compositor, &mural->CEntry);
475 if (!RT_SUCCESS(rc))
476 {
477 crWarning("CrVrScrCompositorEntryRemove failed, rc %d", rc);
478 return;
479 }
480 CrVrScrCompositorEntryInit(&mural->CEntry, &Tex);
481 /* initially set regions to all visible since this is what some guest assume
482 * and will not post any more visible regions command */
483 Rect.xLeft = 0;
484 Rect.xRight = width;
485 Rect.yTop = 0;
486 Rect.yBottom = height;
487 rc = CrVrScrCompositorEntryRegionsSet(&mural->Compositor, &mural->CEntry, NULL, 1, &Rect, NULL);
488 if (!RT_SUCCESS(rc))
489 {
490 crWarning("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc);
491 return;
492 }
493 /* CrVrScrCompositorUnlock(&mural->Compositor); */
494 mural->width = width;
495 mural->height = height;
496
497 if (cr_server.currentMural == mural)
498 {
499 crStateGetCurrent()->buffer.width = mural->width;
500 crStateGetCurrent()->buffer.height = mural->height;
501 }
502
503 if (mural->fRootVrOn)
504 {
505 rc = CrVrScrCompositorEntryRemove(&mural->RootVrCompositor, &mural->RootVrCEntry);
506 if (!RT_SUCCESS(rc))
507 {
508 crWarning("CrVrScrCompositorEntryRemove failed, rc %d", rc);
509 return;
510 }
511 CrVrScrCompositorEntryInit(&mural->RootVrCEntry, &Tex);
512 /* initially set regions to all visible since this is what some guest assume
513 * and will not post any more visible regions command */
514 Rect.xLeft = 0;
515 Rect.xRight = width;
516 Rect.yTop = 0;
517 Rect.yBottom = height;
518 rc = CrVrScrCompositorEntryRegionsSet(&mural->RootVrCompositor, &mural->RootVrCEntry, NULL, 1, &Rect, NULL);
519 if (!RT_SUCCESS(rc))
520 {
521 crWarning("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc);
522 return;
523 }
524
525 crServerVBoxRootVrTranslateForMural(mural);
526 rc = CrVrScrCompositorEntryListIntersect(&mural->RootVrCompositor, &mural->RootVrCEntry, &cr_server.RootVr, NULL);
527 if (!RT_SUCCESS(rc))
528 {
529 crWarning("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc);
530 return;
531 }
532
533 rc = CrVrScrCompositorEntryRegionsGet(&mural->RootVrCompositor, &mural->RootVrCEntry, &cRects, NULL, &pRects);
534 if (!RT_SUCCESS(rc))
535 {
536 crWarning("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc);
537 return;
538 }
539 }
540 else
541 {
542 rc = CrVrScrCompositorEntryRegionsGet(&mural->Compositor, &mural->CEntry, &cRects, NULL, &pRects);
543 if (!RT_SUCCESS(rc))
544 {
545 crWarning("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc);
546 return;
547 }
548 }
549
550 crServerCheckMuralGeometry(mural);
551
552 cr_server.head_spu->dispatch_table.WindowSize(mural->spuWindow, width, height);
553
554 cr_server.head_spu->dispatch_table.WindowVisibleRegion(mural->spuWindow, cRects, pRects);
555
556 if (mural->pvOutputRedirectInstance)
557 {
558 /* @todo the code assumes that RTRECT == four GLInts. */
559 cr_server.outputRedirect.CRORVisibleRegion(mural->pvOutputRedirectInstance,
560 cRects, (RTRECT *)pRects);
561 }
562
563 /* 3. (so far not needed for resize, but in case it is in the future) re-set the compositor (see above comment) */
564 /* uncomment when needed */
565 /* NOTE: !!! we have mural->fHasPresentationData set to GL_FALSE above, so crServerVBoxCompositionReenable will have no effect in any way
566 crServerVBoxCompositionReenable(mural);
567 */
568 }
569}
570
571void SERVER_DISPATCH_APIENTRY
572crServerDispatchWindowSize( GLint window, GLint width, GLint height )
573{
574 CRMuralInfo *mural;
575
576 /* crDebug("CRServer: Window %d size %d x %d", window, width, height);*/
577 mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window);
578 if (!mural) {
579#if EXTRA_WARN
580 crWarning("CRServer: invalid window %d passed to WindowSize()", window);
581#endif
582 return;
583 }
584
585 crServerMuralSize(mural, width, height);
586
587 if (cr_server.currentMural == mural)
588 {
589 crServerPerformMakeCurrent( mural, cr_server.currentCtxInfo );
590 }
591}
592
593
594void SERVER_DISPATCH_APIENTRY
595crServerDispatchWindowPosition( GLint window, GLint x, GLint y )
596{
597 CRMuralInfo *mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window);
598 GLboolean fForcePresent = GL_FALSE;
599 /* crDebug("CRServer: Window %d pos %d, %d", window, x, y);*/
600 if (!mural) {
601#if EXTRA_WARN
602 crWarning("CRServer: invalid window %d passed to WindowPosition()", window);
603#endif
604 return;
605 }
606// if (mural->gX != x || mural->gY != y)
607 {
608 /* since we're going to change the current compositor & the window we need to avoid
609 * renderspu fron dealing with inconsistent data, i.e. modified compositor and
610 * still unmodified window.
611 * So what we do is:
612 * 1. tell renderspu to stop using the current compositor -> renderspu would do necessary synchronization with its redraw thread to ensure compositor is no longer used
613 * 2. do necessary modifications
614 * 3. re-set the compositor */
615
616 /* 1. tell renderspu to stop using the current compositor (see above comment) */
617 crServerVBoxCompositionDisable(mural);
618
619 /* 2. do necessary modifications (see above comment) */
620 /* NOTE: we can do it even if mural->fUseFBO == CR_SERVER_REDIR_NONE to make sure the compositor data is always up to date */
621
622 if (mural->gX != x || mural->gY != y)
623 {
624 if (mural->fRootVrOn)
625 {
626 fForcePresent = crServerVBoxCompositionPresentNeeded(mural);
627 }
628
629 mural->gX = x;
630 mural->gY = y;
631
632 /* the compositor lock is not needed actually since we have prevented renderspu from using the compositor */
633 /* CrVrScrCompositorLock(&mural->Compositor); */
634 /* no need to set position because the position is relative to window */
635 /*CrVrScrCompositorEntryPosSet(&mural->Compositor, &mural->CEntry, &Pos);*/
636 /*CrVrScrCompositorUnlock(&mural->Compositor);*/
637
638 if (mural->fRootVrOn)
639 {
640 uint32_t cRects;
641 const RTRECT *pRects;
642 int rc = crServerMuralSynchRootVr(mural, &cRects, &pRects);
643
644 if (RT_SUCCESS(rc))
645 {
646 cr_server.head_spu->dispatch_table.WindowVisibleRegion(mural->spuWindow, cRects, pRects);
647
648 if (mural->pvOutputRedirectInstance)
649 {
650 /* @todo the code assumes that RTRECT == four GLInts. */
651 cr_server.outputRedirect.CRORVisibleRegion(mural->pvOutputRedirectInstance,
652 cRects, pRects);
653 }
654 }
655 else
656 {
657 crWarning("crServerMuralSynchRootVr failed, rc %d", rc);
658 }
659 }
660 }
661
662 crServerCheckMuralGeometry(mural);
663
664 /* 3. re-set the compositor (see above comment) */
665 crServerVBoxCompositionReenable(mural, fForcePresent);
666 }
667}
668
669void SERVER_DISPATCH_APIENTRY
670crServerDispatchWindowVisibleRegion( GLint window, GLint cRects, const GLint *pRects )
671{
672 CRMuralInfo *mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window);
673 GLboolean fForcePresent = crServerVBoxCompositionPresentNeeded(mural);
674 bool fRegionsChanged = false;
675 int rc = VINF_SUCCESS;
676 if (!mural) {
677#if EXTRA_WARN
678 crWarning("CRServer: invalid window %d passed to WindowVisibleRegion()", window);
679#endif
680 return;
681 }
682
683 /* since we're going to change the current compositor & the window we need to avoid
684 * renderspu fron dealing with inconsistent data, i.e. modified compositor and
685 * still unmodified window.
686 * So what we do is:
687 * 1. tell renderspu to stop using the current compositor -> renderspu would do necessary synchronization with its redraw thread to ensure compositor is no longer used
688 * 2. do necessary modifications
689 * 3. re-set the compositor */
690
691 /* 1. tell renderspu to stop using the current compositor (see above comment) */
692 crServerVBoxCompositionDisable(mural);
693
694 /* 2. do necessary modifications (see above comment) */
695 if (mural->pVisibleRects)
696 {
697 crFree(mural->pVisibleRects);
698 mural->pVisibleRects = NULL;
699 }
700
701 mural->cVisibleRects = cRects;
702 mural->bReceivedRects = GL_TRUE;
703 if (cRects)
704 {
705 mural->pVisibleRects = (GLint*) crAlloc(4*sizeof(GLint)*cRects);
706 if (!mural->pVisibleRects)
707 {
708 crError("Out of memory in crServerDispatchWindowVisibleRegion");
709 }
710 crMemcpy(mural->pVisibleRects, pRects, 4*sizeof(GLint)*cRects);
711 }
712
713 /* NOTE: we can do it even if mural->fUseFBO = CR_SERVER_REDIR_NONE to make sure the compositor data is always up to date */
714 /* the compositor lock is not needed actually since we have prevented renderspu from using the compositor */
715 /* CrVrScrCompositorLock(&mural->Compositor); */
716 rc = CrVrScrCompositorEntryRegionsSet(&mural->Compositor, &mural->CEntry, NULL, cRects, (const RTRECT *)pRects, &fRegionsChanged);
717 /*CrVrScrCompositorUnlock(&mural->Compositor);*/
718 if (!RT_SUCCESS(rc))
719 {
720 crWarning("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc);
721 return;
722 }
723
724 if (fRegionsChanged)
725 {
726 if (mural->fRootVrOn)
727 {
728 rc = CrVrScrCompositorEntryRegionsSet(&mural->RootVrCompositor, &mural->RootVrCEntry, NULL, cRects, (const RTRECT *)pRects, NULL);
729 if (!RT_SUCCESS(rc))
730 {
731 crWarning("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc);
732 return;
733 }
734
735 crServerVBoxRootVrTranslateForMural(mural);
736 rc = CrVrScrCompositorEntryListIntersect(&mural->RootVrCompositor, &mural->RootVrCEntry, &cr_server.RootVr, NULL);
737 if (!RT_SUCCESS(rc))
738 {
739 crWarning("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc);
740 return;
741 }
742
743 rc = CrVrScrCompositorEntryRegionsGet(&mural->RootVrCompositor, &mural->RootVrCEntry, &cRects, NULL, (const RTRECT **)&pRects);
744 if (!RT_SUCCESS(rc))
745 {
746 crWarning("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc);
747 return;
748 }
749 }
750 else
751 {
752 rc = CrVrScrCompositorEntryRegionsGet(&mural->Compositor, &mural->CEntry, &cRects, NULL, (const RTRECT **)&pRects);
753 if (!RT_SUCCESS(rc))
754 {
755 crWarning("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc);
756 return;
757 }
758 }
759
760 cr_server.head_spu->dispatch_table.WindowVisibleRegion(mural->spuWindow, cRects, pRects);
761
762 if (mural->pvOutputRedirectInstance)
763 {
764 /* @todo the code assumes that RTRECT == four GLInts. */
765 cr_server.outputRedirect.CRORVisibleRegion(mural->pvOutputRedirectInstance,
766 cRects, (RTRECT *)pRects);
767 }
768 }
769
770 /* 3. re-set the compositor (see above comment) */
771 crServerVBoxCompositionReenable(mural, fForcePresent);
772}
773
774void SERVER_DISPATCH_APIENTRY
775crServerDispatchWindowShow( GLint window, GLint state )
776{
777 CRMuralInfo *mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window);
778 if (!mural) {
779#if EXTRA_WARN
780 crWarning("CRServer: invalid window %d passed to WindowShow()", window);
781#endif
782 return;
783 }
784
785 if (mural->fUseFBO != CR_SERVER_REDIR_FBO_RAM)
786 {
787 cr_server.head_spu->dispatch_table.WindowShow(mural->spuWindow, state);
788 }
789
790 mural->bVisible = state;
791}
792
793
794GLint
795crServerSPUWindowID(GLint serverWindow)
796{
797 CRMuralInfo *mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, serverWindow);
798 if (!mural) {
799#if EXTRA_WARN
800 crWarning("CRServer: invalid window %d passed to crServerSPUWindowID()",
801 serverWindow);
802#endif
803 return -1;
804 }
805 return mural->spuWindow;
806}
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