Implement robust GetQuery entry points.

BUG=angleproject:1354

Change-Id: Ic1aaab56d2313a19fb0362f280dbfbf804fb3fcc
Reviewed-on: https://chromium-review.googlesource.com/399040
Commit-Queue: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp
index b9d9dce..b87820d 100644
--- a/src/libANGLE/Context.cpp
+++ b/src/libANGLE/Context.cpp
@@ -97,22 +97,21 @@
 }
 
 template <typename T>
-gl::Error GetQueryObjectParameter(gl::Context *context, GLuint id, GLenum pname, T *params)
+gl::Error GetQueryObjectParameter(gl::Query *query, GLenum pname, T *params)
 {
-    gl::Query *queryObject = context->getQuery(id, false, GL_NONE);
-    ASSERT(queryObject != nullptr);
+    ASSERT(query != nullptr);
 
     switch (pname)
     {
         case GL_QUERY_RESULT_EXT:
-            return queryObject->getResult(params);
+            return query->getResult(params);
         case GL_QUERY_RESULT_AVAILABLE_EXT:
         {
             bool available;
-            gl::Error error = queryObject->isResultAvailable(&available);
+            gl::Error error = query->isResultAvailable(&available);
             if (!error.isError())
             {
-                *params = static_cast<T>(available ? GL_TRUE : GL_FALSE);
+                *params = gl::ConvertFromGLboolean<T>(available);
             }
             return error;
         }
@@ -1133,24 +1132,24 @@
     }
 }
 
-Error Context::getQueryObjectiv(GLuint id, GLenum pname, GLint *params)
+void Context::getQueryObjectiv(GLuint id, GLenum pname, GLint *params)
 {
-    return GetQueryObjectParameter(this, id, pname, params);
+    handleError(GetQueryObjectParameter(getQuery(id), pname, params));
 }
 
-Error Context::getQueryObjectuiv(GLuint id, GLenum pname, GLuint *params)
+void Context::getQueryObjectuiv(GLuint id, GLenum pname, GLuint *params)
 {
-    return GetQueryObjectParameter(this, id, pname, params);
+    handleError(GetQueryObjectParameter(getQuery(id), pname, params));
 }
 
-Error Context::getQueryObjecti64v(GLuint id, GLenum pname, GLint64 *params)
+void Context::getQueryObjecti64v(GLuint id, GLenum pname, GLint64 *params)
 {
-    return GetQueryObjectParameter(this, id, pname, params);
+    handleError(GetQueryObjectParameter(getQuery(id), pname, params));
 }
 
-Error Context::getQueryObjectui64v(GLuint id, GLenum pname, GLuint64 *params)
+void Context::getQueryObjectui64v(GLuint id, GLenum pname, GLuint64 *params)
 {
-    return GetQueryObjectParameter(this, id, pname, params);
+    handleError(GetQueryObjectParameter(getQuery(id), pname, params));
 }
 
 Framebuffer *Context::getFramebuffer(unsigned int handle) const
diff --git a/src/libANGLE/Context.h b/src/libANGLE/Context.h
index 58cde74..8e39ab5 100644
--- a/src/libANGLE/Context.h
+++ b/src/libANGLE/Context.h
@@ -149,10 +149,10 @@
     Error endQuery(GLenum target);
     Error queryCounter(GLuint id, GLenum target);
     void getQueryiv(GLenum target, GLenum pname, GLint *params);
-    Error getQueryObjectiv(GLuint id, GLenum pname, GLint *params);
-    Error getQueryObjectuiv(GLuint id, GLenum pname, GLuint *params);
-    Error getQueryObjecti64v(GLuint id, GLenum pname, GLint64 *params);
-    Error getQueryObjectui64v(GLuint id, GLenum pname, GLuint64 *params);
+    void getQueryObjectiv(GLuint id, GLenum pname, GLint *params);
+    void getQueryObjectuiv(GLuint id, GLenum pname, GLuint *params);
+    void getQueryObjecti64v(GLuint id, GLenum pname, GLint64 *params);
+    void getQueryObjectui64v(GLuint id, GLenum pname, GLuint64 *params);
 
     void setVertexAttribDivisor(GLuint index, GLuint divisor);
 
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp
index a41e3f6..9c96f78 100644
--- a/src/libANGLE/validationES.cpp
+++ b/src/libANGLE/validationES.cpp
@@ -2001,8 +2001,13 @@
     return true;
 }
 
-bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname)
+bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
 {
+    if (numParams)
+    {
+        *numParams = 0;
+    }
+
     if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
     {
         context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
@@ -2032,6 +2037,12 @@
             return false;
     }
 
+    if (numParams)
+    {
+        // All queries return only one value
+        *numParams = 1;
+    }
+
     return true;
 }
 
@@ -2044,11 +2055,41 @@
         return false;
     }
 
-    return ValidateGetQueryivBase(context, target, pname);
+    return ValidateGetQueryivBase(context, target, pname, nullptr);
 }
 
-bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname)
+bool ValidateGetQueryivRobustANGLE(Context *context,
+                                   GLenum target,
+                                   GLenum pname,
+                                   GLsizei bufSize,
+                                   GLsizei *length,
+                                   GLint *params)
 {
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateGetQueryivBase(context, target, pname, length))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *length))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
+{
+    if (numParams)
+    {
+        *numParams = 0;
+    }
+
     Query *queryObject = context->getQuery(id, false, GL_NONE);
 
     if (!queryObject)
@@ -2074,6 +2115,11 @@
             return false;
     }
 
+    if (numParams)
+    {
+        *numParams = 1;
+    }
+
     return true;
 }
 
@@ -2084,7 +2130,38 @@
         context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
         return false;
     }
-    return ValidateGetQueryObjectValueBase(context, id, pname);
+    return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
+}
+
+bool ValidateGetQueryObjectivRobustANGLE(Context *context,
+                                         GLuint id,
+                                         GLenum pname,
+                                         GLsizei bufSize,
+                                         GLsizei *length,
+                                         GLint *params)
+{
+    if (!context->getExtensions().disjointTimerQuery)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
+        return false;
+    }
+
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *length))
+    {
+        return false;
+    }
+
+    return true;
 }
 
 bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
@@ -2095,7 +2172,39 @@
         context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
         return false;
     }
-    return ValidateGetQueryObjectValueBase(context, id, pname);
+    return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
+}
+
+bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
+                                          GLuint id,
+                                          GLenum pname,
+                                          GLsizei bufSize,
+                                          GLsizei *length,
+                                          GLuint *params)
+{
+    if (!context->getExtensions().disjointTimerQuery &&
+        !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
+        return false;
+    }
+
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *length))
+    {
+        return false;
+    }
+
+    return true;
 }
 
 bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
@@ -2105,7 +2214,38 @@
         context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
         return false;
     }
-    return ValidateGetQueryObjectValueBase(context, id, pname);
+    return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
+}
+
+bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
+                                           GLuint id,
+                                           GLenum pname,
+                                           GLsizei bufSize,
+                                           GLsizei *length,
+                                           GLint64 *params)
+{
+    if (!context->getExtensions().disjointTimerQuery)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
+        return false;
+    }
+
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *length))
+    {
+        return false;
+    }
+
+    return true;
 }
 
 bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
@@ -2115,7 +2255,38 @@
         context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
         return false;
     }
-    return ValidateGetQueryObjectValueBase(context, id, pname);
+    return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
+}
+
+bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
+                                            GLuint id,
+                                            GLenum pname,
+                                            GLsizei bufSize,
+                                            GLsizei *length,
+                                            GLuint64 *params)
+{
+    if (!context->getExtensions().disjointTimerQuery)
+    {
+        context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
+        return false;
+    }
+
+    if (!ValidateRobustEntryPoint(context, bufSize))
+    {
+        return false;
+    }
+
+    if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
+    {
+        return false;
+    }
+
+    if (!ValidateRobustBufferSize(context, bufSize, *length))
+    {
+        return false;
+    }
+
+    return true;
 }
 
 static bool ValidateUniformCommonBase(gl::Context *context,
diff --git a/src/libANGLE/validationES.h b/src/libANGLE/validationES.h
index 0fc5999..de12674 100644
--- a/src/libANGLE/validationES.h
+++ b/src/libANGLE/validationES.h
@@ -138,13 +138,46 @@
 bool ValidateEndQueryBase(Context *context, GLenum target);
 bool ValidateEndQueryEXT(Context *context, GLenum target);
 bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target);
-bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname);
+bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams);
 bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params);
-bool ValidateGetQueryObjectValueBase(Context *context, GLenum target, GLenum pname);
+bool ValidateGetQueryivRobustANGLE(Context *context,
+                                   GLenum target,
+                                   GLenum pname,
+                                   GLsizei bufSize,
+                                   GLsizei *length,
+                                   GLint *params);
+bool ValidateGetQueryObjectValueBase(Context *context,
+                                     GLenum target,
+                                     GLenum pname,
+                                     GLsizei *numParams);
 bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params);
+bool ValidateGetQueryObjectivRobustANGLE(Context *context,
+                                         GLuint id,
+                                         GLenum pname,
+                                         GLsizei bufSize,
+                                         GLsizei *length,
+                                         GLint *params);
 bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params);
+bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
+                                          GLuint id,
+                                          GLenum pname,
+                                          GLsizei bufSize,
+                                          GLsizei *length,
+                                          GLuint *params);
 bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params);
+bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
+                                           GLuint id,
+                                           GLenum pname,
+                                           GLsizei bufSize,
+                                           GLsizei *length,
+                                           GLint64 *params);
 bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params);
+bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
+                                            GLuint id,
+                                            GLenum pname,
+                                            GLsizei bufSize,
+                                            GLsizei *length,
+                                            GLuint64 *params);
 
 bool ValidateUniform(Context *context, GLenum uniformType, GLint location, GLsizei count);
 bool ValidateUniformMatrix(Context *context, GLenum matrixType, GLint location, GLsizei count,
diff --git a/src/libANGLE/validationES3.cpp b/src/libANGLE/validationES3.cpp
index 03b48b3..692d739 100644
--- a/src/libANGLE/validationES3.cpp
+++ b/src/libANGLE/validationES3.cpp
@@ -945,7 +945,7 @@
         return false;
     }
 
-    return ValidateGetQueryivBase(context, target, pname);
+    return ValidateGetQueryivBase(context, target, pname, nullptr);
 }
 
 bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
@@ -956,7 +956,7 @@
         return false;
     }
 
-    return ValidateGetQueryObjectValueBase(context, id, pname);
+    return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
 }
 
 bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment,
diff --git a/src/libGLESv2/entry_points_gles_2_0_ext.cpp b/src/libGLESv2/entry_points_gles_2_0_ext.cpp
index 6197907..3588b3c 100644
--- a/src/libGLESv2/entry_points_gles_2_0_ext.cpp
+++ b/src/libGLESv2/entry_points_gles_2_0_ext.cpp
@@ -187,12 +187,7 @@
             return;
         }
 
-        Error error = context->getQueryObjectiv(id, pname, params);
-        if (error.isError())
-        {
-            context->handleError(error);
-            return;
-        }
+        context->getQueryObjectiv(id, pname, params);
     }
 }
 
@@ -208,12 +203,7 @@
             return;
         }
 
-        Error error = context->getQueryObjectuiv(id, pname, params);
-        if (error.isError())
-        {
-            context->handleError(error);
-            return;
-        }
+        context->getQueryObjectuiv(id, pname, params);
     }
 }
 
@@ -229,12 +219,7 @@
             return;
         }
 
-        Error error = context->getQueryObjecti64v(id, pname, params);
-        if (error.isError())
-        {
-            context->handleError(error);
-            return;
-        }
+        context->getQueryObjecti64v(id, pname, params);
     }
 }
 
@@ -250,12 +235,7 @@
             return;
         }
 
