VirtualBox

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

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

crOpenGL: yet another adjustment to 3D notify mechanism

  • 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);
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 return &pDEntry->RootVrCEntry;
507}
508
509int crServerMuralSynchRootVr(CRMuralInfo *mural)
510{
511 int rc;
512
513 crServerVBoxRootVrTranslateForMural(mural);
514
515 /* ensure the rootvr compositor does not hold any data,
516 * i.e. cleanup all rootvr entries data */
517 CrVrScrCompositorClear(&mural->RootVrCompositor);
518
519 rc = CrVrScrCompositorIntersectedList(&mural->Compositor, &cr_server.RootVr, &mural->RootVrCompositor, crServerMuralGetRootVrCEntry, NULL, NULL);
520 if (!RT_SUCCESS(rc))
521 {
522 crWarning("CrVrScrCompositorIntersectedList failed, rc %d", rc);
523 return rc;
524 }
525
526 return VINF_SUCCESS;
527}
528
529GLboolean crServerMuralSize(CRMuralInfo *mural, GLint width, GLint height)
530{
531 RTRECT Rect;
532 VBOXVR_TEXTURE Tex;
533 int rc = VINF_SUCCESS;
534 Tex.width = width;
535 Tex.height = height;
536 Tex.target = GL_TEXTURE_2D;
537 Tex.hwid = 0;
538
539 if (mural->width == width && mural->height == height)
540 return GL_FALSE;
541
542
543 /* since we're going to change the current compositor & the window we need to avoid
544 * renderspu fron dealing with inconsistent data, i.e. modified compositor and
545 * still unmodified window.
546 * So what we do is:
547 * 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
548 * 2. do necessary modifications
549 * 3. (so far not needed for resize, but in case it is in the future) re-set the compositor */
550
551 /* 1. tell renderspu to stop using the current compositor (see above comment) */
552 crServerVBoxCompositionDisableEnter(mural);
553
554 /* 2. do necessary modifications (see above comment) */
555 /* 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 */
556 /* the compositor lock is not needed actually since we have prevented renderspu from using the compositor */
557 /* CrVrScrCompositorLock(&mural->Compositor); */
558 if (mural->fUseDefaultDEntry)
559 {
560 if (!mural->bReceivedRects)
561 {
562 rc = CrVrScrCompositorEntryRemove(&mural->Compositor, &mural->DefaultDEntry.CEntry);
563 if (!RT_SUCCESS(rc))
564 {
565 crWarning("CrVrScrCompositorEntryRemove failed, rc %d", rc);
566 goto end;
567 }
568 CrVrScrCompositorEntryInit(&mural->DefaultDEntry.CEntry, &Tex, NULL);
569 /* initially set regions to all visible since this is what some guest assume
570 * and will not post any more visible regions command */
571 Rect.xLeft = 0;
572 Rect.xRight = width;
573 Rect.yTop = 0;
574 Rect.yBottom = height;
575 rc = CrVrScrCompositorEntryRegionsSet(&mural->Compositor, &mural->DefaultDEntry.CEntry, NULL, 1, &Rect, false, NULL);
576 if (!RT_SUCCESS(rc))
577 {
578 crWarning("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc);
579 goto end;
580 }
581 }
582 else
583 {
584 rc = CrVrScrCompositorEntryTexUpdate(&mural->Compositor, &mural->DefaultDEntry.CEntry, &Tex);
585 if (!RT_SUCCESS(rc))
586 {
587 crWarning("CrVrScrCompositorEntryTexUpdate failed, rc %d", rc);
588 goto end;
589 }
590 }
591 }
592 else
593 {
594 CrVrScrCompositorClear(&mural->Compositor);
595 }
596
597 /* CrVrScrCompositorUnlock(&mural->Compositor); */
598 mural->width = width;
599 mural->height = height;
600
601 mural->fDataPresented = GL_FALSE;
602
603 if (cr_server.curClient && cr_server.curClient->currentMural == mural)
604 {
605 crStateGetCurrent()->buffer.width = mural->width;
606 crStateGetCurrent()->buffer.height = mural->height;
607 }
608
609 if (mural->fRootVrOn)
610 {
611 rc = crServerMuralSynchRootVr(mural);
612 if (!RT_SUCCESS(rc))
613 {
614 crWarning("crServerMuralSynchRootVr failed, rc %d", rc);
615 goto end;
616 }
617 }
618
619 crServerCheckMuralGeometry(mural);
620
621 crServerWindowSize(mural);
622
623 crServerWindowVisibleRegion(mural);
624
625 crServerDEntryAllResized(mural);
626end:
627 /* 3. (so far not needed for resize, but in case it is in the future) re-set the compositor (see above comment) */
628 /* uncomment when needed */
629 /* NOTE: !!! we have mural->fHasPresentationData set to GL_FALSE above, so crServerVBoxCompositionReenable will have no effect in any way
630
631 */
632 crServerVBoxCompositionDisableLeave(mural, GL_FALSE);
633
634 return GL_TRUE;
635}
636
637void SERVER_DISPATCH_APIENTRY
638crServerDispatchWindowSize( GLint window, GLint width, GLint height )
639{
640 CRMuralInfo *mural;
641
642 /* crDebug("CRServer: Window %d size %d x %d", window, width, height);*/
643 mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window);
644 if (!mural) {
645#if EXTRA_WARN
646 crWarning("CRServer: invalid window %d passed to WindowSize()", window);
647#endif
648 return;
649 }
650
651 crServerMuralSize(mural, width, height);
652
653 if (cr_server.currentMural == mural)
654 {
655 crServerPerformMakeCurrent( mural, cr_server.currentCtxInfo );
656 }
657}
658
659void crServerMuralPosition(CRMuralInfo *mural, GLint x, GLint y, GLboolean fSkipCheckGeometry)
660{
661 GLboolean fForcePresent = GL_FALSE;
662 /* crDebug("CRServer: Window %d pos %d, %d", window, x, y);*/
663
664// if (mural->gX != x || mural->gY != y)
665 {
666 /* since we're going to change the current compositor & the window we need to avoid
667 * renderspu fron dealing with inconsistent data, i.e. modified compositor and
668 * still unmodified window.
669 * So what we do is:
670 * 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
671 * 2. do necessary modifications
672 * 3. re-set the compositor */
673
674 /* 1. tell renderspu to stop using the current compositor (see above comment) */
675 crServerVBoxCompositionDisableEnter(mural);
676
677 /* 2. do necessary modifications (see above comment) */
678 /* 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 */
679
680 if (mural->gX != x || mural->gY != y)
681 {
682 if (mural->fRootVrOn)
683 {
684 fForcePresent = crServerVBoxCompositionPresentNeeded(mural);
685 }
686
687 mural->gX = x;
688 mural->gY = y;
689
690 /* no need to set position because the position is relative to window */
691 /*CrVrScrCompositorEntryPosSet(&mural->Compositor, &mural->CEntry, &Pos);*/
692
693 if (mural->fRootVrOn)
694 {
695 int rc = crServerMuralSynchRootVr(mural);
696 if (RT_SUCCESS(rc))
697 {
698 crServerWindowVisibleRegion(mural);
699 }
700 else
701 {
702 crWarning("crServerMuralSynchRootVr failed, rc %d", rc);
703 }
704 }
705 }
706
707 if (!fSkipCheckGeometry)
708 crServerCheckMuralGeometry(mural);
709
710 crServerDEntryAllMoved(mural);
711
712 /* 3. re-set the compositor (see above comment) */
713 crServerVBoxCompositionDisableLeave(mural, fForcePresent);
714 }
715}
716
717void SERVER_DISPATCH_APIENTRY
718crServerDispatchWindowPosition( GLint window, GLint x, GLint y )
719{
720 CRMuralInfo *mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window);
721 if (!mural) {
722#if EXTRA_WARN
723 crWarning("CRServer: invalid window %d passed to WindowPosition()", window);
724#endif
725 return;
726 }
727 crServerMuralPosition(mural, x, y, GL_FALSE);
728}
729
730void crServerMuralVisibleRegion( CRMuralInfo *mural, GLint cRects, const GLint *pRects )
731{
732 GLboolean fForcePresent = crServerVBoxCompositionPresentNeeded(mural);
733 bool fRegionsChanged = false;
734 int rc = VINF_SUCCESS;
735
736 /* since we're going to change the current compositor & the window we need to avoid
737 * renderspu fron dealing with inconsistent data, i.e. modified compositor and
738 * still unmodified window.
739 * So what we do is:
740 * 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
741 * 2. do necessary modifications
742 * 3. re-set the compositor */
743
744 /* 1. tell renderspu to stop using the current compositor (see above comment) */
745 crServerVBoxCompositionDisableEnter(mural);
746
747 /* 2. do necessary modifications (see above comment) */
748 if (mural->pVisibleRects)
749 {
750 crFree(mural->pVisibleRects);
751 mural->pVisibleRects = NULL;
752 }
753
754 mural->cVisibleRects = cRects;
755 mural->bReceivedRects = GL_TRUE;
756 if (cRects)
757 {
758 mural->pVisibleRects = (GLint*) crAlloc(4*sizeof(GLint)*cRects);
759 if (!mural->pVisibleRects)
760 {
761 crError("Out of memory in crServerDispatchWindowVisibleRegion");
762 }
763 crMemcpy(mural->pVisibleRects, pRects, 4*sizeof(GLint)*cRects);
764 }
765
766 if (mural->fUseDefaultDEntry)
767 {
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 else
780 {
781 fRegionsChanged = true;
782 }
783
784 if (fRegionsChanged)
785 {
786 if (mural->fRootVrOn)
787 {
788 rc = crServerMuralSynchRootVr(mural);
789 if (!RT_SUCCESS(rc))
790 {
791 crWarning("crServerMuralSynchRootVr failed, rc %d", rc);
792 goto end;
793 }
794 }
795
796 crServerWindowVisibleRegion(mural);
797
798 crServerDEntryAllVibleRegions(mural);
799 }
800end:
801 /* 3. re-set the compositor (see above comment) */
802 crServerVBoxCompositionDisableLeave(mural, fForcePresent);
803}
804
805void SERVER_DISPATCH_APIENTRY
806crServerDispatchWindowVisibleRegion( GLint window, GLint cRects, const GLint *pRects )
807{
808 CRMuralInfo *mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window);
809 if (!mural) {
810#if EXTRA_WARN
811 crWarning("CRServer: invalid window %d passed to WindowVisibleRegion()", window);
812#endif
813 return;
814 }
815
816 crServerMuralVisibleRegion( mural, cRects, pRects );
817}
818
819void crServerMuralShow( CRMuralInfo *mural, GLint state )
820{
821 mural->bVisible = !!state;
822
823 if (mural->fPresentMode & CR_SERVER_REDIR_F_DISPLAY)
824 crServerWindowShow(mural);
825}
826
827void SERVER_DISPATCH_APIENTRY
828crServerDispatchWindowShow( GLint window, GLint state )
829{
830 CRMuralInfo *mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window);
831 if (!mural) {
832#if EXTRA_WARN
833 crWarning("CRServer: invalid window %d passed to WindowShow()", window);
834#endif
835 return;
836 }
837
838 crServerMuralShow( mural, state );
839}
840
841GLint
842crServerSPUWindowID(GLint serverWindow)
843{
844 CRMuralInfo *mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, serverWindow);
845 if (!mural) {
846#if EXTRA_WARN
847 crWarning("CRServer: invalid window %d passed to crServerSPUWindowID()",
848 serverWindow);
849#endif
850 return -1;
851 }
852 return mural->spuWindow;
853}
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