Split Buffer::map into map and mapRange to match the API.

BUG=angleproject:681

Change-Id: Ia4bf2b81134a922265ca762f33ac85d9ddbf1a7c
Reviewed-on: https://chromium-review.googlesource.com/261890
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Brandon Jones <bajones@chromium.org>
Tested-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/Buffer.cpp b/src/libANGLE/Buffer.cpp
index f394a6b..621d8d2 100644
--- a/src/libANGLE/Buffer.cpp
+++ b/src/libANGLE/Buffer.cpp
@@ -21,6 +21,7 @@
       mUsage(GL_DYNAMIC_DRAW),
       mSize(0),
       mAccessFlags(0),
+      mAccess(GL_WRITE_ONLY_OES),
       mMapped(GL_FALSE),
       mMapPointer(NULL),
       mMapOffset(0),
@@ -74,12 +75,36 @@
     return error;
 }
 
+Error Buffer::map(GLenum access)
+{
+    ASSERT(!mMapped);
+
+    Error error = mBuffer->map(access, &mMapPointer);
+    if (error.isError())
+    {
+        mMapPointer = NULL;
+        return error;
+    }
+
+    ASSERT(access == GL_WRITE_ONLY_OES);
+
+    mMapped = GL_TRUE;
+    mMapOffset = 0;
+    mMapLength = mSize;
+    mAccess = access;
+    mAccessFlags = GL_MAP_WRITE_BIT;
+
+    mIndexRangeCache.invalidateRange(0, mMapLength);
+
+    return error;
+}
+
 Error Buffer::mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access)
 {
     ASSERT(!mMapped);
     ASSERT(offset + length <= mSize);
 
-    Error error = mBuffer->map(offset, length, access, &mMapPointer);
+    Error error = mBuffer->mapRange(offset, length, access, &mMapPointer);
     if (error.isError())
     {
         mMapPointer = NULL;
@@ -89,7 +114,13 @@
     mMapped = GL_TRUE;
     mMapOffset = static_cast<GLint64>(offset);
     mMapLength = static_cast<GLint64>(length);
-    mAccessFlags = static_cast<GLint>(access);
+    mAccess = GL_WRITE_ONLY_OES;
+    mAccessFlags = access;
+
+    // The OES_mapbuffer extension states that GL_WRITE_ONLY_OES is the only valid
+    // value for GL_BUFFER_ACCESS_OES because it was written against ES2.  Since there is
+    // no update for ES3 and the GL_READ_ONLY and GL_READ_WRITE enums don't exist for ES,
+    // we cannot properly set GL_BUFFER_ACCESS_OES when glMapBufferRange is called.
 
     if ((access & GL_MAP_WRITE_BIT) > 0)
     {
@@ -99,13 +130,14 @@
     return error;
 }
 
-Error Buffer::unmap()
+Error Buffer::unmap(GLboolean *result)
 {
     ASSERT(mMapped);
 
-    Error error = mBuffer->unmap();
+    Error error = mBuffer->unmap(result);
     if (error.isError())
     {
+        *result = GL_FALSE;
         return error;
     }
 
@@ -113,6 +145,7 @@
     mMapPointer = NULL;
     mMapOffset = 0;
     mMapLength = 0;
+    mAccess = GL_WRITE_ONLY_OES;
     mAccessFlags = 0;
 
     return error;
diff --git a/src/libANGLE/Buffer.h b/src/libANGLE/Buffer.h
index 6793028..029aff8 100644
--- a/src/libANGLE/Buffer.h
+++ b/src/libANGLE/Buffer.h
@@ -35,11 +35,13 @@
     Error bufferData(const void *data, GLsizeiptr size, GLenum usage);
     Error bufferSubData(const void *data, GLsizeiptr size, GLintptr offset);
     Error copyBufferSubData(Buffer* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size);
+    Error map(GLenum access);
     Error mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access);
-    Error unmap();
+    Error unmap(GLboolean *result);
 
     GLenum getUsage() const { return mUsage; }
-    GLint getAccessFlags() const {  return mAccessFlags; }
+    GLbitfield getAccessFlags() const { return mAccessFlags; }
+    GLenum getAccess() const { return mAccess; }
     GLboolean isMapped() const { return mMapped; }
     GLvoid *getMapPointer() const { return mMapPointer; }
     GLint64 getMapOffset() const { return mMapOffset; }
@@ -56,7 +58,8 @@
 
     GLenum mUsage;
     GLint64 mSize;
-    GLint mAccessFlags;
+    GLbitfield mAccessFlags;
+    GLenum mAccess;
     GLboolean mMapped;
     GLvoid *mMapPointer;
     GLint64 mMapOffset;
diff --git a/src/libANGLE/renderer/BufferImpl.h b/src/libANGLE/renderer/BufferImpl.h
index 9bc5eaf..755e793 100644
--- a/src/libANGLE/renderer/BufferImpl.h
+++ b/src/libANGLE/renderer/BufferImpl.h
@@ -25,8 +25,9 @@
     virtual gl::Error setData(const void* data, size_t size, GLenum usage) = 0;
     virtual gl::Error setSubData(const void* data, size_t size, size_t offset) = 0;
     virtual gl::Error copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) = 0;
-    virtual gl::Error map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) = 0;
-    virtual gl::Error unmap() = 0;
+    virtual gl::Error map(GLenum access, GLvoid **mapPtr) = 0;
+    virtual gl::Error mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) = 0;
+    virtual gl::Error unmap(GLboolean *result) = 0;
 
     // This method may not have a corresponding GL-backed function. It is necessary
     // for validation, for certain indexed draw calls.
