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)