GBA Video: Do not affect OBJ pixel priority when writing OBJWIN (fixes #1890)

This commit is contained in:
Vicki Pfau 2020-10-04 01:02:28 -07:00
parent e0ef6a51de
commit f734c2f6c7
2 changed files with 23 additions and 13 deletions

View File

@ -10,6 +10,7 @@ Emulation fixes:
- GBA Video: Invalidate map cache when modifying BGCNT (fixes mgba.io/i/1846) - GBA Video: Invalidate map cache when modifying BGCNT (fixes mgba.io/i/1846)
- GBA Video: Don't draw sprites using unmapped VRAM in GL renderer (fixes mgba.io/i/1865) - GBA Video: Don't draw sprites using unmapped VRAM in GL renderer (fixes mgba.io/i/1865)
- GBA Video: Fix rare regression blending semitransparent sprites (fixes mgba.io/i/1876) - GBA Video: Fix rare regression blending semitransparent sprites (fixes mgba.io/i/1876)
- GBA Video: Do not affect OBJ pixel priority when writing OBJWIN (fixes mgba.io/i/1890)
Other fixes: Other fixes:
- 3DS: Redo video sync to be more precise - 3DS: Redo video sync to be more precise
- 3DS: Fix crash with libctru 2.0 when exiting - 3DS: Fix crash with libctru 2.0 when exiting

View File

@ -916,6 +916,7 @@ void GBAVideoGLRendererDeinit(struct GBAVideoRenderer* renderer) {
_deleteShader(&glRenderer->bgShader[3]); _deleteShader(&glRenderer->bgShader[3]);
_deleteShader(&glRenderer->objShader[0]); _deleteShader(&glRenderer->objShader[0]);
_deleteShader(&glRenderer->objShader[1]); _deleteShader(&glRenderer->objShader[1]);
_deleteShader(&glRenderer->objShader[2]);
_deleteShader(&glRenderer->finalizeShader); _deleteShader(&glRenderer->finalizeShader);
int i; int i;
@ -1705,12 +1706,18 @@ void GBAVideoGLRendererDrawSprite(struct GBAVideoGLRenderer* renderer, struct GB
} }
glUniform4i(uniforms[GBA_GL_OBJ_DIMS], width, height, totalWidth, totalHeight); glUniform4i(uniforms[GBA_GL_OBJ_DIMS], width, height, totalWidth, totalHeight);
if (GBAObjAttributesAGetMode(sprite->a) == OBJ_MODE_OBJWIN) { if (GBAObjAttributesAGetMode(sprite->a) == OBJ_MODE_OBJWIN) {
// OBJWIN writes do not affect pixel priority
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glStencilMask(GL_FALSE);
int window = renderer->objwin & 0x3F; int window = renderer->objwin & 0x3F;
glUniform4i(uniforms[GBA_GL_OBJ_OBJWIN], 1, window, renderer->bldb, renderer->bldy); glUniform4i(uniforms[GBA_GL_OBJ_OBJWIN], 1, window, renderer->bldb, renderer->bldy);
glDrawBuffers(3, (GLenum[]) { GL_NONE, GL_NONE, GL_COLOR_ATTACHMENT2 }); glDrawBuffers(3, (GLenum[]) { GL_NONE, GL_NONE, GL_COLOR_ATTACHMENT2 });
} else { } else {
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glStencilMask(GL_TRUE);
glStencilFunc(GL_ALWAYS, 1, 1);
glUniform4i(uniforms[GBA_GL_OBJ_OBJWIN], 0, 0, 0, 0); glUniform4i(uniforms[GBA_GL_OBJ_OBJWIN], 0, 0, 0, 0);
glDrawBuffers(2, (GLenum[]) { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 }); glDrawBuffers(2, (GLenum[]) { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 });
} }
@ -1723,11 +1730,12 @@ void GBAVideoGLRendererDrawSprite(struct GBAVideoGLRenderer* renderer, struct GB
} else { } else {
glUniform4i(uniforms[GBA_GL_OBJ_MOSAIC], 0, 0, 0, 0); glUniform4i(uniforms[GBA_GL_OBJ_MOSAIC], 0, 0, 0, 0);
} }
glStencilFunc(GL_ALWAYS, 1, 1);
if (GBAObjAttributesAGetMode(sprite->a) != OBJ_MODE_OBJWIN || GBARegisterDISPCNTIsObjwinEnable(renderer->dispcnt)) { if (GBAObjAttributesAGetMode(sprite->a) != OBJ_MODE_OBJWIN || GBARegisterDISPCNTIsObjwinEnable(renderer->dispcnt)) {
glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
} }
if (GBAObjAttributesAGetMode(sprite->a) != OBJ_MODE_OBJWIN) {
// Update the pixel priority for already-written pixels
shader = &renderer->objShader[2]; shader = &renderer->objShader[2];
uniforms = shader->uniforms; uniforms = shader->uniforms;
glStencilFunc(GL_EQUAL, 1, 1); glStencilFunc(GL_EQUAL, 1, 1);
@ -1740,6 +1748,7 @@ void GBAVideoGLRendererDrawSprite(struct GBAVideoGLRenderer* renderer, struct GB
(renderer->target1Obj || GBAObjAttributesAGetMode(sprite->a) == OBJ_MODE_SEMITRANSPARENT) | (renderer->target2Obj * 2) | (renderer->blendEffect * 4), (renderer->target1Obj || GBAObjAttributesAGetMode(sprite->a) == OBJ_MODE_SEMITRANSPARENT) | (renderer->target2Obj * 2) | (renderer->blendEffect * 4),
renderer->blda, GBAObjAttributesAGetMode(sprite->a) == OBJ_MODE_SEMITRANSPARENT); renderer->blda, GBAObjAttributesAGetMode(sprite->a) == OBJ_MODE_SEMITRANSPARENT);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
glDrawBuffers(1, (GLenum[]) { GL_COLOR_ATTACHMENT0 }); glDrawBuffers(1, (GLenum[]) { GL_COLOR_ATTACHMENT0 });
} }