mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-11-03 23:28:48 +00: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/video_core.h"
 | 
			
		||||
 | 
			
		||||
using SurfaceType = SurfaceParams::SurfaceType;
 | 
			
		||||
using PixelFormat = SurfaceParams::PixelFormat;
 | 
			
		||||
 | 
			
		||||
static std::array<OGLFramebuffer, 2> transfer_framebuffers;
 | 
			
		||||
 | 
			
		||||
struct FormatTuple {
 | 
			
		||||
    GLint internal_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
 | 
			
		||||
}};
 | 
			
		||||
 | 
			
		||||
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,
 | 
			
		||||
                        const MathUtil::Rectangle<u32>& fill_rect) {
 | 
			
		||||
    OpenGLState state = OpenGLState::GetCurState();
 | 
			
		||||
| 
						 | 
				
			
			@ -53,11 +79,11 @@ static bool FillSurface(const Surface& surface, const u8* fill_data,
 | 
			
		|||
    OpenGLState prev_state = state;
 | 
			
		||||
    SCOPE_EXIT({ prev_state.Apply(); });
 | 
			
		||||
 | 
			
		||||
    OpenGLState::ResetTexture(surface->texture.handle);
 | 
			
		||||
    state.ResetTexture(surface->texture.handle);
 | 
			
		||||
 | 
			
		||||
    state.scissor.enabled = true;
 | 
			
		||||
    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.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
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void RasterizerCacheOpenGL::BlitTextures(GLuint src_tex, GLuint dst_tex,
 | 
			
		||||
                                         CachedSurface::SurfaceType type,
 | 
			
		||||
                                         const MathUtil::Rectangle<int>& src_rect,
 | 
			
		||||
                                         const MathUtil::Rectangle<int>& dst_rect) {
 | 
			
		||||
    using SurfaceType = CachedSurface::SurfaceType;
 | 
			
		||||
static bool BlitTextures(GLuint src_tex, const MathUtil::Rectangle<u32>& src_rect, GLuint dst_tex,
 | 
			
		||||
                         const MathUtil::Rectangle<u32>& dst_rect, SurfaceType type) {
 | 
			
		||||
    OpenGLState state = OpenGLState::GetCurState();
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
    // components
 | 
			
		||||
    OpenGLState::ResetTexture(src_tex);
 | 
			
		||||
    OpenGLState::ResetTexture(dst_tex);
 | 
			
		||||
    state.ResetTexture(src_tex);
 | 
			
		||||
    state.ResetTexture(dst_tex);
 | 
			
		||||
 | 
			
		||||
    // Keep track of previous framebuffer bindings
 | 
			
		||||
    GLuint old_fbs[2] = {cur_state.draw.read_framebuffer, cur_state.draw.draw_framebuffer};
 | 
			
		||||
    cur_state.draw.read_framebuffer = transfer_framebuffers[0].handle;
 | 
			
		||||
    cur_state.draw.draw_framebuffer = transfer_framebuffers[1].handle;
 | 
			
		||||
    cur_state.Apply();
 | 
			
		||||
    state.draw.read_framebuffer = transfer_framebuffers[0].handle;
 | 
			
		||||
    state.draw.draw_framebuffer = transfer_framebuffers[1].handle;
 | 
			
		||||
    state.Apply();
 | 
			
		||||
 | 
			
		||||
    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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    glBlitFramebuffer(src_rect.left, src_rect.top, src_rect.right, src_rect.bottom, dst_rect.left,
 | 
			
		||||
                      dst_rect.top, dst_rect.right, dst_rect.bottom, buffers,
 | 
			
		||||
    glBlitFramebuffer(src_rect.left, src_rect.bottom, src_rect.right, src_rect.top, dst_rect.left,
 | 
			
		||||
                      dst_rect.bottom, dst_rect.right, dst_rect.top, buffers,
 | 
			
		||||
                      buffers == GL_COLOR_BUFFER_BIT ? GL_LINEAR : GL_NEAREST);
 | 
			
		||||
 | 
			
		||||
    // Restore previous framebuffer bindings
 | 
			
		||||
    cur_state.draw.read_framebuffer = old_fbs[0];
 | 
			
		||||
    cur_state.draw.draw_framebuffer = old_fbs[1];
 | 
			
		||||
    cur_state.Apply();
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RasterizerCacheOpenGL::TryBlitSurfaces(CachedSurface* src_surface,
 | 
			
		||||
| 
						 | 
				
			
			@ -336,11 +357,9 @@ bool RasterizerCacheOpenGL::TryBlitSurfaces(CachedSurface* src_surface,
 | 
			
		|||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void AllocateSurfaceTexture(GLuint texture, CachedSurface::PixelFormat pixel_format,
 | 
			
		||||
                                   u32 width, u32 height) {
 | 
			
		||||
    // Allocate an uninitialized texture of appropriate size and format for the surface
 | 
			
		||||
    using SurfaceType = CachedSurface::SurfaceType;
 | 
			
		||||
 | 
			
		||||
// Allocate an uninitialized texture of appropriate size and format for the surface
 | 
			
		||||
static void AllocateSurfaceTexture(GLuint texture, const FormatTuple& format_tuple, u32 width,
 | 
			
		||||
                                   u32 height) {
 | 
			
		||||
    OpenGLState cur_state = OpenGLState::GetCurState();
 | 
			
		||||
 | 
			
		||||
    // Keep track of previous texture bindings
 | 
			
		||||
| 
						 | 
				
			
			@ -349,22 +368,8 @@ static void AllocateSurfaceTexture(GLuint texture, CachedSurface::PixelFormat pi
 | 
			
		|||
    cur_state.Apply();
 | 
			
		||||
    glActiveTexture(GL_TEXTURE0);
 | 
			
		||||
 | 
			
		||||
    SurfaceType type = CachedSurface::GetFormatType(pixel_format);
 | 
			
		||||
 | 
			
		||||
    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);
 | 
			
		||||
    glTexImage2D(GL_TEXTURE_2D, 0, format_tuple.internal_format, width, height, 0,
 | 
			
		||||
                 format_tuple.format, format_tuple.type, nullptr);
 | 
			
		||||
 | 
			
		||||
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
 | 
			
		||||
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue