COGLTexture::COGLTexture(uint32 dwWidth, uint32 dwHeight, TextureUsage usage) : CTexture(dwWidth,dwHeight,usage), m_glInternalFmt(GL_RGBA) { // FIXME: If usage is AS_RENDER_TARGET, we need to create pbuffer instead of regular texture m_dwTextureFmt = TEXTURE_FMT_A8R8G8B8; // Always use 32bit to load texture glGenTextures( 1, &m_dwTextureName ); OPENGL_CHECK_ERRORS; // Make the width and height be the power of 2 uint32 w; for (w = 1; w < dwWidth; w <<= 1); m_dwCreatedTextureWidth = w; for (w = 1; w < dwHeight; w <<= 1); m_dwCreatedTextureHeight = w; if (dwWidth*dwHeight > 256*256) TRACE4("Large texture: (%d x %d), created as (%d x %d)", dwWidth, dwHeight,m_dwCreatedTextureWidth,m_dwCreatedTextureHeight); m_fYScale = (float)m_dwCreatedTextureHeight/(float)m_dwHeight; m_fXScale = (float)m_dwCreatedTextureWidth/(float)m_dwWidth; m_pTexture = malloc(m_dwCreatedTextureWidth * m_dwCreatedTextureHeight * GetPixelSize()); switch( options.textureQuality ) { case TXT_QUALITY_DEFAULT: if( options.colorQuality == TEXTURE_FMT_A4R4G4B4 ) m_glInternalFmt = GL_RGBA4; break; case TXT_QUALITY_32BIT: break; case TXT_QUALITY_16BIT: m_glInternalFmt = GL_RGBA4; break; }; #ifndef USE_GLES m_glFmt = GL_BGRA; m_glType = GL_UNSIGNED_INT_8_8_8_8_REV; #else m_glInternalFmt = m_glFmt = COGLGraphicsContext::Get()->IsSupportTextureFormatBGRA() ? GL_BGRA_EXT : GL_RGBA; m_glType = GL_UNSIGNED_BYTE; #endif LOG_TEXTURE(TRACE2("New texture: (%d, %d)", dwWidth, dwHeight)); // We create the OGL texture here and will use glTexSubImage2D to increase performance. glBindTexture(GL_TEXTURE_2D, m_dwTextureName); OPENGL_CHECK_ERRORS; glTexImage2D(GL_TEXTURE_2D, 0, m_glInternalFmt, m_dwCreatedTextureWidth, m_dwCreatedTextureHeight, 0, m_glFmt, m_glType, NULL); OPENGL_CHECK_ERRORS; }
COGLTexture::COGLTexture(uint32_t dwWidth, uint32_t dwHeight, TextureUsage usage) : CTexture(dwWidth,dwHeight,usage), m_glFmt(GL_RGBA) { // FIXME: If usage is AS_RENDER_TARGET, we need to create pbuffer instead of regular texture m_dwTextureFmt = TEXTURE_FMT_A8R8G8B8; // Always use 32bit to load texture glGenTextures( 1, &m_dwTextureName ); OPENGL_CHECK_ERRORS; // Make the width and height be the power of 2 uint32_t w; for (w = 1; w < dwWidth; w <<= 1); m_dwCreatedTextureWidth = w; for (w = 1; w < dwHeight; w <<= 1); m_dwCreatedTextureHeight = w; if (dwWidth*dwHeight > 256*256) TRACE4("Large texture: (%d x %d), created as (%d x %d)", dwWidth, dwHeight,m_dwCreatedTextureWidth,m_dwCreatedTextureHeight); m_fYScale = (float)m_dwCreatedTextureHeight/(float)m_dwHeight; m_fXScale = (float)m_dwCreatedTextureWidth/(float)m_dwWidth; m_pTexture = malloc(m_dwCreatedTextureWidth * m_dwCreatedTextureHeight * GetPixelSize()); switch( options.textureQuality ) { case TXT_QUALITY_DEFAULT: if( options.colorQuality == TEXTURE_FMT_A4R4G4B4 ) m_glFmt = GL_RGBA4; break; case TXT_QUALITY_32BIT: break; case TXT_QUALITY_16BIT: m_glFmt = GL_RGBA4; break; }; LOG_TEXTURE(TRACE2("New texture: (%d, %d)", dwWidth, dwHeight)); glBindTexture(GL_TEXTURE_2D, m_dwTextureName); glTexImage2D(GL_TEXTURE_2D, 0, m_glFmt, m_dwCreatedTextureWidth, m_dwCreatedTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_pTexture); }
TxtrCacheEntry * CTextureManager::GetTexture(TxtrInfo * pgti, bool fromTMEM, bool doCRCCheck, bool AutoExtendTexture) { TxtrCacheEntry *pEntry; if( g_curRomInfo.bDisableTextureCRC ) doCRCCheck = false; gRDP.texturesAreReloaded = true; dwAsmCRC = 0; uint32 dwPalCRC = 0; pEntry = GetTxtrCacheEntry(pgti); bool loadFromTextureBuffer=false; int txtBufIdxToLoadFrom = -1; if( (frameBufferOptions.bCheckRenderTextures&&!frameBufferOptions.bWriteBackBufToRDRAM) || (frameBufferOptions.bCheckBackBufs&&!frameBufferOptions.bWriteBackBufToRDRAM) ) { txtBufIdxToLoadFrom = g_pFrameBufferManager->CheckAddrInRenderTextures(pgti->Address); if( txtBufIdxToLoadFrom >= 0 ) { loadFromTextureBuffer = true; // Check if it is the same size, RenderTextureInfo &info = gRenderTextureInfos[txtBufIdxToLoadFrom]; //if( info.pRenderTexture && info.CI_Info.dwAddr == pgti->Address && info.CI_Info.dwFormat == pgti->Format if( info.pRenderTexture && info.CI_Info.dwFormat == pgti->Format && info.CI_Info.dwSize == pgti->Size ) { info.txtEntry.ti = *pgti; return &info.txtEntry; } } } if( frameBufferOptions.bCheckBackBufs && g_pFrameBufferManager->CheckAddrInBackBuffers(pgti->Address, pgti->HeightToLoad*pgti->Pitch) >= 0 ) { if( !frameBufferOptions.bWriteBackBufToRDRAM ) { // Load the texture from recent back buffer txtBufIdxToLoadFrom = g_pFrameBufferManager->CheckAddrInRenderTextures(pgti->Address); if( txtBufIdxToLoadFrom >= 0 ) { loadFromTextureBuffer = true; // Check if it is the same size, RenderTextureInfo &info = gRenderTextureInfos[txtBufIdxToLoadFrom]; //if( info.pRenderTexture && info.CI_Info.dwAddr == pgti->Address && info.CI_Info.dwFormat == pgti->Format if( info.pRenderTexture && info.CI_Info.dwFormat == pgti->Format && info.CI_Info.dwSize == pgti->Size ) { info.txtEntry.ti = *pgti; return &info.txtEntry; } } } } if (pEntry && pEntry->dwTimeLastUsed == status.gRDPTime && status.gDlistCount != 0 && !status.bN64FrameBufferIsUsed ) // This is not good, Palatte may changes { // We've already calculated a CRC this frame! dwAsmCRC = pEntry->dwCRC; } else { if ( doCRCCheck ) { if( loadFromTextureBuffer ) dwAsmCRC = gRenderTextureInfos[txtBufIdxToLoadFrom].crcInRDRAM; else CalculateRDRAMCRC(pgti->pPhysicalAddress, pgti->LeftToLoad, pgti->TopToLoad, pgti->WidthToLoad, pgti->HeightToLoad, pgti->Size, pgti->Pitch); } } int maxCI = 0; if ( doCRCCheck && (pgti->Format == TXT_FMT_CI || (pgti->Format == TXT_FMT_RGBA && pgti->Size <= TXT_SIZE_8b ))) { //maxCI = pgti->Size == TXT_SIZE_8b ? 255 : 15; extern unsigned char CalculateMaxCI(void *pPhysicalAddress, uint32 left, uint32 top, uint32 width, uint32 height, uint32 size, uint32 pitchInBytes ); if( !pEntry || pEntry->dwCRC != dwAsmCRC || pEntry->maxCI < 0 ) { maxCI = CalculateMaxCI(pgti->pPhysicalAddress, pgti->LeftToLoad, pgti->TopToLoad, pgti->WidthToLoad, pgti->HeightToLoad, pgti->Size, pgti->Pitch); } else { maxCI = pEntry->maxCI; } //Check PAL CRC uint8 * pStart; uint32 dwPalSize = 16; uint32 dwOffset; if( pgti->Size == TXT_SIZE_8b ) { dwPalSize = 256; dwOffset = 0; } else { dwOffset = pgti->Palette << 4; } pStart = (uint8*)pgti->PalAddress+dwOffset*2; //uint32 y; //for (y = 0; y < dwPalSize*2; y+=4) //{ // dwPalCRC = (dwPalCRC + *(uint32*)&pStart[y]); //} uint32 dwAsmCRCSave = dwAsmCRC; //dwPalCRC = CalculateRDRAMCRC(pStart, 0, 0, dwPalSize, 1, TXT_SIZE_16b, dwPalSize*2); dwPalCRC = CalculateRDRAMCRC(pStart, 0, 0, maxCI+1, 1, TXT_SIZE_16b, dwPalSize*2); dwAsmCRC = dwAsmCRCSave; } if (pEntry && doCRCCheck ) { if(pEntry->dwCRC == dwAsmCRC && pEntry->dwPalCRC == dwPalCRC && (!loadFromTextureBuffer || gRenderTextureInfos[txtBufIdxToLoadFrom].updateAtFrame < pEntry->FrameLastUsed ) ) { // Tile is ok, return pEntry->dwUses++; pEntry->dwTimeLastUsed = status.gRDPTime; pEntry->FrameLastUsed = status.gDlistCount; LOG_TEXTURE(TRACE0(" Use current texture:\n")); pEntry->lastEntry = g_lastTextureEntry; g_lastTextureEntry = pEntry; lastEntryModified = false; DEBUGGER_IF_DUMP((pauseAtNext && loadFromTextureBuffer) , {DebuggerAppendMsg("Load cached texture from render_texture");} );
TxtrCacheEntry * CTextureManager::GetTexture(TxtrInfo * pgti, bool fromTMEM, bool doCRCCheck, bool AutoExtendTexture) { TxtrCacheEntry *pEntry; if( g_curRomInfo.bDisableTextureCRC ) doCRCCheck = false; gRDP.texturesAreReloaded = true; dwAsmCRC = 0; uint32 dwPalCRC = 0; pEntry = GetTxtrCacheEntry(pgti); bool loadFromTextureBuffer=false; int txtBufIdxToLoadFrom = -1; if( (frameBufferOptions.bCheckRenderTextures&&!frameBufferOptions.bWriteBackBufToRDRAM) || (frameBufferOptions.bCheckBackBufs&&!frameBufferOptions.bWriteBackBufToRDRAM) ) { txtBufIdxToLoadFrom = g_pFrameBufferManager->CheckAddrInRenderTextures(pgti->Address); if( txtBufIdxToLoadFrom >= 0 ) { loadFromTextureBuffer = true; // Check if it is the same size, RenderTextureInfo &info = gRenderTextureInfos[txtBufIdxToLoadFrom]; //if( info.pRenderTexture && info.CI_Info.dwAddr == pgti->Address && info.CI_Info.dwFormat == pgti->Format if( info.pRenderTexture && info.CI_Info.dwFormat == pgti->Format && info.CI_Info.dwSize == pgti->Size ) { info.txtEntry.ti = *pgti; return &info.txtEntry; } } } bool loadFromBackBuffer=false; if( frameBufferOptions.bCheckBackBufs && g_pFrameBufferManager->CheckAddrInBackBuffers(pgti->Address, pgti->HeightToLoad*pgti->Pitch) >= 0 ) { if( !frameBufferOptions.bWriteBackBufToRDRAM ) { // Load the texture from recent back buffer loadFromBackBuffer = true; txtBufIdxToLoadFrom = g_pFrameBufferManager->CheckAddrInRenderTextures(pgti->Address); if( txtBufIdxToLoadFrom >= 0 ) { loadFromTextureBuffer = true; // Check if it is the same size, RenderTextureInfo &info = gRenderTextureInfos[txtBufIdxToLoadFrom]; //if( info.pRenderTexture && info.CI_Info.dwAddr == pgti->Address && info.CI_Info.dwFormat == pgti->Format if( info.pRenderTexture && info.CI_Info.dwFormat == pgti->Format && info.CI_Info.dwSize == pgti->Size ) { info.txtEntry.ti = *pgti; return &info.txtEntry; } } } } if (pEntry && pEntry->dwTimeLastUsed == status.gRDPTime && status.gDlistCount != 0 && !status.bN64FrameBufferIsUsed ) // This is not good, Palatte may changes { // We've already calculated a CRC this frame! dwAsmCRC = pEntry->dwCRC; } else { if ( doCRCCheck ) { if( loadFromTextureBuffer ) dwAsmCRC = gRenderTextureInfos[txtBufIdxToLoadFrom].crcInRDRAM; else CalculateRDRAMCRC(pgti->pPhysicalAddress, pgti->LeftToLoad, pgti->TopToLoad, pgti->WidthToLoad, pgti->HeightToLoad, pgti->Size, pgti->Pitch); } } int maxCI = 0; if ( doCRCCheck && (pgti->Format == TXT_FMT_CI || (pgti->Format == TXT_FMT_RGBA && pgti->Size <= TXT_SIZE_8b ))) { //maxCI = pgti->Size == TXT_SIZE_8b ? 255 : 15; extern BYTE CalculateMaxCI(void *pPhysicalAddress, uint32 left, uint32 top, uint32 width, uint32 height, uint32 size, uint32 pitchInBytes ); if( !pEntry || pEntry->dwCRC != dwAsmCRC || pEntry->maxCI < 0 ) { maxCI = CalculateMaxCI(pgti->pPhysicalAddress, pgti->LeftToLoad, pgti->TopToLoad, pgti->WidthToLoad, pgti->HeightToLoad, pgti->Size, pgti->Pitch); } else { maxCI = pEntry->maxCI; } //Check PAL CRC uint8 * pStart; uint32 dwPalSize = 16; uint32 dwOffset; if( pgti->Size == TXT_SIZE_8b ) { dwPalSize = 256; dwOffset = 0; } else { dwOffset = pgti->Palette << 4; } pStart = (uint8*)pgti->PalAddress+dwOffset*2; //uint32 y; //for (y = 0; y < dwPalSize*2; y+=4) //{ // dwPalCRC = (dwPalCRC + *(uint32*)&pStart[y]); //} uint32 dwAsmCRCSave = dwAsmCRC; //dwPalCRC = CalculateRDRAMCRC(pStart, 0, 0, dwPalSize, 1, TXT_SIZE_16b, dwPalSize*2); dwPalCRC = CalculateRDRAMCRC(pStart, 0, 0, maxCI+1, 1, TXT_SIZE_16b, dwPalSize*2); dwAsmCRC = dwAsmCRCSave; } // Fix for textures where ti is identical. In this case just the first texture has been added to the Cache. // for further instances this texture has just been replaced instead of adding the additional texture to the same index // in the cachelist. This was causing the slowdowns. Thus we have to iterate through the bucket of the cache list and see // which of the textures that have been placed to it is the one we are looking for if(pEntry && doCRCCheck && pEntry->dwCRC == dwAsmCRC && pEntry->dwPalCRC != dwPalCRC && (!loadFromTextureBuffer || gRenderTextureInfos[txtBufIdxToLoadFrom].updateAtFrame < pEntry->FrameLastUsed )){ bool bChecksumDoMatch=false; // iterate through all textures located in the same bucket while(pEntry->pNext){ // check the next texture in the same bucket pEntry = pEntry->pNext; // let's see if this one is the one we are actually looking for if(pEntry->dwCRC == dwAsmCRC && pEntry->dwPalCRC == dwPalCRC && (!loadFromTextureBuffer || gRenderTextureInfos[txtBufIdxToLoadFrom].updateAtFrame < pEntry->FrameLastUsed )){ // found it in the neighbourhood bChecksumDoMatch = true; break; } } // cannot find it if(!bChecksumDoMatch){ // try to load it pEntry = NULL; } } if (pEntry && doCRCCheck ) { if(pEntry->dwCRC == dwAsmCRC && pEntry->dwPalCRC == dwPalCRC && (!loadFromTextureBuffer || gRenderTextureInfos[txtBufIdxToLoadFrom].updateAtFrame < pEntry->FrameLastUsed ) ) { // Tile is ok, return pEntry->dwUses++; pEntry->dwTimeLastUsed = status.gRDPTime; pEntry->FrameLastUsed = status.gDlistCount; LOG_TEXTURE(TRACE0(" Use current texture:\n")); pEntry->lastEntry = g_lastTextureEntry; g_lastTextureEntry = pEntry; lastEntryModified = false; DEBUGGER_IF_DUMP((pauseAtNext && loadFromTextureBuffer) , {DebuggerAppendMsg("Load cached texture from render_texture");} );