Migrate flush & misc methods to GrDirectContext
More cut and paste work.
Change-Id: I0dfc822ae168e15c6734a6c079bb930fc0fa9e60
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/325618
Commit-Queue: Adlai Holler <adlai@google.com>
Auto-Submit: Adlai Holler <adlai@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/include/gpu/GrDirectContext.h b/include/gpu/GrDirectContext.h
index 9ec2f86..38051fc 100644
--- a/include/gpu/GrDirectContext.h
+++ b/include/gpu/GrDirectContext.h
@@ -274,6 +274,105 @@
*/
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. 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.
+ */
+ 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 3D
+ * API. This is equivalent to calling GrContext::flush with a default GrFlushInfo followed by
+ * GrContext::submit(syncCpu).
+ */
+ void flushAndSubmit(bool syncCpu = false) {
+ this->flush(GrFlushInfo());
+ this->submit(syncCpu);
+ }
+
+ /**
+ * Call to ensure all drawing to the context has been flushed to underlying 3D 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.
+ * Regardleess 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({}); }
+
+ /**
+ * 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 the syncCpu flag is true this function will return once the gpu has finished with all
+ * submitted work.
+ */
+ bool submit(bool syncCpu = false);
+
+ /**
+ * 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;
+
+ void storeVkPipelineCacheData();
+
+ // Returns the gpu memory size of the the texture that backs the passed in SkImage. Returns 0 if
+ // the SkImage is not texture backed. For external format textures this will also return 0 as we
+ // cannot determine the correct size.
+ static size_t ComputeImageSize(sk_sp<SkImage> image, GrMipmapped, bool useNextPow2 = false);
+
+ /**
+ * 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 SkSurfaceCharacterization-based createBackendTexture methods.
+ *
+ * The caller should check that the returned format is valid.
+ */
+ GrBackendFormat defaultBackendFormat(SkColorType ct, GrRenderable renderable) const {
+ return INHERITED::defaultBackendFormat(ct, renderable);
+ }
protected:
GrDirectContext(GrBackendApi backend, const GrContextOptions& options);
diff --git a/include/private/GrContext.h b/include/private/GrContext.h
index 92c5eea..3da11b0 100644
--- a/include/private/GrContext.h
+++ b/include/private/GrContext.h
@@ -57,110 +57,6 @@
public:
~GrContext() override;
- ///////////////////////////////////////////////////////////////////////////
- // Misc.
-
- /**
- * Inserts a list of GPU semaphores that the current GPU-backed API must wait on before
- * executing any more commands on the GPU. 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.
- */
- 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 3D
- * API. This is equivalent to calling GrContext::flush with a default GrFlushInfo followed by
- * GrContext::submit(syncCpu).
- */
- void flushAndSubmit(bool syncCpu = false) {
- this->flush(GrFlushInfo());
- this->submit(syncCpu);
- }
-
- /**
- * Call to ensure all drawing to the context has been flushed to underlying 3D API specific
- * objects. A call to GrContext::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.
- * Regardleess 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({}); }
-
- /**
- * 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 the syncCpu flag is true this function will return once the gpu has finished with all
- * submitted work.
- */
- bool submit(bool syncCpu = false);
-
- /**
- * Checks whether any asynchronous work is complete and if so calls related callbacks.
- */
- void checkAsyncWorkCompletion();
-
- // Provides access to functions that aren't part of the public API.
- GrContextPriv priv();
- const GrContextPriv priv() const; // NOLINT(readability-const-return-type)
-
- /** Enumerates all cached GPU resources and dumps their memory to traceMemoryDump. */
- // Chrome is using this!
- void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const;
-
- bool supportsDistanceFieldText() const;
-
- void storeVkPipelineCacheData();
-
- // Returns the gpu memory size of the the texture that backs the passed in SkImage. Returns 0 if
- // the SkImage is not texture backed. For external format textures this will also return 0 as we
- // cannot determine the correct size.
- static size_t ComputeImageSize(sk_sp<SkImage> image, GrMipmapped, bool useNextPow2 = false);
-
- /**
- * 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 SkSurfaceCharacterization-based createBackendTexture methods.
- *
- * The caller should check that the returned format is valid.
- */
- GrBackendFormat defaultBackendFormat(SkColorType ct, GrRenderable renderable) const {
- return INHERITED::defaultBackendFormat(ct, renderable);
- }
-
/**
* 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.)
@@ -478,6 +374,9 @@
SkString dump() const;
#endif
+ // Provides access to functions that aren't part of the public API.
+ GrContextPriv priv();
+ const GrContextPriv priv() const; // NOLINT(readability-const-return-type)
protected:
GrContext(sk_sp<GrContextThreadSafeProxy>);
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 183cd59..575adf9 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -48,114 +48,10 @@
#define RETURN_FALSE_IF_ABANDONED if (this->abandoned()) { return false; }
#define RETURN_NULL_IF_ABANDONED if (this->abandoned()) { return nullptr; }
-////////////////////////////////////////////////////////////////////////////////
-
GrContext::GrContext(sk_sp<GrContextThreadSafeProxy> proxy) : INHERITED(std::move(proxy)) { }
GrContext::~GrContext() = default;
-size_t GrContext::ComputeImageSize(sk_sp<SkImage> image, GrMipmapped mipMapped, bool useNextPow2) {
- if (!image->isTextureBacked()) {
- return 0;
- }
- SkImage_GpuBase* gpuImage = static_cast<SkImage_GpuBase*>(as_IB(image.get()));
- GrTextureProxy* proxy = gpuImage->peekProxy();
- if (!proxy) {
- return 0;
- }
-
- int colorSamplesPerPixel = 1;
- return GrSurface::ComputeSize(proxy->backendFormat(), image->dimensions(),
- colorSamplesPerPixel, mipMapped, useNextPow2);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-bool GrContext::wait(int numSemaphores, const GrBackendSemaphore waitSemaphores[],
- bool deleteSemaphoresAfterWait) {
- if (!fGpu || fGpu->caps()->semaphoreSupport()) {
- return false;
- }
- GrWrapOwnership ownership =
- deleteSemaphoresAfterWait ? kAdopt_GrWrapOwnership : kBorrow_GrWrapOwnership;
- for (int i = 0; i < numSemaphores; ++i) {
- std::unique_ptr<GrSemaphore> sema = fResourceProvider->wrapBackendSemaphore(
- waitSemaphores[i], GrResourceProvider::SemaphoreWrapType::kWillWait, ownership);
- // If we failed to wrap the semaphore it means the client didn't give us a valid semaphore
- // to begin with. Therefore, it is fine to not wait on it.
- if (sema) {
- fGpu->waitSemaphore(sema.get());
- }
- }
- return true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-GrSemaphoresSubmitted GrContext::flush(const GrFlushInfo& info) {
- ASSERT_SINGLE_OWNER
- if (this->abandoned()) {
- if (info.fFinishedProc) {
- info.fFinishedProc(info.fFinishedContext);
- }
- if (info.fSubmittedProc) {
- info.fSubmittedProc(info.fSubmittedContext, false);
- }
- return GrSemaphoresSubmitted::kNo;
- }
-
- bool flushed = this->drawingManager()->flush(
- nullptr, 0, SkSurface::BackendSurfaceAccess::kNoAccess, info, nullptr);
-
- if (!flushed || (!this->priv().caps()->semaphoreSupport() && info.fNumSemaphores)) {
- return GrSemaphoresSubmitted::kNo;
- }
- return GrSemaphoresSubmitted::kYes;
-}
-
-bool GrContext::submit(bool syncCpu) {
- ASSERT_SINGLE_OWNER
- if (this->abandoned()) {
- return false;
- }
-
- if (!fGpu) {
- return false;
- }
-
- return fGpu->submitToGpu(syncCpu);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-void GrContext::checkAsyncWorkCompletion() {
- if (fGpu) {
- fGpu->checkFinishProcs();
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-void GrContext::storeVkPipelineCacheData() {
- if (fGpu) {
- fGpu->storeVkPipelineCacheData();
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-bool GrContext::supportsDistanceFieldText() const {
- return this->caps()->shaderCaps()->supportsDistanceFieldText();
-}
-
-//////////////////////////////////////////////////////////////////////////////
-void GrContext::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
- ASSERT_SINGLE_OWNER
- fResourceCache->dumpMemoryStatistics(traceMemoryDump);
- traceMemoryDump->dumpNumericValue("skia/gr_text_blob_cache", "size", "bytes",
- this->getTextBlobCache()->usedBytes());
-}
-
-//////////////////////////////////////////////////////////////////////////////
GrBackendTexture GrContext::createBackendTexture(int width, int height,
const GrBackendFormat& backendFormat,
GrMipmapped mipMapped,
diff --git a/src/gpu/GrContextPriv.cpp b/src/gpu/GrContextPriv.cpp
index 5967304..476da52 100644
--- a/src/gpu/GrContextPriv.cpp
+++ b/src/gpu/GrContextPriv.cpp
@@ -173,7 +173,7 @@
}
void GrContextPriv::testingOnly_flushAndRemoveOnFlushCallbackObject(GrOnFlushCallbackObject* cb) {
- fContext->flushAndSubmit();
+ fContext->asDirectContext()->flushAndSubmit();
fContext->drawingManager()->testingOnly_removeOnFlushCallbackObject(cb);
}
#endif
diff --git a/src/gpu/GrDirectContext.cpp b/src/gpu/GrDirectContext.cpp
index f2e8f3f..78fa9ab 100644
--- a/src/gpu/GrDirectContext.cpp
+++ b/src/gpu/GrDirectContext.cpp
@@ -8,6 +8,7 @@
#include "include/gpu/GrDirectContext.h"
+#include "include/core/SkTraceMemoryDump.h"
#include "include/gpu/GrContextThreadSafeProxy.h"
#include "src/core/SkTaskGroup.h"
#include "src/gpu/GrClientMappedBufferManager.h"
@@ -17,6 +18,7 @@
#include "src/gpu/GrGpu.h"
#include "src/gpu/GrResourceProvider.h"
#include "src/gpu/GrShaderUtils.h"
+#include "src/image/SkImage_GpuBase.h"
#include "src/gpu/ccpr/GrCoverageCountingPathRenderer.h"
#include "src/gpu/effects/GrSkSLFP.h"
@@ -330,6 +332,25 @@
fResourceCache->purgeUnlockedResources(bytesToPurge, preferScratchResources);
}
+////////////////////////////////////////////////////////////////////////////////
+bool GrDirectContext::wait(int numSemaphores, const GrBackendSemaphore waitSemaphores[],
+ bool deleteSemaphoresAfterWait) {
+ if (!fGpu || fGpu->caps()->semaphoreSupport()) {
+ return false;
+ }
+ GrWrapOwnership ownership =
+ deleteSemaphoresAfterWait ? kAdopt_GrWrapOwnership : kBorrow_GrWrapOwnership;
+ for (int i = 0; i < numSemaphores; ++i) {
+ std::unique_ptr<GrSemaphore> sema = fResourceProvider->wrapBackendSemaphore(
+ waitSemaphores[i], GrResourceProvider::SemaphoreWrapType::kWillWait, ownership);
+ // If we failed to wrap the semaphore it means the client didn't give us a valid semaphore
+ // to begin with. Therefore, it is fine to not wait on it.
+ if (sema) {
+ fGpu->waitSemaphore(sema.get());
+ }
+ }
+ return true;
+}
GrSmallPathAtlasMgr* GrDirectContext::onGetSmallPathAtlasMgr() {
if (!fSmallPathAtlasMgr) {
@@ -345,6 +366,89 @@
return fSmallPathAtlasMgr.get();
}
+////////////////////////////////////////////////////////////////////////////////
+
+GrSemaphoresSubmitted GrDirectContext::flush(const GrFlushInfo& info) {
+ ASSERT_SINGLE_OWNER
+ if (this->abandoned()) {
+ if (info.fFinishedProc) {
+ info.fFinishedProc(info.fFinishedContext);
+ }
+ if (info.fSubmittedProc) {
+ info.fSubmittedProc(info.fSubmittedContext, false);
+ }
+ return GrSemaphoresSubmitted::kNo;
+ }
+
+ bool flushed = this->drawingManager()->flush(
+ nullptr, 0, SkSurface::BackendSurfaceAccess::kNoAccess, info, nullptr);
+
+ if (!flushed || (!this->priv().caps()->semaphoreSupport() && info.fNumSemaphores)) {
+ return GrSemaphoresSubmitted::kNo;
+ }
+ return GrSemaphoresSubmitted::kYes;
+}
+
+bool GrDirectContext::submit(bool syncCpu) {
+ ASSERT_SINGLE_OWNER
+ if (this->abandoned()) {
+ return false;
+ }
+
+ if (!fGpu) {
+ return false;
+ }
+
+ return fGpu->submitToGpu(syncCpu);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+void GrDirectContext::checkAsyncWorkCompletion() {
+ if (fGpu) {
+ fGpu->checkFinishProcs();
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+void GrDirectContext::storeVkPipelineCacheData() {
+ if (fGpu) {
+ fGpu->storeVkPipelineCacheData();
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+bool GrDirectContext::supportsDistanceFieldText() const {
+ return this->caps()->shaderCaps()->supportsDistanceFieldText();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void GrDirectContext::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
+ ASSERT_SINGLE_OWNER
+ fResourceCache->dumpMemoryStatistics(traceMemoryDump);
+ traceMemoryDump->dumpNumericValue("skia/gr_text_blob_cache", "size", "bytes",
+ this->getTextBlobCache()->usedBytes());
+}
+
+size_t GrDirectContext::ComputeImageSize(sk_sp<SkImage> image, GrMipmapped mipMapped,
+ bool useNextPow2) {
+ if (!image->isTextureBacked()) {
+ return 0;
+ }
+ SkImage_GpuBase* gpuImage = static_cast<SkImage_GpuBase*>(as_IB(image.get()));
+ GrTextureProxy* proxy = gpuImage->peekProxy();
+ if (!proxy) {
+ return 0;
+ }
+
+ int colorSamplesPerPixel = 1;
+ return GrSurface::ComputeSize(proxy->backendFormat(), image->dimensions(),
+ colorSamplesPerPixel, mipMapped, useNextPow2);
+}
+
#ifdef SK_GL
/*************************************************************************************************/
diff --git a/src/gpu/GrDrawingManager.h b/src/gpu/GrDrawingManager.h
index d41c61d..d3ac74b 100644
--- a/src/gpu/GrDrawingManager.h
+++ b/src/gpu/GrDrawingManager.h
@@ -203,6 +203,7 @@
SkDEBUGCODE(void validate() const);
friend class GrContext; // access to: flush & cleanup
+ friend class GrDirectContext; // access to: flush & cleanup
friend class GrContextPriv; // access to: flush
friend class GrOnFlushResourceProvider; // this is just a shallow wrapper around this class
friend class GrRecordingContext; // access to: ctor