/* * Copyright 2011 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef GrGpu_DEFINED #define GrGpu_DEFINED #include "include/core/SkPath.h" #include "include/core/SkSpan.h" #include "include/core/SkSurface.h" #include "include/gpu/GrTypes.h" #include "include/private/SkTArray.h" #include "src/core/SkTInternalLList.h" #include "src/gpu/GrAttachment.h" #include "src/gpu/GrCaps.h" #include "src/gpu/GrOpsRenderPass.h" #include "src/gpu/GrPixmap.h" #include "src/gpu/GrSwizzle.h" #include "src/gpu/GrXferProcessor.h" class GrAttachment; class GrBackendRenderTarget; class GrBackendSemaphore; struct GrContextOptions; class GrDirectContext; class GrGpuBuffer; class GrGLContext; class GrPath; class GrPathRenderer; class GrPathRendererChain; class GrPipeline; class GrGeometryProcessor; class GrRenderTarget; class GrRingBuffer; class GrSemaphore; class GrStagingBufferManager; class GrStencilSettings; class GrSurface; class GrTexture; class GrThreadSafePipelineBuilder; class SkJSONWriter; namespace SkSL { class Compiler; } class GrGpu : public SkRefCnt { public: GrGpu(GrDirectContext* direct); ~GrGpu() override; GrDirectContext* getContext() { return fContext; } const GrDirectContext* getContext() const { return fContext; } /** * Gets the capabilities of the draw target. */ const GrCaps* caps() const { return fCaps.get(); } sk_sp refCaps() const { return fCaps; } virtual GrStagingBufferManager* stagingBufferManager() { return nullptr; } virtual GrRingBuffer* uniformsRingBuffer() { return nullptr; } SkSL::Compiler* shaderCompiler() const { return fCompiler.get(); } enum class DisconnectType { // No cleanup should be attempted, immediately cease making backend API calls kAbandon, // Free allocated resources (not known by GrResourceCache) before returning and // ensure no backend backend 3D API calls will be made after disconnect() returns. kCleanup, }; // Called by context when the underlying backend context is already or will be destroyed // before GrDirectContext. virtual void disconnect(DisconnectType); virtual GrThreadSafePipelineBuilder* pipelineBuilder() = 0; virtual sk_sp refPipelineBuilder() = 0; // Called by GrDirectContext::isContextLost. Returns true if the backend Gpu object has gotten // into an unrecoverable, lost state. virtual bool isDeviceLost() const { return false; } /** * The GrGpu object normally assumes that no outsider is setting state * within the underlying 3D API's context/device/whatever. This call informs * the GrGpu that the state was modified and it shouldn't make assumptions * about the state. */ void markContextDirty(uint32_t state = kAll_GrBackendState) { fResetBits |= state; } /** * Creates a texture object. If renderable is kYes then the returned texture can * be used as a render target by calling GrTexture::asRenderTarget(). Not all * pixel configs can be used as render targets. Support for configs as textures * or render targets can be checked using GrCaps. * * @param dimensions dimensions of the texture to be created. * @param format the format for the texture (not currently used). * @param renderable should the resulting texture be renderable * @param renderTargetSampleCnt The number of samples to use for rendering if renderable is * kYes. If renderable is kNo then this must be 1. * @param budgeted does this texture count against the resource cache budget? * @param isProtected should the texture be created as protected. * @param texels array of mipmap levels containing texel data to load. * If level i has pixels then it is assumed that its dimensions are * max(1, floor(dimensions.fWidth / 2)) by * max(1, floor(dimensions.fHeight / 2)). * If texels[i].fPixels == nullptr for all i <= mipLevelCount or * mipLevelCount is 0 then the texture's contents are uninitialized. * If a level has non-null pixels, its row bytes must be a multiple of the * config's bytes-per-pixel. The row bytes must be tight to the * level width if !caps->writePixelsRowBytesSupport(). * If mipLevelCount > 1 and texels[i].fPixels != nullptr for any i > 0 * then all levels must have non-null pixels. All levels must have * non-null pixels if GrCaps::createTextureMustSpecifyAllLevels() is true. * @param textureColorType The color type interpretation of the texture for the purpose of * of uploading texel data. * @param srcColorType The color type of data in texels[]. * @param texelLevelCount the number of levels in 'texels'. May be 0, 1, or * floor(max((log2(dimensions.fWidth), log2(dimensions.fHeight)))). It * must be the latter if GrCaps::createTextureMustSpecifyAllLevels() is * true. * @return The texture object if successful, otherwise nullptr. */ sk_sp createTexture(SkISize dimensions, const GrBackendFormat& format, GrRenderable renderable, int renderTargetSampleCnt, SkBudgeted budgeted, GrProtected isProtected, GrColorType textureColorType, GrColorType srcColorType, const GrMipLevel texels[], int texelLevelCount); /** * Simplified createTexture() interface for when there is no initial texel data to upload. */ sk_sp createTexture(SkISize dimensions, const GrBackendFormat& format, GrRenderable renderable, int renderTargetSampleCnt, GrMipmapped mipMapped, SkBudgeted budgeted, GrProtected isProtected); sk_sp createCompressedTexture(SkISize dimensions, const GrBackendFormat& format, SkBudgeted budgeted, GrMipmapped mipMapped, GrProtected isProtected, const void* data, size_t dataSize); /** * Implements GrResourceProvider::wrapBackendTexture */ sk_sp wrapBackendTexture(const GrBackendTexture&, GrWrapOwnership, GrWrapCacheable, GrIOType); sk_sp wrapCompressedBackendTexture(const GrBackendTexture&, GrWrapOwnership, GrWrapCacheable); /** * Implements GrResourceProvider::wrapRenderableBackendTexture */ sk_sp wrapRenderableBackendTexture(const GrBackendTexture&, int sampleCnt, GrWrapOwnership, GrWrapCacheable); /** * Implements GrResourceProvider::wrapBackendRenderTarget */ sk_sp wrapBackendRenderTarget(const GrBackendRenderTarget&); /** * Implements GrResourceProvider::wrapVulkanSecondaryCBAsRenderTarget */ sk_sp wrapVulkanSecondaryCBAsRenderTarget(const SkImageInfo&, const GrVkDrawableInfo&); /** * Creates a buffer in GPU memory. For a client-side buffer use GrBuffer::CreateCPUBacked. * * @param size size of buffer to create. * @param intendedType hint to the graphics subsystem about what the buffer will be used for. * @param accessPattern hint to the graphics subsystem about how the data will be accessed. * @param data optional data with which to initialize the buffer. * * @return the buffer if successful, otherwise nullptr. */ sk_sp createBuffer(size_t size, GrGpuBufferType intendedType, GrAccessPattern accessPattern, const void* data = nullptr); /** * Resolves MSAA. The resolveRect must already be in the native destination space. */ void resolveRenderTarget(GrRenderTarget*, const SkIRect& resolveRect); /** * Uses the base of the texture to recompute the contents of the other levels. */ bool regenerateMipMapLevels(GrTexture*); /** * If the backend API has stateful texture bindings, this resets them back to defaults. */ void resetTextureBindings(); /** * Reads a rectangle of pixels from a render target. No sRGB/linear conversions are performed. * * @param surface The surface to read from * @param left left edge of the rectangle to read (inclusive) * @param top top edge of the rectangle to read (inclusive) * @param width width of rectangle to read in pixels. * @param height height of rectangle to read in pixels. * @param surfaceColorType the color type for this use of the surface. * @param dstColorType the color type of the destination buffer. * @param buffer memory to read the rectangle into. * @param rowBytes the number of bytes between consecutive rows. Must be a multiple of * dstColorType's bytes-per-pixel. Must be tight to width if * !caps->readPixelsRowBytesSupport(). * * @return true if the read succeeded, false if not. The read can fail * because of the surface doesn't support reading, the color type * is not allowed for the format of the surface or if the rectangle * read is not contained in the surface. */ bool readPixels(GrSurface* surface, int left, int top, int width, int height, GrColorType surfaceColorType, GrColorType dstColorType, void* buffer, size_t rowBytes); /** * Updates the pixels in a rectangle of a surface. No sRGB/linear conversions are performed. * * @param surface The surface to write to. * @param left left edge of the rectangle to write (inclusive) * @param top top edge of the rectangle to write (inclusive) * @param width width of rectangle to write in pixels. * @param height height of rectangle to write in pixels. * @param surfaceColorType the color type for this use of the surface. * @param srcColorType the color type of the source buffer. * @param texels array of mipmap levels containing texture data. Row bytes must be a * multiple of srcColorType's bytes-per-pixel. Must be tight to level * width if !caps->writePixelsRowBytesSupport(). * @param mipLevelCount number of levels in 'texels' * @param prepForTexSampling After doing write pixels should the surface be prepared for texture * sampling. This is currently only used by Vulkan for inline uploads * to set that layout back to sampled after doing the upload. Inline * uploads currently can happen between draws in a single op so it is * not trivial to break up the GrOpsTask into two tasks when we see * an inline upload. However, once we are able to support doing that * we can remove this parameter. * * @return true if the write succeeded, false if not. The read can fail * because of the surface doesn't support writing (e.g. read only), * the color type is not allowed for the format of the surface or * if the rectangle written is not contained in the surface. */ bool writePixels(GrSurface* surface, int left, int top, int width, int height, GrColorType surfaceColorType, GrColorType srcColorType, const GrMipLevel texels[], int mipLevelCount, bool prepForTexSampling = false); /** * Helper for the case of a single level. */ bool writePixels(GrSurface* surface, int left, int top, int width, int height, GrColorType surfaceColorType, GrColorType srcColorType, const void* buffer, size_t rowBytes, bool prepForTexSampling = false) { GrMipLevel mipLevel = {buffer, rowBytes, nullptr}; return this->writePixels(surface, left, top, width, height, surfaceColorType, srcColorType, &mipLevel, 1, prepForTexSampling); } /** * Updates the pixels in a rectangle of a texture using a buffer. If the texture is MIP mapped, * the base level is written to. * * @param texture The texture to write to. * @param left left edge of the rectangle to write (inclusive) * @param top top edge of the rectangle to write (inclusive) * @param width width of rectangle to write in pixels. * @param height height of rectangle to write in pixels. * @param textureColorType the color type for this use of the surface. * @param bufferColorType the color type of the transfer buffer's pixel data * @param transferBuffer GrBuffer to read pixels from (type must be "kXferCpuToGpu") * @param offset offset from the start of the buffer * @param rowBytes number of bytes between consecutive rows in the buffer. Must be a * multiple of bufferColorType's bytes-per-pixel. Must be tight to width * if !caps->writePixelsRowBytesSupport(). */ bool transferPixelsTo(GrTexture* texture, int left, int top, int width, int height, GrColorType textureColorType, GrColorType bufferColorType, sk_sp transferBuffer, size_t offset, size_t rowBytes); /** * Reads the pixels from a rectangle of a surface into a buffer. Use * GrCaps::SupportedRead::fOffsetAlignmentForTransferBuffer to determine the requirements for * the buffer offset alignment. If the surface is a MIP mapped texture, the base level is read. * * If successful the row bytes in the buffer is always: * GrColorTypeBytesPerPixel(bufferColorType) * width * * Asserts that the caller has passed a properly aligned offset and that the buffer is * large enough to hold the result * * @param surface The surface to read from. * @param left left edge of the rectangle to read (inclusive) * @param top top edge of the rectangle to read (inclusive) * @param width width of rectangle to read in pixels. * @param height height of rectangle to read in pixels. * @param surfaceColorType the color type for this use of the surface. * @param bufferColorType the color type of the transfer buffer's pixel data * @param transferBuffer GrBuffer to write pixels to (type must be "kXferGpuToCpu") * @param offset offset from the start of the buffer */ bool transferPixelsFrom(GrSurface* surface, int left, int top, int width, int height, GrColorType surfaceColorType, GrColorType bufferColorType, sk_sp transferBuffer, size_t offset); // Called to perform a surface to surface copy. Fallbacks to issuing a draw from the src to dst // take place at higher levels and this function implement faster copy paths. The rect // and point are pre-clipped. The src rect and implied dst rect are guaranteed to be within the // src/dst bounds and non-empty. They must also be in their exact device space coords, including // already being transformed for origin if need be. If canDiscardOutsideDstRect is set to true // then we don't need to preserve any data on the dst surface outside of the copy. bool copySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint); // Returns a GrOpsRenderPass which GrOpsTasks send draw commands to instead of directly // to the Gpu object. The 'bounds' rect is the content rect of the renderTarget. // If a 'stencil' is provided it will be the one bound to 'renderTarget'. If one is not // provided but 'renderTarget' has a stencil buffer then that is a signal that the // render target's stencil buffer should be ignored. GrOpsRenderPass* getOpsRenderPass(GrRenderTarget* renderTarget, bool useMSAASurface, GrAttachment* stencil, GrSurfaceOrigin, const SkIRect& bounds, const GrOpsRenderPass::LoadAndStoreInfo&, const GrOpsRenderPass::StencilLoadAndStoreInfo&, const SkTArray& sampledProxies, GrXferBarrierFlags renderPassXferBarriers); // Called by GrDrawingManager when flushing. // Provides a hook for post-flush actions (e.g. Vulkan command buffer submits). This will also // insert any numSemaphore semaphores on the gpu and set the backendSemaphores to match the // inserted semaphores. void executeFlushInfo(SkSpan, SkSurface::BackendSurfaceAccess access, const GrFlushInfo&, const GrBackendSurfaceMutableState* newState); bool submitToGpu(bool syncCpu); virtual void submit(GrOpsRenderPass*) = 0; virtual GrFence SK_WARN_UNUSED_RESULT insertFence() = 0; virtual bool waitFence(GrFence) = 0; virtual void deleteFence(GrFence) const = 0; virtual std::unique_ptr SK_WARN_UNUSED_RESULT makeSemaphore( bool isOwned = true) = 0; virtual std::unique_ptr wrapBackendSemaphore(const GrBackendSemaphore& semaphore, GrResourceProvider::SemaphoreWrapType wrapType, GrWrapOwnership ownership) = 0; virtual void insertSemaphore(GrSemaphore* semaphore) = 0; virtual void waitSemaphore(GrSemaphore* semaphore) = 0; virtual void addFinishedProc(GrGpuFinishedProc finishedProc, GrGpuFinishedContext finishedContext) = 0; virtual void checkFinishProcs() = 0; virtual void finishOutstandingGpuWork() = 0; virtual void takeOwnershipOfBuffer(sk_sp) {} /** * Checks if we detected an OOM from the underlying 3D API and if so returns true and resets * the internal OOM state to false. Otherwise, returns false. */ bool checkAndResetOOMed(); /** * Put this texture in a safe and known state for use across multiple contexts. Depending on * the backend, this may return a GrSemaphore. If so, other contexts should wait on that * semaphore before using this texture. */ virtual std::unique_ptr prepareTextureForCrossContextUsage(GrTexture*) = 0; /** * Frees any backend specific objects that are not currently in use by the GPU. This is called * when the client is trying to free up as much GPU memory as possible. We will not release * resources connected to programs/pipelines since the cost to recreate those is significantly * higher that other resources. */ virtual void releaseUnlockedBackendObjects() {} /////////////////////////////////////////////////////////////////////////// // Debugging and Stats class Stats { public: #if GR_GPU_STATS Stats() = default; void reset() { *this = {}; } int textureCreates() const { return fTextureCreates; } void incTextureCreates() { fTextureCreates++; } int textureUploads() const { return fTextureUploads; } void incTextureUploads() { fTextureUploads++; } int transfersToTexture() const { return fTransfersToTexture; } void incTransfersToTexture() { fTransfersToTexture++; } int transfersFromSurface() const { return fTransfersFromSurface; } void incTransfersFromSurface() { fTransfersFromSurface++; } int stencilAttachmentCreates() const { return fStencilAttachmentCreates; } void incStencilAttachmentCreates() { fStencilAttachmentCreates++; } int msaaAttachmentCreates() const { return fMSAAAttachmentCreates; } void incMSAAAttachmentCreates() { fMSAAAttachmentCreates++; } int numDraws() const { return fNumDraws; } void incNumDraws() { fNumDraws++; } int numFailedDraws() const { return fNumFailedDraws; } void incNumFailedDraws() { ++fNumFailedDraws; } int numSubmitToGpus() const { return fNumSubmitToGpus; } void incNumSubmitToGpus() { ++fNumSubmitToGpus; } int numScratchTexturesReused() const { return fNumScratchTexturesReused; } void incNumScratchTexturesReused() { ++fNumScratchTexturesReused; } int numScratchMSAAAttachmentsReused() const { return fNumScratchMSAAAttachmentsReused; } void incNumScratchMSAAAttachmentsReused() { ++fNumScratchMSAAAttachmentsReused; } int renderPasses() const { return fRenderPasses; } void incRenderPasses() { fRenderPasses++; } int numReorderedDAGsOverBudget() const { return fNumReorderedDAGsOverBudget; } void incNumReorderedDAGsOverBudget() { fNumReorderedDAGsOverBudget++; } #if GR_TEST_UTILS void dump(SkString*); void dumpKeyValuePairs(SkTArray* keys, SkTArray* values); #endif private: int fTextureCreates = 0; int fTextureUploads = 0; int fTransfersToTexture = 0; int fTransfersFromSurface = 0; int fStencilAttachmentCreates = 0; int fMSAAAttachmentCreates = 0; int fNumDraws = 0; int fNumFailedDraws = 0; int fNumSubmitToGpus = 0; int fNumScratchTexturesReused = 0; int fNumScratchMSAAAttachmentsReused = 0; int fRenderPasses = 0; int fNumReorderedDAGsOverBudget = 0; #else // !GR_GPU_STATS #if GR_TEST_UTILS void dump(SkString*) {} void dumpKeyValuePairs(SkTArray*, SkTArray*) {} #endif void incTextureCreates() {} void incTextureUploads() {} void incTransfersToTexture() {} void incTransfersFromSurface() {} void incStencilAttachmentCreates() {} void incMSAAAttachmentCreates() {} void incNumDraws() {} void incNumFailedDraws() {} void incNumSubmitToGpus() {} void incNumScratchTexturesReused() {} void incNumScratchMSAAAttachmentsReused() {} void incRenderPasses() {} void incNumReorderedDAGsOverBudget() {} #endif }; Stats* stats() { return &fStats; } void dumpJSON(SkJSONWriter*) const; /** * Creates a texture directly in the backend API without wrapping it in a GrTexture. * Must be matched with a call to deleteBackendTexture(). * * If data is null the texture is uninitialized. * * If data represents a color then all texture levels are cleared to that color. * * If data represents pixmaps then it must have a either one pixmap or, if mipmapping * is specified, a complete MIP hierarchy of pixmaps. Additionally, if provided, the mip * levels must be sized correctly according to the MIP sizes implied by dimensions. They * must all have the same color type and that color type must be compatible with the * texture format. */ GrBackendTexture createBackendTexture(SkISize dimensions, const GrBackendFormat&, GrRenderable, GrMipmapped, GrProtected); bool clearBackendTexture(const GrBackendTexture&, sk_sp finishedCallback, std::array color); /** * Same as the createBackendTexture case except compressed backend textures can * never be renderable. */ GrBackendTexture createCompressedBackendTexture(SkISize dimensions, const GrBackendFormat&, GrMipmapped, GrProtected); bool updateCompressedBackendTexture(const GrBackendTexture&, sk_sp finishedCallback, const void* data, size_t length); virtual bool setBackendTextureState(const GrBackendTexture&, const GrBackendSurfaceMutableState&, GrBackendSurfaceMutableState* previousState, sk_sp finishedCallback) { return false; } virtual bool setBackendRenderTargetState(const GrBackendRenderTarget&, const GrBackendSurfaceMutableState&, GrBackendSurfaceMutableState* previousState, sk_sp finishedCallback) { return false; } /** * Frees a texture created by createBackendTexture(). If ownership of the backend * texture has been transferred to a context using adopt semantics this should not be called. */ virtual void deleteBackendTexture(const GrBackendTexture&) = 0; /** * In this case we have a program descriptor and a program info but no render target. */ virtual bool compile(const GrProgramDesc&, const GrProgramInfo&) = 0; virtual bool precompileShader(const SkData& key, const SkData& data) { return false; } #if GR_TEST_UTILS /** Check a handle represents an actual texture in the backend API that has not been freed. */ virtual bool isTestingOnlyBackendTexture(const GrBackendTexture&) const = 0; /** * Creates a GrBackendRenderTarget that can be wrapped using * SkSurface::MakeFromBackendRenderTarget. Ideally this is a non-textureable allocation to * differentiate from testing with SkSurface::MakeFromBackendTexture. When sampleCnt > 1 this * is used to test client wrapped allocations with MSAA where Skia does not allocate a separate * buffer for resolving. If the color is non-null the backing store should be cleared to the * passed in color. */ virtual GrBackendRenderTarget createTestingOnlyBackendRenderTarget( SkISize dimensions, GrColorType, int sampleCount = 1, GrProtected = GrProtected::kNo) = 0; /** * Deletes a GrBackendRenderTarget allocated with the above. Synchronization to make this safe * is up to the caller. */ virtual void deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) = 0; // This is only to be used in GL-specific tests. virtual const GrGLContext* glContextForTesting() const { return nullptr; } // This is only to be used by testing code virtual void resetShaderCacheForTesting() const {} /** * Inserted as a pair around a block of code to do a GPU frame capture. * Currently only works with the Metal backend. */ virtual void testingOnly_startCapture() {} virtual void testingOnly_endCapture() {} #endif // width and height may be larger than rt (if underlying API allows it). // Returns nullptr if compatible sb could not be created, otherwise the caller owns the ref on // the GrAttachment. virtual sk_sp makeStencilAttachment(const GrBackendFormat& colorFormat, SkISize dimensions, int numStencilSamples) = 0; virtual GrBackendFormat getPreferredStencilFormat(const GrBackendFormat&) = 0; // Creates an MSAA surface to be used as an MSAA attachment on a framebuffer. virtual sk_sp makeMSAAAttachment(SkISize dimensions, const GrBackendFormat& format, int numSamples, GrProtected isProtected) = 0; void handleDirtyContext() { if (fResetBits) { this->resetContext(); } } virtual void storeVkPipelineCacheData() {} // http://skbug.com/9739 virtual void insertManualFramebufferBarrier() { SkASSERT(!this->caps()->requiresManualFBBarrierAfterTessellatedStencilDraw()); SK_ABORT("Manual framebuffer barrier not supported."); } // Called before certain draws in order to guarantee coherent results from dst reads. virtual void xferBarrier(GrRenderTarget*, GrXferBarrierType) = 0; protected: static bool CompressedDataIsCorrect(SkISize dimensions, SkImage::CompressionType, GrMipmapped, const void* data, size_t length); // Handles cases where a surface will be updated without a call to flushRenderTarget. void didWriteToSurface(GrSurface* surface, GrSurfaceOrigin origin, const SkIRect* bounds, uint32_t mipLevels = 1) const; void setOOMed() { fOOMed = true; } Stats fStats; // Subclass must call this to initialize caps & compiler in its constructor. void initCapsAndCompiler(sk_sp caps); private: virtual GrBackendTexture onCreateBackendTexture(SkISize dimensions, const GrBackendFormat&, GrRenderable, GrMipmapped, GrProtected) = 0; virtual GrBackendTexture onCreateCompressedBackendTexture( SkISize dimensions, const GrBackendFormat&, GrMipmapped, GrProtected) = 0; virtual bool onClearBackendTexture(const GrBackendTexture&, sk_sp finishedCallback, std::array color) = 0; virtual bool onUpdateCompressedBackendTexture(const GrBackendTexture&, sk_sp finishedCallback, const void* data, size_t length) = 0; // called when the 3D context state is unknown. Subclass should emit any // assumed 3D context state and dirty any state cache. virtual void onResetContext(uint32_t resetBits) {} // Implementation of resetTextureBindings. virtual void onResetTextureBindings() {} // overridden by backend-specific derived class to create objects. // Texture size, renderablility, format support, sample count will have already been validated // in base class before onCreateTexture is called. // If the ith bit is set in levelClearMask then the ith MIP level should be cleared. virtual sk_sp onCreateTexture(SkISize dimensions, const GrBackendFormat&, GrRenderable, int renderTargetSampleCnt, SkBudgeted, GrProtected, int mipLevelCoont, uint32_t levelClearMask) = 0; virtual sk_sp onCreateCompressedTexture(SkISize dimensions, const GrBackendFormat&, SkBudgeted, GrMipmapped, GrProtected, const void* data, size_t dataSize) = 0; virtual sk_sp onWrapBackendTexture(const GrBackendTexture&, GrWrapOwnership, GrWrapCacheable, GrIOType) = 0; virtual sk_sp onWrapCompressedBackendTexture(const GrBackendTexture&, GrWrapOwnership, GrWrapCacheable) = 0; virtual sk_sp onWrapRenderableBackendTexture(const GrBackendTexture&, int sampleCnt, GrWrapOwnership, GrWrapCacheable) = 0; virtual sk_sp onWrapBackendRenderTarget(const GrBackendRenderTarget&) = 0; virtual sk_sp onWrapVulkanSecondaryCBAsRenderTarget(const SkImageInfo&, const GrVkDrawableInfo&); virtual sk_sp onCreateBuffer(size_t size, GrGpuBufferType intendedType, GrAccessPattern, const void* data) = 0; // overridden by backend-specific derived class to perform the surface read virtual bool onReadPixels(GrSurface*, int left, int top, int width, int height, GrColorType surfaceColorType, GrColorType dstColorType, void* buffer, size_t rowBytes) = 0; // overridden by backend-specific derived class to perform the surface write virtual bool onWritePixels(GrSurface*, int left, int top, int width, int height, GrColorType surfaceColorType, GrColorType srcColorType, const GrMipLevel texels[], int mipLevelCount, bool prepForTexSampling) = 0; // overridden by backend-specific derived class to perform the texture transfer virtual bool onTransferPixelsTo(GrTexture*, int left, int top, int width, int height, GrColorType textiueColorType, GrColorType bufferColorType, sk_sp transferBuffer, size_t offset, size_t rowBytes) = 0; // overridden by backend-specific derived class to perform the surface transfer virtual bool onTransferPixelsFrom(GrSurface*, int left, int top, int width, int height, GrColorType surfaceColorType, GrColorType bufferColorType, sk_sp transferBuffer, size_t offset) = 0; // overridden by backend-specific derived class to perform the resolve virtual void onResolveRenderTarget(GrRenderTarget* target, const SkIRect& resolveRect) = 0; // overridden by backend specific derived class to perform mip map level regeneration. virtual bool onRegenerateMipMapLevels(GrTexture*) = 0; // overridden by backend specific derived class to perform the copy surface virtual bool onCopySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) = 0; virtual GrOpsRenderPass* onGetOpsRenderPass( GrRenderTarget* renderTarget, bool useMSAASurface, GrAttachment* stencil, GrSurfaceOrigin, const SkIRect& bounds, const GrOpsRenderPass::LoadAndStoreInfo&, const GrOpsRenderPass::StencilLoadAndStoreInfo&, const SkTArray& sampledProxies, GrXferBarrierFlags renderPassXferBarriers) = 0; virtual void prepareSurfacesForBackendAccessAndStateUpdates( SkSpan proxies, SkSurface::BackendSurfaceAccess access, const GrBackendSurfaceMutableState* newState) {} virtual bool onSubmitToGpu(bool syncCpu) = 0; void reportSubmitHistograms(); virtual void onReportSubmitHistograms() {} #ifdef SK_ENABLE_DUMP_GPU virtual void onDumpJSON(SkJSONWriter*) const {} #endif sk_sp createTextureCommon(SkISize, const GrBackendFormat&, GrRenderable, int renderTargetSampleCnt, SkBudgeted, GrProtected, int mipLevelCnt, uint32_t levelClearMask); void resetContext() { this->onResetContext(fResetBits); fResetBits = 0; } void callSubmittedProcs(bool success); sk_sp fCaps; // Compiler used for compiling SkSL into backend shader code. We only want to create the // compiler once, as there is significant overhead to the first compile. std::unique_ptr fCompiler; uint32_t fResetBits; // The context owns us, not vice-versa, so this ptr is not ref'ed by Gpu. GrDirectContext* fContext; struct SubmittedProc { SubmittedProc(GrGpuSubmittedProc proc, GrGpuSubmittedContext context) : fProc(proc), fContext(context) {} GrGpuSubmittedProc fProc; GrGpuSubmittedContext fContext; }; SkSTArray<4, SubmittedProc> fSubmittedProcs; bool fOOMed = false; #if SK_HISTOGRAMS_ENABLED int fCurrentSubmitRenderPassCount = 0; #endif friend class GrPathRendering; using INHERITED = SkRefCnt; }; #endif