VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_muralfbo.c@ 47623

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

crOpenGL: output redirect fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 40.0 KB
Line 
1/* $Id: server_muralfbo.c 47623 2013-08-08 21:19:43Z vboxsync $ */
2
3/** @file
4 * VBox crOpenGL: Window to FBO redirect support.
5 */
6
7/*
8 * Copyright (C) 2010-2013 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19#include "server.h"
20#include "cr_string.h"
21#include "cr_mem.h"
22#include "cr_vreg.h"
23#include "render/renderspu.h"
24
25static int crServerGetPointScreen(GLint x, GLint y)
26{
27 int i;
28
29 for (i=0; i<cr_server.screenCount; ++i)
30 {
31 if ((x>=cr_server.screen[i].x && x<cr_server.screen[i].x+(int)cr_server.screen[i].w)
32 && (y>=cr_server.screen[i].y && y<cr_server.screen[i].y+(int)cr_server.screen[i].h))
33 {
34 return i;
35 }
36 }
37
38 return -1;
39}
40
41static GLboolean crServerMuralCoverScreen(CRMuralInfo *mural, int sId)
42{
43 return mural->gX < cr_server.screen[sId].x
44 && mural->gX+(int)mural->width > cr_server.screen[sId].x+(int)cr_server.screen[sId].w
45 && mural->gY < cr_server.screen[sId].y
46 && mural->gY+(int)mural->height > cr_server.screen[sId].y+(int)cr_server.screen[sId].h;
47}
48
49void crServerDEntryResized(CRMuralInfo *pMural, CR_DISPLAY_ENTRY *pDEntry)
50{
51 /*PBO*/
52 if (pDEntry->idPBO)
53 {
54 CRASSERT(cr_server.bUsePBOForReadback);
55 cr_server.head_spu->dispatch_table.DeleteBuffersARB(1, &pDEntry->idPBO);
56 pDEntry->idPBO = 0;
57 }
58
59 if (pDEntry->pvORInstance)
60 {
61 cr_server.outputRedirect.CRORGeometry(pDEntry->pvORInstance,
62 pMural->hX + CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->x,
63 pMural->hY + CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->y,
64 CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->width,
65 CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->height);
66
67 crServerDEntryVibleRegions(pMural, pDEntry);
68 }
69}
70
71void crServerDEntryMoved(CRMuralInfo *pMural, CR_DISPLAY_ENTRY *pDEntry)
72{
73 if (pDEntry->pvORInstance)
74 {
75 cr_server.outputRedirect.CRORGeometry(pDEntry->pvORInstance,
76 pMural->hX + CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->x,
77 pMural->hY + CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->y,
78 CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->width,
79 CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->height);
80
81 crServerDEntryVibleRegions(pMural, pDEntry);
82 }
83
84}
85
86void crServerDEntryCleanup(CR_DISPLAY_ENTRY *pDEntry)
87{
88 if (pDEntry->pvORInstance)
89 {
90 cr_server.outputRedirect.CROREnd(pDEntry->pvORInstance);
91 pDEntry->pvORInstance = NULL;
92 }
93}
94
95void crServerDEntryVibleRegions(CRMuralInfo *pMural, CR_DISPLAY_ENTRY *pDEntry)
96{
97 if (pDEntry->pvORInstance)
98 {
99 uint32_t cRects;
100 const RTRECT *pRects;
101
102 int rc = CrVrScrCompositorEntryRegionsGet(&pMural->Compositor, &pDEntry->CEntry, &cRects, NULL, &pRects, NULL);
103 if (!RT_SUCCESS(rc))
104 {
105 crWarning("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc);
106 return;
107 }
108
109 cr_server.outputRedirect.CRORVisibleRegion(pDEntry->pvORInstance, cRects, pRects);
110 }
111}
112
113/***/
114void crServerDEntryAllResized(CRMuralInfo *pMural)
115{
116 VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
117 PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
118
119 CrVrScrCompositorIterInit(&pMural->Compositor, &Iter);
120 while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
121 {
122 CR_DISPLAY_ENTRY *pDEntry = CR_DENTRY_FROM_CENTRY(pEntry);
123 crServerDEntryResized(pMural, pDEntry);
124 }
125}
126
127void crServerDEntryAllMoved(CRMuralInfo *pMural)
128{
129 VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
130 PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
131
132 CrVrScrCompositorIterInit(&pMural->Compositor, &Iter);
133
134 while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
135 {
136 CR_DISPLAY_ENTRY *pDEntry = CR_DENTRY_FROM_CENTRY(pEntry);
137 crServerDEntryMoved(pMural, pDEntry);
138 }
139}
140
141void crServerDEntryAllVibleRegions(CRMuralInfo *pMural)
142{
143 VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
144 PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
145
146 CrVrScrCompositorIterInit(&pMural->Compositor, &Iter);
147
148 while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
149 {
150 CR_DISPLAY_ENTRY *pDEntry = CR_DENTRY_FROM_CENTRY(pEntry);
151 crServerDEntryVibleRegions(pMural, pDEntry);
152 }
153}
154/**/
155
156void crServerDEntryCheckFBO(CRMuralInfo *pMural, CR_DISPLAY_ENTRY *pDEntry, CRContext *ctx)
157{
158 if (!cr_server.bUsePBOForReadback == !pDEntry->idPBO)
159 return;
160
161 if (cr_server.bUsePBOForReadback)
162 {
163 Assert(!pDEntry->idPBO);
164 cr_server.head_spu->dispatch_table.GenBuffersARB(1, &pDEntry->idPBO);
165 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pDEntry->idPBO);
166 cr_server.head_spu->dispatch_table.BufferDataARB(GL_PIXEL_PACK_BUFFER_ARB,
167 CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->width*CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->height*4,
168 0, GL_STREAM_READ_ARB);
169 cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, ctx->bufferobject.packBuffer->hwid);
170
171 if (!pDEntry->idPBO)
172 {
173 crWarning("PBO create failed");
174 }
175 }
176}
177
178/* Called when a new CRMuralInfo is created
179 * or when OutputRedirect status is changed.
180 */
181void crServerSetupOutputRedirectEntry(CRMuralInfo *mural, CR_DISPLAY_ENTRY *pDEntry)
182{
183 /* Unset the previous redirect. */
184 if (pDEntry->pvORInstance)
185 {
186 cr_server.outputRedirect.CROREnd(pDEntry->pvORInstance);
187 pDEntry->pvORInstance = NULL;
188 }
189
190 /* Setup a new redirect. */
191 if (cr_server.bUseOutputRedirect)
192 {
193 /* Query supported formats. */
194 uint32_t cbFormats = 4096;
195 char *pachFormats = (char *)crAlloc(cbFormats);
196
197 if (pachFormats)
198 {
199 int rc = cr_server.outputRedirect.CRORContextProperty(cr_server.outputRedirect.pvContext,
200 0 /* H3DOR_PROP_FORMATS */, // @todo from a header
201 pachFormats, cbFormats, &cbFormats);
202 if (RT_SUCCESS(rc))
203 {
204 if (RTStrStr(pachFormats, "H3DOR_FMT_RGBA_TOPDOWN"))
205 {
206 cr_server.outputRedirect.CRORBegin(cr_server.outputRedirect.pvContext,
207 &pDEntry->pvORInstance,
208 "H3DOR_FMT_RGBA_TOPDOWN"); // @todo from a header
209 }
210 }
211
212 crFree(pachFormats);
213 }
214
215 /* If this is not NULL then there was a supported format. */
216 if (pDEntry->pvORInstance)
217 {
218 uint32_t cRects;
219 const RTRECT *pRects;
220
221 int rc = CrVrScrCompositorEntryRegionsGet(&mural->Compositor, &pDEntry->CEntry, &cRects, NULL, &pRects, NULL);
222 if (!RT_SUCCESS(rc))
223 {
224 crWarning("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc);
225 return;
226 }
227
228 cr_server.outputRedirect.CRORGeometry(pDEntry->pvORInstance,
229 mural->hX + CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->x,
230 mural->hY + CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->y,
231 CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->width,
232 CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->height);
233
234 cr_server.outputRedirect.CRORVisibleRegion(pDEntry->pvORInstance, cRects, pRects);
235//!!
236// crServerPresentFBO(mural);
237 }
238 }
239}
240
241void crServerCheckMuralGeometry(CRMuralInfo *mural)
242{
243 int tlS, brS, trS, blS;
244 int overlappingScreenCount = 0, primaryS = -1 , i;
245 uint64_t winID = 0;
246 GLuint fPresentMode;
247
248 if (!mural->CreateInfo.externalID)
249 return;
250
251 CRASSERT(mural->spuWindow);
252 CRASSERT(mural->spuWindow != CR_RENDER_DEFAULT_WINDOW_ID);
253
254 crServerVBoxCompositionDisableEnter(mural);
255
256 if (!mural->width || !mural->height)
257 {
258 crServerRedirMuralFBO(mural, CR_SERVER_REDIR_F_NONE);
259 crServerDeleteMuralFBO(mural);
260 crServerVBoxCompositionDisableLeave(mural, GL_FALSE);
261 return;
262 }
263
264 tlS = crServerGetPointScreen(mural->gX, mural->gY);
265 brS = crServerGetPointScreen(mural->gX+mural->width-1, mural->gY+mural->height-1);
266
267 if ((tlS==brS && tlS>=0) || cr_server.screenCount <= 1)
268 {
269 if (cr_server.screenCount <= 1)
270 {
271 if (tlS != brS)
272 {
273 if (tlS >= 0)
274 brS = tlS;
275 else
276 tlS = brS;
277 }
278
279 primaryS = 0;
280 }
281 else
282 {
283 Assert(brS == tlS);
284
285 primaryS = brS;
286 }
287
288
289 Assert(brS == tlS);
290
291 if (tlS>=0 && cr_server.screen[tlS].winID)
292 {
293 overlappingScreenCount = 1;
294 }
295 }
296 else
297 {
298 bool fFoundWindIdScreen = false;
299 trS = crServerGetPointScreen(mural->gX+mural->width-1, mural->gY);
300 blS = crServerGetPointScreen(mural->gX, mural->gY+mural->height-1);
301
302 primaryS = -1; overlappingScreenCount = 0;
303 for (i=0; i<cr_server.screenCount; ++i)
304 {
305 if ((i==tlS) || (i==brS) || (i==trS) || (i==blS)
306 || crServerMuralCoverScreen(mural, i))
307 {
308 if ((!fFoundWindIdScreen && cr_server.screen[i].winID) || primaryS<0)
309 primaryS = i;
310
311 if (cr_server.screen[i].winID)
312 {
313 overlappingScreenCount++;
314 fFoundWindIdScreen = true;
315 }
316 }
317 }
318
319 if (primaryS<0)
320 {
321 primaryS = 0;
322 }
323 }
324
325 CRASSERT(primaryS >= 0);
326
327 winID = overlappingScreenCount ? cr_server.screen[primaryS].winID : 0;
328
329 if (!winID != !mural->fHasParentWindow
330 || (winID && primaryS!=mural->screenId))
331 {
332 mural->fHasParentWindow = !!winID;
333
334 renderspuSetWindowId(winID);
335 renderspuReparentWindow(mural->spuWindow);
336 renderspuSetWindowId(cr_server.screen[0].winID);
337 }
338
339 if (primaryS != mural->screenId)
340 {
341 /* mark it invisible on the old screen */
342 crServerWindowSetIsVisible(mural, GL_FALSE);
343 mural->screenId = primaryS;
344 /* check if mural is visivle on the new screen, and mark it as such */
345 crServerWindowCheckIsVisible(mural);
346 }
347
348 mural->hX = mural->gX-cr_server.screen[primaryS].x;
349 mural->hY = mural->gY-cr_server.screen[primaryS].y;
350
351 fPresentMode = cr_server.fPresentMode;
352
353 if (!mural->fHasParentWindow)
354 fPresentMode &= ~CR_SERVER_REDIR_F_DISPLAY;
355
356 if (!overlappingScreenCount)
357 fPresentMode &= ~CR_SERVER_REDIR_F_DISPLAY;
358 else if (overlappingScreenCount > 1)
359 fPresentMode = (fPresentMode | CR_SERVER_REDIR_F_FBO_RAM_VMFB | cr_server.fVramPresentModeDefault) & ~CR_SERVER_REDIR_F_DISPLAY;
360
361 if (!mural->fUseDefaultDEntry)
362 {
363 /* only display matters */
364 fPresentMode &= CR_SERVER_REDIR_F_DISPLAY;
365 }
366
367 fPresentMode = crServerRedirModeAdjust(fPresentMode);
368
369 if (!(fPresentMode & CR_SERVER_REDIR_F_FBO))
370 {
371 crServerRedirMuralFBO(mural, fPresentMode);
372 crServerDeleteMuralFBO(mural);
373 }
374 else
375 {
376 if (mural->fPresentMode & CR_SERVER_REDIR_F_FBO)
377 {
378 if (mural->width!=mural->fboWidth
379 || mural->height!=mural->fboHeight)
380 {
381 crServerRedirMuralFBO(mural, fPresentMode & CR_SERVER_REDIR_F_DISPLAY);
382 crServerDeleteMuralFBO(mural);
383 }
384 }
385
386 crServerRedirMuralFBO(mural, fPresentMode);
387 }
388
389 if (mural->fPresentMode & CR_SERVER_REDIR_F_DISPLAY)
390 {
391 CRScreenViewportInfo *pVieport = &cr_server.screenVieport[mural->screenId];
392
393 cr_server.head_spu->dispatch_table.WindowPosition(mural->spuWindow, mural->hX - pVieport->x, mural->hY - pVieport->y);
394 }
395
396 crServerVBoxCompositionDisableLeave(mural, GL_FALSE);
397}
398
399GLboolean crServerSupportRedirMuralFBO(void)
400{
401 static GLboolean fInited = GL_FALSE;
402 static GLboolean fSupported = GL_FALSE;
403 if (!fInited)
404 {
405 const GLubyte* pExt = cr_server.head_spu->dispatch_table.GetString(GL_REAL_EXTENSIONS);
406
407 fSupported = ( NULL!=crStrstr((const char*)pExt, "GL_ARB_framebuffer_object")
408 || NULL!=crStrstr((const char*)pExt, "GL_EXT_framebuffer_object"))
409 && NULL!=crStrstr((const char*)pExt, "GL_ARB_texture_non_power_of_two");
410 fInited = GL_TRUE;
411 }
412 return fSupported;
413}
414
415static void crServerDentryPresentVRAM(CRMuralInfo *mural, CR_DISPLAY_ENTRY *pDEntry, char *pixels);
416
417#define CR_SERVER_MURAL_FROM_RPW_ENTRY(_pEntry) ((CRMuralInfo*)(((uint8_t*)(_pEntry)) - RT_OFFSETOF(CRMuralInfo, RpwEntry)))
418
419static DECLCALLBACK(void) crServerMuralRpwDataCB(const struct CR_SERVER_RPW_ENTRY* pEntry, void *pvEntryTexData)
420{
421 CRMuralInfo *pMural = CR_SERVER_MURAL_FROM_RPW_ENTRY(pEntry);
422
423 Assert(&pMural->RpwEntry == pEntry);
424 crError("port me!");
425 // crServerPresentMuralVRAM(pMural, pvEntryTexData);
426}
427
428static void crServerCreateMuralFBO(CRMuralInfo *mural);
429
430static bool crServerEnableMuralRpw(CRMuralInfo *mural, GLboolean fEnable)
431{
432 if (!mural->CreateInfo.externalID)
433 {
434 crWarning("trying to change Rpw setting for internal mural %d", mural->spuWindow);
435 return !fEnable;
436 }
437
438 if (fEnable)
439 {
440 if (!(mural->fPresentMode & CR_SERVER_REDIR_F_FBO_RPW))
441 {
442 int rc;
443 if (!crServerRpwIsInitialized(&cr_server.RpwWorker))
444 {
445 rc = crServerRpwInit(&cr_server.RpwWorker);
446 if (!RT_SUCCESS(rc))
447 {
448 crWarning("crServerRpwInit failed rc %d", rc);
449 return false;
450 }
451 }
452
453 CRASSERT(!mural->RpwEntry.Size.cx);
454 CRASSERT(!mural->RpwEntry.Size.cy);
455
456 if (!crServerRpwEntryIsInitialized(&mural->RpwEntry))
457 {
458 rc = crServerRpwEntryInit(&cr_server.RpwWorker, &mural->RpwEntry, mural->width, mural->height, crServerMuralRpwDataCB);
459 if (!RT_SUCCESS(rc))
460 {
461 crWarning("crServerRpwEntryInit failed rc %d", rc);
462 return false;
463 }
464 }
465 else
466 {
467 rc = crServerRpwEntryResize(&cr_server.RpwWorker, &mural->RpwEntry, mural->width, mural->height);
468 if (!RT_SUCCESS(rc))
469 {
470 crWarning("crServerRpwEntryResize failed rc %d", rc);
471 return false;
472 }
473 }
474
475 mural->fPresentMode |= CR_SERVER_REDIR_F_FBO_RPW;
476 }
477 }
478 else
479 {
480 if ((mural->fPresentMode & CR_SERVER_REDIR_F_FBO_RPW))
481 {
482// crServerRpwEntryCleanup(&cr_server.RpwWorker, &mural->RpwEntry);
483 mural->fPresentMode &= ~CR_SERVER_REDIR_F_FBO_RPW;
484 }
485 }
486
487 return true;
488}
489
490static void crServerEnableDisplayMuralFBO(CRMuralInfo *mural, GLboolean fEnable)
491{
492 if (!mural->CreateInfo.externalID)
493 {
494 crWarning("trying to change display setting for internal mural %d", mural->spuWindow);
495 return;
496 }
497
498 if (fEnable)
499 {
500 if (!(mural->fPresentMode & CR_SERVER_REDIR_F_DISPLAY))
501 {
502 mural->fPresentMode |= CR_SERVER_REDIR_F_DISPLAY;
503
504 if (mural->bVisible)
505 crServerWindowShow(mural);
506 }
507 }
508 else
509 {
510 if ((mural->fPresentMode & CR_SERVER_REDIR_F_DISPLAY))
511 {
512 mural->fPresentMode &= ~CR_SERVER_REDIR_F_DISPLAY;
513
514 if (mural->bVisible)
515 crServerWindowShow(mural);
516 }
517 }
518}
519
520void crServerRedirMuralFBO(CRMuralInfo *mural, GLuint redir)
521{
522 if (mural->fPresentMode == redir)
523 {
524// if (redir)
525// crWarning("crServerRedirMuralFBO called with the same redir status %d", redir);
526 return;
527 }
528
529 if (!mural->CreateInfo.externalID)
530 {
531 crWarning("trying to change redir setting for internal mural %d", mural->spuWindow);
532 return;
533 }
534
535 crServerVBoxCompositionDisableEnter(mural);
536
537 if (redir & CR_SERVER_REDIR_F_FBO)
538 {
539 if (!crServerSupportRedirMuralFBO())
540 {
541 crWarning("FBO not supported, can't redirect window output");
542 goto end;
543 }
544
545 if (mural->fUseDefaultDEntry && mural->aidFBOs[0]==0)
546 {
547 crServerCreateMuralFBO(mural);
548 }
549
550 if (cr_server.curClient && cr_server.curClient->currentMural == mural)
551 {
552 if (!crStateGetCurrent()->framebufferobject.drawFB)
553 {
554 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, CR_SERVER_FBO_FOR_IDX(mural, mural->iCurDrawBuffer));
555 }
556 if (!crStateGetCurrent()->framebufferobject.readFB)
557 {
558 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, CR_SERVER_FBO_FOR_IDX(mural, mural->iCurReadBuffer));
559 }
560
561 crStateGetCurrent()->buffer.width = 0;
562 crStateGetCurrent()->buffer.height = 0;
563 }
564 }
565 else
566 {
567 if (cr_server.curClient && cr_server.curClient->currentMural == mural)
568 {
569 if (!crStateGetCurrent()->framebufferobject.drawFB)
570 {
571 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
572 }
573 if (!crStateGetCurrent()->framebufferobject.readFB)
574 {
575 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, 0);
576 }
577
578 crStateGetCurrent()->buffer.width = mural->width;
579 crStateGetCurrent()->buffer.height = mural->height;
580 }
581 }
582
583 crServerEnableMuralRpw(mural, !!(redir & CR_SERVER_REDIR_F_FBO_RPW));
584
585 crServerEnableDisplayMuralFBO(mural, !!(redir & CR_SERVER_REDIR_F_DISPLAY));
586
587 mural->fPresentMode = redir;
588
589end:
590 crServerVBoxCompositionDisableLeave(mural, GL_FALSE);
591}
592
593static void crServerCreateMuralFBO(CRMuralInfo *mural)
594{
595 CRContext *ctx = crStateGetCurrent();
596 GLuint uid, i;
597 GLenum status;
598 SPUDispatchTable *gl = &cr_server.head_spu->dispatch_table;
599 CRContextInfo *pMuralContextInfo;
600
601 CRASSERT(mural->aidFBOs[0]==0);
602 CRASSERT(mural->aidFBOs[1]==0);
603 CRASSERT(mural->fUseDefaultDEntry);
604 CRASSERT(mural->width == mural->DefaultDEntry.CEntry.Tex.width);
605 CRASSERT(mural->height == mural->DefaultDEntry.CEntry.Tex.height);
606
607 pMuralContextInfo = cr_server.currentCtxInfo;
608 if (!pMuralContextInfo)
609 {
610 /* happens on saved state load */
611 CRASSERT(cr_server.MainContextInfo.SpuContext);
612 pMuralContextInfo = &cr_server.MainContextInfo;
613 cr_server.head_spu->dispatch_table.MakeCurrent(mural->spuWindow, 0, cr_server.MainContextInfo.SpuContext);
614 }
615
616 if (pMuralContextInfo->CreateInfo.visualBits != mural->CreateInfo.visualBits)
617 {
618 crWarning("mural visual bits do not match with current context visual bits!");
619 }
620
621 mural->cBuffers = 2;
622 mural->iBbBuffer = 0;
623 /*Color texture*/
624
625 if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
626 {
627 gl->BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
628 }
629
630 for (i = 0; i < mural->cBuffers; ++i)
631 {
632 gl->GenTextures(1, &mural->aidColorTexs[i]);
633 gl->BindTexture(GL_TEXTURE_2D, mural->aidColorTexs[i]);
634 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
635 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
636 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
637 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
638 gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, mural->width, mural->height,
639 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
640 }
641
642 /*Depth&Stencil*/
643 gl->GenRenderbuffersEXT(1, &mural->idDepthStencilRB);
644 gl->BindRenderbufferEXT(GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
645 gl->RenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT,
646 mural->width, mural->height);
647
648 /*FBO*/
649 for (i = 0; i < mural->cBuffers; ++i)
650 {
651 gl->GenFramebuffersEXT(1, &mural->aidFBOs[i]);
652 gl->BindFramebufferEXT(GL_FRAMEBUFFER_EXT, mural->aidFBOs[i]);
653
654 gl->FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
655 GL_TEXTURE_2D, mural->aidColorTexs[i], 0);
656 gl->FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
657 GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
658 gl->FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
659 GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
660
661 status = gl->CheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
662 if (status!=GL_FRAMEBUFFER_COMPLETE_EXT)
663 {
664 crWarning("FBO status(0x%x) isn't complete", status);
665 }
666 }
667
668 mural->iCurDrawBuffer = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.drawBuffer);
669 mural->iCurReadBuffer = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.readBuffer);
670
671 mural->fboWidth = mural->width;
672 mural->fboHeight = mural->height;
673
674 mural->iCurDrawBuffer = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.drawBuffer);
675 mural->iCurReadBuffer = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.readBuffer);
676
677 /*Restore gl state*/
678 uid = ctx->texture.unit[ctx->texture.curTextureUnit].currentTexture2D->hwid;
679 gl->BindTexture(GL_TEXTURE_2D, uid);
680
681 uid = ctx->framebufferobject.renderbuffer ? ctx->framebufferobject.renderbuffer->hwid:0;
682 gl->BindRenderbufferEXT(GL_RENDERBUFFER_EXT, uid);
683
684 uid = ctx->framebufferobject.drawFB ? ctx->framebufferobject.drawFB->hwid:0;
685 gl->BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, uid);
686
687 uid = ctx->framebufferobject.readFB ? ctx->framebufferobject.readFB->hwid:0;
688 gl->BindFramebufferEXT(GL_READ_FRAMEBUFFER, uid);
689
690 if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
691 {
692 gl->BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, ctx->bufferobject.unpackBuffer->hwid);
693 }
694
695 if (crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB))
696 {
697 gl->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, ctx->bufferobject.packBuffer->hwid);
698 }
699 else
700 {
701 gl->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
702 }
703
704 CRASSERT(mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
705
706 CrVrScrCompositorEntryTexNameUpdate(&mural->DefaultDEntry.CEntry, mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
707
708// if (mural->fRootVrOn)
709// CrVrScrCompositorEntryTexNameUpdate(&mural->DefaultDEntry.RootVrCEntry, mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
710}
711
712void crServerDeleteMuralFBO(CRMuralInfo *mural)
713{
714 CRASSERT(!(mural->fPresentMode & CR_SERVER_REDIR_F_FBO));
715
716 if (mural->aidFBOs[0]!=0)
717 {
718 GLuint i;
719 for (i = 0; i < mural->cBuffers; ++i)
720 {
721 cr_server.head_spu->dispatch_table.DeleteTextures(1, &mural->aidColorTexs[i]);
722 mural->aidColorTexs[i] = 0;
723 }
724
725 cr_server.head_spu->dispatch_table.DeleteRenderbuffersEXT(1, &mural->idDepthStencilRB);
726 mural->idDepthStencilRB = 0;
727
728 for (i = 0; i < mural->cBuffers; ++i)
729 {
730 cr_server.head_spu->dispatch_table.DeleteFramebuffersEXT(1, &mural->aidFBOs[i]);
731 mural->aidFBOs[i] = 0;
732 }
733 }
734
735 mural->cBuffers = 0;
736
737 if (crServerRpwEntryIsInitialized(&mural->RpwEntry))
738 crServerRpwEntryCleanup(&cr_server.RpwWorker, &mural->RpwEntry);
739}
740
741#define MIN(a, b) ((a) < (b) ? (a) : (b))
742#define MAX(a, b) ((a) > (b) ? (a) : (b))
743
744static GLboolean crServerIntersectRect(CRrecti *a, CRrecti *b, CRrecti *rect)
745{
746 CRASSERT(a && b && rect);
747
748 rect->x1 = MAX(a->x1, b->x1);
749 rect->x2 = MIN(a->x2, b->x2);
750 rect->y1 = MAX(a->y1, b->y1);
751 rect->y2 = MIN(a->y2, b->y2);
752
753 return (rect->x2>rect->x1) && (rect->y2>rect->y1);
754}
755
756static GLboolean crServerIntersectScreen(CRMuralInfo *mural, CR_DISPLAY_ENTRY *pDEntry, int sId, CRrecti *rect)
757{
758 rect->x1 = MAX(mural->gX + CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->x, cr_server.screen[sId].x);
759 rect->x2 = MIN(mural->gX + CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->x
760 + (int)CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->width,
761 cr_server.screen[sId].x+(int)cr_server.screen[sId].w);
762 rect->y1 = MAX(mural->gY + CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->y, cr_server.screen[sId].y);
763 rect->y2 = MIN(mural->gY + CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->y
764 + (int)CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->height,
765 cr_server.screen[sId].y+(int)cr_server.screen[sId].h);
766
767 return (rect->x2>rect->x1) && (rect->y2>rect->y1);
768}
769
770static void crServerCopySubImage(char *pDst, char* pSrc, CRrecti *pRect, int srcWidth, int srcHeight)
771{
772 int i;
773 int dstrowsize = 4*(pRect->x2-pRect->x1);
774 int srcrowsize = 4*srcWidth;
775 int height = pRect->y2-pRect->y1;
776
777 pSrc += 4*pRect->x1 + srcrowsize*(srcHeight-1-pRect->y1);
778
779 for (i=0; i<height; ++i)
780 {
781 crMemcpy(pDst, pSrc, dstrowsize);
782
783 pSrc -= srcrowsize;
784 pDst += dstrowsize;
785 }
786}
787
788static void crServerTransformRect(CRrecti *pDst, CRrecti *pSrc, int dx, int dy)
789{
790 pDst->x1 = pSrc->x1+dx;
791 pDst->x2 = pSrc->x2+dx;
792 pDst->y1 = pSrc->y1+dy;
793 pDst->y2 = pSrc->y2+dy;
794}
795
796static void crServerVBoxCompositionPresentPerform(CRMuralInfo *mural)
797{
798 CRMuralInfo *currentMural = cr_server.currentMural;
799 CRContextInfo *curCtxInfo = cr_server.currentCtxInfo;
800 GLuint idDrawFBO, idReadFBO;
801 CRContext *curCtx = curCtxInfo ? curCtxInfo->pContext : NULL;
802
803 CRASSERT(curCtx == crStateGetCurrent());
804
805 Assert((mural->fPresentMode & CR_SERVER_REDIR_F_FBO) || !mural->fUseDefaultDEntry);
806 Assert(mural->fPresentMode & CR_SERVER_REDIR_F_DISPLAY);
807
808 mural->fDataPresented = GL_TRUE;
809
810 if (currentMural)
811 {
812 idDrawFBO = CR_SERVER_FBO_FOR_IDX(currentMural, currentMural->iCurDrawBuffer);
813 idReadFBO = CR_SERVER_FBO_FOR_IDX(currentMural, currentMural->iCurReadBuffer);
814 }
815 else
816 {
817 idDrawFBO = 0;
818 idReadFBO = 0;
819 }
820
821 crStateSwitchPrepare(NULL, curCtx, idDrawFBO, idReadFBO);
822
823 if (!mural->fRootVrOn)
824 cr_server.head_spu->dispatch_table.VBoxPresentComposition(mural->spuWindow, &mural->Compositor, NULL);
825 else
826 cr_server.head_spu->dispatch_table.VBoxPresentComposition(mural->spuWindow, &mural->RootVrCompositor, NULL);
827
828 crStateSwitchPostprocess(curCtx, NULL, idDrawFBO, idReadFBO);
829}
830
831void crServerVBoxCompositionPresent(CRMuralInfo *mural)
832{
833 if (!crServerVBoxCompositionPresentNeeded(mural))
834 return;
835 crServerVBoxCompositionPresentPerform(mural);
836}
837
838static void crServerVBoxCompositionReenable(CRMuralInfo *mural)
839{
840 GLboolean fForcePresent = mural->fForcePresentState;
841 GLboolean fOrPresentOnReenable = mural->fOrPresentOnReenable;
842
843 mural->fForcePresentState = GL_FALSE;
844 mural->fOrPresentOnReenable = GL_FALSE;
845
846 if ((mural->fUseDefaultDEntry && !(mural->fPresentMode & CR_SERVER_REDIR_F_FBO))
847 || !mural->fDataPresented
848 || (!fForcePresent
849 && !crServerVBoxCompositionPresentNeeded(mural)))
850 return;
851
852 if (mural->fPresentMode & CR_SERVER_REDIR_F_DISPLAY)
853 crServerVBoxCompositionPresentPerform(mural);
854
855 if (fOrPresentOnReenable
856 && cr_server.bUseOutputRedirect
857 && crServerVBoxCompositionPresentNeeded(mural))
858 crServerPresentOutputRedirect(mural);
859}
860
861static void crServerVBoxCompositionDisable(CRMuralInfo *mural)
862{
863 if ((mural->fPresentMode & (CR_SERVER_REDIR_F_FBO | CR_SERVER_REDIR_F_DISPLAY)) != (CR_SERVER_REDIR_F_FBO | CR_SERVER_REDIR_F_DISPLAY)
864 || !mural->fDataPresented)
865 return;
866 cr_server.head_spu->dispatch_table.VBoxPresentComposition(mural->spuWindow, NULL, NULL);
867}
868
869void crServerVBoxCompositionDisableEnter(CRMuralInfo *mural)
870{
871 ++cr_server.cDisableEvents;
872 Assert(cr_server.cDisableEvents);
873
874 ++mural->cDisabled;
875 Assert(mural->cDisabled);
876 if (mural->cDisabled == 1)
877 {
878 crServerVBoxCompositionDisable(mural);
879 }
880}
881
882void crServerVBoxCompositionDisableLeave(CRMuralInfo *mural, GLboolean fForcePresentOnEnabled)
883{
884 mural->fForcePresentState |= fForcePresentOnEnabled;
885 --mural->cDisabled;
886 Assert(mural->cDisabled < UINT32_MAX/2);
887 if (!mural->cDisabled)
888 {
889 crServerVBoxCompositionReenable(mural);
890 }
891
892 --cr_server.cDisableEvents;
893 Assert(cr_server.cDisableEvents < UINT32_MAX/2);
894 crVBoxServerCheckVisibilityEvent(-1);
895}
896
897static void crServerVBoxCompositionSetEnableStateGlobalCB(unsigned long key, void *data1, void *data2)
898{
899 CRMuralInfo *mural = (CRMuralInfo *)data1;
900
901 if (data2)
902 crServerVBoxCompositionDisableLeave(mural, GL_FALSE);
903 else
904 crServerVBoxCompositionDisableEnter(mural);
905}
906
907DECLEXPORT(void) crServerVBoxCompositionSetEnableStateGlobal(GLboolean fEnable)
908{
909 int i;
910
911 crHashtableWalk(cr_server.muralTable, crServerVBoxCompositionSetEnableStateGlobalCB, (void*)(uintptr_t)fEnable);
912
913 crHashtableWalk(cr_server.dummyMuralTable, crServerVBoxCompositionSetEnableStateGlobalCB, (void*)(uintptr_t)fEnable);
914
915 for (i = 0; i < cr_server.screenCount; ++i)
916 {
917 PCR_DISPLAY pDisplay = crServerDisplayGetInitialized((uint32_t)i);
918 if (!pDisplay)
919 continue;
920
921 if (!fEnable)
922 CrDpEnter(pDisplay);
923 else
924 CrDpLeave(pDisplay);
925 }
926}
927
928static void crServerDentryPresentVRAM(CRMuralInfo *mural, CR_DISPLAY_ENTRY *pDEntry, char *pixels)
929{
930 char *tmppixels;
931 CRrecti rect, rectwr, sectr;
932 int i, rc;
933 uint32_t j;
934
935 if (mural->fPresentMode & CR_SERVER_REDIR_F_FBO_RAM_VMFB)
936 {
937 for (i=0; i<cr_server.screenCount; ++i)
938 {
939 if (crServerIntersectScreen(mural, pDEntry, i, &rect))
940 {
941 uint32_t cRects;
942 const RTRECT *pRects;
943
944 /* rect in window relative coords */
945 crServerTransformRect(&rectwr, &rect, -mural->gX, -mural->gY);
946
947 rc = CrVrScrCompositorEntryRegionsGet(&mural->Compositor, &pDEntry->CEntry, &cRects, NULL, &pRects, NULL);
948 if (RT_SUCCESS(rc))
949 {
950 /*we don't get any rects info for guest compiz windows, so we treat windows as visible unless explicitly received 0 visible rects*/
951 for (j=0; j<cRects; ++j)
952 {
953 if (crServerIntersectRect(&rectwr, (CRrecti*)&pRects[j], &sectr))
954 {
955 tmppixels = crAlloc(4*(sectr.x2-sectr.x1)*(sectr.y2-sectr.y1));
956 if (!tmppixels)
957 {
958 crWarning("Out of memory in crServerPresentFBO");
959 crFree(pixels);
960 return;
961 }
962
963 crServerCopySubImage(tmppixels, pixels, &sectr, CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->width, CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->height);
964 /*Note: pfnPresentFBO would free tmppixels*/
965 cr_server.pfnPresentFBO(tmppixels, i,
966 sectr.x1+mural->gX+CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->x-cr_server.screen[i].x,
967 sectr.y1+mural->gY+CrVrScrCompositorEntryPosGet(&pDEntry->CEntry)->y-cr_server.screen[i].y,
968 sectr.x2-sectr.x1, sectr.y2-sectr.y1);
969 }
970 }
971 }
972 else
973 {
974 crWarning("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc);
975 }
976 }
977 }
978 }
979
980 if (pDEntry->pvORInstance)
981 {
982 /* @todo find out why presentfbo is not called but crorframe is called. */
983 cr_server.outputRedirect.CRORFrame(pDEntry->pvORInstance,
984 pixels,
985 4 * CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->width * CrVrScrCompositorEntryTexGet(&pDEntry->CEntry)->height);
986 }
987}
988
989void crServerPresentOutputRedirectEntry(CRMuralInfo *pMural, CR_DISPLAY_ENTRY *pDEntry)
990{
991 char *pixels=NULL;
992 GLuint idPBO;
993 CRContext *ctx = crStateGetCurrent();
994
995 if (!pDEntry->pvORInstance)
996 {
997 crServerSetupOutputRedirectEntry(pMural, pDEntry);
998 if (!pDEntry->pvORInstance)
999 {
1000 crWarning("crServerSetupOutputRedirectEntry failed!");
1001 return;
1002 }
1003 }
1004
1005 crServerDEntryCheckFBO(pMural, pDEntry, ctx);
1006
1007 if (pMural->fPresentMode & CR_SERVER_REDIR_F_FBO_RPW)
1008 {
1009 crError("port me!");
1010#if 0
1011 /* 1. blit to RPW entry draw texture */
1012 CRMuralInfo *pCurrentMural = cr_server.currentMural;
1013 CRContextInfo *pCurCtxInfo = cr_server.currentCtxInfo;
1014 PCR_BLITTER pBlitter = crServerVBoxBlitterGet();
1015 CRMuralInfo *pBlitterMural;
1016 CR_SERVER_CTX_SWITCH CtxSwitch;
1017 RTRECT Rect;
1018 VBOXVR_TEXTURE DstTex;
1019 CR_BLITTER_WINDOW BlitterBltInfo, CurrentBltInfo;
1020 CR_BLITTER_CONTEXT CtxBltInfo;
1021 int rc;
1022
1023 Rect.xLeft = 0;
1024 Rect.yTop = 0;
1025 Rect.xRight = Tex.width;
1026 Rect.yBottom = Tex.height;
1027
1028 if (pCurrentMural && pCurrentMural->CreateInfo.visualBits == CrBltGetVisBits(pBlitter))
1029 {
1030 pBlitterMural = pCurrentMural;
1031 }
1032 else
1033 {
1034 pBlitterMural = crServerGetDummyMural(pCurrentMural->CreateInfo.visualBits);
1035 if (!pBlitterMural)
1036 {
1037 crWarning("crServerGetDummyMural failed for blitter mural");
1038 return;
1039 }
1040 }
1041
1042 crServerRpwEntryDrawSettingsToTex(&mural->RpwEntry, &DstTex);
1043
1044 crServerCtxSwitchPrepare(&CtxSwitch, NULL);
1045
1046 crServerVBoxBlitterWinInit(&CurrentBltInfo, pCurrentMural);
1047 crServerVBoxBlitterWinInit(&BlitterBltInfo, pBlitterMural);
1048 crServerVBoxBlitterCtxInit(&CtxBltInfo, pCurCtxInfo);
1049
1050 CrBltMuralSetCurrent(pBlitter, &BlitterBltInfo);
1051
1052 rc = CrBltEnter(pBlitter, &CtxBltInfo, &CurrentBltInfo);
1053 if (RT_SUCCESS(rc))
1054 {
1055 CrBltBlitTexTex(pBlitter, &Tex, &Rect, &DstTex, &Rect, 1, 0);
1056 CrBltLeave(pBlitter);
1057 }
1058 else
1059 {
1060 crWarning("CrBltEnter failed rc %d", rc);
1061 }
1062
1063 crServerCtxSwitchPostprocess(&CtxSwitch);
1064
1065#if 1
1066 if (RT_SUCCESS(rc))
1067 {
1068 /* 2. submit RPW entry */
1069 rc = crServerRpwEntrySubmit(&cr_server.RpwWorker, &mural->RpwEntry);
1070 if (!RT_SUCCESS(rc))
1071 {
1072 crWarning("crServerRpwEntrySubmit failed rc %d", rc);
1073 }
1074 }
1075#endif
1076#endif
1077 return;
1078 }
1079
1080 if (cr_server.bUsePBOForReadback && !pDEntry->idPBO)
1081 {
1082 crWarning("Mural doesn't have PBO even though bUsePBOForReadback is set!");
1083 }
1084
1085 idPBO = cr_server.bUsePBOForReadback ? pDEntry->idPBO : 0;
1086
1087 pixels = CrHlpGetTexImage(ctx, CrVrScrCompositorEntryTexGet(&pDEntry->CEntry), idPBO, GL_BGRA);
1088 if (!pixels)
1089 {
1090 crWarning("CrHlpGetTexImage failed in crServerPresentFBO");
1091 return;
1092 }
1093
1094 crServerDentryPresentVRAM(pMural, pDEntry, pixels);
1095
1096 CrHlpFreeTexImage(ctx, idPBO, pixels);
1097}
1098
1099void crServerPresentOutputRedirect(CRMuralInfo *pMural)
1100{
1101 VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
1102 PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
1103
1104 CrVrScrCompositorIterInit(&pMural->Compositor, &Iter);
1105
1106 while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
1107 {
1108 CR_DISPLAY_ENTRY *pDEntry = CR_DENTRY_FROM_CENTRY(pEntry);
1109 crServerPresentOutputRedirectEntry(pMural, pDEntry);
1110 }
1111}
1112
1113void crServerOutputRedirectCheckEnableDisable(CRMuralInfo *pMural)
1114{
1115 VBOXVR_SCR_COMPOSITOR_ITERATOR Iter;
1116 PVBOXVR_SCR_COMPOSITOR_ENTRY pEntry;
1117
1118 CrVrScrCompositorIterInit(&pMural->Compositor, &Iter);
1119
1120 while ((pEntry = CrVrScrCompositorIterNext(&Iter)) != NULL)
1121 {
1122 CR_DISPLAY_ENTRY *pDEntry = CR_DENTRY_FROM_CENTRY(pEntry);
1123 crServerSetupOutputRedirectEntry(pMural, pDEntry);
1124 }
1125}
1126
1127void crServerPresentFBO(CRMuralInfo *mural)
1128{
1129 CRASSERT(mural->fPresentMode & CR_SERVER_REDIR_F_FBO);
1130 CRASSERT(cr_server.pfnPresentFBO || (mural->fPresentMode & CR_SERVER_REDIR_F_DISPLAY));
1131
1132 if (!crServerVBoxCompositionPresentNeeded(mural))
1133 return;
1134
1135 mural->fDataPresented = GL_TRUE;
1136
1137 if (mural->fPresentMode & CR_SERVER_REDIR_F_DISPLAY)
1138 crServerVBoxCompositionPresentPerform(mural);
1139
1140 if (mural->fPresentMode & CR_SERVER_REDIR_FGROUP_REQUIRE_FBO_RAM)
1141 crServerPresentOutputRedirect(mural);
1142}
1143
1144GLboolean crServerIsRedirectedToFBO()
1145{
1146#ifdef DEBUG_misha
1147 Assert(cr_server.curClient);
1148 if (cr_server.curClient)
1149 {
1150 Assert(cr_server.curClient->currentMural == cr_server.currentMural);
1151 Assert(cr_server.curClient->currentCtxInfo == cr_server.currentCtxInfo);
1152 }
1153#endif
1154 return cr_server.curClient
1155 && cr_server.curClient->currentMural
1156 && (cr_server.curClient->currentMural->fPresentMode & CR_SERVER_REDIR_F_FBO);
1157}
1158
1159GLint crServerMuralFBOIdxFromBufferName(CRMuralInfo *mural, GLenum buffer)
1160{
1161 switch (buffer)
1162 {
1163 case GL_FRONT:
1164 case GL_FRONT_LEFT:
1165 case GL_FRONT_RIGHT:
1166 return CR_SERVER_FBO_FB_IDX(mural);
1167 case GL_BACK:
1168 case GL_BACK_LEFT:
1169 case GL_BACK_RIGHT:
1170 return CR_SERVER_FBO_BB_IDX(mural);
1171 case GL_NONE:
1172 case GL_AUX0:
1173 case GL_AUX1:
1174 case GL_AUX2:
1175 case GL_AUX3:
1176 case GL_LEFT:
1177 case GL_RIGHT:
1178 case GL_FRONT_AND_BACK:
1179 return -1;
1180 default:
1181 crWarning("crServerMuralFBOIdxFromBufferName: invalid buffer passed 0x%x", buffer);
1182 return -2;
1183 }
1184}
1185
1186void crServerMuralFBOSwapBuffers(CRMuralInfo *mural)
1187{
1188 CRContext *ctx = crStateGetCurrent();
1189 GLuint iOldCurDrawBuffer = mural->iCurDrawBuffer;
1190 GLuint iOldCurReadBuffer = mural->iCurReadBuffer;
1191 mural->iBbBuffer = ((mural->iBbBuffer + 1) % (mural->cBuffers));
1192 if (mural->iCurDrawBuffer >= 0)
1193 mural->iCurDrawBuffer = ((mural->iCurDrawBuffer + 1) % (mural->cBuffers));
1194 if (mural->iCurReadBuffer >= 0)
1195 mural->iCurReadBuffer = ((mural->iCurReadBuffer + 1) % (mural->cBuffers));
1196 Assert(iOldCurDrawBuffer != mural->iCurDrawBuffer || mural->cBuffers == 1 || mural->iCurDrawBuffer < 0);
1197 Assert(iOldCurReadBuffer != mural->iCurReadBuffer || mural->cBuffers == 1 || mural->iCurReadBuffer < 0);
1198 if (!ctx->framebufferobject.drawFB && iOldCurDrawBuffer != mural->iCurDrawBuffer)
1199 {
1200 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, CR_SERVER_FBO_FOR_IDX(mural, mural->iCurDrawBuffer));
1201 }
1202 if (!ctx->framebufferobject.readFB && iOldCurReadBuffer != mural->iCurReadBuffer)
1203 {
1204 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, CR_SERVER_FBO_FOR_IDX(mural, mural->iCurReadBuffer));
1205 }
1206 Assert(mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
1207 Assert(mural->fUseDefaultDEntry);
1208 CrVrScrCompositorEntryTexNameUpdate(&mural->DefaultDEntry.CEntry, mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
1209 if (mural->fRootVrOn)
1210 CrVrScrCompositorEntryTexNameUpdate(&mural->DefaultDEntry.RootVrCEntry, mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
1211}
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