summaryrefslogtreecommitdiff
path: root/Source/Core/VideoBackends/OGL/OGLTexture.cpp
diff options
context:
space:
mode:
authorPierre Bourdon <delroth@gmail.com>2017-11-19 04:58:59 +0100
committerGitHub <noreply@github.com>2017-11-19 04:58:59 +0100
commit609a17a0cd41a12c0fbf9a7c47c8889232594778 (patch)
tree0a5f6f4b0a7d480accc4dfbcc3e9c1c6e3652dc0 /Source/Core/VideoBackends/OGL/OGLTexture.cpp
parentd800b0f79868a28356b4e40cb9b2e5af43977042 (diff)
parent1f1574b7ab032afa7b3a600a071699f2cbea124e (diff)
Merge pull request #5498 from iwubcode/hybrid_xfb
Hybrid xfb
Diffstat (limited to 'Source/Core/VideoBackends/OGL/OGLTexture.cpp')
-rw-r--r--Source/Core/VideoBackends/OGL/OGLTexture.cpp88
1 files changed, 65 insertions, 23 deletions
diff --git a/Source/Core/VideoBackends/OGL/OGLTexture.cpp b/Source/Core/VideoBackends/OGL/OGLTexture.cpp
index 8569e9b8b0..659cc9764b 100644
--- a/Source/Core/VideoBackends/OGL/OGLTexture.cpp
+++ b/Source/Core/VideoBackends/OGL/OGLTexture.cpp
@@ -66,22 +66,6 @@ GLenum GetGLTypeForTextureFormat(AbstractTextureFormat format)
}
} // Anonymous namespace
-bool SaveTexture(const std::string& filename, u32 textarget, u32 tex, int virtual_width,
- int virtual_height, unsigned int level)
-{
- if (GLInterface->GetMode() != GLInterfaceMode::MODE_OPENGL)
- return false;
- int width = std::max(virtual_width >> level, 1);
- int height = std::max(virtual_height >> level, 1);
- std::vector<u8> data(width * height * 4);
- glActiveTexture(GL_TEXTURE9);
- glBindTexture(textarget, tex);
- glGetTexImage(textarget, level, GL_RGBA, GL_UNSIGNED_BYTE, data.data());
- OGLTexture::SetStage();
-
- return TextureToPng(data.data(), width * 4, filename, width, height, true);
-}
-
OGLTexture::OGLTexture(const TextureConfig& tex_config) : AbstractTexture(tex_config)
{
glGenTextures(1, &m_texId);
@@ -164,15 +148,73 @@ void OGLTexture::Bind(unsigned int stage)
}
}
-bool OGLTexture::Save(const std::string& filename, unsigned int level)
+std::optional<AbstractTexture::RawTextureInfo> OGLTexture::MapFullImpl()
+{
+ if (GLInterface->GetMode() != GLInterfaceMode::MODE_OPENGL)
+ return {};
+
+ m_staging_data.reserve(m_config.width * m_config.height * 4);
+ glActiveTexture(GL_TEXTURE9);
+
+ glBindTexture(GL_TEXTURE_2D_ARRAY, m_texId);
+ glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_staging_data.data());
+ OGLTexture::SetStage();
+ return AbstractTexture::RawTextureInfo{reinterpret_cast<u8*>(m_staging_data.data()),
+ m_config.width * 4, m_config.width, m_config.height};
+}
+
+std::optional<AbstractTexture::RawTextureInfo> OGLTexture::MapRegionImpl(u32 level, u32 x, u32 y,
+ u32 width, u32 height)
{
- // We can't dump compressed textures currently (it would mean drawing them to a RGBA8
- // framebuffer, and saving that). TextureCache does not call Save for custom textures
- // anyway, so this is fine for now.
- _assert_(m_config.format == AbstractTextureFormat::RGBA8);
+ if (GLInterface->GetMode() != GLInterfaceMode::MODE_OPENGL)
+ return {};
+ m_staging_data.reserve(m_config.width * m_config.height * 4);
+ glActiveTexture(GL_TEXTURE9);
+ glBindTexture(GL_TEXTURE_2D_ARRAY, m_texId);
+ if (g_ogl_config.bSupportTextureSubImage)
+ {
+ glGetTextureSubImage(GL_TEXTURE_2D_ARRAY, level, GLint(x), GLint(y), 0, GLsizei(width),
+ GLsizei(height), 0, GL_RGBA, GL_UNSIGNED_BYTE, GLsizei(width * height * 4),
+ m_staging_data.data());
+ }
+ else
+ {
+ MapRegionSlow(level, x, y, width, height);
+ }
+ OGLTexture::SetStage();
+ return AbstractTexture::RawTextureInfo{m_staging_data.data(), width * 4, width, height};
+}
+
+void OGLTexture::MapRegionSlow(u32 level, u32 x, u32 y, u32 width, u32 height)
+{
+ glActiveTexture(GL_TEXTURE9);
+
+ glBindTexture(GL_TEXTURE_2D_ARRAY, m_texId);
+ glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_staging_data.data());
+
+ // Now copy the region out of the staging data
+
+ const u32 partial_stride = width * 4;
+
+ std::vector<u8> partial_data;
+ partial_data.resize(partial_stride * height);
+
+ const u32 staging_stride = m_config.width * 4;
+ const u32 x_offset = x * 4;
+
+ auto staging_location = m_staging_data.begin() + staging_stride * y;
+ auto partial_location = partial_data.begin();
+
+ for (size_t i = 0; i < height; ++i)
+ {
+ auto starting_location = staging_location + x_offset;
+ std::copy(starting_location, starting_location + partial_stride, partial_location);
+ staging_location += staging_stride;
+ partial_location += partial_stride;
+ }
- return SaveTexture(filename, GL_TEXTURE_2D_ARRAY, m_texId, m_config.width, m_config.height,
- level);
+ // Now swap the region back in for the staging data
+ m_staging_data.swap(partial_data);
}
void OGLTexture::CopyRectangleFromTexture(const AbstractTexture* source,