Created Fence11.

TRAC #22420

Signed-off-by: Jamie Madill
Signed-off-by: Shannon Woods
Author: Geoff Lang

git-svn-id: https://angleproject.googlecode.com/svn/branches/dx11proto@1847 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/renderer/Fence11.cpp b/src/libGLESv2/renderer/Fence11.cpp
new file mode 100644
index 0000000..2959a0a
--- /dev/null
+++ b/src/libGLESv2/renderer/Fence11.cpp
@@ -0,0 +1,132 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Fence11.cpp: Defines the rx::Fence11 class which implements rx::FenceImpl.
+
+#include "libGLESv2/renderer/Fence11.h"
+#include "libGLESv2/main.h"
+
+namespace rx
+{
+
+Fence11::Fence11(rx::Renderer11 *renderer)
+{
+    mRenderer = renderer;
+    mQuery = NULL;
+}
+
+Fence11::~Fence11()
+{
+    if (mQuery)
+    {
+        mQuery->Release();
+        mQuery = NULL;
+    }
+}
+
+GLboolean Fence11::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 != NULL;
+}
+
+void Fence11::setFence(GLenum condition)
+{
+    if (!mQuery)
+    {
+        D3D11_QUERY_DESC queryDesc;
+        queryDesc.Query = D3D11_QUERY_EVENT;
+        queryDesc.MiscFlags = 0;
+
+        if (FAILED(mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery)))
+        {
+            return error(GL_OUT_OF_MEMORY);
+        }
+    }
+
+    mRenderer->getDeviceContext()->End(mQuery);
+
+    setCondition(condition);
+    setStatus(GL_FALSE);
+}
+
+GLboolean Fence11::testFence()
+{
+    if (mQuery == NULL)
+    {
+        return error(GL_INVALID_OPERATION, GL_TRUE);
+    }
+
+    HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, NULL, 0, 0);
+
+    if (mRenderer->isDeviceLost())
+    {
+       return error(GL_OUT_OF_MEMORY, GL_TRUE);
+    }
+
+    ASSERT(result == S_OK || result == S_FALSE);
+    setStatus(result == S_OK);
+    return getStatus();
+}
+
+void Fence11::finishFence()
+{
+    if (mQuery == NULL)
+    {
+        return error(GL_INVALID_OPERATION);
+    }
+
+    while (!testFence())
+    {
+        Sleep(0);
+    }
+}
+
+void Fence11::getFenceiv(GLenum pname, GLint *params)
+{
+    if (mQuery == NULL)
+    {
+        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 (getStatus())
+            {
+                params[0] = GL_TRUE;
+                return;
+            }
+
+            HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH);
+
+            if (mRenderer->isDeviceLost())
+            {
+                params[0] = GL_TRUE;
+                return error(GL_OUT_OF_MEMORY);
+            }
+
+            ASSERT(result == S_OK || result == S_FALSE);
+            setStatus(result == S_OK);
+            params[0] = getStatus();
+
+            break;
+        }
+      case GL_FENCE_CONDITION_NV:
+        params[0] = getCondition();
+        break;
+      default:
+        return error(GL_INVALID_ENUM);
+        break;
+    }
+}
+
+}
diff --git a/src/libGLESv2/renderer/Fence11.h b/src/libGLESv2/renderer/Fence11.h
new file mode 100644
index 0000000..bb33401
--- /dev/null
+++ b/src/libGLESv2/renderer/Fence11.h
@@ -0,0 +1,39 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Fence11.h: Defines the rx::Fence11 class which implements rx::FenceImpl.
+
+#ifndef LIBGLESV2_RENDERER_Fence11_H_
+#define LIBGLESV2_RENDERER_Fence11_H_
+
+#include "libGLESv2/renderer/FenceImpl.h"
+#include "libGLESv2/renderer/Renderer11.h"
+
+namespace rx
+{
+
+class Fence11 : public FenceImpl
+{
+  public:
+    explicit Fence11(rx::Renderer11 *renderer);
+    virtual ~Fence11();
+
+    GLboolean isFence();
+    void setFence(GLenum condition);
+    GLboolean testFence();
+    void finishFence();
+    void getFenceiv(GLenum pname, GLint *params);
+
+  private:
+    DISALLOW_COPY_AND_ASSIGN(Fence11);
+
+    rx::Renderer11 *mRenderer;
+    ID3D11Query *mQuery;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_FENCE11_H_
diff --git a/src/libGLESv2/renderer/Renderer11.cpp b/src/libGLESv2/renderer/Renderer11.cpp
index 602a423..69819ad 100644
--- a/src/libGLESv2/renderer/Renderer11.cpp
+++ b/src/libGLESv2/renderer/Renderer11.cpp
@@ -26,6 +26,7 @@
 #include "libGLESv2/renderer/IndexDataManager.h"
 #include "libGLESv2/renderer/TextureStorage11.h"
 #include "libGLESv2/renderer/Query11.h"
+#include "libGLESv2/renderer/Fence11.h"
 
 #include "libGLESv2/renderer/shaders/compiled/passthrough11vs.h"
 #include "libGLESv2/renderer/shaders/compiled/passthroughrgba11ps.h"
@@ -1917,9 +1918,7 @@
 
 bool Renderer11::getEventQuerySupport()
 {
-    // TODO
-    // UNIMPLEMENTED();
-    return false;
+    return true;
 }
 
 unsigned int Renderer11::getMaxVertexTextureImageUnits() const
@@ -2563,9 +2562,7 @@
 
 FenceImpl *Renderer11::createFence()
 {
-    // TODO
-    UNIMPLEMENTED();
-    return NULL;
+    return new Fence11(this);
 }
 
 bool Renderer11::getRenderTargetResource(gl::Framebuffer *framebuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource)