Files
CosmicEngine/lib/All/JoltPhysics/TestFramework/Image/Surface.cpp

221 lines
7.0 KiB
C++
Raw Normal View History

// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
// SPDX-License-Identifier: MIT
#include <TestFramework.h>
#include <Image/Surface.h>
//////////////////////////////////////////////////////////////////////////////////////////
// FormatDescription
//
// Description of a surface format
//////////////////////////////////////////////////////////////////////////////////////////
// Format descriptions
static FormatDescription sFormats[] =
{
// Description BPP #CMP Closest 8 Bit Closest Alpha Red Mask Green Mask Blue Mask Alpha Mask
FormatDescription("A4L4", 8, 2, ESurfaceFormat::A8L8, ESurfaceFormat::A4L4, 0x0000000f, 0x0000000f, 0x0000000f, 0x000000f0),
FormatDescription("L8", 8, 1, ESurfaceFormat::L8, ESurfaceFormat::A8L8, 0x000000ff, 0x000000ff, 0x000000ff, 0x00000000),
FormatDescription("A8", 8, 1, ESurfaceFormat::A8, ESurfaceFormat::A8, 0x00000000, 0x00000000, 0x00000000, 0x000000ff),
FormatDescription("A8L8", 16, 2, ESurfaceFormat::A8L8, ESurfaceFormat::A8L8, 0x000000ff, 0x000000ff, 0x000000ff, 0x0000ff00),
FormatDescription("R5G6B5", 16, 3, ESurfaceFormat::R8G8B8, ESurfaceFormat::A1R5G5B5, 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000),
FormatDescription("X1R5G5B5", 16, 3, ESurfaceFormat::R8G8B8, ESurfaceFormat::A1R5G5B5, 0x00007c00, 0x000003e0, 0x0000001f, 0x00000000),
FormatDescription("X4R4G4B4", 16, 3, ESurfaceFormat::R8G8B8, ESurfaceFormat::A4R4G4B4, 0x00000f00, 0x000000f0, 0x0000000f, 0x00000000),
FormatDescription("A1R5G5B5", 16, 4, ESurfaceFormat::A8R8G8B8, ESurfaceFormat::A1R5G5B5, 0x00007c00, 0x000003e0, 0x0000001f, 0x00008000),
FormatDescription("A4R4G4B4", 16, 4, ESurfaceFormat::A8R8G8B8, ESurfaceFormat::A4R4G4B4, 0x00000f00, 0x000000f0, 0x0000000f, 0x0000f000),
FormatDescription("R8G8B8", 24, 3, ESurfaceFormat::R8G8B8, ESurfaceFormat::A8R8G8B8, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000),
FormatDescription("B8G8R8", 24, 3, ESurfaceFormat::B8G8R8, ESurfaceFormat::A8B8G8R8, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000),
FormatDescription("X8R8G8B8", 32, 3, ESurfaceFormat::X8R8G8B8, ESurfaceFormat::A8R8G8B8, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000),
FormatDescription("X8B8G8R8", 32, 3, ESurfaceFormat::X8B8G8R8, ESurfaceFormat::A8B8G8R8, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000),
FormatDescription("A8R8G8B8", 32, 4, ESurfaceFormat::A8R8G8B8, ESurfaceFormat::A8R8G8B8, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000),
FormatDescription("A8B8G8R8", 32, 4, ESurfaceFormat::A8B8G8R8, ESurfaceFormat::A8B8G8R8, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000),
FormatDescription("Invalid", 0, 0, ESurfaceFormat::Invalid, ESurfaceFormat::Invalid, 0x00000000, 0x00000000, 0x00000000, 0x00000000),
};
FormatDescription::FormatDescription(const char *inFormatName, int inBitsPerPixel, int inNumberOfComponents, ESurfaceFormat inClosest8BitFormat, ESurfaceFormat inClosestAlphaFormat, uint32 inRedMask, uint32 inGreenMask, uint32 inBlueMask, uint32 inAlphaMask) :
mFormatName(inFormatName),
mBitsPerPixel(inBitsPerPixel),
mNumberOfComponents(inNumberOfComponents),
mClosest8BitFormat(inClosest8BitFormat),
mClosestAlphaFormat(inClosestAlphaFormat),
mRedMask(inRedMask),
mGreenMask(inGreenMask),
mBlueMask(inBlueMask),
mAlphaMask(inAlphaMask)
{
}
uint32 FormatDescription::Encode(ColorArg inColor) const
{
uint32 col = 0;
uint32 written_mask = 0;
// Loop through all components
for (int c = 0; c < 4; ++c)
{
// Check that we have not yet written this part of the color yet
uint32 mask = GetComponentMask(c);
if ((written_mask & mask) != 0) continue;
written_mask |= mask;
// Or in this component
col |= int(round((1.0f / 255.0f) * mask * inColor(c))) & mask;
}
return col;
}
const Color FormatDescription::Decode(uint32 inColor) const
{
Color col(0, 0, 0, 0);
// Loop through all components
for (int c = 0; c < 4; ++c)
{
uint32 mask = GetComponentMask(c);
if (mask != 0)
{
uint32 shift = CountTrailingZeros(mask);
uint32 shifted_color = (inColor & mask) >> shift;
uint32 shifted_mask = mask >> shift;
col(c) = uint8((255 * shifted_color + 127) / shifted_mask);
}
else
col(c) = 255;
}
return col;
}
const FormatDescription &GetFormatDescription(ESurfaceFormat inFormat)
{
if (inFormat <= ESurfaceFormat::Invalid)
return sFormats[uint(inFormat)];
return sFormats[uint(ESurfaceFormat::Invalid)];
}
//////////////////////////////////////////////////////////////////////////////////////////
// Surface
//
// Class that contains an image in arbitrary format
//////////////////////////////////////////////////////////////////////////////////////////
Surface::Surface(int inWidth, int inHeight, ESurfaceFormat inFormat) :
mFormat(inFormat),
mWidth(inWidth),
mHeight(inHeight),
mLength(0),
mLockMode(ESurfaceLockMode::None),
mStride(0),
mData(nullptr)
{
}
Surface::~Surface()
{
JPH_ASSERT(!IsLocked());
JPH_ASSERT(mData == nullptr);
JPH_ASSERT(mStride == 0);
JPH_ASSERT(mLength == 0);
}
void Surface::Lock(ESurfaceLockMode inMode) const
{
// Check if this resource can be locked
JPH_ASSERT(!IsLocked());
JPH_ASSERT((uint(inMode) & uint(ESurfaceLockMode::ReadWrite)) != 0);
// Store mode
mLockMode = inMode;
// Lock the buffer
HardwareLock();
// Check that data and stride were filled in
JPH_ASSERT(mData != nullptr);
JPH_ASSERT(mStride > 0);
JPH_ASSERT(mLength > 0);
}
void Surface::UnLock() const
{
// Check if this resource was locked
JPH_ASSERT(IsLocked());
// Unlock the hardware resource
HardwareUnLock();
// Reset members, so we are sure they will be set next time
mLockMode = ESurfaceLockMode::None;
mStride = 0;
mLength = 0;
mData = nullptr;
}
void Surface::Clear(ColorArg inColor)
{
Lock(ESurfaceLockMode::Write);
// Get image properties
int bpp = GetBytesPerPixel();
int width = GetWidth();
int height = GetHeight();
// Determine clear color
uint32 col = GetFormatDescription().Encode(inColor);
// Clear the image
for (int y = 0; y < height; ++y)
{
uint8 *d = GetScanLine(y);
uint8 *d_end = GetScanLine(y) + width * bpp;
while (d < d_end)
{
memcpy(d, &col, bpp);
d += bpp;
}
}
UnLock();
}
//////////////////////////////////////////////////////////////////////////////////////////
// SoftwareSurface
//
// Class that contains an image in arbitrary format
//////////////////////////////////////////////////////////////////////////////////////////
SoftwareSurface::SoftwareSurface(int inWidth, int inHeight, ESurfaceFormat inFormat, int inStride) :
Surface(inWidth, inHeight, inFormat)
{
// Determine stride and length
mPixelStride = inStride == 0? ((mWidth * GetBytesPerPixel() + 3) & ~3) : inStride;
mPixelLength = mPixelStride * inHeight;
// Allocate pixel data
JPH_ASSERT(mPixelLength > 0);
mPixelData = new uint8 [mPixelLength];
}
SoftwareSurface::~SoftwareSurface()
{
delete [] mPixelData;
}
void SoftwareSurface::HardwareLock() const
{
// Get pointer to data
mData = mPixelData;
mStride = mPixelStride;
mLength = mPixelLength;
}
void SoftwareSurface::HardwareUnLock() const
{
}