1 /* 2 * Copyright 2011 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 GrGpu_DEFINED 9 #define GrGpu_DEFINED 10 11 #include "GrCaps.h" 12 #include "GrGpuCommandBuffer.h" 13 #include "GrProgramDesc.h" 14 #include "GrSwizzle.h" 15 #include "GrAllocator.h" 16 #include "GrTextureProducer.h" 17 #include "GrTypes.h" 18 #include "GrXferProcessor.h" 19 #include "SkPath.h" 20 #include "SkTArray.h" 21 #include <map> 22 23 class GrBackendRenderTarget; 24 class GrBackendSemaphore; 25 class GrBuffer; 26 class GrContext; 27 struct GrContextOptions; 28 class GrGLContext; 29 class GrMesh; 30 class GrPath; 31 class GrPathRenderer; 32 class GrPathRendererChain; 33 class GrPathRendering; 34 class GrPipeline; 35 class GrPrimitiveProcessor; 36 class GrRenderTarget; 37 class GrSemaphore; 38 class GrStencilAttachment; 39 class GrStencilSettings; 40 class GrSurface; 41 class GrTexture; 42 class SkJSONWriter; 43 44 class GrGpu : public SkRefCnt { 45 public: 46 GrGpu(GrContext* context); 47 ~GrGpu() override; 48 49 GrContext* getContext() { return fContext; } 50 const GrContext* getContext() const { return fContext; } 51 52 /** 53 * Gets the capabilities of the draw target. 54 */ 55 const GrCaps* caps() const { return fCaps.get(); } 56 sk_sp<const GrCaps> refCaps() const { return fCaps; } 57 58 GrPathRendering* pathRendering() { return fPathRendering.get(); } 59 60 enum class DisconnectType { 61 // No cleanup should be attempted, immediately cease making backend API calls 62 kAbandon, 63 // Free allocated resources (not known by GrResourceCache) before returning and 64 // ensure no backend backend 3D API calls will be made after disconnect() returns. 65 kCleanup, 66 }; 67 68 // Called by GrContext when the underlying backend context is already or will be destroyed 69 // before GrContext. 70 virtual void disconnect(DisconnectType); 71 72 /** 73 * The GrGpu object normally assumes that no outsider is setting state 74 * within the underlying 3D API's context/device/whatever. This call informs 75 * the GrGpu that the state was modified and it shouldn't make assumptions 76 * about the state. 77 */ 78 void markContextDirty(uint32_t state = kAll_GrBackendState) { fResetBits |= state; } 79 80 /** 81 * Creates a texture object. If kRenderTarget_GrSurfaceFlag the texture can 82 * be used as a render target by calling GrTexture::asRenderTarget(). Not all 83 * pixel configs can be used as render targets. Support for configs as textures 84 * or render targets can be checked using GrCaps. 85 * 86 * @param desc describes the texture to be created. 87 * @param budgeted does this texture count against the resource cache budget? 88 * @param texels array of mipmap levels containing texel data to load. 89 * Each level begins with full-size palette data for paletted textures. 90 * It contains width*height texels. If there is only one 91 * element and it contains nullptr fPixels, texture data is 92 * uninitialized. 93 * @param mipLevelCount the number of levels in 'texels' 94 * @return The texture object if successful, otherwise nullptr. 95 */ 96 sk_sp<GrTexture> createTexture(const GrSurfaceDesc&, SkBudgeted, const GrMipLevel texels[], 97 int mipLevelCount); 98 99 /** 100 * Simplified createTexture() interface for when there is no initial texel data to upload. 101 */ 102 sk_sp<GrTexture> createTexture(const GrSurfaceDesc& desc, SkBudgeted); 103 104 /** 105 * Implements GrResourceProvider::wrapBackendTexture 106 */ 107 sk_sp<GrTexture> wrapBackendTexture(const GrBackendTexture&, GrWrapOwnership, GrWrapCacheable, 108 GrIOType); 109 110 /** 111 * Implements GrResourceProvider::wrapRenderableBackendTexture 112 */ 113 sk_sp<GrTexture> wrapRenderableBackendTexture(const GrBackendTexture&, int sampleCnt, 114 GrWrapOwnership, GrWrapCacheable); 115 116 /** 117 * Implements GrResourceProvider::wrapBackendRenderTarget 118 */ 119 sk_sp<GrRenderTarget> wrapBackendRenderTarget(const GrBackendRenderTarget&); 120 121 /** 122 * Implements GrResourceProvider::wrapBackendTextureAsRenderTarget 123 */ 124 sk_sp<GrRenderTarget> wrapBackendTextureAsRenderTarget(const GrBackendTexture&, 125 int sampleCnt); 126 127 /** 128 * Implements GrResourceProvider::wrapVulkanSecondaryCBAsRenderTarget 129 */ 130 sk_sp<GrRenderTarget> wrapVulkanSecondaryCBAsRenderTarget(const SkImageInfo&, 131 const GrVkDrawableInfo&); 132 133 /** 134 * Creates a buffer in GPU memory. For a client-side buffer use GrBuffer::CreateCPUBacked. 135 * 136 * @param size size of buffer to create. 137 * @param intendedType hint to the graphics subsystem about what the buffer will be used for. 138 * @param accessPattern hint to the graphics subsystem about how the data will be accessed. 139 * @param data optional data with which to initialize the buffer. 140 * 141 * @return the buffer if successful, otherwise nullptr. 142 */ 143 sk_sp<GrBuffer> createBuffer(size_t size, GrBufferType intendedType, 144 GrAccessPattern accessPattern, const void* data = nullptr); 145 146 /** 147 * Resolves MSAA. 148 */ 149 void resolveRenderTarget(GrRenderTarget*); 150 151 /** 152 * Uses the base of the texture to recompute the contents of the other levels. 153 */ 154 bool regenerateMipMapLevels(GrTexture*); 155 156 /** 157 * Reads a rectangle of pixels from a render target. No sRGB/linear conversions are performed. 158 * 159 * @param surface The surface to read from 160 * @param left left edge of the rectangle to read (inclusive) 161 * @param top top edge of the rectangle to read (inclusive) 162 * @param width width of rectangle to read in pixels. 163 * @param height height of rectangle to read in pixels. 164 * @param dstColorType the color type of the destination buffer. 165 * @param buffer memory to read the rectangle into. 166 * @param rowBytes the number of bytes between consecutive rows. Zero 167 * means rows are tightly packed. 168 * @param invertY buffer should be populated bottom-to-top as opposed 169 * to top-to-bottom (skia's usual order) 170 * 171 * @return true if the read succeeded, false if not. The read can fail 172 * because of a unsupported pixel config or because no render 173 * target is currently set. 174 */ 175 bool readPixels(GrSurface* surface, int left, int top, int width, int height, 176 GrColorType dstColorType, void* buffer, size_t rowBytes); 177 178 /** 179 * Updates the pixels in a rectangle of a surface. No sRGB/linear conversions are performed. 180 * 181 * @param surface The surface to write to. 182 * @param left left edge of the rectangle to write (inclusive) 183 * @param top top edge of the rectangle to write (inclusive) 184 * @param width width of rectangle to write in pixels. 185 * @param height height of rectangle to write in pixels. 186 * @param srcColorType the color type of the source buffer. 187 * @param texels array of mipmap levels containing texture data 188 * @param mipLevelCount number of levels in 'texels' 189 */ 190 bool writePixels(GrSurface* surface, int left, int top, int width, int height, 191 GrColorType srcColorType, const GrMipLevel texels[], int mipLevelCount); 192 193 /** 194 * Helper for the case of a single level. 195 */ 196 bool writePixels(GrSurface* surface, int left, int top, int width, int height, 197 GrColorType srcColorType, const void* buffer, size_t rowBytes) { 198 GrMipLevel mipLevel = {buffer, rowBytes}; 199 return this->writePixels(surface, left, top, width, height, srcColorType, &mipLevel, 1); 200 } 201 202 /** 203 * Updates the pixels in a rectangle of a texture using a buffer 204 * 205 * There are a couple of assumptions here. First, we only update the top miplevel. 206 * And second, that any y flip needed has already been done in the buffer. 207 * 208 * @param texture The texture to write to. 209 * @param left left edge of the rectangle to write (inclusive) 210 * @param top top edge of the rectangle to write (inclusive) 211 * @param width width of rectangle to write in pixels. 212 * @param height height of rectangle to write in pixels. 213 * @param bufferColorType the color type of the transfer buffer's pixel data 214 * @param transferBuffer GrBuffer to read pixels from (type must be "kXferCpuToGpu") 215 * @param offset offset from the start of the buffer 216 * @param rowBytes number of bytes between consecutive rows in the buffer. Zero 217 * means rows are tightly packed. 218 */ 219 bool transferPixels(GrTexture* texture, int left, int top, int width, int height, 220 GrColorType bufferColorType, GrBuffer* transferBuffer, size_t offset, 221 size_t rowBytes); 222 223 // After the client interacts directly with the 3D context state the GrGpu 224 // must resync its internal state and assumptions about 3D context state. 225 // Each time this occurs the GrGpu bumps a timestamp. 226 // state of the 3D context 227 // At 10 resets / frame and 60fps a 64bit timestamp will overflow in about 228 // a billion years. 229 typedef uint64_t ResetTimestamp; 230 231 // This timestamp is always older than the current timestamp 232 static const ResetTimestamp kExpiredTimestamp = 0; 233 // Returns a timestamp based on the number of times the context was reset. 234 // This timestamp can be used to lazily detect when cached 3D context state 235 // is dirty. 236 ResetTimestamp getResetTimestamp() const { return fResetTimestamp; } 237 238 // Called to perform a surface to surface copy. Fallbacks to issuing a draw from the src to dst 239 // take place at the GrOpList level and this function implement faster copy paths. The rect 240 // and point are pre-clipped. The src rect and implied dst rect are guaranteed to be within the 241 // src/dst bounds and non-empty. If canDiscardOutsideDstRect is set to true then we don't need 242 // to preserve any data on the dst surface outside of the copy. 243 bool copySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin, 244 GrSurface* src, GrSurfaceOrigin srcOrigin, 245 const SkIRect& srcRect, 246 const SkIPoint& dstPoint, 247 bool canDiscardOutsideDstRect = false); 248 249 // Returns a GrGpuRTCommandBuffer which GrOpLists send draw commands to instead of directly 250 // to the Gpu object. The 'bounds' rect is the content rect of the destination. 251 virtual GrGpuRTCommandBuffer* getCommandBuffer( 252 GrRenderTarget*, GrSurfaceOrigin, const SkRect& bounds, 253 const GrGpuRTCommandBuffer::LoadAndStoreInfo&, 254 const GrGpuRTCommandBuffer::StencilLoadAndStoreInfo&) = 0; 255 256 // Returns a GrGpuTextureCommandBuffer which GrOpLists send texture commands to instead of 257 // directly to the Gpu object. 258 virtual GrGpuTextureCommandBuffer* getCommandBuffer(GrTexture*, GrSurfaceOrigin) = 0; 259 260 // Called by GrDrawingManager when flushing. 261 // Provides a hook for post-flush actions (e.g. Vulkan command buffer submits). This will also 262 // insert any numSemaphore semaphores on the gpu and set the backendSemaphores to match the 263 // inserted semaphores. 264 GrSemaphoresSubmitted finishFlush(int numSemaphores, GrBackendSemaphore backendSemaphores[]); 265 266 virtual void submit(GrGpuCommandBuffer*) = 0; 267 268 virtual GrFence SK_WARN_UNUSED_RESULT insertFence() = 0; 269 virtual bool waitFence(GrFence, uint64_t timeout = 1000) = 0; 270 virtual void deleteFence(GrFence) const = 0; 271 272 virtual sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT makeSemaphore(bool isOwned = true) = 0; 273 virtual sk_sp<GrSemaphore> wrapBackendSemaphore(const GrBackendSemaphore& semaphore, 274 GrResourceProvider::SemaphoreWrapType wrapType, 275 GrWrapOwnership ownership) = 0; 276 virtual void insertSemaphore(sk_sp<GrSemaphore> semaphore) = 0; 277 virtual void waitSemaphore(sk_sp<GrSemaphore> semaphore) = 0; 278 279 /** 280 * Put this texture in a safe and known state for use across multiple GrContexts. Depending on 281 * the backend, this may return a GrSemaphore. If so, other contexts should wait on that 282 * semaphore before using this texture. 283 */ 284 virtual sk_sp<GrSemaphore> prepareTextureForCrossContextUsage(GrTexture*) = 0; 285 286 /////////////////////////////////////////////////////////////////////////// 287 // Debugging and Stats 288 289 class Stats { 290 public: 291 #if GR_GPU_STATS 292 Stats() { this->reset(); } 293 294 void reset() { 295 fRenderTargetBinds = 0; 296 fShaderCompilations = 0; 297 fTextureCreates = 0; 298 fTextureUploads = 0; 299 fTransfersToTexture = 0; 300 fStencilAttachmentCreates = 0; 301 fNumDraws = 0; 302 fNumFailedDraws = 0; 303 fNumFinishFlushes = 0; 304 } 305 306 int renderTargetBinds() const { return fRenderTargetBinds; } 307 void incRenderTargetBinds() { fRenderTargetBinds++; } 308 int shaderCompilations() const { return fShaderCompilations; } 309 void incShaderCompilations() { fShaderCompilations++; } 310 int textureCreates() const { return fTextureCreates; } 311 void incTextureCreates() { fTextureCreates++; } 312 int textureUploads() const { return fTextureUploads; } 313 void incTextureUploads() { fTextureUploads++; } 314 int transfersToTexture() const { return fTransfersToTexture; } 315 void incTransfersToTexture() { fTransfersToTexture++; } 316 void incStencilAttachmentCreates() { fStencilAttachmentCreates++; } 317 void incNumDraws() { fNumDraws++; } 318 void incNumFailedDraws() { ++fNumFailedDraws; } 319 void incNumFinishFlushes() { ++fNumFinishFlushes; } 320 void dump(SkString*); 321 void dumpKeyValuePairs(SkTArray<SkString>* keys, SkTArray<double>* values); 322 int numDraws() const { return fNumDraws; } 323 int numFailedDraws() const { return fNumFailedDraws; } 324 int numFinishFlushes() const { return fNumFinishFlushes; } 325 private: 326 int fRenderTargetBinds; 327 int fShaderCompilations; 328 int fTextureCreates; 329 int fTextureUploads; 330 int fTransfersToTexture; 331 int fStencilAttachmentCreates; 332 int fNumDraws; 333 int fNumFailedDraws; 334 int fNumFinishFlushes; 335 #else 336 void dump(SkString*) {} 337 void dumpKeyValuePairs(SkTArray<SkString>*, SkTArray<double>*) {} 338 void incRenderTargetBinds() {} 339 void incShaderCompilations() {} 340 void incTextureCreates() {} 341 void incTextureUploads() {} 342 void incTransfersToTexture() {} 343 void incStencilAttachmentCreates() {} 344 void incNumDraws() {} 345 void incNumFailedDraws() {} 346 void incNumFinishFlushes() {} 347 #endif 348 }; 349 350 Stats* stats() { return &fStats; } 351 void dumpJSON(SkJSONWriter*) const; 352 353 #if GR_TEST_UTILS 354 GrBackendTexture createTestingOnlyBackendTexture(const void* pixels, int w, int h, 355 SkColorType, bool isRenderTarget, 356 GrMipMapped, size_t rowBytes = 0); 357 358 /** Creates a texture directly in the backend API without wrapping it in a GrTexture. This is 359 only to be used for testing (particularly for testing the methods that import an externally 360 created texture into Skia. Must be matched with a call to deleteTestingOnlyTexture(). */ 361 virtual GrBackendTexture createTestingOnlyBackendTexture(const void* pixels, int w, int h, 362 GrColorType, bool isRenderTarget, 363 GrMipMapped, size_t rowBytes = 0) = 0; 364 365 /** Check a handle represents an actual texture in the backend API that has not been freed. */ 366 virtual bool isTestingOnlyBackendTexture(const GrBackendTexture&) const = 0; 367 /** 368 * Frees a texture created by createTestingOnlyBackendTexture(). If ownership of the backend 369 * texture has been transferred to a GrContext using adopt semantics this should not be called. 370 */ 371 virtual void deleteTestingOnlyBackendTexture(const GrBackendTexture&) = 0; 372 373 virtual GrBackendRenderTarget createTestingOnlyBackendRenderTarget(int w, int h, 374 GrColorType) = 0; 375 376 virtual void deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) = 0; 377 378 // This is only to be used in GL-specific tests. 379 virtual const GrGLContext* glContextForTesting() const { return nullptr; } 380 381 // This is only to be used by testing code 382 virtual void resetShaderCacheForTesting() const {} 383 384 /** 385 * Flushes all work to the gpu and forces the GPU to wait until all the gpu work has completed. 386 * This is for testing purposes only. 387 */ 388 virtual void testingOnly_flushGpuAndSync() = 0; 389 #endif 390 391 // width and height may be larger than rt (if underlying API allows it). 392 // Returns nullptr if compatible sb could not be created, otherwise the caller owns the ref on 393 // the GrStencilAttachment. 394 virtual GrStencilAttachment* createStencilAttachmentForRenderTarget(const GrRenderTarget*, 395 int width, 396 int height) = 0; 397 398 // Determines whether a texture will need to be rescaled in order to be used with the 399 // GrSamplerState. 400 static bool IsACopyNeededForRepeatWrapMode(const GrCaps*, GrTextureProxy* texProxy, 401 int width, int height, 402 GrSamplerState::Filter, 403 GrTextureProducer::CopyParams*, 404 SkScalar scaleAdjust[2]); 405 406 // Determines whether a texture will need to be copied because the draw requires mips but the 407 // texutre doesn't have any. This call should be only checked if IsACopyNeededForTextureParams 408 // fails. If the previous call succeeds, then a copy should be done using those params and the 409 // mip mapping requirements will be handled there. 410 static bool IsACopyNeededForMips(const GrCaps* caps, const GrTextureProxy* texProxy, 411 GrSamplerState::Filter filter, 412 GrTextureProducer::CopyParams* copyParams); 413 414 void handleDirtyContext() { 415 if (fResetBits) { 416 this->resetContext(); 417 } 418 } 419 420 /** 421 * Returns a key that represents the sampler that will be created for the passed in parameters. 422 * Currently this key is only used when we are building a vulkan pipeline with immutable 423 * samplers. In that case, we need our cache key to also contain this key. 424 * 425 * A return value of 0 indicates that the program/pipeline we are creating is not affected by 426 * the sampler. 427 */ 428 virtual uint32_t getExtraSamplerKeyForProgram(const GrSamplerState&, const GrBackendFormat&) { 429 return 0; 430 } 431 432 virtual void storeVkPipelineCacheData() {} 433 434 protected: 435 // Handles cases where a surface will be updated without a call to flushRenderTarget. 436 void didWriteToSurface(GrSurface* surface, GrSurfaceOrigin origin, const SkIRect* bounds, 437 uint32_t mipLevels = 1) const; 438 439 Stats fStats; 440 std::unique_ptr<GrPathRendering> fPathRendering; 441 // Subclass must initialize this in its constructor. 442 sk_sp<const GrCaps> fCaps; 443 444 typedef SkTArray<SkPoint, true> SamplePattern; 445 446 private: 447 // called when the 3D context state is unknown. Subclass should emit any 448 // assumed 3D context state and dirty any state cache. 449 virtual void onResetContext(uint32_t resetBits) = 0; 450 451 // Called before certain draws in order to guarantee coherent results from dst reads. 452 virtual void xferBarrier(GrRenderTarget*, GrXferBarrierType) = 0; 453 454 // overridden by backend-specific derived class to create objects. 455 // Texture size and sample size will have already been validated in base class before 456 // onCreateTexture is called. 457 virtual sk_sp<GrTexture> onCreateTexture(const GrSurfaceDesc&, SkBudgeted, 458 const GrMipLevel texels[], int mipLevelCount) = 0; 459 460 virtual sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&, GrWrapOwnership, 461 GrWrapCacheable, GrIOType) = 0; 462 virtual sk_sp<GrTexture> onWrapRenderableBackendTexture(const GrBackendTexture&, int sampleCnt, 463 GrWrapOwnership, GrWrapCacheable) = 0; 464 virtual sk_sp<GrRenderTarget> onWrapBackendRenderTarget(const GrBackendRenderTarget&) = 0; 465 virtual sk_sp<GrRenderTarget> onWrapBackendTextureAsRenderTarget(const GrBackendTexture&, 466 int sampleCnt) = 0; 467 virtual sk_sp<GrRenderTarget> onWrapVulkanSecondaryCBAsRenderTarget(const SkImageInfo&, 468 const GrVkDrawableInfo&); 469 470 virtual sk_sp<GrBuffer> onCreateBuffer(size_t size, GrBufferType intendedType, GrAccessPattern, 471 const void* data) = 0; 472 473 // overridden by backend-specific derived class to perform the surface read 474 virtual bool onReadPixels(GrSurface*, int left, int top, int width, int height, GrColorType, 475 void* buffer, size_t rowBytes) = 0; 476 477 // overridden by backend-specific derived class to perform the surface write 478 virtual bool onWritePixels(GrSurface*, int left, int top, int width, int height, GrColorType, 479 const GrMipLevel texels[], int mipLevelCount) = 0; 480 481 // overridden by backend-specific derived class to perform the texture transfer 482 virtual bool onTransferPixels(GrTexture*, int left, int top, int width, int height, 483 GrColorType colorType, GrBuffer* transferBuffer, size_t offset, 484 size_t rowBytes) = 0; 485 486 // overridden by backend-specific derived class to perform the resolve 487 virtual void onResolveRenderTarget(GrRenderTarget* target) = 0; 488 489 // overridden by backend specific derived class to perform mip map level regeneration. 490 virtual bool onRegenerateMipMapLevels(GrTexture*) = 0; 491 492 // overridden by backend specific derived class to perform the copy surface 493 virtual bool onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin, 494 GrSurface* src, GrSurfaceOrigin srcOrigin, 495 const SkIRect& srcRect, const SkIPoint& dstPoint, 496 bool canDiscardOutsideDstRect) = 0; 497 498 virtual void onFinishFlush(bool insertedSemaphores) = 0; 499 500 #ifdef SK_ENABLE_DUMP_GPU 501 virtual void onDumpJSON(SkJSONWriter*) const {} 502 #endif 503 504 void resetContext() { 505 this->onResetContext(fResetBits); 506 fResetBits = 0; 507 ++fResetTimestamp; 508 } 509 510 ResetTimestamp fResetTimestamp; 511 uint32_t fResetBits; 512 // The context owns us, not vice-versa, so this ptr is not ref'ed by Gpu. 513 GrContext* fContext; 514 515 friend class GrPathRendering; 516 typedef SkRefCnt INHERITED; 517 }; 518 519 #endif 520