Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
DirectXTexPMAlpha.cpp
Go to the documentation of this file.
1 //-------------------------------------------------------------------------------------
2 // DirectXTexPMAlpha.cpp
3 //
4 // DirectX Texture Library - Premultiplied alpha operations
5 //
6 // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
7 // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
8 // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
9 // PARTICULAR PURPOSE.
10 //
11 // Copyright (c) Microsoft Corporation. All rights reserved.
12 //
13 // http://go.microsoft.com/fwlink/?LinkId=248926
14 //-------------------------------------------------------------------------------------
15 
16 #include "directxtexp.h"
17 
18 namespace DirectX
19 {
20 
21 static HRESULT _PremultiplyAlpha( _In_ const Image& srcImage, _In_ const Image& destImage )
22 {
23  assert( srcImage.width == destImage.width );
24  assert( srcImage.height == destImage.height );
25 
26  ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*srcImage.width), 16 ) ) );
27  if ( !scanline )
28  return E_OUTOFMEMORY;
29 
30  const uint8_t *pSrc = srcImage.pixels;
31  uint8_t *pDest = destImage.pixels;
32  if ( !pSrc || !pDest )
33  return E_POINTER;
34 
35  for( size_t h = 0; h < srcImage.height; ++h )
36  {
37  if ( !_LoadScanline( scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format ) )
38  return E_FAIL;
39 
40  XMVECTOR* ptr = scanline.get();
41  for( size_t w = 0; w < srcImage.width; ++w )
42  {
43  XMVECTOR v = *ptr;
44  XMVECTOR alpha = XMVectorSplatW( *ptr );
45  alpha = XMVectorMultiply( v, alpha );
46  *(ptr++) = XMVectorSelect( v, alpha, g_XMSelect1110 );
47  }
48 
49  if ( !_StoreScanline( pDest, destImage.rowPitch, destImage.format, scanline.get(), srcImage.width ) )
50  return E_FAIL;
51 
52  pSrc += srcImage.rowPitch;
53  pDest += destImage.rowPitch;
54  }
55 
56  return S_OK;
57 }
58 
59 static HRESULT _PremultiplyAlphaLinear( _In_ const Image& srcImage, _In_ DWORD flags, _In_ const Image& destImage )
60 {
61  assert( srcImage.width == destImage.width );
62  assert( srcImage.height == destImage.height );
63 
64  static_assert( TEX_PMALPHA_SRGB_IN == TEX_FILTER_SRGB_IN, "TEX_PMALHPA_SRGB* should match TEX_FILTER_SRGB*" );
65  static_assert( TEX_PMALPHA_SRGB_OUT == TEX_FILTER_SRGB_OUT, "TEX_PMALHPA_SRGB* should match TEX_FILTER_SRGB*" );
66  static_assert( TEX_PMALPHA_SRGB == TEX_FILTER_SRGB, "TEX_PMALHPA_SRGB* should match TEX_FILTER_SRGB*" );
67  flags &= TEX_PMALPHA_SRGB;
68 
69  ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*srcImage.width), 16 ) ) );
70  if ( !scanline )
71  return E_OUTOFMEMORY;
72 
73  const uint8_t *pSrc = srcImage.pixels;
74  uint8_t *pDest = destImage.pixels;
75  if ( !pSrc || !pDest )
76  return E_POINTER;
77 
78  for( size_t h = 0; h < srcImage.height; ++h )
79  {
80  if ( !_LoadScanlineLinear( scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format, flags ) )
81  return E_FAIL;
82 
83  XMVECTOR* ptr = scanline.get();
84  for( size_t w = 0; w < srcImage.width; ++w )
85  {
86  XMVECTOR v = *ptr;
87  XMVECTOR alpha = XMVectorSplatW( *ptr );
88  alpha = XMVectorMultiply( v, alpha );
89  *(ptr++) = XMVectorSelect( v, alpha, g_XMSelect1110 );
90  }
91 
92  if ( !_StoreScanlineLinear( pDest, destImage.rowPitch, destImage.format, scanline.get(), srcImage.width, flags ) )
93  return E_FAIL;
94 
95  pSrc += srcImage.rowPitch;
96  pDest += destImage.rowPitch;
97  }
98 
99  return S_OK;
100 }
101 
102 
103 //=====================================================================================
104 // Entry-points
105 //=====================================================================================
106 
107 //-------------------------------------------------------------------------------------
108 // Converts to a premultiplied alpha version of the texture
109 //-------------------------------------------------------------------------------------
110 _Use_decl_annotations_
111 HRESULT PremultiplyAlpha( const Image& srcImage, DWORD flags, ScratchImage& image )
112 {
113  if ( !srcImage.pixels )
114  return E_POINTER;
115 
116  if ( IsCompressed(srcImage.format)
117  || IsPlanar(srcImage.format)
118  || IsPalettized(srcImage.format)
119  || IsTypeless(srcImage.format)
120  || !HasAlpha(srcImage.format) )
121  return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
122 
123 #ifdef _M_X64
124  if ( (srcImage.width > 0xFFFFFFFF) || (srcImage.height > 0xFFFFFFFF) )
125  return E_INVALIDARG;
126 #endif
127 
128  HRESULT hr = image.Initialize2D( srcImage.format, srcImage.width, srcImage.height, 1, 1 );
129  if ( FAILED(hr) )
130  return hr;
131 
132  const Image *rimage = image.GetImage( 0, 0, 0 );
133  if ( !rimage )
134  {
135  image.Release();
136  return E_POINTER;
137  }
138 
139  hr = ( flags & TEX_PMALPHA_IGNORE_SRGB ) ? _PremultiplyAlpha( srcImage, *rimage ) : _PremultiplyAlphaLinear( srcImage, flags, *rimage );
140  if ( FAILED(hr) )
141  {
142  image.Release();
143  return hr;
144  }
145 
146  return S_OK;
147 }
148 
149 
150 //-------------------------------------------------------------------------------------
151 // Converts to a premultiplied alpha version of the texture (complex)
152 //-------------------------------------------------------------------------------------
153 _Use_decl_annotations_
154 HRESULT PremultiplyAlpha( const Image* srcImages, size_t nimages, const TexMetadata& metadata, DWORD flags, ScratchImage& result )
155 {
156  if ( !srcImages || !nimages )
157  return E_INVALIDARG;
158 
159  if ( IsCompressed(metadata.format)
160  || IsPlanar(metadata.format)
161  || IsPalettized(metadata.format)
162  || IsTypeless(metadata.format)
163  || !HasAlpha(metadata.format) )
164  return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
165 
166 #ifdef _M_X64
167  if ( (metadata.width > 0xFFFFFFFF) || (metadata.height > 0xFFFFFFFF) )
168  return E_INVALIDARG;
169 #endif
170 
171  if ( metadata.IsPMAlpha() )
172  {
173  // Already premultiplied
174  return E_FAIL;
175  }
176 
177  TexMetadata mdata2 = metadata;
179  HRESULT hr = result.Initialize( mdata2 );
180  if ( FAILED(hr) )
181  return hr;
182 
183  if ( nimages != result.GetImageCount() )
184  {
185  result.Release();
186  return E_FAIL;
187  }
188 
189  const Image* dest = result.GetImages();
190  if ( !dest )
191  {
192  result.Release();
193  return E_POINTER;
194  }
195 
196  for( size_t index=0; index < nimages; ++index )
197  {
198  const Image& src = srcImages[ index ];
199  if ( src.format != metadata.format )
200  {
201  result.Release();
202  return E_FAIL;
203  }
204 
205 #ifdef _M_X64
206  if ( (src.width > 0xFFFFFFFF) || (src.height > 0xFFFFFFFF) )
207  return E_FAIL;
208 #endif
209  const Image& dst = dest[ index ];
210  assert( dst.format == metadata.format );
211 
212  if ( src.width != dst.width || src.height != dst.height )
213  {
214  result.Release();
215  return E_FAIL;
216  }
217 
218  hr = ( flags & TEX_PMALPHA_IGNORE_SRGB ) ? _PremultiplyAlpha( src, dst ) : _PremultiplyAlphaLinear( src, flags, dst );
219  if ( FAILED(hr) )
220  {
221  result.Release();
222  return hr;
223  }
224  }
225 
226  return S_OK;
227 }
228 
229 }; // namespace
std::unique_ptr< DirectX::XMVECTOR, aligned_deleter > ScopedAlignedArrayXMVECTOR
Definition: scoped.h:27
const Image * GetImage(_In_ size_t mip, _In_ size_t item, _In_ size_t slice) const
uint8_t * pixels
Definition: DirectXTex.h:230
bool HasAlpha(_In_ DXGI_FORMAT fmt)
bool IsPlanar(_In_ DXGI_FORMAT fmt)
DXGI_FORMAT format
Definition: DirectXTex.h:125
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ DXGI_FORMAT _In_ DWORD flags
Definition: DirectXTexP.h:170
size_t _In_ DXGI_FORMAT size_t _In_ TEXP_LEGACY_FORMAT _In_ DWORD flags assert(pDestination &&outSize > 0)
HRESULT Initialize(_In_ const TexMetadata &mdata, _In_ DWORD flags=CP_FLAGS_NONE)
static HRESULT _PremultiplyAlphaLinear(_In_ const Image &srcImage, _In_ DWORD flags, _In_ const Image &destImage)
HRESULT Initialize2D(_In_ DXGI_FORMAT fmt, _In_ size_t width, _In_ size_t height, _In_ size_t arraySize, _In_ size_t mipLevels, _In_ DWORD flags=CP_FLAGS_NONE)
_Use_decl_annotations_ bool _LoadScanline(XMVECTOR *pDestination, size_t count, LPCVOID pSource, size_t size, DXGI_FORMAT format)
bool IsCompressed(_In_ DXGI_FORMAT fmt)
size_t GetImageCount() const
Definition: DirectXTex.h:264
_In_ size_t _In_ const TexMetadata & metadata
Definition: DirectXTexP.h:116
bool IsPalettized(_In_ DXGI_FORMAT fmt)
void SetAlphaMode(TEX_ALPHA_MODE mode)
Definition: DirectXTex.h:135
_Use_decl_annotations_ bool _LoadScanlineLinear(XMVECTOR *pDestination, size_t count, LPCVOID pSource, size_t size, DXGI_FORMAT format, DWORD flags)
_Use_decl_annotations_ bool _StoreScanlineLinear(LPVOID pDestination, size_t size, DXGI_FORMAT format, XMVECTOR *pSource, size_t count, DWORD flags)
bool IsTypeless(_In_ DXGI_FORMAT fmt, _In_ bool partialTypeless=true)
static HRESULT _PremultiplyAlpha(_In_ const Image &srcImage, _In_ const Image &destImage)
char * dest
Definition: lz4.h:61
DXGI_FORMAT format
Definition: DirectXTex.h:227
const Image * GetImages() const
Definition: DirectXTex.h:263
bool IsPMAlpha() const
Definition: DirectXTex.h:134
_Use_decl_annotations_ bool _StoreScanline(LPVOID pDestination, size_t size, DXGI_FORMAT format, const XMVECTOR *pSource, size_t count, float threshold)
HRESULT PremultiplyAlpha(_In_ const Image &srcImage, _In_ DWORD flags, _Out_ ScratchImage &image)