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#include "GrGpuResourceRef.h"
9
10GrGpuResourceRef::GrGpuResourceRef() {
11    fResource = NULL;
12    fOwnRef = false;
13    fPendingIO = false;
14}
15
16GrGpuResourceRef::GrGpuResourceRef(GrGpuResource* resource, GrIORef::IOType ioType) {
17    fResource = NULL;
18    fOwnRef = false;
19    fPendingIO = false;
20    this->setResource(resource, ioType);
21}
22
23GrGpuResourceRef::~GrGpuResourceRef() {
24    if (fOwnRef) {
25        SkASSERT(fResource);
26        fResource->unref();
27    }
28    if (fPendingIO) {
29        switch (fIOType) {
30            case GrIORef::kRead_IOType:
31                fResource->completedRead();
32                break;
33            case GrIORef::kWrite_IOType:
34                fResource->completedWrite();
35                break;
36            case GrIORef::kRW_IOType:
37                fResource->completedRead();
38                fResource->completedWrite();
39                break;
40        }
41    }
42}
43
44void GrGpuResourceRef::reset() {
45    SkASSERT(!fPendingIO);
46    SkASSERT(SkToBool(fResource) == fOwnRef);
47    if (fOwnRef) {
48        fResource->unref();
49        fOwnRef = false;
50        fResource = NULL;
51    }
52}
53
54void GrGpuResourceRef::setResource(GrGpuResource* resource, GrIORef::IOType ioType) {
55    SkASSERT(!fPendingIO);
56    SkASSERT(SkToBool(fResource) == fOwnRef);
57    SkSafeUnref(fResource);
58    if (NULL == resource) {
59        fResource = NULL;
60        fOwnRef = false;
61    } else {
62        fResource = resource;
63        fOwnRef = true;
64        fIOType = ioType;
65    }
66}
67
68void GrGpuResourceRef::markPendingIO() const {
69    // This should only be called when the owning GrProgramElement gets its first
70    // pendingExecution ref.
71    SkASSERT(!fPendingIO);
72    SkASSERT(fResource);
73    fPendingIO = true;
74    switch (fIOType) {
75        case GrIORef::kRead_IOType:
76            fResource->addPendingRead();
77            break;
78        case GrIORef::kWrite_IOType:
79            fResource->addPendingWrite();
80            break;
81        case GrIORef::kRW_IOType:
82            fResource->addPendingRead();
83            fResource->addPendingWrite();
84            break;
85    }
86}
87
88void GrGpuResourceRef::pendingIOComplete() const {
89    // This should only be called when the owner's pending executions have ocurred but it is still
90    // reffed.
91    SkASSERT(fOwnRef);
92    SkASSERT(fPendingIO);
93    switch (fIOType) {
94        case GrIORef::kRead_IOType:
95            fResource->completedRead();
96            break;
97        case GrIORef::kWrite_IOType:
98            fResource->completedWrite();
99            break;
100        case GrIORef::kRW_IOType:
101            fResource->completedRead();
102            fResource->completedWrite();
103            break;
104
105    }
106    fPendingIO = false;
107}
108
109void GrGpuResourceRef::removeRef() const {
110    // This should only be called once, when the owners last ref goes away and
111    // there is a pending execution.
112    SkASSERT(fOwnRef);
113    SkASSERT(fPendingIO);
114    SkASSERT(fResource);
115    fResource->unref();
116    fOwnRef = false;
117}
118