1 /* 2 * Copyright 2017 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef GrBackendSurface_DEFINED 9 #define GrBackendSurface_DEFINED 10 11 #include "include/core/SkRefCnt.h" 12 #include "include/core/SkSize.h" 13 #include "include/gpu/GpuTypes.h" 14 #include "include/gpu/ganesh/GrTypes.h" 15 #include "include/gpu/ganesh/mock/GrMockTypes.h" 16 #include "include/private/base/SkAPI.h" 17 #include "include/private/base/SkAnySubclass.h" 18 #include "include/private/base/SkDebug.h" 19 #include "include/private/gpu/ganesh/GrTypesPriv.h" 20 21 enum class SkTextureCompressionType; 22 class GrBackendFormatData; 23 class GrBackendTextureData; 24 class GrBackendRenderTargetData; 25 26 namespace skgpu { 27 class MutableTextureState; 28 } 29 30 #ifdef SK_DIRECT3D 31 #include "include/private/gpu/ganesh/GrD3DTypesMinimal.h" 32 class GrD3DResourceState; 33 #endif 34 35 #if defined(SK_DEBUG) || defined(GPU_TEST_UTILS) 36 class SkString; 37 #endif 38 39 #include <cstddef> 40 #include <cstdint> 41 #include <string> 42 #include <string_view> 43 44 class SK_API GrBackendFormat { 45 public: 46 // Creates an invalid backend format. 47 GrBackendFormat(); 48 GrBackendFormat(const GrBackendFormat&); 49 GrBackendFormat& operator=(const GrBackendFormat&); 50 ~GrBackendFormat(); 51 52 #ifdef SK_DIRECT3D MakeDxgi(DXGI_FORMAT format)53 static GrBackendFormat MakeDxgi(DXGI_FORMAT format) { 54 return GrBackendFormat(format); 55 } 56 #endif 57 58 static GrBackendFormat MakeMock(GrColorType colorType, 59 SkTextureCompressionType compression, 60 bool isStencilFormat = false); 61 62 bool operator==(const GrBackendFormat& that) const; 63 bool operator!=(const GrBackendFormat& that) const { return !(*this == that); } 64 backend()65 GrBackendApi backend() const { return fBackend; } textureType()66 GrTextureType textureType() const { return fTextureType; } 67 68 /** 69 * Gets the channels present in the format as a bitfield of SkColorChannelFlag values. 70 * Luminance channels are reported as kGray_SkColorChannelFlag. 71 */ 72 uint32_t channelMask() const; 73 74 GrColorFormatDesc desc() const; 75 76 #ifdef SK_DIRECT3D 77 /** 78 * If the backend API is Direct3D this gets the format as a DXGI_FORMAT and returns true. 79 * Otherwise, returns false. 80 */ 81 bool asDxgiFormat(DXGI_FORMAT*) const; 82 #endif 83 84 /** 85 * If the backend API is not Mock these three calls will return kUnknown, kNone or false, 86 * respectively. Otherwise, only one of the following can be true. The GrColorType is not 87 * kUnknown, the compression type is not kNone, or this is a mock stencil format. 88 */ 89 GrColorType asMockColorType() const; 90 SkTextureCompressionType asMockCompressionType() const; 91 bool isMockStencilFormat() const; 92 93 // If possible, copies the GrBackendFormat and forces the texture type to be Texture2D. If the 94 // GrBackendFormat was for Vulkan and it originally had a skgpu::VulkanYcbcrConversionInfo, 95 // we will remove the conversion and set the format to be VK_FORMAT_R8G8B8A8_UNORM. 96 GrBackendFormat makeTexture2D() const; 97 98 // Returns true if the backend format has been initialized. isValid()99 bool isValid() const { return fValid; } 100 101 #if defined(SK_DEBUG) || defined(GPU_TEST_UTILS) 102 SkString toStr() const; 103 #endif 104 105 private: 106 // Size determined by looking at the GrBackendFormatData subclasses, then guessing-and-checking. 107 // Compiler will complain if this is too small - in that case, just increase the number. 108 inline constexpr static size_t kMaxSubclassSize = 80; 109 using AnyFormatData = SkAnySubclass<GrBackendFormatData, kMaxSubclassSize>; 110 111 friend class GrBackendSurfacePriv; 112 friend class GrBackendFormatData; 113 114 // Used by internal factories. Should not be used externally. Use factories like 115 // GrBackendFormats::MakeGL instead. 116 template <typename FormatData> GrBackendFormat(GrTextureType textureType,GrBackendApi api,const FormatData & formatData)117 GrBackendFormat(GrTextureType textureType, GrBackendApi api, const FormatData& formatData) 118 : fBackend(api), fValid(true), fTextureType(textureType) { 119 fFormatData.emplace<FormatData>(formatData); 120 } 121 122 #ifdef SK_DIRECT3D 123 GrBackendFormat(DXGI_FORMAT dxgiFormat); 124 #endif 125 126 GrBackendFormat(GrColorType, SkTextureCompressionType, bool isStencilFormat); 127 128 #ifdef SK_DEBUG 129 bool validateMock() const; 130 #endif 131 132 GrBackendApi fBackend = GrBackendApi::kMock; 133 bool fValid = false; 134 AnyFormatData fFormatData; 135 136 union { 137 #ifdef SK_DIRECT3D 138 DXGI_FORMAT fDxgiFormat; 139 #endif 140 struct { 141 GrColorType fColorType; 142 SkTextureCompressionType fCompressionType; 143 bool fIsStencilFormat; 144 } fMock; 145 }; 146 GrTextureType fTextureType = GrTextureType::kNone; 147 }; 148 149 class SK_API GrBackendTexture { 150 public: 151 // Creates an invalid backend texture. 152 GrBackendTexture(); 153 154 #ifdef SK_DIRECT3D 155 GrBackendTexture(int width, 156 int height, 157 const GrD3DTextureResourceInfo& d3dInfo, 158 std::string_view label = {}); 159 #endif 160 161 GrBackendTexture(int width, 162 int height, 163 skgpu::Mipmapped, 164 const GrMockTextureInfo& mockInfo, 165 std::string_view label = {}); 166 167 GrBackendTexture(const GrBackendTexture& that); 168 169 ~GrBackendTexture(); 170 171 GrBackendTexture& operator=(const GrBackendTexture& that); 172 dimensions()173 SkISize dimensions() const { return {fWidth, fHeight}; } width()174 int width() const { return fWidth; } height()175 int height() const { return fHeight; } getLabel()176 std::string_view getLabel() const { return fLabel; } mipmapped()177 skgpu::Mipmapped mipmapped() const { return fMipmapped; } hasMipmaps()178 bool hasMipmaps() const { return fMipmapped == skgpu::Mipmapped::kYes; } backend()179 GrBackendApi backend() const {return fBackend; } textureType()180 GrTextureType textureType() const { return fTextureType; } 181 182 #ifdef SK_DIRECT3D 183 // If the backend API is Direct3D, copies a snapshot of the GrD3DTextureResourceInfo struct into 184 // the passed in pointer and returns true. This snapshot will set the fResourceState to the 185 // current resource state. Otherwise returns false if the backend API is not D3D. 186 bool getD3DTextureResourceInfo(GrD3DTextureResourceInfo*) const; 187 188 // Anytime the client changes the D3D12_RESOURCE_STATES of the D3D12_RESOURCE captured by this 189 // GrBackendTexture, they must call this function to notify Skia of the changed layout. 190 void setD3DResourceState(GrD3DResourceStateEnum); 191 #endif 192 193 // Get the GrBackendFormat for this texture (or an invalid format if this is not valid). 194 GrBackendFormat getBackendFormat() const; 195 196 // If the backend API is Mock, copies a snapshot of the GrMockTextureInfo struct into the passed 197 // in pointer and returns true. Otherwise returns false if the backend API is not Mock. 198 bool getMockTextureInfo(GrMockTextureInfo*) const; 199 200 // If the client changes any of the mutable backend of the GrBackendTexture they should call 201 // this function to inform Skia that those values have changed. The backend API specific state 202 // that can be set from this function are: 203 // 204 // Vulkan: VkImageLayout and QueueFamilyIndex 205 void setMutableState(const skgpu::MutableTextureState&); 206 207 // Returns true if we are working with protected content. 208 bool isProtected() const; 209 210 // Returns true if the backend texture has been initialized. isValid()211 bool isValid() const { return fIsValid; } 212 213 // Returns true if both textures are valid and refer to the same API texture. 214 bool isSameTexture(const GrBackendTexture&); 215 216 #if defined(GPU_TEST_UTILS) 217 static bool TestingOnly_Equals(const GrBackendTexture&, const GrBackendTexture&); 218 #endif 219 220 private: 221 // Size determined by looking at the GrBackendTextureData subclasses, then guessing-and-checking. 222 // Compiler will complain if this is too small - in that case, just increase the number. 223 inline constexpr static size_t kMaxSubclassSize = 176; 224 using AnyTextureData = SkAnySubclass<GrBackendTextureData, kMaxSubclassSize>; 225 226 friend class GrBackendSurfacePriv; 227 friend class GrBackendTextureData; 228 229 // Used by internal factories. Should not be used externally. Use factories like 230 // GrBackendTextures::MakeGL instead. 231 template <typename TextureData> GrBackendTexture(int width,int height,std::string_view label,skgpu::Mipmapped mipped,GrBackendApi backend,GrTextureType texture,const TextureData & textureData)232 GrBackendTexture(int width, 233 int height, 234 std::string_view label, 235 skgpu::Mipmapped mipped, 236 GrBackendApi backend, 237 GrTextureType texture, 238 const TextureData& textureData) 239 : fIsValid(true) 240 , fWidth(width) 241 , fHeight(height) 242 , fLabel(label) 243 , fMipmapped(mipped) 244 , fBackend(backend) 245 , fTextureType(texture) { 246 fTextureData.emplace<TextureData>(textureData); 247 } 248 249 friend class GrVkGpu; // for getMutableState 250 sk_sp<skgpu::MutableTextureState> getMutableState() const; 251 252 #ifdef SK_DIRECT3D 253 friend class GrD3DTexture; 254 friend class GrD3DGpu; // for getGrD3DResourceState 255 GrBackendTexture(int width, 256 int height, 257 const GrD3DTextureResourceInfo& vkInfo, 258 sk_sp<GrD3DResourceState> state, 259 std::string_view label = {}); 260 sk_sp<GrD3DResourceState> getGrD3DResourceState() const; 261 #endif 262 263 // Free and release and resources being held by the GrBackendTexture. 264 void cleanup(); 265 266 bool fIsValid; 267 int fWidth; //<! width in pixels 268 int fHeight; //<! height in pixels 269 const std::string fLabel; 270 skgpu::Mipmapped fMipmapped; 271 GrBackendApi fBackend; 272 GrTextureType fTextureType; 273 AnyTextureData fTextureData; 274 275 union { 276 GrMockTextureInfo fMockInfo; 277 #ifdef SK_DIRECT3D 278 GrD3DBackendSurfaceInfo fD3DInfo; 279 #endif 280 }; 281 }; 282 283 class SK_API GrBackendRenderTarget { 284 public: 285 // Creates an invalid backend texture. 286 GrBackendRenderTarget(); 287 288 #ifdef SK_DIRECT3D 289 GrBackendRenderTarget(int width, 290 int height, 291 const GrD3DTextureResourceInfo& d3dInfo); 292 #endif 293 294 GrBackendRenderTarget(int width, 295 int height, 296 int sampleCnt, 297 int stencilBits, 298 const GrMockRenderTargetInfo& mockInfo); 299 300 ~GrBackendRenderTarget(); 301 302 GrBackendRenderTarget(const GrBackendRenderTarget& that); 303 GrBackendRenderTarget& operator=(const GrBackendRenderTarget&); 304 dimensions()305 SkISize dimensions() const { return {fWidth, fHeight}; } width()306 int width() const { return fWidth; } height()307 int height() const { return fHeight; } sampleCnt()308 int sampleCnt() const { return fSampleCnt; } stencilBits()309 int stencilBits() const { return fStencilBits; } backend()310 GrBackendApi backend() const {return fBackend; } isFramebufferOnly()311 bool isFramebufferOnly() const { return fFramebufferOnly; } 312 313 #ifdef SK_DIRECT3D 314 // If the backend API is Direct3D, copies a snapshot of the GrMtlTextureInfo struct into the 315 // passed in pointer and returns true. Otherwise returns false if the backend API is not D3D. 316 bool getD3DTextureResourceInfo(GrD3DTextureResourceInfo*) const; 317 318 // Anytime the client changes the D3D12_RESOURCE_STATES of the D3D12_RESOURCE captured by this 319 // GrBackendTexture, they must call this function to notify Skia of the changed layout. 320 void setD3DResourceState(GrD3DResourceStateEnum); 321 #endif 322 323 // Get the GrBackendFormat for this render target (or an invalid format if this is not valid). 324 GrBackendFormat getBackendFormat() const; 325 326 // If the backend API is Mock, copies a snapshot of the GrMockTextureInfo struct into the passed 327 // in pointer and returns true. Otherwise returns false if the backend API is not Mock. 328 bool getMockRenderTargetInfo(GrMockRenderTargetInfo*) const; 329 330 // If the client changes any of the mutable backend of the GrBackendTexture they should call 331 // this function to inform Skia that those values have changed. The backend API specific state 332 // that can be set from this function are: 333 // 334 // Vulkan: VkImageLayout and QueueFamilyIndex 335 void setMutableState(const skgpu::MutableTextureState&); 336 337 // Returns true if we are working with protected content. 338 bool isProtected() const; 339 340 // Returns true if the backend texture has been initialized. isValid()341 bool isValid() const { return fIsValid; } 342 343 #if defined(GPU_TEST_UTILS) 344 static bool TestingOnly_Equals(const GrBackendRenderTarget&, const GrBackendRenderTarget&); 345 #endif 346 347 private: 348 // Size determined by looking at the GrBackendRenderTargetData subclasses, then 349 // guessing-and-checking. Compiler will complain if this is too small - in that case, just 350 // increase the number. 351 inline constexpr static size_t kMaxSubclassSize = 176; 352 using AnyRenderTargetData = SkAnySubclass<GrBackendRenderTargetData, kMaxSubclassSize>; 353 354 friend class GrBackendSurfacePriv; 355 friend class GrBackendRenderTargetData; 356 357 // Used by internal factories. Should not be used externally. Use factories like 358 // GrBackendRenderTargets::MakeGL instead. 359 template <typename RenderTargetData> GrBackendRenderTarget(int width,int height,int sampleCnt,int stencilBits,GrBackendApi backend,bool framebufferOnly,const RenderTargetData & rtData)360 GrBackendRenderTarget(int width, 361 int height, 362 int sampleCnt, 363 int stencilBits, 364 GrBackendApi backend, 365 bool framebufferOnly, 366 const RenderTargetData& rtData) 367 : fIsValid(true) 368 , fFramebufferOnly(framebufferOnly) 369 , fWidth(width) 370 , fHeight(height) 371 , fSampleCnt(sampleCnt) 372 , fStencilBits(stencilBits) 373 , fBackend(backend) { 374 fRTData.emplace<RenderTargetData>(rtData); 375 } 376 377 friend class GrVkGpu; // for getMutableState 378 sk_sp<skgpu::MutableTextureState> getMutableState() const; 379 380 #ifdef SK_DIRECT3D 381 friend class GrD3DGpu; 382 friend class GrD3DRenderTarget; 383 GrBackendRenderTarget(int width, 384 int height, 385 const GrD3DTextureResourceInfo& d3dInfo, 386 sk_sp<GrD3DResourceState> state); 387 sk_sp<GrD3DResourceState> getGrD3DResourceState() const; 388 #endif 389 390 // Free and release and resources being held by the GrBackendTexture. 391 void cleanup(); 392 393 bool fIsValid; 394 bool fFramebufferOnly = false; 395 int fWidth; //<! width in pixels 396 int fHeight; //<! height in pixels 397 398 int fSampleCnt; 399 int fStencilBits; 400 401 GrBackendApi fBackend; 402 AnyRenderTargetData fRTData; 403 404 union { 405 GrMockRenderTargetInfo fMockInfo; 406 #ifdef SK_DIRECT3D 407 GrD3DBackendSurfaceInfo fD3DInfo; 408 #endif 409 }; 410 }; 411 412 #endif 413