GBA: Tile cache improvements

This commit is contained in:
Jeffrey Pfau 2016-07-23 19:34:43 -07:00
parent 4a7dc8bff6
commit 2f3c4982bd
3 changed files with 66 additions and 32 deletions

View File

@ -13,14 +13,28 @@
void GBAVideoTileCacheInit(struct GBAVideoTileCache* cache) { void GBAVideoTileCacheInit(struct GBAVideoTileCache* cache) {
// TODO: Reconfigurable cache for space savings // TODO: Reconfigurable cache for space savings
cache->cache = anonymousMemoryMap(CACHE_SIZE); cache->cache = anonymousMemoryMap(CACHE_SIZE);
cache->config = GBAVideoTileCacheConfigurationFillShouldStore(0);
memset(cache->status, 0, sizeof(cache->status)); memset(cache->status, 0, sizeof(cache->status));
memset(cache->globalPaletteVersion, 0, sizeof(cache->globalPaletteVersion)); memset(cache->globalPaletteVersion, 0, sizeof(cache->globalPaletteVersion));
memset(cache->globalPalette256Version, 0, sizeof(cache->globalPalette256Version)); memset(cache->globalPalette256Version, 0, sizeof(cache->globalPalette256Version));
} }
void GBAVideoTileCacheConfigure(struct GBAVideoTileCache* cache, GBAVideoTileCacheConfiguration config) {
if (GBAVideoTileCacheConfigurationIsShouldStore(cache->config) || !GBAVideoTileCacheConfigurationIsShouldStore(config)) {
mappedMemoryFree(cache->cache, CACHE_SIZE);
cache->cache = NULL;
} else if (!GBAVideoTileCacheConfigurationIsShouldStore(cache->config) || GBAVideoTileCacheConfigurationIsShouldStore(config)) {
cache->cache = anonymousMemoryMap(CACHE_SIZE);
}
cache->config = config;
}
void GBAVideoTileCacheDeinit(struct GBAVideoTileCache* cache) { void GBAVideoTileCacheDeinit(struct GBAVideoTileCache* cache) {
mappedMemoryFree(cache->cache, CACHE_SIZE); if (GBAVideoTileCacheConfigurationIsShouldStore(cache->config)) {
cache->cache = NULL; mappedMemoryFree(cache->cache, CACHE_SIZE);
cache->cache = NULL;
}
} }
void GBAVideoTileCacheAssociate(struct GBAVideoTileCache* cache, struct GBAVideo* video) { void GBAVideoTileCacheAssociate(struct GBAVideoTileCache* cache, struct GBAVideo* video) {
@ -30,7 +44,10 @@ void GBAVideoTileCacheAssociate(struct GBAVideoTileCache* cache, struct GBAVideo
} }
void GBAVideoTileCacheWriteVRAM(struct GBAVideoTileCache* cache, uint32_t address) { void GBAVideoTileCacheWriteVRAM(struct GBAVideoTileCache* cache, uint32_t address) {
cache->status[address >> 5].vramClean = 0; size_t i;
for (i = 0; i > 16; ++i) {
cache->status[address >> 5][i].vramClean = 0;
}
} }
void GBAVideoTileCacheWritePalette(struct GBAVideoTileCache* cache, uint32_t address) { void GBAVideoTileCacheWritePalette(struct GBAVideoTileCache* cache, uint32_t address) {
@ -38,8 +55,7 @@ void GBAVideoTileCacheWritePalette(struct GBAVideoTileCache* cache, uint32_t add
++cache->globalPalette256Version[address >> 9]; ++cache->globalPalette256Version[address >> 9];
} }
static void _regenerateTile16(struct GBAVideoTileCache* cache, unsigned tileId, unsigned paletteId) { static void _regenerateTile16(struct GBAVideoTileCache* cache, uint16_t* tile, unsigned tileId, unsigned paletteId) {
uint16_t* tile = &cache->cache[tileId << 6];
uint32_t* start = (uint32_t*) &cache->vram[tileId << 4]; uint32_t* start = (uint32_t*) &cache->vram[tileId << 4];
paletteId <<= 4; paletteId <<= 4;
uint16_t* palette = &cache->palette[paletteId]; uint16_t* palette = &cache->palette[paletteId];
@ -68,11 +84,10 @@ static void _regenerateTile16(struct GBAVideoTileCache* cache, unsigned tileId,
} }
} }
static void _regenerateTile256(struct GBAVideoTileCache* cache, unsigned tileId, unsigned paletteId) { static void _regenerateTile256(struct GBAVideoTileCache* cache, uint16_t* tile, unsigned tileId, unsigned paletteId) {
uint16_t* tile = &cache->cache[tileId << 6];
uint32_t* start = (uint32_t*) &cache->vram[tileId << 5]; uint32_t* start = (uint32_t*) &cache->vram[tileId << 5];
paletteId <<= 8; paletteId <<= 8;
uint16_t* palette = &cache->palette[paletteId]; uint16_t* palette = &cache->palette[paletteId * 16];
int i; int i;
for (i = 0; i < 8; ++i) { for (i = 0; i < 8; ++i) {
uint32_t line = *start; uint32_t line = *start;
@ -101,49 +116,61 @@ static void _regenerateTile256(struct GBAVideoTileCache* cache, unsigned tileId,
} }
} }
static inline uint16_t* _tileLookup(struct GBAVideoTileCache* cache, unsigned tileId, unsigned paletteId) {
if (GBAVideoTileCacheConfigurationIsShouldStore(cache->config)) {
return &cache->cache[((tileId << 4) + (paletteId & 0xF)) << 6];
} else {
return cache->temporaryTile;
}
}
const uint16_t* GBAVideoTileCacheGetTile16(struct GBAVideoTileCache* cache, unsigned tileId, unsigned paletteId) { const uint16_t* GBAVideoTileCacheGetTile16(struct GBAVideoTileCache* cache, unsigned tileId, unsigned paletteId) {
struct GBAVideoTileCacheEntry* status = &cache->status[tileId]; struct GBAVideoTileCacheEntry* status = &cache->status[tileId][paletteId & 0xF];
if (!status->vramClean || status->palette256 || status->paletteVersion[paletteId & 0xF] != cache->globalPaletteVersion[paletteId]) { uint16_t* tile = _tileLookup(cache, tileId, paletteId);
_regenerateTile16(cache, tileId, paletteId); if (!GBAVideoTileCacheConfigurationIsShouldStore(cache->config) || !status->vramClean || status->palette256 || status->paletteVersion != cache->globalPaletteVersion[paletteId]) {
status->paletteVersion[paletteId & 0xF] = cache->globalPaletteVersion[paletteId]; _regenerateTile16(cache, tile, tileId, paletteId);
status->paletteVersion = cache->globalPaletteVersion[paletteId];
status->palette256 = 0; status->palette256 = 0;
status->vramClean = 1; status->vramClean = 1;
} }
return &cache->cache[tileId << 6]; return tile;
} }
const uint16_t* GBAVideoTileCacheGetTile16IfDirty(struct GBAVideoTileCache* cache, unsigned tileId, unsigned paletteId) { const uint16_t* GBAVideoTileCacheGetTile16IfDirty(struct GBAVideoTileCache* cache, unsigned tileId, unsigned paletteId) {
struct GBAVideoTileCacheEntry* status = &cache->status[tileId]; struct GBAVideoTileCacheEntry* status = &cache->status[tileId][paletteId & 0xF];
if (!status->vramClean || status->palette256 || status->paletteVersion[paletteId & 0xF] != cache->globalPaletteVersion[paletteId]) { if (!status->vramClean || status->palette256 || status->paletteVersion != cache->globalPaletteVersion[paletteId]) {
_regenerateTile16(cache, tileId, paletteId); uint16_t* tile = _tileLookup(cache, tileId, paletteId);
status->paletteVersion[paletteId & 0xF] = cache->globalPaletteVersion[paletteId]; _regenerateTile16(cache, tile, tileId, paletteId);
status->paletteVersion = cache->globalPaletteVersion[paletteId];
status->palette256 = 0; status->palette256 = 0;
status->vramClean = 1; status->vramClean = 1;
return &cache->cache[tileId << 6]; return tile;
} }
return NULL; return NULL;
} }
const uint16_t* GBAVideoTileCacheGetTile256(struct GBAVideoTileCache* cache, unsigned tileId, unsigned paletteId) { const uint16_t* GBAVideoTileCacheGetTile256(struct GBAVideoTileCache* cache, unsigned tileId, unsigned paletteId) {
struct GBAVideoTileCacheEntry* status = &cache->status[tileId]; struct GBAVideoTileCacheEntry* status = &cache->status[tileId][paletteId];
if (!status->vramClean || !status->palette256 || status->paletteVersion[0] != cache->globalPalette256Version[paletteId]) { uint16_t* tile = _tileLookup(cache, tileId, paletteId);
_regenerateTile256(cache, tileId, paletteId); if (!GBAVideoTileCacheConfigurationIsShouldStore(cache->config) || !status->vramClean || !status->palette256 || status->paletteVersion != cache->globalPalette256Version[paletteId]) {
status->paletteVersion[0] = cache->globalPalette256Version[paletteId]; _regenerateTile256(cache, tile, tileId, paletteId);
status->paletteVersion = cache->globalPalette256Version[paletteId];
status->palette256 = 1; status->palette256 = 1;
status->vramClean = 1; status->vramClean = 1;
} }
return &cache->cache[tileId << 6]; return tile;
} }
const uint16_t* GBAVideoTileCacheGetTile256IfDirty(struct GBAVideoTileCache* cache, unsigned tileId, unsigned paletteId) { const uint16_t* GBAVideoTileCacheGetTile256IfDirty(struct GBAVideoTileCache* cache, unsigned tileId, unsigned paletteId) {
struct GBAVideoTileCacheEntry* status = &cache->status[tileId]; struct GBAVideoTileCacheEntry* status = &cache->status[tileId][paletteId];
if (!status->vramClean || !status->palette256 || status->paletteVersion[0] != cache->globalPalette256Version[paletteId]) { if (!status->vramClean || !status->palette256 || status->paletteVersion != cache->globalPalette256Version[paletteId]) {
_regenerateTile256(cache, tileId, paletteId); uint16_t* tile = _tileLookup(cache, tileId, paletteId);
status->paletteVersion[0] = cache->globalPalette256Version[paletteId]; _regenerateTile256(cache, tile, tileId, paletteId);
status->paletteVersion = cache->globalPalette256Version[paletteId];
status->palette256 = 1; status->palette256 = 1;
status->vramClean = 1; status->vramClean = 1;
return &cache->cache[tileId << 6]; return tile;
} }
return NULL; return NULL;
} }

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2013-2015 Jeffrey Pfau /* Copyright (c) 2013-2016 Jeffrey Pfau
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -10,22 +10,29 @@
struct GBAVideo; struct GBAVideo;
DECL_BITFIELD(GBAVideoTileCacheConfiguration, uint32_t);
DECL_BIT(GBAVideoTileCacheConfiguration, ShouldStore, 0);
struct GBAVideoTileCache { struct GBAVideoTileCache {
uint16_t* cache; uint16_t* cache;
struct GBAVideoTileCacheEntry { struct GBAVideoTileCacheEntry {
uint32_t paletteVersion[16]; uint32_t paletteVersion;
uint8_t vramClean; uint8_t vramClean;
uint8_t palette256; uint8_t palette256;
} status[1024 * 3]; } status[1024 * 3][16];
uint32_t globalPaletteVersion[32]; uint32_t globalPaletteVersion[32];
uint32_t globalPalette256Version[2]; uint32_t globalPalette256Version[2];
uint16_t* vram; uint16_t* vram;
uint16_t* palette; uint16_t* palette;
uint16_t temporaryTile[64];
GBAVideoTileCacheConfiguration config;
}; };
void GBAVideoTileCacheInit(struct GBAVideoTileCache* cache); void GBAVideoTileCacheInit(struct GBAVideoTileCache* cache);
void GBAVideoTileCacheDeinit(struct GBAVideoTileCache* cache); void GBAVideoTileCacheDeinit(struct GBAVideoTileCache* cache);
void GBAVideoTileCacheConfigure(struct GBAVideoTileCache* cache, GBAVideoTileCacheConfiguration config);
void GBAVideoTileCacheAssociate(struct GBAVideoTileCache* cache, struct GBAVideo* video); void GBAVideoTileCacheAssociate(struct GBAVideoTileCache* cache, struct GBAVideo* video);
void GBAVideoTileCacheWriteVRAM(struct GBAVideoTileCache* cache, uint32_t address); void GBAVideoTileCacheWriteVRAM(struct GBAVideoTileCache* cache, uint32_t address);
void GBAVideoTileCacheWritePalette(struct GBAVideoTileCache* cache, uint32_t address); void GBAVideoTileCacheWritePalette(struct GBAVideoTileCache* cache, uint32_t address);

View File

@ -123,7 +123,7 @@ void TileView::updateTiles(bool force) {
void TileView::updatePalette(int palette) { void TileView::updatePalette(int palette) {
m_paletteId = palette; m_paletteId = palette;
updateTiles(); updateTiles(true);
} }
void TileView::resizeEvent(QResizeEvent*) { void TileView::resizeEvent(QResizeEvent*) {