mirror of https://github.com/mgba-emu/mgba.git
GBA: Tile cache improvements
This commit is contained in:
parent
4a7dc8bff6
commit
2f3c4982bd
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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*) {
|
||||||
|
|
Loading…
Reference in New Issue