VirtualBox

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

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

crOpenGL: don't notify event when there is no parent window

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 26.6 KB
Line 
1/* Copyright (c) 2001, Stanford University
2 * All rights reserved
3 *
4 * See the file LICENSE.txt for information on redistributing this software.
5 */
6
7#include "server.h"
8#include "server_dispatch.h"
9#include "cr_mem.h"
10#include "cr_rand.h"
11#include "cr_string.h"
12
13GLint SERVER_DISPATCH_APIENTRY
14crServerDispatchWindowCreate(const char *dpyName, GLint visBits)
15{
16 return crServerDispatchWindowCreateEx(dpyName, visBits, -1);
17}
18
19GLint crServerMuralInit(CRMuralInfo *mural, const char *dpyName, GLint visBits, GLint preloadWinID)
20{
21 CRMuralInfo *defaultMural;
22 GLint dims[2];
23 GLint windowID = -1;
24 GLint spuWindow;
25 VBOXVR_TEXTURE Tex = {0};
26 RTRECT Rect;
27 int rc;
28
29 crMemset(mural, 0, sizeof (*mural));
30
31 rc = CrVrScrCompositorInit(&mural->Compositor);
32 if (!RT_SUCCESS(rc))
33 {
34 crWarning("CrVrScrCompositorInit failed, rc %d", rc);
35 return -1;
36 }
37
38 if (cr_server.fRootVrOn)
39 {
40 rc = CrVrScrCompositorInit(&mural->RootVrCompositor);
41 if (!RT_SUCCESS(rc))
42 {
43 crWarning("CrVrScrCompositorInit failed, rc %d", rc);
44 return -1;
45 }
46 }
47
48 /*
49 * Have first SPU make a new window.
50 */
51 spuWindow = cr_server.head_spu->dispatch_table.WindowCreate( dpyName, visBits );
52 if (spuWindow < 0) {
53 CrVrScrCompositorTerm(&mural->Compositor);
54 if (cr_server.fRootVrOn)
55 CrVrScrCompositorTerm(&mural->RootVrCompositor);
56 return spuWindow;
57 }
58
59 /* get initial window size */
60 cr_server.head_spu->dispatch_table.GetChromiumParametervCR(GL_WINDOW_SIZE_CR, spuWindow, GL_INT, 2, dims);
61
62 Tex.width = dims[0];
63 Tex.height = dims[1];
64 Tex.target = GL_TEXTURE_2D;
65 Tex.hwid = 0;
66 CrVrScrCompositorEntryInit(&mural->CEntry, &Tex);
67
68 if (cr_server.fRootVrOn)
69 {
70 CrVrScrCompositorEntryInit(&mural->RootVrCEntry, &Tex);
71 mural->fRootVrOn = GL_TRUE;
72 }
73
74 defaultMural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, 0);
75 CRASSERT(defaultMural);
76 mural->gX = 0;
77 mural->gY = 0;
78 mural->width = dims[0];
79 mural->height = dims[1];
80
81 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 CrVrScrCompositorTerm(&mural->Compositor);
296
297 if (mural->fRootVrOn)
298 CrVrScrCompositorTerm(&mural->RootVrCompositor);
299}
300
301static void crServerCleanupCtxMuralRefsCB(unsigned long key, void *data1, void *data2)
302{
303 CRContextInfo *ctxInfo = (CRContextInfo *) data1;
304 CRMuralInfo *mural = (CRMuralInfo *) data2;
305
306 if (ctxInfo->currentMural == mural)
307 ctxInfo->currentMural = NULL;
308}
309
310void SERVER_DISPATCH_APIENTRY
311crServerDispatchWindowDestroy( GLint window )
312{
313 CRMuralInfo *mural;
314 int32_t client;
315 CRClientNode *pNode;
316 int found=false;
317
318 if (!window)
319 {
320 crWarning("Unexpected attempt to delete default mural, ignored!");
321 return;
322 }
323
324 mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window);
325 if (!mural) {
326 crWarning("CRServer: invalid window %d passed to WindowDestroy()", window);
327 return;
328 }
329
330 crDebug("CRServer: Destroying window %d (spu window %d)", window, mural->spuWindow);
331
332 crHashtableWalk(cr_server.contextTable, crServerCleanupCtxMuralRefsCB, mural);
333
334 crServerMuralTerm(mural);
335
336 CRASSERT(cr_server.currentWindow != window);
337
338 if (cr_server.curClient)
339 {
340 if (cr_server.curClient->currentMural == mural)
341 {
342 cr_server.curClient->currentMural = NULL;
343 cr_server.curClient->currentWindow = -1;
344 }
345
346 found = crServerRemoveClientWindow(cr_server.curClient, window);
347
348 /*Same as with contexts, some apps destroy it not in a thread where it was created*/
349 if (!found)
350 {
351 for (client=0; client<cr_server.numClients; ++client)
352 {
353 if (cr_server.clients[client]==cr_server.curClient)
354 continue;
355
356 found = crServerRemoveClientWindow(cr_server.clients[client], window);
357
358 if (found) break;
359 }
360 }
361
362 if (!found)
363 {
364 pNode=cr_server.pCleanupClient;
365
366 while (pNode && !found)
367 {
368 found = crServerRemoveClientWindow(pNode->pClient, window);
369 pNode = pNode->next;
370 }
371 }
372
373 CRASSERT(found);
374 }
375
376 /*Make sure this window isn't active in other clients*/
377 for (client=0; client<cr_server.numClients; ++client)
378 {
379 if (cr_server.clients[client]->currentMural == mural)
380 {
381 cr_server.clients[client]->currentMural = NULL;
382 cr_server.clients[client]->currentWindow = -1;
383 }
384 }
385
386 pNode=cr_server.pCleanupClient;
387 while (pNode)
388 {
389 if (pNode->pClient->currentMural == mural)
390 {
391 pNode->pClient->currentMural = NULL;
392 pNode->pClient->currentWindow = -1;
393 }
394 pNode = pNode->next;
395 }
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 0
468 if (!mural->bReceivedRects)
469 {
470 rc = CrVrScrCompositorEntryRemove(&mural->Compositor, &mural->CEntry);
471 if (!RT_SUCCESS(rc))
472 {
473 crWarning("CrVrScrCompositorEntryRemove failed, rc %d", rc);
474 goto end;
475 }
476 CrVrScrCompositorEntryInit(&mural->CEntry, &Tex);
477 /* initially set regions to all visible since this is what some guest assume
478 * and will not post any more visible regions command */
479 Rect.xLeft = 0;
480 Rect.xRight = width;
481 Rect.yTop = 0;
482 Rect.yBottom = height;
483 rc = CrVrScrCompositorEntryRegionsSet(&mural->Compositor, &mural->CEntry, NULL, 1, &Rect, NULL);
484 if (!RT_SUCCESS(rc))
485 {
486 crWarning("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc);
487 goto end;
488 }
489 }
490 else
491#endif
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, (const GLint*)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, (const GLint*)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, (const GLint*)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 if (state && mural->fHasParentWindow)
811 crVBoxServerNotifyEvent(mural->screenId);
812 }
813
814 mural->bVisible = !!state;
815}
816
817
818GLint
819crServerSPUWindowID(GLint serverWindow)
820{
821 CRMuralInfo *mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, serverWindow);
822 if (!mural) {
823#if EXTRA_WARN
824 crWarning("CRServer: invalid window %d passed to crServerSPUWindowID()",
825 serverWindow);
826#endif
827 return -1;
828 }
829 return mural->spuWindow;
830}
Note: See TracBrowser for help on using the repository browser.

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