/* * Copyright 2017 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef GrBackendSurface_DEFINED #define GrBackendSurface_DEFINED #include "include/core/SkRefCnt.h" #include "include/core/SkSize.h" #include "include/gpu/GpuTypes.h" #include "include/gpu/ganesh/GrTypes.h" #include "include/gpu/ganesh/mock/GrMockTypes.h" #include "include/private/base/SkAPI.h" #include "include/private/base/SkAnySubclass.h" #include "include/private/base/SkDebug.h" #include "include/private/gpu/ganesh/GrTypesPriv.h" enum class SkTextureCompressionType; class GrBackendFormatData; class GrBackendTextureData; class GrBackendRenderTargetData; namespace skgpu { class MutableTextureState; } #ifdef SK_DIRECT3D #include "include/private/gpu/ganesh/GrD3DTypesMinimal.h" class GrD3DResourceState; #endif #if defined(SK_DEBUG) || defined(GPU_TEST_UTILS) class SkString; #endif #include #include #include #include class SK_API GrBackendFormat { public: // Creates an invalid backend format. GrBackendFormat(); GrBackendFormat(const GrBackendFormat&); GrBackendFormat& operator=(const GrBackendFormat&); ~GrBackendFormat(); #ifdef SK_DIRECT3D static GrBackendFormat MakeDxgi(DXGI_FORMAT format) { return GrBackendFormat(format); } #endif static GrBackendFormat MakeMock(GrColorType colorType, SkTextureCompressionType compression, bool isStencilFormat = false); bool operator==(const GrBackendFormat& that) const; bool operator!=(const GrBackendFormat& that) const { return !(*this == that); } GrBackendApi backend() const { return fBackend; } GrTextureType textureType() const { return fTextureType; } /** * Gets the channels present in the format as a bitfield of SkColorChannelFlag values. * Luminance channels are reported as kGray_SkColorChannelFlag. */ uint32_t channelMask() const; GrColorFormatDesc desc() const; #ifdef SK_DIRECT3D /** * If the backend API is Direct3D this gets the format as a DXGI_FORMAT and returns true. * Otherwise, returns false. */ bool asDxgiFormat(DXGI_FORMAT*) const; #endif /** * If the backend API is not Mock these three calls will return kUnknown, kNone or false, * respectively. Otherwise, only one of the following can be true. The GrColorType is not * kUnknown, the compression type is not kNone, or this is a mock stencil format. */ GrColorType asMockColorType() const; SkTextureCompressionType asMockCompressionType() const; bool isMockStencilFormat() const; // If possible, copies the GrBackendFormat and forces the texture type to be Texture2D. If the // GrBackendFormat was for Vulkan and it originally had a skgpu::VulkanYcbcrConversionInfo, // we will remove the conversion and set the format to be VK_FORMAT_R8G8B8A8_UNORM. GrBackendFormat makeTexture2D() const; // Returns true if the backend format has been initialized. bool isValid() const { return fValid; } #if defined(SK_DEBUG) || defined(GPU_TEST_UTILS) SkString toStr() const; #endif private: // Size determined by looking at the GrBackendFormatData subclasses, then guessing-and-checking. // Compiler will complain if this is too small - in that case, just increase the number. inline constexpr static size_t kMaxSubclassSize = 80; using AnyFormatData = SkAnySubclass; friend class GrBackendSurfacePriv; friend class GrBackendFormatData; // Used by internal factories. Should not be used externally. Use factories like // GrBackendFormats::MakeGL instead. template GrBackendFormat(GrTextureType textureType, GrBackendApi api, const FormatData& formatData) : fBackend(api), fValid(true), fTextureType(textureType) { fFormatData.emplace(formatData); } #ifdef SK_DIRECT3D GrBackendFormat(DXGI_FORMAT dxgiFormat); #endif GrBackendFormat(GrColorType, SkTextureCompressionType, bool isStencilFormat); #ifdef SK_DEBUG bool validateMock() const; #endif GrBackendApi fBackend = GrBackendApi::kMock; bool fValid = false; AnyFormatData fFormatData; union { #ifdef SK_DIRECT3D DXGI_FORMAT fDxgiFormat; #endif struct { GrColorType fColorType; SkTextureCompressionType fCompressionType; bool fIsStencilFormat; } fMock; }; GrTextureType fTextureType = GrTextureType::kNone; }; class SK_API GrBackendTexture { public: // Creates an invalid backend texture. GrBackendTexture(); #ifdef SK_DIRECT3D GrBackendTexture(int width, int height, const GrD3DTextureResourceInfo& d3dInfo, std::string_view label = {}); #endif GrBackendTexture(int width, int height, skgpu::Mipmapped, const GrMockTextureInfo& mockInfo, std::string_view label = {}); GrBackendTexture(const GrBackendTexture& that); ~GrBackendTexture(); GrBackendTexture& operator=(const GrBackendTexture& that); SkISize dimensions() const { return {fWidth, fHeight}; } int width() const { return fWidth; } int height() const { return fHeight; } std::string_view getLabel() const { return fLabel; } skgpu::Mipmapped mipmapped() const { return fMipmapped; } bool hasMipmaps() const { return fMipmapped == skgpu::Mipmapped::kYes; } GrBackendApi backend() const {return fBackend; } GrTextureType textureType() const { return fTextureType; } #ifdef SK_DIRECT3D // If the backend API is Direct3D, copies a snapshot of the GrD3DTextureResourceInfo struct into // the passed in pointer and returns true. This snapshot will set the fResourceState to the // current resource state. Otherwise returns false if the backend API is not D3D. bool getD3DTextureResourceInfo(GrD3DTextureResourceInfo*) const; // Anytime the client changes the D3D12_RESOURCE_STATES of the D3D12_RESOURCE captured by this // GrBackendTexture, they must call this function to notify Skia of the changed layout. void setD3DResourceState(GrD3DResourceStateEnum); #endif // Get the GrBackendFormat for this texture (or an invalid format if this is not valid). GrBackendFormat getBackendFormat() const; // If the backend API is Mock, copies a snapshot of the GrMockTextureInfo struct into the passed // in pointer and returns true. Otherwise returns false if the backend API is not Mock. bool getMockTextureInfo(GrMockTextureInfo*) const; // If the client changes any of the mutable backend of the GrBackendTexture they should call // this function to inform Skia that those values have changed. The backend API specific state // that can be set from this function are: // // Vulkan: VkImageLayout and QueueFamilyIndex void setMutableState(const skgpu::MutableTextureState&); // Returns true if we are working with protected content. bool isProtected() const; // Returns true if the backend texture has been initialized. bool isValid() const { return fIsValid; } // Returns true if both textures are valid and refer to the same API texture. bool isSameTexture(const GrBackendTexture&); #if defined(GPU_TEST_UTILS) static bool TestingOnly_Equals(const GrBackendTexture&, const GrBackendTexture&); #endif private: // Size determined by looking at the GrBackendTextureData subclasses, then guessing-and-checking. // Compiler will complain if this is too small - in that case, just increase the number. inline constexpr static size_t kMaxSubclassSize = 176; using AnyTextureData = SkAnySubclass; friend class GrBackendSurfacePriv; friend class GrBackendTextureData; // Used by internal factories. Should not be used externally. Use factories like // GrBackendTextures::MakeGL instead. template GrBackendTexture(int width, int height, std::string_view label, skgpu::Mipmapped mipped, GrBackendApi backend, GrTextureType texture, const TextureData& textureData) : fIsValid(true) , fWidth(width) , fHeight(height) , fLabel(label) , fMipmapped(mipped) , fBackend(backend) , fTextureType(texture) { fTextureData.emplace(textureData); } friend class GrVkGpu; // for getMutableState sk_sp getMutableState() const; #ifdef SK_DIRECT3D friend class GrD3DTexture; friend class GrD3DGpu; // for getGrD3DResourceState GrBackendTexture(int width, int height, const GrD3DTextureResourceInfo& vkInfo, sk_sp state, std::string_view label = {}); sk_sp getGrD3DResourceState() const; #endif // Free and release and resources being held by the GrBackendTexture. void cleanup(); bool fIsValid; int fWidth; //; friend class GrBackendSurfacePriv; friend class GrBackendRenderTargetData; // Used by internal factories. Should not be used externally. Use factories like // GrBackendRenderTargets::MakeGL instead. template GrBackendRenderTarget(int width, int height, int sampleCnt, int stencilBits, GrBackendApi backend, bool framebufferOnly, const RenderTargetData& rtData) : fIsValid(true) , fFramebufferOnly(framebufferOnly) , fWidth(width) , fHeight(height) , fSampleCnt(sampleCnt) , fStencilBits(stencilBits) , fBackend(backend) { fRTData.emplace(rtData); } friend class GrVkGpu; // for getMutableState sk_sp getMutableState() const; #ifdef SK_DIRECT3D friend class GrD3DGpu; friend class GrD3DRenderTarget; GrBackendRenderTarget(int width, int height, const GrD3DTextureResourceInfo& d3dInfo, sk_sp state); sk_sp getGrD3DResourceState() const; #endif // Free and release and resources being held by the GrBackendTexture. void cleanup(); bool fIsValid; bool fFramebufferOnly = false; int fWidth; //