citra-emu
/
citra
Archived
1
0
Fork 0

OpenGL Cache: Add surface utility functions

Separates creating and filling surfaces into static functions that
can be reused from the different RasterizerCache methods.
This commit is contained in:
James Rowe 2017-11-13 22:37:49 -07:00
parent e9e2d444ef
commit 0b98b768f5
1 changed files with 46 additions and 41 deletions

View File

@ -25,6 +25,11 @@
#include "video_core/utils.h" #include "video_core/utils.h"
#include "video_core/video_core.h" #include "video_core/video_core.h"
using SurfaceType = SurfaceParams::SurfaceType;
using PixelFormat = SurfaceParams::PixelFormat;
static std::array<OGLFramebuffer, 2> transfer_framebuffers;
struct FormatTuple { struct FormatTuple {
GLint internal_format; GLint internal_format;
GLenum format; GLenum format;
@ -46,6 +51,27 @@ static const std::array<FormatTuple, 4> depth_format_tuples = {{
{GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, // D24S8 {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, // D24S8
}}; }};
static constexpr FormatTuple tex_tuple = {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE};
static const FormatTuple& GetFormatTuple(PixelFormat pixel_format) {
const SurfaceType type = SurfaceParams::GetFormatType(pixel_format);
if (type == SurfaceType::Color) {
ASSERT((size_t)pixel_format < fb_format_tuples.size());
return fb_format_tuples[(unsigned int)pixel_format];
} else if (type == SurfaceType::Depth || type == SurfaceType::DepthStencil) {
size_t tuple_idx = (size_t)pixel_format - 14;
ASSERT(tuple_idx < depth_format_tuples.size());
return depth_format_tuples[tuple_idx];
} else {
return tex_tuple;
}
}
template <typename Map, typename Interval>
constexpr auto RangeFromInterval(Map& map, const Interval& interval) {
return boost::make_iterator_range(map.equal_range(interval));
}
static bool FillSurface(const Surface& surface, const u8* fill_data, static bool FillSurface(const Surface& surface, const u8* fill_data,
const MathUtil::Rectangle<u32>& fill_rect) { const MathUtil::Rectangle<u32>& fill_rect) {
OpenGLState state = OpenGLState::GetCurState(); OpenGLState state = OpenGLState::GetCurState();
@ -53,11 +79,11 @@ static bool FillSurface(const Surface& surface, const u8* fill_data,
OpenGLState prev_state = state; OpenGLState prev_state = state;
SCOPE_EXIT({ prev_state.Apply(); }); SCOPE_EXIT({ prev_state.Apply(); });
OpenGLState::ResetTexture(surface->texture.handle); state.ResetTexture(surface->texture.handle);
state.scissor.enabled = true; state.scissor.enabled = true;
state.scissor.x = static_cast<GLint>(fill_rect.left); state.scissor.x = static_cast<GLint>(fill_rect.left);
state.scissor.y = static_cast<GLint>(std::min(fill_rect.top, fill_rect.bottom)); state.scissor.y = static_cast<GLint>(fill_rect.bottom);
state.scissor.width = static_cast<GLsizei>(fill_rect.GetWidth()); state.scissor.width = static_cast<GLsizei>(fill_rect.GetWidth());
state.scissor.height = static_cast<GLsizei>(fill_rect.GetHeight()); state.scissor.height = static_cast<GLsizei>(fill_rect.GetHeight());
@ -256,24 +282,22 @@ static constexpr std::array<void (*)(u32, u32, u8*, PAddr, PAddr, PAddr), 18> gl
MortonCopy<false, PixelFormat::D24S8> // 17 MortonCopy<false, PixelFormat::D24S8> // 17
}; };
void RasterizerCacheOpenGL::BlitTextures(GLuint src_tex, GLuint dst_tex, static bool BlitTextures(GLuint src_tex, const MathUtil::Rectangle<u32>& src_rect, GLuint dst_tex,
CachedSurface::SurfaceType type, const MathUtil::Rectangle<u32>& dst_rect, SurfaceType type) {
const MathUtil::Rectangle<int>& src_rect, OpenGLState state = OpenGLState::GetCurState();
const MathUtil::Rectangle<int>& dst_rect) {
using SurfaceType = CachedSurface::SurfaceType;
OpenGLState cur_state = OpenGLState::GetCurState(); OpenGLState prev_state = state;
SCOPE_EXIT({ prev_state.Apply(); });
// Make sure textures aren't bound to texture units, since going to bind them to framebuffer // Make sure textures aren't bound to texture units, since going to bind them to framebuffer
// components // components
OpenGLState::ResetTexture(src_tex); state.ResetTexture(src_tex);
OpenGLState::ResetTexture(dst_tex); state.ResetTexture(dst_tex);
// Keep track of previous framebuffer bindings // Keep track of previous framebuffer bindings
GLuint old_fbs[2] = {cur_state.draw.read_framebuffer, cur_state.draw.draw_framebuffer}; state.draw.read_framebuffer = transfer_framebuffers[0].handle;
cur_state.draw.read_framebuffer = transfer_framebuffers[0].handle; state.draw.draw_framebuffer = transfer_framebuffers[1].handle;
cur_state.draw.draw_framebuffer = transfer_framebuffers[1].handle; state.Apply();
cur_state.Apply();
u32 buffers = 0; u32 buffers = 0;
@ -311,14 +335,11 @@ void RasterizerCacheOpenGL::BlitTextures(GLuint src_tex, GLuint dst_tex,
buffers = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; buffers = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
} }
glBlitFramebuffer(src_rect.left, src_rect.top, src_rect.right, src_rect.bottom, dst_rect.left, glBlitFramebuffer(src_rect.left, src_rect.bottom, src_rect.right, src_rect.top, dst_rect.left,
dst_rect.top, dst_rect.right, dst_rect.bottom, buffers, dst_rect.bottom, dst_rect.right, dst_rect.top, buffers,
buffers == GL_COLOR_BUFFER_BIT ? GL_LINEAR : GL_NEAREST); buffers == GL_COLOR_BUFFER_BIT ? GL_LINEAR : GL_NEAREST);
// Restore previous framebuffer bindings return true;
cur_state.draw.read_framebuffer = old_fbs[0];
cur_state.draw.draw_framebuffer = old_fbs[1];
cur_state.Apply();
} }
bool RasterizerCacheOpenGL::TryBlitSurfaces(CachedSurface* src_surface, bool RasterizerCacheOpenGL::TryBlitSurfaces(CachedSurface* src_surface,
@ -336,11 +357,9 @@ bool RasterizerCacheOpenGL::TryBlitSurfaces(CachedSurface* src_surface,
return true; return true;
} }
static void AllocateSurfaceTexture(GLuint texture, CachedSurface::PixelFormat pixel_format, // Allocate an uninitialized texture of appropriate size and format for the surface
u32 width, u32 height) { static void AllocateSurfaceTexture(GLuint texture, const FormatTuple& format_tuple, u32 width,
// Allocate an uninitialized texture of appropriate size and format for the surface u32 height) {
using SurfaceType = CachedSurface::SurfaceType;
OpenGLState cur_state = OpenGLState::GetCurState(); OpenGLState cur_state = OpenGLState::GetCurState();
// Keep track of previous texture bindings // Keep track of previous texture bindings
@ -349,22 +368,8 @@ static void AllocateSurfaceTexture(GLuint texture, CachedSurface::PixelFormat pi
cur_state.Apply(); cur_state.Apply();
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
SurfaceType type = CachedSurface::GetFormatType(pixel_format); glTexImage2D(GL_TEXTURE_2D, 0, format_tuple.internal_format, width, height, 0,
format_tuple.format, format_tuple.type, nullptr);
FormatTuple tuple;
if (type == SurfaceType::Color) {
ASSERT((size_t)pixel_format < fb_format_tuples.size());
tuple = fb_format_tuples[(unsigned int)pixel_format];
} else if (type == SurfaceType::Depth || type == SurfaceType::DepthStencil) {
size_t tuple_idx = (size_t)pixel_format - 14;
ASSERT(tuple_idx < depth_format_tuples.size());
tuple = depth_format_tuples[tuple_idx];
} else {
tuple = {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE};
}
glTexImage2D(GL_TEXTURE_2D, 0, tuple.internal_format, width, height, 0, tuple.format,
tuple.type, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);