VirtualBox

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

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

crOpenGL: visible regions fixes

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id
檔案大小: 26.6 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 if (!mural->bReceivedRects)
470 {
471 rc = CrVrScrCompositorEntryRemove(&mural->Compositor, &mural->CEntry);
472 if (!RT_SUCCESS(rc))
473 {
474 crWarning("CrVrScrCompositorEntryRemove failed, rc %d", rc);
475 goto end;
476 }
477 CrVrScrCompositorEntryInit(&mural->CEntry, &Tex);
478 /* initially set regions to all visible since this is what some guest assume
479 * and will not post any more visible regions command */
480 Rect.xLeft = 0;
481 Rect.xRight = width;
482 Rect.yTop = 0;
483 Rect.yBottom = height;
484 rc = CrVrScrCompositorEntryRegionsSet(&mural->Compositor, &mural->CEntry, NULL, 1, &Rect, NULL);
485 if (!RT_SUCCESS(rc))
486 {
487 crWarning("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc);
488 goto end;
489 }
490 }
491 else
492 {
493 rc = CrVrScrCompositorEntryTexUpdate(&mural->Compositor, &mural->CEntry, &Tex);
494 if (!RT_SUCCESS(rc))
495 {
496 crWarning("CrVrScrCompositorEntryTexUpdate failed, rc %d", rc);
497 goto end;
498 }
499 }
500
501 /* CrVrScrCompositorUnlock(&mural->Compositor); */
502 mural->width = width;
503 mural->height = height;
504
505 mural->fDataPresented = GL_FALSE;
506
507 if (cr_server.curClient && cr_server.curClient->currentMural == mural)
508 {
509 crStateGetCurrent()->buffer.width = mural->width;
510 crStateGetCurrent()->buffer.height = mural->height;
511 }
512
513 rc = CrVrScrCompositorEntryRegionsGet(&mural->Compositor, &mural->CEntry, &cRects, NULL, &pRects);
514 if (!RT_SUCCESS(rc))
515 {
516 crWarning("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc);
517 goto end;
518 }
519
520 if (mural->fRootVrOn)
521 {
522 rc = CrVrScrCompositorEntryRemove(&mural->RootVrCompositor, &mural->RootVrCEntry);
523 if (!RT_SUCCESS(rc))
524 {
525 crWarning("CrVrScrCompositorEntryRemove failed, rc %d", rc);
526 goto end;
527 }
528 CrVrScrCompositorEntryInit(&mural->RootVrCEntry, &Tex);
529
530 rc = CrVrScrCompositorEntryRegionsSet(&mural->RootVrCompositor, &mural->RootVrCEntry, NULL, cRects, pRects, NULL);
531 if (!RT_SUCCESS(rc))
532 {
533 crWarning("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc);
534 goto end;
535 }
536
537 crServerVBoxRootVrTranslateForMural(mural);
538 rc = CrVrScrCompositorEntryListIntersect(&mural->RootVrCompositor, &mural->RootVrCEntry, &cr_server.RootVr, NULL);
539 if (!RT_SUCCESS(rc))
540 {
541 crWarning("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc);
542 goto end;
543 }
544
545 rc = CrVrScrCompositorEntryRegionsGet(&mural->RootVrCompositor, &mural->RootVrCEntry, &cRects, NULL, &pRects);
546 if (!RT_SUCCESS(rc))
547 {
548 crWarning("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc);
549 goto end;
550 }
551 }
552 else
553 {
554 }
555
556 crServerCheckMuralGeometry(mural);
557
558 cr_server.head_spu->dispatch_table.WindowSize(mural->spuWindow, width, height);
559
560 cr_server.head_spu->dispatch_table.WindowVisibleRegion(mural->spuWindow, cRects, pRects);
561
562 if (mural->pvOutputRedirectInstance)
563 {
564 if (mural->fRootVrOn)
565 {
566 rc = CrVrScrCompositorEntryRegionsGet(&mural->Compositor, &mural->CEntry, &cRects, NULL, &pRects);
567 if (!RT_SUCCESS(rc))
568 {
569 crWarning("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc);
570 goto end;
571 }
572 }
573 /* @todo the code assumes that RTRECT == four GLInts. */
574 cr_server.outputRedirect.CRORVisibleRegion(mural->pvOutputRedirectInstance,
575 cRects, pRects);
576 }
577
578end:
579 /* 3. (so far not needed for resize, but in case it is in the future) re-set the compositor (see above comment) */
580 /* uncomment when needed */
581 /* NOTE: !!! we have mural->fHasPresentationData set to GL_FALSE above, so crServerVBoxCompositionReenable will have no effect in any way
582
583 */
584 crServerVBoxCompositionDisableLeave(mural, GL_FALSE);
585
586}
587
588void SERVER_DISPATCH_APIENTRY
589crServerDispatchWindowSize( GLint window, GLint width, GLint height )
590{
591 CRMuralInfo *mural;
592
593 /* crDebug("CRServer: Window %d size %d x %d", window, width, height);*/
594 mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window);
595 if (!mural) {
596#if EXTRA_WARN
597 crWarning("CRServer: invalid window %d passed to WindowSize()", window);
598#endif
599 return;
600 }
601
602 crServerMuralSize(mural, width, height);
603
604 if (cr_server.currentMural == mural)
605 {
606 crServerPerformMakeCurrent( mural, cr_server.currentCtxInfo );
607 }
608}
609
610
611void SERVER_DISPATCH_APIENTRY
612crServerDispatchWindowPosition( GLint window, GLint x, GLint y )
613{
614 CRMuralInfo *mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window);
615 GLboolean fForcePresent = GL_FALSE;
616 /* crDebug("CRServer: Window %d pos %d, %d", window, x, y);*/
617 if (!mural) {
618#if EXTRA_WARN
619 crWarning("CRServer: invalid window %d passed to WindowPosition()", window);
620#endif
621 return;
622 }
623// if (mural->gX != x || mural->gY != y)
624 {
625 /* since we're going to change the current compositor & the window we need to avoid
626 * renderspu fron dealing with inconsistent data, i.e. modified compositor and
627 * still unmodified window.
628 * So what we do is:
629 * 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
630 * 2. do necessary modifications
631 * 3. re-set the compositor */
632
633 /* 1. tell renderspu to stop using the current compositor (see above comment) */
634 crServerVBoxCompositionDisableEnter(mural);
635
636 /* 2. do necessary modifications (see above comment) */
637 /* 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 */
638
639 if (mural->gX != x || mural->gY != y)
640 {
641 if (mural->fRootVrOn)
642 {
643 fForcePresent = crServerVBoxCompositionPresentNeeded(mural);
644 }
645
646 mural->gX = x;
647 mural->gY = y;
648
649 /* the compositor lock is not needed actually since we have prevented renderspu from using the compositor */
650 /* CrVrScrCompositorLock(&mural->Compositor); */
651 /* no need to set position because the position is relative to window */
652 /*CrVrScrCompositorEntryPosSet(&mural->Compositor, &mural->CEntry, &Pos);*/
653 /*CrVrScrCompositorUnlock(&mural->Compositor);*/
654
655 if (mural->fRootVrOn)
656 {
657 uint32_t cRects;
658 const RTRECT *pRects;
659 int rc = crServerMuralSynchRootVr(mural, &cRects, &pRects);
660
661 if (RT_SUCCESS(rc))
662 {
663 cr_server.head_spu->dispatch_table.WindowVisibleRegion(mural->spuWindow, cRects, pRects);
664 }
665 else
666 {
667 crWarning("crServerMuralSynchRootVr failed, rc %d", rc);
668 }
669 }
670 }
671
672 crServerCheckMuralGeometry(mural);
673
674 /* 3. re-set the compositor (see above comment) */
675 crServerVBoxCompositionDisableLeave(mural, fForcePresent);
676 }
677}
678
679void SERVER_DISPATCH_APIENTRY
680crServerDispatchWindowVisibleRegion( GLint window, GLint cRects, const GLint *pRects )
681{
682 CRMuralInfo *mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window);
683 GLboolean fForcePresent = crServerVBoxCompositionPresentNeeded(mural);
684 bool fRegionsChanged = false;
685 int rc = VINF_SUCCESS;
686 if (!mural) {
687#if EXTRA_WARN
688 crWarning("CRServer: invalid window %d passed to WindowVisibleRegion()", window);
689#endif
690 return;
691 }
692
693 /* since we're going to change the current compositor & the window we need to avoid
694 * renderspu fron dealing with inconsistent data, i.e. modified compositor and
695 * still unmodified window.
696 * So what we do is:
697 * 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
698 * 2. do necessary modifications
699 * 3. re-set the compositor */
700
701 /* 1. tell renderspu to stop using the current compositor (see above comment) */
702 crServerVBoxCompositionDisableEnter(mural);
703
704 /* 2. do necessary modifications (see above comment) */
705 if (mural->pVisibleRects)
706 {
707 crFree(mural->pVisibleRects);
708 mural->pVisibleRects = NULL;
709 }
710
711 mural->cVisibleRects = cRects;
712 mural->bReceivedRects = GL_TRUE;
713 if (cRects)
714 {
715 mural->pVisibleRects = (GLint*) crAlloc(4*sizeof(GLint)*cRects);
716 if (!mural->pVisibleRects)
717 {
718 crError("Out of memory in crServerDispatchWindowVisibleRegion");
719 }
720 crMemcpy(mural->pVisibleRects, pRects, 4*sizeof(GLint)*cRects);
721 }
722
723 /* 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 */
724 /* the compositor lock is not needed actually since we have prevented renderspu from using the compositor */
725 /* CrVrScrCompositorLock(&mural->Compositor); */
726 rc = CrVrScrCompositorEntryRegionsSet(&mural->Compositor, &mural->CEntry, NULL, cRects, (const RTRECT *)pRects, &fRegionsChanged);
727 /*CrVrScrCompositorUnlock(&mural->Compositor);*/
728 if (!RT_SUCCESS(rc))
729 {
730 crWarning("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc);
731 goto end;
732 }
733
734 if (fRegionsChanged)
735 {
736 const RTRECT * pRealRects;
737 uint32_t cRealRects;
738
739 if (mural->fRootVrOn)
740 {
741 rc = CrVrScrCompositorEntryRegionsSet(&mural->RootVrCompositor, &mural->RootVrCEntry, NULL, cRects, (const RTRECT *)pRects, NULL);
742 if (!RT_SUCCESS(rc))
743 {
744 crWarning("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc);
745 goto end;
746 }
747
748 crServerVBoxRootVrTranslateForMural(mural);
749 rc = CrVrScrCompositorEntryListIntersect(&mural->RootVrCompositor, &mural->RootVrCEntry, &cr_server.RootVr, NULL);
750 if (!RT_SUCCESS(rc))
751 {
752 crWarning("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc);
753 goto end;
754 }
755
756 rc = CrVrScrCompositorEntryRegionsGet(&mural->RootVrCompositor, &mural->RootVrCEntry, &cRealRects, NULL, &pRealRects);
757 if (!RT_SUCCESS(rc))
758 {
759 crWarning("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc);
760 goto end;
761 }
762 }
763 else
764 {
765 rc = CrVrScrCompositorEntryRegionsGet(&mural->Compositor, &mural->CEntry, &cRealRects, NULL, &pRealRects);
766 if (!RT_SUCCESS(rc))
767 {
768 crWarning("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc);
769 goto end;
770 }
771 }
772
773 cr_server.head_spu->dispatch_table.WindowVisibleRegion(mural->spuWindow, cRealRects, pRealRects);
774
775 if (mural->pvOutputRedirectInstance)
776 {
777 if (mural->fRootVrOn)
778 {
779 rc = CrVrScrCompositorEntryRegionsGet(&mural->Compositor, &mural->CEntry, &cRealRects, NULL, &pRealRects);
780 if (!RT_SUCCESS(rc))
781 {
782 crWarning("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc);
783 goto end;
784 }
785 }
786 /* @todo the code assumes that RTRECT == four GLInts. */
787 cr_server.outputRedirect.CRORVisibleRegion(mural->pvOutputRedirectInstance, cRealRects, pRealRects);
788 }
789 }
790end:
791 /* 3. re-set the compositor (see above comment) */
792 crServerVBoxCompositionDisableLeave(mural, fForcePresent);
793}
794
795void SERVER_DISPATCH_APIENTRY
796crServerDispatchWindowShow( GLint window, GLint state )
797{
798 CRMuralInfo *mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window);
799 if (!mural) {
800#if EXTRA_WARN
801 crWarning("CRServer: invalid window %d passed to WindowShow()", window);
802#endif
803 return;
804 }
805
806 if (mural->fPresentMode && CR_SERVER_REDIR_F_DISPLAY)
807 {
808 cr_server.head_spu->dispatch_table.WindowShow(mural->spuWindow, state);
809 }
810
811 mural->bVisible = state;
812}
813
814
815GLint
816crServerSPUWindowID(GLint serverWindow)
817{
818 CRMuralInfo *mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, serverWindow);
819 if (!mural) {
820#if EXTRA_WARN
821 crWarning("CRServer: invalid window %d passed to crServerSPUWindowID()",
822 serverWindow);
823#endif
824 return -1;
825 }
826 return mural->spuWindow;
827}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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