Skip to content

Commit

Permalink
Fixed OpenGL renderer
Browse files Browse the repository at this point in the history
  • Loading branch information
leiradel committed Apr 1, 2018
1 parent de9e3cb commit a2d98b2
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 121 deletions.
2 changes: 1 addition & 1 deletion src/RALibretro.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>$(MSBuildProjectDirectory)\..\SDL2\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>SDL2main.lib;SDL2.lib;dinput8.lib;dxguid.lib;winmm.lib;imm32.lib;version.lib;winhttp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>SDL2main.lib;SDL2.lib;dinput8.lib;dxguid.lib;winmm.lib;imm32.lib;version.lib;winhttp.lib;opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
Expand Down
232 changes: 116 additions & 116 deletions src/components/Video.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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())
{
Expand All @@ -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;
Expand Down Expand Up @@ -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;

Expand All @@ -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);
Expand All @@ -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
Expand All @@ -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;
}
Expand All @@ -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;
}

Expand All @@ -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);
}
}
}
Expand Down Expand Up @@ -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;
}
7 changes: 3 additions & 4 deletions src/components/Video.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,16 @@ 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;

GLuint _program;
GLint _posAttribute;
GLint _uvAttribute;
GLint _ratioUniform;
GLint _texUniform;
GLuint _vertexBuffer;
GLuint _texture;
Expand Down

0 comments on commit a2d98b2

Please sign in to comment.