Browse Source

Merge pull request #101 from starwing/master

add external APIs to GL backend to get native Texture Id.
shared-context
Mikko Mononen 11 years ago
parent
commit
43a8dcc981
5 changed files with 161 additions and 11 deletions
  1. +30
    -1
      example/example_gl2.c
  2. +5
    -0
      src/nanovg.c
  3. +2
    -0
      src/nanovg.h
  4. +63
    -10
      src/nanovg_gl.h
  5. +61
    -0
      src/nanovg_gl_utils.h

+ 30
- 1
example/example_gl2.c View File

@@ -24,6 +24,7 @@
#include "nanovg.h"
#define NANOVG_GL2_IMPLEMENTATION
#include "nanovg_gl.h"
#include "nanovg_gl_utils.h"
#include "demo.h"
#include "perf.h"

@@ -56,8 +57,10 @@ int main()
GLFWwindow* window;
struct DemoData data;
struct NVGcontext* vg = NULL;
struct NVGLUframebuffer fb;
struct PerfGraph fps;
double prevt = 0;
int hasFBO;

if (!glfwInit()) {
printf("Failed to init GLFW.");
@@ -74,7 +77,7 @@ int main()
glfwWindowHint(GLFW_SAMPLES, 4);
#endif

window = glfwCreateWindow(1000, 600, "NanoVG", NULL, NULL);
window = glfwCreateWindow(1000, 600, "NanoVG", NULL, NULL);
// window = glfwCreateWindow(1000, 600, "NanoVG", glfwGetPrimaryMonitor(), NULL);
if (!window) {
glfwTerminate();
@@ -109,6 +112,8 @@ int main()
glfwSetTime(0);
prevt = glfwGetTime();

hasFBO = nvgluCreateFramebuffer(vg, &fb, 600, 600);

while (!glfwWindowShouldClose(window))
{
double mx, my, t, dt;
@@ -116,6 +121,20 @@ int main()
int fbWidth, fbHeight;
float pxRatio;

if (hasFBO) {
int fboWidth, fboHeight;
nvgImageSize(vg, fb.image, &fboWidth, &fboHeight);
// Draw some stull to an FBO as a test
glBindFramebuffer(GL_FRAMEBUFFER, fb.fbo);
glViewport(0, 0, fboWidth, fboHeight);
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
nvgBeginFrame(vg, fboWidth, fboHeight, pxRatio, NVG_PREMULTIPLIED_ALPHA);
renderDemo(vg, mx, my, fboWidth, fboHeight, t, blowup, &data);
nvgEndFrame(vg);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

t = glfwGetTime();
dt = t - prevt;
prevt = t;
@@ -141,6 +160,15 @@ int main()
renderDemo(vg, mx,my, winWidth,winHeight, t, blowup, &data);
renderGraph(vg, 5,5, &fps);

if (hasFBO) {
struct NVGpaint img = nvgImagePattern(vg, 0, 0, 150, 150, 0, fb.image, 0);
nvgBeginPath(vg);
nvgTranslate(vg, 540, 300);
nvgRect(vg, 0, 0, 150, 150);
nvgFillPaint(vg, img);
nvgFill(vg);
}

nvgEndFrame(vg);

if (screenshot) {
@@ -154,6 +182,7 @@ int main()

freeDemoData(vg, &data);

nvgluDeleteFramebuffer(vg, &fb);
nvgDeleteGL2(vg);

glfwTerminate();


+ 5
- 0
src/nanovg.c View File

@@ -236,6 +236,11 @@ error:
return 0;
}

struct NVGparams* nvgInternalParams(struct NVGcontext* ctx)
{
return &ctx->params;
}

void nvgDeleteInternal(struct NVGcontext* ctx)
{
if (ctx == NULL) return;


+ 2
- 0
src/nanovg.h View File

@@ -580,6 +580,8 @@ struct NVGparams {
struct NVGcontext* nvgCreateInternal(struct NVGparams* params);
void nvgDeleteInternal(struct NVGcontext* ctx);

struct NVGparams* nvgInternalParams(struct NVGcontext* ctx);

// Debug function to dump cached path data.
void nvgDebugDumpPathCache(struct NVGcontext* ctx);



+ 63
- 10
src/nanovg_gl.h View File

@@ -15,8 +15,8 @@
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#ifndef NANOVG_GL3_H
#define NANOVG_GL3_H
#ifndef NANOVG_GL_H
#define NANOVG_GL_H

#ifdef __cplusplus
extern "C" {
@@ -38,7 +38,7 @@ extern "C" {
# define NANOVG_GLES3 1
# define NANOVG_GL_IMPLEMENTATION 1
#endif

#if defined NANOVG_GL2

@@ -62,11 +62,21 @@ void nvgDeleteGLES3(struct NVGcontext* ctx);

#endif

enum NVGLtextureflags {
NVGL_TEXTURE_FLIP_Y = 0x01,
NVGL_TEXTURE_NODELETE = 0x02,
};

int nvglCreateImageFromHandle(struct NVGcontext* ctx, GLuint textureId, int flags);
GLuint nvglImageHandle(struct NVGcontext* ctx, int image);
void nvglImageFlags(struct NVGcontext* ctx, int image, int flags);


#ifdef __cplusplus
}
#endif

#endif
#endif /* NANOVG_GL_H */

#ifdef NANOVG_GL_IMPLEMENTATION

@@ -123,6 +133,7 @@ struct GLNVGtexture {
GLuint tex;
int width, height;
int type;
int flags;
};

enum GLNVGcallType {
@@ -242,7 +253,7 @@ static int glnvg__deleteTexture(struct GLNVGcontext* gl, int id)
int i;
for (i = 0; i < gl->ntextures; i++) {
if (gl->textures[i].id == id) {
if (gl->textures[i].tex != 0)
if (gl->textures[i].tex != 0 && (gl->textures[i].flags & NVGL_TEXTURE_NODELETE) == 0)
glDeleteTextures(1, &gl->textures[i].tex);
memset(&gl->textures[i], 0, sizeof(gl->textures[i]));
return 1;
@@ -707,9 +718,6 @@ static int glnvg__convertPaint(struct GLNVGcontext* gl, struct GLNVGfragUniforms
frag->innerCol = paint->innerColor;
frag->outerCol = paint->outerColor;

nvgTransformInverse(invxform, paint->xform);
glnvg__xformToMat3x4(frag->paintMat, invxform);

if (scissor->extent[0] < 0.5f || scissor->extent[1] < 0.5f) {
memset(frag->scissorMat, 0, sizeof(frag->scissorMat));
frag->scissorExt[0] = 1.0f;
@@ -724,19 +732,32 @@ static int glnvg__convertPaint(struct GLNVGcontext* gl, struct GLNVGfragUniforms
frag->scissorScale[0] = sqrtf(scissor->xform[0]*scissor->xform[0] + scissor->xform[2]*scissor->xform[2]) / fringe;
frag->scissorScale[1] = sqrtf(scissor->xform[1]*scissor->xform[1] + scissor->xform[3]*scissor->xform[3]) / fringe;
}

memcpy(frag->extent, paint->extent, sizeof(frag->extent));
frag->strokeMult = (width*0.5f + fringe*0.5f) / fringe;

if (paint->image != 0) {
tex = glnvg__findTexture(gl, paint->image);
if (tex == NULL) return 0;
if ((tex->flags & NVGL_TEXTURE_FLIP_Y) != 0) {
float flipped[6];
nvgTransformScale(flipped, 1.0f, -1.0f);
nvgTransformMultiply(flipped, paint->xform);
nvgTransformInverse(invxform, flipped);
} else {
nvgTransformInverse(invxform, paint->xform);
}
frag->type = NSVG_SHADER_FILLIMG;
frag->texType = tex->type == NVG_TEXTURE_RGBA ? 0 : 1;
} else {
frag->type = NSVG_SHADER_FILLGRAD;
frag->radius = paint->radius;
frag->feather = paint->feather;
nvgTransformInverse(invxform, paint->xform);
}

glnvg__xformToMat3x4(frag->paintMat, invxform);

return 1;
}

@@ -1226,7 +1247,7 @@ static void glnvg__renderDelete(void* uptr)
glDeleteBuffers(1, &gl->vertBuf);

for (i = 0; i < gl->ntextures; i++) {
if (gl->textures[i].tex != 0)
if (gl->textures[i].tex != 0 && (gl->textures[i].flags & NVGL_TEXTURE_NODELETE) == 0)
glDeleteTextures(1, &gl->textures[i].tex);
}
free(gl->textures);
@@ -1294,4 +1315,36 @@ void nvgDeleteGLES3(struct NVGcontext* ctx)
nvgDeleteInternal(ctx);
}

#endif
int nvglCreateImageFromHandle(struct NVGcontext* ctx, GLuint textureId, int flags)
{
struct GLNVGcontext* gl = (struct GLNVGcontext*)nvgInternalParams(ctx)->userPtr;
struct GLNVGtexture* tex = glnvg__allocTexture(gl);

if (tex == NULL) return 0;

tex->tex = textureId;
tex->type = NVG_TEXTURE_RGBA;
tex->flags = 0;
glBindTexture(GL_TEXTURE_2D, tex->tex);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &tex->width);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &tex->height);
glBindTexture(GL_TEXTURE_2D, 0);

return tex->id;
}

GLuint nvglImageHandle(struct NVGcontext* ctx, int image)
{
struct GLNVGcontext* gl = (struct GLNVGcontext*)nvgInternalParams(ctx)->userPtr;
struct GLNVGtexture* tex = glnvg__findTexture(gl, image);
return tex->tex;
}

void nvglImageFlags(struct NVGcontext* ctx, int image, int flags)
{
struct GLNVGcontext* gl = (struct GLNVGcontext*)nvgInternalParams(ctx)->userPtr;
struct GLNVGtexture* tex = glnvg__findTexture(gl, image);
tex->flags = flags;
}

#endif /* NANOVG_GL_IMPLEMENTATION */

+ 61
- 0
src/nanovg_gl_utils.h View File

@@ -0,0 +1,61 @@
#ifndef gl_utils_h
#define gl_utils_h


struct NVGLUframebuffer {
struct NVGcontext* ctx;
GLuint fbo;
GLuint rbo;
GLuint texture;
int image;
};

int nvgluCreateFramebuffer(struct NVGcontext* ctx, struct NVGLUframebuffer* fb, int w, int h);
void nvgluDeleteFramebuffer(struct NVGcontext* ctx, struct NVGLUframebuffer* fb);


#endif /* gl_utils_h */

#ifdef NANOVG_GL_IMPLEMENTATION

int nvgluCreateFramebuffer(struct NVGcontext* ctx, struct NVGLUframebuffer* fb, int w, int h) {
fb->image = nvgCreateImageRGBA(ctx, w, h, NULL);
fb->texture = nvglImageHandle(ctx, fb->image);
nvglImageFlags(ctx, fb->image, NVGL_TEXTURE_FLIP_Y);

/* frame buffer object */
glGenFramebuffers(1, &fb->fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fb->fbo);

/* render buffer object */
glGenRenderbuffers(1, &fb->rbo);
glBindRenderbuffer(GL_RENDERBUFFER, fb->rbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, w, h);

/* combine all */
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb->texture, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb->rbo);

if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
nvgluDeleteFramebuffer(ctx, fb);
return 0;
}
return 1;
}

void nvgluDeleteFramebuffer(struct NVGcontext* ctx, struct NVGLUframebuffer* fb) {
if (fb->fbo != 0)
glDeleteFramebuffers(1, &fb->fbo);
if (fb->rbo != 0)
glDeleteRenderbuffers(1, &fb->rbo);
if (fb->image >= 0)
nvgDeleteImage(ctx, fb->image);
fb->fbo = 0;
fb->rbo = 0;
fb->texture = 0;
fb->image = -1;
}


#endif /* NANOVG_GL_IMPLEMENTATION */
/* vim: set ft=c nu noet ts=4 sw=4 : */

Loading…
Cancel
Save