32-bit color support

This commit is contained in:
elasota
2020-06-13 04:33:41 -04:00
parent 24f43b973a
commit 4920781619
42 changed files with 1161 additions and 450 deletions

View File

@@ -1,6 +1,9 @@
#include "AntiAliasTable.h"
#include "RGBAColor.h"
#include <algorithm>
#include <math.h>
// TODO: This is not gamma correct...
namespace PortabilityLayer
{
@@ -116,5 +119,29 @@ namespace PortabilityLayer
}
}
}
void AntiAliasTable::GenerateForSimpleScale(uint8_t colorChannel)
{
const double gamma = 1.8;
const double rcpGamma = 1.0 / gamma;
const double rcp255 = 1.0 / 255.0;
const double rcp15 = 1.0 / 15.0;
double colorChannelLinear = pow(colorChannel * rcp255, gamma);
for (size_t baseColor = 0; baseColor < 256; baseColor++)
{
const double baseColorLinear = pow(baseColor * rcp255, gamma);
for (size_t opacity = 0; opacity < 16; opacity++)
{
const double opacityF = static_cast<double>(opacity) * rcp15;
const double blendedColor = colorChannelLinear * opacityF + (1.0 - opacityF) * baseColorLinear;
const double blendedColorGammaSpace = pow(std::min(std::max(0.0, blendedColor), 1.0), rcpGamma);
m_aaTranslate[baseColor][opacity] = static_cast<uint8_t>(floor(blendedColorGammaSpace * 255.0 + 0.5));
}
}
}
#endif
}

View File

@@ -12,5 +12,6 @@ namespace PortabilityLayer
uint8_t m_aaTranslate[256][16];
void GenerateForPalette(const RGBAColor &baseColor, const RGBAColor *colors, size_t numColors);
void GenerateForSimpleScale(uint8_t colorChannel);
};
}

View File

@@ -830,7 +830,7 @@ namespace PortabilityLayer
void DialogManagerImpl::PositionWindow(Window *window, const Rect &rect) const
{
unsigned int displayWidth, displayHeight;
PortabilityLayer::HostDisplayDriver::GetInstance()->GetDisplayResolution(&displayWidth, &displayHeight, nullptr);
PortabilityLayer::HostDisplayDriver::GetInstance()->GetDisplayResolution(&displayWidth, &displayHeight);
const unsigned int halfDisplayHeight = displayHeight / 2;
const unsigned int quarterDisplayWidth = displayHeight / 4;

View File

@@ -16,6 +16,7 @@ namespace PortabilityLayer
void Init() override;
void Shutdown() override;
void SetPixelFormat(GpPixelFormat_t pixelFormat) override;
GpPixelFormat_t GetPixelFormat() const override;
void SyncPalette(IGpDisplayDriver *displayDriver) override;
@@ -62,8 +63,6 @@ namespace PortabilityLayer
void DisplayDeviceManagerImpl::Init()
{
HostDisplayDriver::GetInstance()->GetDisplayResolution(nullptr, nullptr, &m_pixelFormat);
const PortabilityLayer::RGBAColor *spColors = StandardPalette::GetInstance()->GetColors();
for (size_t i = 0; i < 256; i++)
m_palette[i] = spColors[i];
@@ -75,6 +74,11 @@ namespace PortabilityLayer
{
}
void DisplayDeviceManagerImpl::SetPixelFormat(GpPixelFormat_t pixelFormat)
{
m_pixelFormat = pixelFormat;
}
GpPixelFormat_t DisplayDeviceManagerImpl::GetPixelFormat() const
{
return m_pixelFormat;

View File

@@ -21,6 +21,7 @@ namespace PortabilityLayer
virtual void Init() = 0;
virtual void Shutdown() = 0;
virtual void SetPixelFormat(GpPixelFormat_t pixelFormat) = 0;
virtual GpPixelFormat_t GetPixelFormat() const = 0;
virtual void SyncPalette(IGpDisplayDriver *displayDriver) = 0;

View File

@@ -1,6 +1,9 @@
#include "IconLoader.h"
#include "DisplayDeviceManager.h"
#include "PLCore.h"
#include "PLCTabReducer.h"
#include "PLStandardColors.h"
#include "ResourceManager.h"
#include "QDStandardPalette.h"
#include "QDPixMap.h"
@@ -119,8 +122,12 @@ namespace PortabilityLayer
return false;
uint8_t remapping[256];
PortabilityLayer::RGBAColor palette[256];
for (int i = 0; i < 256; i++)
{
remapping[i] = 0;
palette[i] = StdColors::Black();
}
for (size_t i = 0; i < numItems; i++)
{
@@ -133,6 +140,7 @@ namespace PortabilityLayer
return false;
const PortabilityLayer::RGBAColor remappedColor = CTabReducer::DecodeClutItem(ctabItem);
palette[i] = remappedColor;
remapping[index] = StandardPalette::GetInstance()->MapColorLUT(remappedColor);
}
@@ -141,7 +149,9 @@ namespace PortabilityLayer
if (!rect.IsValid())
return false;
THandle<PixMapImpl> pixMap = PixMapImpl::Create(rect, GpPixelFormats::k8BitStandard);
GpPixelFormat_t pixelFormat = DisplayDeviceManager::GetInstance()->GetPixelFormat();
THandle<PixMapImpl> pixMap = PixMapImpl::Create(rect, pixelFormat);
if (!pixMap)
return false;
@@ -152,49 +162,117 @@ namespace PortabilityLayer
uint8_t *outData = static_cast<uint8_t*>((*pixMap)->GetPixelData());
const size_t outPitch = (*pixMap)->GetPitch();
for (size_t row = 0; row < height; row++)
if (pixelFormat == GpPixelFormats::k8BitStandard)
{
if (numItems > 16)
for (size_t row = 0; row < height; row++)
{
// 8bpp
for (size_t col = 0; col < width; col++)
if (numItems > 16)
{
const unsigned int index = inData[col];
outData[col] = remapping[index];
// 8bpp
for (size_t col = 0; col < width; col++)
{
const unsigned int index = inData[col];
outData[col] = remapping[index];
}
}
}
else if (numItems > 4)
{
// 4bpp
for (size_t col = 0; col < width; col++)
else if (numItems > 4)
{
const unsigned int index = (inData[col / 2] >> (4 - ((col & 1) * 4))) & 0x0f;
outData[col] = remapping[index];
// 4bpp
for (size_t col = 0; col < width; col++)
{
const unsigned int index = (inData[col / 2] >> (4 - ((col & 1) * 4))) & 0x0f;
outData[col] = remapping[index];
}
}
}
else if (numItems > 2)
{
// 2bpp
for (size_t col = 0; col < width; col++)
else if (numItems > 2)
{
const unsigned int index = (inData[col / 4] >> (6 - ((col & 3) * 2))) & 0x03;
outData[col] = remapping[index];
// 2bpp
for (size_t col = 0; col < width; col++)
{
const unsigned int index = (inData[col / 4] >> (6 - ((col & 3) * 2))) & 0x03;
outData[col] = remapping[index];
}
}
}
else
{
// 1bpp
for (size_t col = 0; col < width; col++)
else
{
const unsigned int index = (inData[col / 4] >> (7 - (col & 7))) & 0x01;
outData[col] = remapping[index];
// 1bpp
for (size_t col = 0; col < width; col++)
{
const unsigned int index = (inData[col / 4] >> (7 - (col & 7))) & 0x01;
outData[col] = remapping[index];
}
}
}
inData += inPitch;
outData += outPitch;
inData += inPitch;
outData += outPitch;
}
}
else if (pixelFormat == GpPixelFormats::kRGB32)
{
for (size_t row = 0; row < height; row++)
{
if (numItems > 16)
{
// 8bpp
for (size_t col = 0; col < width; col++)
{
const unsigned int index = inData[col];
const PortabilityLayer::RGBAColor &color = palette[index];
outData[col * 4 + 0] = color.r;
outData[col * 4 + 1] = color.g;
outData[col * 4 + 2] = color.b;
outData[col * 4 + 3] = 255;
}
}
else if (numItems > 4)
{
// 4bpp
for (size_t col = 0; col < width; col++)
{
const unsigned int index = (inData[col / 2] >> (4 - ((col & 1) * 4))) & 0x0f;
const PortabilityLayer::RGBAColor &color = palette[index];
outData[col * 4 + 0] = color.r;
outData[col * 4 + 1] = color.g;
outData[col * 4 + 2] = color.b;
outData[col * 4 + 3] = 255;
}
}
else if (numItems > 2)
{
// 2bpp
for (size_t col = 0; col < width; col++)
{
const unsigned int index = (inData[col / 4] >> (6 - ((col & 3) * 2))) & 0x03;
const PortabilityLayer::RGBAColor &color = palette[index];
outData[col * 4 + 0] = color.r;
outData[col * 4 + 1] = color.g;
outData[col * 4 + 2] = color.b;
outData[col * 4 + 3] = 255;
}
}
else
{
// 1bpp
for (size_t col = 0; col < width; col++)
{
const unsigned int index = (inData[col / 4] >> (7 - (col & 7))) & 0x01;
const PortabilityLayer::RGBAColor &color = palette[index];
outData[col * 4 + 0] = color.r;
outData[col * 4 + 1] = color.g;
outData[col * 4 + 2] = color.b;
outData[col * 4 + 3] = 255;
}
}
inData += inPitch;
outData += outPitch;
}
}
else
{
PL_NotYetImplemented();
}
outHandle = pixMap;
dataPtr = inData;
@@ -245,7 +323,10 @@ namespace PortabilityLayer
return THandle<PixMapImpl>();
const Rect rect = Rect::Create(0, 0, 32, 32);
THandle<PixMapImpl> pixMap = PixMapImpl::Create(rect, GpPixelFormats::k8BitStandard);
GpPixelFormat_t pixelFormat = DisplayDeviceManager::GetInstance()->GetPixelFormat();
THandle<PixMapImpl> pixMap = PixMapImpl::Create(rect, pixelFormat);
if (!pixMap)
return THandle<PixMapImpl>();
@@ -253,13 +334,34 @@ namespace PortabilityLayer
uint8_t *outData = static_cast<uint8_t*>((*pixMap)->GetPixelData());
const size_t outPitch = (*pixMap)->GetPitch();
for (size_t row = 0; row < 32; row++)
if (pixelFormat == GpPixelFormats::kRGB32)
{
for (size_t col = 0; col < 32; col++)
outData[col] = inData[col];
const PortabilityLayer::RGBAColor *palette = StandardPalette::GetInstance()->GetColors();
inData += 32;
outData += outPitch;
for (size_t row = 0; row < 32; row++)
{
uint32_t *outU32 = reinterpret_cast<uint32_t*>(outData);
for (size_t col = 0; col < 32; col++)
outU32[col] = palette[inData[col]].AsUInt32();
inData += 32;
outData += outPitch;
}
}
else if (pixelFormat == GpPixelFormats::k8BitStandard)
{
for (size_t row = 0; row < 32; row++)
{
for (size_t col = 0; col < 32; col++)
outData[col] = inData[col];
inData += 32;
outData += outPitch;
}
}
else
{
PL_NotYetImplemented();
}
return pixMap;

View File

@@ -819,8 +819,9 @@ namespace PortabilityLayer
}
unsigned int width;
GpPixelFormat_t pixelFormat;
PortabilityLayer::HostDisplayDriver::GetInstance()->GetDisplayResolution(&width, nullptr, &pixelFormat);
HostDisplayDriver::GetInstance()->GetDisplayResolution(&width, nullptr);
GpPixelFormat_t pixelFormat = DisplayDeviceManager::GetInstance()->GetPixelFormat();
PortabilityLayer::QDManager *qdManager = PortabilityLayer::QDManager::GetInstance();
@@ -1310,7 +1311,7 @@ namespace PortabilityLayer
int32_t popupBottom = m_popupPosition.m_y + menu->layoutFinalHeight;
unsigned int displayHeight = 0;
PortabilityLayer::HostDisplayDriver::GetInstance()->GetDisplayResolution(nullptr, &displayHeight, nullptr);
PortabilityLayer::HostDisplayDriver::GetInstance()->GetDisplayResolution(nullptr, &displayHeight);
if (popupBottom > static_cast<int32_t>(displayHeight))
m_popupPosition.m_y -= popupBottom - static_cast<int32_t>(displayHeight);
}
@@ -1397,8 +1398,7 @@ namespace PortabilityLayer
if (m_menuGraf == nullptr)
{
GpPixelFormat_t pixelFormat;
PortabilityLayer::HostDisplayDriver::GetInstance()->GetDisplayResolution(nullptr, nullptr, &pixelFormat);
GpPixelFormat_t pixelFormat = DisplayDeviceManager::GetInstance()->GetPixelFormat();
if (qdManager->NewGWorld(&m_menuGraf, pixelFormat, menuRect, nullptr) != 0)
return;

File diff suppressed because it is too large Load Diff

View File

@@ -8,8 +8,8 @@
DrawSurface::~DrawSurface()
{
if (m_cachedAATable)
PortabilityLayer::MemoryManager::GetInstance()->Release(m_cachedAATable);
if (m_cachedAATables)
PortabilityLayer::MemoryManager::GetInstance()->Release(m_cachedAATables);
}
void DrawSurface::PushToDDSurface(IGpDisplayDriver *displayDriver)

View File

@@ -32,7 +32,7 @@ struct DrawSurface
: m_port(PortabilityLayer::QDPortType_DrawSurface)
, m_ddSurface(nullptr)
, m_cachedAAColor(PortabilityLayer::RGBAColor::Create(0, 0, 0, 255))
, m_cachedAATable(nullptr)
, m_cachedAATables(nullptr)
{
}
@@ -40,7 +40,7 @@ struct DrawSurface
: m_port(overridePortType)
, m_ddSurface(nullptr)
, m_cachedAAColor(PortabilityLayer::RGBAColor::Create(0, 0, 0, 255))
, m_cachedAATable(nullptr)
, m_cachedAATables(nullptr)
{
}
@@ -85,7 +85,7 @@ struct DrawSurface
IGpDisplayDriverSurface *m_ddSurface;
PortabilityLayer::AntiAliasTable *m_cachedAATable;
PortabilityLayer::AntiAliasTable *m_cachedAATables;
PortabilityLayer::RGBAColor m_cachedAAColor;
PortabilityLayer::QDPort m_port;

View File

@@ -1,9 +1,12 @@
#include "QDPixMap.h"
#include "CoreDefs.h"
#include "MemoryManager.h"
#include "QDStandardPalette.h"
#include <assert.h>
static const PortabilityLayer::RGBAColor *gs_staticPalette = PortabilityLayer::StandardPalette::GetInstance()->GetColors();
class PixMapSampler_8BitStandard
{
public:
@@ -11,6 +14,26 @@ public:
{
return static_cast<const uint8_t*>(rowData)[index];
}
inline static uint32_t ReadAsRGBA(const void *rowData, size_t index)
{
return gs_staticPalette[static_cast<const uint8_t*>(rowData)[index]].AsUInt32();
}
};
class PixMapSampler_32Bit
{
public:
inline static uint8_t ReadAs8BitStandard(const void *rowData, size_t index)
{
const uint8_t *pixelData = static_cast<const uint8_t*>(rowData) + index * 4;
return PortabilityLayer::StandardPalette::GetInstance()->MapColorLUT(PortabilityLayer::RGBAColor::Create(pixelData[0], pixelData[1], pixelData[2], 255));
}
inline static uint32_t ReadAsRGBA(const void *rowData, size_t index)
{
return static_cast<const uint32_t*>(rowData)[index];
}
};
template<class TSampler>
@@ -23,6 +46,16 @@ public:
}
};
template<class TSampler>
class PixMapCopier_32Bit
{
public:
inline static void Copy(const void *inData, size_t inIndex, void *outData, size_t outIndex)
{
static_cast<uint32_t*>(outData)[outIndex] = TSampler::ReadAsRGBA(inData, inIndex);
}
};
template<class TCopier>
class PixMapColBlitter
{
@@ -139,6 +172,9 @@ public:
case GpPixelFormats::k8BitStandard:
blitFunc = PixMapRowBlitter<PixMapCopier_8BitStandard<TSampler> >::Blit;
break;
case GpPixelFormats::kRGB32:
blitFunc = PixMapRowBlitter<PixMapCopier_32Bit<TSampler> >::Blit;
break;
default:
PL_NotYetImplemented();
break;
@@ -163,6 +199,9 @@ public:
case GpPixelFormats::k8BitStandard:
blitFunc = PixMapBlitTargetDisambiguator<PixMapSampler_8BitStandard>::Blit;
break;
case GpPixelFormats::kRGB32:
blitFunc = PixMapBlitTargetDisambiguator<PixMapSampler_32Bit>::Blit;
break;
default:
PL_NotYetImplemented();
break;

View File

@@ -115,6 +115,9 @@ namespace PortabilityLayer
m_blackAATable.GenerateForPalette(RGBAColor::Create(0, 0, 0, 255), m_colors, 256);
m_whiteAATable.GenerateForPalette(RGBAColor::Create(255, 255, 255, 255), m_colors, 256);
#endif
m_whiteToneAATable.GenerateForSimpleScale(255);
m_blackToneAATable.GenerateForSimpleScale(0);
}
const RGBAColor *StandardPalette::GetColors() const
@@ -273,5 +276,15 @@ namespace PortabilityLayer
return m_blackAATable;
}
const AntiAliasTable &StandardPalette::GetWhiteToneAATable() const
{
return m_whiteToneAATable;
}
const AntiAliasTable &StandardPalette::GetBlackToneAATable() const
{
return m_blackToneAATable;
}
StandardPalette StandardPalette::ms_instance;
}

