From fbdbd4aa01dc33f0a1424bfa50ce7d032fb84658 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 4 Jul 2013 17:54:23 +0200 Subject: [PATCH] Implemented CHROMIUM_map_sub for Buffer. --- src/Buffer.cpp | 33 ++++++++++++++++++++++++++ src/Buffer.h | 50 ++++++++++++++++++++++++++++++++++----- src/OpenGL.h | 4 ++++ src/Test/BufferGLTest.cpp | 29 +++++++++++++++++++++++ 4 files changed, 110 insertions(+), 6 deletions(-) diff --git a/src/Buffer.cpp b/src/Buffer.cpp index 69bddf75c..7957e2461 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -78,6 +78,14 @@ void Buffer::initializeContextBasedFunctionality(Context* context) { #endif } +Buffer::Buffer(Buffer::Target targetHint): _targetHint(targetHint) + #ifdef CORRADE_TARGET_NACL + , _mappedBuffer(nullptr) + #endif +{ + glGenBuffers(1, &_id); +} + Buffer::~Buffer() { GLuint* bindings = Context::current()->state()->buffer->bindings; @@ -127,6 +135,31 @@ Int Buffer::size() { return size; } +#ifdef MAGNUM_TARGET_GLES2 +void* Buffer::mapSub(const GLintptr offset, const GLsizeiptr length, const MapAccess access) { + /** @todo Enable also in Emscripten (?) when extension wrangler is available */ + #ifdef CORRADE_TARGET_NACL + CORRADE_ASSERT(!_mappedBuffer, "Buffer::mapSub(): the buffer is already mapped", nullptr); + return _mappedBuffer = glMapBufferSubDataCHROMIUM(static_cast(bindInternal(_targetHint)), offset, length, GLenum(access)); + #else + CORRADE_INTERNAL_ASSERT(false); + static_cast(offset); + static_cast(length); + static_cast(access); + #endif +} + +void Buffer::unmapSub() { + #ifdef CORRADE_TARGET_NACL + CORRADE_ASSERT(_mappedBuffer, "Buffer::unmapSub(): the buffer is not mapped", ); + glUnmapBufferSubDataCHROMIUM(_mappedBuffer); + _mappedBuffer = nullptr; + #else + CORRADE_INTERNAL_ASSERT(false); + #endif +} +#endif + #ifndef MAGNUM_TARGET_GLES2 void Buffer::copyImplementationDefault(Buffer* read, Buffer* write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) { glCopyBufferSubData(static_cast(read->bindInternal(Target::CopyRead)), static_cast(write->bindInternal(Target::CopyWrite)), readOffset, writeOffset, size); diff --git a/src/Buffer.h b/src/Buffer.h index 5f16b13a1..7cbc99ae2 100644 --- a/src/Buffer.h +++ b/src/Buffer.h @@ -324,9 +324,10 @@ class MAGNUM_EXPORT Buffer { * * @deprecated Prefer to use @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)" * instead, as it has more complete set of features. - * @see map(MapAccess) - * @requires_es_extension %Extension @es_extension{OES,mapbuffer} in - * OpenGL ES 2.0, use @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)" + * @see map(MapAccess), mapSub() + * @requires_es_extension %Extension @es_extension{OES,mapbuffer} or + * @es_extension{CHROMIUM,map_sub} in OpenGL ES 2.0, use + * @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)" * in OpenGL ES 3.0 instead. */ enum class MapAccess: GLenum { @@ -471,9 +472,7 @@ class MAGNUM_EXPORT Buffer { * Generates new OpenGL buffer. * @see @fn_gl{GenBuffers} */ - explicit Buffer(Target targetHint = Target::Array): _targetHint(targetHint) { - glGenBuffers(1, &_id); - } + explicit Buffer(Target targetHint = Target::Array); /** * @brief Destructor @@ -728,6 +727,27 @@ class MAGNUM_EXPORT Buffer { } #endif + #if defined(MAGNUM_TARGET_GLES2) || defined(DOXYGEN_GENERATING_OUTPUT) + /** + * @brief Map portion of buffer to client memory + * @param offset Offset into the buffer + * @param length Length of the mapped memory + * @param access Access + * @return Pointer to buffer data + * + * If the buffer is not already bound somewhere, it is bound to hinted + * target before the operation. + * @deprecated Prefer to use @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)" + * instead, as it has more complete set of features. + * @see unmapSub(), setTargetHint(), @fn_gl_extension{MapBufferSubData,CHROMIUM,map_sub} + * @requires_gles20 Not available in ES 3.0 or desktop OpenGL. Use + * @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)" + * instead. + * @requires_es_extension %Extension @es_extension{CHROMIUM,map_sub} + */ + void* mapSub(GLintptr offset, GLsizeiptr length, MapAccess access); + #endif + /** * @brief Map buffer to client memory * @param offset Offset into the buffer @@ -789,6 +809,21 @@ class MAGNUM_EXPORT Buffer { return (this->*unmapImplementation)(); } + #if defined(MAGNUM_TARGET_GLES2) || defined(DOXYGEN_GENERATING_OUTPUT) + /** + * @brief Unmap portion of buffer + * + * Unmaps portion of buffer previously mapped with mapSub(), + * invalidating the pointer returned by the function. + * @see @fn_gl_extension{UnmapBufferSubData,CHROMIUM,map_sub} + * @requires_gles20 Not available in ES 3.0 or desktop OpenGL. Use + * @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)" + * instead. + * @requires_es_extension %Extension @es_extension{CHROMIUM,map_sub} + */ + void unmapSub(); + #endif + private: static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context* context); @@ -878,6 +913,9 @@ class MAGNUM_EXPORT Buffer { GLuint _id; Target _targetHint; + #ifdef CORRADE_TARGET_NACL + void* _mappedBuffer; + #endif }; CORRADE_ENUMSET_OPERATORS(Buffer::MapFlags) diff --git a/src/OpenGL.h b/src/OpenGL.h index a63f743d2..8e8645a57 100644 --- a/src/OpenGL.h +++ b/src/OpenGL.h @@ -40,6 +40,10 @@ to NaCl's gl2ext.h we are including our own to prevent undeclared symbol errors with some recent extensions. */ #elif defined(CORRADE_TARGET_NACL) + +/* Enable function prototypes (the supported ones shouldn't fail at link time) */ +#define GL_GLEXT_PROTOTYPES + #include #include #undef __gl2ext_h_ diff --git a/src/Test/BufferGLTest.cpp b/src/Test/BufferGLTest.cpp index a87a06da7..fc21ff125 100644 --- a/src/Test/BufferGLTest.cpp +++ b/src/Test/BufferGLTest.cpp @@ -38,6 +38,9 @@ class BufferGLTest: public AbstractOpenGLTester { void construct(); void data(); void map(); + #ifdef MAGNUM_TARGET_GLES2 + void mapSub(); + #endif void mapRange(); void mapRangeExplicitFlush(); #ifndef MAGNUM_TARGET_GLES2 @@ -52,6 +55,9 @@ BufferGLTest::BufferGLTest() { addTests({&BufferGLTest::construct, &BufferGLTest::data, &BufferGLTest::map, + #ifdef MAGNUM_TARGET_GLES2 + &BufferGLTest::mapSub, + #endif &BufferGLTest::mapRange, &BufferGLTest::mapRangeExplicitFlush, #ifndef MAGNUM_TARGET_GLES2 @@ -147,6 +153,29 @@ void BufferGLTest::map() { } #endif +#ifdef MAGNUM_TARGET_GLES2 +void BufferGLTest::mapSub() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::CHROMIUM::map_sub::string() + std::string(" is not supported")); + + Buffer buffer; + + constexpr char data[] = {2, 7, 5, 13, 25}; + buffer.setData(data, Buffer::Usage::StaticDraw); + + char* contents = reinterpret_cast(buffer.mapSub(1, 4, Buffer::MapAccess::WriteOnly)); + MAGNUM_VERIFY_NO_ERROR(); + + CORRADE_VERIFY(contents); + contents[3] = 107; + + buffer.unmapSub(); + MAGNUM_VERIFY_NO_ERROR(); + + /** @todo How to verify the contents in ES? */ +} +#endif + void BufferGLTest::mapRange() { #ifndef MAGNUM_TARGET_GLES2 if(!Context::current()->isExtensionSupported())