[WASAPI] fix stream types and frequencies enumeration
[xbmc.git] / xbmc / GUILargeTextureManager.cpp
blob6a3bfc6a8e151d50307f5ae8f5d960c42a1cf9f1
1 /*
2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "GUILargeTextureManager.h"
11 #include "ServiceBroker.h"
12 #include "TextureCache.h"
13 #include "commons/ilog.h"
14 #include "guilib/GUIComponent.h"
15 #include "guilib/Texture.h"
16 #include "settings/AdvancedSettings.h"
17 #include "settings/SettingsComponent.h"
18 #include "utils/JobManager.h"
19 #include "utils/TimeUtils.h"
20 #include "utils/log.h"
21 #include "windowing/GraphicContext.h"
22 #include "windowing/WinSystem.h"
24 #include <cassert>
25 #include <chrono>
26 #include <exception>
27 #include <mutex>
29 CImageLoader::CImageLoader(const std::string& path, const bool useCache)
30 : m_path(path), m_texture(nullptr)
32 m_use_cache = useCache;
35 CImageLoader::~CImageLoader() = default;
37 bool CImageLoader::DoWork()
39 bool needsChecking = false;
40 std::string loadPath;
42 std::string texturePath = CServiceBroker::GetGUI()->GetTextureManager().GetTexturePath(m_path);
43 if (texturePath.empty())
44 return false;
46 if (m_use_cache)
47 loadPath = CServiceBroker::GetTextureCache()->CheckCachedImage(texturePath, needsChecking);
48 else
49 loadPath = texturePath;
51 if (!loadPath.empty())
53 // direct route - load the image
54 auto start = std::chrono::steady_clock::now();
55 m_texture =
56 CTexture::LoadFromFile(loadPath, CServiceBroker::GetWinSystem()->GetGfxContext().GetWidth(),
57 CServiceBroker::GetWinSystem()->GetGfxContext().GetHeight());
59 auto end = std::chrono::steady_clock::now();
60 auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
62 if (duration.count() > 100)
63 CLog::Log(LOGDEBUG, "{} - took {} ms to load {}", __FUNCTION__, duration.count(), loadPath);
65 if (m_texture)
67 if (needsChecking)
68 CServiceBroker::GetTextureCache()->BackgroundCacheImage(texturePath);
70 if (CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_guiAsyncTextureUpload)
71 m_texture->LoadToGPUAsync();
73 return true;
76 // Fallthrough on failure:
77 CLog::Log(LOGERROR, "{} - Direct texture file loading failed for {}", __FUNCTION__, loadPath);
80 if (!m_use_cache)
81 return false; // We're done
83 // not in our texture cache or it failed to load from it, so try and load directly and then cache the result
84 CServiceBroker::GetTextureCache()->CacheImage(texturePath, &m_texture);
86 if (!m_texture)
87 return false;
89 if (CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_guiAsyncTextureUpload)
90 m_texture->LoadToGPUAsync();
92 return true;
95 CGUILargeTextureManager::CLargeTexture::CLargeTexture(const std::string &path):
96 m_path(path)
98 m_refCount = 1;
99 m_timeToDelete = 0;
102 CGUILargeTextureManager::CLargeTexture::~CLargeTexture()
104 assert(m_refCount == 0);
105 m_texture.Free();
108 void CGUILargeTextureManager::CLargeTexture::AddRef()
110 m_refCount++;
113 bool CGUILargeTextureManager::CLargeTexture::DecrRef(bool deleteImmediately)
115 assert(m_refCount);
116 m_refCount--;
117 if (m_refCount == 0)
119 if (deleteImmediately)
120 delete this;
121 else
122 m_timeToDelete = CTimeUtils::GetFrameTime() + TIME_TO_DELETE;
123 return true;
125 return false;
128 bool CGUILargeTextureManager::CLargeTexture::DeleteIfRequired(bool deleteImmediately)
130 if (m_refCount == 0 && (deleteImmediately || m_timeToDelete < CTimeUtils::GetFrameTime()))
132 delete this;
133 return true;
135 return false;
138 void CGUILargeTextureManager::CLargeTexture::SetTexture(std::unique_ptr<CTexture> texture)
140 assert(!m_texture.size());
141 if (texture)
143 const auto width = texture->GetWidth();
144 const auto height = texture->GetHeight();
145 m_texture.Set(std::move(texture), width, height);
149 CGUILargeTextureManager::CGUILargeTextureManager() = default;
151 CGUILargeTextureManager::~CGUILargeTextureManager() = default;
153 void CGUILargeTextureManager::CleanupUnusedImages(bool immediately)
155 std::unique_lock<CCriticalSection> lock(m_listSection);
156 // check for items to remove from allocated list, and remove
157 listIterator it = m_allocated.begin();
158 while (it != m_allocated.end())
160 CLargeTexture *image = *it;
161 if (image->DeleteIfRequired(immediately))
162 it = m_allocated.erase(it);
163 else
164 ++it;
168 // if available, increment reference count, and return the image.
169 // else, add to the queue list if appropriate.
170 bool CGUILargeTextureManager::GetImage(const std::string &path, CTextureArray &texture, bool firstRequest, const bool useCache)
172 std::unique_lock<CCriticalSection> lock(m_listSection);
173 for (listIterator it = m_allocated.begin(); it != m_allocated.end(); ++it)
175 CLargeTexture *image = *it;
176 if (image->GetPath() == path)
178 if (firstRequest)
179 image->AddRef();
180 texture = image->GetTexture();
181 return texture.size() > 0;
185 if (firstRequest)
186 QueueImage(path, useCache);
188 return true;
191 void CGUILargeTextureManager::ReleaseImage(const std::string &path, bool immediately)
193 std::unique_lock<CCriticalSection> lock(m_listSection);
194 for (listIterator it = m_allocated.begin(); it != m_allocated.end(); ++it)
196 CLargeTexture *image = *it;
197 if (image->GetPath() == path)
199 if (image->DecrRef(immediately) && immediately)
200 m_allocated.erase(it);
201 return;
204 for (queueIterator it = m_queued.begin(); it != m_queued.end(); ++it)
206 unsigned int id = it->first;
207 CLargeTexture *image = it->second;
208 if (image->GetPath() == path && image->DecrRef(true))
210 // cancel this job
211 CServiceBroker::GetJobManager()->CancelJob(id);
212 m_queued.erase(it);
213 return;
218 // queue the image, and start the background loader if necessary
219 void CGUILargeTextureManager::QueueImage(const std::string &path, bool useCache)
221 if (path.empty())
222 return;
224 std::unique_lock<CCriticalSection> lock(m_listSection);
225 for (queueIterator it = m_queued.begin(); it != m_queued.end(); ++it)
227 CLargeTexture *image = it->second;
228 if (image->GetPath() == path)
230 image->AddRef();
231 return; // already queued
235 // queue the item
236 CLargeTexture *image = new CLargeTexture(path);
237 unsigned int jobID = CServiceBroker::GetJobManager()->AddJob(new CImageLoader(path, useCache),
238 this, CJob::PRIORITY_NORMAL);
239 m_queued.emplace_back(jobID, image);
242 void CGUILargeTextureManager::OnJobComplete(unsigned int jobID, bool success, CJob *job)
244 // see if we still have this job id
245 std::unique_lock<CCriticalSection> lock(m_listSection);
246 for (queueIterator it = m_queued.begin(); it != m_queued.end(); ++it)
248 if (it->first == jobID)
249 { // found our job
250 CImageLoader *loader = static_cast<CImageLoader*>(job);
251 CLargeTexture *image = it->second;
252 image->SetTexture(std::move(loader->m_texture));
253 loader->m_texture = NULL; // we want to keep the texture, and jobs are auto-deleted.
254 m_queued.erase(it);
255 m_allocated.push_back(image);
256 return;