View File

@@ -23,6 +23,9 @@ namespace PortabilityLayer
const AntiAliasTable &GetWhiteAATable() const;
const AntiAliasTable &GetBlackAATable() const;
const AntiAliasTable &GetWhiteToneAATable() const;
const AntiAliasTable &GetBlackToneAATable() const;
static const StandardPalette *GetInstance();
private:
@@ -31,6 +34,8 @@ namespace PortabilityLayer
RGBAColor m_colors[kSize];
AntiAliasTable m_whiteAATable;
AntiAliasTable m_blackAATable;
AntiAliasTable m_whiteToneAATable;
AntiAliasTable m_blackToneAATable;
uint8_t m_lut[16 * 16 * 16];
};
}

View File

@@ -10,7 +10,9 @@ namespace PortabilityLayer
bool operator==(const RGBAColor &other) const;
bool operator!=(const RGBAColor &other) const;
static RGBAColor Create(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
static RGBAColor Create(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
uint32_t AsUInt32() const;
};
inline RGBAColor RGBAColor::Create(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
@@ -32,5 +34,16 @@ namespace PortabilityLayer
inline bool RGBAColor::operator!=(const RGBAColor &other) const
{
return !((*this) == other);
}
}
inline uint32_t RGBAColor::AsUInt32() const
{
uint32_t rgbaColor = 0;
uint8_t *rgbaColorBytes = reinterpret_cast<uint8_t*>(&rgbaColor);
rgbaColorBytes[0] = r;
rgbaColorBytes[1] = g;
rgbaColorBytes[2] = b;
rgbaColorBytes[3] = a;
return rgbaColor;
}
}

