Remove "finalized" flag in favor of stricter sorting

This commit is contained in:
Jeffrey Pfau 2013-11-13 01:20:38 -08:00
parent a2a306bb03
commit 55c6103116
2 changed files with 38 additions and 45 deletions

View File

@ -355,7 +355,10 @@ static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* render
return;
}
memset(softwareRenderer->spriteLayer, 0, sizeof(softwareRenderer->spriteLayer));
int x;
for (x = 0; x < VIDEO_HORIZONTAL_PIXELS; ++x) {
softwareRenderer->spriteLayer[x] = FLAG_UNWRITTEN;
}
softwareRenderer->windows[0].endX = VIDEO_HORIZONTAL_PIXELS;
softwareRenderer->nWindows = 1;
@ -372,7 +375,7 @@ static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* render
}
int w;
int x = 0;
x = 0;
for (w = 0; w < softwareRenderer->nWindows; ++w) {
// TOOD: handle objwin on backdrop
uint32_t backdrop = FLAG_UNWRITTEN | FLAG_PRIORITY | FLAG_IS_BACKGROUND;
@ -392,7 +395,7 @@ static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* render
if (softwareRenderer->target2Bd) {
x = 0;
for (w = 0; w < softwareRenderer->nWindows; ++w) {
uint32_t backdrop = FLAG_UNWRITTEN | FLAG_PRIORITY | FLAG_IS_BACKGROUND;
uint32_t backdrop = FLAG_UNWRITTEN;
if (!softwareRenderer->target1Bd || softwareRenderer->blendEffect == BLEND_NONE || softwareRenderer->blendEffect == BLEND_ALPHA || !softwareRenderer->windows[w].control.blendEnable) {
backdrop |= softwareRenderer->normalPalette[0];
} else {
@ -401,7 +404,7 @@ static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* render
int end = softwareRenderer->windows[w].endX;
for (; x < end; ++x) {
uint32_t color = softwareRenderer->row[x];
if (color & FLAG_TARGET_1 && !(color & FLAG_FINALIZED)) {
if (color & FLAG_TARGET_1) {
softwareRenderer->row[x] = _mix(softwareRenderer->bldb, backdrop, softwareRenderer->blda, color);
}
}
@ -624,20 +627,14 @@ static void _composite(struct GBAVideoSoftwareRenderer* renderer, uint32_t* pixe
// We stash the priority on the top bits so we can do a one-operator comparison
// The lower the number, the higher the priority, and sprites take precendence over backgrounds
// We want to do special processing if the color pixel is target 1, however
if (current & FLAG_UNWRITTEN) {
color |= (current & FLAG_OBJWIN);
} else if ((color & FLAG_ORDER_MASK) < (current & FLAG_ORDER_MASK)) {
if (!(color & FLAG_TARGET_1) || !(current & FLAG_TARGET_2)) {
color |= FLAG_FINALIZED;
if (color >= current){
if (current & FLAG_TARGET_1 && color & FLAG_TARGET_2) {
color = _mix(renderer->blda, current, renderer->bldb, color);
} else {
color = _mix(renderer->bldb, current, renderer->blda, color) | FLAG_FINALIZED;
color = current & 0x00FFFFFF;
}
} else {
if (current & FLAG_TARGET_1 && color & FLAG_TARGET_2) {
color = _mix(renderer->blda, current, renderer->bldb, color) | FLAG_FINALIZED;
} else {
color = current | FLAG_FINALIZED;
}
color = (color & ~FLAG_TARGET_2) | (current & FLAG_OBJWIN);
}
*pixel = color;
}
@ -645,7 +642,7 @@ static void _composite(struct GBAVideoSoftwareRenderer* renderer, uint32_t* pixe
#define BACKGROUND_DRAW_PIXEL_16 \
pixelData = tileData & 0xF; \
current = *pixel; \
if (pixelData && !(current & FLAG_FINALIZED)) { \
if (pixelData && IS_WRITABLE(current)) { \
if (!objwinSlowPath) { \
_composite(renderer, pixel, palette[pixelData] | flags, current); \
} else if (objwinForceEnable || !(current & FLAG_OBJWIN) == objwinOnly) { \
@ -658,7 +655,7 @@ static void _composite(struct GBAVideoSoftwareRenderer* renderer, uint32_t* pixe
#define BACKGROUND_DRAW_PIXEL_256 \
pixelData = tileData & 0xFF; \
current = *pixel; \
if (pixelData && !(current & FLAG_FINALIZED)) { \
if (pixelData && IS_WRITABLE(current)) { \
if (!objwinSlowPath) { \
_composite(renderer, pixel, palette[pixelData] | flags, current); \
} else if (objwinForceEnable || !(current & FLAG_OBJWIN) == objwinOnly) { \
@ -734,12 +731,9 @@ static void _drawBackgroundMode0(struct GBAVideoSoftwareRenderer* renderer, stru
unsigned xBase;
int flags = (background->priority << OFFSET_PRIORITY) | FLAG_IS_BACKGROUND;
int flags = (background->priority << OFFSET_PRIORITY) | (background->index << OFFSET_INDEX) | FLAG_IS_BACKGROUND;
flags |= FLAG_TARGET_1 * (background->target1 && renderer->blendEffect == BLEND_ALPHA);
flags |= FLAG_TARGET_2 * background->target2;
if (!renderer->anyTarget2) {
flags |= FLAG_FINALIZED;
}
uint32_t screenBase;
uint32_t charBase;
@ -1057,12 +1051,9 @@ static void _drawBackgroundMode0(struct GBAVideoSoftwareRenderer* renderer, stru
int32_t localX; \
int32_t localY; \
\
int flags = (background->priority << OFFSET_PRIORITY) | FLAG_IS_BACKGROUND; \
int flags = (background->priority << OFFSET_PRIORITY) | (background->index << OFFSET_INDEX) | FLAG_IS_BACKGROUND; \
flags |= FLAG_TARGET_1 * (background->target1 && renderer->blendEffect == BLEND_ALPHA); \
flags |= FLAG_TARGET_2 * background->target2; \
if (!renderer->anyTarget2) { \
flags |= FLAG_FINALIZED; \
} \
int variant = background->target1 && renderer->currentWindow.blendEnable && (renderer->blendEffect == BLEND_BRIGHTEN || renderer->blendEffect == BLEND_DARKEN); \
color_t* palette = renderer->normalPalette; \
if (variant) { \
@ -1110,7 +1101,7 @@ static void _drawBackgroundMode2(struct GBAVideoSoftwareRenderer* renderer, stru
tileData = ((uint8_t*)renderer->d.vram)[charBase + (mapData << 6) + ((localY & 0x700) >> 5) + ((localX & 0x700) >> 8)];
uint32_t current = *pixel;
if (tileData && !(current & FLAG_FINALIZED)) {
if (tileData && IS_WRITABLE(current)) {
if (!objwinSlowPath) {
_composite(renderer, pixel, palette[tileData] | flags, current);
} else if (objwinForceEnable || !(current & FLAG_OBJWIN) == objwinOnly) {
@ -1142,7 +1133,7 @@ static void _drawBackgroundMode3(struct GBAVideoSoftwareRenderer* renderer, stru
#endif
uint32_t current = *pixel;
if (!(current & FLAG_FINALIZED) && (!objwinSlowPath || !(current & FLAG_OBJWIN) != objwinOnly)) {
if (!objwinSlowPath || !(current & FLAG_OBJWIN) != objwinOnly) {
if (!variant) {
_composite(renderer, pixel, color | flags, current);
} else if (renderer->blendEffect == BLEND_BRIGHTEN) {
@ -1171,7 +1162,7 @@ static void _drawBackgroundMode4(struct GBAVideoSoftwareRenderer* renderer, stru
color = ((uint8_t*)renderer->d.vram)[offset + (localX >> 8) + (localY >> 8) * VIDEO_HORIZONTAL_PIXELS];
uint32_t current = *pixel;
if (color && !(current & FLAG_FINALIZED)) {
if (color && IS_WRITABLE(current)) {
if (!objwinSlowPath) {
_composite(renderer, pixel, palette[color] | flags, current);
} else if (objwinForceEnable || !(current & FLAG_OBJWIN) == objwinOnly) {
@ -1206,7 +1197,7 @@ static void _drawBackgroundMode5(struct GBAVideoSoftwareRenderer* renderer, stru
#endif
uint32_t current = *pixel;
if (!(current & FLAG_FINALIZED) && (!objwinSlowPath || !(current & FLAG_OBJWIN) != objwinOnly)) {
if (!objwinSlowPath || !(current & FLAG_OBJWIN) != objwinOnly) {
if (!variant) {
_composite(renderer, pixel, color | flags, current);
} else if (renderer->blendEffect == BLEND_BRIGHTEN) {
@ -1287,7 +1278,7 @@ static const int _objSizes[32] = {
#define SPRITE_DRAW_PIXEL_16_NORMAL(localX) \
unsigned tileData = renderer->d.vram[(yBase + charBase + xBase) >> 1]; \
tileData = (tileData >> ((localX & 3) << 2)) & 0xF; \
if (tileData && (!(renderer->spriteLayer[outX]) || ((renderer->spriteLayer[outX] & FLAG_ORDER_MASK) > flags))) { \
if (tileData && (renderer->spriteLayer[outX] & FLAG_ORDER_MASK) > flags) { \
renderer->spriteLayer[outX] = palette[tileData] | flags; \
}
@ -1304,7 +1295,7 @@ static const int _objSizes[32] = {
#define SPRITE_DRAW_PIXEL_256_NORMAL(localX) \
unsigned tileData = renderer->d.vram[(yBase + charBase + xBase) >> 1]; \
tileData = (tileData >> ((localX & 1) << 3)) & 0xFF; \
if (tileData && (!(renderer->spriteLayer[outX]) || ((renderer->spriteLayer[outX] & FLAG_ORDER_MASK) > flags))) { \
if (tileData && (renderer->spriteLayer[outX] & FLAG_ORDER_MASK) > flags) { \
renderer->spriteLayer[outX] = palette[tileData] | flags; \
}
@ -1327,9 +1318,8 @@ static int _preprocessSprite(struct GBAVideoSoftwareRenderer* renderer, struct G
int width = _objSizes[sprite->shape * 8 + sprite->size * 2];
int start = renderer->start;
int end = renderer->end;
uint32_t flags = (sprite->priority << OFFSET_PRIORITY) | FLAG_FINALIZED;
uint32_t flags = sprite->priority << OFFSET_PRIORITY;
flags |= FLAG_TARGET_1 * ((renderer->currentWindow.blendEnable && renderer->target1Obj && renderer->blendEffect == BLEND_ALPHA) || sprite->mode == OBJ_MODE_SEMITRANSPARENT);
flags |= FLAG_TARGET_2 *renderer->target2Obj;
flags |= FLAG_OBJWIN * (sprite->mode == OBJ_MODE_OBJWIN);
int x = sprite->x;
unsigned charBase = BASE_TILE + sprite->tile * 0x20;
@ -1399,9 +1389,8 @@ static int _preprocessTransformedSprite(struct GBAVideoSoftwareRenderer* rendere
int totalWidth = width << sprite->doublesize;
int start = renderer->start;
int end = renderer->end;
uint32_t flags = (sprite->priority << OFFSET_PRIORITY) | FLAG_FINALIZED;
uint32_t flags = sprite->priority << OFFSET_PRIORITY;
flags |= FLAG_TARGET_1 * ((renderer->currentWindow.blendEnable && renderer->target1Obj && renderer->blendEffect == BLEND_ALPHA) || sprite->mode == OBJ_MODE_SEMITRANSPARENT);
flags |= FLAG_TARGET_2 * renderer->target2Obj;
flags |= FLAG_OBJWIN * (sprite->mode == OBJ_MODE_OBJWIN);
int x = sprite->x;
unsigned charBase = BASE_TILE + sprite->tile * 0x20;
@ -1439,11 +1428,12 @@ static int _preprocessTransformedSprite(struct GBAVideoSoftwareRenderer* rendere
static void _postprocessSprite(struct GBAVideoSoftwareRenderer* renderer, unsigned priority) {
int x;
uint32_t* pixel = renderer->row;
uint32_t flags = FLAG_TARGET_2 * renderer->target2Obj;
for (x = 0; x < VIDEO_HORIZONTAL_PIXELS; ++x, ++pixel) {
uint32_t color = renderer->spriteLayer[x];
uint32_t color = renderer->spriteLayer[x] & ~FLAG_OBJWIN;
uint32_t current = *pixel;
if ((color & FLAG_FINALIZED) && (color & FLAG_PRIORITY) >> OFFSET_PRIORITY == priority && !(current & FLAG_FINALIZED)) {
_composite(renderer, pixel, color & ~FLAG_FINALIZED, current);
if ((color & FLAG_UNWRITTEN) != FLAG_UNWRITTEN && (color & FLAG_PRIORITY) >> OFFSET_PRIORITY == priority) {
_composite(renderer, pixel, color | flags, current);
}
}
}

View File

@ -52,21 +52,24 @@ enum {
#else
GBA_COLOR_WHITE = 0x00F8F8F8,
#endif
OFFSET_PRIORITY = 29
OFFSET_PRIORITY = 30,
OFFSET_INDEX = 28,
};
enum PixelFlags {
FLAG_FINALIZED = 0x80000000,
FLAG_PRIORITY = 0x60000000,
FLAG_IS_BACKGROUND = 0x10000000,
FLAG_UNWRITTEN = 0x08000000,
FLAG_TARGET_1 = 0x04000000,
FLAG_TARGET_2 = 0x02000000,
FLAG_PRIORITY = 0xC0000000,
FLAG_INDEX = 0x30000000,
FLAG_IS_BACKGROUND = 0x08000000,
FLAG_UNWRITTEN = 0xFC000000,
FLAG_TARGET_1 = 0x02000000,
FLAG_TARGET_2 = 0x01000000,
FLAG_OBJWIN = 0x01000000,
FLAG_ORDER_MASK = 0xF8000000
};
#define IS_WRITABLE(PIXEL) ((PIXEL) & 0xFE000000)
union WindowRegion {
struct {
uint8_t end;