VirtualBox

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

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

crOpenGL: seamles mode support impl; bugfizes & cleanup

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 24.9 KB
Line 
1/* $Id: server_muralfbo.c 45132 2013-03-21 16:11:28Z 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.215389.xyz. 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
49/* Called when a new CRMuralInfo is created
50 * or when OutputRedirect status is changed.
51 */
52void crServerSetupOutputRedirect(CRMuralInfo *mural)
53{
54 /* Unset the previous redirect. */
55 if (mural->pvOutputRedirectInstance)
56 {
57 cr_server.outputRedirect.CROREnd(mural->pvOutputRedirectInstance);
58 mural->pvOutputRedirectInstance = NULL;
59 }
60
61 /* Setup a new redirect. */
62 if (cr_server.bUseOutputRedirect)
63 {
64 /* Query supported formats. */
65 uint32_t cbFormats = 4096;
66 char *pachFormats = (char *)crAlloc(cbFormats);
67
68 if (pachFormats)
69 {
70 int rc = cr_server.outputRedirect.CRORContextProperty(cr_server.outputRedirect.pvContext,
71 0 /* H3DOR_PROP_FORMATS */, // @todo from a header
72 pachFormats, cbFormats, &cbFormats);
73 if (RT_SUCCESS(rc))
74 {
75 if (RTStrStr(pachFormats, "H3DOR_FMT_RGBA_TOPDOWN"))
76 {
77 cr_server.outputRedirect.CRORBegin(cr_server.outputRedirect.pvContext,
78 &mural->pvOutputRedirectInstance,
79 "H3DOR_FMT_RGBA_TOPDOWN"); // @todo from a header
80 }
81 }
82
83 crFree(pachFormats);
84 }
85
86 /* If this is not NULL then there was a supported format. */
87 if (mural->pvOutputRedirectInstance)
88 {
89 cr_server.outputRedirect.CRORGeometry(mural->pvOutputRedirectInstance,
90 mural->hX, mural->hY,
91 mural->width, mural->height);
92 // @todo the code assumes that RTRECT == four of GLInts
93 cr_server.outputRedirect.CRORVisibleRegion(mural->pvOutputRedirectInstance,
94 mural->cVisibleRects, (RTRECT *)mural->pVisibleRects);
95 }
96 }
97}
98
99void crServerCheckMuralGeometry(CRMuralInfo *mural)
100{
101 int tlS, brS, trS, blS;
102 int overlappingScreenCount, primaryS, i;
103
104 if (!mural->CreateInfo.externalID)
105 return;
106
107 if (!mural->width || !mural->height)
108 {
109 crServerRedirMuralFBO(mural, CR_SERVER_REDIR_NONE);
110 crServerDeleteMuralFBO(mural);
111 return;
112 }
113
114 if (cr_server.screenCount<2 && !cr_server.bForceOffscreenRendering)
115 {
116 CRScreenViewportInfo *pVieport = &cr_server.screenVieport[mural->screenId];
117 CRASSERT(cr_server.screenCount>0);
118 CRASSERT(mural->fUseFBO == CR_SERVER_REDIR_NONE);
119
120 mural->hX = mural->gX-cr_server.screen[0].x;
121 mural->hY = mural->gY-cr_server.screen[0].y;
122
123 cr_server.head_spu->dispatch_table.WindowPosition(mural->spuWindow, mural->hX - pVieport->x, mural->hY - pVieport->y);
124
125 return;
126 }
127
128 tlS = crServerGetPointScreen(mural->gX, mural->gY);
129 brS = crServerGetPointScreen(mural->gX+mural->width-1, mural->gY+mural->height-1);
130
131 if (tlS==brS && tlS>=0)
132 {
133 overlappingScreenCount = 1;
134 primaryS = tlS;
135 }
136 else
137 {
138 trS = crServerGetPointScreen(mural->gX+mural->width-1, mural->gY);
139 blS = crServerGetPointScreen(mural->gX, mural->gY+mural->height-1);
140
141 primaryS = -1; overlappingScreenCount = 0;
142 for (i=0; i<cr_server.screenCount; ++i)
143 {
144 if ((i==tlS) || (i==brS) || (i==trS) || (i==blS)
145 || crServerMuralCoverScreen(mural, i))
146 {
147 overlappingScreenCount++;
148 primaryS = primaryS<0 ? i:primaryS;
149 }
150 }
151
152 if (!overlappingScreenCount)
153 {
154 primaryS = 0;
155 }
156 }
157
158 if (primaryS!=mural->screenId)
159 {
160 mural->screenId = primaryS;
161
162 renderspuSetWindowId(cr_server.screen[primaryS].winID);
163 renderspuReparentWindow(mural->spuWindow);
164 renderspuSetWindowId(cr_server.screen[0].winID);
165 }
166
167 mural->hX = mural->gX-cr_server.screen[primaryS].x;
168 mural->hY = mural->gY-cr_server.screen[primaryS].y;
169
170 if (overlappingScreenCount<2 && !cr_server.bForceOffscreenRendering)
171 {
172 CRScreenViewportInfo *pVieport = &cr_server.screenVieport[mural->screenId];
173
174 if (mural->fUseFBO)
175 {
176 crServerRedirMuralFBO(mural, CR_SERVER_REDIR_NONE);
177 crServerDeleteMuralFBO(mural);
178 }
179
180 cr_server.head_spu->dispatch_table.WindowPosition(mural->spuWindow, mural->hX - pVieport->x, mural->hY - pVieport->y);
181 }
182 else
183 {
184 GLubyte redir = overlappingScreenCount >= 2 ? CR_SERVER_REDIR_FBO_RAM : cr_server.bForceOffscreenRendering;
185
186 if (mural->spuWindow)
187 {
188 if (mural->fUseFBO)
189 {
190 if (mural->width!=mural->fboWidth
191 || mural->height!=mural->fboHeight)
192 {
193 crServerRedirMuralFBO(mural, CR_SERVER_REDIR_NONE);
194 crServerDeleteMuralFBO(mural);
195 }
196 }
197
198 if (mural->fUseFBO != redir)
199 {
200 crServerRedirMuralFBO(mural, redir);
201 }
202 }
203#ifdef DEBUG_misha
204 else
205 {
206 Assert(!mural->fUseFBO);
207 }
208#endif
209
210 if (mural->fUseFBO != CR_SERVER_REDIR_FBO_RAM)
211 {
212 CRScreenViewportInfo *pVieport = &cr_server.screenVieport[mural->screenId];
213
214 cr_server.head_spu->dispatch_table.WindowPosition(mural->spuWindow, mural->hX - pVieport->x, mural->hY - pVieport->y);
215 }
216 }
217
218 if (mural->pvOutputRedirectInstance)
219 {
220 cr_server.outputRedirect.CRORGeometry(mural->pvOutputRedirectInstance,
221 mural->hX, mural->hY,
222 mural->width, mural->height);
223 }
224}
225
226GLboolean crServerSupportRedirMuralFBO(void)
227{
228 static GLboolean fInited = GL_FALSE;
229 static GLboolean fSupported = GL_FALSE;
230 if (!fInited)
231 {
232 const GLubyte* pExt = cr_server.head_spu->dispatch_table.GetString(GL_REAL_EXTENSIONS);
233
234 fSupported = ( NULL!=crStrstr((const char*)pExt, "GL_ARB_framebuffer_object")
235 || NULL!=crStrstr((const char*)pExt, "GL_EXT_framebuffer_object"))
236 && NULL!=crStrstr((const char*)pExt, "GL_ARB_texture_non_power_of_two");
237 fInited = GL_TRUE;
238 }
239 return fSupported;
240}
241
242static void crServerCreateMuralFBO(CRMuralInfo *mural);
243
244void crServerRedirMuralFBO(CRMuralInfo *mural, GLubyte redir)
245{
246 if (mural->fUseFBO == redir)
247 {
248 if (redir)
249 crWarning("crServerRedirMuralFBO called with the same redir status %d", redir);
250 return;
251 }
252
253 crServerVBoxCompositionDisable(mural);
254
255 if (redir)
256 {
257 if (!crServerSupportRedirMuralFBO())
258 {
259 crWarning("FBO not supported, can't redirect window output");
260 return;
261 }
262
263 if (redir == CR_SERVER_REDIR_FBO_RAM)
264 cr_server.head_spu->dispatch_table.WindowShow(mural->spuWindow, GL_FALSE);
265 else
266 cr_server.head_spu->dispatch_table.WindowShow(mural->spuWindow, mural->bVisible);
267
268 if (mural->aidFBOs[0]==0)
269 {
270 crServerCreateMuralFBO(mural);
271 }
272
273 if (cr_server.currentMural == mural)
274 {
275 if (!crStateGetCurrent()->framebufferobject.drawFB)
276 {
277 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, mural->aidFBOs[mural->iCurDrawBuffer]);
278 }
279 if (!crStateGetCurrent()->framebufferobject.readFB)
280 {
281 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, mural->aidFBOs[mural->iCurReadBuffer]);
282 }
283
284 crStateGetCurrent()->buffer.width = 0;
285 crStateGetCurrent()->buffer.height = 0;
286 }
287 }
288 else
289 {
290 if (redir == CR_SERVER_REDIR_NONE)
291 {
292 /* tell renderspu we do not want compositor presentation anymore
293 * renderspu will ensure its redraw thread is done with using the compositor, etc. */
294 crServerVBoxCompositionDisable(mural);
295 }
296
297 if (mural->fUseFBO == CR_SERVER_REDIR_FBO_RAM)
298 cr_server.head_spu->dispatch_table.WindowShow(mural->spuWindow, mural->bVisible);
299
300 if (cr_server.currentMural == mural)
301 {
302 if (!crStateGetCurrent()->framebufferobject.drawFB)
303 {
304 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
305 }
306 if (!crStateGetCurrent()->framebufferobject.readFB)
307 {
308 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, 0);
309 }
310
311 crStateGetCurrent()->buffer.width = mural->width;
312 crStateGetCurrent()->buffer.height = mural->height;
313 }
314 }
315
316 mural->fUseFBO = redir;
317 crServerVBoxCompositionReenable(mural, GL_FALSE);
318}
319
320static void crServerCreateMuralFBO(CRMuralInfo *mural)
321{
322 CRContext *ctx = crStateGetCurrent();
323 GLuint uid, i;
324 GLenum status;
325 SPUDispatchTable *gl = &cr_server.head_spu->dispatch_table;
326 CRContextInfo *pMuralContextInfo;
327 VBOXVR_TEXTURE Tex;
328
329 CRASSERT(mural->aidFBOs[0]==0);
330 CRASSERT(mural->aidFBOs[1]==0);
331 CRASSERT(mural->width == mural->CEntry.Tex.width);
332 CRASSERT(mural->height == mural->CEntry.Tex.height);
333
334 pMuralContextInfo = cr_server.currentCtxInfo;
335 if (!pMuralContextInfo)
336 {
337 /* happens on saved state load */
338 CRASSERT(cr_server.MainContextInfo.SpuContext);
339 pMuralContextInfo = &cr_server.MainContextInfo;
340 cr_server.head_spu->dispatch_table.MakeCurrent(mural->spuWindow, 0, cr_server.MainContextInfo.SpuContext);
341 }
342
343 if (pMuralContextInfo->CreateInfo.visualBits != mural->CreateInfo.visualBits)
344 {
345 crWarning("mural visual bits do not match with current context visual bits!");
346 }
347
348 mural->cBuffers = 2;
349 mural->iBbBuffer = 0;
350 /*Color texture*/
351 for (i = 0; i < mural->cBuffers; ++i)
352 {
353 gl->GenTextures(1, &mural->aidColorTexs[i]);
354 gl->BindTexture(GL_TEXTURE_2D, mural->aidColorTexs[i]);
355 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
356 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
357 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
358 gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
359 if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
360 {
361 gl->BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
362 }
363 gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, mural->width, mural->height,
364 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
365 }
366
367 /*Depth&Stencil*/
368 gl->GenRenderbuffersEXT(1, &mural->idDepthStencilRB);
369 gl->BindRenderbufferEXT(GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
370 gl->RenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT,
371 mural->width, mural->height);
372
373 /*FBO*/
374 for (i = 0; i < mural->cBuffers; ++i)
375 {
376 gl->GenFramebuffersEXT(1, &mural->aidFBOs[i]);
377 gl->BindFramebufferEXT(GL_FRAMEBUFFER_EXT, mural->aidFBOs[i]);
378
379 gl->FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
380 GL_TEXTURE_2D, mural->aidColorTexs[i], 0);
381 gl->FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
382 GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
383 gl->FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
384 GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
385
386 status = gl->CheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
387 if (status!=GL_FRAMEBUFFER_COMPLETE_EXT)
388 {
389 crWarning("FBO status(0x%x) isn't complete", status);
390 }
391 }
392
393 mural->fboWidth = mural->width;
394 mural->fboHeight = mural->height;
395
396 mural->iCurDrawBuffer = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.drawBuffer);
397 mural->iCurReadBuffer = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.readBuffer);
398
399 /*PBO*/
400 if (cr_server.bUsePBOForReadback)
401 {
402 gl->GenBuffersARB(1, &mural->idPBO);
403 gl->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, mural->idPBO);
404 gl->BufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, mural->width*mural->height*4, 0, GL_STREAM_READ_ARB);
405 gl->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, ctx->bufferobject.packBuffer->hwid);
406
407 if (!mural->idPBO)
408 {
409 crWarning("PBO create failed");
410 }
411 }
412
413 /*Restore gl state*/
414 uid = ctx->texture.unit[ctx->texture.curTextureUnit].currentTexture2D->hwid;
415 gl->BindTexture(GL_TEXTURE_2D, uid);
416
417 uid = ctx->framebufferobject.renderbuffer ? ctx->framebufferobject.renderbuffer->hwid:0;
418 gl->BindRenderbufferEXT(GL_RENDERBUFFER_EXT, uid);
419
420 uid = ctx->framebufferobject.drawFB ? ctx->framebufferobject.drawFB->hwid:0;
421 gl->BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, uid);
422
423 uid = ctx->framebufferobject.readFB ? ctx->framebufferobject.readFB->hwid:0;
424 gl->BindFramebufferEXT(GL_READ_FRAMEBUFFER, uid);
425
426 if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
427 {
428 gl->BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, ctx->bufferobject.unpackBuffer->hwid);
429 }
430
431 CRASSERT(mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
432
433 Tex.width = mural->width;
434 Tex.height = mural->height;
435 Tex.target = GL_TEXTURE_2D;
436 Tex.hwid = mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)];
437
438 CrVrScrCompositorEntryTexUpdate(&mural->CEntry, &Tex);
439
440 if (mural->fRootVrOn)
441 CrVrScrCompositorEntryTexUpdate(&mural->RootVrCEntry, &Tex);
442}
443
444void crServerDeleteMuralFBO(CRMuralInfo *mural)
445{
446 CRASSERT(!mural->fUseFBO);
447
448 if (mural->aidFBOs[0]!=0)
449 {
450 GLuint i;
451 for (i = 0; i < mural->cBuffers; ++i)
452 {
453 cr_server.head_spu->dispatch_table.DeleteTextures(1, &mural->aidColorTexs[i]);
454 mural->aidColorTexs[i] = 0;
455 }
456
457 cr_server.head_spu->dispatch_table.DeleteRenderbuffersEXT(1, &mural->idDepthStencilRB);
458 mural->idDepthStencilRB = 0;
459
460 for (i = 0; i < mural->cBuffers; ++i)
461 {
462 cr_server.head_spu->dispatch_table.DeleteFramebuffersEXT(1, &mural->aidFBOs[i]);
463 mural->aidFBOs[i] = 0;
464 }
465 }
466
467 if (mural->idPBO!=0)
468 {
469 CRASSERT(cr_server.bUsePBOForReadback);
470 cr_server.head_spu->dispatch_table.DeleteBuffersARB(1, &mural->idPBO);
471 mural->idPBO = 0;
472 }
473
474 mural->cBuffers = 0;
475}
476
477#define MIN(a, b) ((a) < (b) ? (a) : (b))
478#define MAX(a, b) ((a) > (b) ? (a) : (b))
479
480static GLboolean crServerIntersectRect(CRrecti *a, CRrecti *b, CRrecti *rect)
481{
482 CRASSERT(a && b && rect);
483
484 rect->x1 = MAX(a->x1, b->x1);
485 rect->x2 = MIN(a->x2, b->x2);
486 rect->y1 = MAX(a->y1, b->y1);
487 rect->y2 = MIN(a->y2, b->y2);
488
489 return (rect->x2>rect->x1) && (rect->y2>rect->y1);
490}
491
492static GLboolean crServerIntersectScreen(CRMuralInfo *mural, int sId, CRrecti *rect)
493{
494 rect->x1 = MAX(mural->gX, cr_server.screen[sId].x);
495 rect->x2 = MIN(mural->gX+(int)mural->fboWidth, cr_server.screen[sId].x+(int)cr_server.screen[sId].w);
496 rect->y1 = MAX(mural->gY, cr_server.screen[sId].y);
497 rect->y2 = MIN(mural->gY+(int)mural->fboHeight, cr_server.screen[sId].y+(int)cr_server.screen[sId].h);
498
499 return (rect->x2>rect->x1) && (rect->y2>rect->y1);
500}
501
502static void crServerCopySubImage(char *pDst, char* pSrc, CRrecti *pRect, int srcWidth, int srcHeight)
503{
504 int i;
505 int dstrowsize = 4*(pRect->x2-pRect->x1);
506 int srcrowsize = 4*srcWidth;
507 int height = pRect->y2-pRect->y1;
508
509 pSrc += 4*pRect->x1 + srcrowsize*(srcHeight-1-pRect->y1);
510
511 for (i=0; i<height; ++i)
512 {
513 crMemcpy(pDst, pSrc, dstrowsize);
514
515 pSrc -= srcrowsize;
516 pDst += dstrowsize;
517 }
518}
519
520static void crServerTransformRect(CRrecti *pDst, CRrecti *pSrc, int dx, int dy)
521{
522 pDst->x1 = pSrc->x1+dx;
523 pDst->x2 = pSrc->x2+dx;
524 pDst->y1 = pSrc->y1+dy;
525 pDst->y2 = pSrc->y2+dy;
526}
527
528static void crServerVBoxCompositionPresentPerform(CRMuralInfo *mural)
529{
530 CRMuralInfo *currentMural = cr_server.currentMural;
531 CRContextInfo *curCtxInfo = cr_server.currentCtxInfo;
532 GLuint idDrawFBO, idReadFBO;
533 CRContext *curCtx = curCtxInfo->pContext;
534
535 CRASSERT(curCtx == crStateGetCurrent());
536
537 if (currentMural)
538 {
539 idDrawFBO = currentMural->aidFBOs[currentMural->iCurDrawBuffer];
540 idReadFBO = currentMural->aidFBOs[currentMural->iCurReadBuffer];
541 }
542 else
543 {
544 idDrawFBO = 0;
545 idReadFBO = 0;
546 }
547
548 crStateSwitchPrepare(NULL, curCtx, idDrawFBO, idReadFBO);
549
550 if (!mural->fRootVrOn)
551 cr_server.head_spu->dispatch_table.VBoxPresentComposition(mural->spuWindow, &mural->Compositor, &mural->CEntry);
552 else
553 cr_server.head_spu->dispatch_table.VBoxPresentComposition(mural->spuWindow, &mural->RootVrCompositor, &mural->RootVrCEntry);
554
555 crStateSwitchPostprocess(curCtx, NULL, idDrawFBO, idReadFBO);
556}
557
558void crServerVBoxCompositionPresent(CRMuralInfo *mural)
559{
560 if (!crServerVBoxCompositionPresentNeeded(mural))
561 return;
562 crServerVBoxCompositionPresentPerform(mural);
563}
564
565void crServerVBoxCompositionReenable(CRMuralInfo *mural, GLboolean fForcePresent)
566{
567 if (mural->fUseFBO != CR_SERVER_REDIR_FBO_BLT ||
568 (!fForcePresent
569 && !crServerVBoxCompositionPresentNeeded(mural)))
570 return;
571
572 crServerVBoxCompositionPresentPerform(mural);
573}
574
575void crServerVBoxCompositionDisable(CRMuralInfo *mural)
576{
577 if (mural->fUseFBO != CR_SERVER_REDIR_FBO_BLT)
578 return;
579 cr_server.head_spu->dispatch_table.VBoxPresentComposition(mural->spuWindow, NULL, NULL);
580}
581
582void crServerPresentFBO(CRMuralInfo *mural)
583{
584 char *pixels=NULL, *tmppixels;
585 int i, j;
586 CRrecti rect, rectwr, sectr;
587 GLuint idPBO;
588 CRContext *ctx = crStateGetCurrent();
589 VBOXVR_TEXTURE Tex;
590
591 CRASSERT(mural->fUseFBO);
592 CRASSERT(cr_server.pfnPresentFBO || mural->fUseFBO == CR_SERVER_REDIR_FBO_BLT);
593
594 if (mural->fUseFBO == CR_SERVER_REDIR_FBO_BLT)
595 {
596 crServerVBoxCompositionPresent(mural);
597 return;
598 }
599
600 if (!crServerVBoxCompositionPresentNeeded(mural))
601 return;
602
603 Tex.width = mural->width;
604 Tex.height = mural->height;
605 Tex.target = GL_TEXTURE_2D;
606 Tex.hwid = mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)];
607 CRASSERT(Tex.hwid);
608
609 if (cr_server.bUsePBOForReadback && !mural->idPBO)
610 {
611 crWarning("Mural doesn't have PBO even though bUsePBOForReadback is set!");
612 }
613
614 idPBO = cr_server.bUsePBOForReadback ? mural->idPBO : 0;
615 if (idPBO)
616 {
617 CRASSERT(mural->fboWidth == mural->width);
618 CRASSERT(mural->fboHeight == mural->height);
619 }
620
621 pixels = CrHlpGetTexImage(ctx, &Tex, idPBO, GL_BGRA);
622 if (!pixels)
623 {
624 crWarning("CrHlpGetTexImage failed in crServerPresentFBO");
625 return;
626 }
627
628 for (i=0; i<cr_server.screenCount; ++i)
629 {
630 if (crServerIntersectScreen(mural, i, &rect))
631 {
632 /* rect in window relative coords */
633 crServerTransformRect(&rectwr, &rect, -mural->gX, -mural->gY);
634
635 if (!mural->pVisibleRects)
636 {
637 /*we don't get any rects info for guest compiz windows, so we treat windows as visible unless explicitly received 0 visible rects*/
638 if (!mural->bReceivedRects)
639 {
640 tmppixels = crAlloc(4*(rect.x2-rect.x1)*(rect.y2-rect.y1));
641 if (!tmppixels)
642 {
643 crWarning("Out of memory in crServerPresentFBO");
644 crFree(pixels);
645 return;
646 }
647
648 crServerCopySubImage(tmppixels, pixels, &rectwr, mural->fboWidth, mural->fboHeight);
649 /*Note: pfnPresentFBO would free tmppixels*/
650 cr_server.pfnPresentFBO(tmppixels, i, rect.x1-cr_server.screen[i].x, rect.y1-cr_server.screen[i].y, rect.x2-rect.x1, rect.y2-rect.y1);
651 }
652 }
653 else
654 {
655 for (j=0; j<mural->cVisibleRects; ++j)
656 {
657 if (crServerIntersectRect(&rectwr, (CRrecti*) &mural->pVisibleRects[4*j], &sectr))
658 {
659 tmppixels = crAlloc(4*(sectr.x2-sectr.x1)*(sectr.y2-sectr.y1));
660 if (!tmppixels)
661 {
662 crWarning("Out of memory in crServerPresentFBO");
663 crFree(pixels);
664 return;
665 }
666
667 crServerCopySubImage(tmppixels, pixels, &sectr, mural->fboWidth, mural->fboHeight);
668 /*Note: pfnPresentFBO would free tmppixels*/
669 cr_server.pfnPresentFBO(tmppixels, i,
670 sectr.x1+mural->gX-cr_server.screen[i].x,
671 sectr.y1+mural->gY-cr_server.screen[i].y,
672 sectr.x2-sectr.x1, sectr.y2-sectr.y1);
673 }
674 }
675 }
676 }
677 }
678
679 if (mural->pvOutputRedirectInstance)
680 {
681 /* @todo find out why presentfbo is not called but crorframe is called. */
682 cr_server.outputRedirect.CRORFrame(mural->pvOutputRedirectInstance,
683 pixels,
684 4 * mural->fboWidth * mural->fboHeight);
685 }
686
687 CrHlpFreeTexImage(ctx, idPBO, pixels);
688}
689
690GLboolean crServerIsRedirectedToFBO()
691{
692#ifdef DEBUG_misha
693 Assert(cr_server.curClient);
694 if (cr_server.curClient)
695 {
696 Assert(cr_server.curClient->currentMural == cr_server.currentMural);
697 Assert(cr_server.curClient->currentCtxInfo == cr_server.currentCtxInfo);
698 }
699#endif
700 return cr_server.curClient
701 && cr_server.curClient->currentMural
702 && cr_server.curClient->currentMural->fUseFBO;
703}
704
705GLuint crServerMuralFBOIdxFromBufferName(CRMuralInfo *mural, GLenum buffer)
706{
707 if (buffer == GL_FRONT
708 || buffer == GL_FRONT_LEFT
709 || buffer == GL_FRONT_RIGHT)
710 return CR_SERVER_FBO_FB_IDX(mural);
711 return CR_SERVER_FBO_BB_IDX(mural);
712}
713
714void crServerMuralFBOSwapBuffers(CRMuralInfo *mural)
715{
716 CRContext *ctx = crStateGetCurrent();
717 GLuint iOldCurDrawBuffer = mural->iCurDrawBuffer;
718 GLuint iOldCurReadBuffer = mural->iCurReadBuffer;
719 mural->iBbBuffer = ((mural->iBbBuffer + 1) % (mural->cBuffers));
720 mural->iCurDrawBuffer = ((mural->iCurDrawBuffer + 1) % (mural->cBuffers));
721 mural->iCurReadBuffer = ((mural->iCurReadBuffer + 1) % (mural->cBuffers));
722 Assert(iOldCurDrawBuffer != mural->iCurDrawBuffer || mural->cBuffers == 1);
723 Assert(iOldCurReadBuffer != mural->iCurReadBuffer || mural->cBuffers == 1);
724 if (!ctx->framebufferobject.drawFB && iOldCurDrawBuffer != mural->iCurDrawBuffer)
725 {
726 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, mural->aidFBOs[mural->iCurDrawBuffer]);
727 }
728 if (!ctx->framebufferobject.readFB && iOldCurReadBuffer != mural->iCurReadBuffer)
729 {
730 cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, mural->aidFBOs[mural->iCurReadBuffer]);
731 }
732 Assert(mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
733 CrVrScrCompositorEntryTexNameUpdate(&mural->CEntry, mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
734 if (mural->fRootVrOn)
735 CrVrScrCompositorEntryTexNameUpdate(&mural->RootVrCEntry, mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
736}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette