From a2d98b2773a639fd02faedd1c6fdae2013dd9d6c Mon Sep 17 00:00:00 2001 From: Andre Leiradella Date: Sun, 1 Apr 2018 10:59:28 +0100 Subject: [PATCH] Fixed OpenGL renderer --- src/RALibretro.vcxproj | 2 +- src/components/Video.cpp | 232 +++++++++++++++++++-------------------- src/components/Video.h | 7 +- 3 files changed, 120 insertions(+), 121 deletions(-) diff --git a/src/RALibretro.vcxproj b/src/RALibretro.vcxproj index d1656fc..ebeb5e1 100644 --- a/src/RALibretro.vcxproj +++ b/src/RALibretro.vcxproj @@ -103,7 +103,7 @@ true true $(MSBuildProjectDirectory)\..\SDL2\lib\x86;%(AdditionalLibraryDirectories) - SDL2main.lib;SDL2.lib;dinput8.lib;dxguid.lib;winmm.lib;imm32.lib;version.lib;winhttp.lib;%(AdditionalDependencies) + SDL2main.lib;SDL2.lib;dinput8.lib;dxguid.lib;winmm.lib;imm32.lib;version.lib;winhttp.lib;opengl32.lib;%(AdditionalDependencies) diff --git a/src/components/Video.cpp b/src/components/Video.cpp index 7d647ea..ee6eed7 100644 --- a/src/components/Video.cpp +++ b/src/components/Video.cpp @@ -34,18 +34,12 @@ bool Video::init(libretro::LoggerComponent* logger, Config* config) _textureWidth = _textureHeight = 0; _viewWidth = _viewHeight = 0; - _program = 0; - _posAttribute = -1; - _uvAttribute = -1; - _ratioUniform = -1; - _texUniform = -1; _vertexBuffer = 0; _texture = 0; _framebuffer = 0; _renderbuffer = 0; - createProgram(); - createVertexAttributes(); + _program = createProgram(&_posAttribute, &_uvAttribute, &_texUniform); if (!Gl::ok()) { @@ -58,7 +52,7 @@ bool Video::init(libretro::LoggerComponent* logger, Config* config) void Video::destroy() { - /*if (_renderbuffer != 0) + if (_renderbuffer != 0) { Gl::deleteRenderbuffers(1, &_renderbuffer); _renderbuffer = 0; @@ -86,23 +80,13 @@ void Video::destroy() { Gl::deleteProgram(_program); _program = 0; - }*/ + } } void Video::draw() { if (_texture != 0) { - bool linearFilter = _config->linearFilter(); - - if (linearFilter != _linearFilter) - { - _linearFilter = linearFilter; - GLint filter = linearFilter ? GL_LINEAR : GL_NEAREST; - Gl::texParameteri(_texture, GL_TEXTURE_MIN_FILTER, filter); - Gl::texParameteri(_texture, GL_TEXTURE_MAG_FILTER, filter); - } - float height = (float)_windowHeight; float width = height * _aspect; @@ -121,9 +105,6 @@ void Video::draw() sy = (float)_viewHeight / (float)_windowHeight; } - /*Gl::clearColor(0.0f, 0.0f, 0.0f, 1.0f); - Gl::clear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);*/ - Gl::useProgram(_program); Gl::enableVertexAttribArray(_posAttribute); @@ -133,48 +114,22 @@ void Video::draw() Gl::bindTexture(GL_TEXTURE_2D, _texture); Gl::uniform1i(_texUniform, 0); - Gl::uniform2f(_ratioUniform, sx, sy); - Gl::drawArrays(GL_TRIANGLE_STRIP, 0, 4); } } bool Video::setGeometry(unsigned width, unsigned height, float aspect, enum retro_pixel_format pixelFormat, const struct retro_hw_render_callback* hwRenderCallback) { - destroy(); - - Gl::genTextures(1, &_texture); - - if (!Gl::ok()) - { - return false; - } - - Gl::bindTexture(GL_TEXTURE_2D, _texture); - - switch (pixelFormat) - { - case RETRO_PIXEL_FORMAT_XRGB8888: - Gl::texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - break; - - case RETRO_PIXEL_FORMAT_RGB565: - Gl::texImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL); - break; - - case RETRO_PIXEL_FORMAT_0RGB1555: - default: - Gl::texImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_1_5_5_5_REV, NULL); - break; - } + (void)width; + (void)height; + (void)hwRenderCallback; - _textureWidth = width; - _textureHeight = height; _aspect = aspect; _pixelFormat = pixelFormat; _logger->printf(RETRO_LOG_DEBUG, "Geometry set to %u x %u (1:%f)", width, height, aspect); +#if 0 if (hwRenderCallback != NULL) { // Hardware framebuffer @@ -191,13 +146,14 @@ bool Video::setGeometry(unsigned width, unsigned height, float aspect, enum retr GLenum drawBuffers[] = {GL_COLOR_ATTACHMENT0}; Gl::drawBuffers(sizeof(drawBuffers) / sizeof(drawBuffers[0]), drawBuffers); - } - if (!Gl::ok()) - { - destroy(); - return false; + if (!Gl::ok()) + { + destroy(); + return false; + } } +#endif return true; } @@ -206,56 +162,50 @@ void Video::refresh(const void* data, unsigned width, unsigned height, size_t pi { if (data != NULL && data != RETRO_HW_FRAME_BUFFER_VALID) { - Gl::bindTexture(GL_TEXTURE_2D, _texture); - uint8_t* p = (uint8_t*)data; + bool updateVertexBuffer = false; + + bool linearFilter = _config->linearFilter(); + + unsigned textureWidth = pitch; switch (_pixelFormat) { - case RETRO_PIXEL_FORMAT_XRGB8888: + case RETRO_PIXEL_FORMAT_XRGB8888: textureWidth /= 4; break; + case RETRO_PIXEL_FORMAT_RGB565: // fallthrough + case RETRO_PIXEL_FORMAT_0RGB1555: textureWidth /= 2; break; + } + + if (linearFilter != _linearFilter || textureWidth > _textureWidth || height > _textureHeight) + { + if (_texture != 0) { - uint32_t* q = (uint32_t*)alloca(width * 4); - - if (q != NULL) - { - for (unsigned y = 0; y < height; y++) - { - uint32_t* r = q; - uint32_t* s = (uint32_t*)p; - - for (unsigned x = 0; x < width; x++) - { - uint32_t color = *s++; - uint32_t red = (color >> 16) & 255; - uint32_t green = (color >> 8) & 255; - uint32_t blue = color & 255; - *r++ = 0xff000000UL | blue << 16 | green << 8 | red; - } - - Gl::texSubImage2D(GL_TEXTURE_2D, 0, 0, y, width, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void*)q); - p += pitch; - } - } + Gl::deleteTextures(1, &_texture); } - + + _texture = createTexture(textureWidth, height, _pixelFormat, linearFilter); + + _linearFilter = linearFilter; + _textureWidth = textureWidth; + _textureHeight = height; + + updateVertexBuffer = true; + } + + Gl::bindTexture(GL_TEXTURE_2D, _texture); + + switch (_pixelFormat) + { + case RETRO_PIXEL_FORMAT_XRGB8888: + Gl::texSubImage2D(GL_TEXTURE_2D, 0, 0, 0, textureWidth, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, data); break; case RETRO_PIXEL_FORMAT_RGB565: - for (unsigned y = 0; y < height; y++) - { - Gl::texSubImage2D(GL_TEXTURE_2D, 0, 0, y, width, 1, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (void*)p); - p += pitch; - } - + Gl::texSubImage2D(GL_TEXTURE_2D, 0, 0, 0, textureWidth, height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data); break; case RETRO_PIXEL_FORMAT_0RGB1555: default: - for (unsigned y = 0; y < height; y++) - { - Gl::texSubImage2D(GL_TEXTURE_2D, 0, 0, y, width, 1, GL_RGB, GL_UNSIGNED_SHORT_1_5_5_5_REV, (void*)p); - p += pitch; - } - + Gl::texSubImage2D(GL_TEXTURE_2D, 0, 0, 0, textureWidth, height, GL_RGB, GL_UNSIGNED_SHORT_1_5_5_5_REV, data); break; } @@ -264,7 +214,16 @@ void Video::refresh(const void* data, unsigned width, unsigned height, size_t pi _viewWidth = width; _viewHeight = height; - _logger->printf(RETRO_LOG_DEBUG, "Video refreshed with geometry %u x %u", width, height); + updateVertexBuffer = true; + } + + if (updateVertexBuffer) + { + float width = (float)_viewWidth / (float)_textureWidth; + float height = (float)_viewHeight / (float)_textureHeight; + + Gl::deleteBuffers(1, &_vertexBuffer); + _vertexBuffer = createVertexBuffer(width, height, _posAttribute, _uvAttribute); } } } @@ -364,51 +323,92 @@ const void* Video::getFramebuffer(unsigned* width, unsigned* height, unsigned* p return NULL; } -void Video::createProgram() +GLuint Video::createProgram(GLint* pos, GLint* uv, GLint* tex) { - static const char* s_vertexShader = + static const char* vertexShader = "attribute vec2 a_pos;\n" "attribute vec2 a_uv;\n" "varying vec2 v_uv;\n" - "uniform vec2 u_ratio;\n" "void main() {\n" " v_uv = a_uv;\n" - " gl_Position = vec4(a_pos * u_ratio, 0.0, 1.0);\n" + " gl_Position = vec4(a_pos, 0.0, 1.0);\n" "}"; - static const char* s_fragmentShader = + static const char* fragmentShader = "varying vec2 v_uv;\n" "uniform sampler2D u_tex;\n" "void main() {\n" " gl_FragColor = texture2D(u_tex, v_uv);\n" "}"; - _program = Gl::createProgram(s_vertexShader, s_fragmentShader); + GLuint program = Gl::createProgram(vertexShader, fragmentShader); - _posAttribute = Gl::getAttribLocation(_program, "a_pos"); - _uvAttribute = Gl::getAttribLocation(_program, "a_uv"); - _ratioUniform = Gl::getUniformLocation(_program, "u_ratio"); - _texUniform = Gl::getUniformLocation(_program, "u_tex"); + *pos = Gl::getAttribLocation(program, "a_pos"); + *uv = Gl::getAttribLocation(program, "a_uv"); + *tex = Gl::getUniformLocation(program, "u_tex"); + + return program; } -void Video::createVertexAttributes() +GLuint Video::createVertexBuffer(float textureWidth, float textureHeight, GLint pos, GLint uv) { struct VertexData { float x, y, u, v; }; - static const VertexData vertexData[] = { - {-1.0f, -1.0f, 0.0f, 0.0f}, - {-1.0f, 1.0f, 0.0f, 1.0f}, - { 1.0f, -1.0f, 1.0f, 0.0f}, - { 1.0f, 1.0f, 1.0f, 1.0f} + const VertexData vertexData[] = { + {-1.0f, -1.0f, 0.0f, textureHeight}, + {-1.0f, 1.0f, 0.0f, 0.0f}, + { 1.0f, -1.0f, textureWidth, textureHeight}, + { 1.0f, 1.0f, textureWidth, 0.0f} }; - Gl::genBuffers(1, &_vertexBuffer); - Gl::bindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + GLuint vertexBuffer; + Gl::genBuffers(1, &vertexBuffer); + + Gl::bindBuffer(GL_ARRAY_BUFFER, vertexBuffer); Gl::bufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW); - Gl::vertexAttribPointer(_posAttribute, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (const GLvoid*)offsetof(VertexData, x)); - Gl::vertexAttribPointer(_uvAttribute, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (const GLvoid*)offsetof(VertexData, u)); + Gl::vertexAttribPointer(pos, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (const GLvoid*)offsetof(VertexData, x)); + Gl::vertexAttribPointer(uv, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (const GLvoid*)offsetof(VertexData, u)); + + _logger->printf(RETRO_LOG_DEBUG, "Vertices updated with texture %f x %f", textureWidth, textureHeight); + return vertexBuffer; +} + +GLuint Video::createTexture(unsigned width, unsigned height, retro_pixel_format pixelFormat, bool linear) +{ + GLuint texture; + Gl::genTextures(1, &texture); + + Gl::bindTexture(GL_TEXTURE_2D, texture); + + GLint filter = linear ? GL_LINEAR : GL_NEAREST; + Gl::texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); + Gl::texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); + + const char* format; + + switch (pixelFormat) + { + case RETRO_PIXEL_FORMAT_XRGB8888: + Gl::texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); + format = "RGBA8888"; + break; + + case RETRO_PIXEL_FORMAT_RGB565: + Gl::texImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL); + format = "RGB565"; + break; + + case RETRO_PIXEL_FORMAT_0RGB1555: + default: + Gl::texImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_1_5_5_5_REV, NULL); + format = "RGBA5551"; + break; + } + + _logger->printf(RETRO_LOG_DEBUG, "Texture created with dimensions %u x %u (%s, %s)", width, height, format, linear ? "linear" : "nearest"); + return texture; } diff --git a/src/components/Video.h b/src/components/Video.h index 1b575db..4079134 100644 --- a/src/components/Video.h +++ b/src/components/Video.h @@ -46,9 +46,9 @@ class Video: public libretro::VideoComponent const void* getFramebuffer(unsigned* width, unsigned* height, unsigned* pitch, enum retro_pixel_format* format); protected: - void createProgram(); - void createVertexAttributes(); - + GLuint createProgram(GLint* pos, GLint* uv, GLint* tex); + GLuint createVertexBuffer(float textureWidth, float textureHeight, GLint pos, GLint uv); + GLuint createTexture(unsigned width, unsigned height, retro_pixel_format pixelFormat, bool linear); libretro::LoggerComponent* _logger; Config* _config; @@ -56,7 +56,6 @@ class Video: public libretro::VideoComponent GLuint _program; GLint _posAttribute; GLint _uvAttribute; - GLint _ratioUniform; GLint _texUniform; GLuint _vertexBuffer; GLuint _texture;