From dcbc8e78d47dabd3762d9c654df01ba57dfd8d4c Mon Sep 17 00:00:00 2001 From: hrydgard Date: Fri, 17 Oct 2008 11:30:14 +0000 Subject: Massive style & comment cleanup of (mostly) GL plugin - also split some large files. A minor speedup for BP writes - merged the two switch()-es. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@899 8ced0084-cf51-0410-be5f-012b33b47a6e --- .../Plugins/Plugin_VideoOGL/Src/VertexManager.cpp | 325 +++++++++++++++++++++ 1 file changed, 325 insertions(+) create mode 100644 Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp (limited to 'Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp') diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp new file mode 100644 index 0000000000..b28423c31e --- /dev/null +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp @@ -0,0 +1,325 @@ +#include "Globals.h" + +#include "MemoryUtil.h" +#include "Profiler.h" +#include "Render.h" +#include "ImageWrite.h" +#include "BPMemory.h" +#include "TextureMngr.h" +#include "PixelShaderManager.h" +#include "VertexShaderManager.h" +#include "VertexLoader.h" +#include "VertexManager.h" + +#define MAX_BUFFER_SIZE 0x4000 + +static GLuint s_vboBuffers[0x40] = {0}; +static int s_nCurVBOIndex = 0; // current free buffer +static GLenum s_prevprimitive = 0; // current primitive type +static u8 *s_pBaseBufferPointer = NULL; +static vector< pair > s_vStoredPrimitives; // every element, mode and count to be passed to glDrawArrays + +u8* VertexManager::s_pCurBufferPointer = NULL; +u32 VertexManager::s_prevvbstride; +u32 VertexManager::s_prevcomponents; // previous state set + + +const GLenum c_primitiveType[8] = +{ + GL_QUADS, + 0, //nothing + GL_TRIANGLES, + GL_TRIANGLE_STRIP, + GL_TRIANGLE_FAN, + GL_LINES, + GL_LINE_STRIP, + GL_POINTS +}; + +// internal state for loading vertices +void (*fnSetupVertexPointers)() = NULL; + +bool VertexManager::Init() +{ + Destroy(); + + s_GlobalVtxDesc.Hex = 0; + s_prevcomponents = 0; + s_prevvbstride = 12; // just pos + s_prevprimitive = 0; + s_pBaseBufferPointer = (u8*)AllocateMemoryPages(MAX_BUFFER_SIZE); + s_pCurBufferPointer = s_pBaseBufferPointer; + + for (u32 i = 0; i < ARRAYSIZE(shiftLookup); i++) + shiftLookup[i] = 1.0f / float(1 << i); + + s_nCurVBOIndex = 0; + glGenBuffers(ARRAYSIZE(s_vboBuffers), s_vboBuffers); + for (u32 i = 0; i < ARRAYSIZE(s_vboBuffers); ++i) { + glBindBuffer(GL_ARRAY_BUFFER, s_vboBuffers[i]); + glBufferData(GL_ARRAY_BUFFER, MAX_BUFFER_SIZE, NULL, GL_STREAM_DRAW); + } + + glEnableClientState(GL_VERTEX_ARRAY); + fnSetupVertexPointers = NULL; + GL_REPORT_ERRORD(); + + return true; +} + +void VertexManager::Destroy() +{ + FreeMemoryPages(s_pBaseBufferPointer, MAX_BUFFER_SIZE); s_pBaseBufferPointer = s_pCurBufferPointer = NULL; + glDeleteBuffers(ARRAYSIZE(s_vboBuffers), s_vboBuffers); + memset(s_vboBuffers, 0, sizeof(s_vboBuffers)); + + s_vStoredPrimitives.resize(0); + s_nCurVBOIndex = 0; + ResetBuffer(); +} + +void VertexManager::ResetBuffer() +{ + s_nCurVBOIndex = (s_nCurVBOIndex+1)%ARRAYSIZE(s_vboBuffers); + s_pCurBufferPointer = s_pBaseBufferPointer; + s_vStoredPrimitives.resize(0); +} + +void VertexManager::ResetComponents() +{ + s_prevcomponents = 0; + s_prevvbstride = 12; // just pos + s_prevprimitive = 0; + glDisableVertexAttribArray(SHADER_POSMTX_ATTRIB); + glDisableClientState(GL_NORMAL_ARRAY); + glDisableVertexAttribArray(SHADER_NORM1_ATTRIB); + glDisableVertexAttribArray(SHADER_NORM2_ATTRIB); + glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_SECONDARY_COLOR_ARRAY); + for (int i = 0; i < 8; ++i) glDisableClientState(GL_TEXTURE_COORD_ARRAY); +} + +int VertexManager::GetRemainingSize() +{ + return MAX_BUFFER_SIZE - (int)(s_pCurBufferPointer-s_pBaseBufferPointer); +} + +void VertexManager::AddVertices(int primitive, int numvertices) +{ + _assert_( numvertices > 0 ); + + ADDSTAT(stats.thisFrame.numPrims, numvertices); + s_vStoredPrimitives.push_back(pair(c_primitiveType[primitive], numvertices)); + +#ifdef _DEBUG + static const char *sprims[8] = {"quads", "nothing", "tris", "tstrip", "tfan", "lines", "lstrip", "points"}; + PRIM_LOG("prim: %s, c=%d\n", sprims[primitive], numvertices); +#endif +} + +void VertexManager::Flush() +{ + if (s_vStoredPrimitives.size() == 0) + return; + + _assert_( fnSetupVertexPointers != NULL ); + _assert_( s_pCurBufferPointer != s_pBaseBufferPointer ); + +#ifdef _DEBUG + PRIM_LOG("frame%d:\ncomps=0x%x, texgen=%d, numchan=%d, dualtex=%d, ztex=%d, proj=%d, cole=%d, alpe=%d, ze=%d\n", g_Config.iSaveTargetId, s_prevcomponents, xfregs.numTexGens, + xfregs.nNumChans, (int)xfregs.bEnableDualTexTransform, bpmem.ztex2.op, VertexShaderMngr::rawProjection[6]==0, + bpmem.blendmode.colorupdate, bpmem.blendmode.alphaupdate, bpmem.zmode.updateenable); + for (int i = 0; i < xfregs.nNumChans; ++i) { + LitChannel* ch = &xfregs.colChans[i].color; + PRIM_LOG("colchan%d: matsrc=%d, light=0x%x, ambsrc=%d, diffunc=%d, attfunc=%d\n", i, ch->matsource, ch->GetFullLightMask(), ch->ambsource, ch->diffusefunc, ch->attnfunc); + ch = &xfregs.colChans[i].alpha; + PRIM_LOG("alpchan%d: matsrc=%d, light=0x%x, ambsrc=%d, diffunc=%d, attfunc=%d\n", i, ch->matsource, ch->GetFullLightMask(), ch->ambsource, ch->diffusefunc, ch->attnfunc); + } + for (int i = 0; i < xfregs.numTexGens; ++i) { + TexMtxInfo tinfo = xfregs.texcoords[i].texmtxinfo; + if (tinfo.texgentype != XF_TEXGEN_EMBOSS_MAP ) tinfo.hex &= 0x7ff; + if (tinfo.texgentype != XF_TEXGEN_REGULAR ) tinfo.projection = 0; + + PRIM_LOG("txgen%d: proj=%d, input=%d, gentype=%d, srcrow=%d, embsrc=%d, emblght=%d, postmtx=%d, postnorm=%d\n", + i, tinfo.projection, tinfo.inputform, tinfo.texgentype, tinfo.sourcerow, tinfo.embosssourceshift, tinfo.embosslightshift, + xfregs.texcoords[i].postmtxinfo.index, xfregs.texcoords[i].postmtxinfo.normalize); + } + + PRIM_LOG("pixel: tev=%d, ind=%d, texgen=%d, dstalpha=%d, alphafunc=0x%x\n", bpmem.genMode.numtevstages+1, bpmem.genMode.numindstages, + bpmem.genMode.numtexgens, (u32)bpmem.dstalpha.enable, (bpmem.alphaFunc.hex>>16)&0xff); +#endif + + DVSTARTPROFILE(); + + GL_REPORT_ERRORD(); + + glBindBuffer(GL_ARRAY_BUFFER, s_vboBuffers[s_nCurVBOIndex]); + glBufferData(GL_ARRAY_BUFFER, s_pCurBufferPointer-s_pBaseBufferPointer, s_pBaseBufferPointer, GL_STREAM_DRAW); + GL_REPORT_ERRORD(); + + // setup the pointers + fnSetupVertexPointers(); + GL_REPORT_ERRORD(); + + // set the textures + { + DVProfileFunc _pf("VertexManager::Flush:textures"); + + u32 usedtextures = 0; + for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages + 1; ++i) { + if (bpmem.tevorders[i/2].getEnable(i & 1)) + usedtextures |= 1< 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<>2]; + TextureMngr::TCacheEntry* tentry = TextureMngr::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 != NULL) { + // texture loaded fine, set dims for pixel shader + if (tentry->isNonPow2) { + PixelShaderMngr::SetTexDims(i, tentry->w, tentry->h, tentry->mode.wrap_s, tentry->mode.wrap_t); + nonpow2tex |= 1<mode.wrap_s > 0 ) nonpow2tex |= 1<<(8+i); + if (tentry->mode.wrap_t > 0 ) nonpow2tex |= 1<<(16+i); + TextureMngr::EnableTexRECT(i); + } + // if texture is power of two, set to ones (since don't need scaling) + else + { + PixelShaderMngr::SetTexDims(i, tentry->w, tentry->h, 0, 0); + TextureMngr::EnableTex2D(i); + } + if (g_Config.iLog & CONF_PRIMLOG) { + // save the textures + char strfile[255]; + sprintf(strfile, "frames/tex%.3d_%d.tga", g_Config.iSaveTargetId, i); + SaveTexture(strfile, tentry->isNonPow2?GL_TEXTURE_RECTANGLE_ARB:GL_TEXTURE_2D, tentry->texture, tentry->w, tentry->h); + } + } + else { + ERROR_LOG("error loading tex\n"); + TextureMngr::DisableStage(i); // disable since won't be used + } + } + else { + TextureMngr::DisableStage(i); // disable since won't be used + } + } + + PixelShaderMngr::SetTexturesUsed(nonpow2tex); + } + + FRAGMENTSHADER* ps = PixelShaderMngr::GetShader(); + VERTEXSHADER* vs = VertexShaderMngr::GetShader(s_prevcomponents); + _assert_( ps != NULL && vs != NULL ); + + bool bRestoreBuffers = false; + if (Renderer::GetZBufferTarget()) { + if (bpmem.zmode.updateenable) { + if (!bpmem.blendmode.colorupdate) { + Renderer::SetRenderMode(bpmem.blendmode.alphaupdate?Renderer::RM_ZBufferAlpha:Renderer::RM_ZBufferOnly); + } + } + else { + Renderer::SetRenderMode(Renderer::RM_Normal); + // remove temporarily + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + bRestoreBuffers = true; + } + } + else + Renderer::SetRenderMode(Renderer::RM_Normal); + + // set global constants + VertexShaderMngr::SetConstants(*vs); + PixelShaderMngr::SetConstants(*ps); + + // finally bind + glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vs->glprogid); + glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, ps->glprogid); + +#ifdef _DEBUG + PRIM_LOG("\n"); +#endif + + int offset = 0; + vector< pair >::iterator it; + for (it = s_vStoredPrimitives.begin(); it != s_vStoredPrimitives.end(); ++it) { + glDrawArrays(it->first, offset, it->second); + offset += it->second; + } + +#ifdef _DEBUG + if (g_Config.iLog & CONF_PRIMLOG) { + // save the shaders + char strfile[255]; + sprintf(strfile, "frames/ps%.3d.txt", g_Config.iSaveTargetId); + std::ofstream fps(strfile); + fps << ps->strprog.c_str(); + sprintf(strfile, "frames/vs%.3d.txt", g_Config.iSaveTargetId); + ofstream fvs(strfile); + fvs << vs->strprog.c_str(); + } + + if (g_Config.iLog & CONF_SAVETARGETS) { + char str[128]; + sprintf(str, "frames/targ%.3d.tga", g_Config.iSaveTargetId); + Renderer::SaveRenderTarget(str, 0); + } +#endif + g_Config.iSaveTargetId++; + + GL_REPORT_ERRORD(); + + if (bRestoreBuffers) { + GLenum s_drawbuffers[2] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT}; + glDrawBuffers(2, s_drawbuffers); + SetColorMask(); + } + + ResetBuffer(); +} + +void VertexManager::LoadCPReg(u32 SubCmd, u32 Value) +{ + switch (SubCmd & 0xF0) + { + case 0x30: + VertexShaderMngr::SetTexMatrixChangedA(Value); + break; + case 0x40: + VertexShaderMngr::SetTexMatrixChangedB(Value); + break; + + case 0x50: + s_GlobalVtxDesc.Hex &= ~0x1FFFF; // keep the Upper bits + s_GlobalVtxDesc.Hex |= Value; + break; + case 0x60: + s_GlobalVtxDesc.Hex &= 0x1FFFF; // keep the lower 17Bits + s_GlobalVtxDesc.Hex |= (u64)Value << 17; + break; + + case 0x70: g_VertexLoaders[SubCmd & 7].SetVAT_group0(Value); _assert_((SubCmd & 0x0F) < 8); break; + case 0x80: g_VertexLoaders[SubCmd & 7].SetVAT_group1(Value); _assert_((SubCmd & 0x0F) < 8); break; + case 0x90: g_VertexLoaders[SubCmd & 7].SetVAT_group2(Value); _assert_((SubCmd & 0x0F) < 8); break; + + case 0xA0: arraybases[SubCmd & 0xF] = Value & 0xFFFFFFFF; break; + case 0xB0: arraystrides[SubCmd & 0xF] = Value & 0xFF; break; + } +} -- cgit v1.2.3