Implements nanovg's framebuffer helper functions. (#869)
This commit ports nanovg's helper functions for rendering stuff in framebuffer defined in `nanovg_gl_utils.h`. Also, a new `nvgState()` function is created for bgfx backend so it is possible to blend between framebuffers, which feature is long requested but not yet supported in original nanovg. The `nvgState()` function can be called between `nvgBeginFrame()` and `nvgEndFrame()`.
This commit is contained in:
parent
41ce24c078
commit
f11d954bc1
@ -548,6 +548,7 @@ namespace
|
||||
static void nvgRenderViewport(void* _userPtr, int width, int height, float devicePixelRatio)
|
||||
{
|
||||
struct GLNVGcontext* gl = (struct GLNVGcontext*)_userPtr;
|
||||
gl->state = 0;
|
||||
gl->view[0] = (float)width;
|
||||
gl->view[1] = (float)height;
|
||||
bgfx::setViewRect(gl->m_viewId, 0, 0, width * devicePixelRatio, height * devicePixelRatio);
|
||||
@ -722,11 +723,8 @@ namespace
|
||||
|
||||
memcpy(gl->tvb.data, gl->verts, gl->nverts * sizeof(struct NVGvertex) );
|
||||
|
||||
gl->state = 0
|
||||
| BGFX_STATE_RGB_WRITE
|
||||
| BGFX_STATE_ALPHA_WRITE
|
||||
;
|
||||
|
||||
if (gl->state == 0)
|
||||
{
|
||||
// if (alphaBlend == NVG_PREMULTIPLIED_ALPHA)
|
||||
// {
|
||||
// gl->state |= BGFX_STATE_BLEND_FUNC_SEPARATE(
|
||||
@ -735,11 +733,11 @@ namespace
|
||||
// );
|
||||
// }
|
||||
// else
|
||||
{
|
||||
gl->state |= BGFX_STATE_BLEND_FUNC(
|
||||
gl->state = BGFX_STATE_BLEND_FUNC(
|
||||
BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA
|
||||
);
|
||||
}
|
||||
gl->state |= BGFX_STATE_RGB_WRITE | BGFX_STATE_ALPHA_WRITE;
|
||||
|
||||
bgfx::setUniform(gl->u_viewSize, gl->view);
|
||||
|
||||
@ -1089,7 +1087,26 @@ error:
|
||||
}
|
||||
|
||||
NVGcontext* nvgCreate(int edgeaa, unsigned char _viewId) {
|
||||
return nvgCreate(edgeaa, _viewId, NULL);
|
||||
return nvgCreate(edgeaa, _viewId, NULL);
|
||||
}
|
||||
|
||||
void nvgDelete(struct NVGcontext* ctx)
|
||||
{
|
||||
nvgDeleteInternal(ctx);
|
||||
}
|
||||
|
||||
void nvgState(struct NVGcontext* ctx, uint64_t state)
|
||||
{
|
||||
struct NVGparams* params = nvgInternalParams(ctx);
|
||||
struct GLNVGcontext* gl = (struct GLNVGcontext*)params->userPtr;
|
||||
gl->state = state;
|
||||
}
|
||||
|
||||
uint8_t nvgViewId(struct NVGcontext* ctx)
|
||||
{
|
||||
struct NVGparams* params = nvgInternalParams(ctx);
|
||||
struct GLNVGcontext* gl = (struct GLNVGcontext*)params->userPtr;
|
||||
return gl->m_viewId;
|
||||
}
|
||||
|
||||
void nvgViewId(struct NVGcontext* ctx, unsigned char _viewId)
|
||||
@ -1099,7 +1116,55 @@ void nvgViewId(struct NVGcontext* ctx, unsigned char _viewId)
|
||||
gl->m_viewId = uint8_t(_viewId);
|
||||
}
|
||||
|
||||
void nvgDelete(struct NVGcontext* ctx)
|
||||
bgfx::TextureHandle nvglImageHandle(NVGcontext* ctx, int image)
|
||||
{
|
||||
nvgDeleteInternal(ctx);
|
||||
GLNVGcontext* gl = (GLNVGcontext*)nvgInternalParams(ctx)->userPtr;
|
||||
GLNVGtexture* tex = glnvg__findTexture(gl, image);
|
||||
return tex->id;
|
||||
}
|
||||
|
||||
NVGLUframebuffer* nvgluCreateFramebuffer(NVGcontext* ctx, int width,
|
||||
int height, int imageFlags) {
|
||||
NVGLUframebuffer* framebuffer = new NVGLUframebuffer;
|
||||
framebuffer->ctx = ctx;
|
||||
framebuffer->image = nvgCreateImageRGBA(ctx, width, height,
|
||||
imageFlags, NULL);
|
||||
bgfx::TextureHandle texture = nvglImageHandle(ctx, framebuffer->image);
|
||||
if (!bgfx::isValid(texture)) {
|
||||
nvgluDeleteFramebuffer(framebuffer);
|
||||
return NULL;
|
||||
}
|
||||
framebuffer->handle = bgfx::createFrameBuffer(1, &texture, false);
|
||||
if (!bgfx::isValid(framebuffer->handle))
|
||||
{
|
||||
nvgluDeleteFramebuffer(framebuffer);
|
||||
return NULL;
|
||||
}
|
||||
static uint8_t s_ViewId = 1; // may have a better way to assign new view id
|
||||
framebuffer->viewId = s_ViewId++;
|
||||
bgfx::setViewFrameBuffer(framebuffer->viewId, framebuffer->handle);
|
||||
bgfx::setViewSeq(framebuffer->viewId, true);
|
||||
return framebuffer;
|
||||
}
|
||||
|
||||
void nvgluBindFramebuffer(NVGLUframebuffer* framebuffer) {
|
||||
static NVGcontext* s_prevCtx = NULL;
|
||||
static uint8_t s_prevViewId;
|
||||
if (framebuffer != NULL) {
|
||||
s_prevCtx = framebuffer->ctx;
|
||||
s_prevViewId = nvgViewId(framebuffer->ctx);
|
||||
nvgViewId(framebuffer->ctx, framebuffer->viewId);
|
||||
} else if (s_prevCtx != NULL) {
|
||||
nvgViewId(s_prevCtx, s_prevViewId);
|
||||
}
|
||||
}
|
||||
|
||||
void nvgluDeleteFramebuffer(NVGLUframebuffer* framebuffer) {
|
||||
if (framebuffer == NULL)
|
||||
return;
|
||||
if (framebuffer->image >= 0)
|
||||
nvgDeleteImage(framebuffer->ctx, framebuffer->image);
|
||||
if (bgfx::isValid(framebuffer->handle))
|
||||
bgfx::destroyFrameBuffer(framebuffer->handle);
|
||||
delete framebuffer;
|
||||
}
|
||||
|
@ -6,13 +6,47 @@
|
||||
#ifndef NANOVG_BGFX_H_HEADER_GUARD
|
||||
#define NANOVG_BGFX_H_HEADER_GUARD
|
||||
|
||||
#include "bgfx/bgfx.h"
|
||||
|
||||
namespace bx { struct AllocatorI; }
|
||||
|
||||
struct NVGcontext;
|
||||
|
||||
struct NVGLUframebuffer {
|
||||
NVGcontext* ctx;
|
||||
bgfx::FrameBufferHandle handle;
|
||||
int image;
|
||||
uint8_t viewId;
|
||||
};
|
||||
typedef struct NVGLUframebuffer NVGLUframebuffer;
|
||||
|
||||
NVGcontext* nvgCreate(int edgeaa, unsigned char _viewId, bx::AllocatorI* _allocator);
|
||||
NVGcontext* nvgCreate(int edgeaa, unsigned char _viewId);
|
||||
void nvgViewId(struct NVGcontext* ctx, unsigned char _viewId);
|
||||
void nvgDelete(struct NVGcontext* ctx);
|
||||
void nvgState(struct NVGcontext* ctx, uint64_t state);
|
||||
uint8_t nvgViewId(struct NVGcontext* ctx);
|
||||
void nvgViewId(struct NVGcontext* ctx, unsigned char _viewId);
|
||||
|
||||
// Helper functions to create bgfx framebuffer to render to.
|
||||
// Example:
|
||||
// float scale = 2;
|
||||
// NVGLUframebuffer* fb = nvgluCreateFramebuffer(ctx, 100 * scale, 100 * scale, 0);
|
||||
// nvgluBindFramebuffer(fb);
|
||||
// nvgBeginFrame(ctx, 100, 100, scale);
|
||||
// // renders anything offscreen
|
||||
// nvgEndFrame(ctx);
|
||||
// nvgluBindFramebuffer(NULL);
|
||||
//
|
||||
// // Pastes the framebuffer rendering.
|
||||
// nvgBeginFrame(ctx, 1024, 768, scale);
|
||||
// NVGpaint paint = nvgImagePattern(ctx, 0, 0, 100, 100, 0, fb->image, 1);
|
||||
// nvgBeginPath(ctx);
|
||||
// nvgRect(ctx, 0, 0, 100, 100);
|
||||
// nvgFillPaint(ctx, paint);
|
||||
// nvgFill(ctx);
|
||||
// nvgEndFrame(ctx);
|
||||
NVGLUframebuffer* nvgluCreateFramebuffer(NVGcontext* ctx, int width, int height, int imageFlags);
|
||||
void nvgluBindFramebuffer(NVGLUframebuffer* framebuffer);
|
||||
void nvgluDeleteFramebuffer(NVGLUframebuffer* framebuffer);
|
||||
|
||||
#endif // NANOVG_BGFX_H_HEADER_GUARD
|
||||
|
Loading…
Reference in New Issue
Block a user