VirtualBox

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

Last change on this file since 47136 was 46990, checked in by vboxsync, 12 years ago

crOpenGL: typo fix

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