Merge pull request #638 from ccawley2011/rawfb-pixel-format

Support arbitrary pixel formats with more rawfb demos
This commit is contained in:
Rob Loach 2024-05-23 13:32:31 -04:00 committed by GitHub
commit 6286f22996
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 114 additions and 1207 deletions

View File

@ -28,23 +28,23 @@
*
* ===============================================================
*/
#ifndef NK_RAWFB_H_
#define NK_RAWFB_H_
struct rawfb_context;
typedef enum rawfb_pixel_layout {
PIXEL_LAYOUT_XRGB_8888,
PIXEL_LAYOUT_RGBX_8888
}
rawfb_pl;
struct rawfb_pl {
unsigned char bytesPerPixel;
unsigned char rshift, gshift, bshift, ashift;
unsigned char rloss, gloss, bloss, aloss;
};
/* All functions are thread-safe */
NK_API struct rawfb_context *nk_rawfb_init(void *fb, void *tex_mem, const unsigned int w, const unsigned int h, const unsigned int pitch, const rawfb_pl pl);
NK_API struct rawfb_context *nk_rawfb_init(void *fb, void *tex_mem, const unsigned int w, const unsigned int h, const unsigned int pitch, const struct rawfb_pl pl);
NK_API void nk_rawfb_render(const struct rawfb_context *rawfb, const struct nk_color clear, const unsigned char enable_clear);
NK_API void nk_rawfb_shutdown(struct rawfb_context *rawfb);
NK_API void nk_rawfb_resize_fb(struct rawfb_context *rawfb, void *fb, const unsigned int w, const unsigned int h, const unsigned int pitch, const rawfb_pl pl);
NK_API void nk_rawfb_resize_fb(struct rawfb_context *rawfb, void *fb, const unsigned int w, const unsigned int h, const unsigned int pitch, const struct rawfb_pl pl);
#endif
/*
@ -62,8 +62,7 @@ NK_API void nk_rawfb_resize_fb(struct rawfb_context *rawfb, voi
struct rawfb_image {
void *pixels;
int w, h, pitch;
rawfb_pl pl;
enum nk_font_atlas_format format;
struct rawfb_pl pl;
};
struct rawfb_context {
struct nk_context ctx;
@ -81,54 +80,28 @@ struct rawfb_context {
#endif
static unsigned int
nk_rawfb_color2int(const struct nk_color c, rawfb_pl pl)
nk_rawfb_color2int(const struct nk_color c, const struct rawfb_pl pl)
{
unsigned int res = 0;
switch (pl) {
case PIXEL_LAYOUT_RGBX_8888:
res |= c.r << 24;
res |= c.g << 16;
res |= c.b << 8;
res |= c.a;
break;
case PIXEL_LAYOUT_XRGB_8888:
res |= c.a << 24;
res |= c.r << 16;
res |= c.g << 8;
res |= c.b;
break;
res |= (c.r >> pl.rloss) << pl.rshift;
res |= (c.g >> pl.gloss) << pl.gshift;
res |= (c.b >> pl.bloss) << pl.bshift;
res |= (c.a >> pl.aloss) << pl.ashift;
default:
perror("nk_rawfb_color2int(): Unsupported pixel layout.\n");
break;
}
return (res);
}
static struct nk_color
nk_rawfb_int2color(const unsigned int i, rawfb_pl pl)
nk_rawfb_int2color(const unsigned int i, const struct rawfb_pl pl)
{
struct nk_color col = {0,0,0,0};
switch (pl) {
case PIXEL_LAYOUT_RGBX_8888:
col.r = (i >> 24) & 0xff;
col.g = (i >> 16) & 0xff;
col.b = (i >> 8) & 0xff;
col.a = i & 0xff;
break;
case PIXEL_LAYOUT_XRGB_8888:
col.a = (i >> 24) & 0xff;
col.r = (i >> 16) & 0xff;
col.g = (i >> 8) & 0xff;
col.b = i & 0xff;
break;
col.r = (pl.rloss == 8) ? 0xff : ((i >> pl.rshift) << pl.rloss) & 0xff;
col.g = (pl.gloss == 8) ? 0xff : ((i >> pl.gshift) << pl.gloss) & 0xff;
col.b = (pl.bloss == 8) ? 0xff : ((i >> pl.bshift) << pl.bloss) & 0xff;
col.a = (pl.aloss == 8) ? 0xff : ((i >> pl.ashift) << pl.aloss) & 0xff;
default:
perror("nk_rawfb_int2color(): Unsupported pixel layout.\n");
break;
}
return col;
}
@ -138,14 +111,20 @@ nk_rawfb_ctx_setpixel(const struct rawfb_context *rawfb,
{
unsigned int c = nk_rawfb_color2int(col, rawfb->fb.pl);
unsigned char *pixels = rawfb->fb.pixels;
unsigned int *ptr;
pixels += y0 * rawfb->fb.pitch;
ptr = (unsigned int *)pixels + x0;
if (y0 < rawfb->scissors.h && y0 >= rawfb->scissors.y &&
x0 >= rawfb->scissors.x && x0 < rawfb->scissors.w)
*ptr = c;
x0 >= rawfb->scissors.x && x0 < rawfb->scissors.w) {
if (rawfb->fb.pl.bytesPerPixel == sizeof(unsigned int)) {
*((unsigned int *)pixels + x0) = c;
} else if (rawfb->fb.pl.bytesPerPixel == sizeof(unsigned short)) {
*((unsigned short *)pixels + x0) = c;
} else {
*((unsigned char *)pixels + x0) = c;
}
}
}
static void
@ -156,22 +135,29 @@ nk_rawfb_line_horizontal(const struct rawfb_context *rawfb,
* It does not check for scissors or image borders.
* The caller has to make sure it does no exceed bounds. */
unsigned int i, n;
unsigned int c[16];
unsigned char c[16 * 4];
unsigned char *pixels = rawfb->fb.pixels;
unsigned int *ptr;
unsigned int bpp = rawfb->fb.pl.bytesPerPixel;
pixels += y * rawfb->fb.pitch;
ptr = (unsigned int *)pixels + x0;
pixels += (y * rawfb->fb.pitch) + (x0 * bpp);
n = x1 - x0;
for (i = 0; i < sizeof(c) / sizeof(c[0]); i++)
c[i] = nk_rawfb_color2int(col, rawfb->fb.pl);
n = (x1 - x0) * bpp;
if (bpp == sizeof(unsigned int)) {
for (i = 0; i < sizeof(c) / bpp; i++)
((unsigned int *)c)[i] = nk_rawfb_color2int(col, rawfb->fb.pl);
} else if (bpp == sizeof(unsigned short)) {
for (i = 0; i < sizeof(c) / bpp; i++)
((unsigned short *)c)[i] = nk_rawfb_color2int(col, rawfb->fb.pl);
} else {
for (i = 0; i < sizeof(c) / bpp; i++)
((unsigned char *)c)[i] = nk_rawfb_color2int(col, rawfb->fb.pl);
}
while (n > 16) {
memcpy((void *)ptr, c, sizeof(c));
n -= 16; ptr += 16;
while (n > sizeof(c)) {
memcpy((void*)pixels, c, sizeof(c));
n -= sizeof(c); pixels += sizeof(c);
} for (i = 0; i < n; i++)
ptr[i] = c[i];
pixels[i] = c[i];
}
static void
@ -180,16 +166,16 @@ nk_rawfb_img_setpixel(const struct rawfb_image *img,
{
unsigned int c = nk_rawfb_color2int(col, img->pl);
unsigned char *ptr;
unsigned int *pixel;
NK_ASSERT(img);
if (y0 < img->h && y0 >= 0 && x0 >= 0 && x0 < img->w) {
ptr = (unsigned char *)img->pixels + (img->pitch * y0);
pixel = (unsigned int *)ptr;
if (img->format == NK_FONT_ATLAS_ALPHA8) {
ptr[x0] = col.a;
if (img->pl.bytesPerPixel == sizeof(unsigned int)) {
((unsigned int *)ptr)[x0] = c;
} else if (img->pl.bytesPerPixel == sizeof(unsigned short)) {
((unsigned short *)ptr)[x0] = c;
} else {
pixel[x0] = c;
((unsigned char *)ptr)[x0] = c;
}
}
}
@ -204,12 +190,15 @@ nk_rawfb_img_getpixel(const struct rawfb_image *img, const int x0, const int y0)
if (y0 < img->h && y0 >= 0 && x0 >= 0 && x0 < img->w) {
ptr = (unsigned char *)img->pixels + (img->pitch * y0);
if (img->format == NK_FONT_ATLAS_ALPHA8) {
col.a = ptr[x0];
col.b = col.g = col.r = 0xff;
} else {
if (img->pl.bytesPerPixel == sizeof(unsigned int)) {
pixel = ((unsigned int *)ptr)[x0];
col = nk_rawfb_int2color(pixel, img->pl);
} else if (img->pl.bytesPerPixel == sizeof(unsigned short)) {
pixel = ((unsigned short *)ptr)[x0];
col = nk_rawfb_int2color(pixel, img->pl);
} else {
pixel = ((unsigned char *)ptr)[x0];
col = nk_rawfb_int2color(pixel, img->pl);
}
} return col;
}
@ -823,33 +812,34 @@ nk_rawfb_clear(const struct rawfb_context *rawfb, const struct nk_color col)
NK_API struct rawfb_context*
nk_rawfb_init(void *fb, void *tex_mem, const unsigned int w, const unsigned int h,
const unsigned int pitch, const rawfb_pl pl)
const unsigned int pitch, const struct rawfb_pl pl)
{
const void *tex;
struct rawfb_context *rawfb;
rawfb = malloc(sizeof(struct rawfb_context));
if (!rawfb)
return NULL;
memset(rawfb, 0, sizeof(struct rawfb_context));
rawfb->font_tex.pixels = tex_mem;
rawfb->font_tex.format = NK_FONT_ATLAS_ALPHA8;
rawfb->font_tex.w = rawfb->font_tex.h = 0;
rawfb->font_tex.pl.bytesPerPixel = 1;
rawfb->font_tex.pl.rshift = 0;
rawfb->font_tex.pl.gshift = 0;
rawfb->font_tex.pl.bshift = 0;
rawfb->font_tex.pl.ashift = 0;
rawfb->font_tex.pl.rloss = 8;
rawfb->font_tex.pl.gloss = 8;
rawfb->font_tex.pl.bloss = 8;
rawfb->font_tex.pl.aloss = 0;
rawfb->font_tex.w = rawfb->font_tex.h = rawfb->font_tex.pitch = 0;
rawfb->fb.pixels = fb;
rawfb->fb.w = w;
rawfb->fb.h = h;
rawfb->fb.pitch = pitch;
rawfb->fb.pl = pl;
if (pl == PIXEL_LAYOUT_RGBX_8888 || pl == PIXEL_LAYOUT_XRGB_8888) {
rawfb->fb.format = NK_FONT_ATLAS_RGBA32;
rawfb->fb.pitch = pitch;
} else {
perror("nk_rawfb_init(): Unsupported pixel layout.\n");
free(rawfb);
return NULL;
}
if (0 == nk_init_default(&rawfb->ctx, 0)) {
free(rawfb);
return NULL;
@ -857,21 +847,13 @@ nk_rawfb_init(void *fb, void *tex_mem, const unsigned int w, const unsigned int
nk_font_atlas_init_default(&rawfb->atlas);
nk_font_atlas_begin(&rawfb->atlas);
tex = nk_font_atlas_bake(&rawfb->atlas, &rawfb->font_tex.w, &rawfb->font_tex.h, rawfb->font_tex.format);
tex = nk_font_atlas_bake(&rawfb->atlas, &rawfb->font_tex.w, &rawfb->font_tex.h, NK_FONT_ATLAS_ALPHA8);
if (!tex) {
free(rawfb);
return NULL;
}
switch(rawfb->font_tex.format) {
case NK_FONT_ATLAS_ALPHA8:
rawfb->font_tex.pitch = rawfb->font_tex.w * 1;
break;
case NK_FONT_ATLAS_RGBA32:
rawfb->font_tex.pitch = rawfb->font_tex.w * 4;
break;
};
/* Store the font texture in tex scratch memory */
rawfb->font_tex.pitch = rawfb->font_tex.w * 1;
memcpy(rawfb->font_tex.pixels, tex, rawfb->font_tex.pitch * rawfb->font_tex.h);
nk_font_atlas_end(&rawfb->atlas, nk_handle_ptr(NULL), NULL);
if (rawfb->atlas.default_font)
@ -1036,7 +1018,7 @@ nk_rawfb_resize_fb(struct rawfb_context *rawfb,
const unsigned int w,
const unsigned int h,
const unsigned int pitch,
const rawfb_pl pl)
const struct rawfb_pl pl)
{
rawfb->fb.w = w;
rawfb->fb.h = h;

View File

@ -2,7 +2,7 @@ CFLAGS=`sdl2-config --cflags --libs` -std=c89 -Wall -Wextra -pedantic -Wno-unu
.PHONY: clean
demo: main.c nuklear_sdl_rawfb.h
demo: main.c ../nuklear_rawfb.h
$(CC) -o demo *.c $(CFLAGS) -lrt -lm
clean:

View File

@ -20,7 +20,7 @@
#define NK_INCLUDE_SOFTWARE_FONT
#include "../../../nuklear.h"
#define NK_RAWFB_IMPLEMENTATION
#include "nuklear_sdl_rawfb.h"
#include "../nuklear_rawfb.h"
/* ===============================================================
*
@ -132,6 +132,8 @@ int main(int argc, char **argv)
struct nk_vec2 vec;
struct nk_rect bounds = {40,40,0,0};
struct rawfb_context *context;
struct rawfb_pl pl;
unsigned char tex_scratch[512 * 512];
SDL_DisplayMode dm;
SDL_Window *window;
@ -164,8 +166,17 @@ int main(int argc, char **argv)
surface = SDL_CreateRGBSurfaceWithFormat(0, dm.w-200, dm.h-200, 32, SDL_PIXELFORMAT_ARGB8888);
pl.bytesPerPixel = surface->format->BytesPerPixel;
pl.rshift = surface->format->Rshift;
pl.gshift = surface->format->Gshift;
pl.bshift = surface->format->Bshift;
pl.ashift = surface->format->Ashift;
pl.rloss = surface->format->Rloss;
pl.gloss = surface->format->Gloss;
pl.bloss = surface->format->Bloss;
pl.aloss = surface->format->Aloss;
context = nk_rawfb_init(surface, 13.0f);
context = nk_rawfb_init(surface->pixels, tex_scratch, surface->w, surface->h, surface->pitch, pl);
while(1)

File diff suppressed because it is too large Load Diff

View File

@ -450,6 +450,7 @@ int main ()
struct nk_wayland nk_wayland_ctx;
struct wl_registry *registry;
int running = 1;
struct rawfb_pl pl;
//1. Initialize display
nk_wayland_ctx.display = wl_display_connect (NULL);
@ -495,7 +496,17 @@ int main ()
wl_surface_attach (nk_wayland_ctx.surface, nk_wayland_ctx.front_buffer, 0, 0);
wl_surface_commit (nk_wayland_ctx.surface);
nk_rawfb_init(nk_wayland_ctx.data, nk_wayland_ctx.tex_scratch, WIDTH, HEIGHT, WIDTH*4, PIXEL_LAYOUT_XRGB_8888);
pl.bytesPerPixel = 4;
pl.ashift = 24;
pl.rshift = 16;
pl.gshift = 8;
pl.bshift = 0;
pl.aloss = 0;
pl.rloss = 0;
pl.gloss = 0;
pl.bloss = 0;
nk_rawfb_init(nk_wayland_ctx.data, nk_wayland_ctx.tex_scratch, WIDTH, HEIGHT, WIDTH*4, pl);
//4. rendering UI

View File

@ -156,7 +156,7 @@ main(void)
XWindow xw;
struct rawfb_context *rawfb;
void *fb = NULL;
rawfb_pl pl;
struct rawfb_pl pl;
unsigned char tex_scratch[512 * 512];
/* X11 */

View File

@ -35,7 +35,7 @@
#include <X11/Xlib.h>
NK_API int nk_xlib_init(Display *dpy, Visual *vis, int screen, Window root, unsigned int w, unsigned int h, void **fb, rawfb_pl *pl);
NK_API int nk_xlib_init(Display *dpy, Visual *vis, int screen, Window root, unsigned int w, unsigned int h, void **fb, struct rawfb_pl *pl);
NK_API int nk_xlib_handle_event(Display *dpy, int screen, Window win, XEvent *evt, struct rawfb_context *rawfb);
NK_API void nk_xlib_render(Drawable screen);
NK_API void nk_xlib_shutdown(void);
@ -74,7 +74,7 @@ static struct {
NK_API int
nk_xlib_init(Display *dpy, Visual *vis, int screen, Window root,
unsigned int w, unsigned int h, void **fb, rawfb_pl *pl)
unsigned int w, unsigned int h, void **fb, struct rawfb_pl *pl)
{
unsigned int depth = XDefaultDepth(dpy, screen);
xlib.dpy = dpy;
@ -138,22 +138,15 @@ nk_xlib_init(Display *dpy, Visual *vis, int screen, Window root,
xlib.gc = XDefaultGC(dpy, screen);
*fb = xlib.ximg->data;
if (xlib.ximg->red_mask == 0xff0000 &&
xlib.ximg->green_mask == 0xff00 &&
xlib.ximg->blue_mask == 0xff &&
xlib.ximg->bits_per_pixel == 32) {
*pl = PIXEL_LAYOUT_XRGB_8888;
}
else if (xlib.ximg->red_mask == 0xff000000 &&
xlib.ximg->green_mask == 0xff0000 &&
xlib.ximg->blue_mask == 0xff00 &&
xlib.ximg->bits_per_pixel == 32) {
*pl = PIXEL_LAYOUT_RGBX_8888;
}
else {
perror("nk_xlib_init(): Unrecognized pixel layout.\n");
return 0;
}
pl->bytesPerPixel = xlib.ximg->bits_per_pixel / 8;
pl->rshift = __builtin_ctzl(xlib.ximg->red_mask);
pl->gshift = __builtin_ctzl(xlib.ximg->green_mask);
pl->bshift = __builtin_ctzl(xlib.ximg->blue_mask);
pl->ashift = 0;
pl->rloss = 8 - __builtin_popcount(xlib.ximg->red_mask);
pl->gloss = 8 - __builtin_popcount(xlib.ximg->green_mask);
pl->bloss = 8 - __builtin_popcount(xlib.ximg->blue_mask);
pl->aloss = 8;
return 1;
}
@ -257,7 +250,7 @@ nk_xlib_handle_event(Display *dpy, int screen, Window win, XEvent *evt, struct r
} else if (evt->type == Expose || evt->type == ConfigureNotify) {
/* Window resize handler */
void *fb;
rawfb_pl pl;
struct rawfb_pl pl;
unsigned int width, height;
XWindowAttributes attr;
XGetWindowAttributes(dpy, win, &attr);