/* * Copyright 2016 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef GrSurfaceProxy_DEFINED #define GrSurfaceProxy_DEFINED #include "GrGpuResource.h" #include "GrSurface.h" #include "SkRect.h" class GrOpList; class GrTextureProxy; class GrRenderTargetProxy; // This class replicates the functionality GrIORef but tracks the // utilitization for later resource allocation (for the deferred case) and // forwards on the utilization in the wrapped case class GrIORefProxy : public SkNoncopyable { public: void ref() const { this->validate(); ++fRefCnt; if (fTarget) { fTarget->ref(); } } void unref() const { this->validate(); if (fTarget) { fTarget->unref(); } if (!(--fRefCnt)) { delete this; return; } this->validate(); } void validate() const { #ifdef SK_DEBUG SkASSERT(fRefCnt >= 0); #endif } protected: GrIORefProxy() : fRefCnt(1), fTarget(nullptr) {} GrIORefProxy(sk_sp surface) : fRefCnt(1) { // Since we're manually forwarding on refs & unrefs we don't want sk_sp doing // anything extra. fTarget = surface.release(); } virtual ~GrIORefProxy() { // We don't unref 'fTarget' here since the 'unref' method will already // have forwarded on the unref call that got use here. } // TODO: add the IO ref counts. Although if we can delay shader creation to flush time // we may not even need to do that. mutable int32_t fRefCnt; // For deferred proxies this will be null. For wrapped proxies it will point to the // wrapped resource. GrSurface* fTarget; }; class GrSurfaceProxy : public GrIORefProxy { public: const GrSurfaceDesc& desc() const { return fDesc; } GrSurfaceOrigin origin() const { SkASSERT(kTopLeft_GrSurfaceOrigin == fDesc.fOrigin || kBottomLeft_GrSurfaceOrigin == fDesc.fOrigin); return fDesc.fOrigin; } int width() const { return fDesc.fWidth; } int height() const { return fDesc.fHeight; } GrPixelConfig config() const { return fDesc.fConfig; } uint32_t uniqueID() const { return fUniqueID; } /** * Helper that gets the width and height of the surface as a bounding rectangle. */ SkRect getBoundsRect() const { return SkRect::MakeIWH(this->width(), this->height()); } /** * @return the texture proxy associated with the surface proxy, may be NULL. */ virtual GrTextureProxy* asTextureProxy() { return nullptr; } virtual const GrTextureProxy* asTextureProxy() const { return nullptr; } /** * @return the render target proxy associated with the surface proxy, may be NULL. */ virtual GrRenderTargetProxy* asRenderTargetProxy() { return nullptr; } virtual const GrRenderTargetProxy* asRenderTargetProxy() const { return nullptr; } /** * Does the resource count against the resource budget? */ SkBudgeted isBudgeted() const { return fBudgeted; } void setLastOpList(GrOpList* opList); GrOpList* getLastOpList() { return fLastOpList; } /** * Retrieves the amount of GPU memory that will be or currently is used by this resource * in bytes. It is approximate since we aren't aware of additional padding or copies made * by the driver. * * @return the amount of GPU memory used in bytes */ size_t gpuMemorySize() const { if (fTarget) { return fTarget->gpuMemorySize(); } if (kInvalidGpuMemorySize == fGpuMemorySize) { fGpuMemorySize = this->onGpuMemorySize(); SkASSERT(kInvalidGpuMemorySize != fGpuMemorySize); } return fGpuMemorySize; } protected: // Deferred version GrSurfaceProxy(const GrSurfaceDesc& desc, SkBackingFit fit, SkBudgeted budgeted) : fDesc(desc) , fFit(fit) , fBudgeted(budgeted) , fUniqueID(GrGpuResource::CreateUniqueID()) , fGpuMemorySize(kInvalidGpuMemorySize) , fLastOpList(nullptr) { } // Wrapped version GrSurfaceProxy(sk_sp surface, SkBackingFit fit); virtual ~GrSurfaceProxy(); // For wrapped resources, 'fDesc' will always be filled in from the wrapped resource. const GrSurfaceDesc fDesc; const SkBackingFit fFit; // always exact for wrapped resources const SkBudgeted fBudgeted; // set from the backing resource for wrapped resources const uint32_t fUniqueID; // set from the backing resource for wrapped resources static const size_t kInvalidGpuMemorySize = ~static_cast(0); // This entry is lazily evaluated so, when the proxy wraps a resource, the resource // will be called but, when the proxy is deferred, it will compute the answer itself. // If the proxy computes its own answer that answer is checked (in debug mode) in // the instantiation method. mutable size_t fGpuMemorySize; private: virtual size_t onGpuMemorySize() const = 0; // The last opList that wrote to or is currently going to write to this surface // The opList can be closed (e.g., no render target context is currently bound // to this renderTarget). // This back-pointer is required so that we can add a dependancy between // the opList used to create the current contents of this surface // and the opList of a destination surface to which this one is being drawn or copied. GrOpList* fLastOpList; typedef GrIORefProxy INHERITED; }; #endif