11#include " pch.h"
22#include " CursorDrawer2.h"
33#include " ByteBuffer.h"
4+ #include " ColorHelper.h"
45#include " CursorHelper.h"
56#include " DynamicDescriptorHeap.h"
67#include " GraphicsContext.h"
910#include " shaders/CursorVS.h"
1011#include " shaders/SimplePS.h"
1112#include " Win32Helper.h"
13+ #include < DirectXPackedVector.h>
1214#include < ShellScalingApi.h>
1315#include < wil/registry.h>
1416
@@ -265,6 +267,12 @@ HRESULT CursorDrawer2::Draw(D3D12_GPU_DESCRIPTOR_HANDLE heapGpuHandle) noexcept
265267 return S_OK;
266268}
267269
270+ HRESULT CursorDrawer2::OnColorInfoChanged (const ColorInfo& colorInfo) noexcept {
271+ _colorInfo = colorInfo;
272+ _colorPSO = nullptr ;
273+ return S_OK;
274+ }
275+
268276static Size CalcCursorSize (
269277 Size cursorBmpSize,
270278 uint32_t cursorDpi,
@@ -499,7 +507,7 @@ wil::unique_hcursor CursorDrawer2::_TryResolveStandardCursor(
499507 Logger::Get ().ComError (" wil::ExpandEnvironmentStringsW 失败" , hr);
500508 return result;
501509 }
502-
510+
503511 result = CursorHelper::ExtractCursorFromCurFile (curPath.c_str (), preferedWidth);
504512 if (!result) {
505513 Logger::Get ().Error (" CursorHelper::ExtractCursorFromCurFile 失败" );
@@ -513,7 +521,7 @@ bool CursorDrawer2::_ResolveCursorPixels(
513521 _CursorInfo& cursorInfo,
514522 HBITMAP hColorBmp,
515523 HBITMAP hMaskBmp
516- ) noexcept {
524+ ) const noexcept {
517525 const Size bmpSize = {
518526 cursorInfo.originSize .width ,
519527 hColorBmp ? cursorInfo.originSize .height : cursorInfo.originSize .height * 2
@@ -532,17 +540,15 @@ bool CursorDrawer2::_ResolveCursorPixels(
532540 }
533541 };
534542
535- ByteBuffer& pixels = cursorInfo.originPixels ;
536- pixels.Resize (bi.bmiHeader .biSizeImage );
537-
543+ ByteBuffer pixels (bi.bmiHeader .biSizeImage );
538544 wil::unique_hdc_window hdcScreen (wil::window_dc (GetDC (NULL )));
539545 if (GetDIBits (hdcScreen.get (), hColorBmp ? hColorBmp : hMaskBmp, 0 , bmpSize.height ,
540546 pixels.Data (), &bi, DIB_RGB_COLORS) != (int )bmpSize.height
541547 ) {
542548 Logger::Get ().Win32Error (" GetDIBits 失败" );
543549 return false ;
544550 }
545-
551+
546552 if (hColorBmp) {
547553 // 彩色掩码光标和彩色光标的区别在于前者的透明通道全为 0
548554 bool hasAlpha = false ;
@@ -556,16 +562,32 @@ bool CursorDrawer2::_ResolveCursorPixels(
556562 if (hasAlpha) {
557563 // 彩色光标
558564 cursorInfo.type = _CursorType::Color;
565+ cursorInfo.originTextureData .Resize (bi.bmiHeader .biSizeImage * 2 );
566+
567+ using namespace DirectX ::PackedVector;
568+
569+ HALF* textureData = (HALF*)cursorInfo.originTextureData .Data ();
559570
560571 for (uint32_t i = 0 ; i < bi.bmiHeader .biSizeImage ; i += 4 ) {
561572 // 预乘 Alpha 通道
562- double alpha = pixels[i + 3 ] / 255 .0f ;
573+ float alpha = pixels[i + 3 ] / 255 .0f ;
574+ float factor = alpha / 255 .0f ;
575+
576+ textureData[i + 3 ] = XMConvertFloatToHalf (1 .0f - alpha);
577+
578+ if (_colorInfo.kind == winrt::AdvancedColorKind::StandardDynamicRange) {
579+ textureData[i] = XMConvertFloatToHalf (pixels[i + 2 ] * factor);
580+ textureData[i + 1 ] = XMConvertFloatToHalf (pixels[i + 1 ] * factor);
581+ textureData[i + 2 ] = XMConvertFloatToHalf (pixels[i] * factor);
582+ } else {
583+ if (_colorInfo.kind == winrt::AdvancedColorKind::HighDynamicRange) {
584+ factor *= _colorInfo.sdrWhiteLevel ;
585+ }
563586
564- uint8_t b = (uint8_t )std::lround (pixels[i] * alpha);
565- pixels[i] = (uint8_t )std::lround (pixels[i + 2 ] * alpha);
566- pixels[i + 1 ] = (uint8_t )std::lround (pixels[i + 1 ] * alpha);
567- pixels[i + 2 ] = b;
568- pixels[i + 3 ] = 255 - pixels[i + 3 ];
587+ textureData[i] = XMConvertFloatToHalf (ColorHelper::SrgbToLinear (pixels[i + 2 ]) * factor);
588+ textureData[i + 1 ] = XMConvertFloatToHalf (ColorHelper::SrgbToLinear (pixels[i + 1 ]) * factor);
589+ textureData[i + 2 ] = XMConvertFloatToHalf (ColorHelper::SrgbToLinear (pixels[i]) * factor);
590+ }
569591 }
570592 } else {
571593 // 彩色掩码光标。如果不需要应用 XOR 则转换成彩色光标
@@ -593,6 +615,7 @@ bool CursorDrawer2::_ResolveCursorPixels(
593615 if (canConvertToColor) {
594616 // 转换为彩色光标以获得更好的插值效果和渲染性能
595617 cursorInfo.type = _CursorType::Color;
618+ cursorInfo.originTextureData .Resize (bi.bmiHeader .biSizeImage * 2 );
596619
597620 for (uint32_t i = 0 ; i < bi.bmiHeader .biSizeImage ; i += 4 ) {
598621 if (maskPixels[i] == 0 ) {
@@ -612,6 +635,8 @@ bool CursorDrawer2::_ResolveCursorPixels(
612635 std::swap (pixels[i], pixels[i + 2 ]);
613636 pixels[i + 3 ] = maskPixels[i];
614637 }
638+
639+ cursorInfo.originTextureData = std::move (pixels);
615640 }
616641 }
617642 } else {
@@ -631,6 +656,7 @@ bool CursorDrawer2::_ResolveCursorPixels(
631656 if (canConvertToColor) {
632657 // 转换为彩色光标以获得更好的插值效果和渲染性能
633658 cursorInfo.type = _CursorType::Color;
659+ cursorInfo.originTextureData .Resize (bi.bmiHeader .biSizeImage * 2 );
634660
635661 for (uint32_t i = 0 ; i < halfSize; i += 4 ) {
636662 // 上半部分是 AND 掩码,下半部分是 XOR 掩码
@@ -664,6 +690,8 @@ bool CursorDrawer2::_ResolveCursorPixels(
664690 upperPtr += 4 ;
665691 lowerPtr += 4 ;
666692 }
693+
694+ cursorInfo.originTextureData = std::move (pixels);
667695 }
668696 }
669697
@@ -678,7 +706,7 @@ HRESULT CursorDrawer2::_InitializeCursorTexture(_CursorInfo& cursorInfo) noexcep
678706 CD3DX12_HEAP_PROPERTIES heapProperties (D3D12_HEAP_TYPE_UPLOAD);
679707
680708 CD3DX12_RESOURCE_DESC texDesc = CD3DX12_RESOURCE_DESC::Tex2D (
681- cursorInfo.type == _CursorType::Monochrome ? DXGI_FORMAT_R8_UNORM : DXGI_FORMAT_R8G8B8A8_UNORM ,
709+ cursorInfo.type == _CursorType::Monochrome ? DXGI_FORMAT_R8_UNORM : DXGI_FORMAT_R16G16B16A16_FLOAT ,
682710 cursorInfo.originSize .width , cursorInfo.originSize .height , 1 , 1 );
683711
684712 D3D12_PLACED_SUBRESOURCE_FOOTPRINT textureLayout;
@@ -688,7 +716,7 @@ HRESULT CursorDrawer2::_InitializeCursorTexture(_CursorInfo& cursorInfo) noexcep
688716 &textureLayout, nullptr , &textureRowSizeInBytes, &textureSize);
689717
690718 assert (textureRowSizeInBytes == cursorInfo.originSize .width *
691- (cursorInfo.type == _CursorType::Monochrome ? 1 : 4 ));
719+ (cursorInfo.type == _CursorType::Monochrome ? 1 : 8 ));
692720
693721 CD3DX12_RESOURCE_DESC bufferDesc = CD3DX12_RESOURCE_DESC::Buffer (textureSize);
694722
@@ -728,20 +756,20 @@ HRESULT CursorDrawer2::_InitializeCursorTexture(_CursorInfo& cursorInfo) noexcep
728756 }
729757
730758 if (textureRowSizeInBytes == textureLayout.Footprint .RowPitch ) {
731- std::memcpy (pData, cursorInfo.originPixels .Data (), textureRowSizeInBytes * cursorInfo.originSize .height );
759+ std::memcpy (pData, cursorInfo.originTextureData .Data (), textureRowSizeInBytes * cursorInfo.originSize .height );
732760 } else {
733761 for (uint32_t i = 0 ; i < cursorInfo.originSize .height ; ++i) {
734762 std::memcpy (
735763 (uint8_t *)pData + textureLayout.Footprint .RowPitch * i,
736- &cursorInfo.originPixels [(uint32_t )textureRowSizeInBytes * i],
764+ &cursorInfo.originTextureData [(uint32_t )textureRowSizeInBytes * i],
737765 textureRowSizeInBytes
738766 );
739767 }
740768 }
741769
742770 cursorInfo.originUploadBuffer ->Unmap (0 , nullptr );
743771
744- cursorInfo.originPixels .Clear ();
772+ cursorInfo.originTextureData .Clear ();
745773
746774 ID3D12GraphicsCommandList* commandList = _graphicsContext->GetCommandList ();
747775
@@ -833,7 +861,7 @@ HRESULT CursorDrawer2::_CreateColorPSO() noexcept {
833861 .PS = CD3DX12_SHADER_BYTECODE (SimplePS, sizeof (SimplePS)),
834862 .BlendState = {
835863 .RenderTarget = {{
836- // FinalColor = ScreenColor * CursorColor.a + CursorColor.rgb
864+ // FinalColor = CursorColor.rgb + ScreenColor * CursorColor.a
837865 .BlendEnable = TRUE ,
838866 .SrcBlend = D3D12_BLEND_ONE,
839867 .DestBlend = D3D12_BLEND_SRC_ALPHA,
@@ -852,8 +880,8 @@ HRESULT CursorDrawer2::_CreateColorPSO() noexcept {
852880 .PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE,
853881 .NumRenderTargets = 1 ,
854882 .RTVFormats = { _colorInfo.kind == winrt::AdvancedColorKind::StandardDynamicRange ?
855- DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R16G16B16A16_FLOAT },
856- .SampleDesc = {.Count = 1 }
883+ DXGI_FORMAT_R8G8B8A8_UNORM : DXGI_FORMAT_R16G16B16A16_FLOAT },
884+ .SampleDesc = { .Count = 1 }
857885 };
858886 HRESULT hr = _graphicsContext->GetDevice ()->CreateGraphicsPipelineState (
859887 &psoDesc, IID_PPV_ARGS (&_colorPSO));
0 commit comments