Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright 2016 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "GrOpList.h"
      9 
     10 #include "GrContext.h"
     11 #include "GrDeferredProxyUploader.h"
     12 #include "GrSurfaceProxy.h"
     13 #include "GrTextureProxyPriv.h"
     14 
     15 #include "SkAtomics.h"
     16 
     17 uint32_t GrOpList::CreateUniqueID() {
     18     static int32_t gUniqueID = SK_InvalidUniqueID;
     19     uint32_t id;
     20     // Loop in case our global wraps around, as we never want to return a 0.
     21     do {
     22         id = static_cast<uint32_t>(sk_atomic_inc(&gUniqueID) + 1);
     23     } while (id == SK_InvalidUniqueID);
     24     return id;
     25 }
     26 
     27 GrOpList::GrOpList(GrResourceProvider* resourceProvider,
     28                    GrSurfaceProxy* surfaceProxy, GrAuditTrail* auditTrail)
     29     : fAuditTrail(auditTrail)
     30     , fUniqueID(CreateUniqueID())
     31     , fFlags(0) {
     32     fTarget.setProxy(sk_ref_sp(surfaceProxy), kWrite_GrIOType);
     33     fTarget.get()->setLastOpList(this);
     34 
     35     if (resourceProvider && !resourceProvider->explicitlyAllocateGPUResources()) {
     36         // MDB TODO: remove this! We are currently moving to having all the ops that target
     37         // the RT as a dest (e.g., clear, etc.) rely on the opList's 'fTarget' pointer
     38         // for the IO Ref. This works well but until they are all swapped over (and none
     39         // are pre-emptively instantiating proxies themselves) we need to instantiate
     40         // here so that the GrSurfaces are created in an order that preserves the GrSurface
     41         // re-use assumptions.
     42         fTarget.get()->instantiate(resourceProvider);
     43     }
     44 
     45     fTarget.markPendingIO();
     46 }
     47 
     48 GrOpList::~GrOpList() {
     49     if (fTarget.get() && this == fTarget.get()->getLastOpList()) {
     50         // Ensure the target proxy doesn't keep hold of a dangling back pointer.
     51         fTarget.get()->setLastOpList(nullptr);
     52     }
     53 }
     54 
     55 bool GrOpList::instantiate(GrResourceProvider* resourceProvider) {
     56     return SkToBool(fTarget.get()->instantiate(resourceProvider));
     57 }
     58 
     59 void GrOpList::endFlush() {
     60     if (fTarget.get() && this == fTarget.get()->getLastOpList()) {
     61         fTarget.get()->setLastOpList(nullptr);
     62     }
     63 
     64     fTarget.reset();
     65     fDeferredProxies.reset();
     66     fAuditTrail = nullptr;
     67 }
     68 
     69 void GrOpList::instantiateDeferredProxies(GrResourceProvider* resourceProvider) {
     70     for (int i = 0; i < fDeferredProxies.count(); ++i) {
     71         if (resourceProvider->explicitlyAllocateGPUResources()) {
     72             SkASSERT(fDeferredProxies[i]->priv().isInstantiated());
     73         } else {
     74             fDeferredProxies[i]->instantiate(resourceProvider);
     75         }
     76     }
     77 }
     78 
     79 void GrOpList::prepare(GrOpFlushState* flushState) {
     80     for (int i = 0; i < fDeferredProxies.count(); ++i) {
     81         fDeferredProxies[i]->texPriv().scheduleUpload(flushState);
     82     }
     83 
     84     this->onPrepare(flushState);
     85 }
     86 
     87 // Add a GrOpList-based dependency
     88 void GrOpList::addDependency(GrOpList* dependedOn) {
     89     SkASSERT(!dependedOn->dependsOn(this));  // loops are bad
     90 
     91     if (this->dependsOn(dependedOn)) {
     92         return;  // don't add duplicate dependencies
     93     }
     94 
     95     fDependencies.push_back(dependedOn);
     96 }
     97 
     98 // Convert from a GrSurface-based dependency to a GrOpList one
     99 void GrOpList::addDependency(GrSurfaceProxy* dependedOn, const GrCaps& caps) {
    100     if (dependedOn->getLastOpList()) {
    101         // If it is still receiving dependencies, this GrOpList shouldn't be closed
    102         SkASSERT(!this->isClosed());
    103 
    104         GrOpList* opList = dependedOn->getLastOpList();
    105         if (opList == this) {
    106             // self-read - presumably for dst reads
    107         } else {
    108             this->addDependency(opList);
    109 
    110             // Can't make it closed in the self-read case
    111             opList->makeClosed(caps);
    112         }
    113     }
    114 
    115     if (GrTextureProxy* textureProxy = dependedOn->asTextureProxy()) {
    116         if (textureProxy->texPriv().isDeferred()) {
    117             fDeferredProxies.push_back(textureProxy);
    118         }
    119     }
    120 }
    121 
    122 bool GrOpList::isInstantiated() const {
    123     return fTarget.get()->priv().isInstantiated();
    124 }
    125 
    126 #ifdef SK_DEBUG
    127 void GrOpList::dump() const {
    128     SkDebugf("--------------------------------------------------------------\n");
    129     SkDebugf("node: %d -> RT: %d\n", fUniqueID, fTarget.get() ? fTarget.get()->uniqueID().asUInt()
    130                                                               : -1);
    131     SkDebugf("relies On (%d): ", fDependencies.count());
    132     for (int i = 0; i < fDependencies.count(); ++i) {
    133         SkDebugf("%d, ", fDependencies[i]->fUniqueID);
    134     }
    135     SkDebugf("\n");
    136 }
    137 #endif
    138