server_muralfbo.c revision 35eff0d985946a77d015272714a53e99f0d5ce8f
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync/* $Id$ */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync/** @file
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * VBox crOpenGL: Window to FBO redirect support.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync/*
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Copyright (C) 2010 Oracle Corporation
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync *
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * available from http://www.virtualbox.org. This file is free software;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * you can redistribute it and/or modify it under the terms of the GNU
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * General Public License (GPL) as published by the Free Software
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#include "server.h"
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#include "cr_string.h"
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#include "cr_mem.h"
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#include "render/renderspu.h"
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsyncstatic int crServerGetPointScreen(GLint x, GLint y)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync{
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync int i;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync for (i=0; i<cr_server.screenCount; ++i)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if ((x>=cr_server.screen[i].x && x<cr_server.screen[i].x+(int)cr_server.screen[i].w)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync && (y>=cr_server.screen[i].y && y<cr_server.screen[i].y+(int)cr_server.screen[i].h))
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync return i;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync return -1;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync}
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsyncstatic GLboolean crServerMuralCoverScreen(CRMuralInfo *mural, int sId)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync{
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync return mural->gX < cr_server.screen[sId].x
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync && mural->gX+(int)mural->width > cr_server.screen[sId].x+(int)cr_server.screen[sId].w
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync && mural->gY < cr_server.screen[sId].y
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync && mural->gY+(int)mural->height > cr_server.screen[sId].y+(int)cr_server.screen[sId].h;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync}
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync/* Called when a new CRMuralInfo is created
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * or when OutputRedirect status is changed.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync */
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsyncvoid crServerSetupOutputRedirect(CRMuralInfo *mural)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync{
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* Unset the previous redirect. */
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync if (mural->pvOutputRedirectInstance)
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync {
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync cr_server.outputRedirect.CROREnd(mural->pvOutputRedirectInstance);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync mural->pvOutputRedirectInstance = NULL;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* Setup a new redirect. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (cr_server.bUseOutputRedirect)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync /* Query supported formats. */
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync uint32_t cbFormats = 4096;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync char *pachFormats = (char *)crAlloc(cbFormats);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (pachFormats)
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync {
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync int rc = cr_server.outputRedirect.CRORContextProperty(cr_server.outputRedirect.pvContext,
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync 0 /* H3DOR_PROP_FORMATS */, // @todo from a header
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync pachFormats, cbFormats, &cbFormats);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (RT_SUCCESS(rc))
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (RTStrStr(pachFormats, "H3DOR_FMT_RGBA_TOPDOWN"))
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync cr_server.outputRedirect.CRORBegin(cr_server.outputRedirect.pvContext,
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync &mural->pvOutputRedirectInstance,
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync "H3DOR_FMT_RGBA_TOPDOWN"); // @todo from a header
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync crFree(pachFormats);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* If this is not NULL then there was a supported format. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (mural->pvOutputRedirectInstance)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync cr_server.outputRedirect.CRORGeometry(mural->pvOutputRedirectInstance,
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync mural->hX, mural->hY,
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync mural->width, mural->height);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync // @todo the code assumes that RTRECT == four of GLInts
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync cr_server.outputRedirect.CRORVisibleRegion(mural->pvOutputRedirectInstance,
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync mural->cVisibleRects, (RTRECT *)mural->pVisibleRects);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync}
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsyncvoid crServerCheckMuralGeometry(CRMuralInfo *mural)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync{
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync int tlS, brS, trS, blS;
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync int overlappingScreenCount, primaryS, i;
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync if (cr_server.screenCount<2 && !cr_server.bForceOffscreenRendering)
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync {
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync CRASSERT(cr_server.screenCount>0);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync mural->hX = mural->gX-cr_server.screen[0].x;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync mural->hY = mural->gY-cr_server.screen[0].y;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync cr_server.head_spu->dispatch_table.WindowPosition(mural->spuWindow, mural->hX, mural->hY);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync return;
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync tlS = crServerGetPointScreen(mural->gX, mural->gY);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync brS = crServerGetPointScreen(mural->gX+mural->width-1, mural->gY+mural->height-1);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (tlS==brS && tlS>=0)
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync overlappingScreenCount = 1;
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync primaryS = tlS;
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync }
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync else
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync trS = crServerGetPointScreen(mural->gX+mural->width-1, mural->gY);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync blS = crServerGetPointScreen(mural->gX, mural->gY+mural->height-1);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync primaryS = -1; overlappingScreenCount = 0;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync for (i=0; i<cr_server.screenCount; ++i)
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync {
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync if ((i==tlS) || (i==brS) || (i==trS) || (i==blS)
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync || crServerMuralCoverScreen(mural, i))
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync overlappingScreenCount++;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync primaryS = primaryS<0 ? i:primaryS;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync if (!overlappingScreenCount)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync primaryS = 0;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (primaryS!=mural->screenId)
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync {
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync mural->screenId = primaryS;
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync renderspuSetWindowId(cr_server.screen[primaryS].winID);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync renderspuReparentWindow(mural->spuWindow);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync renderspuSetWindowId(cr_server.screen[0].winID);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync mural->hX = mural->gX-cr_server.screen[primaryS].x;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync mural->hY = mural->gY-cr_server.screen[primaryS].y;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (overlappingScreenCount<2 && !cr_server.bForceOffscreenRendering)
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (mural->bUseFBO)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync crServerRedirMuralFBO(mural, GL_FALSE);
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync crServerDeleteMuralFBO(mural);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync cr_server.head_spu->dispatch_table.WindowPosition(mural->spuWindow, mural->hX, mural->hY);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync else
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (!mural->bUseFBO)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync crServerRedirMuralFBO(mural, GL_TRUE);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync else
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
2ca0ef39e90f953a6517aa2a658146c70485425dvboxsync if (mural->width!=mural->fboWidth
2ca0ef39e90f953a6517aa2a658146c70485425dvboxsync || mural->height!=mural->height)
2ca0ef39e90f953a6517aa2a658146c70485425dvboxsync {
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync crServerRedirMuralFBO(mural, GL_FALSE);
2ca0ef39e90f953a6517aa2a658146c70485425dvboxsync crServerDeleteMuralFBO(mural);
2ca0ef39e90f953a6517aa2a658146c70485425dvboxsync crServerRedirMuralFBO(mural, GL_TRUE);
2ca0ef39e90f953a6517aa2a658146c70485425dvboxsync }
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync }
2ca0ef39e90f953a6517aa2a658146c70485425dvboxsync
2ca0ef39e90f953a6517aa2a658146c70485425dvboxsync if (!mural->bUseFBO)
2ca0ef39e90f953a6517aa2a658146c70485425dvboxsync {
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync cr_server.head_spu->dispatch_table.WindowPosition(mural->spuWindow, mural->hX, mural->hY);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync }
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync }
2ca0ef39e90f953a6517aa2a658146c70485425dvboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (mural->pvOutputRedirectInstance)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync cr_server.outputRedirect.CRORGeometry(mural->pvOutputRedirectInstance,
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync mural->hX, mural->hY,
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync mural->width, mural->height);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync}
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsyncGLboolean crServerSupportRedirMuralFBO(void)
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync{
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync static GLboolean fInited = GL_FALSE;
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync static GLboolean fSupported = GL_FALSE;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (!fInited)
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync {
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync const GLubyte* pExt = cr_server.head_spu->dispatch_table.GetString(GL_REAL_EXTENSIONS);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync fSupported = ( NULL!=crStrstr((const char*)pExt, "GL_ARB_framebuffer_object")
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync || NULL!=crStrstr((const char*)pExt, "GL_EXT_framebuffer_object"))
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync && NULL!=crStrstr((const char*)pExt, "GL_ARB_texture_non_power_of_two");
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync fInited = GL_TRUE;
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync }
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync return fSupported;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync}
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsyncvoid crServerRedirMuralFBO(CRMuralInfo *mural, GLboolean redir)
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync{
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync if (redir)
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync {
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync if (!crServerSupportRedirMuralFBO())
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync {
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync crWarning("FBO not supported, can't redirect window output");
2ca0ef39e90f953a6517aa2a658146c70485425dvboxsync return;
2ca0ef39e90f953a6517aa2a658146c70485425dvboxsync }
2ca0ef39e90f953a6517aa2a658146c70485425dvboxsync
2ca0ef39e90f953a6517aa2a658146c70485425dvboxsync cr_server.head_spu->dispatch_table.WindowShow(mural->spuWindow, GL_FALSE);
2ca0ef39e90f953a6517aa2a658146c70485425dvboxsync
2ca0ef39e90f953a6517aa2a658146c70485425dvboxsync if (mural->idFBO==0)
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync crServerCreateMuralFBO(mural);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync if (!crStateGetCurrent()->framebufferobject.drawFB)
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync {
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, mural->idFBO);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync if (!crStateGetCurrent()->framebufferobject.readFB)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, mural->idFBO);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync }
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync crStateGetCurrent()->buffer.width = 0;
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync crStateGetCurrent()->buffer.height = 0;
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync }
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync else
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync {
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync cr_server.head_spu->dispatch_table.WindowShow(mural->spuWindow, mural->bVisible);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync if (mural->bUseFBO && crServerSupportRedirMuralFBO())
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync {
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync if (!crStateGetCurrent()->framebufferobject.drawFB)
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync {
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync }
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync if (!crStateGetCurrent()->framebufferobject.readFB)
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync {
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, 0);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync }
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync }
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync crStateGetCurrent()->buffer.width = mural->width;
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync crStateGetCurrent()->buffer.height = mural->height;
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync }
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync mural->bUseFBO = redir;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync}
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsyncvoid crServerCreateMuralFBO(CRMuralInfo *mural)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync{
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync CRContext *ctx = crStateGetCurrent();
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync GLuint uid;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync GLenum status;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync SPUDispatchTable *gl = &cr_server.head_spu->dispatch_table;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync CRASSERT(mural->idFBO==0);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /*Color texture*/
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync gl->GenTextures(1, &mural->idColorTex);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync gl->BindTexture(GL_TEXTURE_2D, mural->idColorTex);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
2ca0ef39e90f953a6517aa2a658146c70485425dvboxsync gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync gl->BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
2ca0ef39e90f953a6517aa2a658146c70485425dvboxsync gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, mural->width, mural->height,
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /*Depth&Stencil*/
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync gl->GenRenderbuffersEXT(1, &mural->idDepthStencilRB);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync gl->BindRenderbufferEXT(GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync gl->RenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT,
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync mural->width, mural->height);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /*FBO*/
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync gl->GenFramebuffersEXT(1, &mural->idFBO);
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync gl->BindFramebufferEXT(GL_FRAMEBUFFER_EXT, mural->idFBO);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync gl->FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync GL_TEXTURE_2D, mural->idColorTex, 0);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync gl->FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync gl->FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync status = gl->CheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (status!=GL_FRAMEBUFFER_COMPLETE_EXT)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync crWarning("FBO status(0x%x) isn't complete", status);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync mural->fboWidth = mural->width;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync mural->fboHeight = mural->height;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /*PBO*/
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (cr_server.bUsePBOForReadback)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync gl->GenBuffersARB(1, &mural->idPBO);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync gl->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, mural->idPBO);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync gl->BufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, mural->width*mural->height*4, 0, GL_STREAM_READ_ARB);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync gl->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, ctx->bufferobject.packBuffer->hwid);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (!mural->idPBO)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync crWarning("PBO create failed");
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /*Restore gl state*/
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync uid = ctx->texture.unit[ctx->texture.curTextureUnit].currentTexture2D->hwid;
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync gl->BindTexture(GL_TEXTURE_2D, uid);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync uid = ctx->framebufferobject.renderbuffer ? ctx->framebufferobject.renderbuffer->hwid:0;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync gl->BindRenderbufferEXT(GL_RENDERBUFFER_EXT, uid);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync uid = ctx->framebufferobject.drawFB ? ctx->framebufferobject.drawFB->hwid:0;
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync gl->BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, uid);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync uid = ctx->framebufferobject.readFB ? ctx->framebufferobject.readFB->hwid:0;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync gl->BindFramebufferEXT(GL_READ_FRAMEBUFFER, uid);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync gl->BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, ctx->bufferobject.unpackBuffer->hwid);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync}
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsyncvoid crServerDeleteMuralFBO(CRMuralInfo *mural)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync{
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync CRASSERT(!mural->bUseFBO);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (mural->idFBO!=0)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync cr_server.head_spu->dispatch_table.DeleteTextures(1, &mural->idColorTex);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync cr_server.head_spu->dispatch_table.DeleteRenderbuffersEXT(1, &mural->idDepthStencilRB);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync cr_server.head_spu->dispatch_table.DeleteFramebuffersEXT(1, &mural->idFBO);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync mural->idFBO = 0;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync mural->idColorTex = 0;
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync mural->idDepthStencilRB = 0;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (mural->idPBO!=0)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync CRASSERT(cr_server.bUsePBOForReadback);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync cr_server.head_spu->dispatch_table.DeleteBuffersARB(1, &mural->idPBO);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync mural->idPBO = 0;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync}
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#define MIN(a, b) ((a) < (b) ? (a) : (b))
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#define MAX(a, b) ((a) > (b) ? (a) : (b))
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsyncstatic GLboolean crServerIntersectRect(CRrecti *a, CRrecti *b, CRrecti *rect)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync{
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync CRASSERT(a && b && rect);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync rect->x1 = MAX(a->x1, b->x1);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync rect->x2 = MIN(a->x2, b->x2);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync rect->y1 = MAX(a->y1, b->y1);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync rect->y2 = MIN(a->y2, b->y2);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync return (rect->x2>rect->x1) && (rect->y2>rect->y1);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync}
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsyncstatic GLboolean crServerIntersectScreen(CRMuralInfo *mural, int sId, CRrecti *rect)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync{
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync rect->x1 = MAX(mural->gX, cr_server.screen[sId].x);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync rect->x2 = MIN(mural->gX+(int)mural->fboWidth, cr_server.screen[sId].x+(int)cr_server.screen[sId].w);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync rect->y1 = MAX(mural->gY, cr_server.screen[sId].y);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync rect->y2 = MIN(mural->gY+(int)mural->fboHeight, cr_server.screen[sId].y+(int)cr_server.screen[sId].h);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync return (rect->x2>rect->x1) && (rect->y2>rect->y1);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync}
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsyncstatic void crServerCopySubImage(char *pDst, char* pSrc, CRrecti *pRect, int srcWidth, int srcHeight)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync{
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync int i;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync int dstrowsize = 4*(pRect->x2-pRect->x1);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync int srcrowsize = 4*srcWidth;
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync int height = pRect->y2-pRect->y1;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync pSrc += 4*pRect->x1 + srcrowsize*(srcHeight-1-pRect->y1);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync for (i=0; i<height; ++i)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync crMemcpy(pDst, pSrc, dstrowsize);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync pSrc -= srcrowsize;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync pDst += dstrowsize;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync}
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsyncstatic void crServerTransformRect(CRrecti *pDst, CRrecti *pSrc, int dx, int dy)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync{
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync pDst->x1 = pSrc->x1+dx;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync pDst->x2 = pSrc->x2+dx;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync pDst->y1 = pSrc->y1+dy;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync pDst->y2 = pSrc->y2+dy;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync}
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsyncvoid crServerPresentFBO(CRMuralInfo *mural)
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync{
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync char *pixels=NULL, *tmppixels;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync GLuint uid;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync int i, j;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync CRrecti rect, rectwr, sectr;
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync GLboolean bUsePBO;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync CRContext *ctx = crStateGetCurrent();
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync CRASSERT(cr_server.pfnPresentFBO);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync if (!mural->bVisible)
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync return;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (!mural->width || !mural->height)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync return;
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync }
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (cr_server.bUsePBOForReadback && !mural->idPBO)
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync crWarning("Mural doesn't have PBO even though bUsePBOForReadback is set!");
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync bUsePBO = cr_server.bUsePBOForReadback && mural->idPBO;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync cr_server.head_spu->dispatch_table.BindTexture(GL_TEXTURE_2D, mural->idColorTex);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync if (bUsePBO)
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync {
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync CRASSERT(mural->idPBO);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, mural->idPBO);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync }
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync else
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync {
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync if (crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB))
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync {
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync }
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync pixels = crAlloc(4*mural->fboWidth*mural->fboHeight);
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync if (!pixels)
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync {
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync crWarning("Out of memory in crServerPresentFBO");
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync return;
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync }
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync }
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync /*read the texture, note pixels are NULL for PBO case as it's offset in the buffer*/
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync cr_server.head_spu->dispatch_table.GetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_BYTE, pixels);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync /*restore gl state*/
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync uid = ctx->texture.unit[ctx->texture.curTextureUnit].currentTexture2D->hwid;
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync cr_server.head_spu->dispatch_table.BindTexture(GL_TEXTURE_2D, uid);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync if (bUsePBO)
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync {
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync pixels = cr_server.head_spu->dispatch_table.MapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync if (!pixels)
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync {
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync crWarning("Failed to MapBuffer in crServerPresentFBO");
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync return;
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync for (i=0; i<cr_server.screenCount; ++i)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (crServerIntersectScreen(mural, i, &rect))
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* rect in window relative coords */
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync crServerTransformRect(&rectwr, &rect, -mural->gX, -mural->gY);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (!mural->pVisibleRects)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /*we don't get any rects info for guest compiz windows, so we treat windows as visible unless explicitly received 0 visible rects*/
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (!mural->bReceivedRects)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync tmppixels = crAlloc(4*(rect.x2-rect.x1)*(rect.y2-rect.y1));
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (!tmppixels)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
2294b1479e3fb6f4e9c9550b3e15f3d3a3f1fc24vboxsync crWarning("Out of memory in crServerPresentFBO");
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync crFree(pixels);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync return;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync crServerCopySubImage(tmppixels, pixels, &rectwr, mural->fboWidth, mural->fboHeight);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /*Note: pfnPresentFBO would free tmppixels*/
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync 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);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync else
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync for (j=0; j<mural->cVisibleRects; ++j)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (crServerIntersectRect(&rectwr, (CRrecti*) &mural->pVisibleRects[4*j], &sectr))
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync tmppixels = crAlloc(4*(sectr.x2-sectr.x1)*(sectr.y2-sectr.y1));
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (!tmppixels)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync crWarning("Out of memory in crServerPresentFBO");
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync crFree(pixels);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync return;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync crServerCopySubImage(tmppixels, pixels, &sectr, mural->fboWidth, mural->fboHeight);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /*Note: pfnPresentFBO would free tmppixels*/
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync cr_server.pfnPresentFBO(tmppixels, i,
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync sectr.x1+mural->gX-cr_server.screen[i].x,
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync sectr.y1+mural->gY-cr_server.screen[i].y,
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync sectr.x2-sectr.x1, sectr.y2-sectr.y1);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
2294b1479e3fb6f4e9c9550b3e15f3d3a3f1fc24vboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (mural->pvOutputRedirectInstance)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* @todo find out why presentfbo is not called but crorframe is called. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync cr_server.outputRedirect.CRORFrame(mural->pvOutputRedirectInstance,
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync pixels,
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync 4 * mural->fboWidth * mural->fboHeight);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (bUsePBO)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync cr_server.head_spu->dispatch_table.UnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, ctx->bufferobject.packBuffer->hwid);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync else
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync crFree(pixels);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB))
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, ctx->bufferobject.packBuffer->hwid);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync}
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsyncGLboolean crServerIsRedirectedToFBO()
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync{
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync return cr_server.curClient
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync && cr_server.curClient->currentMural
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync && cr_server.curClient->currentMural->bUseFBO;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync}
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync