nanovg_gl_utils.h (4807B)
1 // 2 // Copyright (c) 2009-2013 Mikko Mononen memon@inside.org 3 // 4 // This software is provided 'as-is', without any express or implied 5 // warranty. In no event will the authors be held liable for any damages 6 // arising from the use of this software. 7 // Permission is granted to anyone to use this software for any purpose, 8 // including commercial applications, and to alter it and redistribute it 9 // freely, subject to the following restrictions: 10 // 1. The origin of this software must not be misrepresented; you must not 11 // claim that you wrote the original software. If you use this software 12 // in a product, an acknowledgment in the product documentation would be 13 // appreciated but is not required. 14 // 2. Altered source versions must be plainly marked as such, and must not be 15 // misrepresented as being the original software. 16 // 3. This notice may not be removed or altered from any source distribution. 17 // 18 #ifndef NANOVG_GL_UTILS_H 19 #define NANOVG_GL_UTILS_H 20 21 struct NVGLUframebuffer { 22 NVGcontext* ctx; 23 GLuint fbo; 24 GLuint rbo; 25 GLuint texture; 26 int image; 27 }; 28 typedef struct NVGLUframebuffer NVGLUframebuffer; 29 30 // Helper function to create GL frame buffer to render to. 31 void nvgluBindFramebuffer(NVGLUframebuffer* fb); 32 NVGLUframebuffer* nvgluCreateFramebuffer(NVGcontext* ctx, int w, int h, int imageFlags); 33 void nvgluDeleteFramebuffer(NVGLUframebuffer* fb); 34 35 #endif // NANOVG_GL_UTILS_H 36 37 #ifdef NANOVG_GL_IMPLEMENTATION 38 39 #if defined(NANOVG_GL3) || defined(NANOVG_GLES2) || defined(NANOVG_GLES3) 40 // FBO is core in OpenGL 3>. 41 # define NANOVG_FBO_VALID 1 42 #elif defined(NANOVG_GL2) 43 // On OS X including glext defines FBO on GL2 too. 44 # ifdef __APPLE__ 45 # include <OpenGL/glext.h> 46 # define NANOVG_FBO_VALID 1 47 # endif 48 #endif 49 50 static GLint defaultFBO = -1; 51 52 NVGLUframebuffer* nvgluCreateFramebuffer(NVGcontext* ctx, int w, int h, int imageFlags) 53 { 54 #ifdef NANOVG_FBO_VALID 55 GLint defaultFBO; 56 GLint defaultRBO; 57 NVGLUframebuffer* fb = NULL; 58 59 glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO); 60 glGetIntegerv(GL_RENDERBUFFER_BINDING, &defaultRBO); 61 62 fb = (NVGLUframebuffer*)malloc(sizeof(NVGLUframebuffer)); 63 if (fb == NULL) goto error; 64 memset(fb, 0, sizeof(NVGLUframebuffer)); 65 66 fb->image = nvgCreateImageRGBA(ctx, w, h, imageFlags | NVG_IMAGE_FLIPY | NVG_IMAGE_PREMULTIPLIED, NULL); 67 68 #if defined NANOVG_GL2 69 fb->texture = nvglImageHandleGL2(ctx, fb->image); 70 #elif defined NANOVG_GL3 71 fb->texture = nvglImageHandleGL3(ctx, fb->image); 72 #elif defined NANOVG_GLES2 73 fb->texture = nvglImageHandleGLES2(ctx, fb->image); 74 #elif defined NANOVG_GLES3 75 fb->texture = nvglImageHandleGLES3(ctx, fb->image); 76 #endif 77 78 fb->ctx = ctx; 79 80 // frame buffer object 81 glGenFramebuffers(1, &fb->fbo); 82 glBindFramebuffer(GL_FRAMEBUFFER, fb->fbo); 83 84 // render buffer object 85 glGenRenderbuffers(1, &fb->rbo); 86 glBindRenderbuffer(GL_RENDERBUFFER, fb->rbo); 87 glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, w, h); 88 89 // combine all 90 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb->texture, 0); 91 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb->rbo); 92 93 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { 94 #ifdef GL_DEPTH24_STENCIL8 95 // If GL_STENCIL_INDEX8 is not supported, try GL_DEPTH24_STENCIL8 as a fallback. 96 // Some graphics cards require a depth buffer along with a stencil. 97 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, w, h); 98 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb->texture, 0); 99 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb->rbo); 100 101 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 102 #endif // GL_DEPTH24_STENCIL8 103 goto error; 104 } 105 106 glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO); 107 glBindRenderbuffer(GL_RENDERBUFFER, defaultRBO); 108 return fb; 109 error: 110 glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO); 111 glBindRenderbuffer(GL_RENDERBUFFER, defaultRBO); 112 nvgluDeleteFramebuffer(fb); 113 return NULL; 114 #else 115 NVG_NOTUSED(ctx); 116 NVG_NOTUSED(w); 117 NVG_NOTUSED(h); 118 NVG_NOTUSED(imageFlags); 119 return NULL; 120 #endif 121 } 122 123 void nvgluBindFramebuffer(NVGLUframebuffer* fb) 124 { 125 #ifdef NANOVG_FBO_VALID 126 if (defaultFBO == -1) glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO); 127 glBindFramebuffer(GL_FRAMEBUFFER, fb != NULL ? fb->fbo : defaultFBO); 128 #else 129 NVG_NOTUSED(fb); 130 #endif 131 } 132 133 void nvgluDeleteFramebuffer(NVGLUframebuffer* fb) 134 { 135 #ifdef NANOVG_FBO_VALID 136 if (fb == NULL) return; 137 if (fb->fbo != 0) 138 glDeleteFramebuffers(1, &fb->fbo); 139 if (fb->rbo != 0) 140 glDeleteRenderbuffers(1, &fb->rbo); 141 if (fb->image >= 0) 142 nvgDeleteImage(fb->ctx, fb->image); 143 fb->ctx = NULL; 144 fb->fbo = 0; 145 fb->rbo = 0; 146 fb->texture = 0; 147 fb->image = -1; 148 free(fb); 149 #else 150 NVG_NOTUSED(fb); 151 #endif 152 } 153 154 #endif // NANOVG_GL_IMPLEMENTATION