GBA Video: Implement layer placement for OpenGL renderer (fixes #1962)

This commit is contained in:
Vicki Pfau 2022-02-20 19:45:13 -08:00
parent 5f3cb2f72f
commit 7c8a06816b
4 changed files with 39 additions and 16 deletions

View File

@ -48,6 +48,7 @@ Misc:
- GB Video: Add default SGB border
- GBA: Automatically skip BIOS if ROM has invalid logo
- GBA DMA: Enhanced logging (closes mgba.io/i/2454)
- GBA Video: Implement layer placement for OpenGL renderer (fixes mgba.io/i/1962)
- mGUI: Add margin to right-aligned menu text (fixes mgba.io/i/871)
- Qt: Rearrange menus some
- Qt: Clean up cheats dialog

View File

@ -60,6 +60,8 @@ struct GBAVideoGLBackground {
uint16_t y;
int32_t refx;
int32_t refy;
int32_t offsetX;
int32_t offsetY;
struct GBAVideoGLAffine affine;
@ -142,6 +144,8 @@ struct GBAVideoGLRenderer {
int oamMax;
bool oamDirty;
struct GBAVideoRendererSprite sprites[128];
int16_t objOffsetX;
int16_t objOffsetY;
GLuint fbo[GBA_GL_FBO_MAX];
GLuint layers[GBA_GL_TEX_MAX];
@ -183,6 +187,8 @@ struct GBAVideoGLRenderer {
struct GBAVideoWindowRegion h;
struct GBAVideoWindowRegion v;
GBAWindowControl control;
int16_t offsetX;
int16_t offsetY;
} winN[2];
GLint winNHistory[2][GBA_VIDEO_VERTICAL_PIXELS * 4];

View File

@ -1105,15 +1105,29 @@ static void _GBACoreAdjustVideoLayer(struct mCore* core, size_t id, int32_t x, i
case GBA_LAYER_BG3:
gbacore->renderer.bg[id].offsetX = x;
gbacore->renderer.bg[id].offsetY = y;
#ifdef BUILD_GLES3
gbacore->glRenderer.bg[id].offsetX = x;
gbacore->glRenderer.bg[id].offsetY = y;
#endif
break;
case GBA_LAYER_OBJ:
gbacore->renderer.objOffsetX = x;
gbacore->renderer.objOffsetY = y;
gbacore->renderer.oamDirty = 1;
#ifdef BUILD_GLES3
gbacore->glRenderer.objOffsetX = x;
gbacore->glRenderer.objOffsetY = y;
gbacore->glRenderer.oamDirty = 1;
#endif
break;
case GBA_LAYER_WIN0:
case GBA_LAYER_WIN1:
gbacore->renderer.winN[id - GBA_LAYER_WIN0].offsetX = x;
gbacore->renderer.winN[id - GBA_LAYER_WIN0].offsetY = y;
#ifdef BUILD_GLES3
gbacore->glRenderer.winN[id - GBA_LAYER_WIN0].offsetX = x;
gbacore->glRenderer.winN[id - GBA_LAYER_WIN0].offsetY = y;
#endif
break;
default:
return;

View File

@ -1331,27 +1331,27 @@ void GBAVideoGLRendererDrawScanline(struct GBAVideoRenderer* renderer, int y) {
}
glRenderer->regsDirty = 0;
glRenderer->winNHistory[0][y * 4 + 0] = glRenderer->winN[0].h.start;
glRenderer->winNHistory[0][y * 4 + 1] = glRenderer->winN[0].h.end;
glRenderer->winNHistory[0][y * 4 + 2] = glRenderer->winN[0].v.start;
glRenderer->winNHistory[0][y * 4 + 3] = glRenderer->winN[0].v.end;
glRenderer->winNHistory[1][y * 4 + 0] = glRenderer->winN[1].h.start;
glRenderer->winNHistory[1][y * 4 + 1] = glRenderer->winN[1].h.end;
glRenderer->winNHistory[1][y * 4 + 2] = glRenderer->winN[1].v.start;
glRenderer->winNHistory[1][y * 4 + 3] = glRenderer->winN[1].v.end;
glRenderer->winNHistory[0][y * 4 + 0] = glRenderer->winN[0].h.start + glRenderer->winN[0].offsetX;
glRenderer->winNHistory[0][y * 4 + 1] = glRenderer->winN[0].h.end + glRenderer->winN[0].offsetX;
glRenderer->winNHistory[0][y * 4 + 2] = glRenderer->winN[0].v.start + glRenderer->winN[0].offsetY;
glRenderer->winNHistory[0][y * 4 + 3] = glRenderer->winN[0].v.end + glRenderer->winN[0].offsetY;
glRenderer->winNHistory[1][y * 4 + 0] = glRenderer->winN[1].h.start + glRenderer->winN[1].offsetX;
glRenderer->winNHistory[1][y * 4 + 1] = glRenderer->winN[1].h.end + glRenderer->winN[1].offsetX;
glRenderer->winNHistory[1][y * 4 + 2] = glRenderer->winN[1].v.start + glRenderer->winN[1].offsetY;
glRenderer->winNHistory[1][y * 4 + 3] = glRenderer->winN[1].v.end + glRenderer->winN[1].offsetY;
glRenderer->bg[0].scanlineOffset[y] = glRenderer->bg[0].x;
glRenderer->bg[0].scanlineOffset[y] |= glRenderer->bg[0].y << 12;
glRenderer->bg[1].scanlineOffset[y] = glRenderer->bg[1].x;
glRenderer->bg[1].scanlineOffset[y] |= glRenderer->bg[1].y << 12;
glRenderer->bg[2].scanlineOffset[y] = glRenderer->bg[2].x;
glRenderer->bg[2].scanlineOffset[y] |= glRenderer->bg[2].y << 12;
glRenderer->bg[0].scanlineOffset[y] = (glRenderer->bg[0].x - glRenderer->bg[0].offsetX) & 0x1FF;
glRenderer->bg[0].scanlineOffset[y] |= ((glRenderer->bg[0].y - glRenderer->bg[0].offsetY) & 0x1FF) << 12;
glRenderer->bg[1].scanlineOffset[y] = (glRenderer->bg[1].x - glRenderer->bg[1].offsetX) & 0x1FF;
glRenderer->bg[1].scanlineOffset[y] |= ((glRenderer->bg[1].y - glRenderer->bg[1].offsetY) & 0x1FF) << 12;
glRenderer->bg[2].scanlineOffset[y] = (glRenderer->bg[2].x - glRenderer->bg[2].offsetX) & 0x1FF;
glRenderer->bg[2].scanlineOffset[y] |= ((glRenderer->bg[2].y - glRenderer->bg[2].offsetY) & 0x1FF) << 12;
glRenderer->bg[2].scanlineAffine[y * 4] = glRenderer->bg[2].affine.dx;
glRenderer->bg[2].scanlineAffine[y * 4 + 1] = glRenderer->bg[2].affine.dy;
glRenderer->bg[2].scanlineAffine[y * 4 + 2] = glRenderer->bg[2].affine.sx;
glRenderer->bg[2].scanlineAffine[y * 4 + 3] = glRenderer->bg[2].affine.sy;
glRenderer->bg[3].scanlineOffset[y] = glRenderer->bg[3].x;
glRenderer->bg[3].scanlineOffset[y] |= glRenderer->bg[3].y << 12;
glRenderer->bg[3].scanlineOffset[y] = (glRenderer->bg[3].x - glRenderer->bg[3].offsetX) & 0x1FF;
glRenderer->bg[3].scanlineOffset[y] |= ((glRenderer->bg[3].y - glRenderer->bg[3].offsetY) & 0x1FF) << 12;
glRenderer->bg[3].scanlineAffine[y * 4] = glRenderer->bg[3].affine.dx;
glRenderer->bg[3].scanlineAffine[y * 4 + 1] = glRenderer->bg[3].affine.dy;
glRenderer->bg[3].scanlineAffine[y * 4 + 2] = glRenderer->bg[3].affine.sx;
@ -1686,6 +1686,7 @@ void GBAVideoGLRendererDrawSprite(struct GBAVideoGLRenderer* renderer, struct GB
int height = GBAVideoObjSizes[GBAObjAttributesAGetShape(sprite->a) * 4 + GBAObjAttributesBGetSize(sprite->b)][1];
int32_t x = (uint32_t) GBAObjAttributesBGetX(sprite->b) << 23;
x >>= 23;
x += renderer->objOffsetX;
if (GBARegisterDISPCNTGetMode(renderer->dispcnt) >= 3 && GBAObjAttributesCGetTile(sprite->c) < 512) {
return;
@ -1702,6 +1703,7 @@ void GBAVideoGLRendererDrawSprite(struct GBAVideoGLRenderer* renderer, struct GB
totalHeight <<= 1;
}
spriteY += renderer->objOffsetY;
if (spriteY + totalHeight >= 256) {
spriteY -= 256;
}