diff --git a/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp b/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
index 575ee15..72cf277 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
@@ -356,7 +356,15 @@
     return gl::Error(GL_NO_ERROR);
 }
 
-gl::Error Buffer11::map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr)
+gl::Error Buffer11::map(GLenum access, GLvoid **mapPtr)
+{
+    // GL_OES_mapbuffer uses an enum instead of a bitfield for it's access, convert to a bitfield
+    // and call mapRange.
+    ASSERT(access == GL_WRITE_ONLY_OES);
+    return mapRange(0, mSize, GL_MAP_WRITE_BIT, mapPtr);
+}
+
+gl::Error Buffer11::mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr)
 {
     ASSERT(!mMappedStorage);
 
@@ -396,11 +404,15 @@
     return gl::Error(GL_NO_ERROR);
 }
 
-gl::Error Buffer11::unmap()
+gl::Error Buffer11::unmap(GLboolean *result)
 {
     ASSERT(mMappedStorage);
     mMappedStorage->unmap();
     mMappedStorage = NULL;
+
+    // TODO: detect if we had corruption. if so, return false.
+    *result = GL_TRUE;
+
     return gl::Error(GL_NO_ERROR);
 }
 
diff --git a/src/libANGLE/renderer/d3d/d3d11/Buffer11.h b/src/libANGLE/renderer/d3d/d3d11/Buffer11.h
index 5591458..5ccabf3 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Buffer11.h
+++ b/src/libANGLE/renderer/d3d/d3d11/Buffer11.h
@@ -64,8 +64,9 @@
     gl::Error getData(const uint8_t **outData) override;
     virtual gl::Error setSubData(const void* data, size_t size, size_t offset);
     virtual gl::Error copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size);
-    virtual gl::Error map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr);
-    virtual gl::Error unmap();
+    virtual gl::Error map(GLenum access, GLvoid **mapPtr);
+    virtual gl::Error mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr);
+    virtual gl::Error unmap(GLboolean *result);
     virtual void markTransformFeedbackUsage();
 
   private:
diff --git a/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp b/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp
index 199c404..c067aa1 100644
--- a/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp
+++ b/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp
@@ -90,13 +90,19 @@
 }
 
 // We do not support buffer mapping in D3D9
-gl::Error Buffer9::map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr)
+gl::Error Buffer9::map(GLenum access, GLvoid **mapPtr)
 {
     UNREACHABLE();
     return gl::Error(GL_INVALID_OPERATION);
 }
 
-gl::Error Buffer9::unmap()
+gl::Error Buffer9::mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr)
+{
+    UNREACHABLE();
+    return gl::Error(GL_INVALID_OPERATION);
+}
+
+gl::Error Buffer9::unmap(GLboolean *result)
 {
     UNREACHABLE();
     return gl::Error(GL_INVALID_OPERATION);
diff --git a/src/libANGLE/renderer/d3d/d3d9/Buffer9.h b/src/libANGLE/renderer/d3d/d3d9/Buffer9.h
index dc1aff6..f40b660 100644
--- a/src/libANGLE/renderer/d3d/d3d9/Buffer9.h
+++ b/src/libANGLE/renderer/d3d/d3d9/Buffer9.h
@@ -32,8 +32,9 @@
     gl::Error getData(const uint8_t **outData) override;
     virtual gl::Error setSubData(const void* data, size_t size, size_t offset);
     virtual gl::Error copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size);
-    virtual gl::Error map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr);
-    virtual gl::Error unmap();
+    virtual gl::Error map(GLenum access, GLvoid **mapPtr);
+    virtual gl::Error mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr);
+    virtual gl::Error unmap(GLboolean *result);
     virtual void markTransformFeedbackUsage();
 
   private:
diff --git a/src/libANGLE/renderer/gl/BufferGL.cpp b/src/libANGLE/renderer/gl/BufferGL.cpp
index c63a9e7..1ce91de 100644
--- a/src/libANGLE/renderer/gl/BufferGL.cpp
+++ b/src/libANGLE/renderer/gl/BufferGL.cpp
@@ -73,20 +73,26 @@
     return gl::Error(GL_NO_ERROR);
 }
 
