Surface.cpp 6.9 KB

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