Need to walk back in memory and check the previous texture tiles to see if they overlap with the current textures being invalidated. If they overlap they must be cleared too. Algorithm is a bit brute forcy and more expensive than I'd like but it fixes the bad textures in Spikeout.

This commit is contained in:
Ian Curtis 2016-11-22 20:30:10 +00:00
parent 84ae8f035c
commit 54c405709f
4 changed files with 83 additions and 11 deletions

View file

@ -334,4 +334,19 @@ bool Texture::Compare(int x, int y, int width, int height, int format)
return false;
}
bool Texture::CheckMapPos(int ax1, int ax2, int ay1, int ay2)
{
int bx1 = m_x;
int bx2 = m_x + m_width;
int by1 = m_y;
int by2 = m_y + m_height;
if (ax1<bx2 && ax2>bx1 &&
ay1<by2 && ay2>by1) {
return true; // rectangles overlap
}
return false;
}
} // New3D

View file

@ -20,6 +20,7 @@ public:
void GetDetails (int& x, int&y, int& width, int& height, int& format);
void SetWrapMode (bool mirrorU, bool mirrorV);
bool Compare (int x, int y, int width, int height, int format);
bool CheckMapPos (int ax1, int ax2, int ay1, int ay2); //check to see if textures overlap
static void GetCoordinates(int width, int height, UINT16 uIn, UINT16 vIn, float uvScale, float& uOut, float& vOut);

View file

@ -75,30 +75,85 @@ void TextureSheet::Release()
void TextureSheet::Invalidate(int x, int y, int width, int height)
{
//==========
//============
int newX;
int newY;
int newWidth;
int newHeight;
int count;
int sWidth; // sample width
int sHeight; // sample height
//==========
//============
// since the smallest sized texture is 32x32 pixels?
// we can invalidate 32x32 tiles over the width/height of the area
if (width <= 512) {
newX = (x + width) - 512;
newWidth = 512;
}
else {
newX = x;
newWidth = width;
}
if (height <= 512) {
newY = (y + height) - 512;
newHeight = 512;
}
else {
newY = y;
newHeight = height;
}
sWidth = width / 32;
sHeight = height / 32;
CropTile(x, y, newX, newY, newWidth, newHeight);
sWidth = newWidth / 32;
sHeight = newHeight / 32;
count = sWidth * sHeight;
for (int i = 0; i < count; i++) {
int index = ToIndex(x + ((i%sWidth) * 32), y + ((i / sWidth) * 32));
for (int j = 0; j<12; j++) {
if (m_texMap[j].count(index) > 0) {
int posX = newX + ((i%sWidth) * 32);
int posY = newY + ((i / sWidth) * 32);
int index = ToIndex(posX, posY);
if (posX >= x && posY >= y) { // invalidate this area of memory
for (int j = 0; j < 12; j++) {
m_texMap[j].erase(index);
}
}
else { // check for overlapping data tiles and invalidate as necessary
for (int j = 0; j < 12; j++) {
auto range = m_texMap[j].equal_range(index);
for (auto it = range.first; it != range.second; ++it) {
if (it->second->CheckMapPos(x, x + width, y, y + height)) {
m_texMap[j].erase(index);
break;
}
}
}
}
}
}
void TextureSheet::CropTile(int oldX, int oldY, int &newX, int &newY, int &newWidth, int &newHeight)
{
if (newX < 0) {
newWidth += newX;
newX = 0;
}
if (newY < 0) {
newHeight += newY;
newY = 0;
}
if (oldY >= 1024 && newY < 1024) { // gone into next memory page, limitation of our flat model
newHeight -= 1024 - newY;
newY = 1024;
}
}

View file

@ -23,6 +23,7 @@ public:
private:
int ToIndex(int x, int y);
void CropTile(int oldX, int oldY, int &newX, int &newY, int &newWidth, int &newHeight);
std::unordered_multimap<int, std::shared_ptr<Texture>> m_texMap[12];