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 #ifdef SK_DISABLE_EXPLICIT_GPU_RESOURCE_ALLOCATION
     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 #endif
     44     fTarget.markPendingIO();
     45 }
     46 
     47 GrOpList::~GrOpList() {
     48     if (fTarget.get() && this == fTarget.get()->getLastOpList()) {
     49         // Ensure the target proxy doesn't keep hold of a dangling back pointer.
     50         fTarget.get()->setLastOpList(nullptr);
     51     }
     52 }
     53 
     54 bool GrOpList::instantiate(GrResourceProvider* resourceProvider) {
     55     return SkToBool(fTarget.get()->instantiate(resourceProvider));
     56 }
     57 
     58 void GrOpList::endFlush() {
     59     if (fTarget.get() && this == fTarget.get()->getLastOpList()) {
     60         fTarget.get()->setLastOpList(nullptr);
     61     }
     62 
     63     fTarget.reset();
     64     fDeferredProxies.reset();
     65     fAuditTrail = nullptr;
     66 }
     67 
     68 void GrOpList::instantiateDeferredProxies(GrResourceProvider* resourceProvider) {
     69     for (int i = 0; i < fDeferredProxies.count(); ++i) {
     70 #ifdef SK_DISABLE_EXPLICIT_GPU_RESOURCE_ALLOCATION
     71         fDeferredProxies[i]->instantiate(resourceProvider);
     72 #else
     73         SkASSERT(fDeferredProxies[i]->priv().isInstantiated());
     74 #endif
     75     }
     76 }
     77 
     78 void GrOpList::prepare(GrOpFlushState* flushState) {
     79     for (int i = 0; i < fDeferredProxies.count(); ++i) {
     80         fDeferredProxies[i]->texPriv().scheduleUpload(flushState);
     81     }
     82 
     83     this->onPrepare(flushState);
     84 }
     85 
     86 // Add a GrOpList-based dependency
     87 void GrOpList::addDependency(GrOpList* dependedOn) {
     88     SkASSERT(!dependedOn->dependsOn(this));  // loops are bad
     89 
     90     if (this->dependsOn(dependedOn)) {
     91         return;  // don't add duplicate dependencies
     92     }
     93 
     94     fDependencies.push_back(dependedOn);
     95 }
     96 
     97 // Convert from a GrSurface-based dependency to a GrOpList one
     98 void GrOpList::addDependency(GrSurfaceProxy* dependedOn, const GrCaps& caps) {
     99     if (dependedOn->getLastOpList()) {
    100         // If it is still receiving dependencies, this GrOpList shouldn't be closed
    101         SkASSERT(!this->isClosed());
    102 
    103         GrOpList* opList = dependedOn->getLastOpList();
    104         if (opList == this) {
    105             // self-read - presumably for dst reads
    106         } else {
    107             this->addDependency(opList);
    108 
    109             // Can't make it closed in the self-read case
    110             opList->makeClosed(caps);
    111         }
    112     }
    113 
    114     if (GrTextureProxy* textureProxy = dependedOn->asTextureProxy()) {
    115         if (textureProxy->texPriv().isDeferred()) {
    116             fDeferredProxies.push_back(textureProxy);
    117         }
    118     }
    119 }
    120 
    121 #ifdef SK_DEBUG
    122 bool GrOpList::isInstantiated() const {
    123     return fTarget.get()->priv().isInstantiated();
    124 }
    125 
    126 void GrOpList::dump() const {
    127     SkDebugf("--------------------------------------------------------------\n");
    128     SkDebugf("node: %d -> RT: %d\n", fUniqueID, fTarget.get() ? fTarget.get()->uniqueID().asUInt()
    129                                                               : -1);
    130     SkDebugf("relies On (%d): ", fDependencies.count());
    131     for (int i = 0; i < fDependencies.count(); ++i) {
    132         SkDebugf("%d, ", fDependencies[i]->fUniqueID);
    133     }
    134     SkDebugf("\n");
    135 }
    136 #endif
    137