VirtualBox

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

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

crOpenGL: burn fix

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

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