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// Query.cpp: Implements the es2::Query class
16
17#include "Query.h"
18
19#include "main.h"
20#include "Common/Thread.hpp"
21
22namespace es2
23{
24
25Query::Query(GLuint name, GLenum type) : NamedObject(name)
26{
27 mQuery = nullptr;
28 mStatus = GL_FALSE;
29 mResult = GL_FALSE;
30 mType = type;
31}
32
33Query::~Query()
34{
35 mQuery->release();
36}
37
38void Query::begin()
39{
40 if(!mQuery)
41 {
42 sw::Query::Type type;
43 switch(mType)
44 {
45 case GL_ANY_SAMPLES_PASSED_EXT:
46 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
47 type = sw::Query::FRAGMENTS_PASSED;
48 break;
49 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
50 type = sw::Query::TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN;
51 break;
52 default:
53 UNREACHABLE(mType);
54 return;
55 }
56
57 mQuery = new sw::Query(type);
58
59 if(!mQuery)
60 {
61 return error(GL_OUT_OF_MEMORY);
62 }
63 }
64
65 Device *device = getDevice();
66
67 mQuery->begin();
68 device->addQuery(mQuery);
69 switch(mType)
70 {
71 case GL_ANY_SAMPLES_PASSED_EXT:
72 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
73 device->setOcclusionEnabled(true);
74 break;
75 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
76 device->setTransformFeedbackQueryEnabled(true);
77 break;
78 default:
79 ASSERT(false);
80 }
81}
82
83void Query::end()
84{
85 if(!mQuery)
86 {
87 return error(GL_INVALID_OPERATION);
88 }
89
90 Device *device = getDevice();
91
92 mQuery->end();
93 device->removeQuery(mQuery);
94 switch(mType)
95 {
96 case GL_ANY_SAMPLES_PASSED_EXT:
97 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
98 device->setOcclusionEnabled(false);
99 break;
100 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
101 device->setTransformFeedbackQueryEnabled(false);
102 break;
103 default:
104 ASSERT(false);
105 }
106
107 mStatus = GL_FALSE;
108 mResult = GL_FALSE;
109}
110
111GLuint Query::getResult()
112{
113 if(mQuery)
114 {
115 while(!testQuery())
116 {
117 sw::Thread::yield();
118 }
119 }
120
121 return (GLuint)mResult;
122}
123
124GLboolean Query::isResultAvailable()
125{
126 if(mQuery)
127 {
128 testQuery();
129 }
130
131 return mStatus;
132}
133
134GLenum Query::getType() const
135{
136 return mType;
137}
138
139GLboolean Query::testQuery()
140{
141 if(mQuery != nullptr && mStatus != GL_TRUE)
142 {
143 if(!mQuery->building && mQuery->isReady())
144 {
145 unsigned int resultSum = mQuery->data;
146 mStatus = GL_TRUE;
147
148 switch(mType)
149 {
150 case GL_ANY_SAMPLES_PASSED_EXT:
151 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
152 mResult = (resultSum > 0) ? GL_TRUE : GL_FALSE;
153 break;
154 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
155 mResult = resultSum;
156 break;
157 default:
158 ASSERT(false);
159 }
160 }
161
162 return mStatus;
163 }
164
165 return GL_TRUE; // Prevent blocking when query is nullptr
166}
167}
168