blob: 498668c0ca4dd13ce2062688c68c9c554fac5953 [file] [log] [blame]
/*
* 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/SkSurface.h"
#include "include/gpu/GrTypes.h"
#include "include/private/SkTArray.h"
#include "src/core/SkSpan.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/GrTextureProducer.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<const GrCaps> 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<GrThreadSafePipelineBuilder> 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<GrTexture> 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<GrTexture> createTexture(SkISize dimensions,
const GrBackendFormat& format,
GrRenderable renderable,
int renderTargetSampleCnt,
GrMipmapped mipMapped,
SkBudgeted budgeted,
GrProtected isProtected);
sk_sp<GrTexture> createCompressedTexture(SkISize dimensions,
const GrBackendFormat& format,
SkBudgeted budgeted,
GrMipmapped mipMapped,
GrProtected isProtected,
const void* data, size_t dataSize);
/**
* Implements GrResourceProvider::wrapBackendTexture
*/
sk_sp<GrTexture> wrapBackendTexture(const GrBackendTexture&,
GrWrapOwnership,
GrWrapCacheable,
GrIOType);
sk_sp<GrTexture> wrapCompressedBackendTexture(const GrBackendTexture&,
GrWrapOwnership,
GrWrapCacheable);
/**
* Implements GrResourceProvider::wrapRenderableBackendTexture
*/
sk_sp<GrTexture> wrapRenderableBackendTexture(const GrBackendTexture&,
int sampleCnt,
GrWrapOwnership,
GrWrapCacheable);
/**
* Implements GrResourceProvider::wrapBackendRenderTarget
*/
sk_sp<GrRenderTarget> wrapBackendRenderTarget(const GrBackendRenderTarget&);
/**
* Implements GrResourceProvider::wrapVulkanSecondaryCBAsRenderTarget
*/
sk_sp<GrRenderTarget> 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<GrGpuBuffer> 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<GrGpuBuffer> 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<GrGpuBuffer> 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<GrSurfaceProxy*, true>& 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<GrSurfaceProxy*>,
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<GrSemaphore> SK_WARN_UNUSED_RESULT makeSemaphore(
bool isOwned = true) = 0;
virtual std::unique_ptr<GrSemaphore> 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<GrGpuBuffer>) {}
/**
* 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<GrSemaphore> 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<SkString>* keys, SkTArray<double>* 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<SkString>*, SkTArray<double>*) {}
#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<GrRefCntedCallback> finishedCallback,
std::array<float, 4> 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<GrRefCntedCallback> finishedCallback,
const void* data,
size_t length);
virtual bool setBackendTextureState(const GrBackendTexture&,
const GrBackendSurfaceMutableState&,
GrBackendSurfaceMutableState* previousState,
sk_sp<GrRefCntedCallback> finishedCallback) {
return false;
}
virtual bool setBackendRenderTargetState(const GrBackendRenderTarget&,
const GrBackendSurfaceMutableState&,
GrBackendSurfaceMutableState* previousState,
sk_sp<GrRefCntedCallback> 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<GrAttachment> makeStencilAttachmentForRenderTarget(const GrRenderTarget*,
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<GrAttachment> 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<const GrCaps> 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<GrRefCntedCallback> finishedCallback,
std::array<float, 4> color) = 0;
virtual bool onUpdateCompressedBackendTexture(const GrBackendTexture&,
sk_sp<GrRefCntedCallback> 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<GrTexture> onCreateTexture(SkISize dimensions,
const GrBackendFormat&,
GrRenderable,
int renderTargetSampleCnt,
SkBudgeted,
GrProtected,
int mipLevelCoont,
uint32_t levelClearMask) = 0;
virtual sk_sp<GrTexture> onCreateCompressedTexture(SkISize dimensions,
const GrBackendFormat&,
SkBudgeted,
GrMipmapped,
GrProtected,
const void* data, size_t dataSize) = 0;
virtual sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&,
GrWrapOwnership,
GrWrapCacheable,
GrIOType) = 0;
virtual sk_sp<GrTexture> onWrapCompressedBackendTexture(const GrBackendTexture&,
GrWrapOwnership,
GrWrapCacheable) = 0;
virtual sk_sp<GrTexture> onWrapRenderableBackendTexture(const GrBackendTexture&,
int sampleCnt,
GrWrapOwnership,
GrWrapCacheable) = 0;
virtual sk_sp<GrRenderTarget> onWrapBackendRenderTarget(const GrBackendRenderTarget&) = 0;
virtual sk_sp<GrRenderTarget> onWrapVulkanSecondaryCBAsRenderTarget(const SkImageInfo&,
const GrVkDrawableInfo&);
virtual sk_sp<GrGpuBuffer> 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<GrGpuBuffer> 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<GrGpuBuffer> 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<GrSurfaceProxy*, true>& sampledProxies,
GrXferBarrierFlags renderPassXferBarriers) = 0;
virtual void prepareSurfacesForBackendAccessAndStateUpdates(
SkSpan<GrSurfaceProxy*> 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<GrTexture> 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<const GrCaps> 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<SkSL::Compiler> 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