1//
2// Copyright (c) 2002-2010 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// Fence.cpp: Implements the gl::Fence class, which supports the GL_NV_fence extension.
8
9#include "libGLESv2/Fence.h"
10
11#include "libGLESv2/main.h"
12
13namespace gl
14{
15
16Fence::Fence()
17{
18    mQuery = NULL;
19    mCondition = GL_NONE;
20    mStatus = GL_FALSE;
21}
22
23Fence::~Fence()
24{
25    if (mQuery != NULL)
26    {
27        mQuery->Release();
28        mQuery = NULL;
29    }
30}
31
32GLboolean Fence::isFence()
33{
34    // GL_NV_fence spec:
35    // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence.
36    return mQuery != NULL;
37}
38
39void Fence::setFence(GLenum condition)
40{
41    if (mQuery != NULL)
42    {
43        mQuery->Release();
44        mQuery = NULL;
45    }
46
47    if (FAILED(getDevice()->CreateQuery(D3DQUERYTYPE_EVENT, &mQuery)))
48    {
49        return error(GL_OUT_OF_MEMORY);
50    }
51
52    HRESULT result = mQuery->Issue(D3DISSUE_END);
53    ASSERT(SUCCEEDED(result));
54
55    mCondition = condition;
56    mStatus = GL_FALSE;
57}
58
59GLboolean Fence::testFence()
60{
61    if (mQuery == NULL)
62    {
63        return error(GL_INVALID_OPERATION, GL_TRUE);
64    }
65
66    HRESULT result = mQuery->GetData(NULL, 0, D3DGETDATA_FLUSH);
67
68    if (result == D3DERR_DEVICELOST)
69    {
70       return error(GL_OUT_OF_MEMORY, GL_TRUE);
71    }
72
73    ASSERT(result == S_OK || result == S_FALSE);
74    mStatus = result == S_OK;
75    return mStatus;
76}
77
78void Fence::finishFence()
79{
80    if (mQuery == NULL)
81    {
82        return error(GL_INVALID_OPERATION);
83    }
84
85    while (!testFence())
86    {
87        Sleep(0);
88    }
89}
90
91void Fence::getFenceiv(GLenum pname, GLint *params)
92{
93    if (mQuery == NULL)
94    {
95        return error(GL_INVALID_OPERATION);
96    }
97
98    switch (pname)
99    {
100        case GL_FENCE_STATUS_NV:
101        {
102            // GL_NV_fence spec:
103            // Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV
104            // or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence.
105            if (mStatus)
106            {
107                params[0] = GL_TRUE;
108                return;
109            }
110
111            HRESULT result = mQuery->GetData(NULL, 0, 0);
112
113            if (result == D3DERR_DEVICELOST)
114            {
115                params[0] = GL_TRUE;
116                return error(GL_OUT_OF_MEMORY);
117            }
118
119            ASSERT(result == S_OK || result == S_FALSE);
120            mStatus = result == S_OK;
121            params[0] = mStatus;
122
123            break;
124        }
125        case GL_FENCE_CONDITION_NV:
126            params[0] = mCondition;
127            break;
128        default:
129            return error(GL_INVALID_ENUM);
130            break;
131    }
132}
133
134}
135