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// Fence.cpp: Implements the Fence class, which supports the GL_NV_fence extension.
16
17#include "Fence.h"
18
19#include "main.h"
20#include "Common/Thread.hpp"
21
22namespace gl
23{
24
25Fence::Fence()
26{
27	mQuery = false;
28	mCondition = GL_NONE;
29	mStatus = GL_FALSE;
30}
31
32Fence::~Fence()
33{
34	mQuery = false;
35}
36
37GLboolean Fence::isFence()
38{
39	// GL_NV_fence spec:
40	// A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence.
41	return mQuery;
42}
43
44void Fence::setFence(GLenum condition)
45{
46	if(condition != GL_ALL_COMPLETED_NV)
47	{
48		return error(GL_INVALID_VALUE);
49	}
50
51	mQuery = true;
52	mCondition = condition;
53	mStatus = GL_FALSE;
54}
55
56GLboolean Fence::testFence()
57{
58	if(!mQuery)
59	{
60		return error(GL_INVALID_OPERATION, GL_TRUE);
61	}
62
63	// The current assumtion is that no matter where the fence is placed, it is
64	// done by the time it is tested, which is similar to Context::flush(), since
65	// we don't queue anything without processing it as fast as possible.
66	mStatus = GL_TRUE;
67
68	return mStatus;
69}
70
71void Fence::finishFence()
72{
73	if(!mQuery)
74	{
75		return error(GL_INVALID_OPERATION);
76	}
77
78	while(!testFence())
79	{
80		sw::Thread::yield();
81	}
82}
83
84void Fence::getFenceiv(GLenum pname, GLint *params)
85{
86	if(!mQuery)
87	{
88		return error(GL_INVALID_OPERATION);
89	}
90
91	switch(pname)
92	{
93	case GL_FENCE_STATUS_NV:
94		{
95			// GL_NV_fence spec:
96			// Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV
97			// or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence.
98			if(mStatus)
99			{
100				params[0] = GL_TRUE;
101				return;
102			}
103
104			mStatus = testFence();
105
106			params[0] = mStatus;
107			break;
108		}
109	case GL_FENCE_CONDITION_NV:
110		params[0] = mCondition;
111		break;
112	default:
113		return error(GL_INVALID_ENUM);
114		break;
115	}
116}
117
118}
119