VirtualBox

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

Last change on this file since 46801 was 46801, checked in by vboxsync, 11 years ago

wddm/crOpenGL: more TexPresent fixes

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