From 6fa020470984970f22f810ceb09f1eeb8fb051f2 Mon Sep 17 00:00:00 2001 From: Sergey Lipskiy Date: Thu, 9 Apr 2015 20:33:40 +0600 Subject: [PATCH] Replace Adler32 by more faster textureCRC from Glide64. textureCRC is good enough to calculate checksum of frame buffer. --- CRC.cpp | 34 +++++++++++++++------------------- CRC.h | 4 +++- FrameBuffer.cpp | 5 +++-- gDP.cpp | 2 +- 4 files changed, 22 insertions(+), 23 deletions(-) diff --git a/CRC.cpp b/CRC.cpp index 5223b002..d7df9dbd 100644 --- a/CRC.cpp +++ b/CRC.cpp @@ -59,28 +59,24 @@ u32 CRC_CalculatePalette(u32 crc, const void * buffer, u32 count ) return crc ^ orig; } -u32 Adler32(u32 crc, const void *buffer, u32 count) +u32 textureCRC(u8 * addr, u32 height, u32 stride) { - register u32 s1 = crc & 0xFFFF; - register u32 s2 = (crc >> 16) & 0xFFFF; - int k; - const u8 *Buffer = (const u8*)buffer; + const u32 width = stride / 8; + const u32 line = stride % 8; + u64 crc = 0; + u64 twopixel_crc; - if (Buffer == NULL) - return 0; - - while (count > 0) { - /* 5552 is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ - k = (count < 5552 ? count : 5552); - count -= k; - while (k--) { - s1 += *Buffer++; - s2 += s1; + u32 * pixelpos = (u32*)addr; + for (; height; height--) { + int col = 0; + for (u32 i = width; i; --i) { + twopixel_crc = i * ((u64)(pixelpos[1] & 0xFFFEFFFE) + (u64)(pixelpos[0] & 0xFFFEFFFE) + crc); + crc = (twopixel_crc >> 32) + twopixel_crc; + pixelpos += 2; } - /* 65521 is the largest prime smaller than 65536 */ - s1 %= 65521; - s2 %= 65521; + crc = (height * crc >> 32) + height * crc; + pixelpos = (u32*)((u8*)pixelpos + line); } - return (s2 << 16) | s1; + return crc&0xFFFFFFFF; } diff --git a/CRC.h b/CRC.h index 2094f781..a9a818fc 100644 --- a/CRC.h +++ b/CRC.h @@ -2,6 +2,8 @@ void CRC_BuildTable(); +// CRC32 u32 CRC_Calculate( u32 crc, const void *buffer, u32 count ); u32 CRC_CalculatePalette( u32 crc, const void *buffer, u32 count ); -u32 Adler32(u32 crc, const void *buffer, u32 count); +// Fast checksum calculation from Glide64 +u32 textureCRC(u8 * addr, u32 height, u32 stride); diff --git a/FrameBuffer.cpp b/FrameBuffer.cpp index 4bd6a5a4..2de1f6f4 100644 --- a/FrameBuffer.cpp +++ b/FrameBuffer.cpp @@ -811,7 +811,8 @@ void FrameBufferToRDRAM::_copyWhite(FrameBuffer * _pBuffer) } } } - _pBuffer->m_RdramCrc = Adler32(0, RDRAM + _pBuffer->m_startAddress, (VI.width*VI.height) << _pBuffer->m_size >> 1); + _pBuffer->m_RdramCrc = textureCRC(RDRAM + _pBuffer->m_startAddress, _pBuffer->m_height, _pBuffer->m_width << _pBuffer->m_size >> 1); + _pBuffer->m_cleared = false; } @@ -880,7 +881,7 @@ void FrameBufferToRDRAM::CopyToRDRAM(u32 _address) } } } - pBuffer->m_RdramCrc = Adler32(0, RDRAM + _address, (VI.width*VI.height) << pBuffer->m_size >> 1); + pBuffer->m_RdramCrc = textureCRC(RDRAM + pBuffer->m_startAddress, pBuffer->m_height, pBuffer->m_width << pBuffer->m_size >> 1); pBuffer->m_cleared = false; #ifndef GLES2 glUnmapBuffer(GL_PIXEL_PACK_BUFFER); diff --git a/gDP.cpp b/gDP.cpp index 59b985b2..0212a150 100644 --- a/gDP.cpp +++ b/gDP.cpp @@ -427,7 +427,7 @@ bool CheckForFrameBufferTexture(u32 _address, u32 _bytes) else frameBufferList().removeBuffer(pBuffer->m_startAddress); } else if (pBuffer->m_RdramCrc != 0) { - const u32 crc = Adler32(0, RDRAM + pBuffer->m_startAddress, (VI.width*VI.height) << pBuffer->m_size >> 1); + const u32 crc = textureCRC(RDRAM + pBuffer->m_startAddress, pBuffer->m_height, pBuffer->m_width << pBuffer->m_size >> 1); bRes = (pBuffer->m_RdramCrc == crc); if (bRes) pBuffer->m_validityChecked = RSP.DList;