VirtualBox

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

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

crOpenGL: fix window mgmt

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

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