Adds support for EXT_occlusion_query_boolean

TRAC #19360
Signed-off-by: Daniel Koch
Authored-by: Shannon Woods

git-svn-id: https://angleproject.googlecode.com/svn/trunk@951 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/Query.cpp b/src/libGLESv2/Query.cpp
new file mode 100644
index 0000000..10edda5
--- /dev/null
+++ b/src/libGLESv2/Query.cpp
@@ -0,0 +1,128 @@
+//
+// Copyright (c) 2012 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.
+//
+
+// Query.cpp: Implements the gl::Query class
+
+#include "libGLESv2/Query.h"
+
+#include "libGLESv2/main.h"
+
+namespace gl
+{
+
+Query::Query(GLuint id, GLenum type) : RefCountObject(id)
+{ 
+    mQuery = NULL;
+    mStatus = GL_FALSE;
+    mResult = GL_FALSE;
+    mType = type;
+}
+
+Query::~Query()
+{
+    if (mQuery != NULL)
+    {
+        mQuery->Release();
+        mQuery = NULL;
+    }
+}
+
+void Query::begin()
+{
+    if (mQuery == NULL)
+    {
+        if (FAILED(getDevice()->CreateQuery(D3DQUERYTYPE_OCCLUSION, &mQuery)))
+        {
+            return error(GL_OUT_OF_MEMORY);
+        }
+    }
+
+    HRESULT result = mQuery->Issue(D3DISSUE_BEGIN);
+    ASSERT(SUCCEEDED(result));
+}
+
+void Query::end()
+{
+    if (mQuery == NULL)
+    {
+        return error(GL_INVALID_OPERATION);
+    }
+
+    HRESULT result = mQuery->Issue(D3DISSUE_END);
+    ASSERT(SUCCEEDED(result));
+    
+    mStatus = GL_FALSE;
+    mResult = GL_FALSE;
+}
+
+GLuint Query::getResult()
+{
+    if (mQuery != NULL)
+    {
+        while (!testQuery())
+        {
+            Sleep(0);
+            // explicitly check for device loss
+            // some drivers seem to return S_FALSE even if the device is lost
+            // instead of D3DERR_DEVICELOST like they should
+            if (gl::getDisplay()->testDeviceLost())
+            {
+                gl::getDisplay()->notifyDeviceLost();
+                return error(GL_OUT_OF_MEMORY, 0);
+            }
+        }
+    }
+
+    return (GLuint)mResult;
+}
+
+GLboolean Query::isResultAvailable()
+{
+    if (mQuery != NULL)
+    {
+        testQuery();
+    }
+    
+    return mStatus;
+}
+
+GLenum Query::getType() const
+{
+    return mType;
+}
+
+GLboolean Query::testQuery()
+{
+    if (mQuery != NULL && mStatus != GL_TRUE)
+    {
+        DWORD numPixels = 0;
+
+        HRESULT hres = mQuery->GetData(&numPixels, sizeof(DWORD), D3DGETDATA_FLUSH);
+        if (hres == S_OK)
+        {
+            mStatus = GL_TRUE;
+
+            switch (mType)
+            {
+              case GL_ANY_SAMPLES_PASSED_EXT:
+              case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
+                mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE;
+                break;
+              default:
+                ASSERT(false);
+            }
+        }
+        else if (checkDeviceLost(hres))
+        {
+            return error(GL_OUT_OF_MEMORY, GL_TRUE);
+        }
+        
+        return mStatus;
+    }
+
+    return GL_TRUE; // prevent blocking when query is null
+}
+}