1 //
2 // Copyright 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 // Query9.cpp: Defines the rx::Query9 class which implements rx::QueryImpl.
8 
9 #include "libANGLE/renderer/d3d/d3d9/Query9.h"
10 
11 #include "libANGLE/Context.h"
12 #include "libANGLE/renderer/d3d/d3d9/Context9.h"
13 #include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
14 #include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
15 
16 #include <GLES2/gl2ext.h>
17 
18 namespace rx
19 {
Query9(Renderer9 * renderer,gl::QueryType type)20 Query9::Query9(Renderer9 *renderer, gl::QueryType type)
21     : QueryImpl(type),
22       mGetDataAttemptCount(0),
23       mResult(GL_FALSE),
24       mQueryFinished(false),
25       mRenderer(renderer),
26       mQuery(nullptr)
27 {}
28 
~Query9()29 Query9::~Query9()
30 {
31     SafeRelease(mQuery);
32 }
33 
begin(const gl::Context * context)34 angle::Result Query9::begin(const gl::Context *context)
35 {
36     Context9 *context9 = GetImplAs<Context9>(context);
37 
38     D3DQUERYTYPE d3dQueryType = gl_d3d9::ConvertQueryType(getType());
39     if (mQuery == nullptr)
40     {
41         HRESULT result = mRenderer->getDevice()->CreateQuery(d3dQueryType, &mQuery);
42         ANGLE_TRY_HR(context9, result, "Internal query creation failed");
43     }
44 
45     if (d3dQueryType != D3DQUERYTYPE_EVENT)
46     {
47         HRESULT result = mQuery->Issue(D3DISSUE_BEGIN);
48         ASSERT(SUCCEEDED(result));
49         ANGLE_TRY_HR(context9, result, "Failed to begin internal query");
50     }
51 
52     return angle::Result::Continue;
53 }
54 
end(const gl::Context * context)55 angle::Result Query9::end(const gl::Context *context)
56 {
57     Context9 *context9 = GetImplAs<Context9>(context);
58     ASSERT(mQuery);
59 
60     HRESULT result = mQuery->Issue(D3DISSUE_END);
61     ASSERT(SUCCEEDED(result));
62     ANGLE_TRY_HR(context9, result, "Failed to end internal query");
63     mQueryFinished = false;
64     mResult        = GL_FALSE;
65 
66     return angle::Result::Continue;
67 }
68 
queryCounter(const gl::Context * context)69 angle::Result Query9::queryCounter(const gl::Context *context)
70 {
71     ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
72 }
73 
74 template <typename T>
getResultBase(Context9 * context9,T * params)75 angle::Result Query9::getResultBase(Context9 *context9, T *params)
76 {
77     while (!mQueryFinished)
78     {
79         ANGLE_TRY(testQuery(context9));
80 
81         if (!mQueryFinished)
82         {
83             Sleep(0);
84         }
85     }
86 
87     ASSERT(mQueryFinished);
88     *params = static_cast<T>(mResult);
89     return angle::Result::Continue;
90 }
91 
getResult(const gl::Context * context,GLint * params)92 angle::Result Query9::getResult(const gl::Context *context, GLint *params)
93 {
94     return getResultBase(GetImplAs<Context9>(context), params);
95 }
96 
getResult(const gl::Context * context,GLuint * params)97 angle::Result Query9::getResult(const gl::Context *context, GLuint *params)
98 {
99     return getResultBase(GetImplAs<Context9>(context), params);
100 }
101 
getResult(const gl::Context * context,GLint64 * params)102 angle::Result Query9::getResult(const gl::Context *context, GLint64 *params)
103 {
104     return getResultBase(GetImplAs<Context9>(context), params);
105 }
106 
getResult(const gl::Context * context,GLuint64 * params)107 angle::Result Query9::getResult(const gl::Context *context, GLuint64 *params)
108 {
109     return getResultBase(GetImplAs<Context9>(context), params);
110 }
111 
isResultAvailable(const gl::Context * context,bool * available)112 angle::Result Query9::isResultAvailable(const gl::Context *context, bool *available)
113 {
114     ANGLE_TRY(testQuery(GetImplAs<Context9>(context)));
115     *available = mQueryFinished;
116     return angle::Result::Continue;
117 }
118 
testQuery(Context9 * context9)119 angle::Result Query9::testQuery(Context9 *context9)
120 {
121     if (!mQueryFinished)
122     {
123         ASSERT(mQuery);
124 
125         HRESULT result = S_OK;
126         switch (getType())
127         {
128             case gl::QueryType::AnySamples:
129             case gl::QueryType::AnySamplesConservative:
130             {
131                 DWORD numPixels = 0;
132                 result          = mQuery->GetData(&numPixels, sizeof(numPixels), D3DGETDATA_FLUSH);
133                 if (result == S_OK)
134                 {
135                     mQueryFinished = true;
136                     mResult        = (numPixels > 0) ? GL_TRUE : GL_FALSE;
137                 }
138                 break;
139             }
140 
141             case gl::QueryType::CommandsCompleted:
142             {
143                 BOOL completed = FALSE;
144                 result         = mQuery->GetData(&completed, sizeof(completed), D3DGETDATA_FLUSH);
145                 if (result == S_OK)
146                 {
147                     mQueryFinished = true;
148                     mResult        = (completed == TRUE) ? GL_TRUE : GL_FALSE;
149                 }
150                 break;
151             }
152 
153             default:
154                 UNREACHABLE();
155                 break;
156         }
157 
158         if (!mQueryFinished)
159         {
160             ANGLE_TRY_HR(context9, result, "Failed to test get query result");
161 
162             mGetDataAttemptCount++;
163             bool checkDeviceLost =
164                 (mGetDataAttemptCount % kPollingD3DDeviceLostCheckFrequency) == 0;
165             if (checkDeviceLost && mRenderer->testDeviceLost())
166             {
167                 ANGLE_TRY_HR(context9, D3DERR_DEVICELOST,
168                              "Failed to test get query result, device is lost");
169             }
170         }
171     }
172 
173     return angle::Result::Continue;
174 }
175 
176 }  // namespace rx
177