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