-gl::Error BufferGL::map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr)
+gl::Error BufferGL::map(GLenum access, GLvoid **mapPtr)
 {
-    // TODO: look into splitting this into two functions, glMapBuffer is available in 1.5, but
-    // glMapBufferRange requires 3.0
+    mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
+    *mapPtr = mFunctions->mapBuffer(DestBufferOperationTarget, access);
+    return gl::Error(GL_NO_ERROR);
+}
 
+gl::Error BufferGL::mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr)
+{
     mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
     *mapPtr = mFunctions->mapBufferRange(DestBufferOperationTarget, offset, length, access);
     return gl::Error(GL_NO_ERROR);
 }
 
-gl::Error BufferGL::unmap()
+gl::Error BufferGL::unmap(GLboolean *result)
 {
+    ASSERT(*result);
+
     mStateManager->bindBuffer(DestBufferOperationTarget, mBufferID);
-    mFunctions->unmapBuffer(DestBufferOperationTarget);
+    *result = mFunctions->unmapBuffer(DestBufferOperationTarget);
     return gl::Error(GL_NO_ERROR);
 }
 
diff --git a/src/libANGLE/renderer/gl/BufferGL.h b/src/libANGLE/renderer/gl/BufferGL.h
index 398c748..2fe7525 100644
--- a/src/libANGLE/renderer/gl/BufferGL.h
+++ b/src/libANGLE/renderer/gl/BufferGL.h
@@ -26,8 +26,9 @@
     gl::Error setData(const void* data, size_t size, GLenum usage) override;
     gl::Error setSubData(const void* data, size_t size, size_t offset) override;
     gl::Error copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) override;
-    gl::Error map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) override;
-    gl::Error unmap() override;
+    gl::Error map(GLenum access, GLvoid **mapPtr) override;
+    gl::Error mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) override;
+    gl::Error unmap(GLboolean *result) override;
 
     // This method may not have a corresponding GL-backed function. It is necessary
     // for validation, for certain indexed draw calls.
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp
index 2e2ca84..7dea88e 100644
--- a/src/libANGLE/validationES.cpp
+++ b/src/libANGLE/validationES.cpp
@@ -129,19 +129,27 @@
 
 bool ValidBufferParameter(const Context *context, GLenum pname)
 {
+    const Extensions &extensions = context->getExtensions();
+
     switch (pname)
     {
       case GL_BUFFER_USAGE:
       case GL_BUFFER_SIZE:
         return true;
 
+      case GL_BUFFER_ACCESS_OES:
+        return extensions.mapBuffer;
+
+      case GL_BUFFER_MAPPED:
+        static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
+        return (context->getClientVersion() >= 3) || extensions.mapBuffer || extensions.mapBufferRange;
+
       // GL_BUFFER_MAP_POINTER is a special case, and may only be
       // queried with GetBufferPointerv
       case GL_BUFFER_ACCESS_FLAGS:
-      case GL_BUFFER_MAPPED:
       case GL_BUFFER_MAP_OFFSET:
       case GL_BUFFER_MAP_LENGTH:
-        return (context->getClientVersion() >= 3);
+        return (context->getClientVersion() >= 3) || extensions.mapBufferRange;
 
       default:
         return false;
diff --git a/src/libGLESv2/entry_points_gles_2_0.cpp b/src/libGLESv2/entry_points_gles_2_0.cpp
index 6d3089b..8c45d55 100644
--- a/src/libGLESv2/entry_points_gles_2_0.cpp
+++ b/src/libGLESv2/entry_points_gles_2_0.cpp
@@ -1784,7 +1784,11 @@
           case GL_BUFFER_ACCESS_FLAGS:
             *params = buffer->getAccessFlags();
             break;
+          case GL_BUFFER_ACCESS_OES:
+            *params = buffer->getAccess();
+            break;
           case GL_BUFFER_MAPPED:
+            static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
             *params = static_cast<GLint>(buffer->isMapped());
             break;
           case GL_BUFFER_MAP_OFFSET:
diff --git a/src/libGLESv2/entry_points_gles_2_0_ext.cpp b/src/libGLESv2/entry_points_gles_2_0_ext.cpp
index 8be6ae7..6f85b2f 100644
--- a/src/libGLESv2/entry_points_gles_2_0_ext.cpp
+++ b/src/libGLESv2/entry_points_gles_2_0_ext.cpp
@@ -863,7 +863,7 @@
             return NULL;
         }
 
-        Error error = buffer->mapRange(0, buffer->getSize(), GL_MAP_WRITE_BIT);
+        Error error = buffer->map(access);
         if (error.isError())
         {
             context->recordError(error);
@@ -897,16 +897,15 @@
             return GL_FALSE;
         }
 
-        // TODO: detect if we had corruption. if so, throw an error and return false.
-
-        Error error = buffer->unmap();
+        GLboolean result;
+        Error error = buffer->unmap(&result);
         if (error.isError())
         {
             context->recordError(error);
             return GL_FALSE;
         }
 
-        return GL_TRUE;
+        return result;
     }
 
     return GL_FALSE;