暂时精简了仓库,后边再放吧
This commit is contained in:
-20
@@ -1,20 +0,0 @@
|
||||
#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
|
||||
@@ -1,80 +0,0 @@
|
||||
#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
|
||||
@@ -1,105 +0,0 @@
|
||||
#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
|
||||
@@ -1,69 +0,0 @@
|
||||
#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
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
#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
|
||||
-36
@@ -1,36 +0,0 @@
|
||||
#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
|
||||
@@ -1,9 +0,0 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cpuinfo_impl.h"
|
||||
|
||||
namespace cpuid {
|
||||
|
||||
void init_cpuinfo(cpuinfo::impl& info) { (void)info; }
|
||||
} // namespace cpuid
|
||||
@@ -1,31 +0,0 @@
|
||||
#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;
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
#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
|
||||
@@ -1,49 +0,0 @@
|
||||
|
||||
#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
|
||||
@@ -1,244 +0,0 @@
|
||||
// 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
|
||||
@@ -1,97 +0,0 @@
|
||||
// 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
|
||||
@@ -1,54 +0,0 @@
|
||||
#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
|
||||
@@ -1,8 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace util {
|
||||
std::string Utf8FromUtf16(std::wstring_view utf16_string);
|
||||
std::wstring Utf16FromUtf8(std::string_view utf8_string);
|
||||
} // namespace util
|
||||
@@ -1,192 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
Reference in New Issue
Block a user