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
}
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<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
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);

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)"
* 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)

1
src/Context.cpp

@ -199,6 +199,7 @@ const std::vector<Extension>& Extension::extensions(Version version) {
#else
static const std::vector<Extension> extensions{
_extension(GL,APPLE,texture_format_BGRA8888),
_extension(GL,CHROMIUM,map_sub),
_extension(GL,EXT,texture_filter_anisotropic),
_extension(GL,EXT,texture_format_BGRA8888),
_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
} namespace ARM {
_extension(GL,ARM,rgba8, GLES200, GLES300) // #82
} namespace CHROMIUM {
_extension(GL,CHROMIUM,map_sub, GLES200, None)
} namespace EXT {
_extension(GL,EXT,texture_filter_anisotropic, GLES200, None) // #41
_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
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 <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#undef __gl2ext_h_

29
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<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() {
#ifndef MAGNUM_TARGET_GLES2
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);
}
#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) {
#ifndef MAGNUM_TARGET_GLES
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::map_buffer_range);
#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);
Warning() << "Text::TextRenderer:" << Extensions::GL::EXT::map_buffer_range::string()
<< "is not supported, using less efficient" << Extensions::GL::OES::mapbuffer::string()
Warning() << "Text::TextRenderer: neither" << Extensions::GL::EXT::map_buffer_range::string()
<< "nor" << Extensions::GL::CHROMIUM::map_sub::string()
<< "is supported, using inefficient" << Extensions::GL::OES::mapbuffer::string()
<< "instead";
}
#endif
@ -258,15 +299,8 @@ void AbstractTextRenderer::reserve(const uint32_t glyphCount, const Buffer::Usag
->setIndexBuffer(&_indexBuffer, 0, indexType, 0, vertexCount);
/* Map buffer for filling */
void* indices;
#ifdef MAGNUM_TARGET_GLES2
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
void* const indices = bufferMapImplementation(_indexBuffer, indicesSize);
CORRADE_INTERNAL_ASSERT(indices);
/* Prefill index buffer */
if(vertexCount < 255)
@ -275,7 +309,7 @@ void AbstractTextRenderer::reserve(const uint32_t glyphCount, const Buffer::Usag
createIndices<UnsignedShort>(indices, glyphCount);
else
createIndices<UnsignedInt>(indices, glyphCount);
CORRADE_INTERNAL_ASSERT_OUTPUT(_indexBuffer.unmap());
bufferUnmapImplementation(_indexBuffer);
}
void AbstractTextRenderer::render(const std::string& text) {
@ -288,17 +322,9 @@ void AbstractTextRenderer::render(const std::string& text) {
_rectangle = {};
/* Map buffer for rendering */
Vertex* vertices;
#ifdef MAGNUM_TARGET_GLES2
if(Context::current()->isExtensionSupported<Extensions::GL::EXT::map_buffer_range>())
#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
Vertex* const vertices = static_cast<Vertex*>(bufferMapImplementation(_vertexBuffer,
layouter->glyphCount()*4*sizeof(Vertex)));
CORRADE_INTERNAL_ASSERT_OUTPUT(vertices);
/* Render all glyphs */
Vector2 cursorPosition;
@ -325,7 +351,7 @@ void AbstractTextRenderer::render(const std::string& text) {
/* Advance cursor position to next character */
cursorPosition += advance;
}
CORRADE_INTERNAL_ASSERT_OUTPUT(_vertexBuffer.unmap());
bufferUnmapImplementation(_vertexBuffer);
/* Update index count */
_mesh.setIndexCount(layouter->glyphCount()*6);

25
src/Text/TextRenderer.h

@ -134,6 +134,25 @@ class MAGNUM_TEXT_EXPORT AbstractTextRenderer {
Float size;
UnsignedInt _capacity;
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
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
not available in ES 2.0, at least @es_extension{OES,mapbuffer} must be
supported for asynchronous buffer updates.
OpenGL (also part of OpenGL ES 3.0). If neither @es_extension{EXT,map_buffer_range}
nor @es_extension{CHROMIUM,map_sub} is not available in ES 2.0, at least
@es_extension{OES,mapbuffer} must be supported for asynchronous buffer updates.
@see TextRenderer2D, TextRenderer3D, Font, Shaders::AbstractVectorShader
*/

Loading…
Cancel
Save