DPF

DISTRHO Plugin Framework
Log | Files | Refs | Submodules | README | LICENSE

commit 92dc4eeddcdbe5b5b2a646652154d222a4483f2a
parent 2c956cabead8f73af85427f9a22a01ccc51f5f26
Author: falkTX <falktx@falktx.com>
Date:   Thu, 16 Sep 2021 16:14:28 +0100

NanoVG: Allow to load raw images of any format, fix size

Signed-off-by: falkTX <falktx@falktx.com>

Diffstat:
Mdgl/NanoVG.hpp | 18++++++++++++++++--
Mdgl/src/NanoVG.cpp | 46++++++++++++++++++++++++++++++++++++++++++++--
Mdgl/src/nanovg/nanovg.c | 9+++++++--
Mdgl/src/nanovg/nanovg.h | 17++++++++++++-----
Mdgl/src/nanovg/nanovg_gl.h | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
5 files changed, 147 insertions(+), 21 deletions(-)

diff --git a/dgl/NanoVG.hpp b/dgl/NanoVG.hpp @@ -582,12 +582,26 @@ public: NanoImage::Handle createImageFromMemory(uchar* data, uint dataSize, int imageFlags); /** - Creates image from specified image data. + Creates image from specified raw format image data. + */ + NanoImage::Handle createImageFromRawMemory(uint w, uint h, const uchar* data, + ImageFlags imageFlags, ImageFormat format); + + /** + Creates image from specified raw format image data. + Overloaded function for convenience. + @see ImageFlags + */ + NanoImage::Handle createImageFromRawMemory(uint w, uint h, const uchar* data, + int imageFlags, ImageFormat format); + + /** + Creates image from specified RGBA image data. */ NanoImage::Handle createImageFromRGBA(uint w, uint h, const uchar* data, ImageFlags imageFlags); /** - Creates image from specified image data. + Creates image from specified RGBA image data. Overloaded function for convenience. @see ImageFlags */ diff --git a/dgl/src/NanoVG.cpp b/dgl/src/NanoVG.cpp @@ -215,6 +215,7 @@ NanoImage& NanoImage::operator=(const Handle& handle) fHandle.context = handle.context; fHandle.imageId = handle.imageId; + _updateSize(); return *this; } @@ -631,6 +632,45 @@ NanoImage::Handle NanoVG::createImageFromMemory(uchar* data, uint dataSize, int return NanoImage::Handle(fContext, nvgCreateImageMem(fContext, imageFlags, data,static_cast<int>(dataSize))); } +NanoImage::Handle NanoVG::createImageFromRawMemory(uint w, uint h, const uchar* data, + ImageFlags imageFlags, ImageFormat format) +{ + return createImageFromRawMemory(w, h, data, static_cast<int>(imageFlags), format); +} + +NanoImage::Handle NanoVG::createImageFromRawMemory(uint w, uint h, const uchar* data, + int imageFlags, ImageFormat format) +{ + if (fContext == nullptr) return NanoImage::Handle(); + DISTRHO_SAFE_ASSERT_RETURN(data != nullptr, NanoImage::Handle()); + + NVGtexture nvgformat; + switch (format) + { + case kImageFormatGrayscale: + nvgformat = NVG_TEXTURE_ALPHA; + break; + case kImageFormatBGR: + nvgformat = NVG_TEXTURE_BGR; + break; + case kImageFormatBGRA: + nvgformat = NVG_TEXTURE_BGRA; + break; + case kImageFormatRGB: + nvgformat = NVG_TEXTURE_RGB; + break; + case kImageFormatRGBA: + nvgformat = NVG_TEXTURE_RGBA; + break; + default: + return NanoImage::Handle(); + } + + return NanoImage::Handle(fContext, nvgCreateImageRaw(fContext, + static_cast<int>(w), + static_cast<int>(h), imageFlags, nvgformat, data)); +} + NanoImage::Handle NanoVG::createImageFromRGBA(uint w, uint h, const uchar* data, ImageFlags imageFlags) { return createImageFromRGBA(w, h, data, static_cast<int>(imageFlags)); @@ -646,12 +686,14 @@ NanoImage::Handle NanoVG::createImageFromRGBA(uint w, uint h, const uchar* data, static_cast<int>(h), imageFlags, data)); } -NanoImage::Handle NanoVG::createImageFromTextureHandle(GLuint textureId, uint w, uint h, ImageFlags imageFlags, bool deleteTexture) +NanoImage::Handle NanoVG::createImageFromTextureHandle(GLuint textureId, uint w, uint h, + ImageFlags imageFlags, bool deleteTexture) { return createImageFromTextureHandle(textureId, w, h, static_cast<int>(imageFlags), deleteTexture); } -NanoImage::Handle NanoVG::createImageFromTextureHandle(GLuint textureId, uint w, uint h, int imageFlags, bool deleteTexture) +NanoImage::Handle NanoVG::createImageFromTextureHandle(GLuint textureId, uint w, uint h, + int imageFlags, bool deleteTexture) { if (fContext == nullptr) return NanoImage::Handle(); DISTRHO_SAFE_ASSERT_RETURN(textureId != 0, NanoImage::Handle()); diff --git a/dgl/src/nanovg/nanovg.c b/dgl/src/nanovg/nanovg.c @@ -817,9 +817,14 @@ int nvgCreateImageMem(NVGcontext* ctx, int imageFlags, unsigned char* data, int return image; } +int nvgCreateImageRaw(NVGcontext* ctx, int w, int h, int imageFlags, NVGtexture format, const unsigned char* data) +{ + return ctx->params.renderCreateTexture(ctx->params.userPtr, format, w, h, imageFlags, data); +} + int nvgCreateImageRGBA(NVGcontext* ctx, int w, int h, int imageFlags, const unsigned char* data) { - return ctx->params.renderCreateTexture(ctx->params.userPtr, NVG_TEXTURE_RGBA, w, h, imageFlags, data); + return nvgCreateImageRaw(ctx, w, h, imageFlags, NVG_TEXTURE_RGBA, data); } void nvgUpdateImage(NVGcontext* ctx, int image, const unsigned char* data) @@ -948,7 +953,7 @@ NVGpaint nvgImagePattern(NVGcontext* ctx, p.image = image; - p.innerColor = p.outerColor = nvgRGBAf(1,1,1,alpha); + p.innerColor = p.outerColor = nvgRGBAf(123,244,1,alpha); return p; } diff --git a/dgl/src/nanovg/nanovg.h b/dgl/src/nanovg/nanovg.h @@ -144,6 +144,14 @@ enum NVGimageFlags { NVG_IMAGE_NEAREST = 1<<5, // Image interpolation is Nearest instead Linear }; +enum NVGtexture { + NVG_TEXTURE_ALPHA, + NVG_TEXTURE_BGR, + NVG_TEXTURE_BGRA, + NVG_TEXTURE_RGB, + NVG_TEXTURE_RGBA, +}; + // Begin drawing a new frame // Calls to nanovg drawing API should be wrapped in nvgBeginFrame() & nvgEndFrame() // nvgBeginFrame() defines the size of the window to render to in relation currently @@ -375,6 +383,10 @@ int nvgCreateImage(NVGcontext* ctx, const char* filename, int imageFlags); // Returns handle to the image. int nvgCreateImageMem(NVGcontext* ctx, int imageFlags, unsigned char* data, int ndata); +// Creates image from specified image data and texture format. +// Returns handle to the image. +int nvgCreateImageRaw(NVGcontext* ctx, int w, int h, int imageFlags, NVGtexture format, const unsigned char* data); + // Creates image from specified image data. // Returns handle to the image. int nvgCreateImageRGBA(NVGcontext* ctx, int w, int h, int imageFlags, const unsigned char* data); @@ -627,11 +639,6 @@ int nvgTextBreakLines(NVGcontext* ctx, const char* string, const char* end, floa // // Internal Render API // -enum NVGtexture { - NVG_TEXTURE_ALPHA = 0x01, - NVG_TEXTURE_RGBA = 0x02, -}; - struct NVGscissor { float xform[6]; float extent[2]; diff --git a/dgl/src/nanovg/nanovg_gl.h b/dgl/src/nanovg/nanovg_gl.h @@ -761,9 +761,21 @@ static int glnvg__renderCreateTexture(void* uptr, int type, int w, int h, int im } #endif - if (type == NVG_TEXTURE_RGBA) + switch (type) + { + case NVG_TEXTURE_BGR: + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_BGR, GL_UNSIGNED_BYTE, data); + break; + case NVG_TEXTURE_BGRA: + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, data); + break; + case NVG_TEXTURE_RGB: + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, data); + break; + case NVG_TEXTURE_RGBA: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); - else + break; + default: #if defined(NANOVG_GLES2) || defined (NANOVG_GL2) glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); #elif defined(NANOVG_GLES3) @@ -771,6 +783,8 @@ static int glnvg__renderCreateTexture(void* uptr, int type, int w, int h, int im #else glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, data); #endif + break; + } if (imageFlags & NVG_IMAGE_GENERATE_MIPMAPS) { if (imageFlags & NVG_IMAGE_NEAREST) { @@ -845,22 +859,50 @@ static int glnvg__renderUpdateTexture(void* uptr, int image, int x, int y, int w glPixelStorei(GL_UNPACK_SKIP_ROWS, y); #else // No support for all of skip, need to update a whole row at a time. - if (tex->type == NVG_TEXTURE_RGBA) + switch (tex->type) + { + case NVG_TEXTURE_BGR: + data += y*tex->width*3; + break; + case NVG_TEXTURE_BGRA: data += y*tex->width*4; - else + break; + case NVG_TEXTURE_RGB: + data += y*tex->width*3; + break; + case NVG_TEXTURE_RGBA: + data += y*tex->width*4; + break; + default: data += y*tex->width; + break; + } x = 0; w = tex->width; #endif - if (tex->type == NVG_TEXTURE_RGBA) + switch (tex->type) + { + case NVG_TEXTURE_BGR: + glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_BGR, GL_UNSIGNED_BYTE, data); + break; + case NVG_TEXTURE_BGRA: + glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_BGRA, GL_UNSIGNED_BYTE, data); + break; + case NVG_TEXTURE_RGB: + glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_RGB, GL_UNSIGNED_BYTE, data); + break; + case NVG_TEXTURE_RGBA: glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_RGBA, GL_UNSIGNED_BYTE, data); - else + break; + default: #if defined(NANOVG_GLES2) || defined(NANOVG_GL2) glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); #else glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_RED, GL_UNSIGNED_BYTE, data); #endif + break; + } glPixelStorei(GL_UNPACK_ALIGNMENT, 4); #ifndef NANOVG_GLES2 @@ -956,15 +998,31 @@ static int glnvg__convertPaint(GLNVGcontext* gl, GLNVGfragUniforms* frag, NVGpai frag->type = NSVG_SHADER_FILLIMG; #if NANOVG_GL_USE_UNIFORMBUFFER - if (tex->type == NVG_TEXTURE_RGBA) + switch (tex->type) + { + case NVG_TEXTURE_BGR: + case NVG_TEXTURE_BGRA: + case NVG_TEXTURE_RGB: + case NVG_TEXTURE_RGBA: frag->texType = (tex->flags & NVG_IMAGE_PREMULTIPLIED) ? 0 : 1; - else + break; + default: frag->texType = 2; + break; + } #else - if (tex->type == NVG_TEXTURE_RGBA) + switch (tex->type) + { + case NVG_TEXTURE_BGR: + case NVG_TEXTURE_BGRA: + case NVG_TEXTURE_RGB: + case NVG_TEXTURE_RGBA: frag->texType = (tex->flags & NVG_IMAGE_PREMULTIPLIED) ? 0.0f : 1.0f; - else + break; + default: frag->texType = 2.0f; + break; + } #endif // printf("frag->texType = %d\n", frag->texType); } else {