1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2017 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#ifndef GrDeferredProxyUploader_DEFINED 9cb93a386Sopenharmony_ci#define GrDeferredProxyUploader_DEFINED 10cb93a386Sopenharmony_ci 11cb93a386Sopenharmony_ci#include "include/core/SkRefCnt.h" 12cb93a386Sopenharmony_ci#include "include/private/SkSemaphore.h" 13cb93a386Sopenharmony_ci#include "src/core/SkAutoPixmapStorage.h" 14cb93a386Sopenharmony_ci 15cb93a386Sopenharmony_ci#include "src/gpu/GrOpFlushState.h" 16cb93a386Sopenharmony_ci#include "src/gpu/GrTextureProxyPriv.h" 17cb93a386Sopenharmony_ci 18cb93a386Sopenharmony_ci/** 19cb93a386Sopenharmony_ci * GrDeferredProxyUploader assists with threaded generation of textures. Currently used by both 20cb93a386Sopenharmony_ci * software clip masks, and the software path renderer. The calling code typically needs to store 21cb93a386Sopenharmony_ci * some additional data (T) for use on the worker thread. GrTDeferredProxyUploader allows storing 22cb93a386Sopenharmony_ci * such data. The common flow is: 23cb93a386Sopenharmony_ci * 24cb93a386Sopenharmony_ci * 1) A GrTDeferredProxyUploader is created, with some payload (eg an SkPath to draw). 25cb93a386Sopenharmony_ci * The uploader is owned by the proxy that it's going to populate. 26cb93a386Sopenharmony_ci * 2) A task is created with a pointer to the uploader. A worker thread executes that task, using 27cb93a386Sopenharmony_ci * the payload data to allocate and fill in the fPixels pixmap. 28cb93a386Sopenharmony_ci * 3) The worker thread calls signalAndFreeData(), which notifies the main thread that the pixmap 29cb93a386Sopenharmony_ci * is ready, and then deletes the payload data (which is no longer needed). 30cb93a386Sopenharmony_ci * 4) In parallel to 2-3, on the main thread... Some op is created that refers to the proxy. When 31cb93a386Sopenharmony_ci * that op is added to an op list, the op list retains a pointer to the "deferred" proxies. 32cb93a386Sopenharmony_ci * 5) At flush time, the op list ensures that the deferred proxies are instantiated, then calls 33cb93a386Sopenharmony_ci * scheduleUpload on those proxies, which calls scheduleUpload on the uploader (below). 34cb93a386Sopenharmony_ci * 6) scheduleUpload defers the upload even further, by adding an ASAPUpload to the flush. 35cb93a386Sopenharmony_ci * 7) When the ASAP upload happens, we wait to make sure that the pixels are marked ready 36cb93a386Sopenharmony_ci * (from step #3 on the worker thread). Then we perform the actual upload to the texture. 37cb93a386Sopenharmony_ci * Finally, we call resetDeferredUploader, which deletes the uploader object, causing fPixels 38cb93a386Sopenharmony_ci * to be freed. 39cb93a386Sopenharmony_ci */ 40cb93a386Sopenharmony_ciclass GrDeferredProxyUploader : public SkNoncopyable { 41cb93a386Sopenharmony_cipublic: 42cb93a386Sopenharmony_ci GrDeferredProxyUploader() : fScheduledUpload(false), fWaited(false) {} 43cb93a386Sopenharmony_ci 44cb93a386Sopenharmony_ci virtual ~GrDeferredProxyUploader() { 45cb93a386Sopenharmony_ci // In normal usage (i.e., through GrTDeferredProxyUploader) this will be redundant 46cb93a386Sopenharmony_ci this->wait(); 47cb93a386Sopenharmony_ci } 48cb93a386Sopenharmony_ci 49cb93a386Sopenharmony_ci void scheduleUpload(GrOpFlushState* flushState, GrTextureProxy* proxy) { 50cb93a386Sopenharmony_ci if (fScheduledUpload) { 51cb93a386Sopenharmony_ci // Multiple references to the owning proxy may have caused us to already execute 52cb93a386Sopenharmony_ci return; 53cb93a386Sopenharmony_ci } 54cb93a386Sopenharmony_ci 55cb93a386Sopenharmony_ci auto uploadMask = [this, proxy](GrDeferredTextureUploadWritePixelsFn& writePixelsFn) { 56cb93a386Sopenharmony_ci this->wait(); 57cb93a386Sopenharmony_ci GrColorType pixelColorType = SkColorTypeToGrColorType(this->fPixels.info().colorType()); 58cb93a386Sopenharmony_ci // If the worker thread was unable to allocate pixels, this check will fail, and we'll 59cb93a386Sopenharmony_ci // end up drawing with an uninitialized mask texture, but at least we won't crash. 60cb93a386Sopenharmony_ci if (this->fPixels.addr()) { 61cb93a386Sopenharmony_ci writePixelsFn(proxy, 62cb93a386Sopenharmony_ci SkIRect::MakeSize(fPixels.dimensions()), 63cb93a386Sopenharmony_ci pixelColorType, 64cb93a386Sopenharmony_ci this->fPixels.addr(), 65cb93a386Sopenharmony_ci this->fPixels.rowBytes()); 66cb93a386Sopenharmony_ci } 67cb93a386Sopenharmony_ci // Upload has finished, so tell the proxy to release this GrDeferredProxyUploader 68cb93a386Sopenharmony_ci proxy->texPriv().resetDeferredUploader(); 69cb93a386Sopenharmony_ci }; 70cb93a386Sopenharmony_ci flushState->addASAPUpload(std::move(uploadMask)); 71cb93a386Sopenharmony_ci fScheduledUpload = true; 72cb93a386Sopenharmony_ci } 73cb93a386Sopenharmony_ci 74cb93a386Sopenharmony_ci void signalAndFreeData() { 75cb93a386Sopenharmony_ci this->freeData(); 76cb93a386Sopenharmony_ci fPixelsReady.signal(); 77cb93a386Sopenharmony_ci } 78cb93a386Sopenharmony_ci 79cb93a386Sopenharmony_ci SkAutoPixmapStorage* getPixels() { return &fPixels; } 80cb93a386Sopenharmony_ci 81cb93a386Sopenharmony_ciprotected: 82cb93a386Sopenharmony_ci void wait() { 83cb93a386Sopenharmony_ci if (!fWaited) { 84cb93a386Sopenharmony_ci fPixelsReady.wait(); 85cb93a386Sopenharmony_ci fWaited = true; 86cb93a386Sopenharmony_ci } 87cb93a386Sopenharmony_ci } 88cb93a386Sopenharmony_ci 89cb93a386Sopenharmony_ciprivate: 90cb93a386Sopenharmony_ci virtual void freeData() {} 91cb93a386Sopenharmony_ci 92cb93a386Sopenharmony_ci SkAutoPixmapStorage fPixels; 93cb93a386Sopenharmony_ci SkSemaphore fPixelsReady; 94cb93a386Sopenharmony_ci bool fScheduledUpload; 95cb93a386Sopenharmony_ci bool fWaited; 96cb93a386Sopenharmony_ci}; 97cb93a386Sopenharmony_ci 98cb93a386Sopenharmony_citemplate <typename T> 99cb93a386Sopenharmony_ciclass GrTDeferredProxyUploader : public GrDeferredProxyUploader { 100cb93a386Sopenharmony_cipublic: 101cb93a386Sopenharmony_ci template <typename... Args> 102cb93a386Sopenharmony_ci GrTDeferredProxyUploader(Args&&... args) 103cb93a386Sopenharmony_ci : fData(std::make_unique<T>(std::forward<Args>(args)...)) { 104cb93a386Sopenharmony_ci } 105cb93a386Sopenharmony_ci 106cb93a386Sopenharmony_ci ~GrTDeferredProxyUploader() override { 107cb93a386Sopenharmony_ci // We need to wait here, so that we don't free fData before the worker thread is done 108cb93a386Sopenharmony_ci // with it. (This happens if the proxy is deleted early due to a full clear or failure 109cb93a386Sopenharmony_ci // of an op list to instantiate). 110cb93a386Sopenharmony_ci this->wait(); 111cb93a386Sopenharmony_ci } 112cb93a386Sopenharmony_ci 113cb93a386Sopenharmony_ci T& data() { return *fData; } 114cb93a386Sopenharmony_ci 115cb93a386Sopenharmony_ciprivate: 116cb93a386Sopenharmony_ci void freeData() override { 117cb93a386Sopenharmony_ci fData.reset(); 118cb93a386Sopenharmony_ci } 119cb93a386Sopenharmony_ci 120cb93a386Sopenharmony_ci std::unique_ptr<T> fData; 121cb93a386Sopenharmony_ci}; 122cb93a386Sopenharmony_ci 123cb93a386Sopenharmony_ci#endif 124