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"
1295740981c36266e4595ddde2264aa38e3c7e2d02bsalomon#include "SkRefCnt.h"
1395740981c36266e4595ddde2264aa38e3c7e2d02bsalomon
1495740981c36266e4595ddde2264aa38e3c7e2d02bsalomon/**
15b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon * This class is intended only for internal use in core Gr code.
16b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon *
1795740981c36266e4595ddde2264aa38e3c7e2d02bsalomon * Class that wraps a resource referenced by a GrProgramElement or GrDrawState. It manages
18b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon * converting refs to pending IO operations. It allows a resource ownership to be in three
19b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon * states:
20b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon *          1. Owns a single ref
21b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon *          2. Owns a single ref and a pending IO operation (read, write, or read-write)
22b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon *          3. Owns a single pending IO operation.
23b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon *
24b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon * It is legal to destroy the GrGpuResourceRef in any of these states. It starts in state
25b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon * 1. Calling markPendingIO() converts it from state 1 to state 2. Calling removeRef() goes from
26b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon * state 2 to state 3. Calling pendingIOComplete() moves from state 2 to state 1. There is no
27b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon * valid way of going from state 3 back to 2 or 1.
28b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon *
296bd5284415bd983b0628c4941dff5def40018f5abungeman * Like sk_sp, its constructor and setter adopt a ref from their caller.
30b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon *
31b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon * TODO: Once GrDODrawState no longer exists and therefore GrDrawState and GrOptDrawState no
32b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon * longer share an instance of this class, attempt to make the resource owned by GrGpuResourceRef
33b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon * only settable via the constructor.
3495740981c36266e4595ddde2264aa38e3c7e2d02bsalomon */
35f96ba02513eadd9fa24d75396ec9f2d6682e464cbsalomonclass GrGpuResourceRef : SkNoncopyable {
3695740981c36266e4595ddde2264aa38e3c7e2d02bsalomonpublic:
37f96ba02513eadd9fa24d75396ec9f2d6682e464cbsalomon    ~GrGpuResourceRef();
3895740981c36266e4595ddde2264aa38e3c7e2d02bsalomon
3995740981c36266e4595ddde2264aa38e3c7e2d02bsalomon    GrGpuResource* getResource() const { return fResource; }
4095740981c36266e4595ddde2264aa38e3c7e2d02bsalomon
4195740981c36266e4595ddde2264aa38e3c7e2d02bsalomon    /** Does this object own a pending read or write on the resource it is wrapping. */
4295740981c36266e4595ddde2264aa38e3c7e2d02bsalomon    bool ownsPendingIO() const { return fPendingIO; }
4395740981c36266e4595ddde2264aa38e3c7e2d02bsalomon
44f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    /** What type of IO does this represent? This is independent of whether a normal ref or a
45f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        pending IO is currently held. */
46f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    GrIOType ioType() const { return fIOType; }
47f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon
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
68f2361d2d93c200cd4555b5e8ecea4531801abaaaRobert Phillips    /** Called when the program element/draw state is no longer owned by GrOpList-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
80ab015efc48c462ffdffebb45c02cd19efb254983Brian Salomon    friend class GrResourceIOProcessor;
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. */
993416969605137214a9e1b1fb85182e5640a655abBrian Salomon    GrTGpuResourceRef(T* resource, GrIOType ioType) : INHERITED(resource, ioType) {}
1003416969605137214a9e1b1fb85182e5640a655abBrian Salomon    GrTGpuResourceRef(sk_sp<T> resource, GrIOType ioType) : INHERITED(resource, ioType) {}
101c49233410e7278f0b95b8b0d28a80105a2930a88bsalomon
102c49233410e7278f0b95b8b0d28a80105a2930a88bsalomon    T* get() const { return static_cast<T*>(this->getResource()); }
103c49233410e7278f0b95b8b0d28a80105a2930a88bsalomon
104c49233410e7278f0b95b8b0d28a80105a2930a88bsalomon    /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as
105c49233410e7278f0b95b8b0d28a80105a2930a88bsalomon        pending on the resource when markPendingIO is called. */
106bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon    void set(T* resource, GrIOType ioType) { this->setResource(resource, ioType); }
107f96ba02513eadd9fa24d75396ec9f2d6682e464cbsalomon
108f96ba02513eadd9fa24d75396ec9f2d6682e464cbsalomonprivate:
109f96ba02513eadd9fa24d75396ec9f2d6682e464cbsalomon    typedef GrGpuResourceRef INHERITED;
110c49233410e7278f0b95b8b0d28a80105a2930a88bsalomon};
111c49233410e7278f0b95b8b0d28a80105a2930a88bsalomon
112b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon/**
113b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon * This is similar to GrTGpuResourceRef but can only be in the pending IO state. It never owns a
114b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon * ref.
115b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon */
116bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomontemplate <typename T, GrIOType IO_TYPE> class GrPendingIOResource : SkNoncopyable {
117b3e3a955b6628acc540ef14854b57abb089e62dfbsalomonpublic:
118a93a14a99816d25b773f0b12868143702baf44bfBen Wagner    GrPendingIOResource(T* resource = nullptr) : fResource(nullptr) {
1197eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt        this->reset(resource);
1207eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt    }
1217eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt
122ff926502069d0ddafaecc18dc08973762e4befd2Chris Dalton    GrPendingIOResource(const GrPendingIOResource& that)
123ff926502069d0ddafaecc18dc08973762e4befd2Chris Dalton        : GrPendingIOResource(that.get()) {
124ff926502069d0ddafaecc18dc08973762e4befd2Chris Dalton    }
125ff926502069d0ddafaecc18dc08973762e4befd2Chris Dalton
1265efd5ea4e146c47394d16c8b6f876264822a0beeRobert Phillips    void reset(T* resource = nullptr) {
1277eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt        if (resource) {
12845725db1d82615d43408ec488549aec6218f80e4bsalomon            switch (IO_TYPE) {
129bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon                case kRead_GrIOType:
1307eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt                    resource->addPendingRead();
131b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon                    break;
132bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon                case kWrite_GrIOType:
1337eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt                    resource->addPendingWrite();
134b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon                    break;
135bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon                case kRW_GrIOType:
1367eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt                    resource->addPendingRead();
1377eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt                    resource->addPendingWrite();
138b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon                    break;
139b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon            }
140b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon        }
1417eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt        this->release();
1427eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt        fResource = resource;
143b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon    }
144b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon
145b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon    ~GrPendingIOResource() {
1467eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt        this->release();
1477eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt    }
1487eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt
149d9ffaed6d21f85c717117904da26a2bac2295607reed    explicit operator bool() const { return SkToBool(fResource); }
150d9ffaed6d21f85c717117904da26a2bac2295607reed
151d9ffaed6d21f85c717117904da26a2bac2295607reed    bool operator==(const GrPendingIOResource& other) const {
152d9ffaed6d21f85c717117904da26a2bac2295607reed        return fResource == other.fResource;
153d9ffaed6d21f85c717117904da26a2bac2295607reed    }
154b03c4a35bd319d883925a39871b4972ff1b2c0ccbsalomon
1557eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt    T* get() const { return fResource; }
1567eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt
1577eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualittprivate:
1587eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt    void release() {
1597eb8c7b00a5d776bebaf33a8687357df95c1aa43joshualitt        if (fResource) {
16045725db1d82615d43408ec488549aec6218f80e4bsalomon            switch (IO_TYPE) {
161bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon                case kRead_GrIOType:
162b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon                    fResource->completedRead();
163b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon                    break;
164bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon                case kWrite_GrIOType:
165b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon                    fResource->completedWrite();
166b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon                    break;
167bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon                case kRW_GrIOType:
168b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon                    fResource->completedRead();
169b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon                    fResource->completedWrite();
170b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon                    break;
171b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon            }
172b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon        }
173b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon    }
174b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon
175bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon    T* fResource;
176b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon};
177620003692923dc6c6df5a1b66288988b6783a69fRobert Phillips
17895740981c36266e4595ddde2264aa38e3c7e2d02bsalomon#endif
179