-        Error error = context->getQueryObjectui64v(id, pname, params);
-        if (error.isError())
-        {
-            context->handleError(error);
-            return;
-        }
+        context->getQueryObjectui64v(id, pname, params);
     }
 }
 
@@ -2584,7 +2564,19 @@
         "(GLenum target = 0x%X, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = "
         "0x%0.8p, GLint* params = 0x%0.8p)",
         target, pname, bufSize, length, params);
-    UNIMPLEMENTED();
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei numParams = 0;
+        if (!ValidateGetQueryivRobustANGLE(context, target, pname, bufSize, &numParams, params))
+        {
+            return;
+        }
+
+        context->getQueryiv(target, pname, params);
+        SetRobustLengthParam(length, numParams);
+    }
 }
 
 ANGLE_EXPORT void GL_APIENTRY GetQueryObjectuivRobustANGLE(GLuint id,
@@ -2597,7 +2589,19 @@
         "(GLuint id = %u, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
         "GLint* params = 0x%0.8p)",
         id, pname, bufSize, length, params);
-    UNIMPLEMENTED();
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei numParams = 0;
+        if (!ValidateGetQueryObjectuivRobustANGLE(context, id, pname, bufSize, &numParams, params))
+        {
+            return;
+        }
+
+        context->getQueryObjectuiv(id, pname, params);
+        SetRobustLengthParam(length, numParams);
+    }
 }
 
 ANGLE_EXPORT void GL_APIENTRY GetBufferPointervRobustANGLE(GLenum target,
@@ -3174,7 +3178,19 @@
         "(GLuint id = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
         "GLuint *params = 0x%0.8p)",
         id, pname, bufSize, length, params);
-    UNIMPLEMENTED();
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei numParams = 0;
+        if (!ValidateGetQueryObjectivRobustANGLE(context, id, pname, bufSize, &numParams, params))
+        {
+            return;
+        }
+
+        context->getQueryObjectiv(id, pname, params);
+        SetRobustLengthParam(length, numParams);
+    }
 }
 
 ANGLE_EXPORT void GL_APIENTRY GetQueryObjecti64vRobustANGLE(GLuint id,
@@ -3187,7 +3203,19 @@
         "(GLuint id = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
         "GLint64 *params = 0x%0.8p)",
         id, pname, bufSize, length, params);
-    UNIMPLEMENTED();
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei numParams = 0;
+        if (!ValidateGetQueryObjecti64vRobustANGLE(context, id, pname, bufSize, &numParams, params))
+        {
+            return;
+        }
+
+        context->getQueryObjecti64v(id, pname, params);
+        SetRobustLengthParam(length, numParams);
+    }
 }
 
 ANGLE_EXPORT void GL_APIENTRY GetQueryObjectui64vRobustANGLE(GLuint id,
@@ -3200,7 +3228,20 @@
         "(GLuint id = %d, GLenum pname = 0x%X, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, "
         "GLuint64 *params = 0x%0.8p)",
         id, pname, bufSize, length, params);
-    UNIMPLEMENTED();
+
+    Context *context = GetValidGlobalContext();
+    if (context)
+    {
+        GLsizei numParams = 0;
+        if (!ValidateGetQueryObjectui64vRobustANGLE(context, id, pname, bufSize, &numParams,
+                                                    params))
+        {
+            return;
+        }
+
+        context->getQueryObjectui64v(id, pname, params);
+        SetRobustLengthParam(length, numParams);
+    }
 }
 
 }  // gl
diff --git a/src/libGLESv2/entry_points_gles_3_0.cpp b/src/libGLESv2/entry_points_gles_3_0.cpp
index cf97f0f..263f916 100644
--- a/src/libGLESv2/entry_points_gles_3_0.cpp
+++ b/src/libGLESv2/entry_points_gles_3_0.cpp
@@ -310,12 +310,7 @@
             return;
         }
 
-        Error error = context->getQueryObjectuiv(id, pname, params);
-        if (error.isError())
-        {
-            context->handleError(error);
-            return;
-        }
+        context->getQueryObjectuiv(id, pname, params);
     }
 }