AmigaPorts / AmigaPorts/ACE

Tilebuffer may benefit from a cache

Aperta
#171 1 commento 0 reazioni 0 assegnatari Vedi su GitHub
Lingua principale
C
Stelle
223
Fork
38
Merge medio
1g 5h
PR unite (30g)
6

Descrizione

When some tiles repeat a lot and no other drawing is taking place (i.e, in the tile draw callback), we can cache what tiles were already drawn where and avoid starting the blitter in many cases.

A simple patch that I'm using right now attached:

```patch
diff --git a/include/ace/managers/viewport/tilebuffer.h b/include/ace/managers/viewport/tilebuffer.h
index 46156b3..5144b45 100644
--- a/include/ace/managers/viewport/tilebuffer.h
+++ b/include/ace/managers/viewport/tilebuffer.h
@@ -123,6 +123,7 @@ typedef struct _tTileBufferManager {
/// TODO: refresh when scrollbuffer changes
tTileDrawCallback cbTileDraw; ///< Called when tile is redrawn
UBYTE **pTileData; ///< 2D array of tile indices
+ UBYTE **pTileCache; ///< 2D array of drawn tile indices
tBitMap *pTileSet; ///< Tileset - one tile beneath another
// Margin & queue geometry
UBYTE ubMarginXLength; ///< Tile number in margins: left & right
diff --git a/src/ace/managers/viewport/tilebuffer.c b/src/ace/managers/viewport/tilebuffer.c
index 7f5ca1e..928a400 100644
--- a/src/ace/managers/viewport/tilebuffer.c
+++ b/src/ace/managers/viewport/tilebuffer.c
@@ -243,6 +243,15 @@ void tileBufferReset(
);
}

+ // Free old tile cache
+ if(pManager->pTileCache) {
+ for(UWORD uwCol = pManager->uwMarginedWidth >> ubTileShift; uwCol--;) {
+ memFree(pManager->pTileCache[uwCol], (pManager->uwMarginedHeight >> ubTileShift) * sizeof(UBYTE) * 2);
+ }
+ memFree(pManager->pTileCache, (pManager->uwMarginedWidth >> ubTileShift) * sizeof(UBYTE *) * 2);
+ pManager->pTileCache = 0;
+ }
+
// Scrollin on one of dirs may be disabled - less redraw on other axis margin
pManager->uwMarginedWidth = bitmapGetByteWidth(pManager->pScroll->pFront)*8;
pManager->uwMarginedHeight = pManager->pScroll->uwBmAvailHeight;
@@ -260,6 +269,15 @@ void tileBufferReset(
pManager->ubMarginXLength, pManager->ubMarginYLength
);

+ // Init new tile cache
+ // TODO: like the redraw states, we always maintain a double buffered cache right now, which eats quite some memory
+ if((pManager->uwMarginedWidth >> ubTileShift) && (pManager->uwMarginedHeight >> ubTileShift)) {
+ pManager->pTileCache = memAllocFast((pManager->uwMarginedWidth >> ubTileShift) * sizeof(UBYTE*) * 2);
+ for(UWORD uwCol = (pManager->uwMarginedWidth >> ubTileShift); uwCol--;) {
+ pManager->pTileCache[uwCol] = memAllocFastClear((pManager->uwMarginedHeight >> ubTileShift) * sizeof(UBYTE) * 2);
+ }
+ }
+
// Reset margin redraw structs
tileBufferResetRedrawState(&pManager->pRedrawStates[0]);
tileBufferResetRedrawState(&pManager->pRedrawStates[1]);
@@ -445,6 +463,8 @@ void tileBufferRedrawAll(tTileBufferManager *pManager) {
UWORD uwTileOffsX = (wStartX << ubTileShift);

for (UWORD uwTileX = wStartX; uwTileX < uwEndX; ++uwTileX) {
+ // force redraw by invalidating cache
+ pManager->pTileCache[uwTileOffsX >> ubTileShift][uwTileOffsY >> ubTileShift] = pManager->pTileData[uwTileX][uwTileY] + 1;
tileBufferDrawTileQuick(
pManager, uwTileX, uwTileY, uwTileOffsX, uwTileOffsY
);
@@ -487,14 +507,22 @@ void tileBufferDrawTileQuick(
const tTileBufferManager *pManager, UWORD uwTileX, UWORD uwTileY,
UWORD uwBfrX, UWORD uwBfrY
) {
- // This can't use safe blit fn because when scrolling in X direction,
- // we need to draw on bitplane 1 as if it is part of bitplane 0.
- blitUnsafeCopyAligned(
- pManager->pTileSet,
- 0, pManager->pTileData[uwTileX][uwTileY] << pManager->ubTileShift,
- pManager->pScroll->pBack, uwBfrX, uwBfrY,
- pManager->ubTileSize, pManager->ubTileSize
- );
+ UBYTE ubTileToDraw = pManager->pTileData[uwTileX][uwTileY];
+ UBYTE ubTileShift = pManager->ubTileShift;
+ UBYTE ubStateIdx = pManager->ubStateIdx;
+ UBYTE *pubDrawnTile = &pManager->pTileCache[uwBfrX >> (ubTileShift - ubStateIdx)][uwBfrY >> (ubTileShift - ubStateIdx)];
+ if (*pubDrawnTile != ubTileToDraw) {
+ // the correct tile is not already on the buffer
+ *pubDrawnTile = ubTileToDraw;
+ // This can't use safe blit fn because when scrolling in X direction,
+ // we need to draw on bitplane 1 as if it is part of bitplane 0.
+ blitUnsafeCopyAligned(
+ pManager->pTileSet,
+ 0, ubTileToDraw << pManager->ubTileShift,
+ pManager->pScroll->pBack, uwBfrX, uwBfrY,
+ pManager->ubTileSize, pManager->ubTileSize
+ );
+ }
if(pManager->cbTileDraw) {
pManager->cbTileDraw(
uwTileX, uwTileY, pManager->pScroll->pBack, uwBfrX, uwBfrY
```

Guida per i contributori

Nessuna guida per i contributori indicizzata per questo repository

Valutazione

Questa issue non è ancora stata valutata.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.