packspu_glsl.c revision ac79e3b1a02e60e199351c42f87287af950a8c7e
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync/* $Id$ */
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync/** @file
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync * VBox OpenGL GLSL related functions
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync */
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync/*
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync * Copyright (C) 2009-2012 Oracle Corporation
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync *
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync * available from http://www.virtualbox.org. This file is free software;
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync * you can redistribute it and/or modify it under the terms of the GNU
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync * General Public License (GPL) as published by the Free Software
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync */
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync#include "packspu.h"
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync#include "cr_packfunctions.h"
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync#include "cr_net.h"
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync#include "packspu_proto.h"
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync#include "cr_mem.h"
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsyncGLuint PACKSPU_APIENTRY packspu_CreateProgram(void)
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync{
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync GET_THREAD(thread);
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync int writeback = 1;
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync GLuint return_val = (GLuint) 0;
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync if (!CRPACKSPU_IS_WDDM_CRHGSMI() && !(pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn->actual_network))
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync {
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync crError("packspu_CreateProgram doesn't work when there's no actual network involved!\nTry using the simplequery SPU in your chain!");
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync }
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync if (pack_spu.swap)
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync {
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync crPackCreateProgramSWAP(&return_val, &writeback);
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync }
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync else
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync {
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync crPackCreateProgram(&return_val, &writeback);
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync }
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync packspuFlush((void *) thread);
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync CRPACKSPU_WRITEBACK_WAIT(thread, writeback);
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync if (pack_spu.swap)
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync {
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync return_val = (GLuint) SWAP32(return_val);
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync }
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync crStateCreateProgram(return_val);
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync return return_val;
cabde247f900dcf6e58d009bbdd15099c028c6fcvboxsync}
static GLint packspu_GetUniformLocationUncached(GLuint program, const char * name)
{
GET_THREAD(thread);
int writeback = 1;
GLint return_val = (GLint) 0;
if (!CRPACKSPU_IS_WDDM_CRHGSMI() && !(pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn->actual_network))
{
crError("packspu_GetUniformLocation doesn't work when there's no actual network involved!\nTry using the simplequery SPU in your chain!");
}
if (pack_spu.swap)
{
crPackGetUniformLocationSWAP(program, name, &return_val, &writeback);
}
else
{
crPackGetUniformLocation(program, name, &return_val, &writeback);
}
packspuFlush((void *) thread);
CRPACKSPU_WRITEBACK_WAIT(thread, writeback);
if (pack_spu.swap)
{
return_val = (GLint) SWAP32(return_val);
}
return return_val;
}
GLint PACKSPU_APIENTRY packspu_GetUniformLocation(GLuint program, const char * name)
{
if (!crStateIsProgramUniformsCached(program))
{
GET_THREAD(thread);
int writeback = 1;
GLsizei maxcbData;
GLsizei *pData;
GLint mu;
packspu_GetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &mu);
maxcbData = 16*mu*sizeof(char);
pData = (GLsizei *) crAlloc(maxcbData+sizeof(GLsizei));
if (!pData)
{
crWarning("packspu_GetUniformLocation: not enough memory, fallback to single query");
return packspu_GetUniformLocationUncached(program, name);
}
crPackGetUniformsLocations(program, maxcbData, pData, NULL, &writeback);
packspuFlush((void *) thread);
CRPACKSPU_WRITEBACK_WAIT(thread, writeback);
crStateGLSLProgramCacheUniforms(program, pData[0], &pData[1]);
CRASSERT(crStateIsProgramUniformsCached(program));
crFree(pData);
}
/*crDebug("packspu_GetUniformLocation(%d, %s)=%i", program, name, crStateGetUniformLocation(program, name));*/
return crStateGetUniformLocation(program, name);
}
void PACKSPU_APIENTRY packspu_GetUniformsLocations(GLuint program, GLsizei maxcbData, GLsizei * cbData, GLvoid * pData)
{
(void) program;
(void) maxcbData;
(void) cbData;
(void) pData;
crWarning("packspu_GetUniformsLocations shouldn't be called directly");
}
void PACKSPU_APIENTRY packspu_DeleteProgram(GLuint program)
{
crStateDeleteProgram(program);
crPackDeleteProgram(program);
}
void PACK_APIENTRY packspu_DeleteObjectARB(GLhandleARB obj)
{
GLuint hwid = crStateGetProgramHWID(obj);
CRASSERT(obj);
/* we do not track shader creation inside guest since it is not needed currently.
* this is why we only care about programs here */
if (hwid)
{
crStateDeleteProgram(obj);
}
crPackDeleteObjectARB(obj);
}
#ifdef VBOX_WITH_CRPACKSPU_DUMPER
static void packspu_RecCheckInitRec()
{
if (pack_spu.Recorder.pDumper)
return;
crDmpDbgPrintInit(&pack_spu.Dumper);
crRecInit(&pack_spu.Recorder, NULL /*pBlitter: we do not support blitter operations here*/, &pack_spu.self, &pack_spu.Dumper.Base);
}
#endif
void PACKSPU_APIENTRY packspu_LinkProgram(GLuint program)
{
#ifdef VBOX_WITH_CRPACKSPU_DUMPER
GLint linkStatus = 0;
#endif
crStateLinkProgram(program);
crPackLinkProgram(program);
#ifdef VBOX_WITH_CRPACKSPU_DUMPER
pack_spu.self.GetObjectParameterivARB(program, GL_OBJECT_LINK_STATUS_ARB, &linkStatus);
Assert(linkStatus);
if (!linkStatus)
{
CRContext *ctx = crStateGetCurrent();
packspu_RecCheckInitRec();
crRecDumpProgram(&pack_spu.Recorder, ctx, program, program);
}
#endif
}
void PACKSPU_APIENTRY packspu_CompileShader(GLuint shader)
{
#ifdef VBOX_WITH_CRPACKSPU_DUMPER
GLint compileStatus = 0;
#endif
// crStateCompileShader(shader);
crPackCompileShader(shader);
#ifdef VBOX_WITH_CRPACKSPU_DUMPER
pack_spu.self.GetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &compileStatus);
Assert(compileStatus);
if (!compileStatus)
{
CRContext *ctx = crStateGetCurrent();
packspu_RecCheckInitRec();
crRecDumpShader(&pack_spu.Recorder, ctx, shader, shader);
}
#endif
}