server_muralfbo.c revision 3904a969d57a5bb3cc5136c75ec805b66f8660dc
/* $Id$ */
/** @file
* VBox crOpenGL: Window to FBO redirect support.
*/
/*
* Copyright (C) 2010-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#include "server.h"
#include "cr_string.h"
#include "cr_mem.h"
#include "cr_vreg.h"
#include "render/renderspu.h"
{
int i;
for (i=0; i<cr_server.screenCount; ++i)
{
{
return i;
}
}
return -1;
}
{
}
/* Called when a new CRMuralInfo is created
* or when OutputRedirect status is changed.
*/
{
/* Unset the previous redirect. */
{
}
/* Setup a new redirect. */
{
/* Query supported formats. */
if (pachFormats)
{
0 /* H3DOR_PROP_FORMATS */, // @todo from a header
if (RT_SUCCESS(rc))
{
{
"H3DOR_FMT_RGBA_TOPDOWN"); // @todo from a header
}
}
}
/* If this is not NULL then there was a supported format. */
{
int rc = CrVrScrCompositorEntryRegionsGet(&mural->Compositor, &mural->CEntry, &cRects, NULL, &pRects);
if (!RT_SUCCESS(rc))
{
return;
}
// @todo the code assumes that RTRECT == four of GLInts
}
}
}
{
return;
{
return;
}
{
{
{
if (tlS >= 0)
else
}
primaryS = 0;
}
{
}
}
else
{
bool fFoundWindIdScreen = false;
for (i=0; i<cr_server.screenCount; ++i)
{
|| crServerMuralCoverScreen(mural, i))
{
primaryS = i;
{
fFoundWindIdScreen = true;
}
}
}
if (primaryS<0)
{
primaryS = 0;
}
}
{
if (mural->bVisible && (mural->fPresentMode & CR_SERVER_REDIR_F_DISPLAY) && mural->fHasParentWindow)
}
if (!overlappingScreenCount)
else if (overlappingScreenCount > 1)
fPresentMode = (fPresentMode | CR_SERVER_REDIR_F_FBO_RAM_VMFB | cr_server.fVramPresentModeDefault) & ~CR_SERVER_REDIR_F_DISPLAY;
if (!(fPresentMode & CR_SERVER_REDIR_F_FBO))
{
}
else
{
{
{
}
}
}
{
cr_server.head_spu->dispatch_table.WindowPosition(mural->spuWindow, mural->hX - pVieport->x, mural->hY - pVieport->y);
}
{
}
}
{
if (!fInited)
{
}
return fSupported;
}
#define CR_SERVER_MURAL_FROM_RPW_ENTRY(_pEntry) ((CRMuralInfo*)(((uint8_t*)(_pEntry)) - RT_OFFSETOF(CRMuralInfo, RpwEntry)))
static DECLCALLBACK(void) crServerMuralRpwDataCB(const struct CR_SERVER_RPW_ENTRY* pEntry, void *pvEntryTexData)
{
}
{
{
return !fEnable;
}
if (fEnable)
{
{
int rc;
{
if (!RT_SUCCESS(rc))
{
return false;
}
}
{
rc = crServerRpwEntryInit(&cr_server.RpwWorker, &mural->RpwEntry, mural->width, mural->height, crServerMuralRpwDataCB);
if (!RT_SUCCESS(rc))
{
return false;
}
}
else
{
if (!RT_SUCCESS(rc))
{
return false;
}
}
}
}
else
{
{
// crServerRpwEntryCleanup(&cr_server.RpwWorker, &mural->RpwEntry);
}
}
return true;
}
{
{
return;
}
if (fEnable)
{
{
{
}
}
}
else
{
{
}
}
}
{
{
return;
}
{
// if (redir)
// crWarning("crServerRedirMuralFBO called with the same redir status %d", redir);
return;
}
if (redir & CR_SERVER_REDIR_F_FBO)
{
if (!crServerSupportRedirMuralFBO())
{
crWarning("FBO not supported, can't redirect window output");
goto end;
}
{
}
{
{
cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, CR_SERVER_FBO_FOR_IDX(mural, mural->iCurDrawBuffer));
}
{
cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, CR_SERVER_FBO_FOR_IDX(mural, mural->iCurReadBuffer));
}
}
}
else
{
{
{
}
{
}
}
}
end:
}
{
if (!pMuralContextInfo)
{
/* happens on saved state load */
cr_server.head_spu->dispatch_table.MakeCurrent(mural->spuWindow, 0, cr_server.MainContextInfo.SpuContext);
}
{
crWarning("mural visual bits do not match with current context visual bits!");
}
/*Color texture*/
{
}
{
}
/*Depth&Stencil*/
/*FBO*/
{
{
}
}
/*PBO*/
{
{
crWarning("PBO create failed");
}
}
/*Restore gl state*/
{
}
{
}
else
{
}
CrVrScrCompositorEntryTexNameUpdate(&mural->CEntry, mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
CrVrScrCompositorEntryTexNameUpdate(&mural->RootVrCEntry, mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
}
{
{
GLuint i;
{
mural->aidColorTexs[i] = 0;
}
mural->idDepthStencilRB = 0;
{
}
}
{
}
}
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
{
}
{
rect->x2 = MIN(mural->gX+(int)mural->fboWidth, cr_server.screen[sId].x+(int)cr_server.screen[sId].w);
rect->y2 = MIN(mural->gY+(int)mural->fboHeight, cr_server.screen[sId].y+(int)cr_server.screen[sId].h);
}
static void crServerCopySubImage(char *pDst, char* pSrc, CRrecti *pRect, int srcWidth, int srcHeight)
{
int i;
for (i=0; i<height; ++i)
{
pSrc -= srcrowsize;
pDst += dstrowsize;
}
}
{
}
{
if (currentMural)
{
}
else
{
idDrawFBO = 0;
idReadFBO = 0;
}
cr_server.head_spu->dispatch_table.VBoxPresentComposition(mural->spuWindow, &mural->Compositor, &mural->CEntry);
else
cr_server.head_spu->dispatch_table.VBoxPresentComposition(mural->spuWindow, &mural->RootVrCompositor, &mural->RootVrCEntry);
}
{
return;
}
{
if ((mural->fPresentMode & (CR_SERVER_REDIR_F_FBO | CR_SERVER_REDIR_F_DISPLAY)) != (CR_SERVER_REDIR_F_FBO | CR_SERVER_REDIR_F_DISPLAY)
|| !mural->fDataPresented
|| (!fForcePresent
return;
}
{
if ((mural->fPresentMode & (CR_SERVER_REDIR_F_FBO | CR_SERVER_REDIR_F_DISPLAY)) != (CR_SERVER_REDIR_F_FBO | CR_SERVER_REDIR_F_DISPLAY)
|| !mural->fDataPresented)
return;
}
{
{
}
}
{
{
}
}
static void crServerVBoxCompositionSetEnableStateGlobalCB(unsigned long key, void *data1, void *data2)
{
if (data2)
else
}
{
if (!fEnable)
crHashtableWalk(cr_server.muralTable, crServerVBoxCompositionSetEnableStateGlobalCB, (void*)fEnable);
crHashtableWalk(cr_server.dummyMuralTable, crServerVBoxCompositionSetEnableStateGlobalCB, (void*)fEnable);
if (fEnable)
{
if(!cr_server.cDisableEvent)
{
int i;
for (i = 0; i < cr_server.screenCount; ++i)
{
continue;
}
}
}
}
{
char *tmppixels;
int i, j;
{
for (i=0; i<cr_server.screenCount; ++i)
{
{
/* rect in window relative coords */
if (!mural->pVisibleRects)
{
/*we don't get any rects info for guest compiz windows, so we treat windows as visible unless explicitly received 0 visible rects*/
if (!mural->bReceivedRects)
{
if (!tmppixels)
{
crWarning("Out of memory in crServerPresentFBO");
return;
}
/*Note: pfnPresentFBO would free tmppixels*/
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);
}
}
else
{
for (j=0; j<mural->cVisibleRects; ++j)
{
{
if (!tmppixels)
{
crWarning("Out of memory in crServerPresentFBO");
return;
}
/*Note: pfnPresentFBO would free tmppixels*/
}
}
}
}
}
}
{
/* @todo find out why presentfbo is not called but crorframe is called. */
}
}
{
return;
{
}
return;
{
/* 1. blit to RPW entry draw texture */
int rc;
{
}
else
{
if (!pBlitterMural)
{
crWarning("crServerGetDummyMural failed for blitter mural");
return;
}
}
if (RT_SUCCESS(rc))
{
}
else
{
}
#if 1
if (RT_SUCCESS(rc))
{
/* 2. submit RPW entry */
if (!RT_SUCCESS(rc))
{
}
}
#endif
return;
}
{
crWarning("Mural doesn't have PBO even though bUsePBOForReadback is set!");
}
if (idPBO)
{
}
if (!pixels)
{
crWarning("CrHlpGetTexImage failed in crServerPresentFBO");
return;
}
}
{
#ifdef DEBUG_misha
{
}
#endif
}
{
|| buffer == GL_FRONT_LEFT
|| buffer == GL_FRONT_RIGHT)
return CR_SERVER_FBO_FB_IDX(mural);
|| buffer == GL_BACK_LEFT
|| buffer == GL_BACK_RIGHT)
return CR_SERVER_FBO_BB_IDX(mural);
return -1;
return -2;
}
{
if (mural->iCurDrawBuffer >= 0)
if (mural->iCurReadBuffer >= 0)
Assert(iOldCurDrawBuffer != mural->iCurDrawBuffer || mural->cBuffers == 1 || mural->iCurDrawBuffer < 0);
Assert(iOldCurReadBuffer != mural->iCurReadBuffer || mural->cBuffers == 1 || mural->iCurReadBuffer < 0);
{
cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, CR_SERVER_FBO_FOR_IDX(mural, mural->iCurDrawBuffer));
}
{
cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, CR_SERVER_FBO_FOR_IDX(mural, mural->iCurReadBuffer));
}
CrVrScrCompositorEntryTexNameUpdate(&mural->CEntry, mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
CrVrScrCompositorEntryTexNameUpdate(&mural->RootVrCEntry, mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
}