uint32_t count)
{
uint32_t size = count * 16;
+ void *ptr;
if (size > backend->vbo_size) {
backend->vbo_size = size;
GL_STREAM_DRAW);
}
- backend->BufferSubData(GL_ARRAY_BUFFER, 0,
- (size / 2), vigs_vector_data(&backend->v1));
- backend->BufferSubData(GL_ARRAY_BUFFER, (size / 2),
- (size / 2), vigs_vector_data(&backend->v2));
+ if (backend->MapBufferRange) {
+ ptr = backend->MapBufferRange(GL_ARRAY_BUFFER, 0, size,
+ GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT);
+
+ if (ptr) {
+ memcpy(ptr, vigs_vector_data(&backend->v1), size / 2);
+ memcpy(ptr + (size / 2), vigs_vector_data(&backend->v2), size / 2);
+
+ backend->UnmapBuffer(GL_ARRAY_BUFFER);
+ } else {
+ VIGS_LOG_ERROR("glMapBufferRange failed");
+ }
+ } else {
+ backend->Finish();
+ backend->BufferSubData(GL_ARRAY_BUFFER, 0,
+ (size / 2), vigs_vector_data(&backend->v1));
+ backend->BufferSubData(GL_ARRAY_BUFFER, (size / 2),
+ (size / 2), vigs_vector_data(&backend->v2));
+ }
backend->EnableVertexAttribArray(backend->tex_prog_vertCoord_loc);
backend->EnableVertexAttribArray(backend->tex_prog_texCoord_loc);
uint32_t count)
{
uint32_t size = count * 8;
+ void *ptr;
if (size > backend->vbo_size) {
backend->vbo_size = size;
GL_STREAM_DRAW);
}
- backend->BufferSubData(GL_ARRAY_BUFFER, 0, size,
- vigs_vector_data(&backend->v1));
+ if (backend->MapBufferRange) {
+ ptr = backend->MapBufferRange(GL_ARRAY_BUFFER, 0, size,
+ GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT);
+
+ if (ptr) {
+ memcpy(ptr, vigs_vector_data(&backend->v1), size);
+
+ backend->UnmapBuffer(GL_ARRAY_BUFFER);
+ } else {
+ VIGS_LOG_ERROR("glMapBufferRange failed");
+ }
+ } else {
+ backend->Finish();
+ backend->BufferSubData(GL_ARRAY_BUFFER, 0, size,
+ vigs_vector_data(&backend->v1));
+ }
backend->Uniform4fv(backend->color_prog_color_loc, 1, color);
return false;
}
- if (!gl_backend->is_gl_2) {
+ if (gl_backend->is_gl_2) {
+ const char *tmp = (const char*)gl_backend->GetString(GL_EXTENSIONS);
+
+ if (!tmp || (strstr(tmp, "GL_ARB_map_buffer_range ") == NULL)) {
+ VIGS_LOG_WARN("glMapBufferRange not supported, using glBufferSubData");
+ }
+
+ gl_backend->MapBufferRange = NULL;
+ } else {
gl_backend->GenVertexArrays(1, &gl_backend->vao);
if (!gl_backend->vao) {
void (GLAPIENTRY *FramebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
void (GLAPIENTRY *FramebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
void (GLAPIENTRY *GetIntegerv)(GLenum pname, GLint *params);
+ const GLubyte *(GLAPIENTRY *GetString)(GLenum name);
void (GLAPIENTRY *DrawArrays)(GLenum mode, GLint first, GLsizei count);
void (GLAPIENTRY *GenBuffers)(GLsizei n, GLuint *buffers);
void (GLAPIENTRY *DeleteBuffers)(GLsizei n, const GLuint *buffers);
*/
/*
+ * Only OpenGL 2.1 + GL_ARB_map_buffer_range or OpenGL 3.1+ core.
+ */
+ GLvoid *(GLAPIENTRY *MapBufferRange)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+
+ /*
* OpenGL 3.1+ core functions and extensions.
* @{
*/
} \
} while (0)
+#define VIGS_GL_GET_PROC_OPTIONAL(func, proc_name) \
+ *(void**)(&gl_backend_cgl->base.func) = dlsym(gl_backend_cgl->handle, #proc_name)
+
static const CGLPixelFormatAttribute pixel_format_legacy_attrs[] =
{
kCGLPFAAccelerated,
VIGS_GL_GET_PROC(FramebufferRenderbuffer, glFramebufferRenderbufferEXT);
VIGS_GL_GET_PROC(FramebufferTexture2D, glFramebufferTexture2DEXT);
VIGS_GL_GET_PROC(GetIntegerv, glGetIntegerv);
+ VIGS_GL_GET_PROC(GetString, glGetString);
VIGS_GL_GET_PROC(DrawArrays, glDrawArrays);
VIGS_GL_GET_PROC(GenBuffers, glGenBuffers);
VIGS_GL_GET_PROC(DeleteBuffers, glDeleteBuffers);
VIGS_GL_GET_PROC(Uniform4fv, glUniform4fv);
VIGS_GL_GET_PROC(UniformMatrix4fv, glUniformMatrix4fv);
+ VIGS_GL_GET_PROC_OPTIONAL(MapBufferRange, glMapBufferRange);
+
if (!vigs_gl_backend_cgl_check_gl_version(gl_backend_cgl,
&gl_backend_cgl->base.is_gl_2)) {
goto fail2;
VIGS_GL_GET_PROC(FramebufferRenderbuffer, glFramebufferRenderbufferEXT);
VIGS_GL_GET_PROC(FramebufferTexture2D, glFramebufferTexture2DEXT);
VIGS_GL_GET_PROC(GetIntegerv, glGetIntegerv);
+ VIGS_GL_GET_PROC(GetString, glGetString);
VIGS_GL_GET_PROC(DrawArrays, glDrawArrays);
VIGS_GL_GET_PROC(GenBuffers, glGenBuffers);
VIGS_GL_GET_PROC(DeleteBuffers, glDeleteBuffers);
VIGS_GL_GET_PROC(Uniform4fv, glUniform4fv);
VIGS_GL_GET_PROC(UniformMatrix4fv, glUniformMatrix4fv);
+ VIGS_GL_GET_PROC_OPTIONAL(MapBufferRange, glMapBufferRange);
+
gl_backend_glx->dpy = x_display;
if (!vigs_gl_backend_glx_check_gl_version(gl_backend_glx,
VIGS_GL_GET_PROC(FramebufferRenderbuffer, glFramebufferRenderbufferEXT);
VIGS_GL_GET_PROC(FramebufferTexture2D, glFramebufferTexture2DEXT);
VIGS_GL_GET_PROC(GetIntegerv, glGetIntegerv);
+ VIGS_GL_GET_PROC(GetString, glGetString);
VIGS_GL_GET_PROC(DrawArrays, glDrawArrays);
VIGS_GL_GET_PROC(GenBuffers, glGenBuffers);
VIGS_GL_GET_PROC(DeleteBuffers, glDeleteBuffers);
VIGS_GL_GET_PROC(Uniform4fv, glUniform4fv);
VIGS_GL_GET_PROC(UniformMatrix4fv, glUniformMatrix4fv);
+ VIGS_GL_GET_PROC_OPTIONAL(MapBufferRange, glMapBufferRange);
+
gl_backend_wgl->wglMakeCurrent(NULL, NULL);
gl_backend_wgl->wglDeleteContext(tmp_ctx);
tmp_ctx = NULL;
{
gles_api_ts->driver = driver;
gles_api_ts->ps = ps;
+ gles_api_ts->use_map_buffer_range = -1;
}
void yagl_gles_api_ts_cleanup(struct yagl_gles_api_ts *gles_api_ts)
struct yagl_gles_array *arrays;
uint32_t num_arrays;
+
+ /*
+ * -1 when undecided, 0/1 when decided.
+ */
+ int use_map_buffer_range;
};
void yagl_gles_api_ts_init(struct yagl_gles_api_ts *gles_api_ts,
yagl_gles1_array_texcoord,
} yagl_gles1_array_type;
+static bool yagl_gles_use_map_buffer_range(void)
+{
+ YAGL_LOG_FUNC_SET(yagl_gles_use_map_buffer_range);
+
+ if (gles_api_ts->use_map_buffer_range == -1) {
+ if (gles_api_ts->driver->gl_version > yagl_gl_2) {
+ gles_api_ts->use_map_buffer_range = 1;
+ } else {
+ const char *tmp = (const char*)gles_api_ts->driver->GetString(GL_EXTENSIONS);
+
+ gles_api_ts->use_map_buffer_range =
+ (tmp && (strstr(tmp, "GL_ARB_map_buffer_range ") != NULL));
+
+ if (!gles_api_ts->use_map_buffer_range) {
+ YAGL_LOG_WARN("glMapBufferRange not supported, using glBufferSubData");
+ }
+ }
+ }
+
+ return gles_api_ts->use_map_buffer_range;
+}
+
static GLuint yagl_gles_bind_array(uint32_t indx,
GLint first,
GLsizei stride,
{
GLuint current_vbo;
uint32_t size;
+ void *ptr;
+
+ YAGL_LOG_FUNC_SET(yagl_gles_bind_array);
if (indx >= gles_api_ts->num_arrays) {
struct yagl_gles_array *arrays;
gles_api_ts->arrays[indx].size = size;
}
+ if (yagl_gles_use_map_buffer_range()) {
+ ptr = gles_api_ts->driver->MapBufferRange(GL_ARRAY_BUFFER,
+ first * stride,
+ data_count,
+ GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT);
- gles_api_ts->driver->BufferSubData(GL_ARRAY_BUFFER,
- first * stride, data_count, data);
+ if (ptr) {
+ memcpy(ptr, data, data_count);
+
+ gles_api_ts->driver->UnmapBuffer(GL_ARRAY_BUFFER);
+ } else {
+ YAGL_LOG_ERROR("glMapBufferRange failed");
+ }
+ } else {
+ gles_api_ts->driver->Finish();
+ gles_api_ts->driver->BufferSubData(GL_ARRAY_BUFFER,
+ first * stride, data_count,
+ data);
+ }
return current_vbo;
}
GLsizei offset,
const GLvoid *data, int32_t data_count)
{
- gles_api_ts->driver->BufferSubData(target, offset, data_count, data);
+ void *ptr;
+
+ YAGL_LOG_FUNC_SET(glBufferSubData);
+
+ if (yagl_gles_use_map_buffer_range()) {
+ ptr = gles_api_ts->driver->MapBufferRange(target,
+ offset,
+ data_count,
+ GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT);
+
+ if (ptr) {
+ memcpy(ptr, data, data_count);
+
+ gles_api_ts->driver->UnmapBuffer(target);
+ } else {
+ YAGL_LOG_ERROR("glMapBufferRange failed");
+ }
+ } else {
+ gles_api_ts->driver->Finish();
+ gles_api_ts->driver->BufferSubData(target, offset, data_count, data);
+ }
}
void yagl_host_glBindBufferBase(GLenum target,
YAGL_GLES_OGL_GET_PROC(driver, Finish, glFinish);
if (gl_version > yagl_gl_2) {
+ YAGL_GLES_OGL_GET_PROC(driver, MapBufferRange, glMapBufferRange);
YAGL_GLES_OGL_GET_PROC(driver, GetStringi, glGetStringi);
YAGL_GLES_OGL_GET_PROC(driver, GenVertexArrays, glGenVertexArrays);
YAGL_GLES_OGL_GET_PROC(driver, BindVertexArray, glBindVertexArray);
YAGL_GLES_OGL_GET_PROC(driver, ClearBufferfv, glClearBufferfv);
YAGL_GLES_OGL_GET_PROC(driver, GetFragDataLocation, glGetFragDataLocation);
YAGL_GLES_OGL_GET_PROC(driver, DrawRangeElements, glDrawRangeElements);
+ } else {
+ YAGL_GLES_OGL_GET_PROC_OPT(driver, MapBufferRange, glMapBufferRange);
}
driver->destroy = &yagl_gles_ogl_destroy;
} \
} while (0)
+#define YAGL_GLES_OGL_GET_PROC_OPT(driver, func, sym) \
+ *(void**)(&driver->func) = yagl_dyn_lib_get_ogl_procaddr(dyn_lib, #sym)
+
/*
* @}
*/
#define YAGL_GLES_DRIVER_FUNC4(func, arg0_type, arg1_type, arg2_type, arg3_type, arg0, arg1, arg2, arg3) \
void (YAGL_GLES_APIENTRY *func)(arg0_type arg0, arg1_type arg1, arg2_type arg2, arg3_type arg3);
+#define YAGL_GLES_DRIVER_FUNC_RET4(ret_type, func, arg0_type, arg1_type, arg2_type, arg3_type, arg0, arg1, arg2, arg3) \
+ret_type (YAGL_GLES_APIENTRY *func)(arg0_type arg0, arg1_type arg1, arg2_type arg2, arg3_type arg3);
+
#define YAGL_GLES_DRIVER_FUNC5(func, arg0_type, arg1_type, arg2_type, arg3_type, arg4_type, arg0, arg1, arg2, arg3, arg4) \
void (YAGL_GLES_APIENTRY *func)(arg0_type arg0, arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4);
YAGL_GLES_DRIVER_FUNC0(Finish)
/*
+ * Only OpenGL 2.1 + GL_ARB_map_buffer_range or OpenGL 3.1+ core.
+ */
+ YAGL_GLES_DRIVER_FUNC_RET4(GLvoid*, MapBufferRange, GLenum, GLintptr, GLsizeiptr, GLbitfield, target, offset, length, access)
+
+ /*
* @}
*/