// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Query.cpp: Implements the es2::Query class #include "Query.h" #include "main.h" #include "Common/Thread.hpp" namespace es2 { Query::Query(GLuint name, GLenum type) : NamedObject(name) { mQuery = nullptr; mStatus = GL_FALSE; mResult = GL_FALSE; mType = type; } Query::~Query() { delete mQuery; } void Query::begin() { if(!mQuery) { sw::Query::Type type; switch(mType) { case GL_ANY_SAMPLES_PASSED_EXT: case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: type = sw::Query::FRAGMENTS_PASSED; break; case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: type = sw::Query::TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN; break; default: UNREACHABLE(mType); return; } mQuery = new sw::Query(type); if(!mQuery) { return error(GL_OUT_OF_MEMORY); } } Device *device = getDevice(); mQuery->begin(); device->addQuery(mQuery); switch(mType) { case GL_ANY_SAMPLES_PASSED_EXT: case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: device->setOcclusionEnabled(true); break; case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: device->setTransformFeedbackQueryEnabled(true); break; default: ASSERT(false); } } void Query::end() { if(!mQuery) { return error(GL_INVALID_OPERATION); } Device *device = getDevice(); mQuery->end(); device->removeQuery(mQuery); switch(mType) { case GL_ANY_SAMPLES_PASSED_EXT: case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: device->setOcclusionEnabled(false); break; case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: device->setTransformFeedbackQueryEnabled(false); break; default: ASSERT(false); } mStatus = GL_FALSE; mResult = GL_FALSE; } GLuint Query::getResult() { if(mQuery) { while(!testQuery()) { sw::Thread::yield(); } } return (GLuint)mResult; } GLboolean Query::isResultAvailable() { if(mQuery) { testQuery(); } return mStatus; } GLenum Query::getType() const { return mType; } GLboolean Query::testQuery() { if(mQuery != nullptr && mStatus != GL_TRUE) { if(!mQuery->building && mQuery->reference == 0) { unsigned int resultSum = mQuery->data; mStatus = GL_TRUE; switch(mType) { case GL_ANY_SAMPLES_PASSED_EXT: case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: mResult = (resultSum > 0) ? GL_TRUE : GL_FALSE; break; case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: mResult = resultSum; break; default: ASSERT(false); } } return mStatus; } return GL_TRUE; // Prevent blocking when query is nullptr } }