blob: 52015a1fb7863bef9a1d023c7f828da59c5d036b [file] [log] [blame]
/*
* Copyright 2024 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/core/SkStream.h"
#include "include/core/SkString.h"
#include "include/gpu/graphite/mtl/MtlGraphiteTypes.h"
#include "src/gpu/graphite/TextureInfoPriv.h"
#include "src/gpu/graphite/mtl/MtlGraphiteUtils.h"
#include "src/gpu/mtl/MtlUtilsPriv.h"
#include <cstdint>
#import <Metal/Metal.h>
class SkStream;
namespace skgpu::graphite {
MtlTextureInfo::MtlTextureInfo(CFTypeRef texture) {
SkASSERT(texture);
id<MTLTexture> mtlTex = (id<MTLTexture>)texture;
fSampleCount = mtlTex.sampleCount;
fMipmapped = mtlTex.mipmapLevelCount > 1 ? Mipmapped::kYes : Mipmapped::kNo;
fFormat = mtlTex.pixelFormat;
fUsage = mtlTex.usage;
fStorageMode = mtlTex.storageMode;
fFramebufferOnly = mtlTex.framebufferOnly;
}
TextureFormat MtlTextureInfo::viewFormat() const {
return MTLPixelFormatToTextureFormat(fFormat);
}
SkString MtlTextureInfo::toBackendString() const {
return SkStringPrintf("usage=0x%04X,storageMode=%u,framebufferOnly=%d",
(uint32_t)fUsage,
(uint32_t)fStorageMode,
fFramebufferOnly);
}
bool MtlTextureInfo::isCompatible(const TextureInfo& that, bool requireExact) const {
const auto& mt = TextureInfoPriv::Get<MtlTextureInfo>(that);
// The usages may match or the usage passed in may be a superset of the usage stored within.
const auto usageMask = requireExact ? mt.fUsage : fUsage;
return fFormat == mt.fFormat &&
fStorageMode == mt.fStorageMode &&
fFramebufferOnly == mt.fFramebufferOnly &&
(usageMask & mt.fUsage) == fUsage;
}
bool MtlTextureInfo::serialize(SkWStream* stream) const {
SkASSERT(fFormat < (1u << 24));
SkASSERT(fUsage < (1u << 5));
SkASSERT(fStorageMode < (1u << 2));
SkASSERT(static_cast<uint32_t>(fFramebufferOnly) < (1u << 1));
// TODO(robertphillips): not densely packed (see above asserts)
if (!stream->write32(static_cast<uint32_t>(fFormat))) { return false; }
if (!stream->write16(static_cast<uint16_t>(fUsage))) { return false; }
if (!stream->write8(static_cast<uint8_t>(fStorageMode))) { return false; }
if (!stream->write8(static_cast<uint8_t>(fFramebufferOnly))) { return false; }
return true;
}
bool MtlTextureInfo::deserialize(SkStream* stream) {
uint32_t tmp32;
if (!stream->readU32(&tmp32)) {
return false;
}
// TODO(robertphillips): add validity checks to deserialized values
fFormat = static_cast<MTLPixelFormat>(tmp32);
uint16_t tmp16;
if (!stream->readU16(&tmp16)) {
return false;
}
fUsage = static_cast<MTLTextureUsage>(tmp16);
uint8_t tmp8;
if (!stream->readU8(&tmp8)) {
return false;
}
fStorageMode = static_cast<MTLStorageMode>(tmp8);
if (!stream->readU8(&tmp8)) {
return false;
}
fFramebufferOnly = SkToBool(tmp8);
return true;
}
namespace TextureInfos {
skgpu::graphite::TextureInfo MakeMetal(CFTypeRef mtlTexture) {
return MakeMetal(MtlTextureInfo(mtlTexture));
}
skgpu::graphite::TextureInfo MakeMetal(const MtlTextureInfo& mtlInfo) {
return TextureInfoPriv::Make(mtlInfo);
}
bool GetMtlTextureInfo(const TextureInfo& info, MtlTextureInfo* out) {
return TextureInfoPriv::Copy(info, out);
}
} // namespace TextureInfos
} // namespace skgpu::graphite