Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / angle / src / libGLESv2 / renderer / d3d / d3d11 / Fence11.cpp
1 //
2 // Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 // Fence11.cpp: Defines the rx::FenceNV11 and rx::FenceSync11 classes which implement rx::FenceNVImpl and rx::FenceSyncImpl.
8
9 #include "libGLESv2/renderer/d3d/d3d11/Fence11.h"
10 #include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
11 #include "libGLESv2/main.h"
12
13 #include "common/utilities.h"
14
15 namespace rx
16 {
17
18 //
19 // Template helpers for set and test operations.
20 //
21
22 template<class FenceClass>
23 gl::Error FenceSetHelper(FenceClass *fence)
24 {
25     if (!fence->mQuery)
26     {
27         D3D11_QUERY_DESC queryDesc;
28         queryDesc.Query = D3D11_QUERY_EVENT;
29         queryDesc.MiscFlags = 0;
30
31         HRESULT result = fence->mRenderer->getDevice()->CreateQuery(&queryDesc, &fence->mQuery);
32         if (FAILED(result))
33         {
34             return gl::Error(GL_OUT_OF_MEMORY, "Failed to create event query, result: 0x%X.", result);
35         }
36     }
37
38     fence->mRenderer->getDeviceContext()->End(fence->mQuery);
39     return gl::Error(GL_NO_ERROR);
40 }
41
42 template <class FenceClass>
43 gl::Error FenceTestHelper(FenceClass *fence, bool flushCommandBuffer, GLboolean *outFinished)
44 {
45     ASSERT(fence->mQuery);
46
47     UINT getDataFlags = (flushCommandBuffer ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH);
48     HRESULT result = fence->mRenderer->getDeviceContext()->GetData(fence->mQuery, NULL, 0, getDataFlags);
49
50     if (FAILED(result))
51     {
52         return gl::Error(GL_OUT_OF_MEMORY, "Failed to get query data, result: 0x%X.", result);
53     }
54     else if (fence->mRenderer->isDeviceLost())
55     {
56         return gl::Error(GL_OUT_OF_MEMORY, "Device was lost while querying result of an event query.");
57     }
58
59     ASSERT(result == S_OK || result == S_FALSE);
60     *outFinished = ((result == S_OK) ? GL_TRUE : GL_FALSE);
61     return gl::Error(GL_NO_ERROR);
62 }
63
64 //
65 // FenceNV11
66 //
67
68 FenceNV11::FenceNV11(Renderer11 *renderer)
69     : FenceNVImpl(),
70       mRenderer(renderer),
71       mQuery(NULL)
72 {
73 }
74
75 FenceNV11::~FenceNV11()
76 {
77     SafeRelease(mQuery);
78 }
79
80 gl::Error FenceNV11::set()
81 {
82     return FenceSetHelper(this);
83 }
84
85 gl::Error FenceNV11::test(bool flushCommandBuffer, GLboolean *outFinished)
86 {
87     return FenceTestHelper(this, flushCommandBuffer, outFinished);
88 }
89
90 gl::Error FenceNV11::finishFence(GLboolean *outFinished)
91 {
92     ASSERT(outFinished);
93
94     while (*outFinished != GL_TRUE)
95     {
96         gl::Error error = test(true, outFinished);
97         if (error.isError())
98         {
99             return error;
100         }
101
102         Sleep(0);
103     }
104
105     return gl::Error(GL_NO_ERROR);
106 }
107
108 //
109 // FenceSync11
110 //
111
112 // Important note on accurate timers in Windows:
113 //
114 // QueryPerformanceCounter has a few major issues, including being 10x as expensive to call
115 // as timeGetTime on laptops and "jumping" during certain hardware events.
116 //
117 // See the comments at the top of the Chromium source file "chromium/src/base/time/time_win.cc"
118 //   https://code.google.com/p/chromium/codesearch#chromium/src/base/time/time_win.cc
119 //
120 // We still opt to use QPC. In the present and moving forward, most newer systems will not suffer
121 // from buggy implementations.
122
123 FenceSync11::FenceSync11(Renderer11 *renderer)
124     : FenceSyncImpl(),
125       mRenderer(renderer),
126       mQuery(NULL)
127 {
128     LARGE_INTEGER counterFreqency = { 0 };
129     BOOL success = QueryPerformanceFrequency(&counterFreqency);
130     UNUSED_ASSERTION_VARIABLE(success);
131     ASSERT(success);
132
133     mCounterFrequency = counterFreqency.QuadPart;
134 }
135
136 FenceSync11::~FenceSync11()
137 {
138     SafeRelease(mQuery);
139 }
140
141 gl::Error FenceSync11::set()
142 {
143     return FenceSetHelper(this);
144 }
145
146 gl::Error FenceSync11::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult)
147 {
148     ASSERT(outResult);
149
150     bool flushCommandBuffer = ((flags & GL_SYNC_FLUSH_COMMANDS_BIT) != 0);
151
152     GLboolean result = GL_FALSE;
153     gl::Error error = FenceTestHelper(this, flushCommandBuffer, &result);
154     if (error.isError())
155     {
156         *outResult = GL_WAIT_FAILED;
157         return error;
158     }
159
160     if (result == GL_TRUE)
161     {
162         *outResult = GL_ALREADY_SIGNALED;
163         return gl::Error(GL_NO_ERROR);
164     }
165
166     if (timeout == 0)
167     {
168         *outResult = GL_TIMEOUT_EXPIRED;
169         return gl::Error(GL_NO_ERROR);
170     }
171
172     LARGE_INTEGER currentCounter = { 0 };
173     BOOL success = QueryPerformanceCounter(&currentCounter);
174     UNUSED_ASSERTION_VARIABLE(success);
175     ASSERT(success);
176
177     LONGLONG timeoutInSeconds = static_cast<LONGLONG>(timeout) * static_cast<LONGLONG>(1000000ll);
178     LONGLONG endCounter = currentCounter.QuadPart + mCounterFrequency * timeoutInSeconds;
179
180     while (currentCounter.QuadPart < endCounter && !result)
181     {
182         Sleep(0);
183         BOOL success = QueryPerformanceCounter(&currentCounter);
184         UNUSED_ASSERTION_VARIABLE(success);
185         ASSERT(success);
186
187         error = FenceTestHelper(this, flushCommandBuffer, &result);
188         if (error.isError())
189         {
190             *outResult = GL_WAIT_FAILED;
191             return error;
192         }
193     }
194
195     if (currentCounter.QuadPart >= endCounter)
196     {
197         *outResult = GL_TIMEOUT_EXPIRED;
198     }
199     else
200     {
201         *outResult = GL_CONDITION_SATISFIED;
202     }
203
204     return gl::Error(GL_NO_ERROR);
205 }
206
207 gl::Error FenceSync11::serverWait(GLbitfield flags, GLuint64 timeout)
208 {
209     // Because our API is currently designed to be called from a single thread, we don't need to do
210     // extra work for a server-side fence. GPU commands issued after the fence is created will always
211     // be processed after the fence is signaled.
212     return gl::Error(GL_NO_ERROR);
213 }
214
215 gl::Error FenceSync11::getStatus(GLint *outResult)
216 {
217     GLboolean result = GL_FALSE;
218     gl::Error error = FenceTestHelper(this, false, &result);
219     if (error.isError())
220     {
221         // The spec does not specify any way to report errors during the status test (e.g. device lost)
222         // so we report the fence is unblocked in case of error or signaled.
223         *outResult = GL_SIGNALED;
224
225         return error;
226     }
227
228     *outResult = (result ? GL_SIGNALED : GL_UNSIGNALED);
229     return gl::Error(GL_NO_ERROR);
230 }
231
232 } // namespace rx