VirtualBox

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

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

crOpenGL: seamless fixes

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