VirtualBox

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

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

crOpenGL: do not pass intersected rects to vrdp backend

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