summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp6
-rw-r--r--src/video_core/gpu.h29
-rw-r--r--src/video_core/rasterizer_interface.h4
-rw-r--r--src/video_core/renderer_base.h33
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp5
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h4
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp56
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.h9
8 files changed, 77 insertions, 69 deletions
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
index 94530724e..7cd1d9306 100644
--- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
@@ -26,14 +26,14 @@ void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u3
26 "Drawing from address %lx offset %08X Width %u Height %u Stride %u Format %u", addr, 26 "Drawing from address %lx offset %08X Width %u Height %u Stride %u Format %u", addr,
27 offset, width, height, stride, format); 27 offset, width, height, stride, format);
28 28
29 using PixelFormat = RendererBase::FramebufferInfo::PixelFormat; 29 using PixelFormat = Tegra::FramebufferConfig::PixelFormat;
30 using Flags = NVFlinger::BufferQueue::BufferTransformFlags; 30 using Flags = NVFlinger::BufferQueue::BufferTransformFlags;
31 const bool flip_vertical = static_cast<u32>(transform) & static_cast<u32>(Flags::FlipV); 31 const bool flip_vertical = static_cast<u32>(transform) & static_cast<u32>(Flags::FlipV);
32 const RendererBase::FramebufferInfo framebuffer_info{ 32 const Tegra::FramebufferConfig framebuffer{
33 addr, offset, width, height, stride, static_cast<PixelFormat>(format), flip_vertical}; 33 addr, offset, width, height, stride, static_cast<PixelFormat>(format), flip_vertical};
34 34
35 Core::System::GetInstance().perf_stats.EndGameFrame(); 35 Core::System::GetInstance().perf_stats.EndGameFrame();
36 VideoCore::g_renderer->SwapBuffers(framebuffer_info); 36 VideoCore::g_renderer->SwapBuffers(framebuffer);
37} 37}
38 38
39} // namespace Devices 39} // namespace Devices
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h
index f9a725dee..f3c5e366a 100644
--- a/src/video_core/gpu.h
+++ b/src/video_core/gpu.h
@@ -12,6 +12,35 @@
12 12
13namespace Tegra { 13namespace Tegra {
14 14
15/**
16 * Struct describing framebuffer configuration
17 */
18struct FramebufferConfig {
19 enum class PixelFormat : u32 {
20 ABGR8 = 1,
21 };
22
23 /**
24 * Returns the number of bytes per pixel.
25 */
26 static u32 BytesPerPixel(PixelFormat format) {
27 switch (format) {
28 case PixelFormat::ABGR8:
29 return 4;
30 }
31
32 UNREACHABLE();
33 }
34
35 VAddr address;
36 u32 offset;
37 u32 width;
38 u32 height;
39 u32 stride;
40 PixelFormat pixel_format;
41 bool flip_vertical;
42};
43
15namespace Engines { 44namespace Engines {
16class Fermi2D; 45class Fermi2D;
17class Maxwell3D; 46class Maxwell3D;
diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h
index 6c7bd0826..966e25f34 100644
--- a/src/video_core/rasterizer_interface.h
+++ b/src/video_core/rasterizer_interface.h
@@ -5,6 +5,7 @@
5#pragma once 5#pragma once
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8#include "video_core/gpu.h"
8 9
9struct ScreenInfo; 10struct ScreenInfo;
10 11
@@ -49,7 +50,8 @@ public:
49 } 50 }
50 51
51 /// Attempt to use a faster method to display the framebuffer to screen 52 /// Attempt to use a faster method to display the framebuffer to screen
52 virtual bool AccelerateDisplay(const void* config, PAddr framebuffer_addr, u32 pixel_stride, 53 virtual bool AccelerateDisplay(const Tegra::FramebufferConfig& framebuffer,
54 PAddr framebuffer_addr, u32 pixel_stride,
53 ScreenInfo& screen_info) { 55 ScreenInfo& screen_info) {
54 return false; 56 return false;
55 } 57 }
diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h
index 532e5b37c..89a960eaf 100644
--- a/src/video_core/renderer_base.h
+++ b/src/video_core/renderer_base.h
@@ -8,6 +8,7 @@
8#include <boost/optional.hpp> 8#include <boost/optional.hpp>
9#include "common/assert.h" 9#include "common/assert.h"
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "video_core/gpu.h"
11#include "video_core/rasterizer_interface.h" 12#include "video_core/rasterizer_interface.h"
12 13
13class EmuWindow; 14class EmuWindow;
@@ -17,40 +18,10 @@ public:
17 /// Used to reference a framebuffer 18 /// Used to reference a framebuffer
18 enum kFramebuffer { kFramebuffer_VirtualXFB = 0, kFramebuffer_EFB, kFramebuffer_Texture }; 19 enum kFramebuffer { kFramebuffer_VirtualXFB = 0, kFramebuffer_EFB, kFramebuffer_Texture };
19 20
20 /**
21 * Struct describing framebuffer metadata
22 * TODO(bunnei): This struct belongs in the GPU code, but we don't have a good place for it yet.
23 */
24 struct FramebufferInfo {
25 enum class PixelFormat : u32 {
26 ABGR8 = 1,
27 };
28
29 /**
30 * Returns the number of bytes per pixel.
31 */
32 static u32 BytesPerPixel(PixelFormat format) {
33 switch (format) {
34 case PixelFormat::ABGR8:
35 return 4;
36 }
37
38 UNREACHABLE();
39 }
40
41 VAddr address;
42 u32 offset;
43 u32 width;
44 u32 height;
45 u32 stride;
46 PixelFormat pixel_format;
47 bool flip_vertical;
48 };
49
50 virtual ~RendererBase() {} 21 virtual ~RendererBase() {}
51 22
52 /// Swap buffers (render frame) 23 /// Swap buffers (render frame)
53 virtual void SwapBuffers(boost::optional<const FramebufferInfo&> framebuffer_info) = 0; 24 virtual void SwapBuffers(boost::optional<const Tegra::FramebufferConfig&> framebuffer) = 0;
54 25
55 /** 26 /**
56 * Set the emulator window to use for renderer 27 * Set the emulator window to use for renderer
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 0aed4b048..abc6607b0 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -226,8 +226,9 @@ bool RasterizerOpenGL::AccelerateFill(const void* config) {
226 return true; 226 return true;
227} 227}
228 228
229bool RasterizerOpenGL::AccelerateDisplay(const void* config, PAddr framebuffer_addr, 229bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& framebuffer,
230 u32 pixel_stride, ScreenInfo& screen_info) { 230 PAddr framebuffer_addr, u32 pixel_stride,
231 ScreenInfo& screen_info) {
231 ASSERT_MSG(false, "Unimplemented"); 232 ASSERT_MSG(false, "Unimplemented");
232 return true; 233 return true;
233} 234}
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 7a68480d9..8f213404d 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -38,8 +38,8 @@ public:
38 bool AccelerateDisplayTransfer(const void* config) override; 38 bool AccelerateDisplayTransfer(const void* config) override;
39 bool AccelerateTextureCopy(const void* config) override; 39 bool AccelerateTextureCopy(const void* config) override;
40 bool AccelerateFill(const void* config) override; 40 bool AccelerateFill(const void* config) override;
41 bool AccelerateDisplay(const void* config, PAddr framebuffer_addr, u32 pixel_stride, 41 bool AccelerateDisplay(const Tegra::FramebufferConfig& framebuffer, PAddr framebuffer_addr,
42 ScreenInfo& screen_info) override; 42 u32 pixel_stride, ScreenInfo& screen_info) override;
43 bool AccelerateDrawBatch(bool is_indexed) override; 43 bool AccelerateDrawBatch(bool is_indexed) override;
44 44
45 /// OpenGL shader generated for a given Maxwell register state 45 /// OpenGL shader generated for a given Maxwell register state
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 65d38ade5..2ea5e91e3 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -98,22 +98,22 @@ RendererOpenGL::RendererOpenGL() = default;
98RendererOpenGL::~RendererOpenGL() = default; 98RendererOpenGL::~RendererOpenGL() = default;
99 99
100/// Swap buffers (render frame) 100/// Swap buffers (render frame)
101void RendererOpenGL::SwapBuffers(boost::optional<const FramebufferInfo&> framebuffer_info) { 101void RendererOpenGL::SwapBuffers(boost::optional<const Tegra::FramebufferConfig&> framebuffer) {
102 // Maintain the rasterizer's state as a priority 102 // Maintain the rasterizer's state as a priority
103 OpenGLState prev_state = OpenGLState::GetCurState(); 103 OpenGLState prev_state = OpenGLState::GetCurState();
104 state.Apply(); 104 state.Apply();
105 105
106 if (framebuffer_info != boost::none) { 106 if (framebuffer != boost::none) {
107 // If framebuffer_info is provided, reload it from memory to a texture 107 // If framebuffer is provided, reload it from memory to a texture
108 if (screen_info.texture.width != (GLsizei)framebuffer_info->width || 108 if (screen_info.texture.width != (GLsizei)framebuffer->width ||
109 screen_info.texture.height != (GLsizei)framebuffer_info->height || 109 screen_info.texture.height != (GLsizei)framebuffer->height ||
110 screen_info.texture.pixel_format != framebuffer_info->pixel_format) { 110 screen_info.texture.pixel_format != framebuffer->pixel_format) {
111 // Reallocate texture if the framebuffer size has changed. 111 // Reallocate texture if the framebuffer size has changed.
112 // This is expected to not happen very often and hence should not be a 112 // This is expected to not happen very often and hence should not be a
113 // performance problem. 113 // performance problem.
114 ConfigureFramebufferTexture(screen_info.texture, *framebuffer_info); 114 ConfigureFramebufferTexture(screen_info.texture, *framebuffer);
115 } 115 }
116 LoadFBToScreenInfo(*framebuffer_info, screen_info); 116 LoadFBToScreenInfo(*framebuffer, screen_info);
117 } 117 }
118 118
119 DrawScreens(); 119 DrawScreens();
@@ -245,43 +245,47 @@ static void MortonCopyPixels128(u32 width, u32 height, u32 bytes_per_pixel, u32
245/** 245/**
246 * Loads framebuffer from emulated memory into the active OpenGL texture. 246 * Loads framebuffer from emulated memory into the active OpenGL texture.
247 */ 247 */
248void RendererOpenGL::LoadFBToScreenInfo(const FramebufferInfo& framebuffer_info, 248void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuffer,
249 ScreenInfo& screen_info) { 249 ScreenInfo& screen_info) {
250 const u32 bpp{FramebufferInfo::BytesPerPixel(framebuffer_info.pixel_format)}; 250 const u32 bpp{Tegra::FramebufferConfig::BytesPerPixel(framebuffer.pixel_format)};
251 const u32 size_in_bytes{framebuffer_info.stride * framebuffer_info.height * bpp}; 251 const u32 size_in_bytes{framebuffer.stride * framebuffer.height * bpp};
252 const VAddr framebuffer_addr{framebuffer.address};
253 const size_t pixel_stride{framebuffer.stride / bpp};
252 254
253 MortonCopyPixels128(framebuffer_info.width, framebuffer_info.height, bpp, 4, 255 // OpenGL only supports specifying a stride in units of pixels, not bytes, unfortunately
254 Memory::GetPointer(framebuffer_info.address), gl_framebuffer_data.data(), 256 ASSERT(pixel_stride * bpp == framebuffer.stride);
255 true); 257
258 MortonCopyPixels128(framebuffer.width, framebuffer.height, bpp, 4,
259 Memory::GetPointer(framebuffer.address), gl_framebuffer_data.data(), true);
256 260
257 LOG_TRACE(Render_OpenGL, "0x%08x bytes from 0x%llx(%dx%d), fmt %x", size_in_bytes, 261 LOG_TRACE(Render_OpenGL, "0x%08x bytes from 0x%llx(%dx%d), fmt %x", size_in_bytes,
258 framebuffer_info.address, framebuffer_info.width, framebuffer_info.height, 262 framebuffer.address, framebuffer.width, framebuffer.height,
259 (int)framebuffer_info.pixel_format); 263 (int)framebuffer.pixel_format);
260 264
261 // Ensure no bad interactions with GL_UNPACK_ALIGNMENT, which by default 265 // Ensure no bad interactions with GL_UNPACK_ALIGNMENT, which by default
262 // only allows rows to have a memory alignement of 4. 266 // only allows rows to have a memory alignement of 4.
263 ASSERT(framebuffer_info.stride % 4 == 0); 267 ASSERT(framebuffer.stride % 4 == 0);
264 268
265 framebuffer_flip_vertical = framebuffer_info.flip_vertical; 269 framebuffer_flip_vertical = framebuffer.flip_vertical;
266 270
267 // Reset the screen info's display texture to its own permanent texture 271 // Reset the screen info's display texture to its own permanent texture
268 screen_info.display_texture = screen_info.texture.resource.handle; 272 screen_info.display_texture = screen_info.texture.resource.handle;
269 screen_info.display_texcoords = MathUtil::Rectangle<float>(0.f, 0.f, 1.f, 1.f); 273 screen_info.display_texcoords = MathUtil::Rectangle<float>(0.f, 0.f, 1.f, 1.f);
270 274
271 // Memory::RasterizerFlushRegion(framebuffer_info.address, size_in_bytes); 275 Rasterizer()->FlushRegion(framebuffer.address, size_in_bytes);
272 276
273 state.texture_units[0].texture_2d = screen_info.texture.resource.handle; 277 state.texture_units[0].texture_2d = screen_info.texture.resource.handle;
274 state.Apply(); 278 state.Apply();
275 279
276 glActiveTexture(GL_TEXTURE0); 280 glActiveTexture(GL_TEXTURE0);
277 glPixelStorei(GL_UNPACK_ROW_LENGTH, (GLint)framebuffer_info.stride); 281 glPixelStorei(GL_UNPACK_ROW_LENGTH, (GLint)framebuffer.stride);
278 282
279 // Update existing texture 283 // Update existing texture
280 // TODO: Test what happens on hardware when you change the framebuffer dimensions so that 284 // TODO: Test what happens on hardware when you change the framebuffer dimensions so that
281 // they differ from the LCD resolution. 285 // they differ from the LCD resolution.
282 // TODO: Applications could theoretically crash Citra here by specifying too large 286 // TODO: Applications could theoretically crash Citra here by specifying too large
283 // framebuffer sizes. We should make sure that this cannot happen. 287 // framebuffer sizes. We should make sure that this cannot happen.
284 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, framebuffer_info.width, framebuffer_info.height, 288 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, framebuffer.width, framebuffer.height,
285 screen_info.texture.gl_format, screen_info.texture.gl_type, 289 screen_info.texture.gl_format, screen_info.texture.gl_type,
286 gl_framebuffer_data.data()); 290 gl_framebuffer_data.data());
287 291
@@ -372,14 +376,14 @@ void RendererOpenGL::InitOpenGLObjects() {
372} 376}
373 377
374void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, 378void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,
375 const FramebufferInfo& framebuffer_info) { 379 const Tegra::FramebufferConfig& framebuffer) {
376 380
377 texture.width = framebuffer_info.width; 381 texture.width = framebuffer.width;
378 texture.height = framebuffer_info.height; 382 texture.height = framebuffer.height;
379 383
380 GLint internal_format; 384 GLint internal_format;
381 switch (framebuffer_info.pixel_format) { 385 switch (framebuffer.pixel_format) {
382 case FramebufferInfo::PixelFormat::ABGR8: 386 case Tegra::FramebufferConfig::PixelFormat::ABGR8:
383 // Use RGBA8 and swap in the fragment shader 387 // Use RGBA8 and swap in the fragment shader
384 internal_format = GL_RGBA; 388 internal_format = GL_RGBA;
385 texture.gl_format = GL_RGBA; 389 texture.gl_format = GL_RGBA;
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h
index 05bb3c5cf..bd7c2510f 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.h
+++ b/src/video_core/renderer_opengl/renderer_opengl.h
@@ -21,7 +21,7 @@ struct TextureInfo {
21 GLsizei height; 21 GLsizei height;
22 GLenum gl_format; 22 GLenum gl_format;
23 GLenum gl_type; 23 GLenum gl_type;
24 RendererBase::FramebufferInfo::PixelFormat pixel_format; 24 Tegra::FramebufferConfig::PixelFormat pixel_format;
25}; 25};
26 26
27/// Structure used for storing information about the display target for each 3DS screen 27/// Structure used for storing information about the display target for each 3DS screen
@@ -37,7 +37,7 @@ public:
37 ~RendererOpenGL() override; 37 ~RendererOpenGL() override;
38 38
39 /// Swap buffers (render frame) 39 /// Swap buffers (render frame)
40 void SwapBuffers(boost::optional<const FramebufferInfo&> framebuffer_info) override; 40 void SwapBuffers(boost::optional<const Tegra::FramebufferConfig&> framebuffer) override;
41 41
42 /** 42 /**
43 * Set the emulator window to use for renderer 43 * Set the emulator window to use for renderer
@@ -53,13 +53,14 @@ public:
53 53
54private: 54private:
55 void InitOpenGLObjects(); 55 void InitOpenGLObjects();
56 void ConfigureFramebufferTexture(TextureInfo& texture, const FramebufferInfo& framebuffer_info); 56 void ConfigureFramebufferTexture(TextureInfo& texture,
57 const Tegra::FramebufferConfig& framebuffer);
57 void DrawScreens(); 58 void DrawScreens();
58 void DrawSingleScreen(const ScreenInfo& screen_info, float x, float y, float w, float h); 59 void DrawSingleScreen(const ScreenInfo& screen_info, float x, float y, float w, float h);
59 void UpdateFramerate(); 60 void UpdateFramerate();
60 61
61 // Loads framebuffer from emulated memory into the display information structure 62 // Loads framebuffer from emulated memory into the display information structure
62 void LoadFBToScreenInfo(const FramebufferInfo& framebuffer_info, ScreenInfo& screen_info); 63 void LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuffer, ScreenInfo& screen_info);
63 // Fills active OpenGL texture with the given RGBA color. 64 // Fills active OpenGL texture with the given RGBA color.
64 void LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a, 65 void LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a,
65 const TextureInfo& texture); 66 const TextureInfo& texture);