VirtualBox

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

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

crOpenGL/VRDP: always show 3D window unles in Headles mode

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

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