| // 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. | 
 |  | 
 | // Fence.cpp: Implements the Fence class, which supports the GL_NV_fence extension. | 
 |  | 
 | #include "Fence.h" | 
 |  | 
 | #include "main.h" | 
 | #include "Common/Thread.hpp" | 
 |  | 
 | namespace es2 | 
 | { | 
 |  | 
 | Fence::Fence() | 
 | { | 
 | 	mQuery = false; | 
 | 	mCondition = GL_NONE; | 
 | 	mStatus = GL_FALSE; | 
 | } | 
 |  | 
 | Fence::~Fence() | 
 | { | 
 | 	mQuery = false; | 
 | } | 
 |  | 
 | GLboolean Fence::isFence() | 
 | { | 
 | 	// GL_NV_fence spec: | 
 | 	// A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence. | 
 | 	return mQuery; | 
 | } | 
 |  | 
 | void Fence::setFence(GLenum condition) | 
 | { | 
 | 	if(condition != GL_ALL_COMPLETED_NV) | 
 | 	{ | 
 | 		return error(GL_INVALID_VALUE); | 
 | 	} | 
 |  | 
 | 	mQuery = true; | 
 | 	mCondition = condition; | 
 | 	mStatus = GL_FALSE; | 
 | } | 
 |  | 
 | GLboolean Fence::testFence() | 
 | { | 
 | 	if(!mQuery) | 
 | 	{ | 
 | 		return error(GL_INVALID_OPERATION, GL_TRUE); | 
 | 	} | 
 |  | 
 | 	// The current assumtion is that no matter where the fence is placed, it is | 
 | 	// done by the time it is tested, which is similar to Context::flush(), since | 
 | 	// we don't queue anything without processing it as fast as possible. | 
 | 	mStatus = GL_TRUE; | 
 |  | 
 | 	return mStatus; | 
 | } | 
 |  | 
 | void Fence::finishFence() | 
 | { | 
 | 	if(!mQuery) | 
 | 	{ | 
 | 		return error(GL_INVALID_OPERATION); | 
 | 	} | 
 |  | 
 | 	while(!testFence()) | 
 | 	{ | 
 | 		sw::Thread::yield(); | 
 | 	} | 
 | } | 
 |  | 
 | void Fence::getFenceiv(GLenum pname, GLint *params) | 
 | { | 
 | 	if(!mQuery) | 
 | 	{ | 
 | 		return error(GL_INVALID_OPERATION); | 
 | 	} | 
 |  | 
 | 	switch(pname) | 
 | 	{ | 
 | 	case GL_FENCE_STATUS_NV: | 
 | 		{ | 
 | 			// GL_NV_fence spec: | 
 | 			// Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV | 
 | 			// or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence. | 
 | 			if(mStatus) | 
 | 			{ | 
 | 				params[0] = GL_TRUE; | 
 | 				return; | 
 | 			} | 
 |  | 
 | 			mStatus = testFence(); | 
 |  | 
 | 			params[0] = mStatus; | 
 | 			break; | 
 | 		} | 
 | 	case GL_FENCE_CONDITION_NV: | 
 | 		params[0] = mCondition; | 
 | 		break; | 
 | 	default: | 
 | 		return error(GL_INVALID_ENUM); | 
 | 		break; | 
 | 	} | 
 | } | 
 |  | 
 | FenceSync::FenceSync(GLuint name, GLenum condition, GLbitfield flags) : NamedObject(name), mCondition(condition), mFlags(flags) | 
 | { | 
 | } | 
 |  | 
 | FenceSync::~FenceSync() | 
 | { | 
 | } | 
 |  | 
 | GLenum FenceSync::clientWait(GLbitfield flags, GLuint64 timeout) | 
 | { | 
 | 	// The current assumtion is that no matter where the fence is placed, it is | 
 | 	// done by the time it is tested, which is similar to Context::flush(), since | 
 | 	// we don't queue anything without processing it as fast as possible. | 
 | 	return GL_ALREADY_SIGNALED; | 
 | } | 
 |  | 
 | void FenceSync::serverWait(GLbitfield flags, GLuint64 timeout) | 
 | { | 
 | } | 
 |  | 
 | void FenceSync::getSynciv(GLenum pname, GLsizei *length, GLint *values) | 
 | { | 
 | 	switch(pname) | 
 | 	{ | 
 | 	case GL_OBJECT_TYPE: | 
 | 		values[0] = GL_SYNC_FENCE; | 
 | 		if(length) { | 
 | 			*length = 1; | 
 | 		} | 
 | 		break; | 
 | 	case GL_SYNC_STATUS: | 
 | 		// The current assumtion is that no matter where the fence is placed, it is | 
 | 		// done by the time it is tested, which is similar to Context::flush(), since | 
 | 		// we don't queue anything without processing it as fast as possible. | 
 | 		values[0] = GL_SIGNALED; | 
 | 		if(length) { | 
 | 			*length = 1; | 
 | 		} | 
 | 		break; | 
 | 	case GL_SYNC_CONDITION: | 
 | 		values[0] = GL_SYNC_GPU_COMMANDS_COMPLETE; | 
 | 		if(length) { | 
 | 			*length = 1; | 
 | 		} | 
 | 		break; | 
 | 	case GL_SYNC_FLAGS: | 
 | 		if(length) { | 
 | 			*length = 0; | 
 | 		} | 
 | 		break; | 
 | 	default: | 
 | 		return error(GL_INVALID_ENUM); | 
 | 	} | 
 | } | 
 |  | 
 | } |