2
0

Surface.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. // Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
  2. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  3. // SPDX-License-Identifier: MIT
  4. #include <TestFramework.h>
  5. #include <Image/Surface.h>
  6. //////////////////////////////////////////////////////////////////////////////////////////
  7. // FormatDescription
  8. //
  9. // Description of a surface format
  10. //////////////////////////////////////////////////////////////////////////////////////////
  11. // Format descriptions
  12. static FormatDescription sFormats[] =
  13. {
  14. // Decription BPP #CMP Closest 8 Bit Closest Alpha Red Mask Green Mask Blue Mask Alpha Mask
  15. FormatDescription("A4L4", 8, 2, ESurfaceFormat::A8L8, ESurfaceFormat::A4L4, 0x0000000f, 0x0000000f, 0x0000000f, 0x000000f0),
  16. FormatDescription("L8", 8, 1, ESurfaceFormat::L8, ESurfaceFormat::A8L8, 0x000000ff, 0x000000ff, 0x000000ff, 0x00000000),
  17. FormatDescription("A8", 8, 1, ESurfaceFormat::A8, ESurfaceFormat::A8, 0x00000000, 0x00000000, 0x00000000, 0x000000ff),
  18. FormatDescription("A8L8", 16, 2, ESurfaceFormat::A8L8, ESurfaceFormat::A8L8, 0x000000ff, 0x000000ff, 0x000000ff, 0x0000ff00),
  19. FormatDescription("R5G6B5", 16, 3, ESurfaceFormat::R8G8B8, ESurfaceFormat::A1R5G5B5, 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000),
  20. FormatDescription("X1R5G5B5", 16, 3, ESurfaceFormat::R8G8B8, ESurfaceFormat::A1R5G5B5, 0x00007c00, 0x000003e0, 0x0000001f, 0x00000000),
  21. FormatDescription("X4R4G4B4", 16, 3, ESurfaceFormat::R8G8B8, ESurfaceFormat::A4R4G4B4, 0x00000f00, 0x000000f0, 0x0000000f, 0x00000000),
  22. FormatDescription("A1R5G5B5", 16, 4, ESurfaceFormat::A8R8G8B8, ESurfaceFormat::A1R5G5B5, 0x00007c00, 0x000003e0, 0x0000001f, 0x00008000),
  23. FormatDescription("A4R4G4B4", 16, 4, ESurfaceFormat::A8R8G8B8, ESurfaceFormat::A4R4G4B4, 0x00000f00, 0x000000f0, 0x0000000f, 0x0000f000),
  24. FormatDescription("R8G8B8", 24, 3, ESurfaceFormat::R8G8B8, ESurfaceFormat::A8R8G8B8, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000),
  25. FormatDescription("B8G8R8", 24, 3, ESurfaceFormat::B8G8R8, ESurfaceFormat::A8B8G8R8, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000),
  26. FormatDescription("X8R8G8B8", 32, 3, ESurfaceFormat::X8R8G8B8, ESurfaceFormat::A8R8G8B8, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000),
  27. FormatDescription("X8B8G8R8", 32, 3, ESurfaceFormat::X8B8G8R8, ESurfaceFormat::A8B8G8R8, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000),
  28. FormatDescription("A8R8G8B8", 32, 4, ESurfaceFormat::A8R8G8B8, ESurfaceFormat::A8R8G8B8, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000),
  29. FormatDescription("A8B8G8R8", 32, 4, ESurfaceFormat::A8B8G8R8, ESurfaceFormat::A8B8G8R8, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000),
  30. FormatDescription("Invalid", 0, 0, ESurfaceFormat::Invalid, ESurfaceFormat::Invalid, 0x00000000, 0x00000000, 0x00000000, 0x00000000),
  31. };
  32. FormatDescription::FormatDescription(const char *inFormatName, int inBitsPerPixel, int inNumberOfComponents, ESurfaceFormat inClosest8BitFormat, ESurfaceFormat inClosestAlphaFormat, uint32 inRedMask, uint32 inGreenMask, uint32 inBlueMask, uint32 inAlphaMask) :
  33. mFormatName(inFormatName),
  34. mBitsPerPixel(inBitsPerPixel),
  35. mNumberOfComponents(inNumberOfComponents),
  36. mClosest8BitFormat(inClosest8BitFormat),
  37. mClosestAlphaFormat(inClosestAlphaFormat),
  38. mRedMask(inRedMask),
  39. mGreenMask(inGreenMask),
  40. mBlueMask(inBlueMask),
  41. mAlphaMask(inAlphaMask)
  42. {
  43. }
  44. uint32 FormatDescription::Encode(ColorArg inColor) const
  45. {
  46. uint32 col = 0;
  47. uint32 written_mask = 0;
  48. // Loop through all components
  49. for (int c = 0; c < 4; ++c)
  50. {
  51. // Check that we have not yet written this part of the color yet
  52. uint32 mask = GetComponentMask(c);
  53. if ((written_mask & mask) != 0) continue;
  54. written_mask |= mask;
  55. // Or in this component
  56. col |= int(round((1.0f / 255.0f) * mask * inColor(c))) & mask;
  57. }
  58. return col;
  59. }
  60. const Color FormatDescription::Decode(uint32 inColor) const
  61. {
  62. Color col(0, 0, 0, 0);
  63. // Loop through all components
  64. for (int c = 0; c < 4; ++c)
  65. {
  66. uint32 mask = GetComponentMask(c);
  67. if (mask != 0)
  68. {
  69. uint32 shift = CountTrailingZeros(mask);
  70. uint32 shifted_color = (inColor & mask) >> shift;
  71. uint32 shifted_mask = mask >> shift;
  72. col(c) = uint8((255 * shifted_color + 127) / shifted_mask);
  73. }
  74. else
  75. col(c) = 255;
  76. }
  77. return col;
  78. }
  79. const FormatDescription &GetFormatDescription(ESurfaceFormat inFormat)
  80. {
  81. if (inFormat <= ESurfaceFormat::Invalid)
  82. return sFormats[uint(inFormat)];
  83. return sFormats[uint(ESurfaceFormat::Invalid)];
  84. }
  85. //////////////////////////////////////////////////////////////////////////////////////////
  86. // Surface
  87. //
  88. // Class that contains an image in arbitrary format
  89. //////////////////////////////////////////////////////////////////////////////////////////
  90. Surface::Surface(int inWidth, int inHeight, ESurfaceFormat inFormat) :
  91. mFormat(inFormat),
  92. mWidth(inWidth),
  93. mHeight(inHeight),
  94. mLength(0),
  95. mLockMode(ESurfaceLockMode::None),
  96. mStride(0),
  97. mData(nullptr)
  98. {
  99. }
  100. Surface::~Surface()
  101. {
  102. JPH_ASSERT(!IsLocked());
  103. JPH_ASSERT(mData == nullptr);
  104. JPH_ASSERT(mStride == 0);
  105. JPH_ASSERT(mLength == 0);
  106. }
  107. void Surface::Lock(ESurfaceLockMode inMode) const
  108. {
  109. // Check if this resource can be locked
  110. JPH_ASSERT(!IsLocked());
  111. JPH_ASSERT((uint(inMode) & uint(ESurfaceLockMode::ReadWrite)) != 0);
  112. // Store mode
  113. mLockMode = inMode;
  114. // Lock the buffer
  115. HardwareLock();
  116. // Check that data and stride were filled in
  117. JPH_ASSERT(mData != nullptr);
  118. JPH_ASSERT(mStride > 0);
  119. JPH_ASSERT(mLength > 0);
  120. }
  121. void Surface::UnLock() const
  122. {
  123. // Check if this resource was locked
  124. JPH_ASSERT(IsLocked());
  125. // Unlock the hardware resource
  126. HardwareUnLock();
  127. // Reset members, so we are sure they will be set next time
  128. mLockMode = ESurfaceLockMode::None;
  129. mStride = 0;
  130. mLength = 0;
  131. mData = nullptr;
  132. }
  133. void Surface::Clear(ColorArg inColor)
  134. {
  135. Lock(ESurfaceLockMode::Write);
  136. // Get image properties
  137. int bpp = GetBytesPerPixel();
  138. int width = GetWidth();
  139. int height = GetHeight();
  140. // Determine clear color
  141. uint32 col = GetFormatDescription().Encode(inColor);
  142. // Clear the image
  143. for (int y = 0; y < height; ++y)
  144. {
  145. uint8 *d = GetScanLine(y);
  146. uint8 *d_end = GetScanLine(y) + width * bpp;
  147. while (d < d_end)
  148. {
  149. memcpy(d, &col, bpp);
  150. d += bpp;
  151. }
  152. }
  153. UnLock();
  154. }
  155. //////////////////////////////////////////////////////////////////////////////////////////
  156. // SoftwareSurface
  157. //
  158. // Class that contains an image in arbitrary format
  159. //////////////////////////////////////////////////////////////////////////////////////////
  160. SoftwareSurface::SoftwareSurface(int inWidth, int inHeight, ESurfaceFormat inFormat, int inStride) :
  161. Surface(inWidth, inHeight, inFormat)
  162. {
  163. // Determine stride and length
  164. mPixelStride = inStride == 0? ((mWidth * GetBytesPerPixel() + 3) & ~3) : inStride;
  165. mPixelLength = mPixelStride * inHeight;
  166. // Allocate pixel data
  167. JPH_ASSERT(mPixelLength > 0);
  168. mPixelData = new uint8 [mPixelLength];
  169. }
  170. SoftwareSurface::~SoftwareSurface()
  171. {
  172. delete mPixelData;
  173. }
  174. void SoftwareSurface::HardwareLock() const
  175. {
  176. // Get pointer to data
  177. mData = mPixelData;
  178. mStride = mPixelStride;
  179. mLength = mPixelLength;
  180. }
  181. void SoftwareSurface::HardwareUnLock() const
  182. {
  183. }