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:
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 {