GrGpuResourceRef.h revision 2766c00fc0b6a07d46e5f74cdad45da2ef625237
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    ~GrGpuResourceRef();
40
41    GrGpuResource* getResource() const { return fResource; }
42
43    /** Does this object own a pending read or write on the resource it is wrapping. */
44    bool ownsPendingIO() const { return fPendingIO; }
45
46    /** Shortcut for calling setResource() with NULL. It cannot be called after markingPendingIO
47        is called. */
48    void reset();
49
50protected:
51    GrGpuResourceRef();
52
53    /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as
54        pending on the resource when markPendingIO is called. */
55    GrGpuResourceRef(GrGpuResource*, GrIOType);
56
57    /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as
58        pending on the resource when markPendingIO is called. */
59    void setResource(GrGpuResource*, GrIOType);
60
61private:
62    /** Called by owning GrProgramElement when the program element is first scheduled for
63        execution. It can only be called once. */
64    void markPendingIO() const;
65
66    /** Called when the program element/draw state is no longer owned by GrDrawTarget-client code.
67        This lets the cache know that the drawing code will no longer schedule additional reads or
68        writes to the resource using the program element or draw state. It can only be called once.
69      */
70    void removeRef() const;
71
72    /** Called to indicate that the previous pending IO is complete. Useful when the owning object
73        still has refs, so it is not about to destroy this GrGpuResourceRef, but its previously
74        pending executions have been complete. Can only be called if removeRef() was not previously
75        called. */
76    void pendingIOComplete() const;
77
78    friend class GrProgramElement;
79
80    GrGpuResource*  fResource;
81    mutable bool    fOwnRef;
82    mutable bool    fPendingIO;
83    GrIOType        fIOType;
84
85    typedef SkNoncopyable INHERITED;
86};
87
88/**
89 * Templated version of GrGpuResourceRef to enforce type safety.
90 */
91template <typename T> class GrTGpuResourceRef : public GrGpuResourceRef {
92public:
93    GrTGpuResourceRef() {}
94
95    /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as
96        pending on the resource when markPendingIO is called. */
97    GrTGpuResourceRef(T* resource, GrIOType ioType) : INHERITED(resource, ioType) { }
98
99    T* get() const { return static_cast<T*>(this->getResource()); }
100
101    /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as
102        pending on the resource when markPendingIO is called. */
103    void set(T* resource, GrIOType ioType) { this->setResource(resource, ioType); }
104
105private:
106    typedef GrGpuResourceRef INHERITED;
107};
108
109// Specializations for GrTexture and GrRenderTarget because they use virtual inheritance.
110template<> class GrTGpuResourceRef<GrTexture> : public GrGpuResourceRef {
111public:
112    GrTGpuResourceRef() {}
113
114    GrTGpuResourceRef(GrTexture* texture, GrIOType ioType) : INHERITED(texture, ioType) { }
115
116    GrTexture* get() const {
117        GrSurface* surface = static_cast<GrSurface*>(this->getResource());
118        if (surface) {
119            return surface->asTexture();
120        } else {
121            return NULL;
122        }
123    }
124
125    void set(GrTexture* texture, GrIOType ioType) { this->setResource(texture, ioType); }
126
127private:
128    typedef GrGpuResourceRef INHERITED;
129};
130
131template<> class GrTGpuResourceRef<GrRenderTarget> : public GrGpuResourceRef {
132public:
133    GrTGpuResourceRef() {}
134
135    GrTGpuResourceRef(GrRenderTarget* rt, GrIOType ioType) : INHERITED(rt, ioType) { }
136
137    GrRenderTarget* get() const {
138        GrSurface* surface = static_cast<GrSurface*>(this->getResource());
139        if (surface) {
140            return surface->asRenderTarget();
141        } else {
142            return NULL;
143        }
144    }
145
146    void set(GrRenderTarget* rt, GrIOType ioType) { this->setResource(rt, ioType); }
147
148private:
149    typedef GrGpuResourceRef INHERITED;
150};
151
152/**
153 * This is similar to GrTGpuResourceRef but can only be in the pending IO state. It never owns a
154 * ref.
155 */
156template <typename T, GrIOType IO_TYPE> class GrPendingIOResource : SkNoncopyable {
157public:
158    GrPendingIOResource(T* resource = NULL) : fResource(NULL) {
159        this->reset(resource);
160    }
161
162    void reset(T* resource) {
163        if (resource) {
164            switch (IO_TYPE) {
165                case kRead_GrIOType:
166                    resource->addPendingRead();
167                    break;
168                case kWrite_GrIOType:
169                    resource->addPendingWrite();
170                    break;
171                case kRW_GrIOType:
172                    resource->addPendingRead();
173                    resource->addPendingWrite();
174                    break;
175            }
176        }
177        this->release();
178        fResource = resource;
179    }
180
181    ~GrPendingIOResource() {
182        this->release();
183    }
184
185    operator bool() const { return SkToBool(fResource); }
186
187    T* get() const { return fResource; }
188
189private:
190    void release() {
191        if (fResource) {
192            switch (IO_TYPE) {
193                case kRead_GrIOType:
194                    fResource->completedRead();
195                    break;
196                case kWrite_GrIOType:
197                    fResource->completedWrite();
198                    break;
199                case kRW_GrIOType:
200                    fResource->completedRead();
201                    fResource->completedWrite();
202                    break;
203            }
204        }
205    }
206
207    T* fResource;
208};
209#endif
210