VirtualBox

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

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

crOpenGL: seamless fixes

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