diff --git a/demo/glfw_opengl3/nuklear_glfw_gl3.h b/demo/glfw_opengl3/nuklear_glfw_gl3.h index 8bf5bb5ba..8e9017644 100644 --- a/demo/glfw_opengl3/nuklear_glfw_gl3.h +++ b/demo/glfw_opengl3/nuklear_glfw_gl3.h @@ -1,7 +1,9 @@ /* - * Nuklear - 1.32.0 - public domain + * Nuklear - 1.40.8 - public domain * no warrenty implied; use at your own risk. - * authored from 2015-2016 by Micha Mettke + * authored from 2015-2017 by Micha Mettke + * emscripten from 2016 by Chris Willcocks + * OpenGL ES 2.0 from 2017 by Dmitry Hrabrov a.k.a. DeXPeriX */ /* * ============================================================== @@ -37,6 +39,10 @@ struct nk_glfw_device { GLint uniform_tex; GLint uniform_proj; GLuint font_tex; + GLsizei vs; + size_t vp, vt, vc; + GLuint have_vao; + GLuint have_mapbuffer; }; struct nk_glfw { @@ -93,8 +99,8 @@ NK_API void nk_glfw3_mouse_button_callback(GLFWwindow *win, int #endif struct nk_glfw_vertex { - float position[2]; - float uv[2]; + GLfloat position[2]; + GLfloat uv[2]; nk_byte col[4]; }; @@ -151,40 +157,47 @@ nk_glfw3_device_create(struct nk_glfw* glfw) glGetProgramiv(dev->prog, GL_LINK_STATUS, &status); assert(status == GL_TRUE); + /* TODO: Detect at runtime */ + dev->have_vao = GL_TRUE; /* OpenGL 3.0 or later, or GL_ARB_vertex_array_object, or GL_OES_vertex_array_object */ + dev->have_mapbuffer = GL_TRUE; /* OpenGL 2.0 or later, or GL_OES_mapbuffer */ + dev->uniform_tex = glGetUniformLocation(dev->prog, "Texture"); dev->uniform_proj = glGetUniformLocation(dev->prog, "ProjMtx"); dev->attrib_pos = glGetAttribLocation(dev->prog, "Position"); dev->attrib_uv = glGetAttribLocation(dev->prog, "TexCoord"); dev->attrib_col = glGetAttribLocation(dev->prog, "Color"); - { /* buffer setup */ - GLsizei vs = sizeof(struct nk_glfw_vertex); - size_t vp = offsetof(struct nk_glfw_vertex, position); - size_t vt = offsetof(struct nk_glfw_vertex, uv); - size_t vc = offsetof(struct nk_glfw_vertex, col); + dev->vs = sizeof(struct nk_glfw_vertex); + dev->vp = offsetof(struct nk_glfw_vertex, position); + dev->vt = offsetof(struct nk_glfw_vertex, uv); + dev->vc = offsetof(struct nk_glfw_vertex, col); + /* Allocate buffers */ glGenBuffers(1, &dev->vbo); glGenBuffers(1, &dev->ebo); - glGenVertexArrays(1, &dev->vao); - glBindVertexArray(dev->vao); - glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); + if (dev->have_vao) { + glGenVertexArrays(1, &dev->vao); - glEnableVertexAttribArray((GLuint)dev->attrib_pos); - glEnableVertexAttribArray((GLuint)dev->attrib_uv); - glEnableVertexAttribArray((GLuint)dev->attrib_col); + glBindVertexArray(dev->vao); + glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); - glVertexAttribPointer((GLuint)dev->attrib_pos, 2, GL_FLOAT, GL_FALSE, vs, (void*)vp); - glVertexAttribPointer((GLuint)dev->attrib_uv, 2, GL_FLOAT, GL_FALSE, vs, (void*)vt); - glVertexAttribPointer((GLuint)dev->attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, vs, (void*)vc); - } + glEnableVertexAttribArray((GLuint)dev->attrib_pos); + glEnableVertexAttribArray((GLuint)dev->attrib_uv); + glEnableVertexAttribArray((GLuint)dev->attrib_col); + glVertexAttribPointer((GLuint)dev->attrib_pos, 2, GL_FLOAT, GL_FALSE, dev->vs, (void*)dev->vp); + glVertexAttribPointer((GLuint)dev->attrib_uv, 2, GL_FLOAT, GL_FALSE, dev->vs, (void*)dev->vt); + glVertexAttribPointer((GLuint)dev->attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, dev->vs, (void*)dev->vc); + } + } glBindTexture(GL_TEXTURE_2D, 0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindVertexArray(0); + if (dev->have_vao) + glBindVertexArray(0); } NK_INTERN void @@ -218,17 +231,17 @@ NK_API void nk_glfw3_render(struct nk_glfw* glfw, enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_buffer) { struct nk_glfw_device *dev = &glfw->ogl; - struct nk_buffer vbuf, ebuf; GLfloat ortho[4][4] = { - {2.0f, 0.0f, 0.0f, 0.0f}, - {0.0f,-2.0f, 0.0f, 0.0f}, - {0.0f, 0.0f,-1.0f, 0.0f}, - {-1.0f,1.0f, 0.0f, 1.0f}, + { 2.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, -2.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, }; ortho[0][0] /= (GLfloat)glfw->width; ortho[1][1] /= (GLfloat)glfw->height; /* setup global state */ + glViewport(0,0,(GLsizei)glfw->display_width,(GLsizei)glfw->display_height); glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -241,24 +254,42 @@ nk_glfw3_render(struct nk_glfw* glfw, enum nk_anti_aliasing AA, int max_vertex_b glUseProgram(dev->prog); glUniform1i(dev->uniform_tex, 0); glUniformMatrix4fv(dev->uniform_proj, 1, GL_FALSE, &ortho[0][0]); - glViewport(0,0,(GLsizei)glfw->display_width,(GLsizei)glfw->display_height); { /* convert from command queue into draw list and draw to screen */ const struct nk_draw_command *cmd; void *vertices, *elements; - nk_size offset = 0; + const nk_draw_index *offset = NULL; + struct nk_buffer vbuf, ebuf; - /* allocate vertex and element buffer */ - glBindVertexArray(dev->vao); + /* Bind buffers */ + if (dev->have_vao) + glBindVertexArray(dev->vao); glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); + if (!dev->have_vao) { + /* buffer setup */ + glEnableVertexAttribArray((GLuint)dev->attrib_pos); + glEnableVertexAttribArray((GLuint)dev->attrib_uv); + glEnableVertexAttribArray((GLuint)dev->attrib_col); + + glVertexAttribPointer((GLuint)dev->attrib_pos, 2, GL_FLOAT, GL_FALSE, dev->vs, (void*)dev->vp); + glVertexAttribPointer((GLuint)dev->attrib_uv, 2, GL_FLOAT, GL_FALSE, dev->vs, (void*)dev->vt); + glVertexAttribPointer((GLuint)dev->attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, dev->vs, (void*)dev->vc); + } + glBufferData(GL_ARRAY_BUFFER, max_vertex_buffer, NULL, GL_STREAM_DRAW); glBufferData(GL_ELEMENT_ARRAY_BUFFER, max_element_buffer, NULL, GL_STREAM_DRAW); - /* load draw vertices & elements directly into vertex + element buffer */ - vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); - elements = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); + /* load vertices/elements directly into vertex/element buffer */ + if (dev->have_mapbuffer) { + vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); + elements = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); + } else { + vertices = malloc((size_t)max_vertex_buffer); + elements = malloc((size_t)max_element_buffer); + } + { /* fill convert configuration */ struct nk_convert_config config; @@ -281,12 +312,20 @@ nk_glfw3_render(struct nk_glfw* glfw, enum nk_anti_aliasing AA, int max_vertex_b config.line_AA = AA; /* setup buffers to load vertices and elements */ - nk_buffer_init_fixed(&vbuf, vertices, (size_t)max_vertex_buffer); - nk_buffer_init_fixed(&ebuf, elements, (size_t)max_element_buffer); + nk_buffer_init_fixed(&vbuf, vertices, (nk_size)max_vertex_buffer); + nk_buffer_init_fixed(&ebuf, elements, (nk_size)max_element_buffer); nk_convert(&glfw->ctx, &dev->cmds, &vbuf, &ebuf, &config); } - glUnmapBuffer(GL_ARRAY_BUFFER); - glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); + + if (dev->have_mapbuffer) { + glUnmapBuffer(GL_ARRAY_BUFFER); + glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); + } else { + glBufferSubData(GL_ARRAY_BUFFER, 0, (size_t)max_vertex_buffer, vertices); + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, (size_t)max_element_buffer, elements); + free(vertices); + free(elements); + } /* iterate over and execute each draw command */ nk_draw_foreach(cmd, &glfw->ctx, &dev->cmds) @@ -298,8 +337,8 @@ nk_glfw3_render(struct nk_glfw* glfw, enum nk_anti_aliasing AA, int max_vertex_b (GLint)((glfw->height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h)) * glfw->fb_scale.y), (GLint)(cmd->clip_rect.w * glfw->fb_scale.x), (GLint)(cmd->clip_rect.h * glfw->fb_scale.y)); - glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, (const void*) offset); - offset += cmd->elem_count * sizeof(nk_draw_index); + glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset); + offset += cmd->elem_count; } nk_clear(&glfw->ctx); nk_buffer_clear(&dev->cmds); @@ -309,7 +348,8 @@ nk_glfw3_render(struct nk_glfw* glfw, enum nk_anti_aliasing AA, int max_vertex_b glUseProgram(0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindVertexArray(0); + if (dev->have_vao) + glBindVertexArray(0); glDisable(GL_BLEND); glDisable(GL_SCISSOR_TEST); } diff --git a/demo/sdl_opengl3/nuklear_sdl_gl3.h b/demo/sdl_opengl3/nuklear_sdl_gl3.h index a88a28564..fea7ed853 100644 --- a/demo/sdl_opengl3/nuklear_sdl_gl3.h +++ b/demo/sdl_opengl3/nuklear_sdl_gl3.h @@ -1,7 +1,9 @@ /* - * Nuklear - 1.32.0 - public domain + * Nuklear - 1.40.8 - public domain * no warrenty implied; use at your own risk. - * authored from 2015-2016 by Micha Mettke + * authored from 2015-2017 by Micha Mettke + * emscripten from 2016 by Chris Willcocks + * OpenGL ES 2.0 from 2017 by Dmitry Hrabrov a.k.a. DeXPeriX */ /* * ============================================================== @@ -54,11 +56,15 @@ struct nk_sdl_device { GLint uniform_tex; GLint uniform_proj; GLuint font_tex; + GLsizei vs; + size_t vp, vt, vc; + GLuint have_vao; + GLuint have_mapbuffer; }; struct nk_sdl_vertex { - float position[2]; - float uv[2]; + GLfloat position[2]; + GLfloat uv[2]; nk_byte col[4]; }; @@ -75,6 +81,7 @@ static struct nk_sdl { #else #define NK_SHADER_VERSION "#version 300 es\n" #endif + NK_API void nk_sdl_device_create(void) { @@ -104,6 +111,7 @@ nk_sdl_device_create(void) "}\n"; struct nk_sdl_device *dev = &sdl.ogl; + nk_buffer_init_default(&dev->cmds); dev->prog = glCreateProgram(); dev->vert_shdr = glCreateShader(GL_VERTEX_SHADER); @@ -122,40 +130,47 @@ nk_sdl_device_create(void) glGetProgramiv(dev->prog, GL_LINK_STATUS, &status); assert(status == GL_TRUE); + /* TODO: Detect at runtime */ + dev->have_vao = GL_TRUE; /* OpenGL 3.0 or later, or GL_ARB_vertex_array_object, or GL_OES_vertex_array_object */ + dev->have_mapbuffer = GL_TRUE; /* OpenGL 2.0 or later, or GL_OES_mapbuffer */ + dev->uniform_tex = glGetUniformLocation(dev->prog, "Texture"); dev->uniform_proj = glGetUniformLocation(dev->prog, "ProjMtx"); dev->attrib_pos = glGetAttribLocation(dev->prog, "Position"); dev->attrib_uv = glGetAttribLocation(dev->prog, "TexCoord"); dev->attrib_col = glGetAttribLocation(dev->prog, "Color"); - { /* buffer setup */ - GLsizei vs = sizeof(struct nk_sdl_vertex); - size_t vp = offsetof(struct nk_sdl_vertex, position); - size_t vt = offsetof(struct nk_sdl_vertex, uv); - size_t vc = offsetof(struct nk_sdl_vertex, col); + dev->vs = sizeof(struct nk_sdl_vertex); + dev->vp = offsetof(struct nk_sdl_vertex, position); + dev->vt = offsetof(struct nk_sdl_vertex, uv); + dev->vc = offsetof(struct nk_sdl_vertex, col); + /* Allocate buffers */ glGenBuffers(1, &dev->vbo); glGenBuffers(1, &dev->ebo); - glGenVertexArrays(1, &dev->vao); - glBindVertexArray(dev->vao); - glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); + if (dev->have_vao) { + glGenVertexArrays(1, &dev->vao); - glEnableVertexAttribArray((GLuint)dev->attrib_pos); - glEnableVertexAttribArray((GLuint)dev->attrib_uv); - glEnableVertexAttribArray((GLuint)dev->attrib_col); + glBindVertexArray(dev->vao); + glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); - glVertexAttribPointer((GLuint)dev->attrib_pos, 2, GL_FLOAT, GL_FALSE, vs, (void*)vp); - glVertexAttribPointer((GLuint)dev->attrib_uv, 2, GL_FLOAT, GL_FALSE, vs, (void*)vt); - glVertexAttribPointer((GLuint)dev->attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, vs, (void*)vc); - } + glEnableVertexAttribArray((GLuint)dev->attrib_pos); + glEnableVertexAttribArray((GLuint)dev->attrib_uv); + glEnableVertexAttribArray((GLuint)dev->attrib_col); + glVertexAttribPointer((GLuint)dev->attrib_pos, 2, GL_FLOAT, GL_FALSE, dev->vs, (void*)dev->vp); + glVertexAttribPointer((GLuint)dev->attrib_uv, 2, GL_FLOAT, GL_FALSE, dev->vs, (void*)dev->vt); + glVertexAttribPointer((GLuint)dev->attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, dev->vs, (void*)dev->vc); + } + } glBindTexture(GL_TEXTURE_2D, 0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindVertexArray(0); + if (dev->have_vao) + glBindVertexArray(0); } NK_INTERN void @@ -232,17 +247,35 @@ nk_sdl_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_b const nk_draw_index *offset = NULL; struct nk_buffer vbuf, ebuf; - /* allocate vertex and element buffer */ - glBindVertexArray(dev->vao); + /* Bind buffers */ + if (dev->have_vao) + glBindVertexArray(dev->vao); glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); + if (!dev->have_vao) { + /* buffer setup */ + glEnableVertexAttribArray((GLuint)dev->attrib_pos); + glEnableVertexAttribArray((GLuint)dev->attrib_uv); + glEnableVertexAttribArray((GLuint)dev->attrib_col); + + glVertexAttribPointer((GLuint)dev->attrib_pos, 2, GL_FLOAT, GL_FALSE, dev->vs, (void*)dev->vp); + glVertexAttribPointer((GLuint)dev->attrib_uv, 2, GL_FLOAT, GL_FALSE, dev->vs, (void*)dev->vt); + glVertexAttribPointer((GLuint)dev->attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, dev->vs, (void*)dev->vc); + } + glBufferData(GL_ARRAY_BUFFER, max_vertex_buffer, NULL, GL_STREAM_DRAW); glBufferData(GL_ELEMENT_ARRAY_BUFFER, max_element_buffer, NULL, GL_STREAM_DRAW); /* load vertices/elements directly into vertex/element buffer */ - vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); - elements = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); + if (dev->have_mapbuffer) { + vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); + elements = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); + } else { + vertices = malloc((size_t)max_vertex_buffer); + elements = malloc((size_t)max_element_buffer); + } + { /* fill convert configuration */ struct nk_convert_config config; @@ -269,14 +302,24 @@ nk_sdl_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_b nk_buffer_init_fixed(&ebuf, elements, (nk_size)max_element_buffer); nk_convert(&sdl.ctx, &dev->cmds, &vbuf, &ebuf, &config); } - glUnmapBuffer(GL_ARRAY_BUFFER); - glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); + + if (dev->have_mapbuffer) { + glUnmapBuffer(GL_ARRAY_BUFFER); + glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); + } else { + glBufferSubData(GL_ARRAY_BUFFER, 0, (size_t)max_vertex_buffer, vertices); + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, (size_t)max_element_buffer, elements); + free(vertices); + free(elements); + } /* iterate over and execute each draw command */ - nk_draw_foreach(cmd, &sdl.ctx, &dev->cmds) { + nk_draw_foreach(cmd, &sdl.ctx, &dev->cmds) + { if (!cmd->elem_count) continue; glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id); - glScissor((GLint)(cmd->clip_rect.x * scale.x), + glScissor( + (GLint)(cmd->clip_rect.x * scale.x), (GLint)((height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h)) * scale.y), (GLint)(cmd->clip_rect.w * scale.x), (GLint)(cmd->clip_rect.h * scale.y)); @@ -287,10 +330,12 @@ nk_sdl_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_b nk_buffer_clear(&dev->cmds); } + /* default OpenGL state */ glUseProgram(0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindVertexArray(0); + if (dev->have_vao) + glBindVertexArray(0); glDisable(GL_BLEND); glDisable(GL_SCISSOR_TEST); } @@ -408,7 +453,6 @@ nk_sdl_handle_event(SDL_Event *evt) case SDLK_e: nk_input_key(ctx, NK_KEY_TEXT_LINE_END, down && ctrl_down); break; case SDLK_UP: nk_input_key(ctx, NK_KEY_UP, down); break; case SDLK_DOWN: nk_input_key(ctx, NK_KEY_DOWN, down); break; - case SDLK_ESCAPE: nk_input_key(ctx, NK_KEY_TEXT_RESET_MODE, down); break; case SDLK_INSERT: if (down) insert_toggle = !insert_toggle; @@ -418,7 +462,6 @@ nk_sdl_handle_event(SDL_Event *evt) nk_input_key(ctx, NK_KEY_TEXT_REPLACE_MODE, down); } break; - case SDLK_a: if (ctrl_down) nk_input_key(ctx,NK_KEY_TEXT_SELECT_ALL, down); diff --git a/demo/sdl_opengles2/nuklear_sdl_gles2.h b/demo/sdl_opengles2/nuklear_sdl_gles2.h index 040c9b304..54298510a 100644 --- a/demo/sdl_opengles2/nuklear_sdl_gles2.h +++ b/demo/sdl_opengles2/nuklear_sdl_gles2.h @@ -46,7 +46,7 @@ NK_API void nk_sdl_handle_grab(void); struct nk_sdl_device { struct nk_buffer cmds; struct nk_draw_null_texture tex_null; - GLuint vbo, ebo; + GLuint vbo, vao, ebo; GLuint prog; GLuint vert_shdr; GLuint frag_shdr; @@ -58,6 +58,12 @@ struct nk_sdl_device { GLuint font_tex; GLsizei vs; size_t vp, vt, vc; +#ifdef NK_SDL_GLES2_HAVE_VAO + GLuint have_vao; +#endif +#ifdef NK_SDL_GLES2_HAVE_MAPBUFFER + GLuint have_mapbuffer; +#endif }; struct nk_sdl_vertex { @@ -74,10 +80,8 @@ static struct nk_sdl { Uint64 time_of_last_frame; } sdl; - #define NK_SHADER_VERSION "#version 100\n" - NK_API void nk_sdl_device_create(void) { @@ -125,6 +129,13 @@ nk_sdl_device_create(void) glGetProgramiv(dev->prog, GL_LINK_STATUS, &status); assert(status == GL_TRUE); + /* TODO: Detect at runtime */ +#ifdef NK_SDL_GLES2_HAVE_VAO + dev->have_vao = GL_FALSE; +#endif +#ifdef NK_SDL_GLES2_HAVE_MAPBUFFER + dev->have_mapbuffer = GL_FALSE; +#endif dev->uniform_tex = glGetUniformLocation(dev->prog, "Texture"); dev->uniform_proj = glGetUniformLocation(dev->prog, "ProjMtx"); @@ -132,6 +143,7 @@ nk_sdl_device_create(void) dev->attrib_uv = glGetAttribLocation(dev->prog, "TexCoord"); dev->attrib_col = glGetAttribLocation(dev->prog, "Color"); { + /* buffer setup */ dev->vs = sizeof(struct nk_sdl_vertex); dev->vp = offsetof(struct nk_sdl_vertex, position); dev->vt = offsetof(struct nk_sdl_vertex, uv); @@ -140,10 +152,32 @@ nk_sdl_device_create(void) /* Allocate buffers */ glGenBuffers(1, &dev->vbo); glGenBuffers(1, &dev->ebo); + +#ifdef NK_SDL_GLES2_HAVE_VAO + if (dev->have_vao) { + glGenVertexArrays(1, &dev->vao); + + glBindVertexArray(dev->vao); + glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); + + glEnableVertexAttribArray((GLuint)dev->attrib_pos); + glEnableVertexAttribArray((GLuint)dev->attrib_uv); + glEnableVertexAttribArray((GLuint)dev->attrib_col); + + glVertexAttribPointer((GLuint)dev->attrib_pos, 2, GL_FLOAT, GL_FALSE, dev->vs, (void*)dev->vp); + glVertexAttribPointer((GLuint)dev->attrib_uv, 2, GL_FLOAT, GL_FALSE, dev->vs, (void*)dev->vt); + glVertexAttribPointer((GLuint)dev->attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, dev->vs, (void*)dev->vc); + } +#endif } glBindTexture(GL_TEXTURE_2D, 0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +#ifdef NK_SDL_GLES2_HAVE_VAO + if (dev->have_vao) + glBindVertexArray(0); +#endif } NK_INTERN void @@ -218,11 +252,19 @@ nk_sdl_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_b const struct nk_draw_command *cmd; void *vertices, *elements; const nk_draw_index *offset = NULL; + struct nk_buffer vbuf, ebuf; /* Bind buffers */ +#ifdef NK_SDL_GLES2_HAVE_VAO + if (dev->have_vao) + glBindVertexArray(dev->vao); +#endif glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); +#ifdef NK_SDL_GLES2_HAVE_VAO + if (!dev->have_vao) +#endif { /* buffer setup */ glEnableVertexAttribArray((GLuint)dev->attrib_pos); @@ -238,8 +280,17 @@ nk_sdl_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_b glBufferData(GL_ELEMENT_ARRAY_BUFFER, max_element_buffer, NULL, GL_STREAM_DRAW); /* load vertices/elements directly into vertex/element buffer */ - vertices = malloc((size_t)max_vertex_buffer); - elements = malloc((size_t)max_element_buffer); +#ifdef NK_SDL_GLES2_HAVE_MAPBUFFER + if (dev->have_mapbuffer) { + vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); + elements = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); + } else +#endif + { + vertices = malloc((size_t)max_vertex_buffer); + elements = malloc((size_t)max_element_buffer); + } + { /* fill convert configuration */ struct nk_convert_config config; @@ -262,21 +313,31 @@ nk_sdl_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_b config.line_AA = AA; /* setup buffers to load vertices and elements */ - {struct nk_buffer vbuf, ebuf; nk_buffer_init_fixed(&vbuf, vertices, (nk_size)max_vertex_buffer); nk_buffer_init_fixed(&ebuf, elements, (nk_size)max_element_buffer); - nk_convert(&sdl.ctx, &dev->cmds, &vbuf, &ebuf, &config);} + nk_convert(&sdl.ctx, &dev->cmds, &vbuf, &ebuf, &config); + } + +#ifdef NK_SDL_GLES2_HAVE_MAPBUFFER + if (dev->have_mapbuffer) { + glUnmapBuffer(GL_ARRAY_BUFFER); + glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); + } else +#endif + { + glBufferSubData(GL_ARRAY_BUFFER, 0, (size_t)max_vertex_buffer, vertices); + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, (size_t)max_element_buffer, elements); + free(vertices); + free(elements); } - glBufferSubData(GL_ARRAY_BUFFER, 0, (size_t)max_vertex_buffer, vertices); - glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, (size_t)max_element_buffer, elements); - free(vertices); - free(elements); /* iterate over and execute each draw command */ - nk_draw_foreach(cmd, &sdl.ctx, &dev->cmds) { + nk_draw_foreach(cmd, &sdl.ctx, &dev->cmds) + { if (!cmd->elem_count) continue; glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id); - glScissor((GLint)(cmd->clip_rect.x * scale.x), + glScissor( + (GLint)(cmd->clip_rect.x * scale.x), (GLint)((height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h)) * scale.y), (GLint)(cmd->clip_rect.w * scale.x), (GLint)(cmd->clip_rect.h * scale.y)); @@ -287,10 +348,14 @@ nk_sdl_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_b nk_buffer_clear(&dev->cmds); } + /* default OpenGL state */ glUseProgram(0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - +#ifdef NK_SDL_GLES2_HAVE_VAO + if (dev->have_vao) + glBindVertexArray(0); +#endif glDisable(GL_BLEND); glDisable(GL_SCISSOR_TEST); } diff --git a/demo/sfml_opengl3/nuklear_sfml_gl3.h b/demo/sfml_opengl3/nuklear_sfml_gl3.h index 9b8ec522d..305a865ea 100644 --- a/demo/sfml_opengl3/nuklear_sfml_gl3.h +++ b/demo/sfml_opengl3/nuklear_sfml_gl3.h @@ -1,7 +1,9 @@ /* - * Nuklear - 1.32.0 - public domain + * Nuklear - 1.40.8 - public domain * no warrenty implied; use at your own risk. - * authored from 2015-2016 by Micha Mettke + * authored from 2015-2017 by Micha Mettke + * emscripten from 2016 by Chris Willcocks + * OpenGL ES 2.0 from 2017 by Dmitry Hrabrov a.k.a. DeXPeriX */ /* * ============================================================== @@ -55,10 +57,15 @@ struct nk_sfml_device { GLint uniform_tex; GLint uniform_proj; GLuint font_tex; + GLsizei vs; + size_t vp, vt, vc; + GLuint have_vao; + GLuint have_mapbuffer; }; + struct nk_sfml_vertex { - float position[2]; - float uv[2]; + GLfloat position[2]; + GLfloat uv[2]; nk_byte col[4]; }; static struct nk_sfml { @@ -103,31 +110,30 @@ nk_sfml_device_create(void) " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" "}\n"; - struct nk_sfml_device* dev = &sfml.ogl; - nk_buffer_init_default(&dev->cmds); + struct nk_sfml_device *dev = &sfml.ogl; + nk_buffer_init_default(&dev->cmds); dev->prog = glCreateProgram(); dev->vert_shdr = glCreateShader(GL_VERTEX_SHADER); dev->frag_shdr = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(dev->vert_shdr, 1, &vertex_shader, 0); glShaderSource(dev->frag_shdr, 1, &fragment_shader, 0); glCompileShader(dev->vert_shdr); glCompileShader(dev->frag_shdr); - glGetShaderiv(dev->vert_shdr, GL_COMPILE_STATUS, &status); assert(status == GL_TRUE); - glGetShaderiv(dev->frag_shdr, GL_COMPILE_STATUS, &status); assert(status == GL_TRUE); - glAttachShader(dev->prog, dev->vert_shdr); glAttachShader(dev->prog, dev->frag_shdr); glLinkProgram(dev->prog); - glGetProgramiv(dev->prog, GL_LINK_STATUS, &status); assert(status == GL_TRUE); + /* TODO: Detect at runtime */ + dev->have_vao = GL_TRUE; /* OpenGL 3.0 or later, or GL_ARB_vertex_array_object, or GL_OES_vertex_array_object */ + dev->have_mapbuffer = GL_TRUE; /* OpenGL 2.0 or later, or GL_OES_mapbuffer */ + dev->uniform_tex = glGetUniformLocation(dev->prog, "Texture"); dev->uniform_proj = glGetUniformLocation(dev->prog, "ProjMtx"); dev->attrib_pos = glGetAttribLocation(dev->prog, "Position"); @@ -135,42 +141,58 @@ nk_sfml_device_create(void) dev->attrib_col = glGetAttribLocation(dev->prog, "Color"); { /* buffer setup */ - GLsizei vs = sizeof(struct nk_sfml_vertex); - size_t vp = NK_OFFSETOF(struct nk_sfml_vertex, position); - size_t vt = NK_OFFSETOF(struct nk_sfml_vertex, uv); - size_t vc = NK_OFFSETOF(struct nk_sfml_vertex, col); + dev->vs = sizeof(struct nk_sfml_vertex); + dev->vp = offsetof(struct nk_sfml_vertex, position); + dev->vt = offsetof(struct nk_sfml_vertex, uv); + dev->vc = offsetof(struct nk_sfml_vertex, col); + /* Allocate buffers */ glGenBuffers(1, &dev->vbo); glGenBuffers(1, &dev->ebo); - glGenVertexArrays(1, &dev->vao); - glBindVertexArray(dev->vao); - glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); + if (dev->have_vao) { + glGenVertexArrays(1, &dev->vao); + + glBindVertexArray(dev->vao); + glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); - glEnableVertexAttribArray((GLuint)dev->attrib_pos); - glEnableVertexAttribArray((GLuint)dev->attrib_uv); - glEnableVertexAttribArray((GLuint)dev->attrib_col); + glEnableVertexAttribArray((GLuint)dev->attrib_pos); + glEnableVertexAttribArray((GLuint)dev->attrib_uv); + glEnableVertexAttribArray((GLuint)dev->attrib_col); - glVertexAttribPointer((GLuint)dev->attrib_pos, 2, GL_FLOAT, GL_FALSE, vs, (void*)vp); - glVertexAttribPointer((GLuint)dev->attrib_uv, 2, GL_FLOAT, GL_FALSE, vs, (void*)vt); - glVertexAttribPointer((GLuint)dev->attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, vs, (void*)vc); + glVertexAttribPointer((GLuint)dev->attrib_pos, 2, GL_FLOAT, GL_FALSE, dev->vs, (void*)dev->vp); + glVertexAttribPointer((GLuint)dev->attrib_uv, 2, GL_FLOAT, GL_FALSE, dev->vs, (void*)dev->vt); + glVertexAttribPointer((GLuint)dev->attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, dev->vs, (void*)dev->vc); + } } glBindTexture(GL_TEXTURE_2D, 0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindVertexArray(0); + if (dev->have_vao) + glBindVertexArray(0); +} + +NK_INTERN void +nk_sfml_device_upload_atlas(const void *image, int width, int height) +{ + struct nk_sfml_device *dev = &sfml.ogl; + glGenTextures(1, &dev->font_tex); + glBindTexture(GL_TEXTURE_2D, dev->font_tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, image); } NK_API void nk_sfml_device_destroy(void) { - struct nk_sfml_device* dev = &sfml.ogl; - + struct nk_sfml_device *dev = &sfml.ogl; glDetachShader(dev->prog, dev->vert_shdr); glDetachShader(dev->prog, dev->frag_shdr); glDeleteShader(dev->vert_shdr); - glDeleteShader(dev->vert_shdr); + glDeleteShader(dev->frag_shdr); glDeleteProgram(dev->prog); glDeleteTextures(1, &dev->font_tex); glDeleteBuffers(1, &dev->vbo); @@ -178,25 +200,15 @@ nk_sfml_device_destroy(void) nk_buffer_free(&dev->cmds); } -NK_INTERN void -nk_sfml_device_upload_atlas(const void* image, int width, int height) -{ - struct nk_sfml_device* dev = &sfml.ogl; - glGenTextures(1, &dev->font_tex); - glBindTexture(GL_TEXTURE_2D, dev->font_tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0, - GL_RGBA, GL_UNSIGNED_BYTE, image); -} - NK_API void nk_sfml_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_buffer) { - /* setup global state */ - struct nk_sfml_device* dev = &sfml.ogl; - int window_width = sfml.window->getSize().x; - int window_height = sfml.window->getSize().y; + struct nk_sfml_device *dev = &sfml.ogl; + int width = sfml.window->getSize().x; + int height = sfml.window->getSize().y; + int display_width = window_width; + int display_height = window_height; + struct nk_vec2 scale; GLfloat ortho[4][4] = { { 2.0f, 0.0f, 0.0f, 0.0f }, { 0.0f, -2.0f, 0.0f, 0.0f }, @@ -207,10 +219,14 @@ nk_sfml_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_ sfml.ctx.delta_time_seconds = (float)((double)sfml.frame_delta_clock->getElapsedTime().asMicroseconds() / 1000000); sfml.frame_delta_clock->restart(); - ortho[0][0] /= (GLfloat)window_width; - ortho[1][1] /= (GLfloat)window_height; + ortho[0][0] /= (GLfloat)width; + ortho[1][1] /= (GLfloat)height; - glViewport(0, 0, window_width, window_height); + scale.x = (float)display_width/(float)width; + scale.y = (float)display_height/(float)height; + + /* setup global state */ + glViewport(0,0,display_width,display_height); glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -228,28 +244,46 @@ nk_sfml_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_ const struct nk_draw_command *cmd; void *vertices, *elements; const nk_draw_index *offset = NULL; + struct nk_buffer vbuf, ebuf; - /* allocate vertex and element buffer */ - glBindVertexArray(dev->vao); + /* Bind buffers */ + if (dev->have_vao) + glBindVertexArray(dev->vao); glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); + if (!dev->have_vao) { + /* buffer setup */ + glEnableVertexAttribArray((GLuint)dev->attrib_pos); + glEnableVertexAttribArray((GLuint)dev->attrib_uv); + glEnableVertexAttribArray((GLuint)dev->attrib_col); + + glVertexAttribPointer((GLuint)dev->attrib_pos, 2, GL_FLOAT, GL_FALSE, dev->vs, (void*)dev->vp); + glVertexAttribPointer((GLuint)dev->attrib_uv, 2, GL_FLOAT, GL_FALSE, dev->vs, (void*)dev->vt); + glVertexAttribPointer((GLuint)dev->attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, dev->vs, (void*)dev->vc); + } + glBufferData(GL_ARRAY_BUFFER, max_vertex_buffer, NULL, GL_STREAM_DRAW); glBufferData(GL_ELEMENT_ARRAY_BUFFER, max_element_buffer, NULL, GL_STREAM_DRAW); /* load vertices/elements directly into vertex/element buffer */ - vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); - elements = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); + if (dev->have_mapbuffer) { + vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); + elements = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); + } else { + vertices = malloc((size_t)max_vertex_buffer); + elements = malloc((size_t)max_element_buffer); + } + { /* fill convert configuration */ struct nk_convert_config config; - static const struct nk_draw_vertex_layout_element vertex_layout[] = { + static const struct nk_draw_vertex_layout_element vertex_layout[] = { {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_sfml_vertex, position)}, {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_sfml_vertex, uv)}, {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct nk_sfml_vertex, col)}, {NK_VERTEX_LAYOUT_END} }; - memset(&config, 0, sizeof(config)); config.vertex_layout = vertex_layout; config.vertex_size = sizeof(struct nk_sfml_vertex); @@ -263,13 +297,20 @@ nk_sfml_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_ config.line_AA = AA; /* setup buffers to load vertices and elements */ - struct nk_buffer vbuf, ebuf; nk_buffer_init_fixed(&vbuf, vertices, (nk_size)max_vertex_buffer); nk_buffer_init_fixed(&ebuf, elements, (nk_size)max_element_buffer); nk_convert(&sfml.ctx, &dev->cmds, &vbuf, &ebuf, &config); } - glUnmapBuffer(GL_ARRAY_BUFFER); - glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); + + if (dev->have_mapbuffer) { + glUnmapBuffer(GL_ARRAY_BUFFER); + glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); + } else { + glBufferSubData(GL_ARRAY_BUFFER, 0, (size_t)max_vertex_buffer, vertices); + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, (size_t)max_element_buffer, elements); + free(vertices); + free(elements); + } /* iterate over and execute each draw command */ nk_draw_foreach(cmd, &sfml.ctx, &dev->cmds) @@ -277,20 +318,23 @@ nk_sfml_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_ if (!cmd->elem_count) continue; glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id); glScissor( - (GLint)(cmd->clip_rect.x), - (GLint)((window_height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h))), - (GLint)(cmd->clip_rect.w), - (GLint)(cmd->clip_rect.h)); + (GLint)(cmd->clip_rect.x * scale.x), + (GLint)((height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h)) * scale.y), + (GLint)(cmd->clip_rect.w * scale.x), + (GLint)(cmd->clip_rect.h * scale.y)); glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset); offset += cmd->elem_count; } nk_clear(&sfml.ctx); nk_buffer_clear(&dev->cmds); } + + /* default OpenGL state */ glUseProgram(0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindVertexArray(0); + if (dev->have_vao) + glBindVertexArray(0); glDisable(GL_BLEND); glDisable(GL_SCISSOR_TEST); } diff --git a/demo/x11_opengl3/nuklear_xlib_gl3.h b/demo/x11_opengl3/nuklear_xlib_gl3.h index 8b5380024..213ce62a9 100644 --- a/demo/x11_opengl3/nuklear_xlib_gl3.h +++ b/demo/x11_opengl3/nuklear_xlib_gl3.h @@ -1,7 +1,9 @@ /* - * Nuklear - v1.17 - public domain + * Nuklear - 1.40.8 - public domain * no warrenty implied; use at your own risk. - * authored from 2015-2016 by Micha Mettke + * authored from 2015-2017 by Micha Mettke + * emscripten from 2016 by Chris Willcocks + * OpenGL ES 2.0 from 2017 by Dmitry Hrabrov a.k.a. DeXPeriX */ /* * ============================================================== @@ -75,8 +77,6 @@ typedef void (*nkglDeleteVertexArrays)(GLsizei, const GLuint*); typedef void(*nkglVertexAttribPointer)(GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid*); typedef void(*nkglEnableVertexAttribArray)(GLuint); typedef void(*nkglDisableVertexAttribArray)(GLuint); -/* GL_ARB_framebuffer_object */ -typedef void(*nkglGenerateMipmap)(GLenum target); /* GLSL/OpenGL 2.0 core */ typedef GLuint(*nkglCreateShader)(GLenum); typedef void(*nkglShaderSource)(GLuint, GLsizei, const GLchar**, const GLint*); @@ -112,7 +112,6 @@ static nkglDeleteVertexArrays glDeleteVertexArrays; static nkglVertexAttribPointer glVertexAttribPointer; static nkglEnableVertexAttribArray glEnableVertexAttribArray; static nkglDisableVertexAttribArray glDisableVertexAttribArray; -static nkglGenerateMipmap glGenerateMipmap; static nkglCreateShader glCreateShader; static nkglShaderSource glShaderSource; static nkglCompileShader glCompileShader; @@ -157,18 +156,10 @@ struct opengl_info { int glsl_available; int vertex_buffer_obj_available; int vertex_array_obj_available; - int map_buffer_range_available; int fragment_program_available; - int frame_buffer_object_available; }; #endif -struct nk_x11_vertex { - float position[2]; - float uv[2]; - nk_byte col[4]; -}; - struct nk_x11_device { #ifdef NK_XLIB_LOAD_OPENGL_EXTENSIONS struct opengl_info info; @@ -185,6 +176,16 @@ struct nk_x11_device { GLint uniform_tex; GLint uniform_proj; GLuint font_tex; + GLsizei vs; + size_t vp, vt, vc; + GLuint have_vao; + GLuint have_mapbuffer; +}; + +struct nk_x11_vertex { + GLfloat position[2]; + GLfloat uv[2]; + nk_byte col[4]; }; static struct nk_x11 { @@ -198,6 +199,7 @@ static struct nk_x11 { double time_of_last_frame; } x11; +/* TODO: Detect at runtime */ #ifdef __APPLE__ #define NK_SHADER_VERSION "#version 150\n" #else @@ -334,11 +336,6 @@ nk_load_opengl(struct opengl_info *gl) glBindVertexArray = GL_EXT(glBindVertexArray); glDeleteVertexArrays = GL_EXT(glDeleteVertexArrays); } - gl->frame_buffer_object_available = nk_x11_check_extension(gl, "GL_ARB_framebuffer_object"); - if (gl->frame_buffer_object_available) { - /* GL_ARB_framebuffer_object */ - glGenerateMipmap = GL_EXT(glGenerateMipmap); - } if (!gl->vertex_buffer_obj_available) { fprintf(stdout, "[GL] Error: GL_ARB_vertex_buffer_object is not available!\n"); failed = nk_true; @@ -347,14 +344,6 @@ nk_load_opengl(struct opengl_info *gl) fprintf(stdout, "[GL] Error: GL_ARB_fragment_program is not available!\n"); failed = nk_true; } - if (!gl->vertex_array_obj_available) { - fprintf(stdout, "[GL] Error: GL_ARB_vertex_array_object is not available!\n"); - failed = nk_true; - } - if (!gl->frame_buffer_object_available) { - fprintf(stdout, "[GL] Error: GL_ARB_framebuffer_object is not available!\n"); - failed = nk_true; - } return !failed; } #endif @@ -391,8 +380,8 @@ nk_x11_device_create(void) #ifdef NK_XLIB_LOAD_OPENGL_EXTENSIONS if (!nk_load_opengl(&dev->info)) return 0; #endif - nk_buffer_init_default(&dev->cmds); + nk_buffer_init_default(&dev->cmds); dev->prog = glCreateProgram(); dev->vert_shdr = glCreateShader(GL_VERTEX_SHADER); dev->frag_shdr = glCreateShader(GL_FRAGMENT_SHADER); @@ -410,40 +399,51 @@ nk_x11_device_create(void) glGetProgramiv(dev->prog, GL_LINK_STATUS, &status); assert(status == GL_TRUE); +#ifdef NK_XLIB_LOAD_OPENGL_EXTENSIONS + dev->have_vao = dev->info.vertex_array_obj_available; +#else + /* TODO: Detect at runtime */ + dev->have_vao = GL_TRUE; /* OpenGL 3.0 or later, or GL_ARB_vertex_array_object, or GL_OES_vertex_array_object */ +#endif + dev->have_mapbuffer = GL_TRUE; /* OpenGL 2.0 or later, or GL_OES_mapbuffer */ + dev->uniform_tex = glGetUniformLocation(dev->prog, "Texture"); dev->uniform_proj = glGetUniformLocation(dev->prog, "ProjMtx"); dev->attrib_pos = glGetAttribLocation(dev->prog, "Position"); dev->attrib_uv = glGetAttribLocation(dev->prog, "TexCoord"); dev->attrib_col = glGetAttribLocation(dev->prog, "Color"); - { /* buffer setup */ - GLsizei vs = sizeof(struct nk_x11_vertex); - size_t vp = offsetof(struct nk_x11_vertex, position); - size_t vt = offsetof(struct nk_x11_vertex, uv); - size_t vc = offsetof(struct nk_x11_vertex, col); + dev->vs = sizeof(struct nk_x11_vertex); + dev->vp = offsetof(struct nk_x11_vertex, position); + dev->vt = offsetof(struct nk_x11_vertex, uv); + dev->vc = offsetof(struct nk_x11_vertex, col); + /* Allocate buffers */ glGenBuffers(1, &dev->vbo); glGenBuffers(1, &dev->ebo); - glGenVertexArrays(1, &dev->vao); - glBindVertexArray(dev->vao); - glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); + if (dev->have_vao) { + glGenVertexArrays(1, &dev->vao); - glEnableVertexAttribArray((GLuint)dev->attrib_pos); - glEnableVertexAttribArray((GLuint)dev->attrib_uv); - glEnableVertexAttribArray((GLuint)dev->attrib_col); + glBindVertexArray(dev->vao); + glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); - glVertexAttribPointer((GLuint)dev->attrib_pos, 2, GL_FLOAT, GL_FALSE, vs, (void*)vp); - glVertexAttribPointer((GLuint)dev->attrib_uv, 2, GL_FLOAT, GL_FALSE, vs, (void*)vt); - glVertexAttribPointer((GLuint)dev->attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, vs, (void*)vc); - } + glEnableVertexAttribArray((GLuint)dev->attrib_pos); + glEnableVertexAttribArray((GLuint)dev->attrib_uv); + glEnableVertexAttribArray((GLuint)dev->attrib_col); + glVertexAttribPointer((GLuint)dev->attrib_pos, 2, GL_FLOAT, GL_FALSE, dev->vs, (void*)dev->vp); + glVertexAttribPointer((GLuint)dev->attrib_uv, 2, GL_FLOAT, GL_FALSE, dev->vs, (void*)dev->vt); + glVertexAttribPointer((GLuint)dev->attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, dev->vs, (void*)dev->vc); + } + } glBindTexture(GL_TEXTURE_2D, 0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindVertexArray(0); + if (dev->have_vao) + glBindVertexArray(0); return 1; } @@ -477,9 +477,11 @@ nk_x11_device_destroy(void) NK_API void nk_x11_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_buffer) { - int width, height; XWindowAttributes attr; struct nk_x11_device *dev = &x11.ogl; + int width, height; + int display_width, display_height; + struct nk_vec2 scale; GLfloat ortho[4][4] = { { 2.0f, 0.0f, 0.0f, 0.0f }, { 0.0f, -2.0f, 0.0f, 0.0f }, @@ -491,13 +493,17 @@ nk_x11_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_b x11.time_of_last_frame = now; XGetWindowAttributes(x11.dpy, x11.win, &attr); - width = attr.width; - height = attr.height; + width = display_width = attr.width; + height = display_height = attr.height; ortho[0][0] /= (GLfloat)width; ortho[1][1] /= (GLfloat)height; + scale.x = (float)display_width/(float)width; + scale.y = (float)display_height/(float)height; + /* setup global state */ + glViewport(0,0,display_width,display_height); glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -510,7 +516,6 @@ nk_x11_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_b glUseProgram(dev->prog); glUniform1i(dev->uniform_tex, 0); glUniformMatrix4fv(dev->uniform_proj, 1, GL_FALSE, &ortho[0][0]); - glViewport(0,0,(GLsizei)width,(GLsizei)height); { /* convert from command queue into draw list and draw to screen */ const struct nk_draw_command *cmd; @@ -518,17 +523,35 @@ nk_x11_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_b const nk_draw_index *offset = NULL; struct nk_buffer vbuf, ebuf; - /* allocate vertex and element buffer */ - glBindVertexArray(dev->vao); + /* Bind buffers */ + if (dev->have_vao) + glBindVertexArray(dev->vao); glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); + if (!dev->have_vao) { + /* buffer setup */ + glEnableVertexAttribArray((GLuint)dev->attrib_pos); + glEnableVertexAttribArray((GLuint)dev->attrib_uv); + glEnableVertexAttribArray((GLuint)dev->attrib_col); + + glVertexAttribPointer((GLuint)dev->attrib_pos, 2, GL_FLOAT, GL_FALSE, dev->vs, (void*)dev->vp); + glVertexAttribPointer((GLuint)dev->attrib_uv, 2, GL_FLOAT, GL_FALSE, dev->vs, (void*)dev->vt); + glVertexAttribPointer((GLuint)dev->attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, dev->vs, (void*)dev->vc); + } + glBufferData(GL_ARRAY_BUFFER, max_vertex_buffer, NULL, GL_STREAM_DRAW); glBufferData(GL_ELEMENT_ARRAY_BUFFER, max_element_buffer, NULL, GL_STREAM_DRAW); - /* load draw vertices & elements directly into vertex + element buffer */ - vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); - elements = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); + /* load vertices/elements directly into vertex/element buffer */ + if (dev->have_mapbuffer) { + vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); + elements = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); + } else { + vertices = malloc((size_t)max_vertex_buffer); + elements = malloc((size_t)max_element_buffer); + } + { /* fill convert configuration */ struct nk_convert_config config; @@ -551,12 +574,20 @@ nk_x11_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_b config.line_AA = AA; /* setup buffers to load vertices and elements */ - nk_buffer_init_fixed(&vbuf, vertices, (size_t)max_vertex_buffer); - nk_buffer_init_fixed(&ebuf, elements, (size_t)max_element_buffer); + nk_buffer_init_fixed(&vbuf, vertices, (nk_size)max_vertex_buffer); + nk_buffer_init_fixed(&ebuf, elements, (nk_size)max_element_buffer); nk_convert(&x11.ctx, &dev->cmds, &vbuf, &ebuf, &config); } - glUnmapBuffer(GL_ARRAY_BUFFER); - glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); + + if (dev->have_mapbuffer) { + glUnmapBuffer(GL_ARRAY_BUFFER); + glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); + } else { + glBufferSubData(GL_ARRAY_BUFFER, 0, (size_t)max_vertex_buffer, vertices); + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, (size_t)max_element_buffer, elements); + free(vertices); + free(elements); + } /* iterate over and execute each draw command */ nk_draw_foreach(cmd, &x11.ctx, &dev->cmds) @@ -564,10 +595,10 @@ nk_x11_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_b if (!cmd->elem_count) continue; glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id); glScissor( - (GLint)(cmd->clip_rect.x), - (GLint)((height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h))), - (GLint)(cmd->clip_rect.w), - (GLint)(cmd->clip_rect.h)); + (GLint)(cmd->clip_rect.x * scale.x), + (GLint)((height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h)) * scale.y), + (GLint)(cmd->clip_rect.w * scale.x), + (GLint)(cmd->clip_rect.h * scale.y)); glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset); offset += cmd->elem_count; } @@ -579,7 +610,8 @@ nk_x11_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_b glUseProgram(0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindVertexArray(0); + if (dev->have_vao) + glBindVertexArray(0); glDisable(GL_BLEND); glDisable(GL_SCISSOR_TEST); }