mirror of
https://github.com/Lime3DS/Lime3DS
synced 2024-12-25 00:23:04 -06:00
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:
parent
e9e2d444ef
commit
0b98b768f5
1 changed files with 46 additions and 41 deletions
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue