mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-23 08:50:09 +00:00
Address some review concerns.
This commit is contained in:
parent
0e0cccf0e2
commit
fbf1aca8f6
@ -13,9 +13,14 @@ in vec2 vert_position;
|
|||||||
in vec2 vert_tex_coord;
|
in vec2 vert_tex_coord;
|
||||||
out vec2 frag_tex_coord;
|
out vec2 frag_tex_coord;
|
||||||
|
|
||||||
|
// This is a truncated 3x3 matrix for 2D transformations, with the last row
|
||||||
|
// assumed to implicitly be [0, 0, 1].
|
||||||
uniform mat3x2 proj_matrix;
|
uniform mat3x2 proj_matrix;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
// Multiply vector by the rotscale part of the matrix and then manually translate by the last
|
||||||
|
// column. This is equivalent to if proj_matrix was a full 3x3 matrix and the vector were
|
||||||
|
// expanded to `vec3(vert_position.xy, 1.0)`.
|
||||||
gl_Position = vec4(mat2(proj_matrix) * vert_position + proj_matrix[2], 0.0, 1.0);
|
gl_Position = vec4(mat2(proj_matrix) * vert_position + proj_matrix[2], 0.0, 1.0);
|
||||||
frag_tex_coord = vert_tex_coord;
|
frag_tex_coord = vert_tex_coord;
|
||||||
}
|
}
|
||||||
|
@ -13,9 +13,18 @@
|
|||||||
#include "video_core/renderer_opengl/gl_shaders.h"
|
#include "video_core/renderer_opengl/gl_shaders.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
|
||||||
|
|
||||||
struct GLVertex {
|
/**
|
||||||
|
* Vertex structure that the drawn screen rectangles are composed of.
|
||||||
|
*/
|
||||||
|
struct ScreenRectVertex {
|
||||||
|
ScreenRectVertex(GLfloat x, GLfloat y, GLfloat u, GLfloat v) {
|
||||||
|
position[0] = x;
|
||||||
|
position[1] = y;
|
||||||
|
tex_coord[0] = u;
|
||||||
|
tex_coord[1] = v;
|
||||||
|
}
|
||||||
|
|
||||||
GLfloat position[2];
|
GLfloat position[2];
|
||||||
GLfloat tex_coord[2];
|
GLfloat tex_coord[2];
|
||||||
};
|
};
|
||||||
@ -24,9 +33,14 @@ struct GLVertex {
|
|||||||
* Defines a 1:1 pixel ortographic projection matrix with (0,0) on the top-left
|
* Defines a 1:1 pixel ortographic projection matrix with (0,0) on the top-left
|
||||||
* corner and (width, height) on the lower-bottom.
|
* corner and (width, height) on the lower-bottom.
|
||||||
*/
|
*/
|
||||||
static void write_orthographic_matrix(std::array<GLfloat, 3*2>& m, float width, float height) {
|
static std::array<GLfloat, 3*2> MakeOrthographicMatrix(const float width, const float height) {
|
||||||
|
std::array<GLfloat, 3*2> m;
|
||||||
|
|
||||||
m[0] = 2.f / width; m[2] = 0.f; m[4] = -1.f;
|
m[0] = 2.f / width; m[2] = 0.f; m[4] = -1.f;
|
||||||
m[1] = 0.f; m[3] = -2.f / height; m[5] = 1.f;
|
m[1] = 0.f; m[3] = -2.f / height; m[5] = 1.f;
|
||||||
|
// Last row is implicitly [0, 0, 1].
|
||||||
|
|
||||||
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// RendererOpenGL constructor
|
/// RendererOpenGL constructor
|
||||||
@ -56,7 +70,7 @@ void RendererOpenGL::SwapBuffers() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves a framebuffer from emulated video memory to a OpenGL texture.
|
* Loads framebuffer from emulated video memory onto an OpenGL texture.
|
||||||
*/
|
*/
|
||||||
void RendererOpenGL::RenderXFB(TextureInfo& texture, const GPU::Regs::FramebufferConfig& framebuffer) {
|
void RendererOpenGL::RenderXFB(TextureInfo& texture, const GPU::Regs::FramebufferConfig& framebuffer) {
|
||||||
const VAddr framebuffer_vaddr = Memory::PhysicalToVirtualAddress(
|
const VAddr framebuffer_vaddr = Memory::PhysicalToVirtualAddress(
|
||||||
@ -70,13 +84,14 @@ void RendererOpenGL::RenderXFB(TextureInfo& texture, const GPU::Regs::Framebuffe
|
|||||||
const u8* framebuffer_data = Memory::GetPointer(framebuffer_vaddr);
|
const u8* framebuffer_data = Memory::GetPointer(framebuffer_vaddr);
|
||||||
|
|
||||||
// TODO: Handle other pixel formats
|
// TODO: Handle other pixel formats
|
||||||
assert(framebuffer.color_format == GPU::Regs::PixelFormat::RGB8);
|
_dbg_assert_msg_(RENDER, framebuffer.color_format == GPU::Regs::PixelFormat::RGB8, "Currently unsupported 3DS pixel format.");
|
||||||
|
|
||||||
size_t pixel_stride = framebuffer.stride / 3;
|
size_t pixel_stride = framebuffer.stride / 3;
|
||||||
// OpenGL only supports specifying a stride in units of pixels, unfortunately
|
// OpenGL only supports specifying a stride in units of pixels, not bytes, unfortunately
|
||||||
assert(pixel_stride * 3 == framebuffer.stride);
|
_dbg_assert_(RENDER, pixel_stride * 3 == framebuffer.stride);
|
||||||
// Ensure no bad interactions with GL_UNPACK_ALIGNMENT
|
// Ensure no bad interactions with GL_UNPACK_ALIGNMENT, which by default
|
||||||
assert(pixel_stride % 4 == 0);
|
// only allows rows to have a memory alignement of 4.
|
||||||
|
_dbg_assert_(RENDER, pixel_stride % 4 == 0);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, texture.handle);
|
glBindTexture(GL_TEXTURE_2D, texture.handle);
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, (GLint)pixel_stride);
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, (GLint)pixel_stride);
|
||||||
@ -84,9 +99,9 @@ void RendererOpenGL::RenderXFB(TextureInfo& texture, const GPU::Regs::Framebuffe
|
|||||||
// TODO: Testing needs to be done on hardware to see if scaling is really
|
// TODO: Testing needs to be done on hardware to see if scaling is really
|
||||||
// what happens if you change the framebuffer dimensions so that they
|
// what happens if you change the framebuffer dimensions so that they
|
||||||
// differ from the LCD resolution.
|
// differ from the LCD resolution.
|
||||||
// TODO: Prevent memory overread
|
// TODO: Prevent overread from memory buffer
|
||||||
if (texture.width != framebuffer.width || texture.height != framebuffer.height) {
|
if (texture.width != framebuffer.width || texture.height != framebuffer.height) {
|
||||||
// If the framebuffer size was changed, re-allocated the texture. The
|
// If the framebuffer size was changed, re-allocate the texture. The
|
||||||
// expectation is that this won't happen very often.
|
// expectation is that this won't happen very often.
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, framebuffer.width, framebuffer.height, 0,
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, framebuffer.width, framebuffer.height, 0,
|
||||||
GL_BGR, GL_UNSIGNED_BYTE, framebuffer_data);
|
GL_BGR, GL_UNSIGNED_BYTE, framebuffer_data);
|
||||||
@ -109,9 +124,8 @@ void RendererOpenGL::RenderXFB(TextureInfo& texture, const GPU::Regs::Framebuffe
|
|||||||
void RendererOpenGL::InitOpenGLObjects() {
|
void RendererOpenGL::InitOpenGLObjects() {
|
||||||
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
|
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
//glDisable(GL_CULL_FACE);
|
|
||||||
|
|
||||||
// Links shaders and get variable locations
|
// Link shaders and get variable locations
|
||||||
program_id = ShaderUtil::LoadShaders(GLShaders::g_vertex_shader, GLShaders::g_fragment_shader);
|
program_id = ShaderUtil::LoadShaders(GLShaders::g_vertex_shader, GLShaders::g_fragment_shader);
|
||||||
uniform_proj_matrix = glGetUniformLocation(program_id, "proj_matrix");
|
uniform_proj_matrix = glGetUniformLocation(program_id, "proj_matrix");
|
||||||
uniform_color_texture = glGetUniformLocation(program_id, "color_texture");
|
uniform_color_texture = glGetUniformLocation(program_id, "color_texture");
|
||||||
@ -127,9 +141,9 @@ void RendererOpenGL::InitOpenGLObjects() {
|
|||||||
|
|
||||||
// Attach vertex data to VAO
|
// Attach vertex data to VAO
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_handle);
|
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_handle);
|
||||||
glBufferData(GL_ARRAY_BUFFER, sizeof(GLVertex) * 4, nullptr, GL_STREAM_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, sizeof(ScreenRectVertex) * 4, nullptr, GL_STREAM_DRAW);
|
||||||
glVertexAttribPointer(attrib_position, 2, GL_FLOAT, GL_FALSE, sizeof(GLVertex), (GLvoid*)offsetof(GLVertex, position));
|
glVertexAttribPointer(attrib_position, 2, GL_FLOAT, GL_FALSE, sizeof(ScreenRectVertex), (GLvoid*)offsetof(ScreenRectVertex, position));
|
||||||
glVertexAttribPointer(attrib_tex_coord, 2, GL_FLOAT, GL_FALSE, sizeof(GLVertex), (GLvoid*)offsetof(GLVertex, tex_coord));
|
glVertexAttribPointer(attrib_tex_coord, 2, GL_FLOAT, GL_FALSE, sizeof(ScreenRectVertex), (GLvoid*)offsetof(ScreenRectVertex, tex_coord));
|
||||||
glEnableVertexAttribArray(attrib_position);
|
glEnableVertexAttribArray(attrib_position);
|
||||||
glEnableVertexAttribArray(attrib_tex_coord);
|
glEnableVertexAttribArray(attrib_tex_coord);
|
||||||
|
|
||||||
@ -154,12 +168,12 @@ void RendererOpenGL::InitOpenGLObjects() {
|
|||||||
* Draws a single texture to the emulator window, rotating the texture to correct for the 3DS's LCD rotation.
|
* Draws a single texture to the emulator window, rotating the texture to correct for the 3DS's LCD rotation.
|
||||||
*/
|
*/
|
||||||
void RendererOpenGL::DrawSingleScreenRotated(const TextureInfo& texture, float x, float y, float w, float h) {
|
void RendererOpenGL::DrawSingleScreenRotated(const TextureInfo& texture, float x, float y, float w, float h) {
|
||||||
std::array<GLVertex, 4> vertices = {{
|
std::array<ScreenRectVertex, 4> vertices = {
|
||||||
{{x, y}, {1.f, 0.f}},
|
ScreenRectVertex(x, y, 1.f, 0.f),
|
||||||
{{x+w, y}, {1.f, 1.f}},
|
ScreenRectVertex(x+w, y, 1.f, 1.f),
|
||||||
{{x, y+h}, {0.f, 0.f}},
|
ScreenRectVertex(x, y+h, 0.f, 0.f),
|
||||||
{{x+w, y+h}, {0.f, 1.f}},
|
ScreenRectVertex(x+w, y+h, 0.f, 1.f),
|
||||||
}};
|
};
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, texture.handle);
|
glBindTexture(GL_TEXTURE_2D, texture.handle);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_handle);
|
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_handle);
|
||||||
@ -177,8 +191,7 @@ void RendererOpenGL::DrawScreens() {
|
|||||||
glUseProgram(program_id);
|
glUseProgram(program_id);
|
||||||
|
|
||||||
// Set projection matrix
|
// Set projection matrix
|
||||||
std::array<GLfloat, 3 * 2> ortho_matrix;
|
std::array<GLfloat, 3*2> ortho_matrix = MakeOrthographicMatrix((float)resolution_width, (float)resolution_height);
|
||||||
write_orthographic_matrix(ortho_matrix, (float)resolution_width, (float)resolution_height);
|
|
||||||
glUniformMatrix3x2fv(uniform_proj_matrix, 1, GL_FALSE, ortho_matrix.data());
|
glUniformMatrix3x2fv(uniform_proj_matrix, 1, GL_FALSE, ortho_matrix.data());
|
||||||
|
|
||||||
// Bind texture in Texture Unit 0
|
// Bind texture in Texture Unit 0
|
||||||
|
@ -17,9 +17,10 @@ namespace VideoCore {
|
|||||||
// 3DS Video Constants
|
// 3DS Video Constants
|
||||||
// -------------------
|
// -------------------
|
||||||
|
|
||||||
// NOTE: The LCDs actually rotate the image 90 degrees when displaying. Because
|
// NOTE: The LCDs actually rotate the image 90 degrees when displaying. Because of that the
|
||||||
// of that the framebuffers in video memory are stored in column-major order
|
// framebuffers in video memory are stored in column-major order and rendered sideways, causing
|
||||||
// and rendered sideways, causing the widths and heights here to be switched.
|
// the widths and heights of the framebuffers read by the LCD to be switched compared to the
|
||||||
|
// heights and widths of the screens listed here.
|
||||||
static const int kScreenTopWidth = 400; ///< 3DS top screen width
|
static const int kScreenTopWidth = 400; ///< 3DS top screen width
|
||||||
static const int kScreenTopHeight = 240; ///< 3DS top screen height
|
static const int kScreenTopHeight = 240; ///< 3DS top screen height
|
||||||
static const int kScreenBottomWidth = 320; ///< 3DS bottom screen width
|
static const int kScreenBottomWidth = 320; ///< 3DS bottom screen width
|
||||||
|
Loading…
Reference in New Issue
Block a user