Browse Source

Merge branch 'master' into compatibility

Vladimír Vondruš 13 years ago
parent
commit
649125e38f
  1. 33
      src/Buffer.cpp
  2. 50
      src/Buffer.h
  3. 1
      src/Context.cpp
  4. 2
      src/Extensions.h
  5. 4
      src/OpenGL.h
  6. 29
      src/Test/BufferGLTest.cpp
  7. 76
      src/Text/TextRenderer.cpp
  8. 25
      src/Text/TextRenderer.h

33
src/Buffer.cpp

@ -78,6 +78,14 @@ void Buffer::initializeContextBasedFunctionality(Context* context) {
#endif #endif
} }
Buffer::Buffer(Buffer::Target targetHint): _targetHint(targetHint)
#ifdef CORRADE_TARGET_NACL
, _mappedBuffer(nullptr)
#endif
{
glGenBuffers(1, &_id);
}
Buffer::~Buffer() { Buffer::~Buffer() {
GLuint* bindings = Context::current()->state()->buffer->bindings; GLuint* bindings = Context::current()->state()->buffer->bindings;
@ -127,6 +135,31 @@ Int Buffer::size() {
return 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<GLenum>(bindInternal(_targetHint)), offset, length, GLenum(access));
#else
CORRADE_INTERNAL_ASSERT(false);
static_cast<void>(offset);
static_cast<void>(length);
static_cast<void>(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 #ifndef MAGNUM_TARGET_GLES2
void Buffer::copyImplementationDefault(Buffer* read, Buffer* write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) { void Buffer::copyImplementationDefault(Buffer* read, Buffer* write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) {
glCopyBufferSubData(static_cast<GLenum>(read->bindInternal(Target::CopyRead)), static_cast<GLenum>(write->bindInternal(Target::CopyWrite)), readOffset, writeOffset, size); glCopyBufferSubData(static_cast<GLenum>(read->bindInternal(Target::CopyRead)), static_cast<GLenum>(write->bindInternal(Target::CopyWrite)), readOffset, writeOffset, size);

50
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)" * @deprecated Prefer to use @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)"
* instead, as it has more complete set of features. * instead, as it has more complete set of features.
* @see map(MapAccess) * @see map(MapAccess), mapSub()
* @requires_es_extension %Extension @es_extension{OES,mapbuffer} in * @requires_es_extension %Extension @es_extension{OES,mapbuffer} or
* OpenGL ES 2.0, use @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)" * @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. * in OpenGL ES 3.0 instead.
*/ */
enum class MapAccess: GLenum { enum class MapAccess: GLenum {
@ -471,9 +472,7 @@ class MAGNUM_EXPORT Buffer {
* Generates new OpenGL buffer. * Generates new OpenGL buffer.
* @see @fn_gl{GenBuffers} * @see @fn_gl{GenBuffers}
*/ */
explicit Buffer(Target targetHint = Target::Array): _targetHint(targetHint) { explicit Buffer(Target targetHint = Target::Array);
glGenBuffers(1, &_id);
}
/** /**
* @brief Destructor * @brief Destructor
@ -728,6 +727,27 @@ class MAGNUM_EXPORT Buffer {
} }
#endif #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 * @brief Map buffer to client memory
* @param offset Offset into the buffer * @param offset Offset into the buffer
@ -789,6 +809,21 @@ class MAGNUM_EXPORT Buffer {
return (this->*unmapImplementation)(); 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: private:
static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context* context); static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context* context);
@ -878,6 +913,9 @@ class MAGNUM_EXPORT Buffer {
GLuint _id; GLuint _id;
Target _targetHint; Target _targetHint;
#ifdef CORRADE_TARGET_NACL
void* _mappedBuffer;
#endif
}; };
CORRADE_ENUMSET_OPERATORS(Buffer::MapFlags) CORRADE_ENUMSET_OPERATORS(Buffer::MapFlags)

1
src/Context.cpp

@ -199,6 +199,7 @@ const std::vector<Extension>& Extension::extensions(Version version) {
#else #else
static const std::vector<Extension> extensions{ static const std::vector<Extension> extensions{
_extension(GL,APPLE,texture_format_BGRA8888), _extension(GL,APPLE,texture_format_BGRA8888),
_extension(GL,CHROMIUM,map_sub),
_extension(GL,EXT,texture_filter_anisotropic), _extension(GL,EXT,texture_filter_anisotropic),
_extension(GL,EXT,texture_format_BGRA8888), _extension(GL,EXT,texture_format_BGRA8888),
_extension(GL,EXT,read_format_bgra), _extension(GL,EXT,read_format_bgra),

2
src/Extensions.h

@ -193,6 +193,8 @@ namespace GL {
_extension(GL,APPLE,texture_format_BGRA8888, GLES200, None) // #79 _extension(GL,APPLE,texture_format_BGRA8888, GLES200, None) // #79
} namespace ARM { } namespace ARM {
_extension(GL,ARM,rgba8, GLES200, GLES300) // #82 _extension(GL,ARM,rgba8, GLES200, GLES300) // #82
} namespace CHROMIUM {
_extension(GL,CHROMIUM,map_sub, GLES200, None)
} namespace EXT { } namespace EXT {
_extension(GL,EXT,texture_filter_anisotropic, GLES200, None) // #41 _extension(GL,EXT,texture_filter_anisotropic, GLES200, None) // #41
_extension(GL,EXT,texture_type_2_10_10_10_REV, GLES200, GLES300) // #42 _extension(GL,EXT,texture_type_2_10_10_10_REV, GLES200, GLES300) // #42

4
src/OpenGL.h

@ -40,6 +40,10 @@
to NaCl's gl2ext.h we are including our own to prevent undeclared symbol to NaCl's gl2ext.h we are including our own to prevent undeclared symbol
errors with some recent extensions. */ errors with some recent extensions. */
#elif defined(CORRADE_TARGET_NACL) #elif defined(CORRADE_TARGET_NACL)
/* Enable function prototypes (the supported ones shouldn't fail at link time) */
#define GL_GLEXT_PROTOTYPES
#include <GLES2/gl2.h> #include <GLES2/gl2.h>
#include <GLES2/gl2ext.h> #include <GLES2/gl2ext.h>
#undef __gl2ext_h_ #undef __gl2ext_h_

29
src/Test/BufferGLTest.cpp

@ -38,6 +38,9 @@ class BufferGLTest: public AbstractOpenGLTester {
void construct(); void construct();
void data(); void data();
void map(); void map();
#ifdef MAGNUM_TARGET_GLES2
void mapSub();
#endif
void mapRange(); void mapRange();
void mapRangeExplicitFlush(); void mapRangeExplicitFlush();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
@ -52,6 +55,9 @@ BufferGLTest::BufferGLTest() {
addTests({&BufferGLTest::construct, addTests({&BufferGLTest::construct,
&BufferGLTest::data, &BufferGLTest::data,
&BufferGLTest::map, &BufferGLTest::map,
#ifdef MAGNUM_TARGET_GLES2
&BufferGLTest::mapSub,
#endif
&BufferGLTest::mapRange, &BufferGLTest::mapRange,
&BufferGLTest::mapRangeExplicitFlush, &BufferGLTest::mapRangeExplicitFlush,
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
@ -147,6 +153,29 @@ void BufferGLTest::map() {
} }
#endif #endif
#ifdef MAGNUM_TARGET_GLES2
void BufferGLTest::mapSub() {
if(!Context::current()->isExtensionSupported<Extensions::GL::CHROMIUM::map_sub>())
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<char*>(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() { void BufferGLTest::mapRange() {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::map_buffer_range>()) if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::map_buffer_range>())

76
src/Text/TextRenderer.cpp

@ -205,14 +205,55 @@ template<UnsignedInt dimensions> std::tuple<Mesh, Rectangle> TextRenderer<dimens
return std::move(r); return std::move(r);
} }
#ifdef MAGNUM_TARGET_GLES2
AbstractTextRenderer::BufferMapImplementation AbstractTextRenderer::bufferMapImplementation = &AbstractTextRenderer::bufferMapImplementationFull;
AbstractTextRenderer::BufferUnmapImplementation AbstractTextRenderer::bufferUnmapImplementation = &AbstractTextRenderer::bufferUnmapImplementationDefault;
void* AbstractTextRenderer::bufferMapImplementationFull(Buffer& buffer, GLsizeiptr) {
return buffer.map(Buffer::MapAccess::WriteOnly);
}
void* AbstractTextRenderer::bufferMapImplementationSub(Buffer& buffer, GLsizeiptr length) {
return buffer.mapSub(0, length, Buffer::MapAccess::WriteOnly);
}
void AbstractTextRenderer::bufferUnmapImplementationSub(Buffer& buffer) {
buffer.unmap();
}
#endif
#ifndef MAGNUM_TARGET_GLES2
inline void* AbstractTextRenderer::bufferMapImplementation(Buffer& buffer, GLsizeiptr length)
#else
void* AbstractTextRenderer::bufferMapImplementationRange(Buffer& buffer, GLsizeiptr length)
#endif
{
return buffer.map(0, length, Buffer::MapFlag::InvalidateBuffer|Buffer::MapFlag::Write);
}
#ifndef MAGNUM_TARGET_GLES2
inline void AbstractTextRenderer::bufferUnmapImplementation(Buffer& buffer)
#else
void AbstractTextRenderer::bufferUnmapImplementationDefault(Buffer& buffer)
#endif
{
buffer.unmap();
}
AbstractTextRenderer::AbstractTextRenderer(AbstractFont* const font, const GlyphCache* const cache, Float size): _vertexBuffer(Buffer::Target::Array), _indexBuffer(Buffer::Target::ElementArray), font(font), cache(cache), size(size), _capacity(0) { AbstractTextRenderer::AbstractTextRenderer(AbstractFont* const font, const GlyphCache* const cache, Float size): _vertexBuffer(Buffer::Target::Array), _indexBuffer(Buffer::Target::ElementArray), font(font), cache(cache), size(size), _capacity(0) {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::map_buffer_range); MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::map_buffer_range);
#elif defined(MAGNUM_TARGET_GLES2) #elif defined(MAGNUM_TARGET_GLES2)
if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::map_buffer_range>()) { if(Context::current()->isExtensionSupported<Extensions::GL::EXT::map_buffer_range>()) {
bufferMapImplementation = &AbstractTextRenderer::bufferMapImplementationRange;
} else if(Context::current()->isExtensionSupported<Extensions::GL::CHROMIUM::map_sub>()) {
bufferMapImplementation = &AbstractTextRenderer::bufferMapImplementationSub;
bufferUnmapImplementation = &AbstractTextRenderer::bufferUnmapImplementationSub;
} else {
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::OES::mapbuffer); MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::OES::mapbuffer);
Warning() << "Text::TextRenderer:" << Extensions::GL::EXT::map_buffer_range::string() Warning() << "Text::TextRenderer: neither" << Extensions::GL::EXT::map_buffer_range::string()
<< "is not supported, using less efficient" << Extensions::GL::OES::mapbuffer::string() << "nor" << Extensions::GL::CHROMIUM::map_sub::string()
<< "is supported, using inefficient" << Extensions::GL::OES::mapbuffer::string()
<< "instead"; << "instead";
} }
#endif #endif
@ -258,15 +299,8 @@ void AbstractTextRenderer::reserve(const uint32_t glyphCount, const Buffer::Usag
->setIndexBuffer(&_indexBuffer, 0, indexType, 0, vertexCount); ->setIndexBuffer(&_indexBuffer, 0, indexType, 0, vertexCount);
/* Map buffer for filling */ /* Map buffer for filling */
void* indices; void* const indices = bufferMapImplementation(_indexBuffer, indicesSize);
#ifdef MAGNUM_TARGET_GLES2 CORRADE_INTERNAL_ASSERT(indices);
if(Context::current()->isExtensionSupported<Extensions::GL::EXT::map_buffer_range>())
#endif
CORRADE_INTERNAL_ASSERT_OUTPUT(indices = _indexBuffer.map(0, indicesSize,
Buffer::MapFlag::InvalidateBuffer|Buffer::MapFlag::Write));
#ifdef MAGNUM_TARGET_GLES2
else CORRADE_INTERNAL_ASSERT_OUTPUT(indices = _indexBuffer.map(Buffer::MapAccess::WriteOnly));
#endif
/* Prefill index buffer */ /* Prefill index buffer */
if(vertexCount < 255) if(vertexCount < 255)
@ -275,7 +309,7 @@ void AbstractTextRenderer::reserve(const uint32_t glyphCount, const Buffer::Usag
createIndices<UnsignedShort>(indices, glyphCount); createIndices<UnsignedShort>(indices, glyphCount);
else else
createIndices<UnsignedInt>(indices, glyphCount); createIndices<UnsignedInt>(indices, glyphCount);
CORRADE_INTERNAL_ASSERT_OUTPUT(_indexBuffer.unmap()); bufferUnmapImplementation(_indexBuffer);
} }
void AbstractTextRenderer::render(const std::string& text) { void AbstractTextRenderer::render(const std::string& text) {
@ -288,17 +322,9 @@ void AbstractTextRenderer::render(const std::string& text) {
_rectangle = {}; _rectangle = {};
/* Map buffer for rendering */ /* Map buffer for rendering */
Vertex* vertices; Vertex* const vertices = static_cast<Vertex*>(bufferMapImplementation(_vertexBuffer,
#ifdef MAGNUM_TARGET_GLES2 layouter->glyphCount()*4*sizeof(Vertex)));
if(Context::current()->isExtensionSupported<Extensions::GL::EXT::map_buffer_range>()) CORRADE_INTERNAL_ASSERT_OUTPUT(vertices);
#endif
CORRADE_INTERNAL_ASSERT_OUTPUT(vertices = static_cast<Vertex*>(_vertexBuffer.map(0,
layouter->glyphCount()*4*sizeof(Vertex),
Buffer::MapFlag::InvalidateBuffer|Buffer::MapFlag::Write)));
#ifdef MAGNUM_TARGET_GLES2
else CORRADE_INTERNAL_ASSERT_OUTPUT(vertices =
static_cast<Vertex*>(_vertexBuffer.map(Buffer::MapAccess::WriteOnly)));
#endif
/* Render all glyphs */ /* Render all glyphs */
Vector2 cursorPosition; Vector2 cursorPosition;
@ -325,7 +351,7 @@ void AbstractTextRenderer::render(const std::string& text) {
/* Advance cursor position to next character */ /* Advance cursor position to next character */
cursorPosition += advance; cursorPosition += advance;
} }
CORRADE_INTERNAL_ASSERT_OUTPUT(_vertexBuffer.unmap()); bufferUnmapImplementation(_vertexBuffer);
/* Update index count */ /* Update index count */
_mesh.setIndexCount(layouter->glyphCount()*6); _mesh.setIndexCount(layouter->glyphCount()*6);

25
src/Text/TextRenderer.h

@ -134,6 +134,25 @@ class MAGNUM_TEXT_EXPORT AbstractTextRenderer {
Float size; Float size;
UnsignedInt _capacity; UnsignedInt _capacity;
Rectangle _rectangle; Rectangle _rectangle;
#ifdef MAGNUM_TARGET_GLES2
typedef void*(*BufferMapImplementation)(Buffer&, GLsizeiptr);
static MAGNUM_TEXT_LOCAL void* bufferMapImplementationFull(Buffer& buffer, GLsizeiptr length);
static MAGNUM_TEXT_LOCAL void* bufferMapImplementationSub(Buffer& buffer, GLsizeiptr length);
static MAGNUM_TEXT_LOCAL void* bufferMapImplementationRange(Buffer& buffer, GLsizeiptr length);
static BufferMapImplementation bufferMapImplementation;
#else
static void* bufferMapImplementation(Buffer& buffer, GLsizeiptr length);
#endif
#ifdef MAGNUM_TARGET_GLES2
typedef void(*BufferUnmapImplementation)(Buffer&);
static MAGNUM_TEXT_LOCAL void bufferUnmapImplementationDefault(Buffer& buffer);
static MAGNUM_TEXT_LOCAL void bufferUnmapImplementationSub(Buffer& buffer);
static MAGNUM_TEXT_LOCAL BufferUnmapImplementation bufferUnmapImplementation;
#else
static void bufferUnmapImplementation(Buffer& buffer);
#endif
}; };
/** /**
@ -198,9 +217,9 @@ renderer.mesh().draw();
@section TextRenderer-extensions Required OpenGL functionality @section TextRenderer-extensions Required OpenGL functionality
Mutable text rendering requires @extension{ARB,map_buffer_range} on desktop Mutable text rendering requires @extension{ARB,map_buffer_range} on desktop
OpenGL (also part of OpenGL ES 3.0). If @es_extension{EXT,map_buffer_range} is OpenGL (also part of OpenGL ES 3.0). If neither @es_extension{EXT,map_buffer_range}
not available in ES 2.0, at least @es_extension{OES,mapbuffer} must be nor @es_extension{CHROMIUM,map_sub} is not available in ES 2.0, at least
supported for asynchronous buffer updates. @es_extension{OES,mapbuffer} must be supported for asynchronous buffer updates.
@see TextRenderer2D, TextRenderer3D, Font, Shaders::AbstractVectorShader @see TextRenderer2D, TextRenderer3D, Font, Shaders::AbstractVectorShader
*/ */

Loading…
Cancel
Save