const CTextureArray& CGUITextureManager::Load(const std::string& strTextureName, bool checkBundleOnly /*= false */) { std::string strPath; static CTextureArray emptyTexture; int bundle = -1; int size = 0; if (!HasTexture(strTextureName, &strPath, &bundle, &size)) return emptyTexture; if (size) // we found the texture { for (int i = 0; i < (int)m_vecTextures.size(); ++i) { CTextureMap *pMap = m_vecTextures[i]; if (pMap->GetName() == strTextureName) { //CLog::Log(LOGDEBUG, "Total memusage %u", GetMemoryUsage()); return pMap->GetTexture(); } } // Whoops, not there. return emptyTexture; } for (ilistUnused i = m_unusedTextures.begin(); i != m_unusedTextures.end(); ++i) { CTextureMap* pMap = i->first; if (pMap->GetName() == strTextureName && i->second > 0) { m_vecTextures.push_back(pMap); m_unusedTextures.erase(i); return pMap->GetTexture(); } } if (checkBundleOnly && bundle == -1) return emptyTexture; //Lock here, we will do stuff that could break rendering CSingleLock lock(g_graphicsContext); #ifdef _DEBUG_TEXTURES int64_t start; start = CurrentHostCounter(); #endif if (bundle >= 0 && StringUtils::EndsWithNoCase(strPath, ".gif")) { CTextureMap* pMap = nullptr; CBaseTexture **pTextures = nullptr; int nLoops = 0, width = 0, height = 0; int* Delay = nullptr; int nImages = m_TexBundle[bundle].LoadAnim(strTextureName, &pTextures, width, height, nLoops, &Delay); if (!nImages) { CLog::Log(LOGERROR, "Texture manager unable to load bundled file: %s", strTextureName.c_str()); delete[] pTextures; delete[] Delay; return emptyTexture; } unsigned int maxWidth = 0; unsigned int maxHeight = 0; pMap = new CTextureMap(strTextureName, width, height, nLoops); for (int iImage = 0; iImage < nImages; ++iImage) { pMap->Add(pTextures[iImage], Delay[iImage]); maxWidth = std::max(maxWidth, pTextures[iImage]->GetWidth()); maxHeight = std::max(maxHeight, pTextures[iImage]->GetHeight()); } pMap->SetWidth((int)maxWidth); pMap->SetHeight((int)maxHeight); delete[] pTextures; delete[] Delay; if (pMap) { m_vecTextures.push_back(pMap); return pMap->GetTexture(); } } else if (StringUtils::EndsWithNoCase(strPath, ".gif") || StringUtils::EndsWithNoCase(strPath, ".apng")) { CTextureMap* pMap = nullptr; std::string mimeType; if (StringUtils::EndsWithNoCase(strPath, ".gif")) mimeType = "image/gif"; else if (StringUtils::EndsWithNoCase(strPath, ".apng")) mimeType = "image/apng"; XFILE::CFile file; XFILE::auto_buffer buf; CFFmpegImage anim(mimeType); pMap = new CTextureMap(strTextureName, 0, 0, 0); if (file.LoadFile(strPath, buf) <= 0 || !anim.Initialize((uint8_t*)buf.get(), buf.size()) || !pMap) { CLog::Log(LOGERROR, "Texture manager unable to load file: %s", CURL::GetRedacted(strPath).c_str()); file.Close(); return emptyTexture; } unsigned int maxWidth = 0; unsigned int maxHeight = 0; uint64_t maxMemoryUsage = 91238400;// 1920*1080*4*11 bytes, i.e, a total of approx. 12 full hd frames auto frame = anim.ReadFrame(); while (frame) { CTexture *glTexture = new CTexture(); if (glTexture) { glTexture->LoadFromMemory(anim.Width(), anim.Height(), frame->GetPitch(), XB_FMT_A8R8G8B8, true, frame->m_pImage); pMap->Add(glTexture, frame->m_delay); maxWidth = std::max(maxWidth, glTexture->GetWidth()); maxHeight = std::max(maxHeight, glTexture->GetHeight()); } if (pMap->GetMemoryUsage() <= maxMemoryUsage) { frame = anim.ReadFrame(); } else { CLog::Log(LOGDEBUG, "Memory limit (%" PRIu64 " bytes) exceeded, %i frames extracted from file : %s", (maxMemoryUsage/11)*12,pMap->GetTexture().size(), CURL::GetRedacted(strPath).c_str()); break; } } pMap->SetWidth((int)maxWidth); pMap->SetHeight((int)maxHeight); file.Close(); if (pMap) { m_vecTextures.push_back(pMap); return pMap->GetTexture(); } } CBaseTexture *pTexture = NULL; int width = 0, height = 0; if (bundle >= 0) { if (!m_TexBundle[bundle].LoadTexture(strTextureName, &pTexture, width, height)) { CLog::Log(LOGERROR, "Texture manager unable to load bundled file: %s", strTextureName.c_str()); return emptyTexture; } } else { pTexture = CBaseTexture::LoadFromFile(strPath); if (!pTexture) return emptyTexture; width = pTexture->GetWidth(); height = pTexture->GetHeight(); } if (!pTexture) return emptyTexture; CTextureMap* pMap = new CTextureMap(strTextureName, width, height, 0); pMap->Add(pTexture, 100); m_vecTextures.push_back(pMap); #ifdef _DEBUG_TEXTURES int64_t end, freq; end = CurrentHostCounter(); freq = CurrentHostFrequency(); char temp[200]; sprintf(temp, "Load %s: %.1fms%s\n", strPath.c_str(), 1000.f * (end - start) / freq, (bundle >= 0) ? " (bundled)" : ""); OutputDebugString(temp); #endif return pMap->GetTexture(); }
int CGUITextureManager::Load(const CStdString& strTextureName, bool checkBundleOnly /*= false */) { CStdString strPath; int bundle = -1; int size = 0; if (!HasTexture(strTextureName, &strPath, &bundle, &size)) return 0; if (size) // we found the texture return size; if (checkBundleOnly && bundle == -1) return 0; //Lock here, we will do stuff that could break rendering CSingleLock lock(g_graphicsContext); #ifdef _DEBUG int64_t start; start = CurrentHostCounter(); #endif if (strPath.Right(4).ToLower() == ".gif") { CTextureMap* pMap; if (bundle >= 0) { CBaseTexture **pTextures; int nLoops = 0, width = 0, height = 0; int* Delay; int nImages = m_TexBundle[bundle].LoadAnim(strTextureName, &pTextures, width, height, nLoops, &Delay); if (!nImages) { CLog::Log(LOGERROR, "Texture manager unable to load bundled file: %s", strTextureName.c_str()); return 0; } pMap = new CTextureMap(strTextureName, width, height, nLoops); for (int iImage = 0; iImage < nImages; ++iImage) { pMap->Add(pTextures[iImage], Delay[iImage]); } delete [] pTextures; delete [] Delay; } else { CAnimatedGifSet AnimatedGifSet; int iImages = AnimatedGifSet.LoadGIF(strPath.c_str()); if (iImages == 0) { CStdString rootPath = strPath.Left(g_SkinInfo->Path().GetLength()); if (0 == rootPath.CompareNoCase(g_SkinInfo->Path())) CLog::Log(LOGERROR, "Texture manager unable to load file: %s", strPath.c_str()); return 0; } int iWidth = AnimatedGifSet.FrameWidth; int iHeight = AnimatedGifSet.FrameHeight; // fixup our palette COLOR *palette = AnimatedGifSet.m_vecimg[0]->Palette; // set the alpha values to fully opaque for (int i = 0; i < 256; i++) palette[i].x = 0xff; // and set the transparent colour if (AnimatedGifSet.m_vecimg[0]->Transparency && AnimatedGifSet.m_vecimg[0]->Transparent >= 0) palette[AnimatedGifSet.m_vecimg[0]->Transparent].x = 0; pMap = new CTextureMap(strTextureName, iWidth, iHeight, AnimatedGifSet.nLoops); for (int iImage = 0; iImage < iImages; iImage++) { CTexture *glTexture = new CTexture(); if (glTexture) { CAnimatedGif* pImage = AnimatedGifSet.m_vecimg[iImage]; glTexture->LoadPaletted(pImage->Width, pImage->Height, pImage->BytesPerRow, XB_FMT_A8R8G8B8, (unsigned char *)pImage->Raster, palette); pMap->Add(glTexture, pImage->Delay); } } // of for (int iImage=0; iImage < iImages; iImage++) } #ifdef _DEBUG int64_t end, freq; end = CurrentHostCounter(); freq = CurrentHostFrequency(); char temp[200]; sprintf(temp, "Load %s: %.1fms%s\n", strPath.c_str(), 1000.f * (end - start) / freq, (bundle >= 0) ? " (bundled)" : ""); OutputDebugString(temp); #endif m_vecTextures.push_back(pMap); return 1; } // of if (strPath.Right(4).ToLower()==".gif") CBaseTexture *pTexture = NULL; int width = 0, height = 0; if (bundle >= 0) { if (FAILED(m_TexBundle[bundle].LoadTexture(strTextureName, &pTexture, width, height))) { CLog::Log(LOGERROR, "Texture manager unable to load bundled file: %s", strTextureName.c_str()); return 0; } } else { pTexture = new CTexture(); if(!pTexture->LoadFromFile(strPath)) return 0; width = pTexture->GetWidth(); height = pTexture->GetHeight(); } if (!pTexture) return 0; CTextureMap* pMap = new CTextureMap(strTextureName, width, height, 0); pMap->Add(pTexture, 100); m_vecTextures.push_back(pMap); #ifdef _DEBUG_TEXTURES int64_t end, freq; end = CurrentHostCounter(); freq = CurrentHostFrequency(); char temp[200]; sprintf(temp, "Load %s: %.1fms%s\n", strPath.c_str(), 1000.f * (end - start) / freq, (bundle >= 0) ? " (bundled)" : ""); OutputDebugString(temp); #endif return 1; }
int CGUITextureManager::Load(const CStdString& strTextureName, DWORD dwColorKey, bool checkBundleOnly /*= false */) { CStdString strPath; int bundle = -1; int size = 0; if (!HasTexture(strTextureName, &strPath, &bundle, &size)) return 0; if (size) // we found the texture return size; // See if texture is being overridden. CStdString strTextureFile = strTextureName; CStdString strTextureOverridePath1; CStdString strTextureOverridePath2; CStdString strExt = CUtil::GetExtension(strTextureFile); CUtil::RemoveExtension(strTextureFile); // Check original format and JPEG. strTextureOverridePath1.Format("%s/media/%s%s", _P("Q:"), strTextureFile.c_str(), strExt.c_str()); strTextureOverridePath2.Format("%s/media/%s.jpg", _P("Q:"), strTextureFile.c_str(), strExt.c_str()); if (checkBundleOnly && bundle == -1) return 0; if (XFILE::CFile::Exists(strTextureOverridePath1)) { strPath = strTextureOverridePath1; bundle = -1; } else if (XFILE::CFile::Exists(strTextureOverridePath2)) { strPath = strTextureOverridePath2; bundle = -1; } else if (bundle == -1) strPath = GetTexturePath(strTextureName); else strPath = strTextureName; //Lock here, we will do stuff that could break rendering CSingleLock lock(g_graphicsContext); #ifndef HAS_SDL LPDIRECT3DTEXTURE8 pTexture; LPDIRECT3DPALETTE8 pPal = 0; #else SDL_Surface* pTexture; SDL_Palette* pPal = NULL; #endif #ifdef _DEBUG LARGE_INTEGER start; QueryPerformanceCounter(&start); #endif D3DXIMAGE_INFO info; if (strPath.Right(4).ToLower() == ".gif") { CTextureMap* pMap; if (bundle >= 0) { #ifndef HAS_SDL LPDIRECT3DTEXTURE8* pTextures; #else SDL_Surface** pTextures; #endif int nLoops = 0; int* Delay; #ifndef HAS_SDL int nImages = m_TexBundle[bundle].LoadAnim(g_graphicsContext.Get3DDevice(), strTextureName, &info, &pTextures, &pPal, nLoops, &Delay); #else int nImages = m_TexBundle[bundle].LoadAnim(strTextureName, &info, &pTextures, &pPal, nLoops, &Delay); #endif if (!nImages) { CLog::Log(LOGERROR, "Texture manager unable to load bundled file: %s", strTextureName.c_str()); return 0; } pMap = new CTextureMap(strTextureName); for (int iImage = 0; iImage < nImages; ++iImage) { CTexture* pclsTexture = new CTexture(pTextures[iImage], info.Width, info.Height, true, 100, pPal); pclsTexture->SetDelay(Delay[iImage]); pclsTexture->SetLoops(nLoops); pMap->Add(pclsTexture); #ifndef HAS_SDL delete pTextures[iImage]; #else SDL_FreeSurface(pTextures[iImage]); #endif } delete [] pTextures; delete [] Delay; } else { CAnimatedGifSet AnimatedGifSet; int iImages = AnimatedGifSet.LoadGIF(strPath.c_str()); if (iImages == 0) { if (!strnicmp(strPath.c_str(), "q:\\skin", 7)) CLog::Log(LOGERROR, "Texture manager unable to load file: %s", strPath.c_str()); return 0; } int iWidth = AnimatedGifSet.FrameWidth; int iHeight = AnimatedGifSet.FrameHeight; int iPaletteSize = (1 << AnimatedGifSet.m_vecimg[0]->BPP); pMap = new CTextureMap(strTextureName); for (int iImage = 0; iImage < iImages; iImage++) { int w = iWidth; int h = iHeight; #if defined(HAS_SDL) pTexture = SDL_CreateRGBSurface(SDL_HWSURFACE, w, h, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000); if (pTexture) #else if (D3DXCreateTexture(g_graphicsContext.Get3DDevice(), w, h, 1, 0, D3DFMT_LIN_A8R8G8B8, D3DPOOL_MANAGED, &pTexture) == D3D_OK) #endif { CAnimatedGif* pImage = AnimatedGifSet.m_vecimg[iImage]; #ifndef HAS_SDL D3DLOCKED_RECT lr; RECT rc = { 0, 0, pImage->Width, pImage->Height }; if ( D3D_OK == pTexture->LockRect( 0, &lr, &rc, 0 )) #else if (SDL_LockSurface(pTexture) != -1) #endif { COLOR *palette = AnimatedGifSet.m_vecimg[0]->Palette; // set the alpha values to fully opaque for (int i = 0; i < iPaletteSize; i++) palette[i].x = 0xff; // and set the transparent colour if (AnimatedGifSet.m_vecimg[0]->Transparency && AnimatedGifSet.m_vecimg[0]->Transparent >= 0) palette[AnimatedGifSet.m_vecimg[0]->Transparent].x = 0; #ifdef HAS_SDL // Allocate memory for the actual pixels in the surface and set the surface BYTE* pixels = (BYTE*) malloc(w * h * 4); pTexture->pixels = pixels; #endif for (int y = 0; y < pImage->Height; y++) { #ifndef HAS_SDL BYTE *dest = (BYTE *)lr.pBits + y * lr.Pitch; #else BYTE *dest = (BYTE *)pixels + (y * w * 4); #endif BYTE *source = (BYTE *)pImage->Raster + y * pImage->BytesPerRow; for (int x = 0; x < pImage->Width; x++) { COLOR col = palette[*source++]; *dest++ = col.b; *dest++ = col.g; *dest++ = col.r; *dest++ = col.x; } } #ifndef HAS_SDL pTexture->UnlockRect( 0 ); #else SDL_UnlockSurface(pTexture); #endif CTexture* pclsTexture = new CTexture(pTexture, iWidth, iHeight, false, 100, pPal); pclsTexture->SetDelay(pImage->Delay); pclsTexture->SetLoops(AnimatedGifSet.nLoops); #ifdef HAS_SDL free(pixels); #endif #ifdef HAS_SDL_2D SDL_FreeSurface(pTexture); #endif pMap->Add(pclsTexture); } } } // of for (int iImage=0; iImage < iImages; iImage++) } #ifdef _DEBUG LARGE_INTEGER end, freq; QueryPerformanceCounter(&end); QueryPerformanceFrequency(&freq); char temp[200]; sprintf(temp, "Load %s: %.1fms%s\n", strPath.c_str(), 1000.f * (end.QuadPart - start.QuadPart) / freq.QuadPart, (bundle >= 0) ? " (bundled)" : ""); OutputDebugString(temp); #endif m_vecTextures.push_back(pMap); return pMap->size(); } // of if (strPath.Right(4).ToLower()==".gif") if (bundle >= 0) { #ifndef HAS_SDL if (FAILED(m_TexBundle[bundle].LoadTexture(g_graphicsContext.Get3DDevice(), strTextureName, &info, &pTexture, &pPal))) #else if (FAILED(m_TexBundle[bundle].LoadTexture(strTextureName, &info, &pTexture, &pPal))) #endif { CLog::Log(LOGERROR, "Texture manager unable to load bundled file: %s", strTextureName.c_str()); return 0; } } else { // normal picture // convert from utf8 CStdString texturePath; g_charsetConverter.utf8ToStringCharset(_P(strPath), texturePath); #ifndef HAS_SDL if ( D3DXCreateTextureFromFileEx(g_graphicsContext.Get3DDevice(), texturePath.c_str(), D3DX_DEFAULT, D3DX_DEFAULT, 1, 0, D3DFMT_LIN_A8R8G8B8, D3DPOOL_MANAGED, D3DX_FILTER_NONE , D3DX_FILTER_NONE, dwColorKey, &info, NULL, &pTexture) != D3D_OK) { if (!strnicmp(strPath.c_str(), "q:\\skin", 7)) CLog::Log(LOGERROR, "Texture manager unable to load file: %s", strPath.c_str()); return 0; } #else SDL_Surface *original = IMG_Load(texturePath.c_str()); CPicture pic; if (!original && !(original = pic.Load(texturePath, MAX_PICTURE_WIDTH, MAX_PICTURE_HEIGHT))) { CLog::Log(LOGERROR, "Texture manager unable to load file: %s", strPath.c_str()); return 0; } // make sure the texture format is correct SDL_PixelFormat format; format.palette = 0; format.colorkey = 0; format.alpha = 0; format.BitsPerPixel = 32; format.BytesPerPixel = 4; format.Amask = 0xff000000; format.Ashift = 24; format.Rmask = 0x00ff0000; format.Rshift = 16; format.Gmask = 0x0000ff00; format.Gshift = 8; format.Bmask = 0x000000ff; format.Bshift = 0; #ifdef HAS_SDL_OPENGL pTexture = SDL_ConvertSurface(original, &format, SDL_SWSURFACE); #else pTexture = SDL_ConvertSurface(original, &format, SDL_HWSURFACE); #endif SDL_FreeSurface(original); if (!pTexture) { CLog::Log(LOGERROR, "Texture manager unable to load file: %s", strPath.c_str()); return 0; } info.Width = pTexture->w; info.Height = pTexture->h; #endif } CTextureMap* pMap = new CTextureMap(strTextureName); CTexture* pclsTexture = new CTexture(pTexture, info.Width, info.Height, bundle >= 0, 100, pPal); pMap->Add(pclsTexture); m_vecTextures.push_back(pMap); #ifdef HAS_SDL_OPENGL SDL_FreeSurface(pTexture); #endif #ifdef _DEBUG LARGE_INTEGER end, freq; QueryPerformanceCounter(&end); QueryPerformanceFrequency(&freq); char temp[200]; sprintf(temp, "Load %s: %.1fms%s\n", strPath.c_str(), 1000.f * (end.QuadPart - start.QuadPart) / freq.QuadPart, (bundle >= 0) ? " (bundled)" : ""); OutputDebugString(temp); #endif return 1; }
const CTextureArray& CGUITextureManager::Load(const std::string& strTextureName, bool checkBundleOnly /*= false */) { std::string strPath; static CTextureArray emptyTexture; int bundle = -1; int size = 0; if (!HasTexture(strTextureName, &strPath, &bundle, &size)) return emptyTexture; if (size) // we found the texture { for (int i = 0; i < (int)m_vecTextures.size(); ++i) { CTextureMap *pMap = m_vecTextures[i]; if (pMap->GetName() == strTextureName) { //CLog::Log(LOGDEBUG, "Total memusage %u", GetMemoryUsage()); return pMap->GetTexture(); } } // Whoops, not there. return emptyTexture; } for (ilistUnused i = m_unusedTextures.begin(); i != m_unusedTextures.end(); ++i) { CTextureMap* pMap = i->first; if (pMap->GetName() == strTextureName && i->second > 0) { m_vecTextures.push_back(pMap); m_unusedTextures.erase(i); return pMap->GetTexture(); } } if (checkBundleOnly && bundle == -1) return emptyTexture; //Lock here, we will do stuff that could break rendering CSingleLock lock(g_graphicsContext); #ifdef _DEBUG_TEXTURES int64_t start; start = CurrentHostCounter(); #endif if (StringUtils::EndsWithNoCase(strPath, ".gif")) { CTextureMap* pMap = nullptr; if (bundle >= 0) { CBaseTexture **pTextures; int nLoops = 0, width = 0, height = 0; int* Delay; int nImages = m_TexBundle[bundle].LoadAnim(strTextureName, &pTextures, width, height, nLoops, &Delay); if (!nImages) { CLog::Log(LOGERROR, "Texture manager unable to load bundled file: %s", strTextureName.c_str()); delete [] pTextures; delete [] Delay; return emptyTexture; } pMap = new CTextureMap(strTextureName, width, height, nLoops); for (int iImage = 0; iImage < nImages; ++iImage) { pMap->Add(pTextures[iImage], Delay[iImage]); } delete [] pTextures; delete [] Delay; } else { #if defined(HAS_GIFLIB) Gif gif; if(!gif.LoadGif(strPath.c_str())) { if (StringUtils::StartsWith(strPath, g_SkinInfo->Path())) CLog::Log(LOGERROR, "Texture manager unable to load file: %s", strPath.c_str()); return emptyTexture; } pMap = new CTextureMap(strTextureName, gif.Width(), gif.Height(), gif.GetNumLoops()); for (auto frame : gif.GetFrames()) { CTexture *glTexture = new CTexture(); if (glTexture) { glTexture->LoadFromMemory(gif.Width(), gif.Height(), gif.GetPitch(), XB_FMT_A8R8G8B8, false, frame->m_pImage); pMap->Add(glTexture, frame->m_delay); } } #endif//HAS_GIFLIB } if (pMap) { m_vecTextures.push_back(pMap); return pMap->GetTexture(); } } // of if (strPath.Right(4).ToLower()==".gif") CBaseTexture *pTexture = NULL; int width = 0, height = 0; if (bundle >= 0) { if (!m_TexBundle[bundle].LoadTexture(strTextureName, &pTexture, width, height)) { CLog::Log(LOGERROR, "Texture manager unable to load bundled file: %s", strTextureName.c_str()); return emptyTexture; } } else { pTexture = CBaseTexture::LoadFromFile(strPath); if (!pTexture) return emptyTexture; width = pTexture->GetWidth(); height = pTexture->GetHeight(); } if (!pTexture) return emptyTexture; CTextureMap* pMap = new CTextureMap(strTextureName, width, height, 0); pMap->Add(pTexture, 100); m_vecTextures.push_back(pMap); #ifdef _DEBUG_TEXTURES int64_t end, freq; end = CurrentHostCounter(); freq = CurrentHostFrequency(); char temp[200]; sprintf(temp, "Load %s: %.1fms%s\n", strPath.c_str(), 1000.f * (end - start) / freq, (bundle >= 0) ? " (bundled)" : ""); OutputDebugString(temp); #endif return pMap->GetTexture(); }