diff options
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> | 2016-09-18 02:38:01 +0200 |
---|---|---|
committer | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> | 2016-09-18 02:38:01 +0200 |
commit | dc8479928c5aee4c6ad6fe4f59006fb604cee701 (patch) | |
tree | 569a7f13128450bbab973236615587ff00bced5f /src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | |
parent | Travis: Import Dolphin’s clang-format hook. (diff) | |
download | yuzu-dc8479928c5aee4c6ad6fe4f59006fb604cee701.tar yuzu-dc8479928c5aee4c6ad6fe4f59006fb604cee701.tar.gz yuzu-dc8479928c5aee4c6ad6fe4f59006fb604cee701.tar.bz2 yuzu-dc8479928c5aee4c6ad6fe4f59006fb604cee701.tar.lz yuzu-dc8479928c5aee4c6ad6fe4f59006fb604cee701.tar.xz yuzu-dc8479928c5aee4c6ad6fe4f59006fb604cee701.tar.zst yuzu-dc8479928c5aee4c6ad6fe4f59006fb604cee701.zip |
Diffstat (limited to 'src/video_core/renderer_opengl/gl_rasterizer_cache.cpp')
-rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | 285 |
1 files changed, 187 insertions, 98 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 7efd0038a..8f1477bcd 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -35,18 +35,18 @@ struct FormatTuple { }; static const std::array<FormatTuple, 5> fb_format_tuples = {{ - { GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8 }, // RGBA8 - { GL_RGB8, GL_BGR, GL_UNSIGNED_BYTE }, // RGB8 - { GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 }, // RGB5A1 - { GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 }, // RGB565 - { GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 }, // RGBA4 + {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8}, // RGBA8 + {GL_RGB8, GL_BGR, GL_UNSIGNED_BYTE}, // RGB8 + {GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1}, // RGB5A1 + {GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5}, // RGB565 + {GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4}, // RGBA4 }}; static const std::array<FormatTuple, 4> depth_format_tuples = {{ - { GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT }, // D16 + {GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}, // D16 {}, - { GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT }, // D24 - { GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 }, // D24S8 + {GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT}, // D24 + {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, // D24S8 }}; RasterizerCacheOpenGL::RasterizerCacheOpenGL() { @@ -58,7 +58,9 @@ RasterizerCacheOpenGL::~RasterizerCacheOpenGL() { FlushAll(); } -static void MortonCopyPixels(CachedSurface::PixelFormat pixel_format, u32 width, u32 height, u32 bytes_per_pixel, u32 gl_bytes_per_pixel, u8* morton_data, u8* gl_data, bool morton_to_gl) { +static void MortonCopyPixels(CachedSurface::PixelFormat pixel_format, u32 width, u32 height, + u32 bytes_per_pixel, u32 gl_bytes_per_pixel, u8* morton_data, + u8* gl_data, bool morton_to_gl) { using PixelFormat = CachedSurface::PixelFormat; u8* data_ptrs[2]; @@ -72,7 +74,8 @@ static void MortonCopyPixels(CachedSurface::PixelFormat pixel_format, u32 width, for (unsigned y = 0; y < height; ++y) { for (unsigned x = 0; x < width; ++x) { const u32 coarse_y = y & ~7; - u32 morton_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * width * bytes_per_pixel; + u32 morton_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + + coarse_y * width * bytes_per_pixel; u32 gl_pixel_index = (x + (height - 1 - y) * width) * gl_bytes_per_pixel; data_ptrs[morton_to_gl] = morton_data + morton_offset; @@ -81,7 +84,8 @@ static void MortonCopyPixels(CachedSurface::PixelFormat pixel_format, u32 width, // Swap depth and stencil value ordering since 3DS does not match OpenGL u32 depth_stencil; memcpy(&depth_stencil, data_ptrs[1], sizeof(u32)); - depth_stencil = (depth_stencil << depth_stencil_shifts[0]) | (depth_stencil >> depth_stencil_shifts[1]); + depth_stencil = (depth_stencil << depth_stencil_shifts[0]) | + (depth_stencil >> depth_stencil_shifts[1]); memcpy(data_ptrs[0], &depth_stencil, sizeof(u32)); } @@ -90,7 +94,8 @@ static void MortonCopyPixels(CachedSurface::PixelFormat pixel_format, u32 width, for (unsigned y = 0; y < height; ++y) { for (unsigned x = 0; x < width; ++x) { const u32 coarse_y = y & ~7; - u32 morton_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * width * bytes_per_pixel; + u32 morton_offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + + coarse_y * width * bytes_per_pixel; u32 gl_pixel_index = (x + (height - 1 - y) * width) * gl_bytes_per_pixel; data_ptrs[morton_to_gl] = morton_data + morton_offset; @@ -102,17 +107,21 @@ static void MortonCopyPixels(CachedSurface::PixelFormat pixel_format, u32 width, } } -bool RasterizerCacheOpenGL::BlitTextures(GLuint src_tex, GLuint dst_tex, CachedSurface::SurfaceType type, const MathUtil::Rectangle<int>& src_rect, const MathUtil::Rectangle<int>& dst_rect) { +bool 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; OpenGLState cur_state = OpenGLState::GetCurState(); - // Make sure textures aren't bound to texture units, since going to bind them to framebuffer components + // 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); // Keep track of previous framebuffer bindings - GLuint old_fbs[2] = { cur_state.draw.read_framebuffer, cur_state.draw.draw_framebuffer }; + 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(); @@ -120,11 +129,15 @@ bool RasterizerCacheOpenGL::BlitTextures(GLuint src_tex, GLuint dst_tex, CachedS u32 buffers = 0; if (type == SurfaceType::Color || type == SurfaceType::Texture) { - glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, src_tex, 0); - glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, src_tex, + 0); + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, + 0); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst_tex, 0); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst_tex, + 0); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, + 0); buffers = GL_COLOR_BUFFER_BIT; } else if (type == SurfaceType::Depth) { @@ -139,10 +152,12 @@ bool RasterizerCacheOpenGL::BlitTextures(GLuint src_tex, GLuint dst_tex, CachedS buffers = GL_DEPTH_BUFFER_BIT; } else if (type == SurfaceType::DepthStencil) { glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); - glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, src_tex, 0); + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, + src_tex, 0); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, dst_tex, 0); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, + dst_tex, 0); buffers = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; } @@ -155,9 +170,9 @@ bool RasterizerCacheOpenGL::BlitTextures(GLuint src_tex, GLuint dst_tex, CachedS return false; } - 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, buffers == GL_COLOR_BUFFER_BIT ? GL_LINEAR : GL_NEAREST); + 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, + buffers == GL_COLOR_BUFFER_BIT ? GL_LINEAR : GL_NEAREST); // Restore previous framebuffer bindings cur_state.draw.read_framebuffer = old_fbs[0]; @@ -167,17 +182,24 @@ bool RasterizerCacheOpenGL::BlitTextures(GLuint src_tex, GLuint dst_tex, CachedS return true; } -bool RasterizerCacheOpenGL::TryBlitSurfaces(CachedSurface* src_surface, const MathUtil::Rectangle<int>& src_rect, CachedSurface* dst_surface, const MathUtil::Rectangle<int>& dst_rect) { +bool RasterizerCacheOpenGL::TryBlitSurfaces(CachedSurface* src_surface, + const MathUtil::Rectangle<int>& src_rect, + CachedSurface* dst_surface, + const MathUtil::Rectangle<int>& dst_rect) { using SurfaceType = CachedSurface::SurfaceType; - if (!CachedSurface::CheckFormatsBlittable(src_surface->pixel_format, dst_surface->pixel_format)) { + if (!CachedSurface::CheckFormatsBlittable(src_surface->pixel_format, + dst_surface->pixel_format)) { return false; } - return BlitTextures(src_surface->texture.handle, dst_surface->texture.handle, CachedSurface::GetFormatType(src_surface->pixel_format), src_rect, dst_rect); + return BlitTextures(src_surface->texture.handle, dst_surface->texture.handle, + CachedSurface::GetFormatType(src_surface->pixel_format), src_rect, + dst_rect); } -static void AllocateSurfaceTexture(GLuint texture, CachedSurface::PixelFormat pixel_format, u32 width, u32 height) { +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; @@ -200,11 +222,11 @@ static void AllocateSurfaceTexture(GLuint texture, CachedSurface::PixelFormat pi ASSERT(tuple_idx < depth_format_tuples.size()); tuple = depth_format_tuples[tuple_idx]; } else { - tuple = { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE }; + 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, 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_MIN_FILTER, GL_LINEAR); @@ -217,7 +239,8 @@ static void AllocateSurfaceTexture(GLuint texture, CachedSurface::PixelFormat pi } MICROPROFILE_DEFINE(OpenGL_SurfaceUpload, "OpenGL", "Surface Upload", MP_RGB(128, 64, 192)); -CachedSurface* RasterizerCacheOpenGL::GetSurface(const CachedSurface& params, bool match_res_scale, bool load_if_create) { +CachedSurface* RasterizerCacheOpenGL::GetSurface(const CachedSurface& params, bool match_res_scale, + bool load_if_create) { using PixelFormat = CachedSurface::PixelFormat; using SurfaceType = CachedSurface::SurfaceType; @@ -225,29 +248,31 @@ CachedSurface* RasterizerCacheOpenGL::GetSurface(const CachedSurface& params, bo return nullptr; } - u32 params_size = params.width * params.height * CachedSurface::GetFormatBpp(params.pixel_format) / 8; + u32 params_size = + params.width * params.height * CachedSurface::GetFormatBpp(params.pixel_format) / 8; // Check for an exact match in existing surfaces CachedSurface* best_exact_surface = nullptr; float exact_surface_goodness = -1.f; - auto surface_interval = boost::icl::interval<PAddr>::right_open(params.addr, params.addr + params_size); + auto surface_interval = + boost::icl::interval<PAddr>::right_open(params.addr, params.addr + params_size); auto range = surface_cache.equal_range(surface_interval); for (auto it = range.first; it != range.second; ++it) { for (auto it2 = it->second.begin(); it2 != it->second.end(); ++it2) { CachedSurface* surface = it2->get(); // Check if the request matches the surface exactly - if (params.addr == surface->addr && - params.width == surface->width && params.height == surface->height && - params.pixel_format == surface->pixel_format) - { + if (params.addr == surface->addr && params.width == surface->width && + params.height == surface->height && params.pixel_format == surface->pixel_format) { // Make sure optional param-matching criteria are fulfilled bool tiling_match = (params.is_tiled == surface->is_tiled); - bool res_scale_match = (params.res_scale_width == surface->res_scale_width && params.res_scale_height == surface->res_scale_height); + bool res_scale_match = (params.res_scale_width == surface->res_scale_width && + params.res_scale_height == surface->res_scale_height); if (!match_res_scale || res_scale_match) { // Prioritize same-tiling and highest resolution surfaces - float match_goodness = (float)tiling_match + surface->res_scale_width * surface->res_scale_height; + float match_goodness = + (float)tiling_match + surface->res_scale_width * surface->res_scale_height; if (match_goodness > exact_surface_goodness || surface->dirty) { exact_surface_goodness = match_goodness; best_exact_surface = surface; @@ -288,9 +313,11 @@ CachedSurface* RasterizerCacheOpenGL::GetSurface(const CachedSurface& params, bo if (!load_if_create) { // Don't load any data; just allocate the surface's texture - AllocateSurfaceTexture(new_surface->texture.handle, new_surface->pixel_format, new_surface->GetScaledWidth(), new_surface->GetScaledHeight()); + AllocateSurfaceTexture(new_surface->texture.handle, new_surface->pixel_format, + new_surface->GetScaledWidth(), new_surface->GetScaledHeight()); } else { - // TODO: Consider attempting subrect match in existing surfaces and direct blit here instead of memory upload below if that's a common scenario in some game + // TODO: Consider attempting subrect match in existing surfaces and direct blit here instead + // of memory upload below if that's a common scenario in some game Memory::RasterizerFlushRegion(params.addr, params_size); @@ -318,7 +345,7 @@ CachedSurface* RasterizerCacheOpenGL::GetSurface(const CachedSurface& params, bo tuple = fb_format_tuples[(unsigned int)params.pixel_format]; } else { // Texture - tuple = { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE }; + tuple = {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE}; } std::vector<Math::Vec4<u8>> tex_buffer(params.width * params.height); @@ -326,19 +353,23 @@ CachedSurface* RasterizerCacheOpenGL::GetSurface(const CachedSurface& params, bo Pica::DebugUtils::TextureInfo tex_info; tex_info.width = params.width; tex_info.height = params.height; - tex_info.stride = params.width * CachedSurface::GetFormatBpp(params.pixel_format) / 8; + tex_info.stride = + params.width * CachedSurface::GetFormatBpp(params.pixel_format) / 8; tex_info.format = (Pica::Regs::TextureFormat)params.pixel_format; tex_info.physical_address = params.addr; for (unsigned y = 0; y < params.height; ++y) { for (unsigned x = 0; x < params.width; ++x) { - tex_buffer[x + params.width * y] = Pica::DebugUtils::LookupTexture(texture_src_data, x, params.height - 1 - y, tex_info); + tex_buffer[x + params.width * y] = Pica::DebugUtils::LookupTexture( + texture_src_data, x, params.height - 1 - y, tex_info); } } - glTexImage2D(GL_TEXTURE_2D, 0, tuple.internal_format, params.width, params.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex_buffer.data()); + glTexImage2D(GL_TEXTURE_2D, 0, tuple.internal_format, params.width, params.height, + 0, GL_RGBA, GL_UNSIGNED_BYTE, tex_buffer.data()); } else { - // Depth/Stencil formats need special treatment since they aren't sampleable using LookupTexture and can't use RGBA format + // Depth/Stencil formats need special treatment since they aren't sampleable using + // LookupTexture and can't use RGBA format size_t tuple_idx = (size_t)params.pixel_format - 14; ASSERT(tuple_idx < depth_format_tuples.size()); const FormatTuple& tuple = depth_format_tuples[tuple_idx]; @@ -350,14 +381,18 @@ CachedSurface* RasterizerCacheOpenGL::GetSurface(const CachedSurface& params, bo u32 gl_bytes_per_pixel = use_4bpp ? 4 : bytes_per_pixel; - std::vector<u8> temp_fb_depth_buffer(params.width * params.height * gl_bytes_per_pixel); + std::vector<u8> temp_fb_depth_buffer(params.width * params.height * + gl_bytes_per_pixel); - u8* temp_fb_depth_buffer_ptr = use_4bpp ? temp_fb_depth_buffer.data() + 1 : temp_fb_depth_buffer.data(); + u8* temp_fb_depth_buffer_ptr = + use_4bpp ? temp_fb_depth_buffer.data() + 1 : temp_fb_depth_buffer.data(); - MortonCopyPixels(params.pixel_format, params.width, params.height, bytes_per_pixel, gl_bytes_per_pixel, texture_src_data, temp_fb_depth_buffer_ptr, true); + MortonCopyPixels(params.pixel_format, params.width, params.height, bytes_per_pixel, + gl_bytes_per_pixel, texture_src_data, temp_fb_depth_buffer_ptr, + true); - glTexImage2D(GL_TEXTURE_2D, 0, tuple.internal_format, params.width, params.height, 0, - tuple.format, tuple.type, temp_fb_depth_buffer.data()); + glTexImage2D(GL_TEXTURE_2D, 0, tuple.internal_format, params.width, params.height, + 0, tuple.format, tuple.type, temp_fb_depth_buffer.data()); } } glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); @@ -367,10 +402,13 @@ CachedSurface* RasterizerCacheOpenGL::GetSurface(const CachedSurface& params, bo OGLTexture scaled_texture; scaled_texture.Create(); - AllocateSurfaceTexture(scaled_texture.handle, new_surface->pixel_format, new_surface->GetScaledWidth(), new_surface->GetScaledHeight()); - BlitTextures(new_surface->texture.handle, scaled_texture.handle, CachedSurface::GetFormatType(new_surface->pixel_format), - MathUtil::Rectangle<int>(0, 0, new_surface->width, new_surface->height), - MathUtil::Rectangle<int>(0, 0, new_surface->GetScaledWidth(), new_surface->GetScaledHeight())); + AllocateSurfaceTexture(scaled_texture.handle, new_surface->pixel_format, + new_surface->GetScaledWidth(), new_surface->GetScaledHeight()); + BlitTextures(new_surface->texture.handle, scaled_texture.handle, + CachedSurface::GetFormatType(new_surface->pixel_format), + MathUtil::Rectangle<int>(0, 0, new_surface->width, new_surface->height), + MathUtil::Rectangle<int>(0, 0, new_surface->GetScaledWidth(), + new_surface->GetScaledHeight())); new_surface->texture.Release(); new_surface->texture.handle = scaled_texture.handle; @@ -389,11 +427,15 @@ CachedSurface* RasterizerCacheOpenGL::GetSurface(const CachedSurface& params, bo } Memory::RasterizerMarkRegionCached(new_surface->addr, new_surface->size, 1); - surface_cache.add(std::make_pair(boost::icl::interval<PAddr>::right_open(new_surface->addr, new_surface->addr + new_surface->size), std::set<std::shared_ptr<CachedSurface>>({ new_surface }))); + surface_cache.add(std::make_pair(boost::icl::interval<PAddr>::right_open( + new_surface->addr, new_surface->addr + new_surface->size), + std::set<std::shared_ptr<CachedSurface>>({new_surface}))); return new_surface.get(); } -CachedSurface* RasterizerCacheOpenGL::GetSurfaceRect(const CachedSurface& params, bool match_res_scale, bool load_if_create, MathUtil::Rectangle<int>& out_rect) { +CachedSurface* RasterizerCacheOpenGL::GetSurfaceRect(const CachedSurface& params, + bool match_res_scale, bool load_if_create, + MathUtil::Rectangle<int>& out_rect) { if (params.addr == 0) { return nullptr; } @@ -405,7 +447,8 @@ CachedSurface* RasterizerCacheOpenGL::GetSurfaceRect(const CachedSurface& params CachedSurface* best_subrect_surface = nullptr; float subrect_surface_goodness = -1.f; - auto surface_interval = boost::icl::interval<PAddr>::right_open(params.addr, params.addr + params_size); + auto surface_interval = + boost::icl::interval<PAddr>::right_open(params.addr, params.addr + params_size); auto cache_upper_bound = surface_cache.upper_bound(surface_interval); for (auto it = surface_cache.lower_bound(surface_interval); it != cache_upper_bound; ++it) { for (auto it2 = it->second.begin(); it2 != it->second.end(); ++it2) { @@ -414,14 +457,15 @@ CachedSurface* RasterizerCacheOpenGL::GetSurfaceRect(const CachedSurface& params // Check if the request is contained in the surface if (params.addr >= surface->addr && params.addr + params_size - 1 <= surface->addr + surface->size - 1 && - params.pixel_format == surface->pixel_format) - { + params.pixel_format == surface->pixel_format) { // Make sure optional param-matching criteria are fulfilled bool tiling_match = (params.is_tiled == surface->is_tiled); - bool res_scale_match = (params.res_scale_width == surface->res_scale_width && params.res_scale_height == surface->res_scale_height); + bool res_scale_match = (params.res_scale_width == surface->res_scale_width && + params.res_scale_height == surface->res_scale_height); if (!match_res_scale || res_scale_match) { // Prioritize same-tiling and highest resolution surfaces - float match_goodness = (float)tiling_match + surface->res_scale_width * surface->res_scale_height; + float match_goodness = + (float)tiling_match + surface->res_scale_width * surface->res_scale_height; if (match_goodness > subrect_surface_goodness || surface->dirty) { subrect_surface_goodness = match_goodness; best_subrect_surface = surface; @@ -433,7 +477,8 @@ CachedSurface* RasterizerCacheOpenGL::GetSurfaceRect(const CachedSurface& params // Return the best subrect surface if found if (best_subrect_surface != nullptr) { - unsigned int bytes_per_pixel = (CachedSurface::GetFormatBpp(best_subrect_surface->pixel_format) / 8); + unsigned int bytes_per_pixel = + (CachedSurface::GetFormatBpp(best_subrect_surface->pixel_format) / 8); int x0, y0; @@ -452,7 +497,9 @@ CachedSurface* RasterizerCacheOpenGL::GetSurfaceRect(const CachedSurface& params y0 = begin_tile_index / tiles_per_row * 8; // Tiled surfaces are flipped vertically in the rasterizer vs. 3DS memory. - out_rect = MathUtil::Rectangle<int>(x0, best_subrect_surface->height - y0, x0 + params.width, best_subrect_surface->height - (y0 + params.height)); + out_rect = + MathUtil::Rectangle<int>(x0, best_subrect_surface->height - y0, x0 + params.width, + best_subrect_surface->height - (y0 + params.height)); } out_rect.left = (int)(out_rect.left * best_subrect_surface->res_scale_width); @@ -465,16 +512,20 @@ CachedSurface* RasterizerCacheOpenGL::GetSurfaceRect(const CachedSurface& params // No subrect found - create and return a new surface if (!params.is_tiled) { - out_rect = MathUtil::Rectangle<int>(0, 0, (int)(params.width * params.res_scale_width), (int)(params.height * params.res_scale_height)); + out_rect = MathUtil::Rectangle<int>(0, 0, (int)(params.width * params.res_scale_width), + (int)(params.height * params.res_scale_height)); } else { - out_rect = MathUtil::Rectangle<int>(0, (int)(params.height * params.res_scale_height), (int)(params.width * params.res_scale_width), 0); + out_rect = MathUtil::Rectangle<int>(0, (int)(params.height * params.res_scale_height), + (int)(params.width * params.res_scale_width), 0); } return GetSurface(params, match_res_scale, load_if_create); } -CachedSurface* RasterizerCacheOpenGL::GetTextureSurface(const Pica::Regs::FullTextureConfig& config) { - Pica::DebugUtils::TextureInfo info = Pica::DebugUtils::TextureInfo::FromPicaRegister(config.config, config.format); +CachedSurface* +RasterizerCacheOpenGL::GetTextureSurface(const Pica::Regs::FullTextureConfig& config) { + Pica::DebugUtils::TextureInfo info = + Pica::DebugUtils::TextureInfo::FromPicaRegister(config.config, config.format); CachedSurface params; params.addr = info.physical_address; @@ -485,20 +536,28 @@ CachedSurface* RasterizerCacheOpenGL::GetTextureSurface(const Pica::Regs::FullTe return GetSurface(params, false, true); } -std::tuple<CachedSurface*, CachedSurface*, MathUtil::Rectangle<int>> RasterizerCacheOpenGL::GetFramebufferSurfaces(const Pica::Regs::FramebufferConfig& config) { +std::tuple<CachedSurface*, CachedSurface*, MathUtil::Rectangle<int>> +RasterizerCacheOpenGL::GetFramebufferSurfaces(const Pica::Regs::FramebufferConfig& config) { const auto& regs = Pica::g_state.regs; // Make sur that framebuffers don't overlap if both color and depth are being used u32 fb_area = config.GetWidth() * config.GetHeight(); - bool framebuffers_overlap = config.GetColorBufferPhysicalAddress() != 0 && - config.GetDepthBufferPhysicalAddress() != 0 && - MathUtil::IntervalsIntersect(config.GetColorBufferPhysicalAddress(), fb_area * GPU::Regs::BytesPerPixel(GPU::Regs::PixelFormat(config.color_format.Value())), - config.GetDepthBufferPhysicalAddress(), fb_area * Pica::Regs::BytesPerDepthPixel(config.depth_format)); + bool framebuffers_overlap = + config.GetColorBufferPhysicalAddress() != 0 && + config.GetDepthBufferPhysicalAddress() != 0 && + MathUtil::IntervalsIntersect( + config.GetColorBufferPhysicalAddress(), + fb_area * GPU::Regs::BytesPerPixel(GPU::Regs::PixelFormat(config.color_format.Value())), + config.GetDepthBufferPhysicalAddress(), + fb_area * Pica::Regs::BytesPerDepthPixel(config.depth_format)); bool using_color_fb = config.GetColorBufferPhysicalAddress() != 0; - bool using_depth_fb = config.GetDepthBufferPhysicalAddress() != 0 && (regs.output_merger.depth_test_enable || regs.output_merger.depth_write_enable || !framebuffers_overlap); + bool using_depth_fb = config.GetDepthBufferPhysicalAddress() != 0 && + (regs.output_merger.depth_test_enable || + regs.output_merger.depth_write_enable || !framebuffers_overlap); if (framebuffers_overlap && using_color_fb && using_depth_fb) { - LOG_CRITICAL(Render_OpenGL, "Color and depth framebuffer memory regions overlap; overlapping framebuffers not supported!"); + LOG_CRITICAL(Render_OpenGL, "Color and depth framebuffer memory regions overlap; " + "overlapping framebuffers not supported!"); using_depth_fb = false; } @@ -512,8 +571,10 @@ std::tuple<CachedSurface*, CachedSurface*, MathUtil::Rectangle<int>> RasterizerC auto layout = VideoCore::g_emu_window->GetFramebufferLayout(); // Assume same scaling factor for top and bottom screens - color_params.res_scale_width = depth_params.res_scale_width = (float)layout.top_screen.GetWidth() / VideoCore::kScreenTopWidth; - color_params.res_scale_height = depth_params.res_scale_height = (float)layout.top_screen.GetHeight() / VideoCore::kScreenTopHeight; + color_params.res_scale_width = depth_params.res_scale_width = + (float)layout.top_screen.GetWidth() / VideoCore::kScreenTopWidth; + color_params.res_scale_height = depth_params.res_scale_height = + (float)layout.top_screen.GetHeight() / VideoCore::kScreenTopHeight; } color_params.addr = config.GetColorBufferPhysicalAddress(); @@ -523,22 +584,28 @@ std::tuple<CachedSurface*, CachedSurface*, MathUtil::Rectangle<int>> RasterizerC depth_params.pixel_format = CachedSurface::PixelFormatFromDepthFormat(config.depth_format); MathUtil::Rectangle<int> color_rect; - CachedSurface* color_surface = using_color_fb ? GetSurfaceRect(color_params, true, true, color_rect) : nullptr; + CachedSurface* color_surface = + using_color_fb ? GetSurfaceRect(color_params, true, true, color_rect) : nullptr; MathUtil::Rectangle<int> depth_rect; - CachedSurface* depth_surface = using_depth_fb ? GetSurfaceRect(depth_params, true, true, depth_rect) : nullptr; + CachedSurface* depth_surface = + using_depth_fb ? GetSurfaceRect(depth_params, true, true, depth_rect) : nullptr; // Sanity check to make sure found surfaces aren't the same if (using_depth_fb && using_color_fb && color_surface == depth_surface) { - LOG_CRITICAL(Render_OpenGL, "Color and depth framebuffer surfaces overlap; overlapping surfaces not supported!"); + LOG_CRITICAL( + Render_OpenGL, + "Color and depth framebuffer surfaces overlap; overlapping surfaces not supported!"); using_depth_fb = false; depth_surface = nullptr; } MathUtil::Rectangle<int> rect; - if (color_surface != nullptr && depth_surface != nullptr && (depth_rect.left != color_rect.left || depth_rect.top != color_rect.top)) { - // Can't specify separate color and depth viewport offsets in OpenGL, so re-zero both if they don't match + if (color_surface != nullptr && depth_surface != nullptr && + (depth_rect.left != color_rect.left || depth_rect.top != color_rect.top)) { + // Can't specify separate color and depth viewport offsets in OpenGL, so re-zero both if + // they don't match if (color_rect.left != 0 || color_rect.top != 0) { color_surface = GetSurface(color_params, true, true); } @@ -548,9 +615,13 @@ std::tuple<CachedSurface*, CachedSurface*, MathUtil::Rectangle<int>> RasterizerC } if (!color_surface->is_tiled) { - rect = MathUtil::Rectangle<int>(0, 0, (int)(color_params.width * color_params.res_scale_width), (int)(color_params.height * color_params.res_scale_height)); + rect = MathUtil::Rectangle<int>( + 0, 0, (int)(color_params.width * color_params.res_scale_width), + (int)(color_params.height * color_params.res_scale_height)); } else { - rect = MathUtil::Rectangle<int>(0, (int)(color_params.height * color_params.res_scale_height), (int)(color_params.width * color_params.res_scale_width), 0); + rect = MathUtil::Rectangle<int>( + 0, (int)(color_params.height * color_params.res_scale_height), + (int)(color_params.width * color_params.res_scale_width), 0); } } else if (color_surface != nullptr) { rect = color_rect; @@ -564,7 +635,8 @@ std::tuple<CachedSurface*, CachedSurface*, MathUtil::Rectangle<int>> RasterizerC } CachedSurface* RasterizerCacheOpenGL::TryGetFillSurface(const GPU::Regs::MemoryFillConfig& config) { - auto surface_interval = boost::icl::interval<PAddr>::right_open(config.GetStartAddress(), config.GetEndAddress()); + auto surface_interval = + boost::icl::interval<PAddr>::right_open(config.GetStartAddress(), config.GetEndAddress()); auto range = surface_cache.equal_range(surface_interval); for (auto it = range.first; it != range.second; ++it) { for (auto it2 = it->second.begin(); it2 != it->second.end(); ++it2) { @@ -581,8 +653,9 @@ CachedSurface* RasterizerCacheOpenGL::TryGetFillSurface(const GPU::Regs::MemoryF if (surface->addr == config.GetStartAddress() && CachedSurface::GetFormatBpp(surface->pixel_format) == bits_per_value && - (surface->width * surface->height * CachedSurface::GetFormatBpp(surface->pixel_format) / 8) == (config.GetEndAddress() - config.GetStartAddress())) - { + (surface->width * surface->height * + CachedSurface::GetFormatBpp(surface->pixel_format) / 8) == + (config.GetEndAddress() - config.GetStartAddress())) { return surface; } } @@ -617,8 +690,11 @@ void RasterizerCacheOpenGL::FlushSurface(CachedSurface* surface) { if (surface->res_scale_width != 1.f || surface->res_scale_height != 1.f) { unscaled_tex.Create(); - AllocateSurfaceTexture(unscaled_tex.handle, surface->pixel_format, surface->width, surface->height); - BlitTextures(surface->texture.handle, unscaled_tex.handle, CachedSurface::GetFormatType(surface->pixel_format), + AllocateSurfaceTexture(unscaled_tex.handle, surface->pixel_format, surface->width, + surface->height); + BlitTextures( + surface->texture.handle, unscaled_tex.handle, + CachedSurface::GetFormatType(surface->pixel_format), MathUtil::Rectangle<int>(0, 0, surface->GetScaledWidth(), surface->GetScaledHeight()), MathUtil::Rectangle<int>(0, 0, surface->width, surface->height)); @@ -648,10 +724,14 @@ void RasterizerCacheOpenGL::FlushSurface(CachedSurface* surface) { glGetTexImage(GL_TEXTURE_2D, 0, tuple.format, tuple.type, temp_gl_buffer.data()); - // Directly copy pixels. Internal OpenGL color formats are consistent so no conversion is necessary. - MortonCopyPixels(surface->pixel_format, surface->width, surface->height, bytes_per_pixel, bytes_per_pixel, dst_buffer, temp_gl_buffer.data(), false); + // Directly copy pixels. Internal OpenGL color formats are consistent so no conversion + // is necessary. + MortonCopyPixels(surface->pixel_format, surface->width, surface->height, + bytes_per_pixel, bytes_per_pixel, dst_buffer, temp_gl_buffer.data(), + false); } else { - // Depth/Stencil formats need special treatment since they aren't sampleable using LookupTexture and can't use RGBA format + // Depth/Stencil formats need special treatment since they aren't sampleable using + // LookupTexture and can't use RGBA format size_t tuple_idx = (size_t)surface->pixel_format - 14; ASSERT(tuple_idx < depth_format_tuples.size()); const FormatTuple& tuple = depth_format_tuples[tuple_idx]; @@ -669,7 +749,9 @@ void RasterizerCacheOpenGL::FlushSurface(CachedSurface* surface) { u8* temp_gl_buffer_ptr = use_4bpp ? temp_gl_buffer.data() + 1 : temp_gl_buffer.data(); - MortonCopyPixels(surface->pixel_format, surface->width, surface->height, bytes_per_pixel, gl_bytes_per_pixel, dst_buffer, temp_gl_buffer_ptr, false); + MortonCopyPixels(surface->pixel_format, surface->width, surface->height, + bytes_per_pixel, gl_bytes_per_pixel, dst_buffer, temp_gl_buffer_ptr, + false); } } glPixelStorei(GL_PACK_ROW_LENGTH, 0); @@ -680,7 +762,8 @@ void RasterizerCacheOpenGL::FlushSurface(CachedSurface* surface) { cur_state.Apply(); } -void RasterizerCacheOpenGL::FlushRegion(PAddr addr, u32 size, const CachedSurface* skip_surface, bool invalidate) { +void RasterizerCacheOpenGL::FlushRegion(PAddr addr, u32 size, const CachedSurface* skip_surface, + bool invalidate) { if (size == 0) { return; } @@ -691,8 +774,11 @@ void RasterizerCacheOpenGL::FlushRegion(PAddr addr, u32 size, const CachedSurfac auto surface_interval = boost::icl::interval<PAddr>::right_open(addr, addr + size); auto cache_upper_bound = surface_cache.upper_bound(surface_interval); for (auto it = surface_cache.lower_bound(surface_interval); it != cache_upper_bound; ++it) { - std::copy_if(it->second.begin(), it->second.end(), std::inserter(touching_surfaces, touching_surfaces.end()), - [skip_surface](std::shared_ptr<CachedSurface> surface) { return (surface.get() != skip_surface); }); + std::copy_if(it->second.begin(), it->second.end(), + std::inserter(touching_surfaces, touching_surfaces.end()), + [skip_surface](std::shared_ptr<CachedSurface> surface) { + return (surface.get() != skip_surface); + }); } // Flush and invalidate surfaces @@ -700,7 +786,10 @@ void RasterizerCacheOpenGL::FlushRegion(PAddr addr, u32 size, const CachedSurfac FlushSurface(surface.get()); if (invalidate) { Memory::RasterizerMarkRegionCached(surface->addr, surface->size, -1); - surface_cache.subtract(std::make_pair(boost::icl::interval<PAddr>::right_open(surface->addr, surface->addr + surface->size), std::set<std::shared_ptr<CachedSurface>>({ surface }))); + surface_cache.subtract( + std::make_pair(boost::icl::interval<PAddr>::right_open( + surface->addr, surface->addr + surface->size), + std::set<std::shared_ptr<CachedSurface>>({surface}))); } } } |