diff options
Diffstat (limited to 'src/GPU_OpenGL.cpp')
-rw-r--r-- | src/GPU_OpenGL.cpp | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/src/GPU_OpenGL.cpp b/src/GPU_OpenGL.cpp new file mode 100644 index 0000000..1cb6864 --- /dev/null +++ b/src/GPU_OpenGL.cpp @@ -0,0 +1,206 @@ +/* + Copyright 2016-2020 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#include <stdio.h> +#include <string.h> +#include "NDS.h" +#include "GPU.h" +#include "Config.h" +#include "OpenGLSupport.h" +#include "GPU_OpenGL_shaders.h" + +namespace GPU +{ +namespace GLCompositor +{ + +using namespace OpenGL; + +int Scale; +int ScreenH, ScreenW; + +GLuint CompShader[1][3]; +GLuint CompScaleLoc[1]; + +GLuint CompVertexBufferID; +GLuint CompVertexArrayID; +float CompVertices[2 * 3*2 * 2]; // position + +GLuint CompScreenInputTex; +GLuint CompScreenOutputTex; +GLuint CompScreenOutputFB; + + +bool Init() +{ + if (!OpenGL::BuildShaderProgram(kCompositorVS, kCompositorFS_Nearest, CompShader[0], "CompositorShader")) + //if (!OpenGL::BuildShaderProgram(kCompositorVS, kCompositorFS_Linear, CompShader[0], "CompositorShader")) + //if (!OpenGL::BuildShaderProgram(kCompositorVS_xBRZ, kCompositorFS_xBRZ, CompShader[0], "CompositorShader")) + return false; + + for (int i = 0; i < 1; i++) + { + GLint uni_id; + + glBindAttribLocation(CompShader[i][2], 0, "vPosition"); + glBindFragDataLocation(CompShader[i][2], 0, "oColor"); + + if (!OpenGL::LinkShaderProgram(CompShader[i])) + return false; + + CompScaleLoc[i] = glGetUniformLocation(CompShader[i][2], "u3DScale"); + + glUseProgram(CompShader[i][2]); + uni_id = glGetUniformLocation(CompShader[i][2], "ScreenTex"); + glUniform1i(uni_id, 0); + uni_id = glGetUniformLocation(CompShader[i][2], "_3DTex"); + glUniform1i(uni_id, 1); + } + +#define SETVERTEX(i, x, y) \ + CompVertices[2*(i) + 0] = x; \ + CompVertices[2*(i) + 1] = y; + + // top screen + SETVERTEX(0, -1, 1); + SETVERTEX(1, 1, 0); + SETVERTEX(2, 1, 1); + SETVERTEX(3, -1, 1); + SETVERTEX(4, -1, 0); + SETVERTEX(5, 1, 0); + + // bottom screen + SETVERTEX(6, -1, 0); + SETVERTEX(7, 1, -1); + SETVERTEX(8, 1, 0); + SETVERTEX(9, -1, 0); + SETVERTEX(10, -1, -1); + SETVERTEX(11, 1, -1); + +#undef SETVERTEX + + glGenBuffers(1, &CompVertexBufferID); + glBindBuffer(GL_ARRAY_BUFFER, CompVertexBufferID); + glBufferData(GL_ARRAY_BUFFER, sizeof(CompVertices), CompVertices, GL_STATIC_DRAW); + + glGenVertexArrays(1, &CompVertexArrayID); + glBindVertexArray(CompVertexArrayID); + glEnableVertexAttribArray(0); // position + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2*4, (void*)(0)); + + glGenFramebuffers(1, &CompScreenOutputFB); + + glGenTextures(1, &CompScreenInputTex); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, CompScreenInputTex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, 256*3 + 1, 192*2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, NULL); + + glGenTextures(1, &CompScreenOutputTex); + glBindTexture(GL_TEXTURE_2D, CompScreenOutputTex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + return true; +} + +void DeInit() +{ + glDeleteFramebuffers(1, &CompScreenOutputFB); + glDeleteTextures(1, &CompScreenInputTex); + glDeleteTextures(1, &CompScreenOutputTex); + + glDeleteVertexArrays(1, &CompVertexArrayID); + glDeleteBuffers(1, &CompVertexBufferID); + + for (int i = 0; i < 1; i++) + OpenGL::DeleteShaderProgram(CompShader[i]); +} + +void Reset() +{ +} + + +void SetRenderSettings(RenderSettings& settings) +{ + int scale = settings.GL_ScaleFactor; + + Scale = scale; + ScreenW = 256 * scale; + ScreenH = 384 * scale; + + glBindTexture(GL_TEXTURE_2D, CompScreenOutputTex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ScreenW, ScreenH, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + GLenum fbassign[] = {GL_COLOR_ATTACHMENT0}; + glBindFramebuffer(GL_FRAMEBUFFER, CompScreenOutputFB); + glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, CompScreenOutputTex, 0); + glDrawBuffers(1, fbassign); +} + + +void RenderFrame() +{ + glBindFramebuffer(GL_FRAMEBUFFER, CompScreenOutputFB); + + glDisable(GL_DEPTH_TEST); + glDisable(GL_STENCIL_TEST); + glDisable(GL_BLEND); + glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + + glViewport(0, 0, ScreenW, ScreenH); + + // TODO: select more shaders (filtering, etc) + OpenGL::UseShaderProgram(CompShader[0]); + glUniform1ui(CompScaleLoc[0], Scale); + + int frontbuf = GPU::FrontBuffer; + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, CompScreenInputTex); + + if (GPU::Framebuffer[frontbuf][0] && GPU::Framebuffer[frontbuf][1]) + { + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256*3 + 1, 192, GL_RGBA_INTEGER, + GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][0]); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 192, 256*3 + 1, 192, GL_RGBA_INTEGER, + GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][1]); + } + + glActiveTexture(GL_TEXTURE1); + GPU3D::GLRenderer::SetupAccelFrame(); + + glBindBuffer(GL_ARRAY_BUFFER, CompVertexBufferID); + glBindVertexArray(CompVertexArrayID); + glDrawArrays(GL_TRIANGLES, 0, 4*3); + + glFlush(); +} + +void BindOutputTexture() +{ + glBindTexture(GL_TEXTURE_2D, CompScreenOutputTex); +} + +} +} |