dolphin/Source/Plugins/Plugin_VideoOGL/Src/NativeVertexFormat.cpp
Ryan Houdek b20176b74f Add in GLSL setting again.
PS and VS making. Untested and won't work for now.

Add in program shader cache files.

Readd NativeVertexFormat stuffs.

Add in PS and VS cache things.

SetShaders in places.

Fixed EFB cache index computations in OpenGL renderer.

The previous computation was very likely to go out of array bounds,
which could result in crashes on EFB access.

Also, the cache size was rounded down instead of up. This is a problem
since EFB_HEIGHT (528) is not a multiple of EFB_CACHE_RECT_SIZE (64).
2011-11-30 22:02:25 -06:00

306 lines
9.2 KiB
C++

// Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "GLUtil.h"
#include "x64Emitter.h"
#include "ABI.h"
#include "MemoryUtil.h"
#include "ProgramShaderCache.h"
#include "VertexShaderGen.h"
#include "CPMemory.h"
#include "NativeVertexFormat.h"
#include "VertexManager.h"
#define COMPILED_CODE_SIZE 4096
// TODO: this guy is never initialized
u32 s_prevcomponents; // previous state set
/*
#ifdef _WIN32
#ifdef _M_IX86
#define USE_JIT
#endif
#endif
*/
// Note the use of CallCdeclFunction3I etc.
// This is a horrible hack that is necessary because in 64-bit mode, Opengl32.dll is based way, way above the 32-bit
// address space that is within reach of a CALL, and just doing &fn gives us these high uncallable addresses. So we
// want to grab the function pointers from the import table instead.
// This problem does not apply to glew functions, only core opengl32 functions.
// Here's some global state. We only use this to keep track of what we've sent to the OpenGL state
// machine.
#ifdef USE_JIT
DECLARE_IMPORT(glNormalPointer);
DECLARE_IMPORT(glVertexPointer);
DECLARE_IMPORT(glColorPointer);
DECLARE_IMPORT(glTexCoordPointer);
#endif
class GLVertexFormat : public NativeVertexFormat
{
u8 *m_compiledCode;
PortableVertexDeclaration vtx_decl;
public:
GLVertexFormat();
~GLVertexFormat();
virtual void Initialize(const PortableVertexDeclaration &_vtx_decl);
virtual void SetupVertexPointers();
virtual void EnableComponents(u32 components);
};
namespace OGL
{
NativeVertexFormat* VertexManager::CreateNativeVertexFormat()
{
return new GLVertexFormat();
}
}
GLVertexFormat::GLVertexFormat()
{
#ifdef USE_JIT
m_compiledCode = (u8 *)AllocateExecutableMemory(COMPILED_CODE_SIZE, false);
if (m_compiledCode)
memset(m_compiledCode, 0, COMPILED_CODE_SIZE);
#endif
}
GLVertexFormat::~GLVertexFormat()
{
#ifdef USE_JIT
FreeMemoryPages(m_compiledCode, COMPILED_CODE_SIZE);
m_compiledCode = 0;
#endif
}
inline GLuint VarToGL(VarType t)
{
static const GLuint lookup[5] = {
GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_FLOAT
};
return lookup[t];
}
void GLVertexFormat::Initialize(const PortableVertexDeclaration &_vtx_decl)
{
s_prevcomponents = 0;
vertex_stride = _vtx_decl.stride;
using namespace Gen;
// We will not allow vertex components causing uneven strides.
if (_vtx_decl.stride & 3)
PanicAlert("Uneven vertex stride: %i", _vtx_decl.stride);
#ifdef USE_JIT
Gen::XEmitter emit(m_compiledCode);
// Alright, we have our vertex declaration. Compile some crazy code to set it quickly using GL.
emit.ABI_EmitPrologue(6);
emit.CallCdeclFunction4_I(glVertexPointer, 3, GL_FLOAT, _vtx_decl.stride, 0);
if (_vtx_decl.num_normals >= 1)
{
emit.CallCdeclFunction3_I(glNormalPointer, VarToGL(_vtx_decl.normal_gl_type), _vtx_decl.stride, _vtx_decl.normal_offset[0]);
if (_vtx_decl.num_normals == 3) {
emit.CallCdeclFunction6((void *)glVertexAttribPointer, SHADER_NORM1_ATTRIB, _vtx_decl.normal_gl_size, VarToGL(_vtx_decl.normal_gl_type), GL_TRUE, _vtx_decl.stride, _vtx_decl.normal_offset[1]);
emit.CallCdeclFunction6((void *)glVertexAttribPointer, SHADER_NORM2_ATTRIB, _vtx_decl.normal_gl_size, VarToGL(_vtx_decl.normal_gl_type), GL_TRUE, _vtx_decl.stride, _vtx_decl.normal_offset[2]);
}
}
for (int i = 0; i < 2; i++)
{
if (_vtx_decl.color_offset[i] != -1)
{
if (i == 0)
emit.CallCdeclFunction4_I(glColorPointer, 4, GL_UNSIGNED_BYTE, _vtx_decl.stride, _vtx_decl.color_offset[i]);
else
emit.CallCdeclFunction4((void *)glSecondaryColorPointer, 4, GL_UNSIGNED_BYTE, _vtx_decl.stride, _vtx_decl.color_offset[i]);
}
}
for (int i = 0; i < 8; i++)
{
if (_vtx_decl.texcoord_offset[i] != -1)
{
int id = GL_TEXTURE0 + i;
#ifdef _M_X64
#ifdef _MSC_VER
emit.MOV(32, R(RCX), Imm32(id));
#else
emit.MOV(32, R(RDI), Imm32(id));
#endif
#else
emit.ABI_AlignStack(1 * 4);
emit.PUSH(32, Imm32(id));
#endif
emit.CALL((void *)glClientActiveTexture);
#ifndef _M_X64
#ifdef _WIN32
// don't inc stack on windows, stdcall
#else
emit.ABI_RestoreStack(1 * 4);
#endif
#endif
emit.CallCdeclFunction4_I(
glTexCoordPointer, _vtx_decl.texcoord_size[i], VarToGL(_vtx_decl.texcoord_gl_type[i]),
_vtx_decl.stride, _vtx_decl.texcoord_offset[i]);
}
}
if (_vtx_decl.posmtx_offset != -1)
emit.CallCdeclFunction6((void *)glVertexAttribPointer, SHADER_POSMTX_ATTRIB, 4, GL_UNSIGNED_BYTE, GL_FALSE, _vtx_decl.stride, _vtx_decl.posmtx_offset);
emit.ABI_EmitEpilogue(6);
if (emit.GetCodePtr() - (u8*)m_compiledCode > COMPILED_CODE_SIZE)
Crash();
#endif
this->vtx_decl = _vtx_decl;
}
void GLVertexFormat::SetupVertexPointers() {
// Cast a pointer to compiled code to a pointer to a function taking no parameters, through a (void *) cast first to
// get around type checking errors, and call it.
#ifdef USE_JIT
((void (*)())(void*)m_compiledCode)();
#else
glVertexPointer(3, GL_FLOAT, vtx_decl.stride, VertexManager::s_pBaseBufferPointer);
if (vtx_decl.num_normals >= 1) {
glNormalPointer(VarToGL(vtx_decl.normal_gl_type), vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.normal_offset[0]));
if (vtx_decl.num_normals == 3) {
GLint varLocation1 = SHADER_NORM1_ATTRIB, varLocation2 = SHADER_NORM2_ATTRIB;
if(g_ActiveConfig.bUseGLSL){
varLocation1 = OGL::ProgramShaderCache::GetAttr(0);
varLocation2 = OGL::ProgramShaderCache::GetAttr(1);
}
if(varLocation1 > 0)
glVertexAttribPointer(varLocation1, vtx_decl.normal_gl_size, VarToGL(vtx_decl.normal_gl_type), GL_TRUE, vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.normal_offset[1]));
if(varLocation2 > 0)
glVertexAttribPointer(varLocation2, vtx_decl.normal_gl_size, VarToGL(vtx_decl.normal_gl_type), GL_TRUE, vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.normal_offset[2]));
}
}
for (int i = 0; i < 2; i++) {
if (vtx_decl.color_offset[i] != -1) {
if (i == 0)
glColorPointer(4, GL_UNSIGNED_BYTE, vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.color_offset[i]));
else {
glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.color_offset[i]));
}
}
}
for (int i = 0; i < 8; i++) {
if (vtx_decl.texcoord_offset[i] != -1) {
int id = GL_TEXTURE0 + i;
glClientActiveTexture(id);
glTexCoordPointer(vtx_decl.texcoord_size[i], VarToGL(vtx_decl.texcoord_gl_type[i]),
vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.texcoord_offset[i]));
}
}
if (vtx_decl.posmtx_offset != -1) {
GLint varLocation = SHADER_POSMTX_ATTRIB;
if(g_ActiveConfig.bUseGLSL)
varLocation = OGL::ProgramShaderCache::GetAttr(2);
if(varLocation > 0)
glVertexAttribPointer(varLocation, 4, GL_UNSIGNED_BYTE, GL_FALSE, vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.posmtx_offset));
}
#endif
}
void GLVertexFormat::EnableComponents(u32 components)
{
if (s_prevcomponents != components)
{
VertexManager::Flush();
// matrices
if ((components & VB_HAS_POSMTXIDX) != (s_prevcomponents & VB_HAS_POSMTXIDX))
{
if (components & VB_HAS_POSMTXIDX)
glEnableVertexAttribArray(SHADER_POSMTX_ATTRIB);
else
glDisableVertexAttribArray(SHADER_POSMTX_ATTRIB);
}
// normals
if ((components & VB_HAS_NRM0) != (s_prevcomponents & VB_HAS_NRM0))
{
if (components & VB_HAS_NRM0)
glEnableClientState(GL_NORMAL_ARRAY);
else
glDisableClientState(GL_NORMAL_ARRAY);
}
if ((components & VB_HAS_NRM1) != (s_prevcomponents & VB_HAS_NRM1))
{
if (components & VB_HAS_NRM1) {
glEnableVertexAttribArray(SHADER_NORM1_ATTRIB);
glEnableVertexAttribArray(SHADER_NORM2_ATTRIB);
}
else {
glDisableVertexAttribArray(SHADER_NORM1_ATTRIB);
glDisableVertexAttribArray(SHADER_NORM2_ATTRIB);
}
}
// color
for (int i = 0; i < 2; ++i)
{
if ((components & (VB_HAS_COL0 << i)) != (s_prevcomponents & (VB_HAS_COL0 << i)))
{
if (components & (VB_HAS_COL0 << i))
glEnableClientState(i ? GL_SECONDARY_COLOR_ARRAY : GL_COLOR_ARRAY);
else
glDisableClientState(i ? GL_SECONDARY_COLOR_ARRAY : GL_COLOR_ARRAY);
}
}
// tex
for (int i = 0; i < 8; ++i)
{
if (!g_ActiveConfig.bDisableTexturing)
{
if ((components & (VB_HAS_UV0 << i)) != (s_prevcomponents & (VB_HAS_UV0 << i)))
{
glClientActiveTexture(GL_TEXTURE0 + i);
if (components & (VB_HAS_UV0 << i))
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
else
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
}
else
{
glClientActiveTexture(GL_TEXTURE0 + i);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
}
s_prevcomponents = components;
}
}