GrGpuResourceRef.h revision b3e3a955b6628acc540ef14854b57abb089e62df
1/*
2 * Copyright 2014 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#ifndef GrGpuResourceRef_DEFINED
9#define GrGpuResourceRef_DEFINED
10
11#include "SkRefCnt.h"
12
13class GrGpuResource;
14
15/**
16 * This class is intended only for internal use in core Gr code.
17 *
18 * Class that wraps a resource referenced by a GrProgramElement or GrDrawState. It manages
19 * converting refs to pending IO operations. It allows a resource ownership to be in three
20 * states:
21 *          1. Owns a single ref
22 *          2. Owns a single ref and a pending IO operation (read, write, or read-write)
23 *          3. Owns a single pending IO operation.
24 *
25 * It is legal to destroy the GrGpuResourceRef in any of these states. It starts in state
26 * 1. Calling markPendingIO() converts it from state 1 to state 2. Calling removeRef() goes from
27 * state 2 to state 3. Calling pendingIOComplete() moves from state 2 to state 1. There is no
28 * valid way of going from state 3 back to 2 or 1.
29 *
30 * Like SkAutoTUnref, its constructor and setter adopt a ref from their caller.
31 *
32 * TODO: Once GrDODrawState no longer exists and therefore GrDrawState and GrOptDrawState no
33 * longer share an instance of this class, attempt to make the resource owned by GrGpuResourceRef
34 * only settable via the constructor.
35 */
36class GrGpuResourceRef : SkNoncopyable {
37public:
38    SK_DECLARE_INST_COUNT_ROOT(GrGpuResourceRef);
39
40    enum IOType {
41        kRead_IOType,
42        kWrite_IOType,
43        kRW_IOType,
44
45        kNone_IOType, // For internal use only, don't specify to constructor or setResource().
46    };
47
48    ~GrGpuResourceRef();
49
50    GrGpuResource* getResource() const { return fResource; }
51
52    /** Does this object own a pending read or write on the resource it is wrapping. */
53    bool ownsPendingIO() const { return fPendingIO; }
54
55    /** Shortcut for calling setResource() with NULL. It cannot be called after markingPendingIO
56        is called. */
57    void reset();
58
59protected:
60    GrGpuResourceRef();
61
62    /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as
63        pending on the resource when markPendingIO is called. */
64    GrGpuResourceRef(GrGpuResource*, IOType);
65
66    /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as
67        pending on the resource when markPendingIO is called. */
68    void setResource(GrGpuResource*, IOType);
69
70private:
71    /** Called by owning GrProgramElement when the program element is first scheduled for
72        execution. It can only be called once. */
73    void markPendingIO() const;
74
75    /** Called when the program element/draw state is no longer owned by GrDrawTarget-client code.
76        This lets the cache know that the drawing code will no longer schedule additional reads or
77        writes to the resource using the program element or draw state. It can only be called once.
78      */
79    void removeRef() const;
80
81    /** Called to indicate that the previous pending IO is complete. Useful when the owning object
82        still has refs, so it is not about to destroy this GrGpuResourceRef, but its previously
83        pending executions have been complete. Can only be called if removeRef() was not previously
84        called. */
85    void pendingIOComplete() const;
86
87    friend class GrRODrawState;
88    friend class GrProgramElement;
89
90    GrGpuResource*      fResource;
91    mutable bool        fOwnRef;
92    mutable bool        fPendingIO;
93    IOType              fIOType;
94
95    typedef SkNoncopyable INHERITED;
96};
97
98/**
99 * Templated version of GrGpuResourceRef to enforce type safety.
100 */
101template <typename T> class GrTGpuResourceRef : public GrGpuResourceRef {
102public:
103    GrTGpuResourceRef() {}
104
105    /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as
106        pending on the resource when markPendingIO is called. */
107    GrTGpuResourceRef(T* resource, IOType ioType) : INHERITED(resource, ioType) {}
108
109    T* get() const { return static_cast<T*>(this->getResource()); }
110
111    /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as
112        pending on the resource when markPendingIO is called. */
113    void set(T* resource, IOType ioType) { this->setResource(resource, ioType); }
114
115private:
116    typedef GrGpuResourceRef INHERITED;
117};
118
119/**
120 * This is similar to GrTGpuResourceRef but can only be in the pending IO state. It never owns a
121 * ref.
122 */
123template <typename T> class GrPendingIOResource : SkNoncopyable {
124public:
125    typedef GrGpuResourceRef::IOType IOType;
126    GrPendingIOResource(T* resource, IOType ioType) : fResource(resource), fIOType(ioType) {
127        if (NULL != fResource) {
128            switch (fIOType) {
129                case GrGpuResourceRef::kNone_IOType:
130                    SkFAIL("GrPendingIOResource with neither reads nor writes?");
131                    break;
132                case GrGpuResourceRef::kRead_IOType:
133                    fResource->addPendingRead();
134                    break;
135                case GrGpuResourceRef::kWrite_IOType:
136                    fResource->addPendingWrite();
137                    break;
138                case GrGpuResourceRef::kRW_IOType:
139                    fResource->addPendingRead();
140                    fResource->addPendingWrite();
141                    break;
142            }
143        }
144    }
145
146    ~GrPendingIOResource() {
147        if (NULL != fResource) {
148            switch (fIOType) {
149                case GrGpuResourceRef::kNone_IOType:
150                    SkFAIL("GrPendingIOResource with neither reads nor writes?");
151                    break;
152                case GrGpuResourceRef::kRead_IOType:
153                    fResource->completedRead();
154                    break;
155                case GrGpuResourceRef::kWrite_IOType:
156                    fResource->completedWrite();
157                    break;
158                case GrGpuResourceRef::kRW_IOType:
159                    fResource->completedRead();
160                    fResource->completedWrite();
161                    break;
162            }
163        }
164    }
165
166    T* get() const { return fResource; }
167
168private:
169    T*      fResource;
170    IOType  fIOType;
171};
172#endif
173