blob: 3fa6d089c446dd258cadecc9b37b2dfec393b626 [file] [log] [blame]
/*
* Copyright 2021 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef skgpu_graphite_TextureInfo_DEFINED
#define skgpu_graphite_TextureInfo_DEFINED
#include "include/core/SkString.h"
#include "include/gpu/graphite/GraphiteTypes.h"
#include "include/private/base/SkAPI.h"
#include "include/private/base/SkAnySubclass.h"
struct SkISize;
namespace skgpu::graphite {
enum class TextureFormat : uint8_t;
/**
* TextureInfo is a backend-agnostic wrapper around the properties of a texture, sans dimensions.
* It is designed this way to be compilable w/o bringing in a specific backend's build files, and
* without requiring heap allocations of virtual types.
*/
class SK_API TextureInfo {
private:
class Data;
friend class MtlTextureInfo;
friend class DawnTextureInfo;
friend class VulkanTextureInfo;
// Size is the largest of the Data subclasses assuming a 64-bit compiler.
inline constexpr static size_t kMaxSubclassSize = 112;
using AnyTextureInfoData = SkAnySubclass<Data, kMaxSubclassSize>;
// Base properties for all backend-specific properties. Clients managing textures directly
// should use the public subclasses of Data directly, e.g. MtlTextureInfo/DawnTextureInfo.
//
// Each backend subclass must expose to TextureInfo[Priv]:
// static constexpr BackendApi kBackend;
// Protected isProtected() const;
// TextureFormat viewFormat() const;
class Data {
public:
virtual ~Data() = default;
Data(uint8_t sampleCount, skgpu::Mipmapped mipmapped)
: fSampleCount(sampleCount)
, fMipmapped(mipmapped) {}
Data() = default;
Data(const Data&) = default;
Data& operator=(const Data&) = default;
// NOTE: These fields are accessible via the backend-specific subclasses.
// Must be a valid SampleCount value, or TextureInfo creation will fail to wrap the backend
// specific data. This is not strongly typed so that it can be assigned directly from the
// backend GPU API's representation, which is often just an integer.
uint8_t fSampleCount = 1;
Mipmapped fMipmapped = Mipmapped::kNo;
private:
friend class TextureInfo;
friend class TextureInfoPriv;
virtual SkString toBackendString() const = 0;
virtual void copyTo(AnyTextureInfoData&) const = 0;
// Passed in TextureInfo will have data of the same backend type and subclass, and
// base properties of Data have already been checked for equality/compatibility.
virtual bool isCompatible(const TextureInfo& that, bool requireExact) const = 0;
};
public:
TextureInfo() = default;
~TextureInfo() = default;
TextureInfo(const TextureInfo&);
TextureInfo& operator=(const TextureInfo&);
bool operator==(const TextureInfo& that) const {
return this->isCompatible(that, /*requireExact=*/true);
}
bool operator!=(const TextureInfo& that) const { return !(*this == that); }
bool isValid() const { return fData.has_value(); }
BackendApi backend() const {
SkASSERT(fData.has_value() || fBackend == BackendApi::kUnsupported);
return fBackend;
}
Protected isProtected() const { return fProtected; }
SampleCount sampleCount() const {
return fData.has_value() ? static_cast<SampleCount>(fData->fSampleCount) : SampleCount::k1;
}
Mipmapped mipmapped() const {
return fData.has_value() ? fData->fMipmapped : Mipmapped::kNo;
}
// Return true if `that` describes a texture that is compatible with this info and can validly
// be used to fulfill a promise image that was created with this TextureInfo.
bool canBeFulfilledBy(const TextureInfo& that) const {
return this->isCompatible(that, /*requireExact=*/false);
}
// Return a string containing the full description of this TextureInfo.
SkString toString() const;
private:
friend class TextureInfoPriv;
template <typename BackendTextureData,
std::enable_if_t<std::is_base_of_v<Data, BackendTextureData>, bool> = true>
explicit TextureInfo(const BackendTextureData& data)
: fBackend(BackendTextureData::kBackend)
, fViewFormat(data.viewFormat())
, fProtected(data.isProtected()) {
// TextureInfoPriv should not construct a TextureInfo if `data` would fail this assert.
SkASSERT(data.fSampleCount == 1 || data.fSampleCount == 2 || data.fSampleCount == 4 ||
data.fSampleCount == 8 || data.fSampleCount == 16);
fData.emplace<BackendTextureData>(data);
}
bool isCompatible(const TextureInfo& that, bool requireExact) const;
skgpu::BackendApi fBackend = BackendApi::kUnsupported;
AnyTextureInfoData fData;
// Derived properties from the backend data, cached to avoid a virtual function call
TextureFormat fViewFormat;
Protected fProtected = Protected::kNo;
};
} // namespace skgpu::graphite
#endif // skgpu_graphite_TextureInfo_DEFINED