New Buffers in OpenGL ES 3.0
Added new GLES 3.0 buffers:
- CopyReadBuffer
- CopyWriteBuffer
- PixelPackBuffer
- PixelUnpackBuffer
- UniformBuffer
Added related API function changes.
Note: I left TransformFeedback related buffer
changes out of this cl to avoid clashing with
other ongoing work and to keep this cl short.
Change-Id: Icb96f217e80a38f634c1735931dc37d53810d7f7
Reviewed-on: https://swiftshader-review.googlesource.com/2827
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
diff --git a/src/OpenGL/libGLESv2/Context.cpp b/src/OpenGL/libGLESv2/Context.cpp
index 923ee91..983914e 100644
--- a/src/OpenGL/libGLESv2/Context.cpp
+++ b/src/OpenGL/libGLESv2/Context.cpp
@@ -232,6 +232,11 @@
mState.arrayBuffer = NULL;
mState.elementArrayBuffer = NULL;
+ mState.copyReadBuffer = NULL;
+ mState.copyWriteBuffer = NULL;
+ mState.pixelPackBuffer = NULL;
+ mState.pixelUnpackBuffer = NULL;
+ mState.uniformBuffer = NULL;
mState.renderbuffer = NULL;
mState.vertexArray = NULL;
@@ -1059,6 +1064,41 @@
mState.elementArrayBuffer = getBuffer(buffer);
}
+void Context::bindCopyReadBuffer(GLuint buffer)
+{
+ mResourceManager->checkBufferAllocation(buffer);
+
+ mState.copyReadBuffer = getBuffer(buffer);
+}
+
+void Context::bindCopyWriteBuffer(GLuint buffer)
+{
+ mResourceManager->checkBufferAllocation(buffer);
+
+ mState.copyWriteBuffer = getBuffer(buffer);
+}
+
+void Context::bindPixelPackBuffer(GLuint buffer)
+{
+ mResourceManager->checkBufferAllocation(buffer);
+
+ mState.pixelPackBuffer = getBuffer(buffer);
+}
+
+void Context::bindPixelUnpackBuffer(GLuint buffer)
+{
+ mResourceManager->checkBufferAllocation(buffer);
+
+ mState.pixelUnpackBuffer = getBuffer(buffer);
+}
+
+void Context::bindUniformBuffer(GLuint buffer)
+{
+ mResourceManager->checkBufferAllocation(buffer);
+
+ mState.uniformBuffer = getBuffer(buffer);
+}
+
void Context::bindTexture2D(GLuint texture)
{
mResourceManager->checkTextureAllocation(texture, TEXTURE_2D);
@@ -1348,6 +1388,89 @@
return mState.elementArrayBuffer;
}
+Buffer *Context::getCopyReadBuffer()
+{
+ return mState.copyReadBuffer;
+}
+
+Buffer *Context::getCopyWriteBuffer()
+{
+ return mState.copyWriteBuffer;
+}
+
+Buffer *Context::getPixelPackBuffer()
+{
+ return mState.pixelPackBuffer;
+}
+
+Buffer *Context::getPixelUnpackBuffer()
+{
+ return mState.pixelUnpackBuffer;
+}
+
+Buffer *Context::getUniformBuffer()
+{
+ return mState.uniformBuffer;
+}
+
+bool Context::getBuffer(GLenum target, es2::Buffer **buffer)
+{
+ switch(target)
+ {
+ case GL_ARRAY_BUFFER:
+ *buffer = getArrayBuffer();
+ break;
+ case GL_ELEMENT_ARRAY_BUFFER:
+ *buffer = getElementArrayBuffer();
+ break;
+ case GL_COPY_READ_BUFFER:
+ if(clientVersion >= 3)
+ {
+ *buffer = getCopyReadBuffer();
+ break;
+ }
+ else return false;
+ case GL_COPY_WRITE_BUFFER:
+ if(clientVersion >= 3)
+ {
+ *buffer = getCopyWriteBuffer();
+ break;
+ }
+ else return false;
+ case GL_PIXEL_PACK_BUFFER:
+ if(clientVersion >= 3)
+ {
+ *buffer = getPixelPackBuffer();
+ break;
+ }
+ else return false;
+ case GL_PIXEL_UNPACK_BUFFER:
+ if(clientVersion >= 3)
+ {
+ *buffer = getPixelUnpackBuffer();
+ break;
+ }
+ else return false;
+ case GL_TRANSFORM_FEEDBACK_BUFFER:
+ if(clientVersion >= 3)
+ {
+ UNIMPLEMENTED();
+ return false;
+ }
+ else return false;
+ case GL_UNIFORM_BUFFER:
+ if(clientVersion >= 3)
+ {
+ *buffer = getUniformBuffer();
+ break;
+ }
+ else return false;
+ default:
+ return false;
+ }
+ return true;
+}
+
TransformFeedback *Context::getTransformFeedback()
{
return getTransformFeedback(mState.transformFeedback);
@@ -1725,12 +1848,24 @@
}
break;
case GL_COPY_READ_BUFFER_BINDING: // name, initially 0
- UNIMPLEMENTED();
- *params = 0;
+ if(clientVersion >= 3)
+ {
+ *params = mState.copyReadBuffer.name();
+ }
+ else
+ {
+ return false;
+ }
break;
case GL_COPY_WRITE_BUFFER_BINDING: // name, initially 0
- UNIMPLEMENTED();
- *params = 0;
+ if(clientVersion >= 3)
+ {
+ *params = mState.copyWriteBuffer.name();
+ }
+ else
+ {
+ return false;
+ }
break;
case GL_DRAW_BUFFER0: // symbolic constant, initial value is GL_BACK
UNIMPLEMENTED();
@@ -1888,12 +2023,24 @@
*params = 0;
break;
case GL_PIXEL_PACK_BUFFER_BINDING: // integer, initially 0
- UNIMPLEMENTED();
- *params = 0;
+ if(clientVersion >= 3)
+ {
+ *params = mState.pixelPackBuffer.name();
+ }
+ else
+ {
+ return false;
+ }
break;
case GL_PIXEL_UNPACK_BUFFER_BINDING: // integer, initially 0
- UNIMPLEMENTED();
- *params = 0;
+ if(clientVersion >= 3)
+ {
+ *params = mState.pixelUnpackBuffer.name();
+ }
+ else
+ {
+ return false;
+ }
break;
case GL_PROGRAM_BINARY_FORMATS: // integer[GL_NUM_PROGRAM_BINARY_FORMATS]
UNIMPLEMENTED();
@@ -1908,8 +2055,14 @@
*params = 0;
break;
case GL_UNIFORM_BUFFER_BINDING: // name, initially 0
- UNIMPLEMENTED();
- *params = 0;
+ if(clientVersion >= 3)
+ {
+ *params = mState.uniformBuffer.name();
+ }
+ else
+ {
+ return false;
+ }
break;
case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: // integer, defaults to 1
UNIMPLEMENTED();
diff --git a/src/OpenGL/libGLESv2/Context.h b/src/OpenGL/libGLESv2/Context.h
index 56031f6..4da5a75 100644
--- a/src/OpenGL/libGLESv2/Context.h
+++ b/src/OpenGL/libGLESv2/Context.h
@@ -325,6 +325,12 @@
unsigned int activeSampler; // Active texture unit selector - GL_TEXTURE0
gl::BindingPointer<Buffer> arrayBuffer;
gl::BindingPointer<Buffer> elementArrayBuffer;
+ gl::BindingPointer<Buffer> copyReadBuffer;
+ gl::BindingPointer<Buffer> copyWriteBuffer;
+ gl::BindingPointer<Buffer> pixelPackBuffer;
+ gl::BindingPointer<Buffer> pixelUnpackBuffer;
+ gl::BindingPointer<Buffer> uniformBuffer;
+
GLuint readFramebuffer;
GLuint drawFramebuffer;
gl::BindingPointer<Renderbuffer> renderbuffer;
@@ -479,6 +485,11 @@
void bindArrayBuffer(GLuint buffer);
void bindElementArrayBuffer(GLuint buffer);
+ void bindCopyReadBuffer(GLuint buffer);
+ void bindCopyWriteBuffer(GLuint buffer);
+ void bindPixelPackBuffer(GLuint buffer);
+ void bindPixelUnpackBuffer(GLuint buffer);
+ void bindUniformBuffer(GLuint buffer);
void bindTexture2D(GLuint texture);
void bindTextureCubeMap(GLuint texture);
void bindTextureExternal(GLuint texture);
@@ -517,6 +528,12 @@
Buffer *getArrayBuffer();
Buffer *getElementArrayBuffer();
+ Buffer *getCopyReadBuffer();
+ Buffer *getCopyWriteBuffer();
+ Buffer *getPixelPackBuffer();
+ Buffer *getPixelUnpackBuffer();
+ Buffer *getUniformBuffer();
+ bool getBuffer(GLenum target, es2::Buffer **buffer);
Program *getCurrentProgram();
Texture2D *getTexture2D();
Texture3D *getTexture3D();
diff --git a/src/OpenGL/libGLESv2/libGLESv2.cpp b/src/OpenGL/libGLESv2/libGLESv2.cpp
index 4b025ef..13f6f6d 100644
--- a/src/OpenGL/libGLESv2/libGLESv2.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv2.cpp
@@ -418,6 +418,8 @@
if(context)
{
+ egl::GLint clientVersion = egl::getClientVersion();
+
switch(target)
{
case GL_ARRAY_BUFFER:
@@ -426,6 +428,48 @@
case GL_ELEMENT_ARRAY_BUFFER:
context->bindElementArrayBuffer(buffer);
return;
+ case GL_COPY_READ_BUFFER:
+ if(clientVersion >= 3)
+ {
+ context->bindCopyReadBuffer(buffer);
+ return;
+ }
+ else return error(GL_INVALID_ENUM);
+ case GL_COPY_WRITE_BUFFER:
+ if(clientVersion >= 3)
+ {
+ context->bindCopyWriteBuffer(buffer);
+ return;
+ }
+ else return error(GL_INVALID_ENUM);
+ case GL_PIXEL_PACK_BUFFER:
+ if(clientVersion >= 3)
+ {
+ context->bindPixelPackBuffer(buffer);
+ return;
+ }
+ else return error(GL_INVALID_ENUM);
+ case GL_PIXEL_UNPACK_BUFFER:
+ if(clientVersion >= 3)
+ {
+ context->bindPixelUnpackBuffer(buffer);
+ return;
+ }
+ else return error(GL_INVALID_ENUM);
+ case GL_TRANSFORM_FEEDBACK_BUFFER:
+ if(clientVersion >= 3)
+ {
+ UNIMPLEMENTED();
+ return;
+ }
+ else return error(GL_INVALID_ENUM);
+ case GL_UNIFORM_BUFFER:
+ if(clientVersion >= 3)
+ {
+ context->bindUniformBuffer(buffer);
+ return;
+ }
+ else return error(GL_INVALID_ENUM);
default:
return error(GL_INVALID_ENUM);
}
@@ -729,16 +773,8 @@
if(context)
{
es2::Buffer *buffer;
-
- switch(target)
+ if(!context->getBuffer(target, &buffer))
{
- case GL_ARRAY_BUFFER:
- buffer = context->getArrayBuffer();
- break;
- case GL_ELEMENT_ARRAY_BUFFER:
- buffer = context->getElementArrayBuffer();
- break;
- default:
return error(GL_INVALID_ENUM);
}
@@ -775,16 +811,8 @@
if(context)
{
es2::Buffer *buffer;
-
- switch(target)
+ if(!context->getBuffer(target, &buffer))
{
- case GL_ARRAY_BUFFER:
- buffer = context->getArrayBuffer();
- break;
- case GL_ELEMENT_ARRAY_BUFFER:
- buffer = context->getElementArrayBuffer();
- break;
- default:
return error(GL_INVALID_ENUM);
}
@@ -2445,16 +2473,8 @@
if(context)
{
es2::Buffer *buffer;
-
- switch(target)
+ if(!context->getBuffer(target, &buffer))
{
- case GL_ARRAY_BUFFER:
- buffer = context->getArrayBuffer();
- break;
- case GL_ELEMENT_ARRAY_BUFFER:
- buffer = context->getElementArrayBuffer();
- break;
- default:
return error(GL_INVALID_ENUM);
}
diff --git a/src/OpenGL/libGLESv2/libGLESv3.cpp b/src/OpenGL/libGLESv2/libGLESv3.cpp
index 405645f..469bbe4 100644
--- a/src/OpenGL/libGLESv2/libGLESv3.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv3.cpp
@@ -991,8 +991,26 @@
{
TRACE("(GLenum target = 0x%X)", target);
- UNIMPLEMENTED();
- return GL_FALSE;
+ es2::Context *context = es2::getContext();
+
+ if(context)
+ {
+ es2::Buffer *buffer = nullptr;
+ if(!context->getBuffer(target, &buffer))
+ {
+ return error(GL_INVALID_ENUM, GL_TRUE);
+ }
+
+ if(!buffer)
+ {
+ // A null buffer means that "0" is bound to the requested buffer target
+ return error(GL_INVALID_OPERATION, GL_TRUE);
+ }
+
+ return buffer->unmap() ? GL_TRUE : GL_FALSE;
+ }
+
+ return GL_TRUE;
}
void GL_APIENTRY glGetBufferPointerv(GLenum target, GLenum pname, void **params)
@@ -1000,17 +1018,29 @@
TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = 0x%0.8p)",
target, pname, params);
- if(!ValidateBufferTarget(target))
- {
- return error(GL_INVALID_ENUM);
- }
-
if(pname != GL_BUFFER_MAP_POINTER)
{
return error(GL_INVALID_ENUM);
}
- UNIMPLEMENTED();
+ es2::Context *context = es2::getContext();
+
+ if(context)
+ {
+ es2::Buffer *buffer = nullptr;
+ if(!context->getBuffer(target, &buffer))
+ {
+ return error(GL_INVALID_ENUM);
+ }
+
+ if(!buffer)
+ {
+ // A null buffer means that "0" is bound to the requested buffer target
+ return error(GL_INVALID_OPERATION);
+ }
+
+ *params = buffer->isMapped() ? (void*)(((const char*)buffer->data()) + buffer->offset()) : nullptr;
+ }
}
void GL_APIENTRY glDrawBuffers(GLsizei n, const GLenum *bufs)
@@ -1397,12 +1427,27 @@
TRACE("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = %X)",
target, offset, length, access);
- GLint bufferSize;
- glGetBufferParameteriv(target, GL_BUFFER_SIZE, &bufferSize);
- if((offset < 0) || (length<0) || ((offset + length) > bufferSize))
+ es2::Context *context = es2::getContext();
+
+ if(context)
{
- error(GL_INVALID_VALUE);
- }
+ es2::Buffer *buffer = nullptr;
+ if(!context->getBuffer(target, &buffer))
+ {
+ return error(GL_INVALID_ENUM, nullptr);
+ }
+
+ if(!buffer)
+ {
+ // A null buffer means that "0" is bound to the requested buffer target
+ return error(GL_INVALID_OPERATION, nullptr);
+ }
+
+ GLint bufferSize = buffer->size();
+ if((offset < 0) || (length < 0) || ((offset + length) > bufferSize))
+ {
+ error(GL_INVALID_VALUE);
+ }
if((access & ~(GL_MAP_READ_BIT |
GL_MAP_WRITE_BIT |
@@ -1414,7 +1459,9 @@
error(GL_INVALID_VALUE);
}
- UNIMPLEMENTED();
+ return buffer->mapRange(offset, length, access);
+ }
+
return nullptr;
}
@@ -1423,17 +1470,30 @@
TRACE("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)",
target, offset, length);
- if(!ValidateBufferTarget(target))
- {
- return error(GL_INVALID_ENUM);
- }
+ es2::Context *context = es2::getContext();
- if((offset < 0) || (length<0)) // FIXME: also check if offset + length exceeds the size of the mapping
+ if(context)
{
- error(GL_INVALID_VALUE);
- }
+ es2::Buffer *buffer = nullptr;
+ if(!context->getBuffer(target, &buffer))
+ {
+ return error(GL_INVALID_ENUM);
+ }
- UNIMPLEMENTED();
+ if(!buffer)
+ {
+ // A null buffer means that "0" is bound to the requested buffer target
+ return error(GL_INVALID_OPERATION);
+ }
+
+ GLint bufferSize = buffer->size();
+ if((offset < 0) || (length < 0) || ((offset + length) > bufferSize))
+ {
+ error(GL_INVALID_VALUE);
+ }
+
+ buffer->flushMappedRange(offset, length);
+ }
}
void GL_APIENTRY glBindVertexArray(GLuint array)
@@ -2368,42 +2428,37 @@
TRACE("(GLenum readTarget = 0x%X, GLenum writeTarget = 0x%X, GLintptr readOffset = %d, GLintptr writeOffset = %d, GLsizeiptr size = %d)",
readTarget, writeTarget, readOffset, writeOffset, size);
- switch(readTarget)
- {
- case GL_ARRAY_BUFFER:
- case GL_COPY_READ_BUFFER:
- case GL_COPY_WRITE_BUFFER:
- case GL_ELEMENT_ARRAY_BUFFER:
- case GL_PIXEL_PACK_BUFFER:
- case GL_PIXEL_UNPACK_BUFFER:
- case GL_TRANSFORM_FEEDBACK_BUFFER:
- case GL_UNIFORM_BUFFER:
- break;
- default:
- return error(GL_INVALID_ENUM);
- }
-
- switch(writeTarget)
- {
- case GL_ARRAY_BUFFER:
- case GL_COPY_READ_BUFFER:
- case GL_COPY_WRITE_BUFFER:
- case GL_ELEMENT_ARRAY_BUFFER:
- case GL_PIXEL_PACK_BUFFER:
- case GL_PIXEL_UNPACK_BUFFER:
- case GL_TRANSFORM_FEEDBACK_BUFFER:
- case GL_UNIFORM_BUFFER:
- break;
- default:
- return error(GL_INVALID_ENUM);
- }
-
if(readOffset < 0 || writeOffset < 0 || size < 0)
{
return error(GL_INVALID_VALUE);
}
- UNIMPLEMENTED();
+ es2::Context *context = es2::getContext();
+
+ if(context)
+ {
+ es2::Buffer *readBuffer = nullptr;
+ if(!context->getBuffer(readTarget, &readBuffer))
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ if((readOffset + size) > readBuffer->size())
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ es2::Buffer *writeBuffer = nullptr;
+ if(!context->getBuffer(writeTarget, &writeBuffer))
+ {
+ return error(GL_INVALID_ENUM);
+ }
+ if((writeOffset + size) > writeBuffer->size())
+ {
+ return error(GL_INVALID_VALUE);
+ }
+
+ writeBuffer->bufferSubData(((char*)readBuffer->data()) + readOffset, size, writeOffset);
+ }
}
void GL_APIENTRY glGetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices)
@@ -2731,7 +2786,73 @@
void GL_APIENTRY glGetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params)
{
TRACE("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint64 *params = 0x%0.8p)", target, pname, params);
- UNIMPLEMENTED();
+
+ es2::Context *context = es2::getContext();
+
+ if(context)
+ {
+ es2::Buffer *buffer = nullptr;
+
+ switch(target)
+ {
+ case GL_ARRAY_BUFFER:
+ buffer = context->getArrayBuffer();
+ break;
+ case GL_ELEMENT_ARRAY_BUFFER:
+ buffer = context->getElementArrayBuffer();
+ break;
+ case GL_COPY_READ_BUFFER:
+ buffer = context->getCopyReadBuffer();
+ break;
+ case GL_COPY_WRITE_BUFFER:
+ buffer = context->getCopyWriteBuffer();
+ break;
+ case GL_PIXEL_PACK_BUFFER:
+ buffer = context->getPixelPackBuffer();
+ break;
+ case GL_PIXEL_UNPACK_BUFFER:
+ buffer = context->getPixelUnpackBuffer();
+ break;
+ case GL_TRANSFORM_FEEDBACK_BUFFER:
+ UNIMPLEMENTED();
+ break;
+ case GL_UNIFORM_BUFFER:
+ buffer = context->getUniformBuffer();
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+
+ if(!buffer)
+ {
+ // A null buffer means that "0" is bound to the requested buffer target
+ return error(GL_INVALID_OPERATION);
+ }
+
+ switch(pname)
+ {
+ case GL_BUFFER_USAGE:
+ *params = buffer->usage();
+ break;
+ case GL_BUFFER_SIZE:
+ *params = buffer->size();
+ break;
+ case GL_BUFFER_ACCESS_FLAGS:
+ *params = buffer->access();
+ break;
+ case GL_BUFFER_MAPPED:
+ *params = buffer->isMapped();
+ break;
+ case GL_BUFFER_MAP_LENGTH:
+ *params = buffer->length();
+ break;
+ case GL_BUFFER_MAP_OFFSET:
+ *params = buffer->offset();
+ break;
+ default:
+ return error(GL_INVALID_ENUM);
+ }
+ }
}
void GL_APIENTRY glGenSamplers(GLsizei count, GLuint *samplers)