diff options
| author | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
|---|---|---|
| committer | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
| commit | 39ed87570bdb2f86969d4be821c94b722dc71179 (patch) | |
| tree | abc53757f75f40c80278e87650ea92808274aa59 /mp/src/public/pixelwriter.h | |
| download | source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.tar.xz source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.zip | |
First version of the SOurce SDK 2013
Diffstat (limited to 'mp/src/public/pixelwriter.h')
| -rw-r--r-- | mp/src/public/pixelwriter.h | 875 |
1 files changed, 875 insertions, 0 deletions
diff --git a/mp/src/public/pixelwriter.h b/mp/src/public/pixelwriter.h new file mode 100644 index 00000000..64b46c56 --- /dev/null +++ b/mp/src/public/pixelwriter.h @@ -0,0 +1,875 @@ +//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//===========================================================================//
+
+#ifndef PIXELWRITER_H
+#define PIXELWRITER_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#ifdef _WIN32
+#define FORCEINLINE_PIXEL FORCEINLINE
+#elif POSIX
+#define FORCEINLINE_PIXEL inline
+#else
+#error "implement me"
+#endif
+
+#include "bitmap/imageformat.h"
+#include "tier0/dbg.h"
+#include "mathlib/compressed_vector.h"
+#include "mathlib/ssemath.h"
+
+//-----------------------------------------------------------------------------
+// Color writing class
+//-----------------------------------------------------------------------------
+
+class CPixelWriter
+{
+public:
+ FORCEINLINE void SetPixelMemory( ImageFormat format, void* pMemory, int stride );
+ FORCEINLINE void *GetPixelMemory() { return m_pBase; }
+
+ // this is no longer used:
+#if 0 // defined( _X360 )
+ // set after SetPixelMemory()
+ FORCEINLINE void ActivateByteSwapping( bool bSwap );
+#endif
+
+ FORCEINLINE void Seek( int x, int y );
+ FORCEINLINE void* SkipBytes( int n );
+ FORCEINLINE void SkipPixels( int n );
+ FORCEINLINE void WritePixel( int r, int g, int b, int a = 255 );
+ FORCEINLINE void WritePixelNoAdvance( int r, int g, int b, int a = 255 );
+ FORCEINLINE void WritePixelSigned( int r, int g, int b, int a = 255 );
+ FORCEINLINE void WritePixelNoAdvanceSigned( int r, int g, int b, int a = 255 );
+ FORCEINLINE void ReadPixelNoAdvance( int &r, int &g, int &b, int &a );
+
+ // Floating point formats
+ FORCEINLINE void WritePixelNoAdvanceF( float r, float g, float b, float a = 1.0f );
+ FORCEINLINE void WritePixelF( float r, float g, float b, float a = 1.0f );
+
+ // SIMD formats
+ FORCEINLINE void WritePixel( FLTX4 rgba );
+ FORCEINLINE void WritePixelNoAdvance( FLTX4 rgba );
+#ifdef _X360
+ // here are some explicit formats so we can avoid the switch:
+ FORCEINLINE void WritePixelNoAdvance_RGBA8888( FLTX4 rgba );
+ FORCEINLINE void WritePixelNoAdvance_BGRA8888( FLTX4 rgba );
+ // as above, but with m_pBits passed in to avoid a LHS
+ FORCEINLINE void WritePixelNoAdvance_BGRA8888( FLTX4 rgba, void *pBits );
+ // for writing entire SIMD registers at once when they have
+ // already been packed, and when m_pBits is vector-aligned
+ // (which is a requirement for write-combined memory)
+ // offset is added to m_pBits (saving you from the obligatory
+ // LHS of a SkipBytes)
+ FORCEINLINE void WriteFourPixelsExplicitLocation_BGRA8888( FLTX4 rgba, int offset );
+#endif
+
+
+ FORCEINLINE unsigned char GetPixelSize() { return m_Size; }
+
+ FORCEINLINE bool IsUsingFloatFormat() const;
+ FORCEINLINE unsigned char *GetCurrentPixel() { return m_pBits; }
+
+private:
+ enum
+ {
+ PIXELWRITER_USING_FLOAT_FORMAT = 0x01,
+ PIXELWRITER_USING_16BIT_FLOAT_FORMAT = 0x02,
+ PIXELWRITER_SWAPBYTES = 0x04,
+ };
+
+ unsigned char* m_pBase;
+ unsigned char* m_pBits;
+ unsigned short m_BytesPerRow;
+ unsigned char m_Size;
+ unsigned char m_nFlags;
+ signed short m_RShift;
+ signed short m_GShift;
+ signed short m_BShift;
+ signed short m_AShift;
+ unsigned int m_RMask;
+ unsigned int m_GMask;
+ unsigned int m_BMask;
+ unsigned int m_AMask;
+
+#ifdef _X360
+ ImageFormat m_Format;
+public:
+ inline const ImageFormat &GetFormat() { return m_Format; }
+private:
+#endif
+};
+
+FORCEINLINE_PIXEL bool CPixelWriter::IsUsingFloatFormat() const
+{
+ return (m_nFlags & PIXELWRITER_USING_FLOAT_FORMAT) != 0;
+}
+
+FORCEINLINE_PIXEL void CPixelWriter::SetPixelMemory( ImageFormat format, void* pMemory, int stride )
+{
+ m_pBits = (unsigned char*)pMemory;
+ m_pBase = m_pBits;
+ m_BytesPerRow = (unsigned short)stride;
+ m_nFlags = 0;
+#ifdef _X360
+ m_Format = format;
+#endif
+
+ switch ( format )
+ {
+ case IMAGE_FORMAT_R32F: // NOTE! : the low order bits are first in this naming convention.
+ m_Size = 4;
+ m_RShift = 0;
+ m_GShift = 0;
+ m_BShift = 0;
+ m_AShift = 0;
+ m_RMask = 0xFFFFFFFF;
+ m_GMask = 0x0;
+ m_BMask = 0x0;
+ m_AMask = 0x0;
+ m_nFlags |= PIXELWRITER_USING_FLOAT_FORMAT;
+ break;
+
+ case IMAGE_FORMAT_RGBA32323232F:
+ m_Size = 16;
+ m_RShift = 0;
+ m_GShift = 32;
+ m_BShift = 64;
+ m_AShift = 96;
+ m_RMask = 0xFFFFFFFF;
+ m_GMask = 0xFFFFFFFF;
+ m_BMask = 0xFFFFFFFF;
+ m_AMask = 0xFFFFFFFF;
+ m_nFlags |= PIXELWRITER_USING_FLOAT_FORMAT;
+ break;
+
+ case IMAGE_FORMAT_RGBA16161616F:
+ m_Size = 8;
+ m_RShift = 0;
+ m_GShift = 16;
+ m_BShift = 32;
+ m_AShift = 48;
+ m_RMask = 0xFFFF;
+ m_GMask = 0xFFFF;
+ m_BMask = 0xFFFF;
+ m_AMask = 0xFFFF;
+ m_nFlags |= PIXELWRITER_USING_FLOAT_FORMAT | PIXELWRITER_USING_16BIT_FLOAT_FORMAT;
+ break;
+
+ case IMAGE_FORMAT_RGBA8888:
+#if defined( _X360 )
+ case IMAGE_FORMAT_LINEAR_RGBA8888:
+#endif
+ m_Size = 4;
+ m_RShift = 0;
+ m_GShift = 8;
+ m_BShift = 16;
+ m_AShift = 24;
+ m_RMask = 0xFF;
+ m_GMask = 0xFF;
+ m_BMask = 0xFF;
+ m_AMask = 0xFF;
+ break;
+
+ case IMAGE_FORMAT_BGRA8888: // NOTE! : the low order bits are first in this naming convention.
+#if defined( _X360 )
+ case IMAGE_FORMAT_LINEAR_BGRA8888:
+#endif
+ m_Size = 4;
+ m_RShift = 16;
+ m_GShift = 8;
+ m_BShift = 0;
+ m_AShift = 24;
+ m_RMask = 0xFF;
+ m_GMask = 0xFF;
+ m_BMask = 0xFF;
+ m_AMask = 0xFF;
+ break;
+
+ case IMAGE_FORMAT_BGRX8888:
+#if defined( _X360 )
+ case IMAGE_FORMAT_LINEAR_BGRX8888:
+#endif
+ m_Size = 4;
+ m_RShift = 16;
+ m_GShift = 8;
+ m_BShift = 0;
+ m_AShift = 24;
+ m_RMask = 0xFF;
+ m_GMask = 0xFF;
+ m_BMask = 0xFF;
+ m_AMask = 0x00;
+ break;
+
+ case IMAGE_FORMAT_BGRA4444:
+ m_Size = 2;
+ m_RShift = 4;
+ m_GShift = 0;
+ m_BShift = -4;
+ m_AShift = 8;
+ m_RMask = 0xF0;
+ m_GMask = 0xF0;
+ m_BMask = 0xF0;
+ m_AMask = 0xF0;
+ break;
+
+ case IMAGE_FORMAT_BGR888:
+ m_Size = 3;
+ m_RShift = 16;
+ m_GShift = 8;
+ m_BShift = 0;
+ m_AShift = 0;
+ m_RMask = 0xFF;
+ m_GMask = 0xFF;
+ m_BMask = 0xFF;
+ m_AMask = 0x00;
+ break;
+
+ case IMAGE_FORMAT_BGR565:
+ m_Size = 2;
+ m_RShift = 8;
+ m_GShift = 3;
+ m_BShift = -3;
+ m_AShift = 0;
+ m_RMask = 0xF8;
+ m_GMask = 0xFC;
+ m_BMask = 0xF8;
+ m_AMask = 0x00;
+ break;
+
+ case IMAGE_FORMAT_BGRA5551:
+ case IMAGE_FORMAT_BGRX5551:
+ m_Size = 2;
+ m_RShift = 7;
+ m_GShift = 2;
+ m_BShift = -3;
+ m_AShift = 8;
+ m_RMask = 0xF8;
+ m_GMask = 0xF8;
+ m_BMask = 0xF8;
+ m_AMask = 0x80;
+ break;
+
+ // GR - alpha format for HDR support
+ case IMAGE_FORMAT_A8:
+ m_Size = 1;
+ m_RShift = 0;
+ m_GShift = 0;
+ m_BShift = 0;
+ m_AShift = 0;
+ m_RMask = 0x00;
+ m_GMask = 0x00;
+ m_BMask = 0x00;
+ m_AMask = 0xFF;
+ break;
+
+ case IMAGE_FORMAT_UVWQ8888:
+ m_Size = 4;
+ m_RShift = 0;
+ m_GShift = 8;
+ m_BShift = 16;
+ m_AShift = 24;
+ m_RMask = 0xFF;
+ m_GMask = 0xFF;
+ m_BMask = 0xFF;
+ m_AMask = 0xFF;
+ break;
+
+ case IMAGE_FORMAT_RGBA16161616:
+#if defined( _X360 )
+ case IMAGE_FORMAT_LINEAR_RGBA16161616:
+#endif
+ m_Size = 8;
+ if ( !IsX360() )
+ {
+ m_RShift = 0;
+ m_GShift = 16;
+ m_BShift = 32;
+ m_AShift = 48;
+ }
+ else
+ {
+ m_RShift = 48;
+ m_GShift = 32;
+ m_BShift = 16;
+ m_AShift = 0;
+ }
+ m_RMask = 0xFFFF;
+ m_GMask = 0xFFFF;
+ m_BMask = 0xFFFF;
+ m_AMask = 0xFFFF;
+ break;
+
+ case IMAGE_FORMAT_I8:
+ // whatever goes into R is considered the intensity.
+ m_Size = 1;
+ m_RShift = 0;
+ m_GShift = 0;
+ m_BShift = 0;
+ m_AShift = 0;
+ m_RMask = 0xFF;
+ m_GMask = 0x00;
+ m_BMask = 0x00;
+ m_AMask = 0x00;
+ break;
+ // FIXME: Add more color formats as need arises
+ default:
+ {
+ static bool format_error_printed[NUM_IMAGE_FORMATS];
+ if ( !format_error_printed[format] )
+ {
+ Assert( 0 );
+ Msg( "CPixelWriter::SetPixelMemory: Unsupported image format %i\n", format );
+ format_error_printed[format] = true;
+ }
+ m_Size = 0; // set to zero so that we don't stomp memory for formats that we don't understand.
+ }
+ break;
+ }
+}
+
+#if 0 // defined( _X360 )
+FORCEINLINE void CPixelWriter::ActivateByteSwapping( bool bSwap )
+{
+ // X360TBD: Who is trying to use this?
+ // Purposely not hooked up because PixelWriter has been ported to read/write native pixels only
+ Assert( 0 );
+
+ if ( bSwap && !(m_nFlags & PIXELWRITER_SWAPBYTES ) )
+ {
+ m_nFlags |= PIXELWRITER_SWAPBYTES;
+
+ // only tested with 4 byte formats
+ Assert( m_Size == 4 );
+ }
+ else if ( !bSwap && (m_nFlags & PIXELWRITER_SWAPBYTES ) )
+ {
+ m_nFlags &= ~PIXELWRITER_SWAPBYTES;
+ }
+ else
+ {
+ // same state
+ return;
+ }
+
+ // swap the shifts
+ m_RShift = 24-m_RShift;
+ m_GShift = 24-m_GShift;
+ m_BShift = 24-m_BShift;
+ m_AShift = 24-m_AShift;
+}
+#endif
+
+//-----------------------------------------------------------------------------
+// Sets where we're writing to
+//-----------------------------------------------------------------------------
+FORCEINLINE_PIXEL void CPixelWriter::Seek( int x, int y )
+{
+ m_pBits = m_pBase + y * m_BytesPerRow + x * m_Size;
+}
+
+
+//-----------------------------------------------------------------------------
+// Skips n bytes:
+//-----------------------------------------------------------------------------
+FORCEINLINE_PIXEL void* CPixelWriter::SkipBytes( int n ) RESTRICT
+{
+ m_pBits += n;
+ return m_pBits;
+}
+
+
+//-----------------------------------------------------------------------------
+// Skips n pixels:
+//-----------------------------------------------------------------------------
+FORCEINLINE_PIXEL void CPixelWriter::SkipPixels( int n )
+{
+ SkipBytes( n * m_Size );
+}
+
+
+//-----------------------------------------------------------------------------
+// Writes a pixel without advancing the index PC ONLY
+//-----------------------------------------------------------------------------
+FORCEINLINE_PIXEL void CPixelWriter::WritePixelNoAdvanceF( float r, float g, float b, float a )
+{
+ Assert( IsUsingFloatFormat() );
+
+ // X360TBD: Not ported
+ Assert( IsPC() );
+
+ if (PIXELWRITER_USING_16BIT_FLOAT_FORMAT & m_nFlags)
+ {
+ float16 fp16[4];
+ fp16[0].SetFloat( r );
+ fp16[1].SetFloat( g );
+ fp16[2].SetFloat( b );
+ fp16[3].SetFloat( a );
+ // fp16
+ unsigned short pBuf[4] = { 0, 0, 0, 0 };
+ pBuf[ m_RShift >> 4 ] |= (fp16[0].GetBits() & m_RMask) << ( m_RShift & 0xF );
+ pBuf[ m_GShift >> 4 ] |= (fp16[1].GetBits() & m_GMask) << ( m_GShift & 0xF );
+ pBuf[ m_BShift >> 4 ] |= (fp16[2].GetBits() & m_BMask) << ( m_BShift & 0xF );
+ pBuf[ m_AShift >> 4 ] |= (fp16[3].GetBits() & m_AMask) << ( m_AShift & 0xF );
+ memcpy( m_pBits, pBuf, m_Size );
+ }
+ else
+ {
+ // fp32
+ int pBuf[4] = { 0, 0, 0, 0 };
+ pBuf[ m_RShift >> 5 ] |= (FloatBits(r) & m_RMask) << ( m_RShift & 0x1F );
+ pBuf[ m_GShift >> 5 ] |= (FloatBits(g) & m_GMask) << ( m_GShift & 0x1F );
+ pBuf[ m_BShift >> 5 ] |= (FloatBits(b) & m_BMask) << ( m_BShift & 0x1F );
+ pBuf[ m_AShift >> 5 ] |= (FloatBits(a) & m_AMask) << ( m_AShift & 0x1F );
+ memcpy( m_pBits, pBuf, m_Size );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Writes a pixel, advances the write index
+//-----------------------------------------------------------------------------
+FORCEINLINE_PIXEL void CPixelWriter::WritePixelF( float r, float g, float b, float a )
+{
+ WritePixelNoAdvanceF(r, g, b, a);
+ m_pBits += m_Size;
+}
+
+
+//-----------------------------------------------------------------------------
+// Writes a pixel, advances the write index
+//-----------------------------------------------------------------------------
+FORCEINLINE_PIXEL void CPixelWriter::WritePixel( int r, int g, int b, int a )
+{
+ WritePixelNoAdvance(r,g,b,a);
+ m_pBits += m_Size;
+}
+
+//-----------------------------------------------------------------------------
+// Writes a pixel, advances the write index
+//-----------------------------------------------------------------------------
+FORCEINLINE_PIXEL void CPixelWriter::WritePixelSigned( int r, int g, int b, int a )
+{
+ WritePixelNoAdvanceSigned(r,g,b,a);
+ m_pBits += m_Size;
+}
+
+
+//-----------------------------------------------------------------------------
+// Writes a pixel without advancing the index
+//-----------------------------------------------------------------------------
+FORCEINLINE_PIXEL void CPixelWriter::WritePixelNoAdvance( int r, int g, int b, int a )
+{
+ Assert( !IsUsingFloatFormat() );
+
+ if ( m_Size <= 0 )
+ {
+ return;
+ }
+ if ( m_Size < 5 )
+ {
+ unsigned int val = (r & m_RMask) << m_RShift;
+ val |= (g & m_GMask) << m_GShift;
+ val |= (m_BShift > 0) ? ((b & m_BMask) << m_BShift) : ((b & m_BMask) >> -m_BShift);
+ val |= (a & m_AMask) << m_AShift;
+
+ switch( m_Size )
+ {
+ default:
+ Assert( 0 );
+ return;
+ case 1:
+ {
+ m_pBits[0] = (unsigned char)((val & 0xff));
+ return;
+ }
+ case 2:
+ {
+ ((unsigned short *)m_pBits)[0] = (unsigned short)((val & 0xffff));
+ return;
+ }
+ case 3:
+ {
+ if ( IsPC() || !IsX360() )
+ {
+ ((unsigned short *)m_pBits)[0] = (unsigned short)((val & 0xffff));
+ m_pBits[2] = (unsigned char)((val >> 16) & 0xff);
+ }
+ else
+ {
+ m_pBits[0] = (unsigned char)(((val >> 16) & 0xff));
+ m_pBits[1] = (unsigned char)(((val >> 8 ) & 0xff));
+ m_pBits[2] = (unsigned char)(val & 0xff);
+ }
+ return;
+ }
+ case 4:
+ {
+ ((unsigned int *)m_pBits)[0] = val;
+ return;
+ }
+ }
+ }
+ else // RGBA32323232 or RGBA16161616 -- PC only.
+ {
+ AssertMsg(!IsX360(), "Unsupported lightmap format used in WritePixelNoAdvance(). This is a severe performance fault.\n");
+
+ int64 val = ( ( int64 )(r & m_RMask) ) << m_RShift;
+ val |= ( ( int64 )(g & m_GMask) ) << m_GShift;
+ val |= (m_BShift > 0) ? ((( int64 )( b & m_BMask)) << m_BShift) : (((int64)( b & m_BMask)) >> -m_BShift);
+ val |= ( ( int64 )(a & m_AMask) ) << m_AShift;
+
+ switch( m_Size )
+ {
+ case 6:
+ {
+ if ( IsPC() || !IsX360() )
+ {
+ ((unsigned int *)m_pBits)[0] = val & 0xffffffff;
+ ((unsigned short *)m_pBits)[2] = (unsigned short)( ( val >> 32 ) & 0xffff );
+ }
+ else
+ {
+ ((unsigned int *)m_pBits)[0] = (val >> 16) & 0xffffffff;
+ ((unsigned short *)m_pBits)[2] = (unsigned short)( val & 0xffff );
+ }
+ return;
+ }
+ case 8:
+ {
+ if ( IsPC() || !IsX360() )
+ {
+ ((unsigned int *)m_pBits)[0] = val & 0xffffffff;
+ ((unsigned int *)m_pBits)[1] = ( val >> 32 ) & 0xffffffff;
+ }
+ else
+ {
+ ((unsigned int *)m_pBits)[0] = ( val >> 32 ) & 0xffffffff;
+ ((unsigned int *)m_pBits)[1] = val & 0xffffffff;
+ }
+ return;
+ }
+ default:
+ Assert( 0 );
+ return;
+ }
+ }
+}
+
+#ifdef _X360
+// There isn't a PC port of these because of the many varied
+// pixel formats the PC deals with. If you write SSE versions
+// of all the various necessary packers, then this can be made
+// to work on PC.
+
+//-----------------------------------------------------------------------------
+// Writes a pixel, advances the write index
+//-----------------------------------------------------------------------------
+FORCEINLINE_PIXEL void CPixelWriter::WritePixel( FLTX4 rgba ) RESTRICT
+{
+ WritePixelNoAdvance(rgba);
+ m_pBits += m_Size;
+}
+
+//-----------------------------------------------------------------------------
+// Writes a pixel without advancing the index
+// rgba are four float values, each on the range 0..255 (though they may leak
+// fractionally over 255 due to numerical errors earlier)
+//-----------------------------------------------------------------------------
+FORCEINLINE_PIXEL void CPixelWriter::WritePixelNoAdvance( FLTX4 rgba ) RESTRICT
+{
+ Assert( !IsUsingFloatFormat() );
+
+ switch (m_Size)
+ {
+ case 0:
+ return;
+ case 4:
+ {
+ AssertMsg((reinterpret_cast<unsigned int>(m_pBits) & 0x03) == 0,"Unaligned m_pBits in WritePixelNoAdvance!");
+ switch ( m_Format )
+ {
+ // note: format names are low-order-byte first.
+ case IMAGE_FORMAT_RGBA8888:
+ case IMAGE_FORMAT_LINEAR_RGBA8888:
+ WritePixelNoAdvance_RGBA8888(rgba);
+ break;
+
+ case IMAGE_FORMAT_BGRA8888: // NOTE! : the low order bits are first in this naming convention.
+ case IMAGE_FORMAT_LINEAR_BGRA8888:
+ WritePixelNoAdvance_BGRA8888(rgba);
+ break;
+
+
+ default:
+ AssertMsg1(false, "Unknown four-byte pixel format %d in lightmap write.\n", m_Format);
+ }
+ break;
+ }
+
+ default:
+ AssertMsg1(false, "WritePixelNoAdvance on unsupported 360 %d-byte format\n", m_Size);
+ break;
+ }
+
+}
+
+
+// here are some explicit formats so we can avoid the switch:
+FORCEINLINE void CPixelWriter::WritePixelNoAdvance_RGBA8888( FLTX4 rgba )
+{
+ // it's easier to do tiered convert-saturates here
+ // than the d3d color convertor op
+
+ // first permute
+ const static fltx4 permReverse = XMVectorPermuteControl(3,2,1,0);
+ fltx4 N = XMVectorPermute(rgba, rgba, permReverse);
+
+ N = __vctuxs(N, 0); // convert to unsigned fixed point 0 w/ saturate
+ N = __vpkuwus(N, N); // convert to halfword saturate
+ N = __vpkuhus(N, N); // convert to byte saturate
+ N = __vspltw(N, 0); // splat w-word to all four
+
+ __stvewx(N, m_pBits, 0); // store whatever word happens to be aligned with m_pBits to that word
+}
+
+FORCEINLINE void CPixelWriter::WritePixelNoAdvance_BGRA8888( FLTX4 rgba )
+{
+ WritePixelNoAdvance_BGRA8888( rgba, m_pBits );
+}
+
+FORCEINLINE void CPixelWriter::WritePixelNoAdvance_BGRA8888( FLTX4 rgba, void * RESTRICT pBits ) RESTRICT
+{
+ // this happens to be in an order such that we can use the handy builtin packing op
+ // clamp to 0..255 (coz it might have leaked over)
+ static const fltx4 vTwoFiftyFive = {255.0f, 255.0f, 255.0f, 255.0f};
+ fltx4 N = MinSIMD(vTwoFiftyFive, rgba);
+
+ // the magic number such that when mul-accummulated against rbga,
+ // gets us a representation 3.0 + (r)*2^-22 -- puts the bits at
+ // the bottom of the float
+ static CONST XMVECTOR PackScale = { (1.0f / (FLOAT)(1 << 22)), (1.0f / (FLOAT)(1 << 22)), (1.0f / (FLOAT)(1 << 22)), (1.0f / (FLOAT)(1 << 22))}; // 255.0f / (FLOAT)(1 << 22)
+ static const XMVECTOR Three = {3.0f, 3.0f, 3.0f, 3.0f};
+
+ N = __vmaddfp(N, PackScale, Three);
+ N = __vpkd3d(N, N, VPACK_D3DCOLOR, VPACK_32, 3); // pack to X word
+ N = __vspltw(N, 0); // splat X
+
+ // this is a nasty thing to work around the April XDK bug in __stvewx
+ {
+ void * RESTRICT copyOfPBits = pBits;
+ __stvewx(N, copyOfPBits, 0);
+ }
+
+}
+
+// for writing entire SIMD registers at once
+FORCEINLINE void CPixelWriter::WriteFourPixelsExplicitLocation_BGRA8888 ( FLTX4 rgba, int offset )
+{
+ Assert( (reinterpret_cast<unsigned int>(m_pBits) & 15) == 0 ); // assert alignment
+ XMStoreVector4A( m_pBits + offset , rgba );
+}
+
+
+#endif
+
+//-----------------------------------------------------------------------------
+// Writes a signed pixel without advancing the index
+//-----------------------------------------------------------------------------
+
+FORCEINLINE_PIXEL void CPixelWriter::WritePixelNoAdvanceSigned( int r, int g, int b, int a )
+{
+ Assert( !IsUsingFloatFormat() );
+
+ if ( m_Size <= 0 )
+ {
+ return;
+ }
+
+ if ( m_Size < 5 )
+ {
+ int val = (r & m_RMask) << m_RShift;
+ val |= (g & m_GMask) << m_GShift;
+ val |= (m_BShift > 0) ? ((b & m_BMask) << m_BShift) : ((b & m_BMask) >> -m_BShift);
+ val |= (a & m_AMask) << m_AShift;
+ signed char *pSignedBits = (signed char *)m_pBits;
+
+ if ( IsPC() || !IsX360() )
+ {
+ switch ( m_Size )
+ {
+ case 4:
+ pSignedBits[3] = (signed char)((val >> 24) & 0xff);
+ // fall through intentionally.
+ case 3:
+ pSignedBits[2] = (signed char)((val >> 16) & 0xff);
+ // fall through intentionally.
+ case 2:
+ pSignedBits[1] = (signed char)((val >> 8) & 0xff);
+ // fall through intentionally.
+ case 1:
+ pSignedBits[0] = (signed char)((val & 0xff));
+ // fall through intentionally.
+ return;
+ }
+ }
+ else
+ {
+ switch ( m_Size )
+ {
+ case 4:
+ pSignedBits[0] = (signed char)((val >> 24) & 0xff);
+ pSignedBits[1] = (signed char)((val >> 16) & 0xff);
+ pSignedBits[2] = (signed char)((val >> 8) & 0xff);
+ pSignedBits[3] = (signed char)(val & 0xff);
+ break;
+ case 3:
+ pSignedBits[0] = (signed char)((val >> 16) & 0xff);
+ pSignedBits[1] = (signed char)((val >> 8) & 0xff);
+ pSignedBits[2] = (signed char)(val & 0xff);
+ break;
+ case 2:
+ pSignedBits[0] = (signed char)((val >> 8) & 0xff);
+ pSignedBits[1] = (signed char)(val & 0xff);
+ break;
+ case 1:
+ pSignedBits[0] = (signed char)(val & 0xff);
+ break;
+ }
+ }
+ }
+ else
+ {
+ int64 val = ( ( int64 )(r & m_RMask) ) << m_RShift;
+ val |= ( ( int64 )(g & m_GMask) ) << m_GShift;
+ val |= (m_BShift > 0) ? ((( int64 )( b & m_BMask)) << m_BShift) : (((int64)( b & m_BMask)) >> -m_BShift);
+ val |= ( ( int64 )(a & m_AMask) ) << m_AShift;
+ signed char *pSignedBits = ( signed char * )m_pBits;
+
+ if ( IsPC() || !IsX360() )
+ {
+ switch( m_Size )
+ {
+ case 8:
+ pSignedBits[7] = (signed char)((val >> 56) & 0xff);
+ pSignedBits[6] = (signed char)((val >> 48) & 0xff);
+ // fall through intentionally.
+ case 6:
+ pSignedBits[5] = (signed char)((val >> 40) & 0xff);
+ pSignedBits[4] = (signed char)((val >> 32) & 0xff);
+ // fall through intentionally.
+ case 4:
+ pSignedBits[3] = (signed char)((val >> 24) & 0xff);
+ // fall through intentionally.
+ case 3:
+ pSignedBits[2] = (signed char)((val >> 16) & 0xff);
+ // fall through intentionally.
+ case 2:
+ pSignedBits[1] = (signed char)((val >> 8) & 0xff);
+ // fall through intentionally.
+ case 1:
+ pSignedBits[0] = (signed char)((val & 0xff));
+ break;
+ default:
+ Assert( 0 );
+ return;
+ }
+ }
+ else
+ {
+ switch( m_Size )
+ {
+ case 8:
+ pSignedBits[0] = (signed char)((val >> 56) & 0xff);
+ pSignedBits[1] = (signed char)((val >> 48) & 0xff);
+ pSignedBits[2] = (signed char)((val >> 40) & 0xff);
+ pSignedBits[3] = (signed char)((val >> 32) & 0xff);
+ pSignedBits[4] = (signed char)((val >> 24) & 0xff);
+ pSignedBits[5] = (signed char)((val >> 16) & 0xff);
+ pSignedBits[6] = (signed char)((val >> 8) & 0xff);
+ pSignedBits[7] = (signed char)(val & 0xff);
+ break;
+ case 6:
+ pSignedBits[0] = (signed char)((val >> 40) & 0xff);
+ pSignedBits[1] = (signed char)((val >> 32) & 0xff);
+ pSignedBits[2] = (signed char)((val >> 24) & 0xff);
+ pSignedBits[3] = (signed char)((val >> 16) & 0xff);
+ pSignedBits[4] = (signed char)((val >> 8) & 0xff);
+ pSignedBits[5] = (signed char)(val & 0xff);
+ break;
+ case 4:
+ pSignedBits[0] = (signed char)((val >> 24) & 0xff);
+ pSignedBits[1] = (signed char)((val >> 16) & 0xff);
+ pSignedBits[2] = (signed char)((val >> 8) & 0xff);
+ pSignedBits[3] = (signed char)(val & 0xff);
+ break;
+ case 3:
+ pSignedBits[0] = (signed char)((val >> 16) & 0xff);
+ pSignedBits[1] = (signed char)((val >> 8) & 0xff);
+ pSignedBits[2] = (signed char)(val & 0xff);
+ break;
+ case 2:
+ pSignedBits[0] = (signed char)((val >> 8) & 0xff);
+ pSignedBits[1] = (signed char)(val & 0xff);
+ break;
+ case 1:
+ pSignedBits[0] = (signed char)(val & 0xff);
+ break;
+ default:
+ Assert( 0 );
+ return;
+ }
+ }
+ }
+}
+
+FORCEINLINE_PIXEL void CPixelWriter::ReadPixelNoAdvance( int &r, int &g, int &b, int &a )
+{
+ Assert( !IsUsingFloatFormat() );
+
+ int val = m_pBits[0];
+ if ( m_Size > 1 )
+ {
+ if ( IsPC() || !IsX360() )
+ {
+ val |= (int)m_pBits[1] << 8;
+ if ( m_Size > 2 )
+ {
+ val |= (int)m_pBits[2] << 16;
+ if ( m_Size > 3 )
+ {
+ val |= (int)m_pBits[3] << 24;
+ }
+ }
+ }
+ else
+ {
+ val <<= 8;
+ val |= (int)m_pBits[1];
+ if ( m_Size > 2 )
+ {
+ val <<= 8;
+ val |= (int)m_pBits[2];
+ if ( m_Size > 3 )
+ {
+ val <<= 8;
+ val |= (int)m_pBits[3];
+ }
+ }
+ }
+ }
+
+ r = (val>>m_RShift) & m_RMask;
+ g = (val>>m_GShift) & m_GMask;
+ b = (val>>m_BShift) & m_BMask;
+ a = (val>>m_AShift) & m_AMask;
+}
+
+#endif // PIXELWRITER_H;
|