VirtualBox

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

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

crOpenGL: more output redirect enhance

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