diff options
| author | skidau <skidau@gmail.com> | 2013-03-27 13:19:23 +1100 |
|---|---|---|
| committer | skidau <skidau@gmail.com> | 2013-03-27 13:19:23 +1100 |
| commit | 7784fa4c67cc8d2545f45694d83805e7e89cd583 (patch) | |
| tree | 7724133aabe971ec417d1dea0977a525bb8debfb /Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp | |
| parent | d33c19b0cd2bae982c8d35e86a9d3551f9e5c72f (diff) | |
| parent | 5cea0d9defeaa23e7af94adf7615a44fb2c9c173 (diff) | |
Merge branch 'master' into wii-network
# By Ryan Houdek (185) and others
# Via degasus (12) and others
* master: (625 commits)
Revert "Don't open/close file for every file operation." as it was crashing PokePark in Windows builds.
Array overrun fixed in VertexShaderCache for the DX11 plugin.
Fixed DSPTool build.
Windows build fix
Go back to assuming every HID device is a wiimote on Windows. Fixed issue 6117. Unfixed issue 6031.
VideoSoftware: Improve fog range adjustment by using less magic and more comments.
revert RasterFont for VideoSoftware
ogl: fix virtual xfb
Windows build fix from web interface...
Adjusted the audio loop criteria, using >= on the Wii and == on GC. This fixes the audio static that occurred in Wii games after hours of play.
Forced the exception check only for ARAM DMA transfers. Removed the Eternal Darkness boot hack and replaced it with an exception check.
VideoSoftware: Implement fog range adjustment, fixing issue 6147.
implement 4xSSAA for OGL
move ogl-only settings into backend
Fix description of disable fog, and move it to enhancements tab.
Reverted rd76ca5783743 as it was made obsolete by r1d550f4496e4.
Removed the tracking of the FIFO Writes as it was made obsolete by r1d550f4496e4.
Forced the external exception check to occur sooner by changing the downcount.
Mark the Direct3D9 backend deprecated.
Prefer D3D11 and OpenGL over D3D9 by default.
...
Conflicts:
CMakeLists.txt
Source/Core/Common/Common.vcxproj.filters
Source/Core/Common/Src/CommonPaths.h
Source/Core/Core/Core.vcxproj.filters
Source/Core/Core/Src/Core.cpp
Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp
Source/VSProps/Dolphin.Win32.props
Source/VSProps/Dolphin.x64.props
Diffstat (limited to 'Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp')
| -rw-r--r-- | Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp | 308 |
1 files changed, 212 insertions, 96 deletions
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp index ee918ee6c0..b0bc682f29 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp @@ -42,7 +42,7 @@ #include "HW/Memmap.h" #include "ImageWrite.h" #include "MemoryUtil.h" -#include "PixelShaderCache.h" +#include "ProgramShaderCache.h" #include "PixelShaderManager.h" #include "Render.h" #include "Statistics.h" @@ -56,6 +56,24 @@ namespace OGL { +static SHADER s_ColorMatrixProgram; +static SHADER s_DepthMatrixProgram; +static GLuint s_ColorMatrixUniform; +static GLuint s_DepthMatrixUniform; +static u32 s_ColorCbufid; +static u32 s_DepthCbufid; + +static u32 s_Textures[8]; +static u32 s_ActiveTexture; +static u32 s_NextStage; + +struct VBOCache { + GLuint vbo; + GLuint vao; + TargetRectangle targetSource; +}; +static std::map<u64,VBOCache> s_VBO; + static u32 s_TempFramebuffer = 0; bool SaveTexture(const char* filename, u32 textarget, u32 tex, int virtual_width, int virtual_height, unsigned int level) @@ -63,8 +81,11 @@ bool SaveTexture(const char* filename, u32 textarget, u32 tex, int virtual_width int width = std::max(virtual_width >> level, 1); int height = std::max(virtual_height >> level, 1); std::vector<u32> data(width * height); + glActiveTexture(GL_TEXTURE0+9); glBindTexture(textarget, tex); glGetTexImage(textarget, level, GL_BGRA, GL_UNSIGNED_BYTE, &data[0]); + glBindTexture(textarget, 0); + TextureCache::SetStage(); const GLenum err = GL_REPORT_ERROR(); if (GL_NO_ERROR != err) @@ -80,6 +101,9 @@ TextureCache::TCacheEntry::~TCacheEntry() { if (texture) { + for(int i=0; i<8; i++) + if(s_Textures[i] == texture) + s_Textures[i] = 0; glDeleteTextures(1, &texture); texture = 0; } @@ -93,14 +117,17 @@ TextureCache::TCacheEntry::TCacheEntry() void TextureCache::TCacheEntry::Bind(unsigned int stage) { - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, texture); - GL_REPORT_ERRORD(); - - // TODO: is this already done somewhere else? - TexMode0 &tm0 = bpmem.tex[stage >> 2].texMode0[stage & 3]; - TexMode1 &tm1 = bpmem.tex[stage >> 2].texMode1[stage & 3]; - SetTextureParameters(tm0, tm1); + if (s_Textures[stage] != texture) + { + if (s_ActiveTexture != stage) + { + glActiveTexture(GL_TEXTURE0 + stage); + s_ActiveTexture = stage; + } + + glBindTexture(GL_TEXTURE_2D, texture); + s_Textures[stage] = texture; + } } bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level) @@ -129,13 +156,13 @@ TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width, PanicAlert("Invalid PC texture format %i", pcfmt); case PC_TEX_FMT_BGRA32: gl_format = GL_BGRA; - gl_iformat = 4; + gl_iformat = GL_RGBA; gl_type = GL_UNSIGNED_BYTE; break; case PC_TEX_FMT_RGBA32: gl_format = GL_RGBA; - gl_iformat = 4; + gl_iformat = GL_RGBA; gl_type = GL_UNSIGNED_BYTE; break; @@ -177,7 +204,7 @@ TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width, entry.gl_type = gl_type; entry.pcfmt = pcfmt; - entry.bHaveMipMaps = tex_levels != 1; + entry.m_tex_levels = tex_levels; entry.Load(width, height, expanded_width, 0); @@ -187,19 +214,33 @@ TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width, void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height, unsigned int expanded_width, unsigned int level) { - //glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, texture); - //GL_REPORT_ERRORD(); + if (s_ActiveTexture != s_NextStage) + { + glActiveTexture(GL_TEXTURE0 + s_NextStage); + s_ActiveTexture = s_NextStage; + } + + if (s_Textures[s_NextStage] != texture) + { + glBindTexture(GL_TEXTURE_2D, texture); + s_Textures[s_NextStage] = texture; + } + + // TODO: sloppy, just do this on creation? + if (level == 0) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, m_tex_levels - 1); + } if (pcfmt != PC_TEX_FMT_DXT1) { if (expanded_width != width) - glPixelStorei(GL_UNPACK_ROW_LENGTH, expanded_width); + glPixelStorei(GL_UNPACK_ROW_LENGTH, expanded_width); glTexImage2D(GL_TEXTURE_2D, level, gl_iformat, width, height, 0, gl_format, gl_type, temp); if (expanded_width != width) - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); } else { @@ -214,31 +255,26 @@ TextureCache::TCacheEntryBase* TextureCache::CreateRenderTargetTexture( unsigned int scaled_tex_w, unsigned int scaled_tex_h) { TCacheEntry *const entry = new TCacheEntry; + glActiveTexture(GL_TEXTURE0+9); glBindTexture(GL_TEXTURE_2D, entry->texture); GL_REPORT_ERRORD(); const GLenum gl_format = GL_RGBA, - gl_iformat = 4, + gl_iformat = GL_RGBA, gl_type = GL_UNSIGNED_BYTE; + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); + entry->m_tex_levels = 1; glTexImage2D(GL_TEXTURE_2D, 0, gl_iformat, scaled_tex_w, scaled_tex_h, 0, gl_format, gl_type, NULL); + glBindTexture(GL_TEXTURE_2D, 0); + + SetStage(); + GL_REPORT_ERRORD(); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - if (GL_REPORT_ERROR() != GL_NO_ERROR) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - GL_REPORT_ERRORD(); - } - return entry; } @@ -247,8 +283,8 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo bool isIntensity, bool scaleByHalf, unsigned int cbufid, const float *colmat) { - glBindTexture(GL_TEXTURE_2D, texture); - + g_renderer->ResetAPIState(); // reset any game specific settings + // Make sure to resolve anything we need to read from. const GLuint read_texture = (srcFormat == PIXELFMT_Z24) ? FramebufferManager::ResolveAndGetDepthTarget(srcRect) : @@ -259,38 +295,85 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo if (type != TCET_EC_DYNAMIC || g_ActiveConfig.bCopyEFBToTexture) { if (s_TempFramebuffer == 0) - glGenFramebuffersEXT(1, (GLuint*)&s_TempFramebuffer); + glGenFramebuffers(1, (GLuint*)&s_TempFramebuffer); FramebufferManager::SetFramebuffer(s_TempFramebuffer); // Bind texture to temporary framebuffer - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texture, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); GL_REPORT_FBO_ERROR(); GL_REPORT_ERRORD(); - - glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); - glActiveTexture(GL_TEXTURE0); - glEnable(GL_TEXTURE_RECTANGLE_ARB); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, read_texture); + + glActiveTexture(GL_TEXTURE0+9); + glBindTexture(GL_TEXTURE_RECTANGLE, read_texture); glViewport(0, 0, virtual_width, virtual_height); - PixelShaderCache::SetCurrentShader((srcFormat == PIXELFMT_Z24) ? PixelShaderCache::GetDepthMatrixProgram() : PixelShaderCache::GetColorMatrixProgram()); - PixelShaderManager::SetColorMatrix(colmat); // set transformation + if(srcFormat == PIXELFMT_Z24) { + s_DepthMatrixProgram.Bind(); + if(s_DepthCbufid != cbufid) + glUniform4fv(s_DepthMatrixUniform, 5, colmat); + s_DepthCbufid = cbufid; + } else { + s_ColorMatrixProgram.Bind(); + if(s_ColorCbufid != cbufid) + glUniform4fv(s_ColorMatrixUniform, 7, colmat); + s_ColorCbufid = cbufid; + } GL_REPORT_ERRORD(); TargetRectangle targetSource = g_renderer->ConvertEFBRectangle(srcRect); - - glBegin(GL_QUADS); - glTexCoord2f((GLfloat)targetSource.left, (GLfloat)targetSource.bottom); glVertex2f(-1, 1); - glTexCoord2f((GLfloat)targetSource.left, (GLfloat)targetSource.top ); glVertex2f(-1, -1); - glTexCoord2f((GLfloat)targetSource.right, (GLfloat)targetSource.top ); glVertex2f( 1, -1); - glTexCoord2f((GLfloat)targetSource.right, (GLfloat)targetSource.bottom); glVertex2f( 1, 1); - glEnd(); + GL_REPORT_ERRORD(); + + // should be unique enough, if not, vbo will "only" be uploaded to much + u64 targetSourceHash = u64(targetSource.left)<<48 | u64(targetSource.top)<<32 | u64(targetSource.right)<<16 | u64(targetSource.bottom); + std::map<u64, VBOCache>::iterator vbo_it = s_VBO.find(targetSourceHash); + + if(vbo_it == s_VBO.end()) { + VBOCache item; + item.targetSource.bottom = -1; + item.targetSource.top = -1; + item.targetSource.left = -1; + item.targetSource.right = -1; + glGenBuffers(1, &item.vbo); + glGenVertexArrays(1, &item.vao); + + glBindBuffer(GL_ARRAY_BUFFER, item.vbo); + glBindVertexArray(item.vao); + + glEnableVertexAttribArray(SHADER_POSITION_ATTRIB); + glVertexAttribPointer(SHADER_POSITION_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL); + glEnableVertexAttribArray(SHADER_TEXTURE0_ATTRIB); + glVertexAttribPointer(SHADER_TEXTURE0_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL+2); + + vbo_it = s_VBO.insert(std::pair<u64,VBOCache>(targetSourceHash, item)).first; + } + if(!(vbo_it->second.targetSource == targetSource)) { + GLfloat vertices[] = { + -1.f, 1.f, + (GLfloat)targetSource.left, (GLfloat)targetSource.bottom, + -1.f, -1.f, + (GLfloat)targetSource.left, (GLfloat)targetSource.top, + 1.f, -1.f, + (GLfloat)targetSource.right, (GLfloat)targetSource.top, + 1.f, 1.f, + (GLfloat)targetSource.right, (GLfloat)targetSource.bottom + }; + + glBindBuffer(GL_ARRAY_BUFFER, vbo_it->second.vbo); + glBufferData(GL_ARRAY_BUFFER, 4*4*sizeof(GLfloat), vertices, GL_STREAM_DRAW); + + vbo_it->second.targetSource = targetSource; + } + + glBindVertexArray(vbo_it->second.vao); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); GL_REPORT_ERRORD(); // Unbind texture from temporary framebuffer - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, 0, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); } if (false == g_ActiveConfig.bCopyEFBToTexture) @@ -318,7 +401,6 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo FramebufferManager::SetFramebuffer(0); VertexShaderManager::SetViewportChanged(); - DisableStage(0); GL_REPORT_ERRORD(); @@ -328,63 +410,97 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo SaveTexture(StringFromFormat("%sefb_frame_%i.tga", File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(), count++).c_str(), GL_TEXTURE_2D, texture, virtual_width, virtual_height, 0); } + + g_renderer->RestoreAPIState(); } -void TextureCache::TCacheEntry::SetTextureParameters(const TexMode0 &newmode, const TexMode1 &newmode1) +TextureCache::TextureCache() { - const GLint c_MinLinearFilter[8] = - { - GL_NEAREST, - GL_NEAREST_MIPMAP_NEAREST, - GL_NEAREST_MIPMAP_LINEAR, - GL_NEAREST, - GL_LINEAR, - GL_LINEAR_MIPMAP_NEAREST, - GL_LINEAR_MIPMAP_LINEAR, - GL_LINEAR, - }; - const GLint c_WrapSettings[4] = - { - GL_CLAMP_TO_EDGE, - GL_REPEAT, - GL_MIRRORED_REPEAT, - GL_REPEAT, - }; - - int filt = newmode.min_filter; - if (g_ActiveConfig.bForceFiltering && newmode.min_filter < 4) - filt += 4; // take equivalent forced linear - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c_MinLinearFilter[filt & 7]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (newmode.mag_filter || g_Config.bForceFiltering) ? GL_LINEAR : GL_NEAREST); - - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, newmode1.min_lod / 16.f); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, newmode1.max_lod / 16.f); - glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, (s32)newmode.lod_bias / 32.0f); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, c_WrapSettings[newmode.wrap_s]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, c_WrapSettings[newmode.wrap_t]); - - // TODO: Reset anisotrop when changed to 1 - if (g_Config.iMaxAnisotropy >= 1) - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, - (float)(1 << g_ActiveConfig.iMaxAnisotropy)); + const char *pColorMatrixProg = + "uniform sampler2DRect samp9;\n" + "uniform vec4 colmat[7];\n" + "in vec2 uv0;\n" + "out vec4 ocol0;\n" + "\n" + "void main(){\n" + " vec4 texcol = texture2DRect(samp9, uv0);\n" + " texcol = round(texcol * colmat[5]) * colmat[6];\n" + " ocol0 = texcol * mat4(colmat[0], colmat[1], colmat[2], colmat[3]) + colmat[4];\n" + "}\n"; + + const char *pDepthMatrixProg = + "uniform sampler2DRect samp9;\n" + "uniform vec4 colmat[5];\n" + "in vec2 uv0;\n" + "out vec4 ocol0;\n" + "\n" + "void main(){\n" + " vec4 texcol = texture2DRect(samp9, uv0);\n" + " vec4 EncodedDepth = fract((texcol.r * (16777215.0f/16777216.0f)) * vec4(1.0f,256.0f,256.0f*256.0f,1.0f));\n" + " texcol = round(EncodedDepth * (16777216.0f/16777215.0f) * vec4(255.0f,255.0f,255.0f,15.0f)) / vec4(255.0f,255.0f,255.0f,15.0f);\n" + " ocol0 = texcol * mat4(colmat[0], colmat[1], colmat[2], colmat[3]) + colmat[4];" + "}\n"; + + + const char *VProgram = + "in vec2 rawpos;\n" + "in vec2 tex0;\n" + "out vec2 uv0;\n" + "void main()\n" + "{\n" + " uv0 = tex0;\n" + " gl_Position = vec4(rawpos,0,1);\n" + "}\n"; + + ProgramShaderCache::CompileShader(s_ColorMatrixProgram, VProgram, pColorMatrixProg); + ProgramShaderCache::CompileShader(s_DepthMatrixProgram, VProgram, pDepthMatrixProg); + + s_ColorMatrixUniform = glGetUniformLocation(s_ColorMatrixProgram.glprogid, "colmat"); + s_DepthMatrixUniform = glGetUniformLocation(s_DepthMatrixProgram.glprogid, "colmat"); + s_ColorCbufid = -1; + s_DepthCbufid = -1; + + s_ActiveTexture = -1; + s_NextStage = -1; + for(int i=0; i<8; i++) + s_Textures[i] = -1; } + TextureCache::~TextureCache() { - if (s_TempFramebuffer) + s_ColorMatrixProgram.Destroy(); + s_DepthMatrixProgram.Destroy(); + + for(std::map<u64, VBOCache>::iterator it = s_VBO.begin(); it != s_VBO.end(); it++) { + glDeleteBuffers(1, &it->second.vbo); + glDeleteVertexArrays(1, &it->second.vao); + } + s_VBO.clear(); + + if (s_TempFramebuffer) { - glDeleteFramebuffersEXT(1, (GLuint*)&s_TempFramebuffer); - s_TempFramebuffer = 0; - } + glDeleteFramebuffers(1, (GLuint*)&s_TempFramebuffer); + s_TempFramebuffer = 0; + } } void TextureCache::DisableStage(unsigned int stage) { - glActiveTexture(GL_TEXTURE0 + stage); - glDisable(GL_TEXTURE_2D); - glDisable(GL_TEXTURE_RECTANGLE_ARB); } +void TextureCache::SetStage () +{ + // -1 is the initial value as we don't know which testure should be bound + if(s_ActiveTexture != (u32)-1) + glActiveTexture(GL_TEXTURE0 + s_ActiveTexture); +} + +void TextureCache::SetNextStage ( unsigned int stage ) +{ + s_NextStage = stage; +} + + + } |
