VirtualBox

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

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

crOpenGL: output redirect fixes

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