Implement FenceNVGL.

BUG=angleproject:888

Change-Id: Iea6993fe5459cf829f4bd23b0df5e223f22903f5
Reviewed-on: https://chromium-review.googlesource.com/264989
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Tested-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/renderer/gl/FenceNVGL.cpp b/src/libANGLE/renderer/gl/FenceNVGL.cpp
index 6e4dd40..b463054 100644
--- a/src/libANGLE/renderer/gl/FenceNVGL.cpp
+++ b/src/libANGLE/renderer/gl/FenceNVGL.cpp
@@ -9,33 +9,43 @@
 #include "libANGLE/renderer/gl/FenceNVGL.h"
 
 #include "common/debug.h"
+#include "libANGLE/renderer/gl/FunctionsGL.h"
+
 
 namespace rx
 {
 
-FenceNVGL::FenceNVGL()
-    : FenceNVImpl()
-{}
+FenceNVGL::FenceNVGL(const FunctionsGL *functions)
+    : FenceNVImpl(),
+      mFunctions(functions)
+{
+    mFunctions->genFencesNV(1, &mFence);
+}
 
 FenceNVGL::~FenceNVGL()
-{}
-
-gl::Error FenceNVGL::set()
 {
-    UNIMPLEMENTED();
-    return gl::Error(GL_INVALID_OPERATION);
+    mFunctions->deleteFencesNV(1, &mFence);
+    mFence = 0;
 }
 
-gl::Error FenceNVGL::test(bool flushCommandBuffer, GLboolean *outFinished)
+gl::Error FenceNVGL::set(GLenum condition)
 {
-    UNIMPLEMENTED();
-    return gl::Error(GL_INVALID_OPERATION);
+    ASSERT(condition == GL_ALL_COMPLETED_NV);
+    mFunctions->setFenceNV(mFence, condition);
+    return gl::Error(GL_NO_ERROR);
 }
 
-gl::Error FenceNVGL::finishFence(GLboolean *outFinished)
+gl::Error FenceNVGL::test(GLboolean *outFinished)
 {
-    UNIMPLEMENTED();
-    return gl::Error(GL_INVALID_OPERATION);
+    ASSERT(outFinished);
+    *outFinished = mFunctions->testFenceNV(mFence);
+    return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error FenceNVGL::finish()
+{
+    mFunctions->finishFenceNV(mFence);
+    return gl::Error(GL_NO_ERROR);
 }
 
 }
diff --git a/src/libANGLE/renderer/gl/FenceNVGL.h b/src/libANGLE/renderer/gl/FenceNVGL.h
index 84d549f..ffeca85 100644
--- a/src/libANGLE/renderer/gl/FenceNVGL.h
+++ b/src/libANGLE/renderer/gl/FenceNVGL.h
@@ -13,16 +13,22 @@
 
 namespace rx
 {
+class FunctionsGL;
 
 class FenceNVGL : public FenceNVImpl
 {
   public:
-    FenceNVGL();
+    explicit FenceNVGL(const FunctionsGL *functions);
     ~FenceNVGL() override;
 
-    gl::Error set() override;
-    gl::Error test(bool flushCommandBuffer, GLboolean *outFinished) override;
-    gl::Error finishFence(GLboolean *outFinished) override;
+    gl::Error set(GLenum condition) override;
+    gl::Error test(GLboolean *outFinished) override;
+    gl::Error finish() override;
+
+  private:
+    GLuint mFence;
+
+    const FunctionsGL *mFunctions;
 };
 
 }
diff --git a/src/libANGLE/renderer/gl/FunctionsGL.cpp b/src/libANGLE/renderer/gl/FunctionsGL.cpp
index e20249f..926209b 100644
--- a/src/libANGLE/renderer/gl/FunctionsGL.cpp
+++ b/src/libANGLE/renderer/gl/FunctionsGL.cpp
@@ -159,6 +159,14 @@
       texImage3D(nullptr),
       texSubImage3D(nullptr),
 
+      deleteFencesNV(nullptr),
+      genFencesNV(nullptr),
+      isFenceNV(nullptr),
+      testFenceNV(nullptr),
+      getFenceivNV(nullptr),
+      finishFenceNV(nullptr),
+      setFenceNV(nullptr),
+
       activeTexture(nullptr),
       compressedTexImage1D(nullptr),
       compressedTexImage2D(nullptr),
@@ -863,6 +871,15 @@
         AssignGLEntryPoint(loadProcAddress("glDrawRangeElements"), &drawRangeElements);
         AssignGLEntryPoint(loadProcAddress("glTexImage3D"), &texImage3D);
         AssignGLEntryPoint(loadProcAddress("glTexSubImage3D"), &texSubImage3D);
+
+        // Extensions
+        AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glDeleteFencesNV"), &deleteFencesNV);
+        AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glGenFencesNV"), &genFencesNV);
+        AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glIsFenceNV"), &isFenceNV);
+        AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glTestFenceNV"), &testFenceNV);
+        AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glGetFenceivNV"), &getFenceivNV);
+        AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glFinishFenceNV"), &finishFenceNV);
+        AssignGLExtensionEntryPoint(extensions, "GL_NV_fence", loadProcAddress("glSetFenceNV"), &setFenceNV);
     }
 
     // 1.3
