1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 // Fence.cpp: Implements the Fence class, which supports the GL_NV_fence extension.
16
17 #include "Fence.h"
18
19 #include "main.h"
20 #include "Common/Thread.hpp"
21
22 namespace es2
23 {
24
Fence()25 Fence::Fence()
26 {
27 mQuery = false;
28 mCondition = GL_NONE;
29 mStatus = GL_FALSE;
30 }
31
~Fence()32 Fence::~Fence()
33 {
34 mQuery = false;
35 }
36
isFence()37 GLboolean Fence::isFence()
38 {
39 // GL_NV_fence spec:
40 // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence.
41 return mQuery;
42 }
43
setFence(GLenum condition)44 void Fence::setFence(GLenum condition)
45 {
46 if(condition != GL_ALL_COMPLETED_NV)
47 {
48 return error(GL_INVALID_VALUE);
49 }
50
51 mQuery = true;
52 mCondition = condition;
53 mStatus = GL_FALSE;
54 }
55
testFence()56 GLboolean Fence::testFence()
57 {
58 if(!mQuery)
59 {
60 return error(GL_INVALID_OPERATION, GL_TRUE);
61 }
62
63 // The current assumtion is that no matter where the fence is placed, it is
64 // done by the time it is tested, which is similar to Context::flush(), since
65 // we don't queue anything without processing it as fast as possible.
66 mStatus = GL_TRUE;
67
68 return mStatus;
69 }
70
finishFence()71 void Fence::finishFence()
72 {
73 if(!mQuery)
74 {
75 return error(GL_INVALID_OPERATION);
76 }
77
78 while(!testFence())
79 {
80 sw::Thread::yield();
81 }
82 }
83
getFenceiv(GLenum pname,GLint * params)84 void Fence::getFenceiv(GLenum pname, GLint *params)
85 {
86 if(!mQuery)
87 {
88 return error(GL_INVALID_OPERATION);
89 }
90
91 switch(pname)
92 {
93 case GL_FENCE_STATUS_NV:
94 {
95 // GL_NV_fence spec:
96 // Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV
97 // or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence.
98 if(mStatus)
99 {
100 params[0] = GL_TRUE;
101 return;
102 }
103
104 mStatus = testFence();
105
106 params[0] = mStatus;
107 break;
108 }
109 case GL_FENCE_CONDITION_NV:
110 params[0] = mCondition;
111 break;
112 default:
113 return error(GL_INVALID_ENUM);
114 break;
115 }
116 }
117
FenceSync(GLuint name,GLenum condition,GLbitfield flags)118 FenceSync::FenceSync(GLuint name, GLenum condition, GLbitfield flags) : NamedObject(name), mCondition(condition), mFlags(flags)
119 {
120 }
121
~FenceSync()122 FenceSync::~FenceSync()
123 {
124 }
125
clientWait(GLbitfield flags,GLuint64 timeout)126 GLenum FenceSync::clientWait(GLbitfield flags, GLuint64 timeout)
127 {
128 // The current assumtion is that no matter where the fence is placed, it is
129 // done by the time it is tested, which is similar to Context::flush(), since
130 // we don't queue anything without processing it as fast as possible.
131 return GL_ALREADY_SIGNALED;
132 }
133
serverWait(GLbitfield flags,GLuint64 timeout)134 void FenceSync::serverWait(GLbitfield flags, GLuint64 timeout)
135 {
136 }
137
getSynciv(GLenum pname,GLsizei * length,GLint * values)138 void FenceSync::getSynciv(GLenum pname, GLsizei *length, GLint *values)
139 {
140 switch(pname)
141 {
142 case GL_OBJECT_TYPE:
143 values[0] = GL_SYNC_FENCE;
144 if(length) {
145 *length = 1;
146 }
147 break;
148 case GL_SYNC_STATUS:
149 // The current assumtion is that no matter where the fence is placed, it is
150 // done by the time it is tested, which is similar to Context::flush(), since
151 // we don't queue anything without processing it as fast as possible.
152 values[0] = GL_SIGNALED;
153 if(length) {
154 *length = 1;
155 }
156 break;
157 case GL_SYNC_CONDITION:
158 values[0] = GL_SYNC_GPU_COMMANDS_COMPLETE;
159 if(length) {
160 *length = 1;
161 }
162 break;
163 case GL_SYNC_FLAGS:
164 if(length) {
165 *length = 0;
166 }
167 break;
168 default:
169 return error(GL_INVALID_ENUM);
170 }
171 }
172
173 }
174