llimagedecodethread.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /**
  2. * @file llimagedecodethread.cpp
  3. * @brief Image decode thread class implementation.
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewergpl$
  6. *
  7. * Copyright (c) 2001-2009, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #include "linden_common.h"
  33. #include "llimagedecodethread.h"
  34. #include "llapp.h" // For LLApp::isExiting()
  35. #include "llsys.h" // For LLCPUInfo
  36. #include "lltimer.h" // For ms_sleep()
  37. #include "hbtracy.h"
  38. // Global variable
  39. LLImageDecodeThread* gImageDecodeThreadp = NULL;
  40. ///////////////////////////////////////////////////////////////////////////////
  41. // LLImageDecodeThread::ImageRequest sub-class. Where decode actually happens.
  42. ///////////////////////////////////////////////////////////////////////////////
  43. LLImageDecodeThread::ImageRequest::ImageRequest(
  44. const LLPointer<LLImageFormatted>& image, S32 discard, bool needs_aux,
  45. const LLPointer<Responder>& responder)
  46. : mFormattedImage(image),
  47. mDiscardLevel(discard),
  48. mNeedsAux(needs_aux),
  49. mResponder(responder),
  50. mDecodedRaw(false),
  51. mDecodedAux(false)
  52. {
  53. }
  54. //virtual
  55. LLImageDecodeThread::ImageRequest::~ImageRequest()
  56. {
  57. mDecodedImageRaw = NULL;
  58. mDecodedImageAux = NULL;
  59. mFormattedImage = NULL;
  60. }
  61. bool LLImageDecodeThread::ImageRequest::processRequest()
  62. {
  63. if (mFormattedImage.isNull())
  64. {
  65. return true;
  66. }
  67. bool done = true;
  68. if (!mDecodedRaw)
  69. {
  70. // Decode primary channels
  71. if (mDecodedImageRaw.isNull())
  72. {
  73. // Parse formatted header
  74. if (!mFormattedImage->updateData())
  75. {
  76. return true; // Done (failed)
  77. }
  78. U16 width = mFormattedImage->getWidth();
  79. U16 height = mFormattedImage->getHeight();
  80. S8 comps = mFormattedImage->getComponents();
  81. if (width * height * comps == 0)
  82. {
  83. return true; // Done (failed)
  84. }
  85. if (mDiscardLevel >= 0)
  86. {
  87. mFormattedImage->setDiscardLevel(mDiscardLevel);
  88. }
  89. mDecodedImageRaw = new LLImageRaw(width, height, comps);
  90. }
  91. if (mDecodedImageRaw.notNull() && mDecodedImageRaw->getData())
  92. {
  93. done = mFormattedImage->decode(mDecodedImageRaw);
  94. // Some decoders are removing data when task is complete and
  95. // there were errors
  96. mDecodedRaw = done && mDecodedImageRaw->getData();
  97. }
  98. else
  99. {
  100. llwarns_sparse << "Failed to allocate raw image !" << llendl;
  101. return true; // Done (failed)
  102. }
  103. }
  104. if (done && mNeedsAux && !mDecodedAux)
  105. {
  106. // Decode aux channel
  107. if (mDecodedImageAux.isNull())
  108. {
  109. mDecodedImageAux = new LLImageRaw(mFormattedImage->getWidth(),
  110. mFormattedImage->getHeight(),
  111. 1);
  112. }
  113. if (mDecodedImageAux.notNull() && mDecodedImageAux->getData())
  114. {
  115. done = mFormattedImage->decodeChannels(mDecodedImageAux, 4, 4);
  116. // Some decoders are removing data when task is complete and
  117. // there were errors
  118. mDecodedAux = done && mDecodedImageAux->getData();
  119. }
  120. else
  121. {
  122. llwarns_sparse << "Failed to allocate raw image !" << llendl;
  123. }
  124. }
  125. return done;
  126. }
  127. void LLImageDecodeThread::ImageRequest::finishRequest(bool completed)
  128. {
  129. if (mResponder.notNull())
  130. {
  131. bool success = completed && mDecodedRaw &&
  132. mDecodedImageRaw && mDecodedImageRaw->getDataSize() &&
  133. (!mNeedsAux || mDecodedAux);
  134. mResponder->completed(success, mDecodedImageRaw, mDecodedImageAux);
  135. }
  136. // Will automatically be deleted
  137. }
  138. ///////////////////////////////////////////////////////////////////////////////
  139. // LLImageDecodeThread class proper
  140. ///////////////////////////////////////////////////////////////////////////////
  141. LLImageDecodeThread::LLImageDecodeThread(U32 pool_size)
  142. {
  143. if (!pool_size) // Auto-determined size requested by user
  144. {
  145. // Limit the number of threads in the pool to 32 maximum (more than
  146. // this is totally useless, even when flying over main land with 512m
  147. // draw distance. HB
  148. pool_size = llmin(LLCPUInfo::getInstance()->getMaxThreadConcurrency(),
  149. 32U);
  150. }
  151. llinfos << "Initializing with " << pool_size << " worker threads."
  152. << llendl;
  153. mThreadPoolp.reset(new LLThreadPool("Image decode", pool_size));
  154. mThreadPoolp->start(true); // true = wait until all threads are started.
  155. }
  156. void LLImageDecodeThread::shutdown()
  157. {
  158. if (mThreadPoolp)
  159. {
  160. mThreadPoolp->close();
  161. mThreadPoolp.reset(nullptr);
  162. llinfos << "Thread pool destroyed." << llendl;
  163. }
  164. }
  165. size_t LLImageDecodeThread::getPending()
  166. {
  167. return mThreadPoolp ? mThreadPoolp->getQueue().size() : 0;
  168. }
  169. bool LLImageDecodeThread::decodeImage(const LLPointer<LLImageFormatted>& image,
  170. S32 discard, bool needs_aux,
  171. const LLPointer<Responder>& responder)
  172. {
  173. if (!mThreadPoolp || LLApp::isExiting())
  174. {
  175. return false;
  176. }
  177. mThreadPoolp->getQueue().post(
  178. [req = ImageRequest(image, discard, needs_aux, responder)]() mutable
  179. {
  180. LL_TRACY_TIMER(TRC_IMG_DECODE);
  181. if (!LLApp::isExiting())
  182. {
  183. req.finishRequest(req.processRequest());
  184. }
  185. });
  186. return true;
  187. }