diff --git a/DirectXTex/DirectXTex.h b/DirectXTex/DirectXTex.h index 6d94332..e4e71ff 100644 --- a/DirectXTex/DirectXTex.h +++ b/DirectXTex/DirectXTex.h @@ -575,8 +575,9 @@ namespace DirectX TEX_FILTER_RGB_COPY_RED = 0x1000, TEX_FILTER_RGB_COPY_GREEN = 0x2000, TEX_FILTER_RGB_COPY_BLUE = 0x4000, - // When converting RGB to R, defaults to using grayscale. These flags indicate copying a specific channel instead - // When converting RGB to RG, defaults to copying RED | GREEN. These flags control which channels are selected instead. + TEX_FILTER_RGB_COPY_ALPHA = 0x8000, + // When converting RGB(A) to R, defaults to using grayscale. These flags indicate copying a specific channel instead + // When converting RGB(A) to RG, defaults to copying RED | GREEN. These flags control which channels are selected instead. TEX_FILTER_DITHER = 0x10000, // Use ordered 4x4 dithering for any required conversions diff --git a/DirectXTex/DirectXTexConvert.cpp b/DirectXTex/DirectXTexConvert.cpp index 2c6b28d..c534a4c 100644 --- a/DirectXTex/DirectXTexConvert.cpp +++ b/DirectXTex/DirectXTexConvert.cpp @@ -3280,8 +3280,8 @@ void DirectX::Internal::ConvertScanline( { // !CONVF_DEPTH -> CONVF_DEPTH - // RGB -> Depth (red channel) - switch (flags & (TEX_FILTER_RGB_COPY_RED | TEX_FILTER_RGB_COPY_GREEN | TEX_FILTER_RGB_COPY_BLUE)) + // RGB -> Depth (red channel or other specified channel) + switch (flags & (TEX_FILTER_RGB_COPY_RED | TEX_FILTER_RGB_COPY_GREEN | TEX_FILTER_RGB_COPY_BLUE | TEX_FILTER_RGB_COPY_ALPHA)) { case TEX_FILTER_RGB_COPY_GREEN: { @@ -3307,6 +3307,18 @@ void DirectX::Internal::ConvertScanline( } break; + case TEX_FILTER_RGB_COPY_ALPHA: + { + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + const XMVECTOR v = *ptr; + const XMVECTOR v1 = XMVectorSplatW(v); + *ptr++ = XMVectorSelect(v, v1, g_XMSelect1000); + } + } + break; + default: if ((in->flags & CONVF_UNORM) && ((in->flags & CONVF_RGB_MASK) == (CONVF_R | CONVF_G | CONVF_B))) { @@ -3574,6 +3586,7 @@ void DirectX::Internal::ConvertScanline( if (((out->flags & CONVF_RGBA_MASK) == CONVF_A) && !(in->flags & CONVF_A)) { // !CONVF_A -> A format + // We ignore TEX_FILTER_RGB_COPY_ALPHA since there's no input alpha channel. switch (flags & (TEX_FILTER_RGB_COPY_RED | TEX_FILTER_RGB_COPY_GREEN | TEX_FILTER_RGB_COPY_BLUE)) { case TEX_FILTER_RGB_COPY_GREEN: @@ -3669,8 +3682,8 @@ void DirectX::Internal::ConvertScanline( { if ((out->flags & CONVF_RGB_MASK) == CONVF_R) { - // RGB format -> R format - switch (flags & (TEX_FILTER_RGB_COPY_RED | TEX_FILTER_RGB_COPY_GREEN | TEX_FILTER_RGB_COPY_BLUE)) + // RGB(A) format -> R format + switch (flags & (TEX_FILTER_RGB_COPY_RED | TEX_FILTER_RGB_COPY_GREEN | TEX_FILTER_RGB_COPY_BLUE | TEX_FILTER_RGB_COPY_ALPHA)) { case TEX_FILTER_RGB_COPY_GREEN: { @@ -3696,6 +3709,18 @@ void DirectX::Internal::ConvertScanline( } break; + case TEX_FILTER_RGB_COPY_ALPHA: + { + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + const XMVECTOR v = *ptr; + const XMVECTOR v1 = XMVectorSplatW(v); + *ptr++ = XMVectorSelect(v, v1, g_XMSelect1110); + } + } + break; + default: if (in->flags & CONVF_UNORM) { @@ -3724,37 +3749,83 @@ void DirectX::Internal::ConvertScanline( } else if ((out->flags & CONVF_RGB_MASK) == (CONVF_R | CONVF_G)) { - // RGB format -> RG format - switch (static_cast(flags & (TEX_FILTER_RGB_COPY_RED | TEX_FILTER_RGB_COPY_GREEN | TEX_FILTER_RGB_COPY_BLUE))) + if ((flags & TEX_FILTER_RGB_COPY_ALPHA) && (in->flags & CONVF_A)) { - case (static_cast(TEX_FILTER_RGB_COPY_RED) | static_cast(TEX_FILTER_RGB_COPY_BLUE)): + // RGBA -> RG format + switch (static_cast(flags & (TEX_FILTER_RGB_COPY_RED | TEX_FILTER_RGB_COPY_GREEN | TEX_FILTER_RGB_COPY_BLUE | TEX_FILTER_RGB_COPY_ALPHA))) { - XMVECTOR* ptr = pBuffer; - for (size_t i = 0; i < count; ++i) + case (static_cast(TEX_FILTER_RGB_COPY_RED) | static_cast(TEX_FILTER_RGB_COPY_ALPHA)): + default: { - const XMVECTOR v = *ptr; - const XMVECTOR v1 = XMVectorSwizzle<0, 2, 0, 2>(v); - *ptr++ = XMVectorSelect(v, v1, g_XMSelect1100); + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + const XMVECTOR v = *ptr; + const XMVECTOR v1 = XMVectorSwizzle<0, 3, 0, 3>(v); + *ptr++ = XMVectorSelect(v, v1, g_XMSelect1100); + } } - } - break; + break; - case (static_cast(TEX_FILTER_RGB_COPY_GREEN) | static_cast(TEX_FILTER_RGB_COPY_BLUE)): + case (static_cast(TEX_FILTER_RGB_COPY_GREEN) | static_cast(TEX_FILTER_RGB_COPY_ALPHA)): + { + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + const XMVECTOR v = *ptr; + const XMVECTOR v1 = XMVectorSwizzle<1, 3, 1, 3>(v); + *ptr++ = XMVectorSelect(v, v1, g_XMSelect1100); + } + } + break; + + case (static_cast(TEX_FILTER_RGB_COPY_BLUE) | static_cast(TEX_FILTER_RGB_COPY_ALPHA)): + { + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + const XMVECTOR v = *ptr; + const XMVECTOR v1 = XMVectorSwizzle<2, 3, 2, 3>(v); + *ptr++ = XMVectorSelect(v, v1, g_XMSelect1100); + } + } + break; + } + } + else + { + // RGB format -> RG format + switch (static_cast(flags & (TEX_FILTER_RGB_COPY_RED | TEX_FILTER_RGB_COPY_GREEN | TEX_FILTER_RGB_COPY_BLUE))) { - XMVECTOR* ptr = pBuffer; - for (size_t i = 0; i < count; ++i) + case (static_cast(TEX_FILTER_RGB_COPY_RED) | static_cast(TEX_FILTER_RGB_COPY_BLUE)): { - const XMVECTOR v = *ptr; - const XMVECTOR v1 = XMVectorSwizzle<1, 2, 3, 0>(v); - *ptr++ = XMVectorSelect(v, v1, g_XMSelect1100); + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + const XMVECTOR v = *ptr; + const XMVECTOR v1 = XMVectorSwizzle<0, 2, 0, 2>(v); + *ptr++ = XMVectorSelect(v, v1, g_XMSelect1100); + } } - } - break; + break; - case (static_cast(TEX_FILTER_RGB_COPY_RED) | static_cast(TEX_FILTER_RGB_COPY_GREEN)): - default: - // Leave data unchanged and the store will handle this... - break; + case (static_cast(TEX_FILTER_RGB_COPY_GREEN) | static_cast(TEX_FILTER_RGB_COPY_BLUE)): + { + XMVECTOR* ptr = pBuffer; + for (size_t i = 0; i < count; ++i) + { + const XMVECTOR v = *ptr; + const XMVECTOR v1 = XMVectorSwizzle<1, 2, 3, 0>(v); + *ptr++ = XMVectorSelect(v, v1, g_XMSelect1100); + } + } + break; + + case (static_cast(TEX_FILTER_RGB_COPY_RED) | static_cast(TEX_FILTER_RGB_COPY_GREEN)): + default: + // Leave data unchanged and the store will handle this... + break; + } } } }