mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-11-03 23:28:48 +00:00 
			
		
		
		
	citra_qt, video_core: Screenshot functionality
Allows capturing screenshot at the current internal resolution (native for software renderer), but a setting is available to capture it in other resolutions. The screenshot is saved to a single PNG in the current layout.
This commit is contained in:
		
							parent
							
								
									7e90abec78
								
							
						
					
					
						commit
						071b41cb61
					
				
					 14 changed files with 202 additions and 14 deletions
				
			
		| 
						 | 
				
			
			@ -24,7 +24,6 @@
 | 
			
		|||
#include "common/vector_math.h"
 | 
			
		||||
#include "core/frontend/emu_window.h"
 | 
			
		||||
#include "core/memory.h"
 | 
			
		||||
#include "core/settings.h"
 | 
			
		||||
#include "video_core/pica_state.h"
 | 
			
		||||
#include "video_core/renderer_base.h"
 | 
			
		||||
#include "video_core/renderer_opengl/gl_rasterizer_cache.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -78,12 +77,6 @@ constexpr auto RangeFromInterval(Map& map, const Interval& interval) {
 | 
			
		|||
    return boost::make_iterator_range(map.equal_range(interval));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static u16 GetResolutionScaleFactor() {
 | 
			
		||||
    return !Settings::values.resolution_factor
 | 
			
		||||
               ? VideoCore::g_renderer->GetRenderWindow().GetFramebufferLayout().GetScalingRatio()
 | 
			
		||||
               : Settings::values.resolution_factor;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <bool morton_to_gl, PixelFormat format>
 | 
			
		||||
static void MortonCopyTile(u32 stride, u8* tile_buffer, u8* gl_buffer) {
 | 
			
		||||
    constexpr u32 bytes_per_pixel = SurfaceParams::GetFormatBpp(format) / 8;
 | 
			
		||||
| 
						 | 
				
			
			@ -1360,9 +1353,9 @@ SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces(
 | 
			
		|||
    const auto& config = regs.framebuffer.framebuffer;
 | 
			
		||||
 | 
			
		||||
    // update resolution_scale_factor and reset cache if changed
 | 
			
		||||
    static u16 resolution_scale_factor = GetResolutionScaleFactor();
 | 
			
		||||
    if (resolution_scale_factor != GetResolutionScaleFactor()) {
 | 
			
		||||
        resolution_scale_factor = GetResolutionScaleFactor();
 | 
			
		||||
    static u16 resolution_scale_factor = VideoCore::GetResolutionScaleFactor();
 | 
			
		||||
    if (resolution_scale_factor != VideoCore::GetResolutionScaleFactor()) {
 | 
			
		||||
        resolution_scale_factor = VideoCore::GetResolutionScaleFactor();
 | 
			
		||||
        FlushAll();
 | 
			
		||||
        while (!surface_cache.empty())
 | 
			
		||||
            UnregisterSurface(*surface_cache.begin()->second.begin());
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -140,7 +140,39 @@ void RendererOpenGL::SwapBuffers() {
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    DrawScreens();
 | 
			
		||||
    if (VideoCore::g_renderer_screenshot_requested) {
 | 
			
		||||
        // Draw this frame to the screenshot framebuffer
 | 
			
		||||
        screenshot_framebuffer.Create();
 | 
			
		||||
        GLuint old_read_fb = state.draw.read_framebuffer;
 | 
			
		||||
        GLuint old_draw_fb = state.draw.draw_framebuffer;
 | 
			
		||||
        state.draw.read_framebuffer = state.draw.draw_framebuffer = screenshot_framebuffer.handle;
 | 
			
		||||
        state.Apply();
 | 
			
		||||
 | 
			
		||||
        Layout::FramebufferLayout layout{VideoCore::g_screenshot_framebuffer_layout};
 | 
			
		||||
 | 
			
		||||
        GLuint renderbuffer;
 | 
			
		||||
        glGenRenderbuffers(1, &renderbuffer);
 | 
			
		||||
        glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
 | 
			
		||||
        glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB8, layout.width, layout.height);
 | 
			
		||||
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
 | 
			
		||||
                                  renderbuffer);
 | 
			
		||||
 | 
			
		||||
        DrawScreens(layout);
 | 
			
		||||
 | 
			
		||||
        glReadPixels(0, 0, layout.width, layout.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
 | 
			
		||||
                     VideoCore::g_screenshot_bits);
 | 
			
		||||
 | 
			
		||||
        screenshot_framebuffer.Release();
 | 
			
		||||
        state.draw.read_framebuffer = old_read_fb;
 | 
			
		||||
        state.draw.draw_framebuffer = old_draw_fb;
 | 
			
		||||
        state.Apply();
 | 
			
		||||
        glDeleteRenderbuffers(1, &renderbuffer);
 | 
			
		||||
 | 
			
		||||
        VideoCore::g_screenshot_complete_callback();
 | 
			
		||||
        VideoCore::g_renderer_screenshot_requested = false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    DrawScreens(render_window.GetFramebufferLayout());
 | 
			
		||||
 | 
			
		||||
    Core::System::GetInstance().perf_stats.EndSystemFrame();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -386,14 +418,13 @@ void RendererOpenGL::DrawSingleScreenRotated(const ScreenInfo& screen_info, floa
 | 
			
		|||
/**
 | 
			
		||||
 * Draws the emulated screens to the emulator window.
 | 
			
		||||
 */
 | 
			
		||||
void RendererOpenGL::DrawScreens() {
 | 
			
		||||
void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout) {
 | 
			
		||||
    if (VideoCore::g_renderer_bg_color_update_requested.exchange(false)) {
 | 
			
		||||
        // Update background color before drawing
 | 
			
		||||
        glClearColor(Settings::values.bg_red, Settings::values.bg_green, Settings::values.bg_blue,
 | 
			
		||||
                     0.0f);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto layout = render_window.GetFramebufferLayout();
 | 
			
		||||
    const auto& top_screen = layout.top_screen;
 | 
			
		||||
    const auto& bottom_screen = layout.bottom_screen;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,6 +13,10 @@
 | 
			
		|||
#include "video_core/renderer_opengl/gl_resource_manager.h"
 | 
			
		||||
#include "video_core/renderer_opengl/gl_state.h"
 | 
			
		||||
 | 
			
		||||
namespace Layout {
 | 
			
		||||
class FramebufferLayout;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace OpenGL {
 | 
			
		||||
 | 
			
		||||
/// Structure used for storing information about the textures for each 3DS screen
 | 
			
		||||
| 
						 | 
				
			
			@ -50,7 +54,7 @@ private:
 | 
			
		|||
    void InitOpenGLObjects();
 | 
			
		||||
    void ConfigureFramebufferTexture(TextureInfo& texture,
 | 
			
		||||
                                     const GPU::Regs::FramebufferConfig& framebuffer);
 | 
			
		||||
    void DrawScreens();
 | 
			
		||||
    void DrawScreens(const Layout::FramebufferLayout& layout);
 | 
			
		||||
    void DrawSingleScreenRotated(const ScreenInfo& screen_info, float x, float y, float w, float h);
 | 
			
		||||
    void UpdateFramerate();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -66,6 +70,7 @@ private:
 | 
			
		|||
    OGLVertexArray vertex_array;
 | 
			
		||||
    OGLBuffer vertex_buffer;
 | 
			
		||||
    OGLProgram shader;
 | 
			
		||||
    OGLFramebuffer screenshot_framebuffer;
 | 
			
		||||
 | 
			
		||||
    /// Display information for top and bottom screens respectively
 | 
			
		||||
    std::array<ScreenInfo, 3> screen_infos;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue