mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-23 00:50:04 +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;
|
||||
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;
|
||||
|
||||
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);
|
||||
frag_tex_coord = vert_tex_coord;
|
||||
}
|
||||
|
@ -13,9 +13,18 @@
|
||||
#include "video_core/renderer_opengl/gl_shaders.h"
|
||||
|
||||
#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 tex_coord[2];
|
||||
};
|
||||
@ -24,9 +33,14 @@ struct GLVertex {
|
||||
* Defines a 1:1 pixel ortographic projection matrix with (0,0) on the top-left
|
||||
* 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[1] = 0.f; m[3] = -2.f / height; m[5] = 1.f;
|
||||
// Last row is implicitly [0, 0, 1].
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/// 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) {
|
||||
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);
|
||||
|
||||
// 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;
|
||||
// OpenGL only supports specifying a stride in units of pixels, unfortunately
|
||||
assert(pixel_stride * 3 == framebuffer.stride);
|
||||
// Ensure no bad interactions with GL_UNPACK_ALIGNMENT
|
||||
assert(pixel_stride % 4 == 0);
|
||||
// OpenGL only supports specifying a stride in units of pixels, not bytes, unfortunately
|
||||
_dbg_assert_(RENDER, pixel_stride * 3 == framebuffer.stride);
|
||||
// Ensure no bad interactions with GL_UNPACK_ALIGNMENT, which by default
|
||||
// only allows rows to have a memory alignement of 4.
|
||||
_dbg_assert_(RENDER, pixel_stride % 4 == 0);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture.handle);
|
||||
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
|
||||
// what happens if you change the framebuffer dimensions so that they
|
||||
// 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 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.
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, framebuffer.width, framebuffer.height, 0,
|
||||
GL_BGR, GL_UNSIGNED_BYTE, framebuffer_data);
|
||||
@ -109,9 +124,8 @@ void RendererOpenGL::RenderXFB(TextureInfo& texture, const GPU::Regs::Framebuffe
|
||||
void RendererOpenGL::InitOpenGLObjects() {
|
||||
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
|
||||
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);
|
||||
uniform_proj_matrix = glGetUniformLocation(program_id, "proj_matrix");
|
||||
uniform_color_texture = glGetUniformLocation(program_id, "color_texture");
|
||||
@ -127,9 +141,9 @@ void RendererOpenGL::InitOpenGLObjects() {
|
||||
|
||||
// Attach vertex data to VAO
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_handle);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(GLVertex) * 4, nullptr, GL_STREAM_DRAW);
|
||||
glVertexAttribPointer(attrib_position, 2, GL_FLOAT, GL_FALSE, sizeof(GLVertex), (GLvoid*)offsetof(GLVertex, position));
|
||||
glVertexAttribPointer(attrib_tex_coord, 2, GL_FLOAT, GL_FALSE, sizeof(GLVertex), (GLvoid*)offsetof(GLVertex, tex_coord));
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(ScreenRectVertex) * 4, nullptr, GL_STREAM_DRAW);
|
||||
glVertexAttribPointer(attrib_position, 2, GL_FLOAT, GL_FALSE, sizeof(ScreenRectVertex), (GLvoid*)offsetof(ScreenRectVertex, position));
|
||||
glVertexAttribPointer(attrib_tex_coord, 2, GL_FLOAT, GL_FALSE, sizeof(ScreenRectVertex), (GLvoid*)offsetof(ScreenRectVertex, tex_coord));
|
||||
glEnableVertexAttribArray(attrib_position);
|
||||
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.
|
||||
*/
|
||||
void RendererOpenGL::DrawSingleScreenRotated(const TextureInfo& texture, float x, float y, float w, float h) {
|
||||
std::array<GLVertex, 4> vertices = {{
|
||||
{{x, y}, {1.f, 0.f}},
|
||||
{{x+w, y}, {1.f, 1.f}},
|
||||
{{x, y+h}, {0.f, 0.f}},
|
||||
{{x+w, y+h}, {0.f, 1.f}},
|
||||
}};
|
||||
std::array<ScreenRectVertex, 4> vertices = {
|
||||
ScreenRectVertex(x, y, 1.f, 0.f),
|
||||
ScreenRectVertex(x+w, y, 1.f, 1.f),
|
||||
ScreenRectVertex(x, y+h, 0.f, 0.f),
|
||||
ScreenRectVertex(x+w, y+h, 0.f, 1.f),
|
||||
};
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture.handle);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_handle);
|
||||
@ -177,8 +191,7 @@ void RendererOpenGL::DrawScreens() {
|
||||
glUseProgram(program_id);
|
||||
|
||||
// Set projection matrix
|
||||
std::array<GLfloat, 3 * 2> ortho_matrix;
|
||||
write_orthographic_matrix(ortho_matrix, (float)resolution_width, (float)resolution_height);
|
||||
std::array<GLfloat, 3*2> ortho_matrix = MakeOrthographicMatrix((float)resolution_width, (float)resolution_height);
|
||||
glUniformMatrix3x2fv(uniform_proj_matrix, 1, GL_FALSE, ortho_matrix.data());
|
||||
|
||||
// Bind texture in Texture Unit 0
|
||||
|
@ -17,9 +17,10 @@ namespace VideoCore {
|
||||
// 3DS Video Constants
|
||||
// -------------------
|
||||
|
||||
// NOTE: The LCDs actually rotate the image 90 degrees when displaying. Because
|
||||
// of that the framebuffers in video memory are stored in column-major order
|
||||
// and rendered sideways, causing the widths and heights here to be switched.
|
||||
// NOTE: The LCDs actually rotate the image 90 degrees when displaying. Because of that the
|
||||
// framebuffers in video memory are stored in column-major order and rendered sideways, causing
|
||||
// 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 kScreenTopHeight = 240; ///< 3DS top screen height
|
||||
static const int kScreenBottomWidth = 320; ///< 3DS bottom screen width
|
||||
|
Loading…
Reference in New Issue
Block a user