blob: 2ed7975acace06e172d1af5bf6cadfc4575ef5f5 [file] [log] [blame]
shannon.woods@transgaming.combe58aa02013-02-28 23:03:55 +00001//
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::Fence11 class which implements rx::FenceImpl.
8
9#include "libGLESv2/renderer/Fence11.h"
10#include "libGLESv2/main.h"
11
12namespace rx
13{
14
15Fence11::Fence11(rx::Renderer11 *renderer)
16{
17 mRenderer = renderer;
18 mQuery = NULL;
19}
20
21Fence11::~Fence11()
22{
23 if (mQuery)
24 {
25 mQuery->Release();
26 mQuery = NULL;
27 }
28}
29
30GLboolean Fence11::isFence()
31{
32 // GL_NV_fence spec:
33 // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence.
34 return mQuery != NULL;
35}
36
37void Fence11::setFence(GLenum condition)
38{
39 if (!mQuery)
40 {
41 D3D11_QUERY_DESC queryDesc;
42 queryDesc.Query = D3D11_QUERY_EVENT;
43 queryDesc.MiscFlags = 0;
44
45 if (FAILED(mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery)))
46 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +000047 return gl::error(GL_OUT_OF_MEMORY);
shannon.woods@transgaming.combe58aa02013-02-28 23:03:55 +000048 }
49 }
50
51 mRenderer->getDeviceContext()->End(mQuery);
52
53 setCondition(condition);
54 setStatus(GL_FALSE);
55}
56
57GLboolean Fence11::testFence()
58{
59 if (mQuery == NULL)
60 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +000061 return gl::error(GL_INVALID_OPERATION, GL_TRUE);
shannon.woods@transgaming.combe58aa02013-02-28 23:03:55 +000062 }
63
64 HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, NULL, 0, 0);
65
66 if (mRenderer->isDeviceLost())
67 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +000068 return gl::error(GL_OUT_OF_MEMORY, GL_TRUE);
shannon.woods@transgaming.combe58aa02013-02-28 23:03:55 +000069 }
70
71 ASSERT(result == S_OK || result == S_FALSE);
72 setStatus(result == S_OK);
73 return getStatus();
74}
75
76void Fence11::finishFence()
77{
78 if (mQuery == NULL)
79 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +000080 return gl::error(GL_INVALID_OPERATION);
shannon.woods@transgaming.combe58aa02013-02-28 23:03:55 +000081 }
82
83 while (!testFence())
84 {
85 Sleep(0);
86 }
87}
88
89void Fence11::getFenceiv(GLenum pname, GLint *params)
90{
91 if (mQuery == NULL)
92 {
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +000093 return gl::error(GL_INVALID_OPERATION);
shannon.woods@transgaming.combe58aa02013-02-28 23:03:55 +000094 }
95
96 switch (pname)
97 {
98 case GL_FENCE_STATUS_NV:
99 {
100 // GL_NV_fence spec:
101 // Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV
102 // or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence.
103 if (getStatus())
104 {
105 params[0] = GL_TRUE;
106 return;
107 }
108
109 HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH);
110
111 if (mRenderer->isDeviceLost())
112 {
113 params[0] = GL_TRUE;
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000114 return gl::error(GL_OUT_OF_MEMORY);
shannon.woods@transgaming.combe58aa02013-02-28 23:03:55 +0000115 }
116
117 ASSERT(result == S_OK || result == S_FALSE);
118 setStatus(result == S_OK);
119 params[0] = getStatus();
120
121 break;
122 }
123 case GL_FENCE_CONDITION_NV:
124 params[0] = getCondition();
125 break;
126 default:
shannon.woods@transgaming.com779aa262013-02-28 23:04:58 +0000127 return gl::error(GL_INVALID_ENUM);
shannon.woods@transgaming.combe58aa02013-02-28 23:03:55 +0000128 break;
129 }
130}
131
132}