/*
* Copyright 2020 Google LLC
*
* Use of this source code is governed by a BSD - style license that can be
* found in the LICENSE file .
*/
#ifndef GrDirectContext_DEFINED
#define GrDirectContext_DEFINED
#include "include/core/SkColor.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkTypes.h"
#include "include/gpu/GpuTypes.h"
#include "include/gpu/ganesh/GrContextOptions.h"
#include "include/gpu/ganesh/GrRecordingContext.h"
#include "include/gpu/ganesh/GrTypes.h"
#include <chrono>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <string_view>
class GrAtlasManager;
class GrBackendSemaphore;
class GrBackendFormat;
class GrBackendTexture;
class GrBackendRenderTarget;
class GrClientMappedBufferManager;
class GrContextThreadSafeProxy;
class GrDirectContextPriv;
class GrGpu;
class GrResourceCache;
class GrResourceProvider;
class SkData;
class SkImage;
class SkPixmap;
class SkSurface;
class SkTaskGroup;
class SkTraceMemoryDump;
enum SkColorType : int ;
enum class SkTextureCompressionType;
struct GrMockOptions;
namespace skgpu {
class MutableTextureState;
#if !defined (SK_ENABLE_OPTIMIZE_SIZE)
namespace ganesh { class SmallPathAtlasMgr; }
#endif
}
namespace sktext { namespace gpu { class StrikeCache; } }
namespace wgpu { class Device; } // IWYU pragma: keep
namespace SkSurfaces {
enum class BackendSurfaceAccess;
}
class SK_API GrDirectContext : public GrRecordingContext {
public :
static sk_sp<GrDirectContext> MakeMock(const GrMockOptions*, const GrContextOptions&);
static sk_sp<GrDirectContext> MakeMock(const GrMockOptions*);
~GrDirectContext() override;
/**
* The context normally assumes that no outsider is setting state
* within the underlying 3 D API ' s context / device / whatever . This call informs
* the context that the state was modified and it should resend . Shouldn ' t
* be called frequently for good performance .
* The flag bits , state , is dependent on which backend is used by the
* context , either GL or D3D ( possible in future ) .
*/
void resetContext(uint32_t state = kAll_GrBackendState);
/**
* If the backend is GrBackendApi : : kOpenGL , then all texture unit / target combinations for which
* the context has modified the bound texture will have texture id 0 bound . This does not
* flush the context . Calling resetContext ( ) does not change the set that will be bound
* to texture id 0 on the next call to resetGLTextureBindings ( ) . After this is called
* all unit / target combinations are considered to have unmodified bindings until the context
* subsequently modifies them ( meaning if this is called twice in a row with no intervening
* context usage then the second call is a no - op . )
*/
void resetGLTextureBindings();
/**
* Abandons all GPU resources and assumes the underlying backend 3 D API context is no longer
* usable . Call this if you have lost the associated GPU context , and thus internal texture ,
* buffer , etc . references / IDs are now invalid . Calling this ensures that the destructors of the
* context and any of its created resource objects will not make backend 3 D API calls . Content
* rendered but not previously flushed may be lost . After this function is called all subsequent
* calls on the context will fail or be no - ops .
*
* The typical use case for this function is that the underlying 3 D context was lost and further
* API calls may crash .
*
* This call is not valid to be made inside ReleaseProcs passed into SkSurface or SkImages . The
* call will simply fail ( and assert in debug ) if it is called while inside a ReleaseProc .
*
* For Vulkan , even if the device becomes lost , the VkQueue , VkDevice , or VkInstance used to
* create the context must be kept alive even after abandoning the context . Those objects must
* live for the lifetime of the context object itself . The reason for this is so that
* we can continue to delete any outstanding GrBackendTextures / RenderTargets which must be
* cleaned up even in a device lost state .
*/
void abandonContext() override;
/**
* Returns true if the context was abandoned or if the backend specific context has gotten into
* an unrecoverarble , lost state ( e . g . in Vulkan backend if we ' ve gotten a
* VK_ERROR_DEVICE_LOST ) . If the backend context is lost , this call will also abandon this
* context .
*/
bool abandoned() override;
/**
* Returns true if the backend specific context has gotten into an unrecoverarble , lost state
* ( e . g . in Vulkan backend if we ' ve gotten a VK_ERROR_DEVICE_LOST ) . If the backend context is
* lost , this call will also abandon this context .
*/
bool isDeviceLost();
// TODO: Remove this from public after migrating Chrome.
sk_sp<GrContextThreadSafeProxy> threadSafeProxy();
/**
* Checks if the underlying 3 D API reported an out - of - memory error . If this returns true it is
* reset and will return false until another out - of - memory error is reported by the 3 D API . If
* the context is abandoned then this will report false .
*
* Currently this is implemented for :
*
* OpenGL [ ES ] - Note that client calls to glGetError ( ) may swallow GL_OUT_OF_MEMORY errors and
* therefore hide the error from Skia . Also , it is not advised to use this in combination with
* enabling GrContextOptions : : fSkipGLErrorChecks . That option may prevent the context from ever
* checking the GL context for OOM .
*
* Vulkan - Reports true if VK_ERROR_OUT_OF_HOST_MEMORY or VK_ERROR_OUT_OF_DEVICE_MEMORY has
* occurred .
*/
bool oomed();
/**
* This is similar to abandonContext ( ) however the underlying 3 D context is not yet lost and
* the context will cleanup all allocated resources before returning . After returning it will
* assume that the underlying context may no longer be valid .
*
* The typical use case for this function is that the client is going to destroy the 3 D context
* but can ' t guarantee that context will be destroyed first ( perhaps because it may be ref ' ed
* elsewhere by either the client or Skia objects ) .
*
* For Vulkan , even if the device becomes lost , the VkQueue , VkDevice , or VkInstance used to
* create the context must be alive before calling releaseResourcesAndAbandonContext .
*/
void releaseResourcesAndAbandonContext();
///////////////////////////////////////////////////////////////////////////
// Resource Cache
/** DEPRECATED
* Return the current GPU resource cache limits .
*
* @ param maxResources If non - null , will be set to - 1 .
* @ param maxResourceBytes If non - null , returns maximum number of bytes of
* video memory that can be held in the cache .
*/
void getResourceCacheLimits(int * maxResources, size_t* maxResourceBytes) const ;
/**
* Return the current GPU resource cache limit in bytes .
*/
size_t getResourceCacheLimit() const ;
/**
* Gets the current GPU resource cache usage .
*
* @ param resourceCount If non - null , returns the number of resources that are held in the
* cache .
* @ param maxResourceBytes If non - null , returns the total number of bytes of video memory held
* in the cache .
*/
void getResourceCacheUsage(int * resourceCount, size_t* resourceBytes) const ;
/**
* Gets the number of bytes in the cache consumed by purgeable ( e . g . unlocked ) resources .
*/
size_t getResourceCachePurgeableBytes() const ;
/** DEPRECATED
* Specify the GPU resource cache limits . If the current cache exceeds the maxResourceBytes
* limit , it will be purged ( LRU ) to keep the cache within the limit .
*
* @ param maxResources Unused .
* @ param maxResourceBytes The maximum number of bytes of video memory
* that can be held in the cache .
*/
void setResourceCacheLimits(int maxResources, size_t maxResourceBytes);
/**
* Specify the GPU resource cache limit . If the cache currently exceeds this limit ,
* it will be purged ( LRU ) to keep the cache within the limit .
*
* @ param maxResourceBytes The maximum number of bytes of video memory
* that can be held in the cache .
*/
void setResourceCacheLimit(size_t maxResourceBytes);
/**
* Frees GPU created by the context . Can be called to reduce GPU memory
* pressure .
*/
void freeGpuResources();
/**
* Purge GPU resources that haven ' t been used in the past ' msNotUsed ' milliseconds or are
* otherwise marked for deletion , regardless of whether the context is under budget .
*
* @ param msNotUsed Only unlocked resources not used in these last milliseconds will be
* cleaned up .
* @ param opts Specify which resources should be cleaned up . If kScratchResourcesOnly
* then , all unlocked scratch resources older than ' msNotUsed ' will be purged
* but the unlocked resources with persistent data will remain . If
* kAllResources
*/
void performDeferredCleanup(
std::chrono::milliseconds msNotUsed,
GrPurgeResourceOptions opts = GrPurgeResourceOptions::kAllResources);
// Temporary compatibility API for Android.
void purgeResourcesNotUsedInMs(std::chrono::milliseconds msNotUsed) {
this ->performDeferredCleanup(msNotUsed);
}
/**
* Purge unlocked resources from the cache until the the provided byte count has been reached
* or we have purged all unlocked resources . The default policy is to purge in LRU order , but
* can be overridden to prefer purging scratch resources ( in LRU order ) prior to purging other
* resource types .
*
* @ param maxBytesToPurge the desired number of bytes to be purged .
* @ param preferScratchResources If true scratch resources will be purged prior to other
* resource types .
*/
void purgeUnlockedResources(size_t bytesToPurge, bool preferScratchResources);
/**
* This entry point is intended for instances where an app has been backgrounded or
* suspended .
* If ' scratchResourcesOnly ' is true all unlocked scratch resources will be purged but the
* unlocked resources with persistent data will remain . If ' scratchResourcesOnly ' is false
* then all unlocked resources will be purged .
* In either case , after the unlocked resources are purged a separate pass will be made to
* ensure that resource usage is under budget ( i . e . , even if ' scratchResourcesOnly ' is true
* some resources with persistent data may be purged to be under budget ) .
*
* @ param opts If kScratchResourcesOnly only unlocked scratch resources will be purged prior
* enforcing the budget requirements .
*/
void purgeUnlockedResources(GrPurgeResourceOptions opts);
/*
* Gets the types of GPU stats supported by this Context .
*/
skgpu::GpuStatsFlags supportedGpuStats() const ;
/**
* Gets the maximum supported texture size .
*/
using GrRecordingContext::maxTextureSize;
/**
* Gets the maximum supported render target size .
*/
using GrRecordingContext::maxRenderTargetSize;
/**
* Can a SkImage be created with the given color type .
*/
using GrRecordingContext::colorTypeSupportedAsImage;
/**
* Does this context support protected content ?
*/
using GrRecordingContext::supportsProtectedContent;
/**
* Can a SkSurface be created with the given color type . To check whether MSAA is supported
* use maxSurfaceSampleCountForColorType ( ) .
*/
using GrRecordingContext::colorTypeSupportedAsSurface;
/**
* Gets the maximum supported sample count for a color type . 1 is returned if only non - MSAA
* rendering is supported for the color type . 0 is returned if rendering to this color type
* is not supported at all .
*/
using GrRecordingContext::maxSurfaceSampleCountForColorType;
///////////////////////////////////////////////////////////////////////////
// Misc.
/**
* Inserts a list of GPU semaphores that the current GPU - backed API must wait on before
* executing any more commands on the GPU . We only guarantee blocking transfer and fragment
* shader work , but may block earlier stages as well depending on the backend . If this call
* returns false , then the GPU back - end will not wait on any passed in semaphores , and the
* client will still own the semaphores , regardless of the value of deleteSemaphoresAfterWait .
*
* If deleteSemaphoresAfterWait is false then Skia will not delete the semaphores . In this case
* it is the client ' s responsibility to not destroy or attempt to reuse the semaphores until it
* knows that Skia has finished waiting on them . This can be done by using finishedProcs on
* flush calls .
*
* This is not supported on the GL backend .
*/
bool wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores,
bool deleteSemaphoresAfterWait = true );
/**
* Call to ensure all drawing to the context has been flushed and submitted to the underlying 3 D
* API . This is equivalent to calling GrContext : : flush with a default GrFlushInfo followed by
* GrContext : : submit ( sync ) .
*/
void flushAndSubmit(GrSyncCpu sync = GrSyncCpu::kNo) {
this ->flush(GrFlushInfo());
this ->submit(sync);
}
/**
* Call to ensure all drawing to the context has been flushed to underlying 3 D API specific
* objects . A call to ` submit ` is always required to ensure work is actually sent to
* the gpu . Some specific API details :
* GL : Commands are actually sent to the driver , but glFlush is never called . Thus some
* sync objects from the flush will not be valid until a submission occurs .
*
* Vulkan / Metal / D3D / Dawn : Commands are recorded to the backend APIs corresponding command
* buffer or encoder objects . However , these objects are not sent to the gpu until a
* submission occurs .
*
* If the return is GrSemaphoresSubmitted : : kYes , only initialized GrBackendSemaphores will be
* submitted to the gpu during the next submit call ( it is possible Skia failed to create a
* subset of the semaphores ) . The client should not wait on these semaphores until after submit
* has been called , and must keep them alive until then . If this call returns
* GrSemaphoresSubmitted : : kNo , the GPU backend will not submit any semaphores to be signaled on
* the GPU . Thus the client should not have the GPU wait on any of the semaphores passed in with
* the GrFlushInfo . Regardless of whether semaphores were submitted to the GPU or not , the
* client is still responsible for deleting any initialized semaphores .
* Regardless of semaphore submission the context will still be flushed . It should be
* emphasized that a return value of GrSemaphoresSubmitted : : kNo does not mean the flush did not
* happen . It simply means there were no semaphores submitted to the GPU . A caller should only
* take this as a failure if they passed in semaphores to be submitted .
*/
GrSemaphoresSubmitted flush(const GrFlushInfo& info);
void flush() { this ->flush(GrFlushInfo()); }
/** Flushes any pending uses of texture-backed images in the GPU backend. If the image is not
* texture - backed ( including promise texture images ) or if the GrDirectContext does not
* have the same context ID as the context backing the image then this is a no - op .
* If the image was not used in any non - culled draws in the current queue of work for the
* passed GrDirectContext then this is a no - op unless the GrFlushInfo contains semaphores or
* a finish proc . Those are respected even when the image has not been used .
* @ param image the non - null image to flush .
* @ param info flush options
*/
GrSemaphoresSubmitted flush(const sk_sp<const SkImage>& image, const GrFlushInfo& info);
void flush(const sk_sp<const SkImage>& image);
/** Version of flush() that uses a default GrFlushInfo. Also submits the flushed work to the
* GPU .
*/
void flushAndSubmit(const sk_sp<const SkImage>& image);
/** Issues pending SkSurface commands to the GPU-backed API objects and resolves any SkSurface
* MSAA . A call to GrDirectContext : : submit is always required to ensure work is actually sent
* to the gpu . Some specific API details :
* GL : Commands are actually sent to the driver , but glFlush is never called . Thus some
* sync objects from the flush will not be valid until a submission occurs .
*
* Vulkan / Metal / D3D / Dawn : Commands are recorded to the backend APIs corresponding command
* buffer or encoder objects . However , these objects are not sent to the gpu until a
* submission occurs .
*
* The work that is submitted to the GPU will be dependent on the BackendSurfaceAccess that is
* passed in .
*
* If BackendSurfaceAccess : : kNoAccess is passed in all commands will be issued to the GPU .
*
* If BackendSurfaceAccess : : kPresent is passed in and the backend API is not Vulkan , it is
* treated the same as kNoAccess . If the backend API is Vulkan , the VkImage that backs the
* SkSurface will be transferred back to its original queue . If the SkSurface was created by
* wrapping a VkImage , the queue will be set to the queue which was originally passed in on
* the GrVkImageInfo . Additionally , if the original queue was not external or foreign the
* layout of the VkImage will be set to VK_IMAGE_LAYOUT_PRESENT_SRC_KHR .
*
* The GrFlushInfo describes additional options to flush . Please see documentation at
* GrFlushInfo for more info .
*
* If the return is GrSemaphoresSubmitted : : kYes , only initialized GrBackendSemaphores will be
* submitted to the gpu during the next submit call ( it is possible Skia failed to create a
* subset of the semaphores ) . The client should not wait on these semaphores until after submit
* has been called , but must keep them alive until then . If a submit flag was passed in with
* the flush these valid semaphores can we waited on immediately . If this call returns
* GrSemaphoresSubmitted : : kNo , the GPU backend will not submit any semaphores to be signaled on
* the GPU . Thus the client should not have the GPU wait on any of the semaphores passed in
* with the GrFlushInfo . Regardless of whether semaphores were submitted to the GPU or not , the
* client is still responsible for deleting any initialized semaphores .
* Regardless of semaphore submission the context will still be flushed . It should be
* emphasized that a return value of GrSemaphoresSubmitted : : kNo does not mean the flush did not
* happen . It simply means there were no semaphores submitted to the GPU . A caller should only
* take this as a failure if they passed in semaphores to be submitted .
*
* Pending surface commands are flushed regardless of the return result .
*
* @ param surface The GPU backed surface to be flushed . Has no effect on a CPU - backed surface .
* @ param access type of access the call will do on the backend object after flush
* @ param info flush options
*/
GrSemaphoresSubmitted flush(SkSurface* surface,
SkSurfaces::BackendSurfaceAccess access,
const GrFlushInfo& info);
/**
* Same as above except :
*
* If a skgpu : : MutableTextureState is passed in , at the end of the flush we will transition
* the surface to be in the state requested by the skgpu : : MutableTextureState . If the surface
* ( or SkImage or GrBackendSurface wrapping the same backend object ) is used again after this
* flush the state may be changed and no longer match what is requested here . This is often
* used if the surface will be used for presenting or external use and the client wants backend
* object to be prepped for that use . A finishedProc or semaphore on the GrFlushInfo will also
* include the work for any requested state change .
*
* If the backend API is Vulkan , the caller can set the skgpu : : MutableTextureState ' s
* VkImageLayout to VK_IMAGE_LAYOUT_UNDEFINED or queueFamilyIndex to VK_QUEUE_FAMILY_IGNORED to
* tell Skia to not change those respective states .
*
* @ param surface The GPU backed surface to be flushed . Has no effect on a CPU - backed surface .
* @ param info flush options
* @ param newState optional state change request after flush
*/
GrSemaphoresSubmitted flush(SkSurface* surface,
const GrFlushInfo& info,
const skgpu::MutableTextureState* newState = nullptr);
/** Call to ensure all reads/writes of the surface have been issued to the underlying 3D API.
* Skia will correctly order its own draws and pixel operations . This must to be used to ensure
* correct ordering when the surface backing store is accessed outside Skia ( e . g . direct use of
* the 3 D API or a windowing system ) . This is equivalent to
* calling : : flush with a default GrFlushInfo followed by : : submit ( syncCpu ) .
*
* Has no effect on a CPU - backed surface .
*/
void flushAndSubmit(SkSurface* surface, GrSyncCpu sync = GrSyncCpu::kNo);
/**
* Flushes the given surface with the default GrFlushInfo .
*
* Has no effect on a CPU - backed surface .
*/
void flush(SkSurface* surface);
/**
* Submit outstanding work to the gpu from all previously un - submitted flushes . The return
* value of the submit will indicate whether or not the submission to the GPU was successful .
*
* If the call returns true , all previously passed in semaphores in flush calls will have been
* submitted to the GPU and they can safely be waited on . The caller should wait on those
* semaphores or perform some other global synchronization before deleting the semaphores .
*
* If it returns false , then those same semaphores will not have been submitted and we will not
* try to submit them again . The caller is free to delete the semaphores at any time .
*
* If GrSubmitInfo : : fSync flag is GrSyncCpu : : kYes , this function will return once the gpu has
* finished with all submitted work .
*
* If GrSubmitInfo : : fMarkBoundary flag is GrMarkFrameBoundary : : kYes and the GPU supports a way
* to be notified about frame boundaries , then we will notify the GPU during / after the
* submission of work to the GPU . GrSubmitInfo : : fFrameID is a frame ID that is passed to the
* GPU when marking a boundary . Ideally this value should be unique for each frame . Currently
* marking frame boundaries is only supported with the Vulkan backend and only if the
* VK_EXT_frame_boudnary extenstion is available .
*/
bool submit(const GrSubmitInfo&);
bool submit(GrSyncCpu sync = GrSyncCpu::kNo) {
GrSubmitInfo info;
info.fSync = sync;
return this ->submit(info);
}
/**
* Checks whether any asynchronous work is complete and if so calls related callbacks .
*/
void checkAsyncWorkCompletion();
/** Enumerates all cached GPU resources and dumps their memory to traceMemoryDump. */
// Chrome is using this!
void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const ;
bool supportsDistanceFieldText() const ;
/**
* Returns true if the underlying Vulkan implementation can accurately detect when the data in
* the pipeline cache changes . Returns false on non - Vulkan implementations .
*
* When this is false , the return value of ` hasNewVkPipelineCacheData ` will occasionally issue a
* false positive .
*/
bool canDetectNewVkPipelineCacheData() const ;
/**
* For Vulkan implementations , returns true if the data in the pipeline cache could have changed
* since the last call to ` storeVkPipelineCacheData ` . Always returns true on non - Vulkan
* implementations .
*
* Pipeline cache changes are detected when creating new pipelines , however this will
* occasionally result in a false positive . When VK_EXT_pipeline_creation_cache_control is
* enabled , we additionally know when a pipeline creation does not change the cache , thus
* eliminating false - positives .
*
* Check ` canDetectNewVkPipelineCacheData ` to see whether VK_EXT_pipeline_creation_cache_control
* is available and enabled .
*/
bool hasNewVkPipelineCacheData() const ;
void storeVkPipelineCacheData();
void storeVkPipelineCacheData(size_t maxSize);
/**
* Retrieve the default GrBackendFormat for a given SkColorType and renderability .
* It is guaranteed that this backend format will be the one used by the following
* SkColorType and GrSurfaceCharacterization - based createBackendTexture methods .
*
* The caller should check that the returned format is valid .
*/
using GrRecordingContext::defaultBackendFormat;
/**
* The explicitly allocated backend texture API allows clients to use Skia to create backend
* objects outside of Skia proper ( i . e . , Skia ' s caching system will not know about them . )
*
* It is the client ' s responsibility to delete all these objects ( using deleteBackendTexture )
* before deleting the context used to create them . If the backend is Vulkan , the textures must
* be deleted before abandoning the context as well . Additionally , clients should only delete
* these objects on the thread for which that context is active .
*
* The client is responsible for ensuring synchronization between different uses
* of the backend object ( i . e . , wrapping it in a surface , rendering to it , deleting the
* surface , rewrapping it in a image and drawing the image will require explicit
* synchronization on the client ' s part ) .
*/
/**
* If possible , create an uninitialized backend texture . The client should ensure that the
* returned backend texture is valid .
* For the Vulkan backend the layout of the created VkImage will be :
* VK_IMAGE_LAYOUT_UNDEFINED .
*/
GrBackendTexture createBackendTexture(int width,
int height,
const GrBackendFormat&,
skgpu::Mipmapped,
GrRenderable,
GrProtected = GrProtected::kNo,
std::string_view label = {});
/**
* If possible , create an uninitialized backend texture . The client should ensure that the
* returned backend texture is valid .
* If successful , the created backend texture will be compatible with the provided
* SkColorType .
* For the Vulkan backend the layout of the created VkImage will be :
* VK_IMAGE_LAYOUT_UNDEFINED .
*/
GrBackendTexture createBackendTexture(int width,
int height,
SkColorType,
skgpu::Mipmapped,
GrRenderable,
GrProtected = GrProtected::kNo,
std::string_view label = {});
/**
* If possible , create a backend texture initialized to a particular color . The client should
* ensure that the returned backend texture is valid . The client can pass in a finishedProc
* to be notified when the data has been uploaded by the gpu and the texture can be deleted . The
* client is required to call ` submit ` to send the upload work to the gpu . The
* finishedProc will always get called even if we failed to create the GrBackendTexture .
* For the Vulkan backend the layout of the created VkImage will be :
* VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
*/
GrBackendTexture createBackendTexture(int width,
int height,
const GrBackendFormat&,
const SkColor4f& color,
skgpu::Mipmapped,
GrRenderable,
GrProtected = GrProtected::kNo,
GrGpuFinishedProc finishedProc = nullptr,
GrGpuFinishedContext finishedContext = nullptr,
std::string_view label = {});
/**
* If possible , create a backend texture initialized to a particular color . The client should
* ensure that the returned backend texture is valid . The client can pass in a finishedProc
* to be notified when the data has been uploaded by the gpu and the texture can be deleted . The
* client is required to call ` submit ` to send the upload work to the gpu . The
* finishedProc will always get called even if we failed to create the GrBackendTexture .
* If successful , the created backend texture will be compatible with the provided
* SkColorType .
* For the Vulkan backend the layout of the created VkImage will be :
* VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
*/
GrBackendTexture createBackendTexture(int width,
int height,
SkColorType,
const SkColor4f& color,
skgpu::Mipmapped,
GrRenderable,
GrProtected = GrProtected::kNo,
GrGpuFinishedProc finishedProc = nullptr,
GrGpuFinishedContext finishedContext = nullptr,
std::string_view label = {});
/**
* If possible , create a backend texture initialized with the provided pixmap data . The client
* should ensure that the returned backend texture is valid . The client can pass in a
* finishedProc to be notified when the data has been uploaded by the gpu and the texture can be
* deleted . The client is required to call ` submit ` to send the upload work to the gpu .
* The finishedProc will always get called even if we failed to create the GrBackendTexture .
* If successful , the created backend texture will be compatible with the provided
* pixmap ( s ) . Compatible , in this case , means that the backend format will be the result
* of calling defaultBackendFormat on the base pixmap ' s colortype . The src data can be deleted
* when this call returns .
* If numLevels is 1 a non - mipmapped texture will result . If a mipmapped texture is desired
* the data for all the mipmap levels must be provided . In the mipmapped case all the
* colortypes of the provided pixmaps must be the same . Additionally , all the miplevels
* must be sized correctly ( please see SkMipmap : : ComputeLevelSize and ComputeLevelCount ) . The
* GrSurfaceOrigin controls whether the pixmap data is vertically flipped in the texture .
* Note : the pixmap ' s alphatypes and colorspaces are ignored .
* For the Vulkan backend the layout of the created VkImage will be :
* VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
*/
GrBackendTexture createBackendTexture(const SkPixmap srcData[],
int numLevels,
GrSurfaceOrigin,
GrRenderable,
GrProtected,
GrGpuFinishedProc finishedProc = nullptr,
GrGpuFinishedContext finishedContext = nullptr,
std::string_view label = {});
/**
* Convenience version createBackendTexture ( ) that takes just a base level pixmap .
*/
GrBackendTexture createBackendTexture(const SkPixmap& srcData,
GrSurfaceOrigin textureOrigin,
GrRenderable renderable,
GrProtected isProtected,
GrGpuFinishedProc finishedProc = nullptr,
GrGpuFinishedContext finishedContext = nullptr,
std::string_view label = {});
// Deprecated versions that do not take origin and assume top-left.
GrBackendTexture createBackendTexture(const SkPixmap srcData[],
int numLevels,
GrRenderable renderable,
GrProtected isProtected,
GrGpuFinishedProc finishedProc = nullptr,
GrGpuFinishedContext finishedContext = nullptr,
std::string_view label = {});
GrBackendTexture createBackendTexture(const SkPixmap& srcData,
GrRenderable renderable,
GrProtected isProtected,
GrGpuFinishedProc finishedProc = nullptr,
GrGpuFinishedContext finishedContext = nullptr,
std::string_view label = {});
/**
* If possible , updates a backend texture to be filled to a particular color . The client should
* check the return value to see if the update was successful . The client can pass in a
* finishedProc to be notified when the data has been uploaded by the gpu and the texture can be
* deleted . The client is required to call ` submit ` to send the upload work to the gpu .
* The finishedProc will always get called even if we failed to update the GrBackendTexture .
* For the Vulkan backend after a successful update the layout of the created VkImage will be :
* VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
*/
bool updateBackendTexture(const GrBackendTexture&,
const SkColor4f& color,
GrGpuFinishedProc finishedProc,
GrGpuFinishedContext finishedContext);
/**
* If possible , updates a backend texture to be filled to a particular color . The data in
* GrBackendTexture and passed in color is interpreted with respect to the passed in
* SkColorType . The client should check the return value to see if the update was successful .
* The client can pass in a finishedProc to be notified when the data has been uploaded by the
* gpu and the texture can be deleted . The client is required to call ` submit ` to send
* the upload work to the gpu . The finishedProc will always get called even if we failed to
* update the GrBackendTexture .
* For the Vulkan backend after a successful update the layout of the created VkImage will be :
* VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
*/
bool updateBackendTexture(const GrBackendTexture&,
SkColorType skColorType,
const SkColor4f& color,
GrGpuFinishedProc finishedProc,
GrGpuFinishedContext finishedContext);
/**
* If possible , updates a backend texture filled with the provided pixmap data . The client
* should check the return value to see if the update was successful . The client can pass in a
* finishedProc to be notified when the data has been uploaded by the gpu and the texture can be
* deleted . The client is required to call ` submit ` to send the upload work to the gpu .
* The finishedProc will always get called even if we failed to create the GrBackendTexture .
* The backend texture must be compatible with the provided pixmap ( s ) . Compatible , in this case ,
* means that the backend format is compatible with the base pixmap ' s colortype . The src data
* can be deleted when this call returns .
* If the backend texture is mip mapped , the data for all the mipmap levels must be provided .
* In the mipmapped case all the colortypes of the provided pixmaps must be the same .
* Additionally , all the miplevels must be sized correctly ( please see
* SkMipmap : : ComputeLevelSize and ComputeLevelCount ) . The GrSurfaceOrigin controls whether the
* pixmap data is vertically flipped in the texture .
* Note : the pixmap ' s alphatypes and colorspaces are ignored .
* For the Vulkan backend after a successful update the layout of the created VkImage will be :
* VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
*/
bool updateBackendTexture(const GrBackendTexture&,
const SkPixmap srcData[],
int numLevels,
GrSurfaceOrigin = kTopLeft_GrSurfaceOrigin,
GrGpuFinishedProc finishedProc = nullptr,
GrGpuFinishedContext finishedContext = nullptr);
/**
* Convenience version of updateBackendTexture that takes just a base level pixmap .
*/
bool updateBackendTexture(const GrBackendTexture& texture,
const SkPixmap& srcData,
GrSurfaceOrigin textureOrigin = kTopLeft_GrSurfaceOrigin,
GrGpuFinishedProc finishedProc = nullptr,
GrGpuFinishedContext finishedContext = nullptr) {
return this ->updateBackendTexture(texture,
&srcData,
1 ,
textureOrigin,
finishedProc,
finishedContext);
}
// Deprecated version that does not take origin and assumes top-left.
bool updateBackendTexture(const GrBackendTexture& texture,
const SkPixmap srcData[],
int numLevels,
GrGpuFinishedProc finishedProc,
GrGpuFinishedContext finishedContext);
/**
* Retrieve the GrBackendFormat for a given SkTextureCompressionType . This is
* guaranteed to match the backend format used by the following
* createCompressedBackendTexture methods that take a CompressionType .
*
* The caller should check that the returned format is valid .
*/
using GrRecordingContext::compressedBackendFormat;
/**
* If possible , create a compressed backend texture initialized to a particular color . The
* client should ensure that the returned backend texture is valid . The client can pass in a
* finishedProc to be notified when the data has been uploaded by the gpu and the texture can be
* deleted . The client is required to call ` submit ` to send the upload work to the gpu .
* The finishedProc will always get called even if we failed to create the GrBackendTexture .
* For the Vulkan backend the layout of the created VkImage will be :
* VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
*/
GrBackendTexture createCompressedBackendTexture(int width,
int height,
const GrBackendFormat&,
const SkColor4f& color,
skgpu::Mipmapped,
GrProtected = GrProtected::kNo,
GrGpuFinishedProc finishedProc = nullptr,
GrGpuFinishedContext finishedContext = nullptr);
GrBackendTexture createCompressedBackendTexture(int width,
int height,
SkTextureCompressionType,
const SkColor4f& color,
skgpu::Mipmapped,
GrProtected = GrProtected::kNo,
GrGpuFinishedProc finishedProc = nullptr,
GrGpuFinishedContext finishedContext = nullptr);
/**
* If possible , create a backend texture initialized with the provided raw data . The client
* should ensure that the returned backend texture is valid . The client can pass in a
* finishedProc to be notified when the data has been uploaded by the gpu and the texture can be
* deleted . The client is required to call ` submit ` to send the upload work to the gpu .
* The finishedProc will always get called even if we failed to create the GrBackendTexture
* If numLevels is 1 a non - mipmapped texture will result . If a mipmapped texture is desired
* the data for all the mipmap levels must be provided . Additionally , all the miplevels
* must be sized correctly ( please see SkMipmap : : ComputeLevelSize and ComputeLevelCount ) .
* For the Vulkan backend the layout of the created VkImage will be :
* VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
*/
GrBackendTexture createCompressedBackendTexture(int width,
int height,
const GrBackendFormat&,
const void * data,
size_t dataSize,
skgpu::Mipmapped,
GrProtected = GrProtected::kNo,
GrGpuFinishedProc finishedProc = nullptr,
GrGpuFinishedContext finishedContext = nullptr);
GrBackendTexture createCompressedBackendTexture(int width,
int height,
SkTextureCompressionType,
const void * data,
size_t dataSize,
skgpu::Mipmapped,
GrProtected = GrProtected::kNo,
GrGpuFinishedProc finishedProc = nullptr,
GrGpuFinishedContext finishedContext = nullptr);
/**
* If possible , updates a backend texture filled with the provided color . If the texture is
* mipmapped , all levels of the mip chain will be updated to have the supplied color . The client
* should check the return value to see if the update was successful . The client can pass in a
* finishedProc to be notified when the data has been uploaded by the gpu and the texture can be
* deleted . The client is required to call ` submit ` to send the upload work to the gpu .
* The finishedProc will always get called even if we failed to create the GrBackendTexture .
* For the Vulkan backend after a successful update the layout of the created VkImage will be :
* VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
*/
bool updateCompressedBackendTexture(const GrBackendTexture&,
const SkColor4f& color,
GrGpuFinishedProc finishedProc,
GrGpuFinishedContext finishedContext);
/**
* If possible , updates a backend texture filled with the provided raw data . The client
* should check the return value to see if the update was successful . The client can pass in a
* finishedProc to be notified when the data has been uploaded by the gpu and the texture can be
* deleted . The client is required to call ` submit ` to send the upload work to the gpu .
* The finishedProc will always get called even if we failed to create the GrBackendTexture .
* If a mipmapped texture is passed in , the data for all the mipmap levels must be provided .
* Additionally , all the miplevels must be sized correctly ( please see
* SkMipMap : : ComputeLevelSize and ComputeLevelCount ) .
* For the Vulkan backend after a successful update the layout of the created VkImage will be :
* VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
*/
bool updateCompressedBackendTexture(const GrBackendTexture&,
const void * data,
size_t dataSize,
GrGpuFinishedProc finishedProc,
GrGpuFinishedContext finishedContext);
/**
* Updates the state of the GrBackendTexture / RenderTarget to have the passed in
* skgpu : : MutableTextureState . All objects that wrap the backend surface ( i . e . SkSurfaces and
* SkImages ) will also be aware of this state change . This call does not submit the state change
* to the gpu , but requires the client to call ` submit ` to send it to the GPU . The work
* for this call is ordered linearly with all other calls that require GrContext : : submit to be
* called ( e . g updateBackendTexture and flush ) . If finishedProc is not null then it will be
* called with finishedContext after the state transition is known to have occurred on the GPU .
*
* See skgpu : : MutableTextureState to see what state can be set via this call .
*
* If the backend API is Vulkan , the caller can set the skgpu : : MutableTextureState ' s
* VkImageLayout to VK_IMAGE_LAYOUT_UNDEFINED or queueFamilyIndex to VK_QUEUE_FAMILY_IGNORED to
* tell Skia to not change those respective states .
*
* If previousState is not null and this returns true , then Skia will have filled in
* previousState to have the values of the state before this call .
*/
bool setBackendTextureState(const GrBackendTexture&,
const skgpu::MutableTextureState&,
skgpu::MutableTextureState* previousState = nullptr,
GrGpuFinishedProc finishedProc = nullptr,
GrGpuFinishedContext finishedContext = nullptr);
bool setBackendRenderTargetState(const GrBackendRenderTarget&,
const skgpu::MutableTextureState&,
skgpu::MutableTextureState* previousState = nullptr,
GrGpuFinishedProc finishedProc = nullptr,
GrGpuFinishedContext finishedContext = nullptr);
void deleteBackendTexture(const GrBackendTexture&);
// This interface allows clients to pre-compile shaders and populate the runtime program cache.
// The key and data blobs should be the ones passed to the PersistentCache, in SkSL format.
//
// Steps to use this API:
//
// 1) Create a GrDirectContext as normal, but set fPersistentCache on GrContextOptions to
// something that will save the cached shader blobs. Set fShaderCacheStrategy to kSkSL. This
// will ensure that the blobs are SkSL, and are suitable for pre-compilation.
// 2) Run your application, and save all of the key/data pairs that are fed to the cache.
//
// 3) Switch over to shipping your application. Include the key/data pairs from above.
// 4) At startup (or any convenient time), call precompileShader for each key/data pair.
// This will compile the SkSL to create a GL program, and populate the runtime cache.
//
// This is only guaranteed to work if the context/device used in step #2 are created in the
// same way as the one used in step #4, and the same GrContextOptions are specified.
// Using cached shader blobs on a different device or driver are undefined.
bool precompileShader(const SkData& key, const SkData& data);
#ifdef SK_ENABLE_DUMP_GPU
/** Returns a string with detailed information about the context & GPU, in JSON format. */
SkString dump() const ;
#endif
class DirectContextID {
public :
static GrDirectContext::DirectContextID Next();
DirectContextID() : fID(SK_InvalidUniqueID) {}
bool operator ==(const DirectContextID& that) const { return fID == that.fID; }
bool operator !=(const DirectContextID& that) const { return !(*this == that); }
void makeInvalid() { fID = SK_InvalidUniqueID; }
bool isValid() const { return fID != SK_InvalidUniqueID; }
private :
constexpr DirectContextID(uint32_t id) : fID(id) {}
uint32_t fID;
};
DirectContextID directContextID() const { return fDirectContextID; }
// Provides access to functions that aren't part of the public API.
GrDirectContextPriv priv();
const GrDirectContextPriv priv() const ; // NOLINT(readability-const-return-type)
protected :
GrDirectContext(GrBackendApi backend,
const GrContextOptions& options,
sk_sp<GrContextThreadSafeProxy> proxy);
bool init() override;
GrAtlasManager* onGetAtlasManager() { return fAtlasManager.get(); }
#if !defined (SK_ENABLE_OPTIMIZE_SIZE)
skgpu::ganesh::SmallPathAtlasMgr* onGetSmallPathAtlasMgr();
#endif
GrDirectContext* asDirectContext() override { return this ; }
private :
// This call will make sure out work on the GPU is finished and will execute any outstanding
// asynchronous work (e.g. calling finished procs, freeing resources, etc.) related to the
// outstanding work on the gpu. The main use currently for this function is when tearing down or
// abandoning the context.
//
// When we finish up work on the GPU it could trigger callbacks to the client. In the case we
// are abandoning the context we don't want the client to be able to use the GrDirectContext to
// issue more commands during the callback. Thus before calling this function we set the
// GrDirectContext's state to be abandoned. However, we need to be able to get by the abaonded
// check in the call to know that it is safe to execute this. The shouldExecuteWhileAbandoned
// bool is used for this signal.
void syncAllOutstandingGpuWork(bool shouldExecuteWhileAbandoned);
// This delete callback needs to be the first thing on the GrDirectContext so that it is the
// last thing destroyed. The callback may signal the client to clean up things that may need
// to survive the lifetime of some of the other objects on the GrDirectCotnext. So make sure
// we don't call it until all else has been destroyed.
class DeleteCallbackHelper {
public :
DeleteCallbackHelper(GrDirectContextDestroyedContext context,
GrDirectContextDestroyedProc proc)
: fContext(context), fProc(proc) {}
~DeleteCallbackHelper() {
if (fProc) {
fProc(fContext);
}
}
private :
GrDirectContextDestroyedContext fContext;
GrDirectContextDestroyedProc fProc;
};
std::unique_ptr<DeleteCallbackHelper> fDeleteCallbackHelper;
const DirectContextID fDirectContextID;
// fTaskGroup must appear before anything that uses it (e.g. fGpu), so that it is destroyed
// after all of its users. Clients of fTaskGroup will generally want to ensure that they call
// wait() on it as they are being destroyed, to avoid the possibility of pending tasks being
// invoked after objects they depend upon have already been destroyed.
std::unique_ptr<SkTaskGroup> fTaskGroup;
std::unique_ptr<sktext::gpu::StrikeCache> fStrikeCache;
std::unique_ptr<GrGpu> fGpu;
std::unique_ptr<GrResourceCache> fResourceCache;
std::unique_ptr<GrResourceProvider> fResourceProvider;
// This is incremented before we start calling ReleaseProcs from GrSurfaces and decremented
// after. A ReleaseProc may trigger code causing another resource to get freed so we to track
// the count to know if we in a ReleaseProc at any level. When this is set to a value greated
// than zero we will not allow abandonContext calls to be made on the context.
int fInsideReleaseProcCnt = 0 ;
bool fDidTestPMConversions;
// true if the PM/UPM conversion succeeded; false otherwise
bool fPMUPMConversionsRoundTrip;
GrContextOptions::PersistentCache* fPersistentCache;
std::unique_ptr<GrClientMappedBufferManager> fMappedBufferManager;
std::unique_ptr<GrAtlasManager> fAtlasManager;
#if !defined (SK_ENABLE_OPTIMIZE_SIZE)
std::unique_ptr<skgpu::ganesh::SmallPathAtlasMgr> fSmallPathAtlasMgr;
#endif
friend class GrDirectContextPriv;
};
#endif
Messung V0.5 in Prozent C=90 H=100 G=95
¤ Dauer der Verarbeitung: 0.33 Sekunden
(vorverarbeitet am 2026-09-30)
¤
*© Formatika GbR, Deutschland