MemoryBlock.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include "EditorDefs.h"
  9. #include "MemoryBlock.h"
  10. #include <zlib.h>
  11. #include <QMessageBox>
  12. #include <QApplication>
  13. //////////////////////////////////////////////////////////////////////////
  14. CMemoryBlock::CMemoryBlock()
  15. : m_buffer(nullptr)
  16. , m_size(0)
  17. , m_uncompressedSize(0)
  18. , m_owns(false)
  19. {
  20. }
  21. //////////////////////////////////////////////////////////////////////////
  22. CMemoryBlock::CMemoryBlock(const CMemoryBlock& mem)
  23. {
  24. *this = mem;
  25. }
  26. //////////////////////////////////////////////////////////////////////////
  27. CMemoryBlock::~CMemoryBlock()
  28. {
  29. Free();
  30. }
  31. //////////////////////////////////////////////////////////////////////////
  32. CMemoryBlock& CMemoryBlock::operator=(const CMemoryBlock& mem)
  33. {
  34. if (mem.GetSize() > 0)
  35. {
  36. // Do not reallocate.
  37. if (mem.GetSize() > GetSize())
  38. {
  39. if (!Allocate(mem.GetSize()))
  40. {
  41. return *this;
  42. }
  43. }
  44. Copy(mem.GetBuffer(), mem.GetSize());
  45. }
  46. else
  47. {
  48. m_buffer = nullptr;
  49. m_size = 0;
  50. m_owns = false;
  51. }
  52. m_uncompressedSize = mem.m_uncompressedSize;
  53. return *this;
  54. }
  55. //////////////////////////////////////////////////////////////////////////
  56. bool CMemoryBlock::Allocate(int size, int uncompressedSize)
  57. {
  58. assert(size > 0);
  59. if (m_buffer)
  60. {
  61. m_buffer = realloc(m_buffer, size);
  62. }
  63. else
  64. {
  65. m_buffer = malloc(size);
  66. }
  67. if (!m_buffer)
  68. {
  69. QString str;
  70. str = QStringLiteral("CMemoryBlock::Allocate failed to allocate %1Mb of Memory").arg(size / (1024 * 1024));
  71. CryLogAlways("%s", str.toUtf8().data());
  72. QMessageBox::critical(QApplication::activeWindow(), QString(), str + QString("\r\nSandbox will try to reduce its working memory set to free memory for this allocation."));
  73. GetIEditor()->ReduceMemory();
  74. if (m_buffer)
  75. {
  76. m_buffer = realloc(m_buffer, size);
  77. }
  78. else
  79. {
  80. m_buffer = malloc(size);
  81. }
  82. if (!m_buffer)
  83. {
  84. AZ_Warning("CMemoryBlock", false, "Reducing working memory set failed, Sandbox must quit");
  85. }
  86. else
  87. {
  88. AZ_Warning("CMemoryBlock", false, "Reducing working memory set succeeded\r\nSandbox may become unstable, it is advised to save the level and restart editor.");
  89. }
  90. }
  91. m_owns = true;
  92. m_size = size;
  93. m_uncompressedSize = uncompressedSize;
  94. // Check if allocation failed.
  95. if (m_buffer == nullptr)
  96. {
  97. return false;
  98. }
  99. return true;
  100. }
  101. //////////////////////////////////////////////////////////////////////////
  102. void CMemoryBlock::Free()
  103. {
  104. if (m_buffer && m_owns)
  105. {
  106. free(m_buffer);
  107. }
  108. m_buffer = nullptr;
  109. m_owns = false;
  110. m_size = 0;
  111. m_uncompressedSize = 0;
  112. }
  113. //////////////////////////////////////////////////////////////////////////
  114. void CMemoryBlock::Copy(void* src, int size)
  115. {
  116. assert(size <= m_size);
  117. memcpy(m_buffer, src, size);
  118. }
  119. //////////////////////////////////////////////////////////////////////////
  120. void CMemoryBlock::Attach(void* buffer, int size, int uncompressedSize)
  121. {
  122. Free();
  123. m_owns = false;
  124. m_buffer = buffer;
  125. m_size = size;
  126. m_uncompressedSize = uncompressedSize;
  127. }
  128. //////////////////////////////////////////////////////////////////////////
  129. void CMemoryBlock::Detach()
  130. {
  131. Free();
  132. }
  133. //////////////////////////////////////////////////////////////////////////
  134. void CMemoryBlock::Compress(CMemoryBlock& toBlock) const
  135. {
  136. // Cannot compress to itself.
  137. assert(this != &toBlock);
  138. unsigned long destSize = m_size * 2 + 128;
  139. CMemoryBlock temp;
  140. temp.Allocate(static_cast<int>(destSize));
  141. compress((unsigned char*)temp.GetBuffer(), &destSize, (unsigned char*)GetBuffer(), m_size);
  142. toBlock.Allocate(static_cast<int>(destSize));
  143. toBlock.Copy(temp.GetBuffer(), static_cast<int>(destSize));
  144. toBlock.m_uncompressedSize = GetSize();
  145. }
  146. //////////////////////////////////////////////////////////////////////////
  147. void CMemoryBlock::Uncompress(CMemoryBlock& toBlock) const
  148. {
  149. assert(this != &toBlock);
  150. toBlock.Allocate(m_uncompressedSize);
  151. toBlock.m_uncompressedSize = 0;
  152. unsigned long destSize = m_uncompressedSize;
  153. [[maybe_unused]] int result = uncompress((unsigned char*)toBlock.GetBuffer(), &destSize, (unsigned char*)GetBuffer(), GetSize());
  154. assert(result == Z_OK);
  155. assert(destSize == static_cast<unsigned long>(m_uncompressedSize));
  156. }
  157. //////////////////////////////////////////////////////////////////////////
  158. void CMemoryBlock::Serialize(CArchive& ar)
  159. {
  160. if (ar.IsLoading())
  161. {
  162. int size;
  163. // Loading.
  164. ar >> size;
  165. if (size != m_size)
  166. {
  167. Allocate(size);
  168. }
  169. m_size = size;
  170. ar >> m_uncompressedSize;
  171. ar.Read(m_buffer, m_size);
  172. }
  173. else
  174. {
  175. // Saving.
  176. ar << m_size;
  177. ar << m_uncompressedSize;
  178. ar.Write(m_buffer, m_size);
  179. }
  180. }