VirtualBox

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

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

crOpenGL: do not pass intersected rects to vrdp backend

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