dolphin/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp
XTra.KrazzY 7419475959 One step closer to fixing D3D. Now textures are set properly.
Still, memory leak exists for some unknown reason (we don't allocate more pages and we release every texture)

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2601 8ced0084-cf51-0410-be5f-012b33b47a6e
2009-03-07 18:05:29 +00:00

270 lines
7 KiB
C++

// Copyright (C) 2003-2008 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 "Common.h"
#include "D3DBase.h"
#include "Statistics.h"
#include "Profiler.h"
#include "VertexManager.h"
#include "OpcodeDecoding.h"
#include "IndexGenerator.h"
#include "VertexShaderManager.h"
#include "VertexShaderCache.h"
#include "PixelShaderManager.h"
#include "PixelShaderCache.h"
#include "Utils.h"
#include "NativeVertexFormat.h"
#include "NativeVertexWriter.h"
#include "TextureCache.h"
#include "BPStructs.h"
#include "XFStructs.h"
using namespace D3D;
// internal state for loading vertices
extern NativeVertexFormat *g_nativeVertexFmt;
namespace VertexManager
{
enum Collection
{
C_NOTHING,
C_TRIANGLES,
C_LINES,
C_POINTS,
};
static IndexGenerator indexGen;
static Collection collection;
static LPDIRECT3DVERTEXDECLARATION9 vDecl;
static u8 *fakeVBuffer; // format undefined - NativeVertexFormat takes care of the declaration.
static u16 *fakeIBuffer; // These are just straightforward 16-bit indices.
#define MAXVBUFFERSIZE 65536*3
#define MAXIBUFFERSIZE 65536*3
const Collection collectionTypeLUT[8] =
{
C_TRIANGLES,//quads
C_NOTHING, //nothing
C_TRIANGLES,//triangles
C_TRIANGLES,//strip
C_TRIANGLES,//fan
C_LINES, //lines
C_LINES, //linestrip
C_POINTS //guess :P
};
void CreateDeviceObjects();
void DestroyDeviceObjects();
bool Init()
{
collection = C_NOTHING;
fakeVBuffer = new u8[MAXVBUFFERSIZE];
fakeIBuffer = new u16[MAXIBUFFERSIZE];
CreateDeviceObjects();
VertexManager::s_pCurBufferPointer = fakeVBuffer;
return true;
}
void Shutdown()
{
DestroyDeviceObjects();
delete [] fakeVBuffer;
delete [] fakeIBuffer;
}
void CreateDeviceObjects()
{
}
void BeginFrame()
{
}
void DestroyDeviceObjects()
{
}
void AddIndices(int _primitive, int _numVertices)
{
switch (_primitive)
{
case GX_DRAW_QUADS: indexGen.AddQuads(_numVertices); return;
case GX_DRAW_TRIANGLES: indexGen.AddList(_numVertices); return;
case GX_DRAW_TRIANGLE_STRIP: indexGen.AddStrip(_numVertices); return;
case GX_DRAW_TRIANGLE_FAN: indexGen.AddFan(_numVertices); return;
case GX_DRAW_LINE_STRIP: indexGen.AddLineStrip(_numVertices); return;
case GX_DRAW_LINES: indexGen.AddLineList(_numVertices); return;
case GX_DRAW_POINTS: indexGen.AddPointList(_numVertices); return;
}
}
int GetRemainingSize()
{
return 60000;
}
void AddVertices(int _primitive, int _numVertices)
{
if (_numVertices <= 0) //This check is pretty stupid...
return;
Collection type = collectionTypeLUT[_primitive];
if (type == C_NOTHING)
return;
DVSTARTPROFILE();
_assert_msg_(type != C_NOTHING, "type == C_NOTHING!!", "WTF");
if (indexGen.GetNumVerts() > 1000) // TODO(ector): Raise?
Flush();
ADDSTAT(stats.thisFrame.numPrims, _numVertices);
if (collection != type)
{
//We are NOT collecting the right type.
Flush();
collection = type;
u16 *ptr = 0;
if (type != C_POINTS)
{
ptr = fakeIBuffer;
indexGen.Start((unsigned short*)ptr);
AddIndices(_primitive, _numVertices);
}
if (_numVertices >= MAXVBUFFERSIZE)
MessageBox(NULL, "Too many vertices for the buffer", "Dolphin DX9 Video Plugin", MB_OK);
}
else //We are collecting the right type, keep going
{
_assert_msg_(vbufferwrite != 0, "collecting: vbufferwrite == 0!","WTF");
INCSTAT(stats.thisFrame.numPrimitiveJoins);
//Success, keep adding to unlocked buffer
int last = indexGen.GetNumVerts();
AddIndices(_primitive, _numVertices);
if (_numVertices >= MAXVBUFFERSIZE)
MessageBox(NULL, "Too many vertices for the buffer", "Dolphin DX9 Video Plugin", MB_OK);
}
}
const D3DPRIMITIVETYPE pts[3] =
{
D3DPT_POINTLIST, //DUMMY
D3DPT_TRIANGLELIST,
D3DPT_LINELIST,
};
void Flush()
{
DVSTARTPROFILE();
if (collection != C_NOTHING)
{
u32 usedtextures = 0;
for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages + 1; ++i) {
if (bpmem.tevorders[i/2].getEnable(i & 1))
usedtextures |= 1 << bpmem.tevorders[i/2].getTexMap(i & 1);
}
if (bpmem.genMode.numindstages > 0) {
for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages + 1; ++i) {
if (bpmem.tevind[i].IsActive() && bpmem.tevind[i].bt < bpmem.genMode.numindstages) {
usedtextures |= 1 << bpmem.tevindref.getTexMap(bpmem.tevind[i].bt);
}
}
}
u32 nonpow2tex = 0;
for (int i = 0; i < 8; i++)
{
// if (usedtextures & (1 << i)) {
{
FourTexUnits &tex = bpmem.tex[i >> 2];
TextureCache::TCacheEntry* tentry = TextureCache::Load(i,
(tex.texImage3[i&3].image_base/* & 0x1FFFFF*/) << 5,
tex.texImage0[i&3].width+1, tex.texImage0[i&3].height+1,
tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9,
tex.texTlut[i&3].tlut_format);
if (tentry) {
// texture loaded fine, set dims for pixel shader
if (tentry->isNonPow2) {
PixelShaderManager::SetTexDims(i, tentry->w, tentry->h, tentry->mode.wrap_s, tentry->mode.wrap_t);
nonpow2tex |= 1 << i;
if (tentry->mode.wrap_s > 0) nonpow2tex |= 1 << (8 + i);
if (tentry->mode.wrap_t > 0) nonpow2tex |= 1 << (16 + i);
}
// if texture is power of two, set to ones (since don't need scaling)
// (the above seems to have changed - we set the width and height here too.
else
{
PixelShaderManager::SetTexDims(i, tentry->w, tentry->h, 0, 0);
}
}
else
ERROR_LOG(VIDEO, "error loading texture");
}
}
PixelShaderManager::SetTexturesUsed(nonpow2tex);
int numVertices = indexGen.GetNumVerts();
if (numVertices)
{
PixelShaderCache::SetShader(); // TODO(ector): only do this if shader has changed
VertexShaderCache::SetShader(g_nativeVertexFmt->m_components); // TODO(ector): only do this if shader has changed
// set global constants
VertexShaderManager::SetConstants(false);
PixelShaderManager::SetConstants();
int stride = g_nativeVertexFmt->GetVertexStride();
g_nativeVertexFmt->SetupVertexPointers();
if (collection != C_POINTS)
{
int numPrimitives = indexGen.GetNumPrims();
D3D::dev->DrawIndexedPrimitiveUP(pts[(int)collection],
0,
numVertices,
numPrimitives,
fakeIBuffer,
D3DFMT_INDEX16,
fakeVBuffer,
stride);
}
else
{
D3D::dev->SetIndices(0);
D3D::dev->DrawPrimitiveUP(D3DPT_POINTLIST, numVertices, fakeVBuffer, stride);
}
INCSTAT(stats.thisFrame.numDrawCalls);
}
collection = C_NOTHING;
VertexManager::s_pCurBufferPointer = fakeVBuffer;
}
}
} // namespace