Address some review concerns.

This commit is contained in:
Yuri Kunde Schlesner 2014-08-30 22:32:36 -03:00
parent 0e0cccf0e2
commit fbf1aca8f6
3 changed files with 46 additions and 27 deletions

View file

@ -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;
}

View file

@ -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

View file

@ -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