og-odamex/common/v_pixelformat.h
2026-01-05 01:52:47 +00:00

210 lines
5.8 KiB
C++

// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id$
//
// Copyright (C) 2006-2026 by The Odamex Team.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// DESCRIPTION:
//
//-----------------------------------------------------------------------------
#pragma once
// ============================================================================
//
// PixelFormat class definition and implementation
//
// ============================================================================
//
// PixelFormat collects information about how a pixel is stored in memory. This
// is most relevant when the size of a pixel is more than 1 byte, making the
// byte ordering of color channels in memory cruical. On some platforms, such
// as certain versions of OSX, the memory layout of pixels changes when
// toggling the video mode between windowed and full-screen. Due to this
// behavior, the memory layout can not be deduced at compile time and thus
// we need to have a way of referencing the current pixel memory layout and
// to convert between different formats at runtime.
//
// The PixelFormat class is based on GPL v2 code from ScummVM:
//
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
class PixelFormat
{
public:
inline PixelFormat() :
mBitsPerPixel(0),
mAShift(0), mRShift(0), mGShift(0), mBShift(0),
mALoss(0), mRLoss(0), mGLoss(0), mBLoss(0)
{ }
inline PixelFormat(uint8_t bitsperpixel,
uint8_t abits, uint8_t rbits, uint8_t gbits, uint8_t bbits,
uint8_t ashift, uint8_t rshift, uint8_t gshift, uint8_t bshift) :
mBitsPerPixel(bitsperpixel),
mAShift(ashift), mRShift(rshift), mGShift(gshift), mBShift(bshift),
mALoss(8 - abits), mRLoss(8 - rbits), mGLoss(8 - gbits), mBLoss(8 - bbits)
{ }
[[nodiscard]]
inline bool operator==(const PixelFormat& other) const
{ return memcmp(this, &other, sizeof(PixelFormat)) == 0; }
inline bool operator!=(const PixelFormat& other) const
{ return !(operator==(other)); }
inline uint8_t getBitsPerPixel() const
{ return mBitsPerPixel; }
inline uint8_t getBytesPerPixel() const
{ return (mBitsPerPixel + 7) >> 3; }
inline argb_t convert(const uint8_t r, const uint8_t g, const uint8_t b) const
{
return ((0xFF >> mALoss) << mAShift) |
((r >> mRLoss) << mRShift) |
((g >> mGLoss) << mGShift) |
((b >> mBLoss) << mBShift);
}
inline uint32_t convert(const uint8_t a, const uint8_t r, const uint8_t g, const uint8_t b) const
{
return ((a >> mALoss) << mAShift) |
((r >> mRLoss) << mRShift) |
((g >> mGLoss) << mGShift) |
((b >> mBLoss) << mBShift);
}
inline uint8_t a(const uint32_t value) const
{ return ((value >> mAShift) << mALoss) & 0xFF; }
inline uint8_t r(const uint32_t value) const
{ return ((value >> mRShift) << mRLoss) & 0xFF; }
inline uint8_t g(const uint32_t value) const
{ return ((value >> mGShift) << mGLoss) & 0xFF; }
inline uint8_t b(const uint32_t value) const
{ return ((value >> mBShift) << mBLoss) & 0xFF; }
inline uint8_t getABits() const
{ return 8 - mALoss; }
inline uint8_t getRBits() const
{ return 8 - mRLoss; }
inline uint8_t getGBits() const
{ return 8 - mGLoss; }
inline uint8_t getBBits() const
{ return 8 - mBLoss; }
inline uint32_t getAMax() const
{ return (1 << getABits()) - 1; }
inline uint32_t getRMax() const
{ return (1 << getRBits()) - 1; }
inline uint32_t getGMax() const
{ return (1 << getGBits()) - 1; }
inline uint32_t getBMax() const
{ return (1 << getBBits()) - 1; }
inline uint8_t getAShift() const
{ return mAShift; }
inline uint8_t getRShift() const
{ return mRShift; }
inline uint8_t getGShift() const
{ return mGShift; }
inline uint8_t getBShift() const
{ return mBShift; }
inline uint8_t getAPos() const
{
#ifdef __BIG_ENDIAN__
return (24 - mAShift) >> 3;
#else
return mAShift >> 3;
#endif
}
inline uint8_t getRPos() const
{
#ifdef __BIG_ENDIAN__
return (24 - mRShift) >> 3;
#else
return mRShift >> 3;
#endif
}
inline uint8_t getGPos() const
{
#ifdef __BIG_ENDIAN__
return (24 - mGShift) >> 3;
#else
return mGShift >> 3;
#endif
}
inline uint8_t getBPos() const
{
#ifdef __BIG_ENDIAN__
return (24 - mBShift) >> 3;
#else
return mBShift >> 3;
#endif
}
private:
uint8_t mBitsPerPixel;
uint8_t mAShift, mRShift, mGShift, mBShift;
uint8_t mALoss, mRLoss, mGLoss, mBLoss;
};
static inline void V_Convert(void* dest, const PixelFormat* destformat, uint16_t destpitch,
void* source, const PixelFormat* source_format, uint16_t sourcepitch,
uint16_t width, uint16_t height)
{
}