diff --git a/DirectXTex/DirectXTexConvert.cpp b/DirectXTex/DirectXTexConvert.cpp index 1a55be6..efab2df 100644 --- a/DirectXTex/DirectXTexConvert.cpp +++ b/DirectXTex/DirectXTexConvert.cpp @@ -1862,6 +1862,75 @@ static inline XMVECTOR _TableEncodeGamma22( FXMVECTOR v ) return XMLoadFloat4( (XMFLOAT4*)f ); } +_Use_decl_annotations_ +bool _StoreScanlineLinear( LPVOID pDestination, size_t size, DXGI_FORMAT format, + XMVECTOR* pSource, size_t count, DWORD flags ) +{ + assert( pDestination && size > 0 ); + assert( pSource && count > 0 && (((uintptr_t)pSource & 0xF) == 0) ); + assert( IsValid(format) && !IsVideo(format) && !IsTypeless(format) && !IsCompressed(format) ); + + switch ( format ) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + flags |= TEX_FILTER_SRGB; + break; + + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R32G32B32_FLOAT: + case DXGI_FORMAT_R16G16B16A16_FLOAT: + case DXGI_FORMAT_R16G16B16A16_UNORM: + case DXGI_FORMAT_R32G32_FLOAT: + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R11G11B10_FLOAT: + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R16G16_FLOAT: + case DXGI_FORMAT_R16G16_UNORM: + case DXGI_FORMAT_R32_FLOAT: + case DXGI_FORMAT_R8G8_UNORM: + case DXGI_FORMAT_R16_FLOAT: + case DXGI_FORMAT_R16_UNORM: + case DXGI_FORMAT_R8_UNORM: + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + case DXGI_FORMAT_R8G8_B8G8_UNORM: + case DXGI_FORMAT_G8R8_G8B8_UNORM: + case DXGI_FORMAT_B5G6R5_UNORM: + case DXGI_FORMAT_B5G5R5A1_UNORM: + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM: +#ifdef DXGI_1_2_FORMATS + case DXGI_FORMAT_B4G4R4A4_UNORM: +#endif + break; + + default: + // can't treat A8, XR, Depth, SNORM, UINT, or SINT as sRGB + flags &= ~TEX_FILTER_SRGB; + break; + } + + // sRGB output processing (RGB -> sRGB) + if ( flags & TEX_FILTER_SRGB_OUT ) + { + // To avoid the need for another temporary scanline buffer, we allow this function to overwrite the source buffer in-place + // Given the intended usage in the filtering routines, this is not a problem. + XMVECTOR* ptr = pSource; + for( size_t i=0; i < count; ++i ) + { + // rgb = rgb^(1/2.2); a=a + XMVECTOR v = *ptr; + XMVECTOR v1 = _TableEncodeGamma22( v ); + // Use table instead of XMVectorPow( v, [1/2.2f 1/2.2f 1/2.2f 1]). + // Note table lookup will also saturate the result + *ptr++ = XMVectorSelect( v, v1, g_XMSelect1110 ); + } + } + + return _StoreScanline( pDestination, size, format, pSource, count ); +} + //------------------------------------------------------------------------------------- // sRGB -> RGB @@ -1902,7 +1971,6 @@ static const uint32_t g_fDecodeGamma22[] = 0x3f795b20, 0x3f7a7651, 0x3f7b91a2, 0x3f7cad0e, 0x3f7dc896, 0x3f7ee43c, 0x3f800000, 0x3f800000 }; - #pragma prefast(suppress : 25000, "FXMVECTOR is 16 bytes") static inline XMVECTOR _TableDecodeGamma22( FXMVECTOR v ) { @@ -1925,6 +1993,78 @@ static inline XMVECTOR _TableDecodeGamma22( FXMVECTOR v ) return XMLoadFloat4( (XMFLOAT4*)f ); } +_Use_decl_annotations_ +bool _LoadScanlineLinear( XMVECTOR* pDestination, size_t count, + LPCVOID pSource, size_t size, DXGI_FORMAT format, DWORD flags ) +{ + assert( pDestination && count > 0 && (((uintptr_t)pDestination & 0xF) == 0) ); + assert( pSource && size > 0 ); + assert( IsValid(format) && !IsVideo(format) && !IsTypeless(format,false) && !IsCompressed(format) ); + + switch ( format ) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + flags |= TEX_FILTER_SRGB; + break; + + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R32G32B32_FLOAT: + case DXGI_FORMAT_R16G16B16A16_FLOAT: + case DXGI_FORMAT_R16G16B16A16_UNORM: + case DXGI_FORMAT_R32G32_FLOAT: + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R11G11B10_FLOAT: + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R16G16_FLOAT: + case DXGI_FORMAT_R16G16_UNORM: + case DXGI_FORMAT_R32_FLOAT: + case DXGI_FORMAT_R8G8_UNORM: + case DXGI_FORMAT_R16_FLOAT: + case DXGI_FORMAT_R16_UNORM: + case DXGI_FORMAT_R8_UNORM: + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + case DXGI_FORMAT_R8G8_B8G8_UNORM: + case DXGI_FORMAT_G8R8_G8B8_UNORM: + case DXGI_FORMAT_B5G6R5_UNORM: + case DXGI_FORMAT_B5G5R5A1_UNORM: + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM: +#ifdef DXGI_1_2_FORMATS + case DXGI_FORMAT_B4G4R4A4_UNORM: +#endif + break; + + default: + // can't treat A8, XR, Depth, SNORM, UINT, or SINT as sRGB + flags &= ~TEX_FILTER_SRGB; + break; + } + + if ( _LoadScanline( pDestination, count, pSource, size, format ) ) + { + // sRGB input processing (sRGB -> RGB) + if ( flags & TEX_FILTER_SRGB_IN ) + { + XMVECTOR* ptr = pDestination; + for( size_t i=0; i < count; ++i ) + { + // rgb = rgb^(2.2); a=a + XMVECTOR v = *ptr; + // Use table instead of XMVectorPow( v, [2.2f 2.2f 2.2f 1]). + // Note table lookup will also saturate the result + XMVECTOR v1 = _TableDecodeGamma22( v ); + *ptr++ = XMVectorSelect( v, v1, g_XMSelect1110 ); + } + } + + return true; + } + + return false; +} + //------------------------------------------------------------------------------------- // Convert scanline based on source/target formats @@ -2083,11 +2223,41 @@ void _ConvertScanline( XMVECTOR* pBuffer, size_t count, DXGI_FORMAT outFormat, D assert( _GetConvertFlags( outFormat ) == out->flags ); // Handle SRGB filtering modes - if ( IsSRGB( inFormat ) ) + switch ( inFormat ) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + case DXGI_FORMAT_BC7_UNORM_SRGB: flags |= TEX_FILTER_SRGB_IN; + break; - if ( IsSRGB( outFormat ) ) + case DXGI_FORMAT_A8_UNORM: + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + flags &= ~TEX_FILTER_SRGB_IN; + break; + } + + switch ( outFormat ) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + case DXGI_FORMAT_BC7_UNORM_SRGB: flags |= TEX_FILTER_SRGB_OUT; + break; + + case DXGI_FORMAT_A8_UNORM: + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + flags &= ~TEX_FILTER_SRGB_OUT; + break; + } if ( (flags & (TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT)) == (TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT) ) { @@ -2097,7 +2267,7 @@ void _ConvertScanline( XMVECTOR* pBuffer, size_t count, DXGI_FORMAT outFormat, D // sRGB input processing (sRGB -> RGB) if ( flags & TEX_FILTER_SRGB_IN ) { - if ( (in->flags & CONVF_FLOAT) || (in->flags & CONVF_UNORM) ) + if ( !(in->flags & CONVF_DEPTH) && ( (in->flags & CONVF_FLOAT) || (in->flags & CONVF_UNORM) ) ) { XMVECTOR* ptr = pBuffer; for( size_t i=0; i < count; ++i ) @@ -2302,7 +2472,7 @@ void _ConvertScanline( XMVECTOR* pBuffer, size_t count, DXGI_FORMAT outFormat, D // sRGB output processing (RGB -> sRGB) if ( flags & TEX_FILTER_SRGB_OUT ) { - if ( (out->flags & CONVF_FLOAT) || (out->flags & CONVF_UNORM) ) + if ( !(out->flags & CONVF_DEPTH) && ( (out->flags & CONVF_FLOAT) || (out->flags & CONVF_UNORM) ) ) { XMVECTOR* ptr = pBuffer; for( size_t i=0; i < count; ++i ) diff --git a/DirectXTex/DirectXTexMipmaps.cpp b/DirectXTex/DirectXTexMipmaps.cpp index 28e7071..639b41e 100644 --- a/DirectXTex/DirectXTexMipmaps.cpp +++ b/DirectXTex/DirectXTexMipmaps.cpp @@ -380,6 +380,12 @@ static bool _UseWICFiltering( _In_ DXGI_FORMAT format, _In_ DWORD filter ) return true; } + if ( IsSRGB(format) || (filter & TEX_FILTER_SRGB) ) + { + // Use non-WIC code paths for sRGB correct filtering + return false; + } + static_assert( TEX_FILTER_POINT == 0x100000, "TEX_FILTER_ flag values don't match TEX_FILTER_MASK" ); switch ( filter & TEX_FILTER_MASK ) @@ -680,7 +686,7 @@ static HRESULT _Generate2DMipsPointFilter( _In_ size_t levels, _In_ const Scratc //--- 2D Box Filter --- -static HRESULT _Generate2DMipsBoxFilter( _In_ size_t levels, _In_ const ScratchImage& mipChain, _In_ size_t item ) +static HRESULT _Generate2DMipsBoxFilter( _In_ size_t levels, _In_ DWORD filter, _In_ const ScratchImage& mipChain, _In_ size_t item ) { if ( !mipChain.GetImages() ) return E_INVALIDARG; @@ -744,13 +750,13 @@ static HRESULT _Generate2DMipsBoxFilter( _In_ size_t levels, _In_ const ScratchI for( size_t y = 0; y < nheight; ++y ) { - if ( !_LoadScanline( urow0, width, pSrc, rowPitch, src->format ) ) + if ( !_LoadScanlineLinear( urow0, width, pSrc, rowPitch, src->format, filter ) ) return E_FAIL; pSrc += rowPitch; if ( urow0 != urow1 ) { - if ( !_LoadScanline( urow1, width, pSrc, rowPitch, src->format ) ) + if ( !_LoadScanlineLinear( urow1, width, pSrc, rowPitch, src->format, filter ) ) return E_FAIL; pSrc += rowPitch; } @@ -762,7 +768,7 @@ static HRESULT _Generate2DMipsBoxFilter( _In_ size_t levels, _In_ const ScratchI AVERAGE4( target[ x ], urow0[ x2 ], urow1[ x2 ], urow2[ x2 ], urow3[ x2 ] ); } - if ( !_StoreScanline( pDest, dest->rowPitch, dest->format, target, nwidth ) ) + if ( !_StoreScanlineLinear( pDest, dest->rowPitch, dest->format, target, nwidth, filter ) ) return E_FAIL; pDest += dest->rowPitch; } @@ -847,7 +853,7 @@ static HRESULT _Generate2DMipsLinearFilter( _In_ size_t levels, _In_ DWORD filte { u0 = toY.u0; - if ( !_LoadScanline( row0, width, pSrc + (rowPitch * u0), rowPitch, src->format ) ) + if ( !_LoadScanlineLinear( row0, width, pSrc + (rowPitch * u0), rowPitch, src->format, filter ) ) return E_FAIL; } else @@ -863,7 +869,7 @@ static HRESULT _Generate2DMipsLinearFilter( _In_ size_t levels, _In_ DWORD filte { u1 = toY.u1; - if ( !_LoadScanline( row1, width, pSrc + (rowPitch * u1), rowPitch, src->format ) ) + if ( !_LoadScanlineLinear( row1, width, pSrc + (rowPitch * u1), rowPitch, src->format, filter ) ) return E_FAIL; } @@ -874,7 +880,7 @@ static HRESULT _Generate2DMipsLinearFilter( _In_ size_t levels, _In_ DWORD filte BILINEAR_INTERPOLATE( target[x], toX, toY, row0, row1 ); } - if ( !_StoreScanline( pDest, dest->rowPitch, dest->format, target, nwidth ) ) + if ( !_StoreScanlineLinear( pDest, dest->rowPitch, dest->format, target, nwidth, filter ) ) return E_FAIL; pDest += dest->rowPitch; } @@ -966,7 +972,7 @@ static HRESULT _Generate2DMipsCubicFilter( _In_ size_t levels, _In_ DWORD filter { u0 = toY.u0; - if ( !_LoadScanline( row0, width, pSrc + (rowPitch * u0), rowPitch, src->format ) ) + if ( !_LoadScanlineLinear( row0, width, pSrc + (rowPitch * u0), rowPitch, src->format, filter ) ) return E_FAIL; } else if ( toY.u0 == u1 ) @@ -999,7 +1005,7 @@ static HRESULT _Generate2DMipsCubicFilter( _In_ size_t levels, _In_ DWORD filter { u1 = toY.u1; - if ( !_LoadScanline( row1, width, pSrc + (rowPitch * u1), rowPitch, src->format ) ) + if ( !_LoadScanlineLinear( row1, width, pSrc + (rowPitch * u1), rowPitch, src->format, filter ) ) return E_FAIL; } else if ( toY.u1 == u2 ) @@ -1025,7 +1031,7 @@ static HRESULT _Generate2DMipsCubicFilter( _In_ size_t levels, _In_ DWORD filter { u2 = toY.u2; - if ( !_LoadScanline( row2, width, pSrc + (rowPitch * u2), rowPitch, src->format ) ) + if ( !_LoadScanlineLinear( row2, width, pSrc + (rowPitch * u2), rowPitch, src->format, filter ) ) return E_FAIL; } else @@ -1042,7 +1048,7 @@ static HRESULT _Generate2DMipsCubicFilter( _In_ size_t levels, _In_ DWORD filter { u3 = toY.u3; - if ( !_LoadScanline( row3, width, pSrc + (rowPitch * u3), rowPitch, src->format ) ) + if ( !_LoadScanlineLinear( row3, width, pSrc + (rowPitch * u3), rowPitch, src->format, filter ) ) return E_FAIL; } @@ -1060,7 +1066,7 @@ static HRESULT _Generate2DMipsCubicFilter( _In_ size_t levels, _In_ DWORD filter CUBIC_INTERPOLATE( target[x], toY.x, C0, C1, C2, C3 ); } - if ( !_StoreScanline( pDest, dest->rowPitch, dest->format, target, nwidth ) ) + if ( !_StoreScanlineLinear( pDest, dest->rowPitch, dest->format, target, nwidth, filter ) ) return E_FAIL; pDest += dest->rowPitch; } @@ -1277,7 +1283,7 @@ static HRESULT _Generate3DMipsPointFilter( _In_ size_t depth, _In_ size_t levels //--- 3D Box Filter --- -static HRESULT _Generate3DMipsBoxFilter( _In_ size_t depth, _In_ size_t levels, _In_ const ScratchImage& mipChain ) +static HRESULT _Generate3DMipsBoxFilter( _In_ size_t depth, _In_ size_t levels, _In_ DWORD filter, _In_ const ScratchImage& mipChain ) { if ( !depth || !mipChain.GetImages() ) return E_INVALIDARG; @@ -1362,24 +1368,24 @@ static HRESULT _Generate3DMipsBoxFilter( _In_ size_t depth, _In_ size_t levels, for( size_t y = 0; y < nheight; ++y ) { - if ( !_LoadScanline( urow0, width, pSrc1, aRowPitch, srca->format ) ) + if ( !_LoadScanlineLinear( urow0, width, pSrc1, aRowPitch, srca->format, filter ) ) return E_FAIL; pSrc1 += aRowPitch; if ( urow0 != urow1 ) { - if ( !_LoadScanline( urow1, width, pSrc1, aRowPitch, srca->format ) ) + if ( !_LoadScanlineLinear( urow1, width, pSrc1, aRowPitch, srca->format, filter ) ) return E_FAIL; pSrc1 += aRowPitch; } - if ( !_LoadScanline( vrow0, width, pSrc2, bRowPitch, srcb->format ) ) + if ( !_LoadScanlineLinear( vrow0, width, pSrc2, bRowPitch, srcb->format, filter ) ) return E_FAIL; pSrc2 += bRowPitch; if ( vrow0 != vrow1 ) { - if ( !_LoadScanline( vrow1, width, pSrc2, bRowPitch, srcb->format ) ) + if ( !_LoadScanlineLinear( vrow1, width, pSrc2, bRowPitch, srcb->format, filter ) ) return E_FAIL; pSrc2 += bRowPitch; } @@ -1392,7 +1398,7 @@ static HRESULT _Generate3DMipsBoxFilter( _In_ size_t depth, _In_ size_t levels, vrow0[ x2 ], vrow1[ x2 ], vrow2[ x2 ], vrow3[ x2 ] ); } - if ( !_StoreScanline( pDest, dest->rowPitch, dest->format, target, nwidth ) ) + if ( !_StoreScanlineLinear( pDest, dest->rowPitch, dest->format, target, nwidth, filter ) ) return E_FAIL; pDest += dest->rowPitch; } @@ -1417,13 +1423,13 @@ static HRESULT _Generate3DMipsBoxFilter( _In_ size_t depth, _In_ size_t levels, for( size_t y = 0; y < nheight; ++y ) { - if ( !_LoadScanline( urow0, width, pSrc, rowPitch, src->format ) ) + if ( !_LoadScanlineLinear( urow0, width, pSrc, rowPitch, src->format, filter ) ) return E_FAIL; pSrc += rowPitch; if ( urow0 != urow1 ) { - if ( !_LoadScanline( urow1, width, pSrc, rowPitch, src->format ) ) + if ( !_LoadScanlineLinear( urow1, width, pSrc, rowPitch, src->format, filter ) ) return E_FAIL; pSrc += rowPitch; } @@ -1435,7 +1441,7 @@ static HRESULT _Generate3DMipsBoxFilter( _In_ size_t depth, _In_ size_t levels, AVERAGE4( target[ x ], urow0[ x2 ], urow1[ x2 ], urow2[ x2 ], urow3[ x2 ] ); } - if ( !_StoreScanline( pDest, dest->rowPitch, dest->format, target, nwidth ) ) + if ( !_StoreScanlineLinear( pDest, dest->rowPitch, dest->format, target, nwidth, filter ) ) return E_FAIL; pDest += dest->rowPitch; } @@ -1538,8 +1544,8 @@ static HRESULT _Generate3DMipsLinearFilter( _In_ size_t depth, _In_ size_t level { u0 = toY.u0; - if ( !_LoadScanline( urow0, width, srca->pixels + (srca->rowPitch * u0), srca->rowPitch, srca->format ) - || !_LoadScanline( vrow0, width, srcb->pixels + (srcb->rowPitch * u0), srcb->rowPitch, srcb->format ) ) + if ( !_LoadScanlineLinear( urow0, width, srca->pixels + (srca->rowPitch * u0), srca->rowPitch, srca->format, filter ) + || !_LoadScanlineLinear( vrow0, width, srcb->pixels + (srcb->rowPitch * u0), srcb->rowPitch, srcb->format, filter ) ) return E_FAIL; } else @@ -1556,8 +1562,8 @@ static HRESULT _Generate3DMipsLinearFilter( _In_ size_t depth, _In_ size_t level { u1 = toY.u1; - if ( !_LoadScanline( urow1, width, srca->pixels + (srca->rowPitch * u1), srca->rowPitch, srca->format ) - || !_LoadScanline( vrow1, width, srcb->pixels + (srcb->rowPitch * u1), srcb->rowPitch, srcb->format ) ) + if ( !_LoadScanlineLinear( urow1, width, srca->pixels + (srca->rowPitch * u1), srca->rowPitch, srca->format, filter ) + || !_LoadScanlineLinear( vrow1, width, srcb->pixels + (srcb->rowPitch * u1), srcb->rowPitch, srcb->format, filter ) ) return E_FAIL; } @@ -1568,7 +1574,7 @@ static HRESULT _Generate3DMipsLinearFilter( _In_ size_t depth, _In_ size_t level TRILINEAR_INTERPOLATE( target[x], toX, toY, toZ, urow0, urow1, vrow0, vrow1 ); } - if ( !_StoreScanline( pDest, dest->rowPitch, dest->format, target, nwidth ) ) + if ( !_StoreScanlineLinear( pDest, dest->rowPitch, dest->format, target, nwidth, filter ) ) return E_FAIL; pDest += dest->rowPitch; } @@ -1601,7 +1607,7 @@ static HRESULT _Generate3DMipsLinearFilter( _In_ size_t depth, _In_ size_t level { u0 = toY.u0; - if ( !_LoadScanline( urow0, width, pSrc + (rowPitch * u0), rowPitch, src->format ) ) + if ( !_LoadScanlineLinear( urow0, width, pSrc + (rowPitch * u0), rowPitch, src->format, filter ) ) return E_FAIL; } else @@ -1617,7 +1623,7 @@ static HRESULT _Generate3DMipsLinearFilter( _In_ size_t depth, _In_ size_t level { u1 = toY.u1; - if ( !_LoadScanline( urow1, width, pSrc + (rowPitch * u1), rowPitch, src->format ) ) + if ( !_LoadScanlineLinear( urow1, width, pSrc + (rowPitch * u1), rowPitch, src->format, filter ) ) return E_FAIL; } @@ -1628,7 +1634,7 @@ static HRESULT _Generate3DMipsLinearFilter( _In_ size_t depth, _In_ size_t level BILINEAR_INTERPOLATE( target[x], toX, toY, urow0, urow1 ); } - if ( !_StoreScanline( pDest, dest->rowPitch, dest->format, target, nwidth ) ) + if ( !_StoreScanlineLinear( pDest, dest->rowPitch, dest->format, target, nwidth, filter ) ) return E_FAIL; pDest += dest->rowPitch; } @@ -1748,10 +1754,10 @@ static HRESULT _Generate3DMipsCubicFilter( _In_ size_t depth, _In_ size_t levels { u0 = toY.u0; - if ( !_LoadScanline( urow[0], width, srca->pixels + (srca->rowPitch * u0), srca->rowPitch, srca->format ) - || !_LoadScanline( urow[1], width, srcb->pixels + (srcb->rowPitch * u0), srcb->rowPitch, srcb->format ) - || !_LoadScanline( urow[2], width, srcc->pixels + (srcc->rowPitch * u0), srcc->rowPitch, srcc->format ) - || !_LoadScanline( urow[3], width, srcd->pixels + (srcd->rowPitch * u0), srcd->rowPitch, srcd->format ) ) + if ( !_LoadScanlineLinear( urow[0], width, srca->pixels + (srca->rowPitch * u0), srca->rowPitch, srca->format, filter ) + || !_LoadScanlineLinear( urow[1], width, srcb->pixels + (srcb->rowPitch * u0), srcb->rowPitch, srcb->format, filter ) + || !_LoadScanlineLinear( urow[2], width, srcc->pixels + (srcc->rowPitch * u0), srcc->rowPitch, srcc->format, filter ) + || !_LoadScanlineLinear( urow[3], width, srcd->pixels + (srcd->rowPitch * u0), srcd->rowPitch, srcd->format, filter ) ) return E_FAIL; } else if ( toY.u0 == u1 ) @@ -1793,10 +1799,10 @@ static HRESULT _Generate3DMipsCubicFilter( _In_ size_t depth, _In_ size_t levels { u1 = toY.u1; - if ( !_LoadScanline( vrow[0], width, srca->pixels + (srca->rowPitch * u1), srca->rowPitch, srca->format ) - || !_LoadScanline( vrow[1], width, srcb->pixels + (srcb->rowPitch * u1), srcb->rowPitch, srcb->format ) - || !_LoadScanline( vrow[2], width, srcc->pixels + (srcc->rowPitch * u1), srcc->rowPitch, srcc->format ) - || !_LoadScanline( vrow[3], width, srcd->pixels + (srcd->rowPitch * u1), srcd->rowPitch, srcd->format ) ) + if ( !_LoadScanlineLinear( vrow[0], width, srca->pixels + (srca->rowPitch * u1), srca->rowPitch, srca->format, filter ) + || !_LoadScanlineLinear( vrow[1], width, srcb->pixels + (srcb->rowPitch * u1), srcb->rowPitch, srcb->format, filter ) + || !_LoadScanlineLinear( vrow[2], width, srcc->pixels + (srcc->rowPitch * u1), srcc->rowPitch, srcc->format, filter ) + || !_LoadScanlineLinear( vrow[3], width, srcd->pixels + (srcd->rowPitch * u1), srcd->rowPitch, srcd->format, filter ) ) return E_FAIL; } else if ( toY.u1 == u2 ) @@ -1828,10 +1834,10 @@ static HRESULT _Generate3DMipsCubicFilter( _In_ size_t depth, _In_ size_t levels { u2 = toY.u2; - if ( !_LoadScanline( srow[0], width, srca->pixels + (srca->rowPitch * u2), srca->rowPitch, srca->format ) - || !_LoadScanline( srow[1], width, srcb->pixels + (srcb->rowPitch * u2), srcb->rowPitch, srcb->format ) - || !_LoadScanline( srow[2], width, srcc->pixels + (srcc->rowPitch * u2), srcc->rowPitch, srcc->format ) - || !_LoadScanline( srow[3], width, srcd->pixels + (srcd->rowPitch * u2), srcd->rowPitch, srcd->format ) ) + if ( !_LoadScanlineLinear( srow[0], width, srca->pixels + (srca->rowPitch * u2), srca->rowPitch, srca->format, filter ) + || !_LoadScanlineLinear( srow[1], width, srcb->pixels + (srcb->rowPitch * u2), srcb->rowPitch, srcb->format, filter ) + || !_LoadScanlineLinear( srow[2], width, srcc->pixels + (srcc->rowPitch * u2), srcc->rowPitch, srcc->format, filter ) + || !_LoadScanlineLinear( srow[3], width, srcd->pixels + (srcd->rowPitch * u2), srcd->rowPitch, srcd->format, filter ) ) return E_FAIL; } else @@ -1851,10 +1857,10 @@ static HRESULT _Generate3DMipsCubicFilter( _In_ size_t depth, _In_ size_t levels { u3 = toY.u3; - if ( !_LoadScanline( trow[0], width, srca->pixels + (srca->rowPitch * u3), srca->rowPitch, srca->format ) - || !_LoadScanline( trow[1], width, srcb->pixels + (srcb->rowPitch * u3), srcb->rowPitch, srcb->format ) - || !_LoadScanline( trow[2], width, srcc->pixels + (srcc->rowPitch * u3), srcc->rowPitch, srcc->format ) - || !_LoadScanline( trow[3], width, srcd->pixels + (srcd->rowPitch * u3), srcd->rowPitch, srcd->format ) ) + if ( !_LoadScanlineLinear( trow[0], width, srca->pixels + (srca->rowPitch * u3), srca->rowPitch, srca->format, filter ) + || !_LoadScanlineLinear( trow[1], width, srcb->pixels + (srcb->rowPitch * u3), srcb->rowPitch, srcb->format, filter ) + || !_LoadScanlineLinear( trow[2], width, srcc->pixels + (srcc->rowPitch * u3), srcc->rowPitch, srcc->format, filter ) + || !_LoadScanlineLinear( trow[3], width, srcd->pixels + (srcd->rowPitch * u3), srcd->rowPitch, srcd->format, filter ) ) return E_FAIL; } @@ -1878,7 +1884,7 @@ static HRESULT _Generate3DMipsCubicFilter( _In_ size_t depth, _In_ size_t levels CUBIC_INTERPOLATE( target[x], toZ.x, D[0], D[1], D[2], D[3] ); } - if ( !_StoreScanline( pDest, dest->rowPitch, dest->format, target, nwidth ) ) + if ( !_StoreScanlineLinear( pDest, dest->rowPitch, dest->format, target, nwidth, filter ) ) return E_FAIL; pDest += dest->rowPitch; } @@ -1914,7 +1920,7 @@ static HRESULT _Generate3DMipsCubicFilter( _In_ size_t depth, _In_ size_t levels { u0 = toY.u0; - if ( !_LoadScanline( urow[0], width, pSrc + (rowPitch * u0), rowPitch, src->format ) ) + if ( !_LoadScanlineLinear( urow[0], width, pSrc + (rowPitch * u0), rowPitch, src->format, filter ) ) return E_FAIL; } else if ( toY.u0 == u1 ) @@ -1947,7 +1953,7 @@ static HRESULT _Generate3DMipsCubicFilter( _In_ size_t depth, _In_ size_t levels { u1 = toY.u1; - if ( !_LoadScanline( vrow[0], width, pSrc + (rowPitch * u1), rowPitch, src->format ) ) + if ( !_LoadScanlineLinear( vrow[0], width, pSrc + (rowPitch * u1), rowPitch, src->format, filter ) ) return E_FAIL; } else if ( toY.u1 == u2 ) @@ -1973,7 +1979,7 @@ static HRESULT _Generate3DMipsCubicFilter( _In_ size_t depth, _In_ size_t levels { u2 = toY.u2; - if ( !_LoadScanline( srow[0], width, pSrc + (rowPitch * u2), rowPitch, src->format ) ) + if ( !_LoadScanlineLinear( srow[0], width, pSrc + (rowPitch * u2), rowPitch, src->format, filter ) ) return E_FAIL; } else @@ -1990,7 +1996,7 @@ static HRESULT _Generate3DMipsCubicFilter( _In_ size_t depth, _In_ size_t levels { u3 = toY.u3; - if ( !_LoadScanline( trow[0], width, pSrc + (rowPitch * u3), rowPitch, src->format ) ) + if ( !_LoadScanlineLinear( trow[0], width, pSrc + (rowPitch * u3), rowPitch, src->format, filter ) ) return E_FAIL; } @@ -2007,7 +2013,7 @@ static HRESULT _Generate3DMipsCubicFilter( _In_ size_t depth, _In_ size_t levels CUBIC_INTERPOLATE( target[x], toY.x, C0, C1, C2, C3 ); } - if ( !_StoreScanline( pDest, dest->rowPitch, dest->format, target, nwidth ) ) + if ( !_StoreScanlineLinear( pDest, dest->rowPitch, dest->format, target, nwidth, filter ) ) return E_FAIL; pDest += dest->rowPitch; } @@ -2143,7 +2149,7 @@ HRESULT GenerateMipMaps( const Image& baseImage, DWORD filter, size_t levels, Sc if ( FAILED(hr) ) return hr; - hr = _Generate2DMipsBoxFilter( levels, mipChain, 0 ); + hr = _Generate2DMipsBoxFilter( levels, filter, mipChain, 0 ); if ( FAILED(hr) ) mipChain.Release(); return hr; @@ -2320,7 +2326,7 @@ HRESULT GenerateMipMaps( const Image* srcImages, size_t nimages, const TexMetada for( size_t item = 0; item < metadata.arraySize; ++item ) { - hr = _Generate2DMipsBoxFilter( levels, mipChain, item ); + hr = _Generate2DMipsBoxFilter( levels, filter, mipChain, item ); if ( FAILED(hr) ) mipChain.Release(); } @@ -2427,7 +2433,7 @@ HRESULT GenerateMipMaps3D( const Image* baseImages, size_t depth, DWORD filter, if ( FAILED(hr) ) return hr; - hr = _Generate3DMipsBoxFilter( depth, levels, mipChain ); + hr = _Generate3DMipsBoxFilter( depth, levels, filter, mipChain ); if ( FAILED(hr) ) mipChain.Release(); return hr; @@ -2525,7 +2531,7 @@ HRESULT GenerateMipMaps3D( const Image* srcImages, size_t nimages, const TexMeta if ( FAILED(hr) ) return hr; - hr = _Generate3DMipsBoxFilter( metadata.depth, levels, mipChain ); + hr = _Generate3DMipsBoxFilter( metadata.depth, levels, filter, mipChain ); if ( FAILED(hr) ) mipChain.Release(); return hr; diff --git a/DirectXTex/DirectXTexP.h b/DirectXTex/DirectXTexP.h index e3bc170..6b4c2a6 100644 --- a/DirectXTex/DirectXTexP.h +++ b/DirectXTex/DirectXTexP.h @@ -185,9 +185,17 @@ namespace DirectX bool _LoadScanline( _Out_writes_(count) XMVECTOR* pDestination, _In_ size_t count, _In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _In_ DXGI_FORMAT format ); + _Success_(return != false) + bool _LoadScanlineLinear( _Out_writes_(count) XMVECTOR* pDestination, _In_ size_t count, + _In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _In_ DXGI_FORMAT format, _In_ DWORD flags ); + _Success_(return != false) bool _StoreScanline( LPVOID pDestination, _In_ size_t size, _In_ DXGI_FORMAT format, - _In_reads_(count) const XMVECTOR* pSource, _In_ size_t count ); + _In_reads_(count) const XMVECTOR* pSource, _In_ size_t count); + + _Success_(return != false) + bool _StoreScanlineLinear( LPVOID pDestination, _In_ size_t size, _In_ DXGI_FORMAT format, + _Inout_updates_all_(count) XMVECTOR* pSource, _In_ size_t count, _In_ DWORD flags ); HRESULT _ConvertToR32G32B32A32( _In_ const Image& srcImage, _Inout_ ScratchImage& image );