diff --git a/src/libANGLE/renderer/gl/FunctionsGL.h b/src/libANGLE/renderer/gl/FunctionsGL.h
index f479086..bf6c2bf 100644
--- a/src/libANGLE/renderer/gl/FunctionsGL.h
+++ b/src/libANGLE/renderer/gl/FunctionsGL.h
@@ -106,6 +106,15 @@
     PFNGLTEXIMAGE3DPROC texImage3D;
     PFNGLTEXSUBIMAGE3DPROC texSubImage3D;
 
+    // 1.2 Extensions
+    PFNGLDELETEFENCESNVPROC deleteFencesNV;
+    PFNGLGENFENCESNVPROC genFencesNV;
+    PFNGLISFENCENVPROC isFenceNV;
+    PFNGLTESTFENCENVPROC testFenceNV;
+    PFNGLGETFENCEIVNVPROC getFenceivNV;
+    PFNGLFINISHFENCENVPROC finishFenceNV;
+    PFNGLSETFENCENVPROC setFenceNV;
+
     // 1.3
     PFNGLACTIVETEXTUREPROC activeTexture;
     PFNGLCOMPRESSEDTEXIMAGE1DPROC compressedTexImage1D;
diff --git a/src/libANGLE/renderer/gl/RendererGL.cpp b/src/libANGLE/renderer/gl/RendererGL.cpp
index 53f2e89..7e1b0b0 100644
--- a/src/libANGLE/renderer/gl/RendererGL.cpp
+++ b/src/libANGLE/renderer/gl/RendererGL.cpp
@@ -144,7 +144,7 @@
 
 FenceNVImpl *RendererGL::createFenceNV()
 {
-    return new FenceNVGL();
+    return new FenceNVGL(mFunctions);
 }
 
 FenceSyncImpl *RendererGL::createFenceSync()
diff --git a/src/libANGLE/renderer/gl/functionsgl_enums.h b/src/libANGLE/renderer/gl/functionsgl_enums.h
index 8e27af9..42e5f38 100644
--- a/src/libANGLE/renderer/gl/functionsgl_enums.h
+++ b/src/libANGLE/renderer/gl/functionsgl_enums.h
@@ -250,6 +250,11 @@
 #define GL_UNSIGNED_SHORT_5_6_5 0x8363
 #define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
 
+// 1.2 Extensions
+#define GL_ALL_COMPLETED_NV 0x84F2
+#define GL_FENCE_STATUS_NV 0x84F3
+#define GL_FENCE_CONDITION_NV 0x84F4
+
 // 1.3
 #define GL_ACTIVE_TEXTURE 0x84E0
 #define GL_CLAMP_TO_BORDER 0x812D
diff --git a/src/libANGLE/renderer/gl/functionsgl_typedefs.h b/src/libANGLE/renderer/gl/functionsgl_typedefs.h
index 713a35a..82fb5d8 100644
--- a/src/libANGLE/renderer/gl/functionsgl_typedefs.h
+++ b/src/libANGLE/renderer/gl/functionsgl_typedefs.h
@@ -125,6 +125,15 @@
 typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXIMAGE3DPROC)(GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *);
 typedef void (INTERNAL_GL_APIENTRY *PFNGLTEXSUBIMAGE3DPROC)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *);
 
+// 1.2 Extensions
+typedef void (INTERNAL_GL_APIENTRY *PFNGLDELETEFENCESNVPROC)(GLsizei, const GLuint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGENFENCESNVPROC)(GLsizei, GLuint *);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLISFENCENVPROC)(GLuint);
+typedef GLboolean (INTERNAL_GL_APIENTRY *PFNGLTESTFENCENVPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLGETFENCEIVNVPROC)(GLuint, GLenum, GLint *);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLFINISHFENCENVPROC)(GLuint);
+typedef void (INTERNAL_GL_APIENTRY *PFNGLSETFENCENVPROC)(GLuint, GLenum);
+
 // 1.3
 typedef void (INTERNAL_GL_APIENTRY *PFNGLACTIVETEXTUREPROC)(GLenum);
 typedef void (INTERNAL_GL_APIENTRY *PFNGLCOMPRESSEDTEXIMAGE1DPROC)(GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const GLvoid *);
diff --git a/src/libANGLE/renderer/gl/renderergl_utils.cpp b/src/libANGLE/renderer/gl/renderergl_utils.cpp
index 433aee2..f395ff4 100644
--- a/src/libANGLE/renderer/gl/renderergl_utils.cpp
+++ b/src/libANGLE/renderer/gl/renderergl_utils.cpp
@@ -155,6 +155,7 @@
     extensions->textureStorage = true;
     extensions->fboRenderMipmap = true;
     extensions->framebufferMultisample = caps->maxSamples > 0;
+    extensions->fence = std::find(functions->extensions.begin(), functions->extensions.end(), "GL_NV_fence") != functions->extensions.end();
 }
 
 }