From 990df72ced66c4fa4a1f51684517bf4204c06a63 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Thu, 11 Aug 2016 03:03:49 -0700 Subject: [PATCH] GBA Video: Optimize sprite drawing --- CHANGES | 1 + src/gba/renderers/software-bg.c | 7 +++--- src/gba/renderers/software-obj.c | 37 ++++++++++++++++++++++++++++---- 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/CHANGES b/CHANGES index b6173d637..bbdeb9513 100644 --- a/CHANGES +++ b/CHANGES @@ -49,6 +49,7 @@ Misc: - GUI: Add back logging - PSP2: Add rumble for PS TV - PSP2: Add fit-to-height screen mode + - GBA Video: Optimize sprite drawing 0.4.1: (2016-07-11) Bugfixes: diff --git a/src/gba/renderers/software-bg.c b/src/gba/renderers/software-bg.c index fec27af04..67d4dc26c 100644 --- a/src/gba/renderers/software-bg.c +++ b/src/gba/renderers/software-bg.c @@ -14,10 +14,9 @@ #define MODE_2_COORD_NO_OVERFLOW \ if ((x | y) & ~(sizeAdjusted - 1)) { \ continue; \ - } else { \ - localX = x; \ - localY = y; \ - } + } \ + localX = x; \ + localY = y; #define MODE_2_MOSAIC(COORD) \ if (!mosaicWait) { \ diff --git a/src/gba/renderers/software-obj.c b/src/gba/renderers/software-obj.c index 9179de85e..91b626499 100644 --- a/src/gba/renderers/software-obj.c +++ b/src/gba/renderers/software-obj.c @@ -56,7 +56,7 @@ int localY = (yAccum >> 8) + (height >> 1); \ \ if (localX & widthMask || localY & heightMask) { \ - continue; \ + break; \ } \ \ SPRITE_YBASE_ ## DEPTH(localY); \ @@ -204,6 +204,35 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re condition = end; } + // Clip off early pixels + if ((xAccum >> 8) < -(width >> 1) || (yAccum >> 8) < -(height >> 1)) { + int32_t diffX = -(width << 7) - xAccum; + int32_t diffY = -(height << 7) - yAccum; + int32_t x = mat.a ? diffX / mat.a : 0; + int32_t y = mat.c ? diffY / mat.c : 0; + if (y > x) { + x = y; + } + xAccum += mat.a * x; + yAccum += mat.c * x; + outX += x; + inX += x; + } + // Clip off late pixels + if ((xAccum >> 8) >= (width >> 1) || (yAccum >> 8) >= (height >> 1)) { + int32_t diffX = (width << 7) - xAccum; + int32_t diffY = (height << 7) - yAccum; + int32_t x = mat.a ? diffX / mat.a : 0; + int32_t y = mat.c ? diffY / mat.c : 0; + if (y > x) { + x = y; + } + xAccum += mat.a * x; + yAccum += mat.c * x; + outX += x; + inX += x; + } + if (!GBAObjAttributesAIs256Color(sprite->a)) { palette = &palette[GBAObjAttributesCGetPalette(sprite->c) << 4]; if (flags & FLAG_OBJWIN) { @@ -230,7 +259,7 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re int outX = x >= start ? x : start; int condition = x + width; int mosaicH = 1; - if (GBAObjAttributesAIsMosaic(sprite->a)) { + if (mosaicH > 1) { mosaicH = GBAMosaicControlGetObjH(renderer->mosaic) + 1; if (condition % mosaicH) { condition += mosaicH - (condition % mosaicH); @@ -255,7 +284,7 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re palette = &palette[GBAObjAttributesCGetPalette(sprite->c) << 4]; if (flags & FLAG_OBJWIN) { SPRITE_NORMAL_LOOP(16, OBJWIN); - } else if (GBAObjAttributesAIsMosaic(sprite->a)) { + } else if (mosaicH > 1) { if (objwinSlowPath) { objwinPalette = &objwinPalette[GBAObjAttributesCGetPalette(sprite->c) << 4]; SPRITE_MOSAIC_LOOP(16, NORMAL_OBJWIN); @@ -271,7 +300,7 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re } else { if (flags & FLAG_OBJWIN) { SPRITE_NORMAL_LOOP(256, OBJWIN); - } else if (GBAObjAttributesAIsMosaic(sprite->a)) { + } else if (mosaicH > 1) { if (objwinSlowPath) { objwinPalette = &objwinPalette[GBAObjAttributesCGetPalette(sprite->c) << 4]; SPRITE_MOSAIC_LOOP(256, NORMAL_OBJWIN);