GrGpuResourceRef.h revision 6f07665768dc84453316e7b2bbd6049576764cb1
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(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 GrProgramElement;
81
82    GrGpuResource*  fResource;
83    mutable bool    fOwnRef;
84    mutable bool    fPendingIO;
85    GrIOType        fIOType;
86
87    typedef SkNoncopyable INHERITED;
88};
89
90/**
91 * Templated version of GrGpuResourceRef to enforce type safety.
92 */
93template <typename T> class GrTGpuResourceRef : public GrGpuResourceRef {
94public:
95    GrTGpuResourceRef() {}
96
97    /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as
98        pending on the resource when markPendingIO is called. */
99    GrTGpuResourceRef(T* resource, GrIOType ioType) : INHERITED(resource, ioType) { }
100
101    T* get() const { return static_cast<T*>(this->getResource()); }
102
103    /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as
104        pending on the resource when markPendingIO is called. */
105    void set(T* resource, GrIOType ioType) { this->setResource(resource, ioType); }
106
107private:
108    typedef GrGpuResourceRef INHERITED;
109};
110
111// Specializations for GrTexture and GrRenderTarget because they use virtual inheritance.
112template<> class GrTGpuResourceRef<GrTexture> : public GrGpuResourceRef {
113public:
114    GrTGpuResourceRef() {}
115
116    GrTGpuResourceRef(GrTexture* texture, GrIOType ioType) : INHERITED(texture, ioType) { }
117
118    GrTexture* get() const {
119        GrSurface* surface = static_cast<GrSurface*>(this->getResource());
120        if (surface) {
121            return surface->asTexture();
122        } else {
123            return NULL;
124        }
125    }
126
127    void set(GrTexture* texture, GrIOType ioType) { this->setResource(texture, ioType); }
128
129private:
130    typedef GrGpuResourceRef INHERITED;
131};
132
133template<> class GrTGpuResourceRef<GrRenderTarget> : public GrGpuResourceRef {
134public:
135    GrTGpuResourceRef() {}
136
137    GrTGpuResourceRef(GrRenderTarget* rt, GrIOType ioType) : INHERITED(rt, ioType) { }
138
139    GrRenderTarget* get() const {
140        GrSurface* surface = static_cast<GrSurface*>(this->getResource());
141        if (surface) {
142            return surface->asRenderTarget();
143        } else {
144            return NULL;
145        }
146    }
147
148    void set(GrRenderTarget* rt, GrIOType ioType) { this->setResource(rt, ioType); }
149
150private:
151    typedef GrGpuResourceRef INHERITED;
152};
153
154/**
155 * This is similar to GrTGpuResourceRef but can only be in the pending IO state. It never owns a
156 * ref.
157 */
158template <typename T, GrIOType IO_TYPE> class GrPendingIOResource : SkNoncopyable {
159public:
160    GrPendingIOResource(T* resource = NULL) : fResource(NULL) {
161        this->reset(resource);
162    }
163
164    void reset(T* resource) {
165        if (resource) {
166            switch (IO_TYPE) {
167                case kRead_GrIOType:
168                    resource->addPendingRead();
169                    break;
170                case kWrite_GrIOType:
171                    resource->addPendingWrite();
172                    break;
173                case kRW_GrIOType:
174                    resource->addPendingRead();
175                    resource->addPendingWrite();
176                    break;
177            }
178        }
179        this->release();
180        fResource = resource;
181    }
182
183    ~GrPendingIOResource() {
184        this->release();
185    }
186
187    operator bool() const { return SkToBool(fResource); }
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