195740981c36266e4595ddde2264aa38e3c7e2d02bsalomon/*
295740981c36266e4595ddde2264aa38e3c7e2d02bsalomon * Copyright 2014 Google Inc.
395740981c36266e4595ddde2264aa38e3c7e2d02bsalomon *
495740981c36266e4595ddde2264aa38e3c7e2d02bsalomon * Use of this source code is governed by a BSD-style license that can be
595740981c36266e4595ddde2264aa38e3c7e2d02bsalomon * found in the LICENSE file.
695740981c36266e4595ddde2264aa38e3c7e2d02bsalomon */
795740981c36266e4595ddde2264aa38e3c7e2d02bsalomon
8f96ba02513eadd9fa24d75396ec9f2d6682e464cbsalomon#ifndef GrGpuResourceRef_DEFINED
9f96ba02513eadd9fa24d75396ec9f2d6682e464cbsalomon#define GrGpuResourceRef_DEFINED
1095740981c36266e4595ddde2264aa38e3c7e2d02bsalomon
1145725db1d82615d43408ec488549aec6218f80e4bsalomon#include "GrGpuResource.h"
1237dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon#include "GrRenderTarget.h"
1337dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon#include "GrTexture.h"
1495740981c36266e4595ddde2264aa38e3c7e2d02bsalomon#include "SkRefCnt.h"
1595740981c36266e4595ddde2264aa38e3c7e2d02bsalomon
1695740981c36266e4595ddde2264aa38e3c7e2d02bsalomon/**
17b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon * This class is intended only for internal use in core Gr code.
18b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon *
1995740981c36266e4595ddde2264aa38e3c7e2d02bsalomon * Class that wraps a resource referenced by a GrProgramElement or GrDrawState. It manages
20b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon * converting refs to pending IO operations. It allows a resource ownership to be in three
21b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon * states:
22b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon *          1. Owns a single ref
23b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon *          2. Owns a single ref and a pending IO operation (read, write, or read-write)
24b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon *          3. Owns a single pending IO operation.
25b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon *
26b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon * It is legal to destroy the GrGpuResourceRef in any of these states. It starts in state
27b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon * 1. Calling markPendingIO() converts it from state 1 to state 2. Calling removeRef() goes from
28b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon * state 2 to state 3. Calling pendingIOComplete() moves from state 2 to state 1. There is no
29b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon * valid way of going from state 3 back to 2 or 1.
30b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon *
31b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon * Like SkAutoTUnref, its constructor and setter adopt a ref from their caller.
32b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon *
33b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon * TODO: Once GrDODrawState no longer exists and therefore GrDrawState and GrOptDrawState no
34b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon * longer share an instance of this class, attempt to make the resource owned by GrGpuResourceRef
35b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon * only settable via the constructor.
3695740981c36266e4595ddde2264aa38e3c7e2d02bsalomon */
37f96ba02513eadd9fa24d75396ec9f2d6682e464cbsalomonclass GrGpuResourceRef : SkNoncopyable {
3895740981c36266e4595ddde2264aa38e3c7e2d02bsalomonpublic:
396f07665768dc84453316e7b2bbd6049576764cb1mtklein    SK_DECLARE_INST_COUNT(GrGpuResourceRef);
40c49233410e7278f0b95b8b0d28a80105a2930a88bsalomon
41f96ba02513eadd9fa24d75396ec9f2d6682e464cbsalomon    ~GrGpuResourceRef();
4295740981c36266e4595ddde2264aa38e3c7e2d02bsalomon
4395740981c36266e4595ddde2264aa38e3c7e2d02bsalomon    GrGpuResource* getResource() const { return fResource; }
4495740981c36266e4595ddde2264aa38e3c7e2d02bsalomon
4595740981c36266e4595ddde2264aa38e3c7e2d02bsalomon    /** Does this object own a pending read or write on the resource it is wrapping. */
4695740981c36266e4595ddde2264aa38e3c7e2d02bsalomon    bool ownsPendingIO() const { return fPendingIO; }
4795740981c36266e4595ddde2264aa38e3c7e2d02bsalomon
4895740981c36266e4595ddde2264aa38e3c7e2d02bsalomon    /** Shortcut for calling setResource() with NULL. It cannot be called after markingPendingIO
4995740981c36266e4595ddde2264aa38e3c7e2d02bsalomon        is called. */
5095740981c36266e4595ddde2264aa38e3c7e2d02bsalomon    void reset();
5195740981c36266e4595ddde2264aa38e3c7e2d02bsalomon
52c49233410e7278f0b95b8b0d28a80105a2930a88bsalomonprotected:
53f96ba02513eadd9fa24d75396ec9f2d6682e464cbsalomon    GrGpuResourceRef();
54c49233410e7278f0b95b8b0d28a80105a2930a88bsalomon
55c49233410e7278f0b95b8b0d28a80105a2930a88bsalomon    /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as
56c49233410e7278f0b95b8b0d28a80105a2930a88bsalomon        pending on the resource when markPendingIO is called. */
57bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon    GrGpuResourceRef(GrGpuResource*, GrIOType);
58c49233410e7278f0b95b8b0d28a80105a2930a88bsalomon
59c49233410e7278f0b95b8b0d28a80105a2930a88bsalomon    /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as
60c49233410e7278f0b95b8b0d28a80105a2930a88bsalomon        pending on the resource when markPendingIO is called. */
61bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon    void setResource(GrGpuResource*, GrIOType);
62c49233410e7278f0b95b8b0d28a80105a2930a88bsalomon
6395740981c36266e4595ddde2264aa38e3c7e2d02bsalomonprivate:
6495740981c36266e4595ddde2264aa38e3c7e2d02bsalomon    /** Called by owning GrProgramElement when the program element is first scheduled for
65b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon        execution. It can only be called once. */
6695740981c36266e4595ddde2264aa38e3c7e2d02bsalomon    void markPendingIO() const;
6795740981c36266e4595ddde2264aa38e3c7e2d02bsalomon
6895740981c36266e4595ddde2264aa38e3c7e2d02bsalomon    /** Called when the program element/draw state is no longer owned by GrDrawTarget-client code.
6995740981c36266e4595ddde2264aa38e3c7e2d02bsalomon        This lets the cache know that the drawing code will no longer schedule additional reads or
70b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon        writes to the resource using the program element or draw state. It can only be called once.
71b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon      */
7295740981c36266e4595ddde2264aa38e3c7e2d02bsalomon    void removeRef() const;
7395740981c36266e4595ddde2264aa38e3c7e2d02bsalomon
74ac8d6193eaa29e02d1786fe56efa98eefee74e50bsalomon    /** Called to indicate that the previous pending IO is complete. Useful when the owning object
75f96ba02513eadd9fa24d75396ec9f2d6682e464cbsalomon        still has refs, so it is not about to destroy this GrGpuResourceRef, but its previously
76b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon        pending executions have been complete. Can only be called if removeRef() was not previously
77b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon        called. */
78ac8d6193eaa29e02d1786fe56efa98eefee74e50bsalomon    void pendingIOComplete() const;
79ac8d6193eaa29e02d1786fe56efa98eefee74e50bsalomon
8095740981c36266e4595ddde2264aa38e3c7e2d02bsalomon    friend class GrProgramElement;
8195740981c36266e4595ddde2264aa38e3c7e2d02bsalomon
82bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon    GrGpuResource*  fResource;
83bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon    mutable bool    fOwnRef;
84bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon    mutable bool    fPendingIO;
85bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon    GrIOType        fIOType;
8695740981c36266e4595ddde2264aa38e3c7e2d02bsalomon
8795740981c36266e4595ddde2264aa38e3c7e2d02bsalomon    typedef SkNoncopyable INHERITED;
8895740981c36266e4595ddde2264aa38e3c7e2d02bsalomon};
8995740981c36266e4595ddde2264aa38e3c7e2d02bsalomon
906f07665768dc84453316e7b2bbd6049576764cb1mtklein/**
91b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon * Templated version of GrGpuResourceRef to enforce type safety.
92b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon */
93f96ba02513eadd9fa24d75396ec9f2d6682e464cbsalomontemplate <typename T> class GrTGpuResourceRef : public GrGpuResourceRef {
94c49233410e7278f0b95b8b0d28a80105a2930a88bsalomonpublic:
95f96ba02513eadd9fa24d75396ec9f2d6682e464cbsalomon    GrTGpuResourceRef() {}
96c49233410e7278f0b95b8b0d28a80105a2930a88bsalomon
97c49233410e7278f0b95b8b0d28a80105a2930a88bsalomon    /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as
98c49233410e7278f0b95b8b0d28a80105a2930a88bsalomon        pending on the resource when markPendingIO is called. */
9937dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon    GrTGpuResourceRef(T* resource, GrIOType ioType) : INHERITED(resource, ioType) { }
100c49233410e7278f0b95b8b0d28a80105a2930a88bsalomon
101c49233410e7278f0b95b8b0d28a80105a2930a88bsalomon    T* get() const { return static_cast<T*>(this->getResource()); }
102c49233410e7278f0b95b8b0d28a80105a2930a88bsalomon
103c49233410e7278f0b95b8b0d28a80105a2930a88bsalomon    /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as
104c49233410e7278f0b95b8b0d28a80105a2930a88bsalomon        pending on the resource when markPendingIO is called. */
105bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon    void set(T* resource, GrIOType ioType) { this->setResource(resource, ioType); }
106f96ba02513eadd9fa24d75396ec9f2d6682e464cbsalomon
107f96ba02513eadd9fa24d75396ec9f2d6682e464cbsalomonprivate:
108f96ba02513eadd9fa24d75396ec9f2d6682e464cbsalomon    typedef GrGpuResourceRef INHERITED;
109c49233410e7278f0b95b8b0d28a80105a2930a88bsalomon};
110c49233410e7278f0b95b8b0d28a80105a2930a88bsalomon
11137dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon// Specializations for GrTexture and GrRenderTarget because they use virtual inheritance.
11237dd331b20a92ce79cc26556e065dec98a66cb0bbsalomontemplate<> class GrTGpuResourceRef<GrTexture> : public GrGpuResourceRef {
11337dd331b20a92ce79cc26556e065dec98a66cb0bbsalomonpublic:
11437dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon    GrTGpuResourceRef() {}
11537dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon
11637dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon    GrTGpuResourceRef(GrTexture* texture, GrIOType ioType) : INHERITED(texture, ioType) { }
11737dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon
11837dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon    GrTexture* get() const {
11937dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon        GrSurface* surface = static_cast<GrSurface*>(this->getResource());
12037dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon        if (surface) {
12137dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon            return surface->asTexture();
12237dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon        } else {
12337dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon            return NULL;
12437dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon        }
12537dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon    }
12637dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon
12737dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon    void set(GrTexture* texture, GrIOType ioType) { this->setResource(texture, ioType); }
12837dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon
12937dd331b20a92ce79cc26556e065dec98a66cb0bbsalomonprivate:
13037dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon    typedef GrGpuResourceRef INHERITED;
13137dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon};
13237dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon
13337dd331b20a92ce79cc26556e065dec98a66cb0bbsalomontemplate<> class GrTGpuResourceRef<GrRenderTarget> : public GrGpuResourceRef {
13437dd331b20a92ce79cc26556e065dec98a66cb0bbsalomonpublic:
13537dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon    GrTGpuResourceRef() {}
13637dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon
13737dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon    GrTGpuResourceRef(GrRenderTarget* rt, GrIOType ioType) : INHERITED(rt, ioType) { }
13837dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon
13937dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon    GrRenderTarget* get() const {
14037dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon        GrSurface* surface = static_cast<GrSurface*>(this->getResource());
14137dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon        if (surface) {
14237dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon            return surface->asRenderTarget();
14337dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon        } else {
14437dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon            return NULL;
14537dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon        }
14637dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon    }
14737dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon
14837dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon    void set(GrRenderTarget* rt, GrIOType ioType) { this->setResource(rt, ioType); }
14937dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon
15037dd331b20a92ce79cc26556e065dec98a66cb0bbsalomonprivate:
15137dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon    typedef GrGpuResourceRef INHERITED;
15237dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon};
15337dd331b20a92ce79cc26556e065dec98a66cb0bbsalomon
154b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon/**
155b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon * This is similar to GrTGpuResourceRef but can only be in the pending IO state. It never owns a
156b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon * ref.
157b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon */
158bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomontemplate <typename T, GrIOType IO_TYPE> class GrPendingIOResource : SkNoncopyable {
159b3e3a955b6628acc540ef14854b57abb089e62dfbsalomonpublic:
1607eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt    GrPendingIOResource(T* resource = NULL) : fResource(NULL) {
1617eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt        this->reset(resource);
1627eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt    }
1637eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt
1647eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt    void reset(T* resource) {
1657eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt        if (resource) {
16645725db1d82615d43408ec488549aec6218f80e4bsalomon            switch (IO_TYPE) {
167bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon                case kRead_GrIOType:
1687eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt                    resource->addPendingRead();
169b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon                    break;
170bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon                case kWrite_GrIOType:
1717eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt                    resource->addPendingWrite();
172b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon                    break;
173bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon                case kRW_GrIOType:
1747eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt                    resource->addPendingRead();
1757eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt                    resource->addPendingWrite();
176b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon                    break;
177b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon            }
178b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon        }
1797eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt        this->release();
1807eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt        fResource = resource;
181b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon    }
182b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon
183b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon    ~GrPendingIOResource() {
1847eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt        this->release();
1857eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt    }
1867eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt
187b03c4a35bd319d883925a39871b4972ff1b2c0ccbsalomon    operator bool() const { return SkToBool(fResource); }
188b03c4a35bd319d883925a39871b4972ff1b2c0ccbsalomon
1897eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt    T* get() const { return fResource; }
1907eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt
1917eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualittprivate:
1927eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt    void release() {
1937eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt        if (fResource) {
19445725db1d82615d43408ec488549aec6218f80e4bsalomon            switch (IO_TYPE) {
195bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon                case kRead_GrIOType:
196b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon                    fResource->completedRead();
197b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon                    break;
198bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon                case kWrite_GrIOType:
199b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon                    fResource->completedWrite();
200b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon                    break;
201bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon                case kRW_GrIOType:
202b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon                    fResource->completedRead();
203b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon                    fResource->completedWrite();
204b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon                    break;
205b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon            }
206b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon        }
207b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon    }
208b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon
209bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon    T* fResource;
210b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon};
21195740981c36266e4595ddde2264aa38e3c7e2d02bsalomon#endif
212