Wrap multiplanar iosurface in wgpuTexture
This CL supports wrapping multiplanar iosurface in wgpuTexture. It also provides mechanism to create TextureView on each planes. Bug:1307194 Change-Id: I5e82f47944fdea542abba097240c880628b1181f Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/81482 Reviewed-by: Corentin Wallez <cwallez@chromium.org> Commit-Queue: Shaobo Yan <shaobo.yan@intel.com>
This commit is contained in:
parent
6cacdc460a
commit
0a6c2b0f99
|
@ -43,6 +43,8 @@ namespace dawn::native::metal {
|
||||||
ExternalImageDescriptorIOSurface();
|
ExternalImageDescriptorIOSurface();
|
||||||
|
|
||||||
IOSurfaceRef ioSurface;
|
IOSurfaceRef ioSurface;
|
||||||
|
|
||||||
|
// This has been deprecated.
|
||||||
uint32_t plane;
|
uint32_t plane;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -358,6 +358,12 @@ namespace dawn::native::metal {
|
||||||
mSupportedFeatures.EnableFeature(Feature::Depth32FloatStencil8);
|
mSupportedFeatures.EnableFeature(Feature::Depth32FloatStencil8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Uses newTextureWithDescriptor::iosurface::plane which is available
|
||||||
|
// on ios 11.0+ and macOS 11.0+
|
||||||
|
if (@available(macOS 10.11, iOS 11.0, *)) {
|
||||||
|
mSupportedFeatures.EnableFeature(Feature::MultiPlanarFormats);
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(DAWN_PLATFORM_MACOS)
|
#if defined(DAWN_PLATFORM_MACOS)
|
||||||
// MTLPixelFormatDepth24Unorm_Stencil8 is only available on macOS 10.11+
|
// MTLPixelFormatDepth24Unorm_Stencil8 is only available on macOS 10.11+
|
||||||
if ([*mDevice isDepth24Stencil8PixelFormatSupported]) {
|
if ([*mDevice isDepth24Stencil8PixelFormatSupported]) {
|
||||||
|
|
|
@ -54,8 +54,7 @@ namespace dawn::native::metal {
|
||||||
MaybeError SubmitPendingCommandBuffer();
|
MaybeError SubmitPendingCommandBuffer();
|
||||||
|
|
||||||
Ref<Texture> CreateTextureWrappingIOSurface(const ExternalImageDescriptor* descriptor,
|
Ref<Texture> CreateTextureWrappingIOSurface(const ExternalImageDescriptor* descriptor,
|
||||||
IOSurfaceRef ioSurface,
|
IOSurfaceRef ioSurface);
|
||||||
uint32_t plane);
|
|
||||||
void WaitForCommandsToBeScheduled();
|
void WaitForCommandsToBeScheduled();
|
||||||
|
|
||||||
ResultOrError<std::unique_ptr<StagingBufferBase>> CreateStagingBuffer(size_t size) override;
|
ResultOrError<std::unique_ptr<StagingBufferBase>> CreateStagingBuffer(size_t size) override;
|
||||||
|
|
|
@ -432,21 +432,18 @@ namespace dawn::native::metal {
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<Texture> Device::CreateTextureWrappingIOSurface(const ExternalImageDescriptor* descriptor,
|
Ref<Texture> Device::CreateTextureWrappingIOSurface(const ExternalImageDescriptor* descriptor,
|
||||||
IOSurfaceRef ioSurface,
|
IOSurfaceRef ioSurface) {
|
||||||
uint32_t plane) {
|
|
||||||
const TextureDescriptor* textureDescriptor = FromAPI(descriptor->cTextureDescriptor);
|
const TextureDescriptor* textureDescriptor = FromAPI(descriptor->cTextureDescriptor);
|
||||||
|
|
||||||
if (ConsumedError(ValidateTextureDescriptor(this, textureDescriptor))) {
|
if (ConsumedError(ValidateTextureDescriptor(this, textureDescriptor))) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (ConsumedError(
|
if (ConsumedError(ValidateIOSurfaceCanBeWrapped(this, textureDescriptor, ioSurface))) {
|
||||||
ValidateIOSurfaceCanBeWrapped(this, textureDescriptor, ioSurface, plane))) {
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<Texture> result;
|
Ref<Texture> result;
|
||||||
if (ConsumedError(Texture::CreateFromIOSurface(this, descriptor, ioSurface, plane),
|
if (ConsumedError(Texture::CreateFromIOSurface(this, descriptor, ioSurface), &result)) {
|
||||||
&result)) {
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -37,8 +37,8 @@ namespace dawn::native::metal {
|
||||||
WGPUTexture WrapIOSurface(WGPUDevice device,
|
WGPUTexture WrapIOSurface(WGPUDevice device,
|
||||||
const ExternalImageDescriptorIOSurface* cDescriptor) {
|
const ExternalImageDescriptorIOSurface* cDescriptor) {
|
||||||
Device* backendDevice = ToBackend(FromAPI(device));
|
Device* backendDevice = ToBackend(FromAPI(device));
|
||||||
Ref<TextureBase> texture = backendDevice->CreateTextureWrappingIOSurface(
|
Ref<TextureBase> texture =
|
||||||
cDescriptor, cDescriptor->ioSurface, cDescriptor->plane);
|
backendDevice->CreateTextureWrappingIOSurface(cDescriptor, cDescriptor->ioSurface);
|
||||||
return ToAPI(texture.Detach());
|
return ToAPI(texture.Detach());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include "dawn/native/Texture.h"
|
#include "dawn/native/Texture.h"
|
||||||
|
|
||||||
|
#include "dawn/common/CoreFoundationRef.h"
|
||||||
#include "dawn/common/NSRef.h"
|
#include "dawn/common/NSRef.h"
|
||||||
#include "dawn/native/DawnNative.h"
|
#include "dawn/native/DawnNative.h"
|
||||||
|
|
||||||
|
@ -31,8 +32,7 @@ namespace dawn::native::metal {
|
||||||
MTLPixelFormat MetalPixelFormat(wgpu::TextureFormat format);
|
MTLPixelFormat MetalPixelFormat(wgpu::TextureFormat format);
|
||||||
MaybeError ValidateIOSurfaceCanBeWrapped(const DeviceBase* device,
|
MaybeError ValidateIOSurfaceCanBeWrapped(const DeviceBase* device,
|
||||||
const TextureDescriptor* descriptor,
|
const TextureDescriptor* descriptor,
|
||||||
IOSurfaceRef ioSurface,
|
IOSurfaceRef ioSurface);
|
||||||
uint32_t plane);
|
|
||||||
|
|
||||||
class Texture final : public TextureBase {
|
class Texture final : public TextureBase {
|
||||||
public:
|
public:
|
||||||
|
@ -41,13 +41,13 @@ namespace dawn::native::metal {
|
||||||
static ResultOrError<Ref<Texture>> CreateFromIOSurface(
|
static ResultOrError<Ref<Texture>> CreateFromIOSurface(
|
||||||
Device* device,
|
Device* device,
|
||||||
const ExternalImageDescriptor* descriptor,
|
const ExternalImageDescriptor* descriptor,
|
||||||
IOSurfaceRef ioSurface,
|
IOSurfaceRef ioSurface);
|
||||||
uint32_t plane);
|
|
||||||
static Ref<Texture> CreateWrapping(Device* device,
|
static Ref<Texture> CreateWrapping(Device* device,
|
||||||
const TextureDescriptor* descriptor,
|
const TextureDescriptor* descriptor,
|
||||||
NSPRef<id<MTLTexture>> wrapped);
|
NSPRef<id<MTLTexture>> wrapped);
|
||||||
|
|
||||||
id<MTLTexture> GetMTLTexture();
|
id<MTLTexture> GetMTLTexture();
|
||||||
|
IOSurfaceRef GetIOSurface();
|
||||||
NSPRef<id<MTLTexture>> CreateFormatView(wgpu::TextureFormat format);
|
NSPRef<id<MTLTexture>> CreateFormatView(wgpu::TextureFormat format);
|
||||||
|
|
||||||
void EnsureSubresourceContentInitialized(CommandRecordingContext* commandContext,
|
void EnsureSubresourceContentInitialized(CommandRecordingContext* commandContext,
|
||||||
|
@ -62,8 +62,7 @@ namespace dawn::native::metal {
|
||||||
MaybeError InitializeAsInternalTexture(const TextureDescriptor* descriptor);
|
MaybeError InitializeAsInternalTexture(const TextureDescriptor* descriptor);
|
||||||
MaybeError InitializeFromIOSurface(const ExternalImageDescriptor* descriptor,
|
MaybeError InitializeFromIOSurface(const ExternalImageDescriptor* descriptor,
|
||||||
const TextureDescriptor* textureDescriptor,
|
const TextureDescriptor* textureDescriptor,
|
||||||
IOSurfaceRef ioSurface,
|
IOSurfaceRef ioSurface);
|
||||||
uint32_t plane);
|
|
||||||
void InitializeAsWrapping(const TextureDescriptor* descriptor,
|
void InitializeAsWrapping(const TextureDescriptor* descriptor,
|
||||||
NSPRef<id<MTLTexture>> wrapped);
|
NSPRef<id<MTLTexture>> wrapped);
|
||||||
|
|
||||||
|
@ -74,7 +73,9 @@ namespace dawn::native::metal {
|
||||||
TextureBase::ClearValue clearValue);
|
TextureBase::ClearValue clearValue);
|
||||||
|
|
||||||
NSPRef<id<MTLTexture>> mMtlTexture;
|
NSPRef<id<MTLTexture>> mMtlTexture;
|
||||||
|
|
||||||
MTLTextureUsage mMtlUsage;
|
MTLTextureUsage mMtlUsage;
|
||||||
|
CFRef<IOSurfaceRef> mIOSurface = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TextureView final : public TextureViewBase {
|
class TextureView final : public TextureViewBase {
|
||||||
|
|
|
@ -181,12 +181,25 @@ namespace dawn::native::metal {
|
||||||
return wgpu::TextureFormat::RG8Unorm;
|
return wgpu::TextureFormat::RG8Unorm;
|
||||||
case kCVPixelFormatType_OneComponent8:
|
case kCVPixelFormatType_OneComponent8:
|
||||||
return wgpu::TextureFormat::R8Unorm;
|
return wgpu::TextureFormat::R8Unorm;
|
||||||
|
case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange:
|
||||||
|
return wgpu::TextureFormat::R8BG8Biplanar420Unorm;
|
||||||
default:
|
default:
|
||||||
return DAWN_FORMAT_VALIDATION_ERROR("Unsupported IOSurface format (%x).",
|
return DAWN_FORMAT_VALIDATION_ERROR("Unsupported IOSurface format (%x).",
|
||||||
format);
|
format);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t GetIOSurfacePlane(wgpu::TextureAspect aspect) {
|
||||||
|
switch (aspect) {
|
||||||
|
case wgpu::TextureAspect::Plane0Only:
|
||||||
|
return 0;
|
||||||
|
case wgpu::TextureAspect::Plane1Only:
|
||||||
|
return 1;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(DAWN_PLATFORM_MACOS)
|
#if defined(DAWN_PLATFORM_MACOS)
|
||||||
MTLStorageMode kIOSurfaceStorageMode = MTLStorageModeManaged;
|
MTLStorageMode kIOSurfaceStorageMode = MTLStorageModeManaged;
|
||||||
#elif defined(DAWN_PLATFORM_IOS)
|
#elif defined(DAWN_PLATFORM_IOS)
|
||||||
|
@ -392,15 +405,7 @@ namespace dawn::native::metal {
|
||||||
|
|
||||||
MaybeError ValidateIOSurfaceCanBeWrapped(const DeviceBase*,
|
MaybeError ValidateIOSurfaceCanBeWrapped(const DeviceBase*,
|
||||||
const TextureDescriptor* descriptor,
|
const TextureDescriptor* descriptor,
|
||||||
IOSurfaceRef ioSurface,
|
IOSurfaceRef ioSurface) {
|
||||||
uint32_t plane) {
|
|
||||||
// IOSurfaceGetPlaneCount can return 0 for non-planar IOSurfaces but we will treat
|
|
||||||
// non-planar like it is a single plane.
|
|
||||||
size_t surfacePlaneCount = std::max(size_t(1), IOSurfaceGetPlaneCount(ioSurface));
|
|
||||||
DAWN_INVALID_IF(plane >= surfacePlaneCount,
|
|
||||||
"IOSurface plane (%u) exceeds the surface's plane count (%u).", plane,
|
|
||||||
surfacePlaneCount);
|
|
||||||
|
|
||||||
DAWN_INVALID_IF(descriptor->dimension != wgpu::TextureDimension::e2D,
|
DAWN_INVALID_IF(descriptor->dimension != wgpu::TextureDimension::e2D,
|
||||||
"Texture dimension (%s) is not %s.", descriptor->dimension,
|
"Texture dimension (%s) is not %s.", descriptor->dimension,
|
||||||
wgpu::TextureDimension::e2D);
|
wgpu::TextureDimension::e2D);
|
||||||
|
@ -414,8 +419,8 @@ namespace dawn::native::metal {
|
||||||
DAWN_INVALID_IF(descriptor->sampleCount != 1, "Sample count (%u) is not 1.",
|
DAWN_INVALID_IF(descriptor->sampleCount != 1, "Sample count (%u) is not 1.",
|
||||||
descriptor->sampleCount);
|
descriptor->sampleCount);
|
||||||
|
|
||||||
uint32_t surfaceWidth = IOSurfaceGetWidthOfPlane(ioSurface, plane);
|
uint32_t surfaceWidth = IOSurfaceGetWidth(ioSurface);
|
||||||
uint32_t surfaceHeight = IOSurfaceGetHeightOfPlane(ioSurface, plane);
|
uint32_t surfaceHeight = IOSurfaceGetHeight(ioSurface);
|
||||||
|
|
||||||
DAWN_INVALID_IF(
|
DAWN_INVALID_IF(
|
||||||
descriptor->size.width != surfaceWidth || descriptor->size.height != surfaceHeight ||
|
descriptor->size.width != surfaceWidth || descriptor->size.height != surfaceHeight ||
|
||||||
|
@ -497,13 +502,12 @@ namespace dawn::native::metal {
|
||||||
ResultOrError<Ref<Texture>> Texture::CreateFromIOSurface(
|
ResultOrError<Ref<Texture>> Texture::CreateFromIOSurface(
|
||||||
Device* device,
|
Device* device,
|
||||||
const ExternalImageDescriptor* descriptor,
|
const ExternalImageDescriptor* descriptor,
|
||||||
IOSurfaceRef ioSurface,
|
IOSurfaceRef ioSurface) {
|
||||||
uint32_t plane) {
|
|
||||||
const TextureDescriptor* textureDescriptor = FromAPI(descriptor->cTextureDescriptor);
|
const TextureDescriptor* textureDescriptor = FromAPI(descriptor->cTextureDescriptor);
|
||||||
|
|
||||||
Ref<Texture> texture =
|
Ref<Texture> texture =
|
||||||
AcquireRef(new Texture(device, textureDescriptor, TextureState::OwnedInternal));
|
AcquireRef(new Texture(device, textureDescriptor, TextureState::OwnedExternal));
|
||||||
DAWN_TRY(texture->InitializeFromIOSurface(descriptor, textureDescriptor, ioSurface, plane));
|
DAWN_TRY(texture->InitializeFromIOSurface(descriptor, textureDescriptor, ioSurface));
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -546,20 +550,28 @@ namespace dawn::native::metal {
|
||||||
|
|
||||||
MaybeError Texture::InitializeFromIOSurface(const ExternalImageDescriptor* descriptor,
|
MaybeError Texture::InitializeFromIOSurface(const ExternalImageDescriptor* descriptor,
|
||||||
const TextureDescriptor* textureDescriptor,
|
const TextureDescriptor* textureDescriptor,
|
||||||
IOSurfaceRef ioSurface,
|
IOSurfaceRef ioSurface) {
|
||||||
uint32_t plane) {
|
mIOSurface = ioSurface;
|
||||||
Device* device = ToBackend(GetDevice());
|
|
||||||
|
|
||||||
NSRef<MTLTextureDescriptor> mtlDesc = CreateMetalTextureDescriptor();
|
// Uses WGPUTexture which wraps multiplanar ioSurface needs to create
|
||||||
[*mtlDesc setStorageMode:kIOSurfaceStorageMode];
|
// texture view explicitly. Wrap the ioSurface and delay to extract
|
||||||
|
// MTLTexture from the plane of it when creating texture view.
|
||||||
|
// WGPUTexture which wraps non-multplanar ioSurface needs to support
|
||||||
|
// ops that doesn't require creating texture view(e.g. copy). Extract
|
||||||
|
// MTLTexture from such ioSurface to support this.
|
||||||
|
if (!GetFormat().IsMultiPlanar()) {
|
||||||
|
Device* device = ToBackend(GetDevice());
|
||||||
|
|
||||||
mMtlUsage = [*mtlDesc usage];
|
NSRef<MTLTextureDescriptor> mtlDesc = CreateMetalTextureDescriptor();
|
||||||
mMtlTexture = AcquireNSPRef([device->GetMTLDevice() newTextureWithDescriptor:mtlDesc.Get()
|
[*mtlDesc setStorageMode:kIOSurfaceStorageMode];
|
||||||
iosurface:ioSurface
|
|
||||||
plane:plane]);
|
|
||||||
|
|
||||||
|
mMtlUsage = [*mtlDesc usage];
|
||||||
|
mMtlTexture =
|
||||||
|
AcquireNSPRef([device->GetMTLDevice() newTextureWithDescriptor:mtlDesc.Get()
|
||||||
|
iosurface:ioSurface
|
||||||
|
plane:0]);
|
||||||
|
}
|
||||||
SetIsSubresourceContentInitialized(descriptor->isInitialized, GetAllSubresources());
|
SetIsSubresourceContentInitialized(descriptor->isInitialized, GetAllSubresources());
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -569,12 +581,17 @@ namespace dawn::native::metal {
|
||||||
void Texture::DestroyImpl() {
|
void Texture::DestroyImpl() {
|
||||||
TextureBase::DestroyImpl();
|
TextureBase::DestroyImpl();
|
||||||
mMtlTexture = nullptr;
|
mMtlTexture = nullptr;
|
||||||
|
mIOSurface = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLTexture> Texture::GetMTLTexture() {
|
id<MTLTexture> Texture::GetMTLTexture() {
|
||||||
return mMtlTexture.Get();
|
return mMtlTexture.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IOSurfaceRef Texture::GetIOSurface() {
|
||||||
|
return mIOSurface.Get();
|
||||||
|
}
|
||||||
|
|
||||||
NSPRef<id<MTLTexture>> Texture::CreateFormatView(wgpu::TextureFormat format) {
|
NSPRef<id<MTLTexture>> Texture::CreateFormatView(wgpu::TextureFormat format) {
|
||||||
if (GetFormat().format == format) {
|
if (GetFormat().format == format) {
|
||||||
return mMtlTexture;
|
return mMtlTexture;
|
||||||
|
@ -821,6 +838,37 @@ namespace dawn::native::metal {
|
||||||
mMtlTextureView = nullptr;
|
mMtlTextureView = nullptr;
|
||||||
} else if (!RequiresCreatingNewTextureView(texture, descriptor)) {
|
} else if (!RequiresCreatingNewTextureView(texture, descriptor)) {
|
||||||
mMtlTextureView = mtlTexture;
|
mMtlTextureView = mtlTexture;
|
||||||
|
} else if (texture->GetFormat().IsMultiPlanar()) {
|
||||||
|
NSRef<MTLTextureDescriptor> mtlDescRef = AcquireNSRef([MTLTextureDescriptor new]);
|
||||||
|
MTLTextureDescriptor* mtlDesc = mtlDescRef.Get();
|
||||||
|
|
||||||
|
mtlDesc.sampleCount = texture->GetSampleCount();
|
||||||
|
mtlDesc.usage = MetalTextureUsage(texture->GetFormat(), texture->GetInternalUsage(),
|
||||||
|
texture->GetSampleCount());
|
||||||
|
mtlDesc.pixelFormat = MetalPixelFormat(descriptor->format);
|
||||||
|
mtlDesc.mipmapLevelCount = texture->GetNumMipLevels();
|
||||||
|
mtlDesc.storageMode = kIOSurfaceStorageMode;
|
||||||
|
|
||||||
|
uint32_t plane = GetIOSurfacePlane(descriptor->aspect);
|
||||||
|
mtlDesc.width = IOSurfaceGetWidthOfPlane(texture->GetIOSurface(), plane);
|
||||||
|
mtlDesc.height = IOSurfaceGetHeightOfPlane(texture->GetIOSurface(), plane);
|
||||||
|
|
||||||
|
// Multiplanar texture is validated to only have single layer, single mipLevel
|
||||||
|
// and 2d textures (depth == 1)
|
||||||
|
ASSERT(texture->GetArrayLayers() == 1 &&
|
||||||
|
texture->GetDimension() == wgpu::TextureDimension::e2D &&
|
||||||
|
texture->GetNumMipLevels() == 1);
|
||||||
|
mtlDesc.arrayLength = 1;
|
||||||
|
mtlDesc.depth = 1;
|
||||||
|
|
||||||
|
mMtlTextureView = AcquireNSPRef([ToBackend(GetDevice())->GetMTLDevice()
|
||||||
|
newTextureWithDescriptor:mtlDesc
|
||||||
|
iosurface:texture->GetIOSurface()
|
||||||
|
plane:plane]);
|
||||||
|
if (mMtlTextureView == nil) {
|
||||||
|
return DAWN_INTERNAL_ERROR(
|
||||||
|
"Failed to create MTLTexture view for external texture.");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
MTLPixelFormat format = MetalPixelFormat(descriptor->format);
|
MTLPixelFormat format = MetalPixelFormat(descriptor->format);
|
||||||
if (descriptor->aspect == wgpu::TextureAspect::StencilOnly) {
|
if (descriptor->aspect == wgpu::TextureAspect::StencilOnly) {
|
||||||
|
|
|
@ -451,7 +451,10 @@ source_set("end2end_tests_sources") {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dawn_enable_metal) {
|
if (dawn_enable_metal) {
|
||||||
sources += [ "end2end/IOSurfaceWrappingTests.cpp" ]
|
sources += [
|
||||||
|
"end2end/IOSurfaceWrappingTests.cpp",
|
||||||
|
"end2end/VideoViewsTests_mac.cpp",
|
||||||
|
]
|
||||||
frameworks = [ "IOSurface.framework" ]
|
frameworks = [ "IOSurface.framework" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -468,7 +471,8 @@ source_set("end2end_tests_sources") {
|
||||||
deps += [ "${dawn_root}/src/dawn/utils:glfw" ]
|
deps += [ "${dawn_root}/src/dawn/utils:glfw" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dawn_enable_d3d12 || (dawn_enable_vulkan && is_chromeos)) {
|
if (dawn_enable_d3d12 || (dawn_enable_vulkan && is_chromeos) ||
|
||||||
|
dawn_enable_metal) {
|
||||||
sources += [
|
sources += [
|
||||||
"end2end/VideoViewsTests.cpp",
|
"end2end/VideoViewsTests.cpp",
|
||||||
"end2end/VideoViewsTests.h",
|
"end2end/VideoViewsTests.h",
|
||||||
|
|
|
@ -96,13 +96,11 @@ namespace {
|
||||||
public:
|
public:
|
||||||
wgpu::Texture WrapIOSurface(const wgpu::TextureDescriptor* descriptor,
|
wgpu::Texture WrapIOSurface(const wgpu::TextureDescriptor* descriptor,
|
||||||
IOSurfaceRef ioSurface,
|
IOSurfaceRef ioSurface,
|
||||||
uint32_t plane,
|
|
||||||
bool isInitialized = true) {
|
bool isInitialized = true) {
|
||||||
dawn::native::metal::ExternalImageDescriptorIOSurface externDesc;
|
dawn::native::metal::ExternalImageDescriptorIOSurface externDesc;
|
||||||
externDesc.cTextureDescriptor =
|
externDesc.cTextureDescriptor =
|
||||||
reinterpret_cast<const WGPUTextureDescriptor*>(descriptor);
|
reinterpret_cast<const WGPUTextureDescriptor*>(descriptor);
|
||||||
externDesc.ioSurface = ioSurface;
|
externDesc.ioSurface = ioSurface;
|
||||||
externDesc.plane = plane;
|
|
||||||
externDesc.isInitialized = isInitialized;
|
externDesc.isInitialized = isInitialized;
|
||||||
WGPUTexture texture = dawn::native::metal::WrapIOSurface(device.Get(), &externDesc);
|
WGPUTexture texture = dawn::native::metal::WrapIOSurface(device.Get(), &externDesc);
|
||||||
return wgpu::Texture::Acquire(texture);
|
return wgpu::Texture::Acquire(texture);
|
||||||
|
@ -134,7 +132,7 @@ class IOSurfaceValidationTests : public IOSurfaceTestBase {
|
||||||
// Test a successful wrapping of an IOSurface in a texture
|
// Test a successful wrapping of an IOSurface in a texture
|
||||||
TEST_P(IOSurfaceValidationTests, Success) {
|
TEST_P(IOSurfaceValidationTests, Success) {
|
||||||
DAWN_TEST_UNSUPPORTED_IF(UsesWire());
|
DAWN_TEST_UNSUPPORTED_IF(UsesWire());
|
||||||
wgpu::Texture texture = WrapIOSurface(&descriptor, defaultIOSurface.get(), 0);
|
wgpu::Texture texture = WrapIOSurface(&descriptor, defaultIOSurface.get());
|
||||||
ASSERT_NE(texture.Get(), nullptr);
|
ASSERT_NE(texture.Get(), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,16 +143,7 @@ TEST_P(IOSurfaceValidationTests, InvalidTextureDescriptor) {
|
||||||
wgpu::ChainedStruct chainedDescriptor;
|
wgpu::ChainedStruct chainedDescriptor;
|
||||||
descriptor.nextInChain = &chainedDescriptor;
|
descriptor.nextInChain = &chainedDescriptor;
|
||||||
|
|
||||||
ASSERT_DEVICE_ERROR(wgpu::Texture texture =
|
ASSERT_DEVICE_ERROR(wgpu::Texture texture = WrapIOSurface(&descriptor, defaultIOSurface.get()));
|
||||||
WrapIOSurface(&descriptor, defaultIOSurface.get(), 0));
|
|
||||||
ASSERT_EQ(texture.Get(), nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test an error occurs if the plane is too large
|
|
||||||
TEST_P(IOSurfaceValidationTests, PlaneTooLarge) {
|
|
||||||
DAWN_TEST_UNSUPPORTED_IF(UsesWire());
|
|
||||||
ASSERT_DEVICE_ERROR(wgpu::Texture texture =
|
|
||||||
WrapIOSurface(&descriptor, defaultIOSurface.get(), 1));
|
|
||||||
ASSERT_EQ(texture.Get(), nullptr);
|
ASSERT_EQ(texture.Get(), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,8 +153,7 @@ TEST_P(IOSurfaceValidationTests, InvalidTextureDimension) {
|
||||||
DAWN_TEST_UNSUPPORTED_IF(UsesWire());
|
DAWN_TEST_UNSUPPORTED_IF(UsesWire());
|
||||||
descriptor.dimension = wgpu::TextureDimension::e3D;
|
descriptor.dimension = wgpu::TextureDimension::e3D;
|
||||||
|
|
||||||
ASSERT_DEVICE_ERROR(wgpu::Texture texture =
|
ASSERT_DEVICE_ERROR(wgpu::Texture texture = WrapIOSurface(&descriptor, defaultIOSurface.get()));
|
||||||
WrapIOSurface(&descriptor, defaultIOSurface.get(), 0));
|
|
||||||
ASSERT_EQ(texture.Get(), nullptr);
|
ASSERT_EQ(texture.Get(), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,8 +162,7 @@ TEST_P(IOSurfaceValidationTests, InvalidMipLevelCount) {
|
||||||
DAWN_TEST_UNSUPPORTED_IF(UsesWire());
|
DAWN_TEST_UNSUPPORTED_IF(UsesWire());
|
||||||
descriptor.mipLevelCount = 2;
|
descriptor.mipLevelCount = 2;
|
||||||
|
|
||||||
ASSERT_DEVICE_ERROR(wgpu::Texture texture =
|
ASSERT_DEVICE_ERROR(wgpu::Texture texture = WrapIOSurface(&descriptor, defaultIOSurface.get()));
|
||||||
WrapIOSurface(&descriptor, defaultIOSurface.get(), 0));
|
|
||||||
ASSERT_EQ(texture.Get(), nullptr);
|
ASSERT_EQ(texture.Get(), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,8 +171,7 @@ TEST_P(IOSurfaceValidationTests, InvalidDepth) {
|
||||||
DAWN_TEST_UNSUPPORTED_IF(UsesWire());
|
DAWN_TEST_UNSUPPORTED_IF(UsesWire());
|
||||||
descriptor.size.depthOrArrayLayers = 2;
|
descriptor.size.depthOrArrayLayers = 2;
|
||||||
|
|
||||||
ASSERT_DEVICE_ERROR(wgpu::Texture texture =
|
ASSERT_DEVICE_ERROR(wgpu::Texture texture = WrapIOSurface(&descriptor, defaultIOSurface.get()));
|
||||||
WrapIOSurface(&descriptor, defaultIOSurface.get(), 0));
|
|
||||||
ASSERT_EQ(texture.Get(), nullptr);
|
ASSERT_EQ(texture.Get(), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,8 +180,7 @@ TEST_P(IOSurfaceValidationTests, InvalidSampleCount) {
|
||||||
DAWN_TEST_UNSUPPORTED_IF(UsesWire());
|
DAWN_TEST_UNSUPPORTED_IF(UsesWire());
|
||||||
descriptor.sampleCount = 4;
|
descriptor.sampleCount = 4;
|
||||||
|
|
||||||
ASSERT_DEVICE_ERROR(wgpu::Texture texture =
|
ASSERT_DEVICE_ERROR(wgpu::Texture texture = WrapIOSurface(&descriptor, defaultIOSurface.get()));
|
||||||
WrapIOSurface(&descriptor, defaultIOSurface.get(), 0));
|
|
||||||
ASSERT_EQ(texture.Get(), nullptr);
|
ASSERT_EQ(texture.Get(), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,8 +189,7 @@ TEST_P(IOSurfaceValidationTests, InvalidWidth) {
|
||||||
DAWN_TEST_UNSUPPORTED_IF(UsesWire());
|
DAWN_TEST_UNSUPPORTED_IF(UsesWire());
|
||||||
descriptor.size.width = 11;
|
descriptor.size.width = 11;
|
||||||
|
|
||||||
ASSERT_DEVICE_ERROR(wgpu::Texture texture =
|
ASSERT_DEVICE_ERROR(wgpu::Texture texture = WrapIOSurface(&descriptor, defaultIOSurface.get()));
|
||||||
WrapIOSurface(&descriptor, defaultIOSurface.get(), 0));
|
|
||||||
ASSERT_EQ(texture.Get(), nullptr);
|
ASSERT_EQ(texture.Get(), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,8 +198,7 @@ TEST_P(IOSurfaceValidationTests, InvalidHeight) {
|
||||||
DAWN_TEST_UNSUPPORTED_IF(UsesWire());
|
DAWN_TEST_UNSUPPORTED_IF(UsesWire());
|
||||||
descriptor.size.height = 11;
|
descriptor.size.height = 11;
|
||||||
|
|
||||||
ASSERT_DEVICE_ERROR(wgpu::Texture texture =
|
ASSERT_DEVICE_ERROR(wgpu::Texture texture = WrapIOSurface(&descriptor, defaultIOSurface.get()));
|
||||||
WrapIOSurface(&descriptor, defaultIOSurface.get(), 0));
|
|
||||||
ASSERT_EQ(texture.Get(), nullptr);
|
ASSERT_EQ(texture.Get(), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,8 +207,7 @@ TEST_P(IOSurfaceValidationTests, InvalidFormat) {
|
||||||
DAWN_TEST_UNSUPPORTED_IF(UsesWire());
|
DAWN_TEST_UNSUPPORTED_IF(UsesWire());
|
||||||
descriptor.format = wgpu::TextureFormat::R8Unorm;
|
descriptor.format = wgpu::TextureFormat::R8Unorm;
|
||||||
|
|
||||||
ASSERT_DEVICE_ERROR(wgpu::Texture texture =
|
ASSERT_DEVICE_ERROR(wgpu::Texture texture = WrapIOSurface(&descriptor, defaultIOSurface.get()));
|
||||||
WrapIOSurface(&descriptor, defaultIOSurface.get(), 0));
|
|
||||||
ASSERT_EQ(texture.Get(), nullptr);
|
ASSERT_EQ(texture.Get(), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,7 +287,7 @@ class IOSurfaceUsageTests : public IOSurfaceTestBase {
|
||||||
textureDescriptor.sampleCount = 1;
|
textureDescriptor.sampleCount = 1;
|
||||||
textureDescriptor.mipLevelCount = 1;
|
textureDescriptor.mipLevelCount = 1;
|
||||||
textureDescriptor.usage = wgpu::TextureUsage::TextureBinding;
|
textureDescriptor.usage = wgpu::TextureUsage::TextureBinding;
|
||||||
wgpu::Texture wrappingTexture = WrapIOSurface(&textureDescriptor, ioSurface, 0);
|
wgpu::Texture wrappingTexture = WrapIOSurface(&textureDescriptor, ioSurface);
|
||||||
|
|
||||||
wgpu::TextureView textureView = wrappingTexture.CreateView();
|
wgpu::TextureView textureView = wrappingTexture.CreateView();
|
||||||
|
|
||||||
|
@ -345,7 +327,7 @@ class IOSurfaceUsageTests : public IOSurfaceTestBase {
|
||||||
textureDescriptor.sampleCount = 1;
|
textureDescriptor.sampleCount = 1;
|
||||||
textureDescriptor.mipLevelCount = 1;
|
textureDescriptor.mipLevelCount = 1;
|
||||||
textureDescriptor.usage = wgpu::TextureUsage::RenderAttachment;
|
textureDescriptor.usage = wgpu::TextureUsage::RenderAttachment;
|
||||||
wgpu::Texture ioSurfaceTexture = WrapIOSurface(&textureDescriptor, ioSurface, 0);
|
wgpu::Texture ioSurfaceTexture = WrapIOSurface(&textureDescriptor, ioSurface);
|
||||||
|
|
||||||
wgpu::TextureView ioSurfaceView = ioSurfaceTexture.CreateView();
|
wgpu::TextureView ioSurfaceView = ioSurfaceTexture.CreateView();
|
||||||
|
|
||||||
|
@ -471,7 +453,7 @@ TEST_P(IOSurfaceUsageTests, UninitializedTextureIsCleared) {
|
||||||
textureDescriptor.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc;
|
textureDescriptor.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc;
|
||||||
|
|
||||||
// wrap ioSurface and ensure color is not visible when isInitialized set to false
|
// wrap ioSurface and ensure color is not visible when isInitialized set to false
|
||||||
wgpu::Texture ioSurfaceTexture = WrapIOSurface(&textureDescriptor, ioSurface.get(), 0, false);
|
wgpu::Texture ioSurfaceTexture = WrapIOSurface(&textureDescriptor, ioSurface.get(), false);
|
||||||
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), ioSurfaceTexture, 0, 0);
|
EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), ioSurfaceTexture, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -117,6 +117,58 @@ std::vector<uint8_t> VideoViewsTests::GetTestTextureData(wgpu::TextureFormat for
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t VideoViewsTests::NumPlanes(wgpu::TextureFormat format) {
|
||||||
|
switch (format) {
|
||||||
|
case wgpu::TextureFormat::R8BG8Biplanar420Unorm:
|
||||||
|
return 2;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::vector<uint8_t> VideoViewsTests::GetTestTextureDataWithPlaneIndex(size_t planeIndex,
|
||||||
|
size_t bytesPerRow,
|
||||||
|
size_t height,
|
||||||
|
bool isCheckerboard) {
|
||||||
|
std::vector<uint8_t> texelData = VideoViewsTests::GetTestTextureData(
|
||||||
|
wgpu::TextureFormat::R8BG8Biplanar420Unorm, isCheckerboard);
|
||||||
|
const uint32_t texelDataRowBytes = kYUVImageDataWidthInTexels;
|
||||||
|
const uint32_t texelDataHeight =
|
||||||
|
planeIndex == 0 ? kYUVImageDataHeightInTexels : kYUVImageDataHeightInTexels / 2;
|
||||||
|
|
||||||
|
std::vector<uint8_t> texels(bytesPerRow * height, 0);
|
||||||
|
uint32_t plane_first_texel_offset = 0;
|
||||||
|
// The size of the test video frame is 4 x 4
|
||||||
|
switch (planeIndex) {
|
||||||
|
case VideoViewsTests::kYUVLumaPlaneIndex:
|
||||||
|
for (uint32_t i = 0; i < texelDataHeight; ++i) {
|
||||||
|
if (i < texelDataHeight) {
|
||||||
|
for (uint32_t j = 0; j < texelDataRowBytes; ++j) {
|
||||||
|
texels[bytesPerRow * i + j] =
|
||||||
|
texelData[texelDataRowBytes * i + j + plane_first_texel_offset];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return texels;
|
||||||
|
case VideoViewsTests::kYUVChromaPlaneIndex:
|
||||||
|
// TexelData is 4 * 6 size, first 4 * 4 is Y plane, UV plane started
|
||||||
|
// at index 16.
|
||||||
|
plane_first_texel_offset = 16;
|
||||||
|
for (uint32_t i = 0; i < texelDataHeight; ++i) {
|
||||||
|
if (i < texelDataHeight) {
|
||||||
|
for (uint32_t j = 0; j < texelDataRowBytes; ++j) {
|
||||||
|
texels[bytesPerRow * i + j] =
|
||||||
|
texelData[texelDataRowBytes * i + j + plane_first_texel_offset];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return texels;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Vertex shader used to render a sampled texture into a quad.
|
// Vertex shader used to render a sampled texture into a quad.
|
||||||
wgpu::ShaderModule VideoViewsTests::GetTestVertexShaderModule() const {
|
wgpu::ShaderModule VideoViewsTests::GetTestVertexShaderModule() const {
|
||||||
return utils::CreateShaderModule(device, R"(
|
return utils::CreateShaderModule(device, R"(
|
||||||
|
|
|
@ -28,7 +28,8 @@ class VideoViewsTestBackend {
|
||||||
virtual ~VideoViewsTestBackend();
|
virtual ~VideoViewsTestBackend();
|
||||||
|
|
||||||
virtual void OnSetUp(WGPUDevice device) = 0;
|
virtual void OnSetUp(WGPUDevice device) = 0;
|
||||||
virtual void OnTearDown() = 0;
|
virtual void OnTearDown() {
|
||||||
|
}
|
||||||
|
|
||||||
class PlatformTexture {
|
class PlatformTexture {
|
||||||
public:
|
public:
|
||||||
|
@ -74,6 +75,11 @@ class VideoViewsTests : public DawnTest {
|
||||||
RGBA8{90, 240, 0, 0xFF}}; // UV
|
RGBA8{90, 240, 0, 0xFF}}; // UV
|
||||||
|
|
||||||
static std::vector<uint8_t> GetTestTextureData(wgpu::TextureFormat format, bool isCheckerboard);
|
static std::vector<uint8_t> GetTestTextureData(wgpu::TextureFormat format, bool isCheckerboard);
|
||||||
|
static uint32_t NumPlanes(wgpu::TextureFormat format);
|
||||||
|
static std::vector<uint8_t> GetTestTextureDataWithPlaneIndex(size_t planeIndex,
|
||||||
|
size_t bytesPerRow,
|
||||||
|
size_t height,
|
||||||
|
bool isCheckerboard);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void SetUp() override;
|
void SetUp() override;
|
||||||
|
|
|
@ -0,0 +1,187 @@
|
||||||
|
// Copyright 2022 The Dawn Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "VideoViewsTests.h"
|
||||||
|
|
||||||
|
#include "dawn/common/Assert.h"
|
||||||
|
#include "dawn/common/CoreFoundationRef.h"
|
||||||
|
#include "dawn/native/MetalBackend.h"
|
||||||
|
|
||||||
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
|
#include <CoreVideo/CVPixelBuffer.h>
|
||||||
|
#include <IOSurface/IOSurfaceRef.h>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
void AddIntegerValue(CFMutableDictionaryRef dictionary, const CFStringRef key, int32_t value) {
|
||||||
|
CFNumberRef number(CFNumberCreate(nullptr, kCFNumberSInt32Type, &value));
|
||||||
|
CFDictionaryAddValue(dictionary, key, number);
|
||||||
|
CFRelease(number);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
class PlatformTextureIOSurface : public VideoViewsTestBackend::PlatformTexture {
|
||||||
|
public:
|
||||||
|
PlatformTextureIOSurface(wgpu::Texture&& texture, IOSurfaceRef iosurface)
|
||||||
|
: PlatformTexture(std::move(texture)) {
|
||||||
|
mIOSurface = AcquireCFRef<IOSurfaceRef>(iosurface);
|
||||||
|
}
|
||||||
|
~PlatformTextureIOSurface() override {
|
||||||
|
mIOSurface = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CanWrapAsWGPUTexture() override {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
CFRef<IOSurfaceRef> mIOSurface = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
class VideoViewsTestBackendIOSurface : public VideoViewsTestBackend {
|
||||||
|
public:
|
||||||
|
void OnSetUp(WGPUDevice device) override {
|
||||||
|
mWGPUDevice = device;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
OSType ToCVFormat(wgpu::TextureFormat format) {
|
||||||
|
switch (format) {
|
||||||
|
case wgpu::TextureFormat::R8BG8Biplanar420Unorm:
|
||||||
|
return kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t GetSubSamplingFactorPerPlane(wgpu::TextureFormat format, size_t plane) {
|
||||||
|
switch (format) {
|
||||||
|
case wgpu::TextureFormat::R8BG8Biplanar420Unorm:
|
||||||
|
return plane == VideoViewsTests::kYUVLumaPlaneIndex ? 1 : 2;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t BytesPerElement(wgpu::TextureFormat format, size_t plane) {
|
||||||
|
switch (format) {
|
||||||
|
case wgpu::TextureFormat::R8BG8Biplanar420Unorm:
|
||||||
|
return plane == VideoViewsTests::kYUVLumaPlaneIndex ? 1 : 2;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<VideoViewsTestBackend::PlatformTexture> CreateVideoTextureForTest(
|
||||||
|
wgpu::TextureFormat format,
|
||||||
|
wgpu::TextureUsage usage,
|
||||||
|
bool isCheckerboard) override {
|
||||||
|
CFMutableDictionaryRef dict(CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
|
||||||
|
&kCFTypeDictionaryKeyCallBacks,
|
||||||
|
&kCFTypeDictionaryValueCallBacks));
|
||||||
|
AddIntegerValue(dict, kIOSurfaceWidth, VideoViewsTests::kYUVImageDataWidthInTexels);
|
||||||
|
AddIntegerValue(dict, kIOSurfaceHeight, VideoViewsTests::kYUVImageDataHeightInTexels);
|
||||||
|
AddIntegerValue(dict, kIOSurfacePixelFormat, ToCVFormat(format));
|
||||||
|
|
||||||
|
size_t num_planes = VideoViewsTests::NumPlanes(format);
|
||||||
|
|
||||||
|
CFMutableArrayRef planes(
|
||||||
|
CFArrayCreateMutable(kCFAllocatorDefault, num_planes, &kCFTypeArrayCallBacks));
|
||||||
|
size_t total_bytes_alloc = 0;
|
||||||
|
for (size_t plane = 0; plane < num_planes; ++plane) {
|
||||||
|
const size_t factor = GetSubSamplingFactorPerPlane(format, plane);
|
||||||
|
const size_t plane_width = VideoViewsTests::kYUVImageDataWidthInTexels / factor;
|
||||||
|
const size_t plane_height = VideoViewsTests::kYUVImageDataHeightInTexels / factor;
|
||||||
|
const size_t plane_bytes_per_element = BytesPerElement(format, plane);
|
||||||
|
const size_t plane_bytes_per_row = IOSurfaceAlignProperty(
|
||||||
|
kIOSurfacePlaneBytesPerRow, plane_width * plane_bytes_per_element);
|
||||||
|
const size_t plane_bytes_alloc =
|
||||||
|
IOSurfaceAlignProperty(kIOSurfacePlaneSize, plane_height * plane_bytes_per_row);
|
||||||
|
const size_t plane_offset =
|
||||||
|
IOSurfaceAlignProperty(kIOSurfacePlaneOffset, total_bytes_alloc);
|
||||||
|
|
||||||
|
CFMutableDictionaryRef plane_info(
|
||||||
|
CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks,
|
||||||
|
&kCFTypeDictionaryValueCallBacks));
|
||||||
|
|
||||||
|
AddIntegerValue(plane_info, kIOSurfacePlaneWidth, plane_width);
|
||||||
|
AddIntegerValue(plane_info, kIOSurfacePlaneHeight, plane_height);
|
||||||
|
AddIntegerValue(plane_info, kIOSurfacePlaneBytesPerElement, plane_bytes_per_element);
|
||||||
|
AddIntegerValue(plane_info, kIOSurfacePlaneBytesPerRow, plane_bytes_per_row);
|
||||||
|
AddIntegerValue(plane_info, kIOSurfacePlaneSize, plane_bytes_alloc);
|
||||||
|
AddIntegerValue(plane_info, kIOSurfacePlaneOffset, plane_offset);
|
||||||
|
CFArrayAppendValue(planes, plane_info);
|
||||||
|
CFRelease(plane_info);
|
||||||
|
total_bytes_alloc = plane_offset + plane_bytes_alloc;
|
||||||
|
}
|
||||||
|
CFDictionaryAddValue(dict, kIOSurfacePlaneInfo, planes);
|
||||||
|
CFRelease(planes);
|
||||||
|
|
||||||
|
total_bytes_alloc = IOSurfaceAlignProperty(kIOSurfaceAllocSize, total_bytes_alloc);
|
||||||
|
AddIntegerValue(dict, kIOSurfaceAllocSize, total_bytes_alloc);
|
||||||
|
|
||||||
|
IOSurfaceRef surface = IOSurfaceCreate(dict);
|
||||||
|
CFRelease(dict);
|
||||||
|
|
||||||
|
IOSurfaceLock(surface, 0, nullptr);
|
||||||
|
for (size_t plane = 0; plane < num_planes; ++plane) {
|
||||||
|
std::vector<uint8_t> data = VideoViewsTests::GetTestTextureDataWithPlaneIndex(
|
||||||
|
plane, IOSurfaceGetBytesPerRowOfPlane(surface, plane),
|
||||||
|
IOSurfaceGetHeightOfPlane(surface, plane), isCheckerboard);
|
||||||
|
void* pointer = IOSurfaceGetBaseAddressOfPlane(surface, plane);
|
||||||
|
memcpy(pointer, data.data(), data.size());
|
||||||
|
}
|
||||||
|
IOSurfaceUnlock(surface, 0, nullptr);
|
||||||
|
|
||||||
|
wgpu::TextureDescriptor textureDesc;
|
||||||
|
textureDesc.format = format;
|
||||||
|
textureDesc.dimension = wgpu::TextureDimension::e2D;
|
||||||
|
textureDesc.usage = usage;
|
||||||
|
textureDesc.size = {VideoViewsTests::kYUVImageDataWidthInTexels,
|
||||||
|
VideoViewsTests::kYUVImageDataHeightInTexels, 1};
|
||||||
|
|
||||||
|
wgpu::DawnTextureInternalUsageDescriptor internalDesc;
|
||||||
|
internalDesc.internalUsage = wgpu::TextureUsage::CopySrc;
|
||||||
|
textureDesc.nextInChain = &internalDesc;
|
||||||
|
|
||||||
|
dawn::native::metal::ExternalImageDescriptorIOSurface descriptor = {};
|
||||||
|
descriptor.cTextureDescriptor =
|
||||||
|
reinterpret_cast<const WGPUTextureDescriptor*>(&textureDesc);
|
||||||
|
descriptor.isInitialized = true;
|
||||||
|
descriptor.ioSurface = surface;
|
||||||
|
|
||||||
|
return std::make_unique<PlatformTextureIOSurface>(
|
||||||
|
wgpu::Texture::Acquire(dawn::native::metal::WrapIOSurface(mWGPUDevice, &descriptor)),
|
||||||
|
surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DestroyVideoTextureForTest(
|
||||||
|
std::unique_ptr<VideoViewsTestBackend::PlatformTexture>&& platformTexture) override {
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUDevice mWGPUDevice = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
// static
|
||||||
|
BackendTestConfig VideoViewsTestBackend::Backend() {
|
||||||
|
return MetalBackend();
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
std::unique_ptr<VideoViewsTestBackend> VideoViewsTestBackend::Create() {
|
||||||
|
return std::make_unique<VideoViewsTestBackendIOSurface>();
|
||||||
|
}
|
|
@ -77,9 +77,6 @@ class VideoViewsTestBackendWin : public VideoViewsTestBackend {
|
||||||
mD3d11Device = std::move(d3d11Device);
|
mD3d11Device = std::move(d3d11Device);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnTearDown() override {
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static DXGI_FORMAT GetDXGITextureFormat(wgpu::TextureFormat format) {
|
static DXGI_FORMAT GetDXGITextureFormat(wgpu::TextureFormat format) {
|
||||||
switch (format) {
|
switch (format) {
|
||||||
|
|
Loading…
Reference in New Issue