功能批量实现 优化 服务端 新浮动小游戏框架 新界面UI

This commit is contained in:
2026-04-24 13:20:16 +08:00
parent e0bc0bbf08
commit 5eec879582
257 changed files with 38481 additions and 1288 deletions
@@ -0,0 +1,20 @@
#pragma once
#include <windows.ui.composition.interop.h>
namespace util {
winrt::com_ptr<ABI::Windows::UI::Composition::Desktop::IDesktopWindowTarget>
TryCreateDesktopWindowTarget(
const winrt::com_ptr<ABI::Windows::UI::Composition::ICompositor>&
compositor,
HWND window) {
namespace abi = ABI::Windows::UI::Composition::Desktop;
auto interop = compositor.try_as<abi::ICompositorDesktopInterop>();
winrt::com_ptr<abi::IDesktopWindowTarget> target;
interop->CreateDesktopWindowTarget(window, true, target.put());
return target;
}
} // namespace util
@@ -0,0 +1,80 @@
#include "cpuinfo.h"
#include "detail/cpuinfo_impl.h"
#if defined(_MSC_VER) && (defined(__x86_64__) || defined(_M_X64))
#include "detail/init_msvc_x86.h"
#else
#include "detail/init_unknown.hpp"
#endif
namespace cpuid {
cpuinfo::cpuinfo() : impl_(new impl) { init_cpuinfo(*impl_); }
cpuinfo::~cpuinfo() {}
// x86 member functions
bool cpuinfo::has_fpu() const { return impl_->m_has_fpu; }
bool cpuinfo::has_mmx() const { return impl_->m_has_mmx; }
bool cpuinfo::has_sse() const { return impl_->m_has_sse; }
bool cpuinfo::has_sse2() const { return impl_->m_has_sse2; }
bool cpuinfo::has_sse3() const { return impl_->m_has_sse3; }
bool cpuinfo::has_ssse3() const { return impl_->m_has_ssse3; }
bool cpuinfo::has_sse4_1() const { return impl_->m_has_sse4_1; }
bool cpuinfo::has_sse4_2() const { return impl_->m_has_sse4_2; }
bool cpuinfo::has_pclmulqdq() const { return impl_->m_has_pclmulqdq; }
bool cpuinfo::has_avx() const { return impl_->m_has_avx; }
bool cpuinfo::has_avx2() const { return impl_->m_has_avx2; }
bool cpuinfo::has_avx512_f() const { return impl_->m_has_avx512_f; }
bool cpuinfo::has_avx512_dq() const { return impl_->m_has_avx512_dq; }
bool cpuinfo::has_avx512_ifma() const { return impl_->m_has_avx512_ifma; }
bool cpuinfo::has_avx512_pf() const { return impl_->m_has_avx512_pf; }
bool cpuinfo::has_avx512_er() const { return impl_->m_has_avx512_er; }
bool cpuinfo::has_avx512_cd() const { return impl_->m_has_avx512_cd; }
bool cpuinfo::has_avx512_bw() const { return impl_->m_has_avx512_bw; }
bool cpuinfo::has_avx512_vl() const { return impl_->m_has_avx512_vl; }
bool cpuinfo::has_avx512_vbmi() const { return impl_->m_has_avx512_vbmi; }
bool cpuinfo::has_avx512_vbmi2() const { return impl_->m_has_avx512_vbmi2; }
bool cpuinfo::has_avx512_vnni() const { return impl_->m_has_avx512_vnni; }
bool cpuinfo::has_avx512_bitalg() const { return impl_->m_has_avx512_bitalg; }
bool cpuinfo::has_avx512_vpopcntdq() const {
return impl_->m_has_avx512_vpopcntdq;
}
bool cpuinfo::has_avx512_4vnniw() const { return impl_->m_has_avx512_4vnniw; }
bool cpuinfo::has_avx512_4fmaps() const { return impl_->m_has_avx512_4fmaps; }
bool cpuinfo::has_avx512_vp2intersect() const {
return impl_->m_has_avx512_vp2intersect;
}
bool cpuinfo::has_f16c() const { return impl_->m_has_f16c; }
// ARM member functions
bool cpuinfo::has_neon() const { return impl_->m_has_neon; }
} // namespace cpuid
@@ -0,0 +1,105 @@
#pragma once
#include <memory>
namespace cpuid {
class cpuinfo {
public:
struct impl;
cpuinfo();
~cpuinfo();
// Has X87 FPU
bool has_fpu() const;
// Return true if the CPU supports MMX
bool has_mmx() const;
// Return true if the CPU supports SSE
bool has_sse() const;
// Return true if the CPU supports SSE2
bool has_sse2() const;
// Return true if the CPU supports SSE3
bool has_sse3() const;
// Return true if the CPU supports SSSE3
bool has_ssse3() const;
// Return true if the CPU supports SSE 4.1
bool has_sse4_1() const;
// Return true if the CPU supports SSE 4.2
bool has_sse4_2() const;
// Return true if the CPU supports pclmulqdq
bool has_pclmulqdq() const;
// Return true if the CPU supports AVX
bool has_avx() const;
// Return true if the CPU supports AVX2
bool has_avx2() const;
// Return true if the CPU supports AVX512F
bool has_avx512_f() const;
// Return true if the CPU supports AVX512DQ
bool has_avx512_dq() const;
// Return true if the CPU supports AVX512_IFMA
bool has_avx512_ifma() const;
// Return true if the CPU supports AVX512PF
bool has_avx512_pf() const;
// Return true if the CPU supports AVX512ER
bool has_avx512_er() const;
// Return true if the CPU supports AVX512CD
bool has_avx512_cd() const;
// Return true if the CPU supports AVX512BW
bool has_avx512_bw() const;
// Return true if the CPU supports AVX512VL
bool has_avx512_vl() const;
// Return true if the CPU supports AVX512_VBMI
bool has_avx512_vbmi() const;
// Return true if the CPU supports AVX512_VBMI2
bool has_avx512_vbmi2() const;
// Return true if the CPU supports AVX512_VNNI
bool has_avx512_vnni() const;
// Return true if the CPU supports AVX512_BITALG
bool has_avx512_bitalg() const;
// Return true if the CPU supports AVX512_VPOPCNTDQ
bool has_avx512_vpopcntdq() const;
// Return true if the CPU supports AVX512_4VNNIW
bool has_avx512_4vnniw() const;
// Return true if the CPU supports AVX512_4FMAPS
bool has_avx512_4fmaps() const;
// Return true if the CPU supports AVX512_VP2INTERSECT
bool has_avx512_vp2intersect() const;
// Return true if the CPU supports F16C
bool has_f16c() const;
// Return true if the CPU supports NEON
bool has_neon() const;
private:
// Private implementation
std::unique_ptr<impl> impl_;
};
} // namespace cpuid
@@ -0,0 +1,69 @@
#pragma once
#include "../cpuinfo.h"
namespace cpuid {
struct cpuinfo::impl {
impl()
: m_has_fpu(false),
m_has_mmx(false),
m_has_sse(false),
m_has_sse2(false),
m_has_sse3(false),
m_has_ssse3(false),
m_has_sse4_1(false),
m_has_sse4_2(false),
m_has_pclmulqdq(false),
m_has_avx(false),
m_has_avx2(false),
m_has_avx512_f(false),
m_has_avx512_dq(false),
m_has_avx512_ifma(false),
m_has_avx512_pf(false),
m_has_avx512_er(false),
m_has_avx512_cd(false),
m_has_avx512_bw(false),
m_has_avx512_vl(false),
m_has_avx512_vbmi(false),
m_has_avx512_vbmi2(false),
m_has_avx512_vnni(false),
m_has_avx512_bitalg(false),
m_has_avx512_vpopcntdq(false),
m_has_avx512_4vnniw(false),
m_has_avx512_4fmaps(false),
m_has_avx512_vp2intersect(false),
m_has_f16c(false),
m_has_neon(false) {}
bool m_has_fpu;
bool m_has_mmx;
bool m_has_sse;
bool m_has_sse2;
bool m_has_sse3;
bool m_has_ssse3;
bool m_has_sse4_1;
bool m_has_sse4_2;
bool m_has_pclmulqdq;
bool m_has_avx;
bool m_has_avx2;
bool m_has_avx512_f;
bool m_has_avx512_dq;
bool m_has_avx512_ifma;
bool m_has_avx512_pf;
bool m_has_avx512_er;
bool m_has_avx512_cd;
bool m_has_avx512_bw;
bool m_has_avx512_vl;
bool m_has_avx512_vbmi;
bool m_has_avx512_vbmi2;
bool m_has_avx512_vnni;
bool m_has_avx512_bitalg;
bool m_has_avx512_vpopcntdq;
bool m_has_avx512_4vnniw;
bool m_has_avx512_4fmaps;
bool m_has_avx512_vp2intersect;
bool m_has_f16c;
bool m_has_neon;
};
} // namespace cpuid
@@ -0,0 +1,43 @@
#pragma once
#include <cstdint>
#include "cpuinfo_impl.h"
namespace cpuid {
void extract_x86_flags(cpuinfo::impl& info, uint32_t ecx, uint32_t edx) {
info.m_has_fpu = (edx & (1 << 0)) != 0;
info.m_has_mmx = (edx & (1 << 23)) != 0;
info.m_has_sse = (edx & (1 << 25)) != 0;
info.m_has_sse2 = (edx & (1 << 26)) != 0;
info.m_has_sse3 = (ecx & (1 << 0)) != 0;
info.m_has_ssse3 = (ecx & (1 << 9)) != 0;
info.m_has_sse4_1 = (ecx & (1 << 19)) != 0;
info.m_has_sse4_2 = (ecx & (1 << 20)) != 0;
info.m_has_pclmulqdq = (ecx & (1 << 1)) != 0;
info.m_has_avx = (ecx & (1 << 28)) != 0;
info.m_has_f16c = (ecx & (1 << 29)) != 0;
}
void extract_x86_extended_flags(cpuinfo::impl& info, uint32_t ebx, uint32_t ecx,
uint32_t edx) {
info.m_has_avx2 = (ebx & (1 << 5)) != 0;
info.m_has_avx512_f = (ebx & (1 << 16)) != 0;
info.m_has_avx512_dq = (ebx & (1 << 17)) != 0;
info.m_has_avx512_ifma = (ebx & (1 << 21)) != 0;
info.m_has_avx512_pf = (ebx & (1 << 26)) != 0;
info.m_has_avx512_er = (ebx & (1 << 27)) != 0;
info.m_has_avx512_cd = (ebx & (1 << 28)) != 0;
info.m_has_avx512_bw = (ebx & (1 << 30)) != 0;
info.m_has_avx512_vl = (ebx & (1 << 31)) != 0;
info.m_has_avx512_vbmi = (ecx & (1 << 1)) != 0;
info.m_has_avx512_vbmi2 = (ecx & (1 << 6)) != 0;
info.m_has_avx512_vnni = (ecx & (1 << 11)) != 0;
info.m_has_avx512_bitalg = (ecx & (1 << 12)) != 0;
info.m_has_avx512_vpopcntdq = (ecx & (1 << 14)) != 0;
info.m_has_avx512_4vnniw = (edx & (1 << 2)) != 0;
info.m_has_avx512_4fmaps = (edx & (1 << 3)) != 0;
info.m_has_avx512_vp2intersect = (edx & (1 << 8)) != 0;
}
} // namespace cpuid
@@ -0,0 +1,36 @@
#pragma once
#include <intrin.h>
#include "cpuinfo_impl.h"
#include "extract_x86_flags.h"
namespace cpuid {
void init_cpuinfo(cpuinfo::impl& info) {
int registers[4];
// The register information per input can be extracted from here:
// http://en.wikipedia.org/wiki/CPUID
//
// CPUID should be called with EAX=0 first, as this will return the
// maximum supported EAX input value for future calls
__cpuid(registers, 0);
uint32_t maximum_eax = registers[0];
// Set registers for basic flag extraction, eax=1
// All CPUs should support index=1
if (maximum_eax >= 1U) {
__cpuid(registers, 1);
extract_x86_flags(info, registers[2], registers[3]);
}
// Set registers for extended flags extraction, eax=7 and ecx=0
// This operation is not supported on older CPUs, so it should be skipped
// to avoid incorrect results
if (maximum_eax >= 7U) {
__cpuidex(registers, 7, 0);
extract_x86_extended_flags(info, registers[1], registers[2], registers[3]);
}
}
} // namespace cpuid
@@ -0,0 +1,9 @@
#pragma once
#include "cpuinfo_impl.h"
namespace cpuid {
void init_cpuinfo(cpuinfo::impl& info) { (void)info; }
} // namespace cpuid
@@ -0,0 +1,31 @@
#pragma once
#include <D3d11.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.System.h>
inline auto CreateD3DDevice(D3D_DRIVER_TYPE const type,
winrt::com_ptr<ID3D11Device>& device) {
WINRT_ASSERT(!device);
UINT flags =
D3D11_CREATE_DEVICE_BGRA_SUPPORT | D3D11_CREATE_DEVICE_VIDEO_SUPPORT;
//#ifdef _DEBUG
// flags |= D3D11_CREATE_DEVICE_DEBUG;
//#endif
return D3D11CreateDevice(nullptr, type, nullptr, flags, nullptr, 0,
D3D11_SDK_VERSION, device.put(), nullptr, nullptr);
}
inline auto CreateD3DDevice() {
winrt::com_ptr<ID3D11Device> device;
HRESULT hr = CreateD3DDevice(D3D_DRIVER_TYPE_HARDWARE, device);
if (DXGI_ERROR_UNSUPPORTED == hr) {
CreateD3DDevice(D3D_DRIVER_TYPE_WARP, device);
}
return device;
}
@@ -0,0 +1,43 @@
#include "direct3d11.interop.h"
namespace util {
namespace {
typedef HRESULT(WINAPI* CreateDirect3D11DeviceFromDXGIDeviceFn)(IDXGIDevice*,
LPVOID*);
struct D3DFuncs {
CreateDirect3D11DeviceFromDXGIDeviceFn CreateDirect3D11DeviceFromDXGIDevice =
nullptr;
D3DFuncs() {
auto handle = GetModuleHandle(L"d3d11.dll");
if (!handle) {
return;
}
CreateDirect3D11DeviceFromDXGIDevice =
reinterpret_cast<CreateDirect3D11DeviceFromDXGIDeviceFn>(
GetProcAddress(handle, "CreateDirect3D11DeviceFromDXGIDevice"));
}
static const D3DFuncs& instance() {
static D3DFuncs funcs;
return funcs;
}
};
} // namespace
HRESULT CreateDirect3D11DeviceFromDXGIDevice(IDXGIDevice* dxgiDevice,
IInspectable** graphicsDevice) {
auto ptr = D3DFuncs::instance().CreateDirect3D11DeviceFromDXGIDevice;
if (ptr) {
return ptr(dxgiDevice, reinterpret_cast<LPVOID*>(graphicsDevice));
}
return E_NOTIMPL;
}
} // namespace util
@@ -0,0 +1,49 @@
#pragma once
#include <inspectable.h>
#include <windows.foundation.h>
#include <winrt/windows.graphics.directx.direct3d11.h>
#include "dxgi.h"
namespace Windows {
namespace Graphics {
namespace DirectX {
namespace Direct3D11 {
struct __declspec(uuid("A9B3D012-3DF2-4EE3-B8D1-8695F457D3C1"))
IDirect3DDxgiInterfaceAccess : ::IUnknown {
virtual HRESULT __stdcall GetInterface(GUID const& id, void** object) = 0;
};
} // namespace Direct3D11
} // namespace DirectX
} // namespace Graphics
} // namespace Windows
namespace util {
HRESULT CreateDirect3D11DeviceFromDXGIDevice(IDXGIDevice* dxgiDevice,
IInspectable** graphicsDevice);
template <typename T>
auto GetDXGIInterfaceFromObject(
winrt::Windows::Foundation::IInspectable const& object) {
auto access = object.as<
Windows::Graphics::DirectX::Direct3D11::IDirect3DDxgiInterfaceAccess>();
winrt::com_ptr<T> result;
winrt::check_hresult(
access->GetInterface(winrt::guid_of<T>(), result.put_void()));
return result;
}
template <typename T>
auto TryGetDXGIInterfaceFromObject(const winrt::com_ptr<IInspectable>& object) {
auto access = object.try_as<
Windows::Graphics::DirectX::Direct3D11::IDirect3DDxgiInterfaceAccess>();
winrt::com_ptr<T> result;
access->GetInterface(winrt::guid_of<T>(), result.put_void());
return result;
}
} // namespace util
@@ -0,0 +1,244 @@
// Based on ANGLE's RoHelper (CompositorNativeWindow11.{cpp,h})
// - https://github.com/google/angle/blob/main/src/libANGLE/renderer/d3d/d3d11/converged/CompositorNativeWindow11.h
// - https://github.com/google/angle/blob/main/src/libANGLE/renderer/d3d/d3d11/converged/CompositorNativeWindow11.cpp
// - https://gist.github.com/clarkezone/43e984fb9bdcd2cfcd9a4f41c208a02f
//
// Copyright 2018 The ANGLE Project Authors.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// Neither the name of TransGaming Inc., Google Inc., 3DLabs Inc.
// Ltd., nor the names of their contributors may be used to endorse
// or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include "rohelper.h"
#include <windows.foundation.metadata.h>
#include <wrl.h>
namespace rx {
template <typename T>
bool AssignProcAddress(HMODULE comBaseModule, const char* name, T*& outProc) {
outProc = reinterpret_cast<T*>(GetProcAddress(comBaseModule, name));
return *outProc != nullptr;
}
RoHelper::RoHelper(RO_INIT_TYPE init_type)
: mFpWindowsCreateStringReference(nullptr),
mFpGetActivationFactory(nullptr),
mFpWindowsCompareStringOrdinal(nullptr),
mFpCreateDispatcherQueueController(nullptr),
mFpWindowsDeleteString(nullptr),
mFpRoInitialize(nullptr),
mFpRoUninitialize(nullptr),
mWinRtAvailable(false),
mComBaseModule(nullptr),
mCoreMessagingModule(nullptr) {
#ifdef WINUWP
mFpWindowsCreateStringReference = &::WindowsCreateStringReference;
mFpRoInitialize = &::RoInitialize;
mFpRoUninitialize = &::RoUninitialize;
mFpWindowsDeleteString = &::WindowsDeleteString;
mFpGetActivationFactory = &::RoGetActivationFactory;
mFpWindowsCompareStringOrdinal = &::WindowsCompareStringOrdinal;
mFpCreateDispatcherQueueController = &::CreateDispatcherQueueController;
mWinRtAvailable = true;
#else
mComBaseModule = LoadLibraryA("ComBase.dll");
if (mComBaseModule == nullptr) {
return;
}
if (!AssignProcAddress(mComBaseModule, "WindowsCreateStringReference",
mFpWindowsCreateStringReference)) {
return;
}
if (!AssignProcAddress(mComBaseModule, "RoGetActivationFactory",
mFpGetActivationFactory)) {
return;
}
if (!AssignProcAddress(mComBaseModule, "WindowsCompareStringOrdinal",
mFpWindowsCompareStringOrdinal)) {
return;
}
if (!AssignProcAddress(mComBaseModule, "WindowsDeleteString",
mFpWindowsDeleteString)) {
return;
}
if (!AssignProcAddress(mComBaseModule, "RoInitialize", mFpRoInitialize)) {
return;
}
if (!AssignProcAddress(mComBaseModule, "RoUninitialize", mFpRoUninitialize)) {
return;
}
mCoreMessagingModule = LoadLibraryA("coremessaging.dll");
if (mCoreMessagingModule == nullptr) {
return;
}
if (!AssignProcAddress(mCoreMessagingModule,
"CreateDispatcherQueueController",
mFpCreateDispatcherQueueController)) {
return;
}
auto result = RoInitialize(init_type);
if (SUCCEEDED(result) || result == S_FALSE || result == RPC_E_CHANGED_MODE) {
mWinRtAvailable = true;
}
#endif
}
RoHelper::~RoHelper() {
#ifndef WINUWP
if (mWinRtAvailable) {
RoUninitialize();
}
if (mCoreMessagingModule != nullptr) {
FreeLibrary(mCoreMessagingModule);
mCoreMessagingModule = nullptr;
}
if (mComBaseModule != nullptr) {
FreeLibrary(mComBaseModule);
mComBaseModule = nullptr;
}
#endif
}
bool RoHelper::WinRtAvailable() const { return mWinRtAvailable; }
bool RoHelper::SupportedWindowsRelease() {
if (!mWinRtAvailable) {
return false;
}
HSTRING className, contractName;
HSTRING_HEADER classNameHeader, contractNameHeader;
boolean isSupported = false;
HRESULT hr = GetStringReference(
RuntimeClass_Windows_Foundation_Metadata_ApiInformation, &className,
&classNameHeader);
if (FAILED(hr)) {
return !!isSupported;
}
Microsoft::WRL::ComPtr<
ABI::Windows::Foundation::Metadata::IApiInformationStatics>
api;
hr = GetActivationFactory(
className,
__uuidof(ABI::Windows::Foundation::Metadata::IApiInformationStatics),
&api);
if (FAILED(hr)) {
return !!isSupported;
}
hr = GetStringReference(L"Windows.Foundation.UniversalApiContract",
&contractName, &contractNameHeader);
if (FAILED(hr)) {
return !!isSupported;
}
api->IsApiContractPresentByMajor(contractName, 6, &isSupported);
return !!isSupported;
}
HRESULT RoHelper::GetStringReference(PCWSTR source, HSTRING* act,
HSTRING_HEADER* header) {
if (!mWinRtAvailable) {
return E_FAIL;
}
const wchar_t* str = static_cast<const wchar_t*>(source);
unsigned int length;
HRESULT hr = SizeTToUInt32(::wcslen(str), &length);
if (FAILED(hr)) {
return hr;
}
return mFpWindowsCreateStringReference(source, length, header, act);
}
HRESULT RoHelper::GetActivationFactory(const HSTRING act,
const IID& interfaceId, void** fac) {
if (!mWinRtAvailable) {
return E_FAIL;
}
auto hr = mFpGetActivationFactory(act, interfaceId, fac);
return hr;
}
HRESULT RoHelper::WindowsCompareStringOrdinal(HSTRING one, HSTRING two,
int* result) {
if (!mWinRtAvailable) {
return E_FAIL;
}
return mFpWindowsCompareStringOrdinal(one, two, result);
}
HRESULT RoHelper::CreateDispatcherQueueController(
DispatcherQueueOptions options,
ABI::Windows::System::IDispatcherQueueController**
dispatcherQueueController) {
if (!mWinRtAvailable) {
return E_FAIL;
}
return mFpCreateDispatcherQueueController(options, dispatcherQueueController);
}
HRESULT RoHelper::WindowsDeleteString(HSTRING one) {
if (!mWinRtAvailable) {
return E_FAIL;
}
return mFpWindowsDeleteString(one);
}
HRESULT RoHelper::RoInitialize(RO_INIT_TYPE type) {
return mFpRoInitialize(type);
}
void RoHelper::RoUninitialize() { mFpRoUninitialize(); }
} // namespace rx
@@ -0,0 +1,97 @@
// Based on ANGLE's RoHelper (CompositorNativeWindow11.{cpp,h})
// - https://github.com/google/angle/blob/main/src/libANGLE/renderer/d3d/d3d11/converged/CompositorNativeWindow11.h
// - https://github.com/google/angle/blob/main/src/libANGLE/renderer/d3d/d3d11/converged/CompositorNativeWindow11.cpp
// - https://gist.github.com/clarkezone/43e984fb9bdcd2cfcd9a4f41c208a02f
//
// Copyright 2018 The ANGLE Project Authors.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// Neither the name of TransGaming Inc., Google Inc., 3DLabs Inc.
// Ltd., nor the names of their contributors may be used to endorse
// or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#pragma once
#include <dispatcherqueue.h>
#include <roapi.h>
#include <windows.ui.composition.interop.h>
namespace rx {
class RoHelper {
public:
RoHelper(RO_INIT_TYPE init_type);
~RoHelper();
bool WinRtAvailable() const;
bool SupportedWindowsRelease();
HRESULT GetStringReference(PCWSTR source, HSTRING* act,
HSTRING_HEADER* header);
HRESULT GetActivationFactory(const HSTRING act, const IID& interfaceId,
void** fac);
HRESULT WindowsCompareStringOrdinal(HSTRING one, HSTRING two, int* result);
HRESULT CreateDispatcherQueueController(
DispatcherQueueOptions options,
ABI::Windows::System::IDispatcherQueueController**
dispatcherQueueController);
HRESULT WindowsDeleteString(HSTRING one);
HRESULT RoInitialize(RO_INIT_TYPE type);
void RoUninitialize();
private:
using WindowsCreateStringReference_ = HRESULT __stdcall(PCWSTR, UINT32,
HSTRING_HEADER*,
HSTRING*);
using GetActivationFactory_ = HRESULT __stdcall(HSTRING, REFIID, void**);
using WindowsCompareStringOrginal_ = HRESULT __stdcall(HSTRING, HSTRING,
int*);
using WindowsDeleteString_ = HRESULT __stdcall(HSTRING);
using CreateDispatcherQueueController_ =
HRESULT __stdcall(DispatcherQueueOptions,
ABI::Windows::System::IDispatcherQueueController**);
using RoInitialize_ = HRESULT __stdcall(RO_INIT_TYPE);
using RoUninitialize_ = void __stdcall();
WindowsCreateStringReference_* mFpWindowsCreateStringReference;
GetActivationFactory_* mFpGetActivationFactory;
WindowsCompareStringOrginal_* mFpWindowsCompareStringOrdinal;
CreateDispatcherQueueController_* mFpCreateDispatcherQueueController;
WindowsDeleteString_* mFpWindowsDeleteString;
RoInitialize_* mFpRoInitialize;
RoUninitialize_* mFpRoUninitialize;
bool mWinRtAvailable;
HMODULE mComBaseModule;
HMODULE mCoreMessagingModule;
};
} // namespace rx
@@ -0,0 +1,54 @@
#include "string_converter.h"
#include <windows.h>
namespace util {
std::string Utf8FromUtf16(std::wstring_view utf16_string) {
if (utf16_string.empty()) {
return std::string();
}
auto src_length = static_cast<int>(utf16_string.size());
int target_length =
::WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string.data(),
src_length, nullptr, 0, nullptr, nullptr);
std::string utf8_string;
if (target_length <= 0 || target_length > utf8_string.max_size()) {
return utf8_string;
}
utf8_string.resize(target_length);
int converted_length = ::WideCharToMultiByte(
CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string.data(), src_length,
utf8_string.data(), target_length, nullptr, nullptr);
if (converted_length == 0) {
return std::string();
}
return utf8_string;
}
std::wstring Utf16FromUtf8(std::string_view utf8_string) {
if (utf8_string.empty()) {
return std::wstring();
}
auto src_length = static_cast<int>(utf8_string.size());
int target_length =
::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8_string.data(),
src_length, nullptr, 0);
std::wstring utf16_string;
if (target_length <= 0 || target_length > utf16_string.max_size()) {
return utf16_string;
}
utf16_string.resize(target_length);
int converted_length =
::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8_string.data(),
src_length, utf16_string.data(), target_length);
if (converted_length == 0) {
return std::wstring();
}
return utf16_string;
}
} // namespace util
@@ -0,0 +1,8 @@
#pragma once
#include <string>
namespace util {
std::string Utf8FromUtf16(std::wstring_view utf16_string);
std::wstring Utf16FromUtf8(std::string_view utf8_string);
} // namespace util
@@ -0,0 +1,192 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/*
* see skia/src/opts/SkSwizzler_opts.h
*/
#pragma once
#include "cpuid/cpuinfo.h"
/**
* SK_CPU_SSE_LEVEL
*
* If defined, SK_CPU_SSE_LEVEL should be set to the highest supported level.
* On non-intel CPU this should be undefined.
*/
#define SK_CPU_SSE_LEVEL_SSE1 10
#define SK_CPU_SSE_LEVEL_SSE2 20
#define SK_CPU_SSE_LEVEL_SSE3 30
#define SK_CPU_SSE_LEVEL_SSSE3 31
#define SK_CPU_SSE_LEVEL_SSE41 41
#define SK_CPU_SSE_LEVEL_SSE42 42
#define SK_CPU_SSE_LEVEL_AVX 51
#define SK_CPU_SSE_LEVEL_AVX2 52
#define SK_CPU_SSE_LEVEL_SKX 60
// Are we in GCC/Clang?
#ifndef SK_CPU_SSE_LEVEL
// These checks must be done in descending order to ensure we set the highest
// available SSE level.
#if defined(__AVX512F__) && defined(__AVX512DQ__) && defined(__AVX512CD__) && \
defined(__AVX512BW__) && defined(__AVX512VL__)
#define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SKX
#elif defined(__AVX2__)
#define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_AVX2
#elif defined(__AVX__)
#define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_AVX
#elif defined(__SSE4_2__)
#define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSE42
#elif defined(__SSE4_1__)
#define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSE41
#elif defined(__SSSE3__)
#define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSSE3
#elif defined(__SSE3__)
#define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSE3
#elif defined(__SSE2__)
#define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSE2
#endif
#endif
// Are we in VisualStudio?
#ifndef SK_CPU_SSE_LEVEL
// These checks must be done in descending order to ensure we set the highest
// available SSE level. 64-bit intel guarantees at least SSE2 support.
#if defined(__AVX512F__) && defined(__AVX512DQ__) && defined(__AVX512CD__) && \
defined(__AVX512BW__) && defined(__AVX512VL__)
#define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SKX
#elif defined(__AVX2__)
#define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_AVX2
#elif defined(__AVX__)
#define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_AVX
#elif defined(_M_X64) || defined(_M_AMD64)
#define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSE2
#elif defined(_M_IX86_FP)
#if _M_IX86_FP >= 2
#define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSE2
#elif _M_IX86_FP == 1
#define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSE1
#endif
#endif
#endif
inline void RGBA_to_BGRA_portable(uint32_t* dst, const uint32_t* src,
int height, int src_stride, int dst_stride) {
auto width = std::min<int>(src_stride, dst_stride);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
uint8_t a = (src[x] >> 24) & 0xFF, b = (src[x] >> 16) & 0xFF,
g = (src[x] >> 8) & 0xFF, r = (src[x] >> 0) & 0xFF;
dst[x] = (uint32_t)a << 24 | (uint32_t)r << 16 | (uint32_t)g << 8 |
(uint32_t)b << 0;
}
src += src_stride;
dst += dst_stride;
}
}
#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SKX
inline void RGBA_to_BGRA_SKX(uint32_t* dst, const uint32_t* src, int height,
int src_stride, int dst_stride) {
const uint8_t mask[64] = {2, 1, 0, 3, 6, 5, 4, 7, 10, 9, 8, 11, 14,
13, 12, 15, 2, 1, 0, 3, 6, 5, 4, 7, 10, 9,
8, 11, 14, 13, 12, 15, 2, 1, 0, 3, 6, 5, 4,
7, 10, 9, 8, 11, 14, 13, 12, 15, 2, 1, 0, 3,
6, 5, 4, 7, 10, 9, 8, 11, 14, 13, 12, 15};
const __m512i swapRB = _mm512_loadu_si512(mask);
auto width = std::min<int>(src_stride, dst_stride);
for (int y = 0; y < height; y++) {
auto cw = width;
auto rptr = src;
auto dptr = dst;
while (cw >= 16) {
__m512i rgba = _mm512_loadu_si512((const __m512i*)rptr);
__m512i bgra = _mm512_shuffle_epi8(rgba, swapRB);
_mm512_storeu_si512((__m512i*)dptr, bgra);
rptr += 16;
dptr += 16;
cw -= 16;
}
for (auto x = 0; x < cw; x++) {
uint8_t a = (rptr[x] >> 24) & 0xFF, b = (rptr[x] >> 16) & 0xFF,
g = (rptr[x] >> 8) & 0xFF, r = (rptr[x] >> 0) & 0xFF;
dptr[x] = (uint32_t)a << 24 | (uint32_t)r << 16 | (uint32_t)g << 8 |
(uint32_t)b << 0;
}
src += src_stride;
dst += dst_stride;
}
}
#endif
#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_AVX2
inline void RGBA_to_BGRA_AVX2(uint32_t* dst, const uint32_t* src, int height,
int src_stride, int dst_stride) {
const __m256i swapRB =
_mm256_setr_epi8(2, 1, 0, 3, 6, 5, 4, 7, 10, 9, 8, 11, 14, 13, 12, 15, 2,
1, 0, 3, 6, 5, 4, 7, 10, 9, 8, 11, 14, 13, 12, 15);
auto width = std::min<int>(src_stride, dst_stride);
for (int y = 0; y < height; y++) {
auto cw = width;
auto rptr = src;
auto dptr = dst;
while (cw >= 8) {
__m256i rgba = _mm256_loadu_si256((const __m256i*)rptr);
__m256i bgra = _mm256_shuffle_epi8(rgba, swapRB);
_mm256_storeu_si256((__m256i*)dptr, bgra);
rptr += 8;
dptr += 8;
cw -= 8;
}
for (auto x = 0; x < cw; x++) {
uint8_t a = (rptr[x] >> 24) & 0xFF, b = (rptr[x] >> 16) & 0xFF,
g = (rptr[x] >> 8) & 0xFF, r = (rptr[x] >> 0) & 0xFF;
dptr[x] = (uint32_t)a << 24 | (uint32_t)r << 16 | (uint32_t)g << 8 |
(uint32_t)b << 0;
}
src += src_stride;
dst += dst_stride;
}
}
#endif
inline void RGBA_to_BGRA(uint32_t* dst, const uint32_t* src, int height,
int src_stride, int dst_stride) {
static cpuid::cpuinfo info;
#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SKX
if (info.has_avx512_f() && info.has_avx512_dq() && info.has_avx512_cd() &&
info.has_avx512_bw() && info.has_avx512_vl()) {
return RGBA_to_BGRA_SKX(dst, src, height, src_stride, dst_stride);
}
#endif
#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_AVX2
if (info.has_avx2()) {
return RGBA_to_BGRA_AVX2(dst, src, height, src_stride, dst_stride);
}
#endif
RGBA_to_BGRA_portable(dst, src, height, src_stride, dst_stride);
}