View File

@@ -92,6 +92,42 @@ namespace PortabilityLayer
}
}
break;
case GpPixelFormats::kRGB32:
{
uint8_t *destFirstPixel = static_cast<uint8_t*>(pixMapData) + destXOffset * 4 + destYOffset * destPitch;
const PortabilityLayer::RGBAColor *srcPixel = m_pixelData;
for (size_t row = 0; row < srcHeight; row++)
{
uint8_t *destRowFirstPixel = destFirstPixel + row * destPitch;
if (maskData)
{
for (size_t col = 0; col < srcWidth; col++)
{
if (maskData[maskOffset / 8] & (0x80 >> (maskOffset & 7)))
{
destRowFirstPixel[col * 4 + 0] = srcPixel->r;
destRowFirstPixel[col * 4 + 1] = srcPixel->g;
destRowFirstPixel[col * 4 + 2] = srcPixel->b;
}
srcPixel++;
maskOffset++;
}
}
else
{
for (size_t col = 0; col < srcWidth; col++)
{
destRowFirstPixel[col * 4 + 0] = srcPixel->r;
destRowFirstPixel[col * 4 + 1] = srcPixel->g;
destRowFirstPixel[col * 4 + 2] = srcPixel->b;
srcPixel++;
}
}
}
}
break;
default:
PL_NotYetImplemented();
break;

View File

@@ -839,6 +839,9 @@ namespace PortabilityLayer
if (int errorCode = m_surface.Init(adjustedBounds, pixelFormat))
return false;
PortabilityLayer::ResolveCachingColor whiteColor = StdColors::White();
m_surface.FillRect(adjustedBounds, whiteColor);
m_title.Set(windowDef.m_title[0], reinterpret_cast<const char*>(windowDef.m_title + 1));
// Resolve chrome