mirror of https://github.com/mgba-emu/mgba.git
OpenGL: Use VAOs
This commit is contained in:
parent
4bd788f715
commit
ee6cd36402
|
@ -85,7 +85,7 @@ Other Unix-like platforms, such as OpenBSD, are known to work as well, but are u
|
||||||
|
|
||||||
### System requirements
|
### System requirements
|
||||||
|
|
||||||
Requirements are minimal. Any computer that can run Windows Vista or newer should be able to handle emulation. Support for OpenGL 1.1 or newer is also required.
|
Requirements are minimal. Any computer that can run Windows Vista or newer should be able to handle emulation. Support for OpenGL 1.1 or newer is also required, with OpenGL 3.0 or newer for shaders and advanced features.
|
||||||
|
|
||||||
Downloads
|
Downloads
|
||||||
---------
|
---------
|
||||||
|
|
|
@ -125,6 +125,12 @@ enum {
|
||||||
GBA_GL_UNIFORM_MAX = 12
|
GBA_GL_UNIFORM_MAX = 12
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct GBAVideoGLShader {
|
||||||
|
GLuint program;
|
||||||
|
GLuint vao;
|
||||||
|
GLuint uniforms[GBA_GL_UNIFORM_MAX];
|
||||||
|
};
|
||||||
|
|
||||||
struct GBAVideoGLRenderer {
|
struct GBAVideoGLRenderer {
|
||||||
struct GBAVideoRenderer d;
|
struct GBAVideoRenderer d;
|
||||||
|
|
||||||
|
@ -136,6 +142,7 @@ struct GBAVideoGLRenderer {
|
||||||
|
|
||||||
GLuint fbo[GBA_GL_FBO_MAX];
|
GLuint fbo[GBA_GL_FBO_MAX];
|
||||||
GLuint layers[GBA_GL_TEX_MAX];
|
GLuint layers[GBA_GL_TEX_MAX];
|
||||||
|
GLuint vbo;
|
||||||
|
|
||||||
GLuint outputTex;
|
GLuint outputTex;
|
||||||
|
|
||||||
|
@ -148,15 +155,10 @@ struct GBAVideoGLRenderer {
|
||||||
GLuint vramTex;
|
GLuint vramTex;
|
||||||
unsigned vramDirty;
|
unsigned vramDirty;
|
||||||
|
|
||||||
GLuint bgProgram[6];
|
struct GBAVideoGLShader bgShader[6];
|
||||||
GLuint bgUniforms[6][GBA_GL_UNIFORM_MAX];
|
struct GBAVideoGLShader objShader[2];
|
||||||
GLuint objProgram[2];
|
struct GBAVideoGLShader compositeShader;
|
||||||
GLuint objUniforms[2][GBA_GL_UNIFORM_MAX];
|
struct GBAVideoGLShader finalizeShader;
|
||||||
|
|
||||||
GLuint compositeProgram;
|
|
||||||
GLuint compositeUniforms[GBA_GL_UNIFORM_MAX];
|
|
||||||
GLuint finalizeProgram;
|
|
||||||
GLuint finalizeUniforms[GBA_GL_UNIFORM_MAX];
|
|
||||||
|
|
||||||
GBARegisterDISPCNT dispcnt;
|
GBARegisterDISPCNT dispcnt;
|
||||||
|
|
||||||
|
|
|
@ -399,7 +399,10 @@ void GBAVideoGLRendererCreate(struct GBAVideoGLRenderer* renderer) {
|
||||||
renderer->scale = 1;
|
renderer->scale = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _compileShader(struct GBAVideoGLRenderer* glRenderer, GLuint program, const char** shaderBuffer, int shaderBufferLines, GLuint vs, char* log) {
|
void _compileShader(struct GBAVideoGLRenderer* glRenderer, struct GBAVideoGLShader* shader, const char** shaderBuffer, int shaderBufferLines, GLuint vs, const struct GBAVideoGLUniform* uniforms, char* log) {
|
||||||
|
GLuint program = glCreateProgram();
|
||||||
|
shader->program = program;
|
||||||
|
|
||||||
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
|
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
|
||||||
glAttachShader(program, vs);
|
glAttachShader(program, vs);
|
||||||
glAttachShader(program, fs);
|
glAttachShader(program, fs);
|
||||||
|
@ -419,6 +422,18 @@ void _compileShader(struct GBAVideoGLRenderer* glRenderer, GLuint program, const
|
||||||
glBindFragDataLocation(program, 0, "color");
|
glBindFragDataLocation(program, 0, "color");
|
||||||
glBindFragDataLocation(program, 1, "flags");
|
glBindFragDataLocation(program, 1, "flags");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
glGenVertexArrays(1, &shader->vao);
|
||||||
|
glBindVertexArray(shader->vao);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, glRenderer->vbo);
|
||||||
|
GLuint positionLocation = glGetAttribLocation(program, "position");
|
||||||
|
glVertexAttribPointer(positionLocation, 2, GL_INT, GL_FALSE, 0, NULL);
|
||||||
|
glEnableVertexAttribArray(positionLocation);
|
||||||
|
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; uniforms[i].name; ++i) {
|
||||||
|
shader->uniforms[uniforms[i].type] = glGetUniformLocation(program, uniforms[i].name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _initFramebufferTexture(GLuint tex, GLenum format, GLenum attachment, int scale) {
|
static void _initFramebufferTexture(GLuint tex, GLenum format, GLenum attachment, int scale) {
|
||||||
|
@ -431,13 +446,6 @@ static void _initFramebufferTexture(GLuint tex, GLenum format, GLenum attachment
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, tex, 0);
|
glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, tex, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _lookupUniforms(GLuint program, GLuint* out, const struct GBAVideoGLUniform* uniforms) {
|
|
||||||
size_t i;
|
|
||||||
for (i = 0; uniforms[i].name; ++i) {
|
|
||||||
out[uniforms[i].type] = glGetUniformLocation(program, uniforms[i].name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GBAVideoGLRendererInit(struct GBAVideoRenderer* renderer) {
|
void GBAVideoGLRendererInit(struct GBAVideoRenderer* renderer) {
|
||||||
struct GBAVideoGLRenderer* glRenderer = (struct GBAVideoGLRenderer*) renderer;
|
struct GBAVideoGLRenderer* glRenderer = (struct GBAVideoGLRenderer*) renderer;
|
||||||
glGenFramebuffers(GBA_GL_FBO_MAX, glRenderer->fbo);
|
glGenFramebuffers(GBA_GL_FBO_MAX, glRenderer->fbo);
|
||||||
|
@ -472,6 +480,10 @@ void GBAVideoGLRendererInit(struct GBAVideoRenderer* renderer) {
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
|
glGenBuffers(1, &glRenderer->vbo);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, glRenderer->vbo);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(_vertices), _vertices, GL_STATIC_DRAW);
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < 4; ++i) {
|
for (i = 0; i < 4; ++i) {
|
||||||
struct GBAVideoGLBackground* bg = &glRenderer->bg[i];
|
struct GBAVideoGLBackground* bg = &glRenderer->bg[i];
|
||||||
|
@ -505,17 +517,6 @@ void GBAVideoGLRendererInit(struct GBAVideoRenderer* renderer) {
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
glRenderer->compositeProgram = glCreateProgram();
|
|
||||||
glRenderer->finalizeProgram = glCreateProgram();
|
|
||||||
glRenderer->objProgram[0] = glCreateProgram();
|
|
||||||
glRenderer->objProgram[1] = glCreateProgram();
|
|
||||||
glRenderer->bgProgram[0] = glCreateProgram();
|
|
||||||
glRenderer->bgProgram[1] = glCreateProgram();
|
|
||||||
glRenderer->bgProgram[2] = glCreateProgram();
|
|
||||||
glRenderer->bgProgram[3] = glCreateProgram();
|
|
||||||
glRenderer->bgProgram[4] = glCreateProgram();
|
|
||||||
glRenderer->bgProgram[5] = glCreateProgram();
|
|
||||||
|
|
||||||
char log[1024];
|
char log[1024];
|
||||||
const GLchar* shaderBuffer[8];
|
const GLchar* shaderBuffer[8];
|
||||||
shaderBuffer[0] = _gl3Header;
|
shaderBuffer[0] = _gl3Header;
|
||||||
|
@ -532,51 +533,44 @@ void GBAVideoGLRendererInit(struct GBAVideoRenderer* renderer) {
|
||||||
shaderBuffer[1] = _renderMode0;
|
shaderBuffer[1] = _renderMode0;
|
||||||
|
|
||||||
shaderBuffer[2] = _renderTile16;
|
shaderBuffer[2] = _renderTile16;
|
||||||
_compileShader(glRenderer, glRenderer->bgProgram[0], shaderBuffer, 3, vs, log);
|
_compileShader(glRenderer, &glRenderer->bgShader[0], shaderBuffer, 3, vs, _uniformsMode0, log);
|
||||||
_lookupUniforms(glRenderer->bgProgram[0], glRenderer->bgUniforms[0], _uniformsMode0);
|
|
||||||
|
|
||||||
shaderBuffer[2] = _renderTile256;
|
shaderBuffer[2] = _renderTile256;
|
||||||
_compileShader(glRenderer, glRenderer->bgProgram[1], shaderBuffer, 3, vs, log);
|
_compileShader(glRenderer, &glRenderer->bgShader[1], shaderBuffer, 3, vs, _uniformsMode0, log);
|
||||||
_lookupUniforms(glRenderer->bgProgram[1], glRenderer->bgUniforms[1], _uniformsMode0);
|
|
||||||
|
|
||||||
shaderBuffer[1] = _renderMode2;
|
shaderBuffer[1] = _renderMode2;
|
||||||
|
|
||||||
shaderBuffer[2] = _fetchTileOverflow;
|
shaderBuffer[2] = _fetchTileOverflow;
|
||||||
_compileShader(glRenderer, glRenderer->bgProgram[2], shaderBuffer, 3, vs, log);
|
_compileShader(glRenderer, &glRenderer->bgShader[2], shaderBuffer, 3, vs, _uniformsMode2, log);
|
||||||
_lookupUniforms(glRenderer->bgProgram[2], glRenderer->bgUniforms[2], _uniformsMode2);
|
|
||||||
|
|
||||||
shaderBuffer[2] = _fetchTileNoOverflow;
|
shaderBuffer[2] = _fetchTileNoOverflow;
|
||||||
_compileShader(glRenderer, glRenderer->bgProgram[3], shaderBuffer, 3, vs, log);
|
_compileShader(glRenderer, &glRenderer->bgShader[3], shaderBuffer, 3, vs, _uniformsMode2, log);
|
||||||
_lookupUniforms(glRenderer->bgProgram[3], glRenderer->bgUniforms[3], _uniformsMode2);
|
|
||||||
|
|
||||||
shaderBuffer[1] = _renderObj;
|
shaderBuffer[1] = _renderObj;
|
||||||
|
|
||||||
shaderBuffer[2] = _renderTile16;
|
shaderBuffer[2] = _renderTile16;
|
||||||
_compileShader(glRenderer, glRenderer->objProgram[0], shaderBuffer, 3, vs, log);
|
_compileShader(glRenderer, &glRenderer->objShader[0], shaderBuffer, 3, vs, _uniformsObj, log);
|
||||||
_lookupUniforms(glRenderer->objProgram[0], glRenderer->objUniforms[0], _uniformsObj);
|
|
||||||
#ifndef BUILD_GLES3
|
#ifndef BUILD_GLES3
|
||||||
glBindFragDataLocation(glRenderer->objProgram[0], 2, "window");
|
glBindFragDataLocation(glRenderer->objShader[0].program, 2, "window");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
shaderBuffer[2] = _renderTile256;
|
shaderBuffer[2] = _renderTile256;
|
||||||
_compileShader(glRenderer, glRenderer->objProgram[1], shaderBuffer, 3, vs, log);
|
_compileShader(glRenderer, &glRenderer->objShader[1], shaderBuffer, 3, vs, _uniformsObj, log);
|
||||||
_lookupUniforms(glRenderer->objProgram[1], glRenderer->objUniforms[1], _uniformsObj);
|
|
||||||
#ifndef BUILD_GLES3
|
#ifndef BUILD_GLES3
|
||||||
glBindFragDataLocation(glRenderer->objProgram[1], 2, "window");
|
glBindFragDataLocation(glRenderer->objShader[1].program, 2, "window");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
shaderBuffer[1] = _composite;
|
shaderBuffer[1] = _composite;
|
||||||
_compileShader(glRenderer, glRenderer->compositeProgram, shaderBuffer, 2, vs, log);
|
_compileShader(glRenderer, &glRenderer->compositeShader, shaderBuffer, 2, vs, _uniformsComposite, log);
|
||||||
_lookupUniforms(glRenderer->compositeProgram, glRenderer->compositeUniforms, _uniformsComposite);
|
|
||||||
#ifndef BUILD_GLES3
|
#ifndef BUILD_GLES3
|
||||||
glBindFragDataLocation(glRenderer->compositeProgram, 2, "oldColor");
|
glBindFragDataLocation(glRenderer->compositeShader.program, 2, "oldColor");
|
||||||
glBindFragDataLocation(glRenderer->compositeProgram, 3, "oldFlags");
|
glBindFragDataLocation(glRenderer->compositeShader.program, 3, "oldFlags");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
shaderBuffer[1] = _finalize;
|
shaderBuffer[1] = _finalize;
|
||||||
_compileShader(glRenderer, glRenderer->finalizeProgram, shaderBuffer, 2, vs, log);
|
_compileShader(glRenderer, &glRenderer->finalizeShader, shaderBuffer, 2, vs, _uniformsFinalize, log);
|
||||||
_lookupUniforms(glRenderer->finalizeProgram, glRenderer->finalizeUniforms, _uniformsFinalize);
|
|
||||||
|
|
||||||
|
glBindVertexArray(0);
|
||||||
glDeleteShader(vs);
|
glDeleteShader(vs);
|
||||||
|
|
||||||
GBAVideoGLRendererReset(renderer);
|
GBAVideoGLRendererReset(renderer);
|
||||||
|
@ -588,16 +582,6 @@ void GBAVideoGLRendererDeinit(struct GBAVideoRenderer* renderer) {
|
||||||
glDeleteTextures(GBA_GL_TEX_MAX, glRenderer->layers);
|
glDeleteTextures(GBA_GL_TEX_MAX, glRenderer->layers);
|
||||||
glDeleteTextures(1, &glRenderer->paletteTex);
|
glDeleteTextures(1, &glRenderer->paletteTex);
|
||||||
glDeleteTextures(1, &glRenderer->vramTex);
|
glDeleteTextures(1, &glRenderer->vramTex);
|
||||||
|
|
||||||
glDeleteProgram(glRenderer->bgProgram[0]);
|
|
||||||
glDeleteProgram(glRenderer->bgProgram[1]);
|
|
||||||
glDeleteProgram(glRenderer->bgProgram[2]);
|
|
||||||
glDeleteProgram(glRenderer->bgProgram[3]);
|
|
||||||
glDeleteProgram(glRenderer->bgProgram[4]);
|
|
||||||
glDeleteProgram(glRenderer->bgProgram[5]);
|
|
||||||
glDeleteProgram(glRenderer->objProgram[0]);
|
|
||||||
glDeleteProgram(glRenderer->objProgram[1]);
|
|
||||||
glDeleteProgram(glRenderer->compositeProgram);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBAVideoGLRendererReset(struct GBAVideoRenderer* renderer) {
|
void GBAVideoGLRendererReset(struct GBAVideoRenderer* renderer) {
|
||||||
|
@ -1075,11 +1059,12 @@ static void _compositeLayer(struct GBAVideoGLRenderer* renderer, GLuint tex, GLu
|
||||||
if ((y & 0x1F) != 0x1F) {
|
if ((y & 0x1F) != 0x1F) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const GLuint* uniforms = renderer->compositeUniforms;
|
const GLuint* uniforms = renderer->compositeShader.uniforms;
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, renderer->fbo[GBA_GL_FBO_COMPOSITE]);
|
glBindFramebuffer(GL_FRAMEBUFFER, renderer->fbo[GBA_GL_FBO_COMPOSITE]);
|
||||||
glViewport(0, 0, GBA_VIDEO_HORIZONTAL_PIXELS * renderer->scale, GBA_VIDEO_VERTICAL_PIXELS * renderer->scale);
|
glViewport(0, 0, GBA_VIDEO_HORIZONTAL_PIXELS * renderer->scale, GBA_VIDEO_VERTICAL_PIXELS * renderer->scale);
|
||||||
glScissor(0, (y & ~0x1F) * renderer->scale, GBA_VIDEO_HORIZONTAL_PIXELS * renderer->scale, 0x20 * renderer->scale);
|
glScissor(0, (y & ~0x1F) * renderer->scale, GBA_VIDEO_HORIZONTAL_PIXELS * renderer->scale, 0x20 * renderer->scale);
|
||||||
glUseProgram(renderer->compositeProgram);
|
glUseProgram(renderer->compositeShader.program);
|
||||||
|
glBindVertexArray(renderer->compositeShader.vao);
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, tex);
|
glBindTexture(GL_TEXTURE_2D, tex);
|
||||||
glActiveTexture(GL_TEXTURE0 + 1);
|
glActiveTexture(GL_TEXTURE0 + 1);
|
||||||
|
@ -1102,23 +1087,21 @@ static void _compositeLayer(struct GBAVideoGLRenderer* renderer, GLuint tex, GLu
|
||||||
glUniform1i(uniforms[GBA_GL_COMPOSITE_OLDLAYERFLAGS], 3);
|
glUniform1i(uniforms[GBA_GL_COMPOSITE_OLDLAYERFLAGS], 3);
|
||||||
glUniform1i(uniforms[GBA_GL_COMPOSITE_OLDOLDFLAGS], 4);
|
glUniform1i(uniforms[GBA_GL_COMPOSITE_OLDOLDFLAGS], 4);
|
||||||
glUniform1i(uniforms[GBA_GL_COMPOSITE_WINDOW], 5);
|
glUniform1i(uniforms[GBA_GL_COMPOSITE_WINDOW], 5);
|
||||||
glVertexAttribPointer(0, 2, GL_INT, GL_FALSE, 0, _vertices);
|
|
||||||
glEnableVertexAttribArray(0);
|
|
||||||
glDrawBuffers(4, (GLenum[]) { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3 });
|
glDrawBuffers(4, (GLenum[]) { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3 });
|
||||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||||
glDrawBuffers(1, (GLenum[]) { GL_COLOR_ATTACHMENT0 });
|
glDrawBuffers(1, (GLenum[]) { GL_COLOR_ATTACHMENT0 });
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _finalizeLayers(struct GBAVideoGLRenderer* renderer, int y) {
|
void _finalizeLayers(struct GBAVideoGLRenderer* renderer, int y) {
|
||||||
if ((y & 0x1F) != 0x1F) {
|
if ((y & 0x1F) != 0x1F) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const GLuint* uniforms = renderer->finalizeUniforms;
|
const GLuint* uniforms = renderer->finalizeShader.uniforms;
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, renderer->fbo[GBA_GL_FBO_OUTPUT]);
|
glBindFramebuffer(GL_FRAMEBUFFER, renderer->fbo[GBA_GL_FBO_OUTPUT]);
|
||||||
glViewport(0, 0, GBA_VIDEO_HORIZONTAL_PIXELS * renderer->scale, GBA_VIDEO_VERTICAL_PIXELS * renderer->scale);
|
glViewport(0, 0, GBA_VIDEO_HORIZONTAL_PIXELS * renderer->scale, GBA_VIDEO_VERTICAL_PIXELS * renderer->scale);
|
||||||
glScissor(0, (y & ~0x1F) * renderer->scale, GBA_VIDEO_HORIZONTAL_PIXELS * renderer->scale, 0x20 * renderer->scale);
|
glScissor(0, (y & ~0x1F) * renderer->scale, GBA_VIDEO_HORIZONTAL_PIXELS * renderer->scale, 0x20 * renderer->scale);
|
||||||
glUseProgram(renderer->finalizeProgram);
|
glUseProgram(renderer->finalizeShader.program);
|
||||||
|
glBindVertexArray(renderer->finalizeShader.vao);
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, renderer->layers[GBA_GL_TEX_COMPOSITE_COLOR]);
|
glBindTexture(GL_TEXTURE_2D, renderer->layers[GBA_GL_TEX_COMPOSITE_COLOR]);
|
||||||
glActiveTexture(GL_TEXTURE0 + 1);
|
glActiveTexture(GL_TEXTURE0 + 1);
|
||||||
|
@ -1134,8 +1117,6 @@ void _finalizeLayers(struct GBAVideoGLRenderer* renderer, int y) {
|
||||||
glUniform1i(uniforms[GBA_GL_FINALIZE_LAYERFLAGS], 1);
|
glUniform1i(uniforms[GBA_GL_FINALIZE_LAYERFLAGS], 1);
|
||||||
glUniform1i(uniforms[GBA_GL_FINALIZE_OLDLAYER], 2);
|
glUniform1i(uniforms[GBA_GL_FINALIZE_OLDLAYER], 2);
|
||||||
glUniform1i(uniforms[GBA_GL_FINALIZE_OLDFLAGS], 3);
|
glUniform1i(uniforms[GBA_GL_FINALIZE_OLDFLAGS], 3);
|
||||||
glVertexAttribPointer(0, 2, GL_INT, GL_FALSE, 0, _vertices);
|
|
||||||
glEnableVertexAttribArray(0);
|
|
||||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
}
|
}
|
||||||
|
@ -1167,11 +1148,13 @@ void GBAVideoGLRendererDrawSprite(struct GBAVideoGLRenderer* renderer, struct GB
|
||||||
|
|
||||||
enum GBAVideoBlendEffect blendEffect = GBAObjAttributesAGetMode(sprite->a) == OBJ_MODE_SEMITRANSPARENT ? BLEND_ALPHA : renderer->blendEffect;
|
enum GBAVideoBlendEffect blendEffect = GBAObjAttributesAGetMode(sprite->a) == OBJ_MODE_SEMITRANSPARENT ? BLEND_ALPHA : renderer->blendEffect;
|
||||||
|
|
||||||
const GLuint* uniforms = renderer->objUniforms[GBAObjAttributesAGet256Color(sprite->a)];
|
const struct GBAVideoGLShader* shader = &renderer->objShader[GBAObjAttributesAGet256Color(sprite->a)];
|
||||||
|
const GLuint* uniforms = shader->uniforms;
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, renderer->fbo[GBA_GL_FBO_OBJ]);
|
glBindFramebuffer(GL_FRAMEBUFFER, renderer->fbo[GBA_GL_FBO_OBJ]);
|
||||||
glViewport(x * renderer->scale, spriteY * renderer->scale, totalWidth * renderer->scale, totalHeight * renderer->scale);
|
glViewport(x * renderer->scale, spriteY * renderer->scale, totalWidth * renderer->scale, totalHeight * renderer->scale);
|
||||||
glScissor(x * renderer->scale, y * renderer->scale, totalWidth * renderer->scale, renderer->scale);
|
glScissor(x * renderer->scale, y * renderer->scale, totalWidth * renderer->scale, renderer->scale);
|
||||||
glUseProgram(renderer->objProgram[GBAObjAttributesAGet256Color(sprite->a)]);
|
glUseProgram(shader->program);
|
||||||
|
glBindVertexArray(shader->vao);
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, renderer->vramTex);
|
glBindTexture(GL_TEXTURE_2D, renderer->vramTex);
|
||||||
glActiveTexture(GL_TEXTURE0 + 1);
|
glActiveTexture(GL_TEXTURE0 + 1);
|
||||||
|
@ -1198,8 +1181,6 @@ void GBAVideoGLRendererDrawSprite(struct GBAVideoGLRenderer* renderer, struct GB
|
||||||
glUniformMatrix2fv(uniforms[GBA_GL_OBJ_TRANSFORM], 1, GL_FALSE, (GLfloat[]) { 1.f, 0, 0, 1.f });
|
glUniformMatrix2fv(uniforms[GBA_GL_OBJ_TRANSFORM], 1, GL_FALSE, (GLfloat[]) { 1.f, 0, 0, 1.f });
|
||||||
}
|
}
|
||||||
glUniform4i(uniforms[GBA_GL_OBJ_DIMS], width, height, totalWidth, totalHeight);
|
glUniform4i(uniforms[GBA_GL_OBJ_DIMS], width, height, totalWidth, totalHeight);
|
||||||
glVertexAttribPointer(0, 2, GL_INT, GL_FALSE, 0, _vertices);
|
|
||||||
glEnableVertexAttribArray(0);
|
|
||||||
if (GBAObjAttributesAGetMode(sprite->a) == OBJ_MODE_OBJWIN) {
|
if (GBAObjAttributesAGetMode(sprite->a) == OBJ_MODE_OBJWIN) {
|
||||||
int window = ~renderer->objwin & 0xFF;
|
int window = ~renderer->objwin & 0xFF;
|
||||||
glUniform3f(uniforms[GBA_GL_OBJ_OBJWIN], 1, (window & 0xF) / 32.f, (window >> 4) / 32.f);
|
glUniform3f(uniforms[GBA_GL_OBJ_OBJWIN], 1, (window & 0xF) / 32.f, (window >> 4) / 32.f);
|
||||||
|
@ -1220,11 +1201,14 @@ void GBAVideoGLRendererDrawBackgroundMode0(struct GBAVideoGLRenderer* renderer,
|
||||||
} else if (background->size == 3) {
|
} else if (background->size == 3) {
|
||||||
yBase += (inY & 0x100) << 1;
|
yBase += (inY & 0x100) << 1;
|
||||||
}
|
}
|
||||||
const GLuint* uniforms = renderer->bgUniforms[background->multipalette ? 1 : 0];
|
|
||||||
|
const struct GBAVideoGLShader* shader = &renderer->bgShader[background->multipalette ? 1 : 0];
|
||||||
|
const GLuint* uniforms = shader->uniforms;
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, background->fbo);
|
glBindFramebuffer(GL_FRAMEBUFFER, background->fbo);
|
||||||
glViewport(0, 0, GBA_VIDEO_HORIZONTAL_PIXELS * renderer->scale, GBA_VIDEO_VERTICAL_PIXELS * renderer->scale);
|
glViewport(0, 0, GBA_VIDEO_HORIZONTAL_PIXELS * renderer->scale, GBA_VIDEO_VERTICAL_PIXELS * renderer->scale);
|
||||||
glScissor(0, y * renderer->scale, GBA_VIDEO_HORIZONTAL_PIXELS * renderer->scale, renderer->scale);
|
glScissor(0, y * renderer->scale, GBA_VIDEO_HORIZONTAL_PIXELS * renderer->scale, renderer->scale);
|
||||||
glUseProgram(renderer->bgProgram[background->multipalette ? 1 : 0]);
|
glUseProgram(shader->program);
|
||||||
|
glBindVertexArray(shader->vao);
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, renderer->vramTex);
|
glBindTexture(GL_TEXTURE_2D, renderer->vramTex);
|
||||||
glActiveTexture(GL_TEXTURE0 + 1);
|
glActiveTexture(GL_TEXTURE0 + 1);
|
||||||
|
@ -1240,8 +1224,6 @@ void GBAVideoGLRendererDrawBackgroundMode0(struct GBAVideoGLRenderer* renderer,
|
||||||
glUniform4i(uniforms[GBA_GL_BG_INFLAGS], (background->priority << 3) + (background->index << 1) + 1,
|
glUniform4i(uniforms[GBA_GL_BG_INFLAGS], (background->priority << 3) + (background->index << 1) + 1,
|
||||||
background->target1 | (background->target2 * 2) | (renderer->blendEffect * 4),
|
background->target1 | (background->target2 * 2) | (renderer->blendEffect * 4),
|
||||||
renderer->blendEffect == BLEND_ALPHA ? renderer->blda : renderer->bldy, renderer->bldb);
|
renderer->blendEffect == BLEND_ALPHA ? renderer->blda : renderer->bldy, renderer->bldb);
|
||||||
glVertexAttribPointer(0, 2, GL_INT, GL_FALSE, 0, _vertices);
|
|
||||||
glEnableVertexAttribArray(0);
|
|
||||||
glDrawBuffers(2, (GLenum[]) { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 });
|
glDrawBuffers(2, (GLenum[]) { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 });
|
||||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||||
glDrawBuffers(1, (GLenum[]) { GL_COLOR_ATTACHMENT0 });
|
glDrawBuffers(1, (GLenum[]) { GL_COLOR_ATTACHMENT0 });
|
||||||
|
@ -1250,11 +1232,13 @@ void GBAVideoGLRendererDrawBackgroundMode0(struct GBAVideoGLRenderer* renderer,
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBAVideoGLRendererDrawBackgroundMode2(struct GBAVideoGLRenderer* renderer, struct GBAVideoGLBackground* background, int y) {
|
void GBAVideoGLRendererDrawBackgroundMode2(struct GBAVideoGLRenderer* renderer, struct GBAVideoGLBackground* background, int y) {
|
||||||
const GLuint* uniforms = renderer->bgUniforms[background->overflow ? 2 : 3];
|
const struct GBAVideoGLShader* shader = &renderer->bgShader[background->overflow ? 2 : 3];
|
||||||
|
const GLuint* uniforms = shader->uniforms;
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, background->fbo);
|
glBindFramebuffer(GL_FRAMEBUFFER, background->fbo);
|
||||||
glViewport(0, 0, GBA_VIDEO_HORIZONTAL_PIXELS * renderer->scale, GBA_VIDEO_VERTICAL_PIXELS * renderer->scale);
|
glViewport(0, 0, GBA_VIDEO_HORIZONTAL_PIXELS * renderer->scale, GBA_VIDEO_VERTICAL_PIXELS * renderer->scale);
|
||||||
glScissor(0, y * renderer->scale, GBA_VIDEO_HORIZONTAL_PIXELS * renderer->scale, renderer->scale);
|
glScissor(0, y * renderer->scale, GBA_VIDEO_HORIZONTAL_PIXELS * renderer->scale, renderer->scale);
|
||||||
glUseProgram(renderer->bgProgram[background->overflow ? 2 : 3]);
|
glUseProgram(shader->program);
|
||||||
|
glBindVertexArray(shader->vao);
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, renderer->vramTex);
|
glBindTexture(GL_TEXTURE_2D, renderer->vramTex);
|
||||||
glActiveTexture(GL_TEXTURE0 + 1);
|
glActiveTexture(GL_TEXTURE0 + 1);
|
||||||
|
@ -1296,8 +1280,6 @@ void GBAVideoGLRendererDrawBackgroundMode2(struct GBAVideoGLRenderer* renderer,
|
||||||
background->affine[0].dx, background->affine[0].dy,
|
background->affine[0].dx, background->affine[0].dy,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
glVertexAttribPointer(0, 2, GL_INT, GL_FALSE, 0, _vertices);
|
|
||||||
glEnableVertexAttribArray(0);
|
|
||||||
glDrawBuffers(2, (GLenum[]) { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 });
|
glDrawBuffers(2, (GLenum[]) { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 });
|
||||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||||
glDrawBuffers(1, (GLenum[]) { GL_COLOR_ATTACHMENT0 });
|
glDrawBuffers(1, (GLenum[]) { GL_COLOR_ATTACHMENT0 });
|
||||||
|
|
|
@ -84,6 +84,10 @@ static void mGLES2ContextInit(struct VideoBackend* v, WHandle handle) {
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
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_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
glGenBuffers(1, &context->vbo);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, context->vbo);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(_vertices), _vertices, GL_STATIC_DRAW);
|
||||||
|
|
||||||
glClearColor(0.f, 0.f, 0.f, 1.f);
|
glClearColor(0.f, 0.f, 0.f, 1.f);
|
||||||
|
|
||||||
struct mGLES2Uniform* uniforms = malloc(sizeof(struct mGLES2Uniform) * 4);
|
struct mGLES2Uniform* uniforms = malloc(sizeof(struct mGLES2Uniform) * 4);
|
||||||
|
@ -159,6 +163,7 @@ static void mGLES2ContextSetDimensions(struct VideoBackend* v, unsigned width, u
|
||||||
static void mGLES2ContextDeinit(struct VideoBackend* v) {
|
static void mGLES2ContextDeinit(struct VideoBackend* v) {
|
||||||
struct mGLES2Context* context = (struct mGLES2Context*) v;
|
struct mGLES2Context* context = (struct mGLES2Context*) v;
|
||||||
glDeleteTextures(1, &context->tex);
|
glDeleteTextures(1, &context->tex);
|
||||||
|
glDeleteBuffers(1, &context->vbo);
|
||||||
mGLES2ShaderDeinit(&context->initialShader);
|
mGLES2ShaderDeinit(&context->initialShader);
|
||||||
mGLES2ShaderDeinit(&context->finalShader);
|
mGLES2ShaderDeinit(&context->finalShader);
|
||||||
free(context->initialShader.uniforms);
|
free(context->initialShader.uniforms);
|
||||||
|
@ -239,8 +244,7 @@ void _drawShader(struct mGLES2Context* context, struct mGLES2Shader* shader) {
|
||||||
glUseProgram(shader->program);
|
glUseProgram(shader->program);
|
||||||
glUniform1i(shader->texLocation, 0);
|
glUniform1i(shader->texLocation, 0);
|
||||||
glUniform2f(shader->texSizeLocation, context->d.width - padW, context->d.height - padH);
|
glUniform2f(shader->texSizeLocation, context->d.width - padW, context->d.height - padH);
|
||||||
glVertexAttribPointer(shader->positionLocation, 2, GL_FLOAT, GL_FALSE, 0, _vertices);
|
glBindVertexArray(shader->vao);
|
||||||
glEnableVertexAttribArray(shader->positionLocation);
|
|
||||||
size_t u;
|
size_t u;
|
||||||
for (u = 0; u < shader->nUniforms; ++u) {
|
for (u = 0; u < shader->nUniforms; ++u) {
|
||||||
struct mGLES2Uniform* uniform = &shader->uniforms[u];
|
struct mGLES2Uniform* uniform = &shader->uniforms[u];
|
||||||
|
@ -420,6 +424,13 @@ void mGLES2ShaderInit(struct mGLES2Shader* shader, const char* vs, const char* f
|
||||||
for (i = 0; i < shader->nUniforms; ++i) {
|
for (i = 0; i < shader->nUniforms; ++i) {
|
||||||
shader->uniforms[i].location = glGetUniformLocation(shader->program, shader->uniforms[i].name);
|
shader->uniforms[i].location = glGetUniformLocation(shader->program, shader->uniforms[i].name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glGenVertexArrays(1, &shader->vao);
|
||||||
|
glBindVertexArray(shader->vao);
|
||||||
|
glVertexAttribPointer(shader->positionLocation, 2, GL_FLOAT, GL_FALSE, 0, NULL);
|
||||||
|
glEnableVertexAttribArray(shader->positionLocation);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,6 +439,7 @@ void mGLES2ShaderDeinit(struct mGLES2Shader* shader) {
|
||||||
glDeleteShader(shader->fragmentShader);
|
glDeleteShader(shader->fragmentShader);
|
||||||
glDeleteProgram(shader->program);
|
glDeleteProgram(shader->program);
|
||||||
glDeleteFramebuffers(1, &shader->fbo);
|
glDeleteFramebuffers(1, &shader->fbo);
|
||||||
|
glDeleteVertexArrays(1, &shader->vao);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mGLES2ShaderAttach(struct mGLES2Context* context, struct mGLES2Shader* shaders, size_t nShaders) {
|
void mGLES2ShaderAttach(struct mGLES2Context* context, struct mGLES2Shader* shaders, size_t nShaders) {
|
||||||
|
@ -443,7 +455,11 @@ void mGLES2ShaderAttach(struct mGLES2Context* context, struct mGLES2Shader* shad
|
||||||
for (i = 0; i < nShaders; ++i) {
|
for (i = 0; i < nShaders; ++i) {
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, context->shaders[i].fbo);
|
glBindFramebuffer(GL_FRAMEBUFFER, context->shaders[i].fbo);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
glBindVertexArray(context->shaders[i].vao);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, context->vbo);
|
||||||
}
|
}
|
||||||
|
glBindVertexArray(0);
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,7 @@ struct mGLES2Shader {
|
||||||
bool blend;
|
bool blend;
|
||||||
GLuint tex;
|
GLuint tex;
|
||||||
GLuint fbo;
|
GLuint fbo;
|
||||||
|
GLuint vao;
|
||||||
GLuint fragmentShader;
|
GLuint fragmentShader;
|
||||||
GLuint vertexShader;
|
GLuint vertexShader;
|
||||||
GLuint program;
|
GLuint program;
|
||||||
|
@ -77,8 +78,7 @@ struct mGLES2Context {
|
||||||
struct VideoBackend d;
|
struct VideoBackend d;
|
||||||
|
|
||||||
GLuint tex;
|
GLuint tex;
|
||||||
GLuint texLocation;
|
GLuint vbo;
|
||||||
GLuint positionLocation;
|
|
||||||
|
|
||||||
struct mGLES2Shader initialShader;
|
struct mGLES2Shader initialShader;
|
||||||
struct mGLES2Shader finalShader;
|
struct mGLES2Shader finalShader;
|
||||||
|
|
|
@ -227,7 +227,7 @@ PainterGL::PainterGL(VideoProxy* proxy, QWindow* surface, QOpenGLContext* parent
|
||||||
QStringList extensions = QString(reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS))).split(' ');
|
QStringList extensions = QString(reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS))).split(' ');
|
||||||
|
|
||||||
#ifdef BUILD_GLES2
|
#ifdef BUILD_GLES2
|
||||||
if (extensions.contains("GL_ARB_framebuffer_object") && majorVersion >= 2) {
|
if ((majorVersion == 2 && extensions.contains("GL_ARB_framebuffer_object")) || majorVersion > 2) {
|
||||||
gl2Backend = static_cast<mGLES2Context*>(malloc(sizeof(mGLES2Context)));
|
gl2Backend = static_cast<mGLES2Context*>(malloc(sizeof(mGLES2Context)));
|
||||||
mGLES2ContextCreate(gl2Backend);
|
mGLES2ContextCreate(gl2Backend);
|
||||||
m_backend = &gl2Backend->d;
|
m_backend = &gl2Backend->d;
|
||||||
|
@ -500,8 +500,8 @@ void PainterGL::clearShaders() {
|
||||||
if (!supportsShaders()) {
|
if (!supportsShaders()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!m_active) {
|
|
||||||
#ifdef BUILD_GLES2
|
#ifdef BUILD_GLES2
|
||||||
|
if (!m_active) {
|
||||||
m_gl->makeCurrent(m_surface);
|
m_gl->makeCurrent(m_surface);
|
||||||
#if defined(_WIN32) && defined(USE_EPOXY)
|
#if defined(_WIN32) && defined(USE_EPOXY)
|
||||||
epoxy_handle_external_wglMakeCurrent();
|
epoxy_handle_external_wglMakeCurrent();
|
||||||
|
|
Loading…
Reference in New Issue