- Determine pixel layout at runtime instead of relying on compile-time flags

- Fix some potential null dereference bugs
This commit is contained in:
0x0203 2019-06-06 14:41:52 -04:00
parent 1dfe4ebc19
commit 4de6d284a3
4 changed files with 108 additions and 55 deletions

View File

@ -2,7 +2,7 @@
BIN = zahnrad
# Flags
CFLAGS += -std=c89 -pedantic -O2 -Wunused -DRAWFB_XRGB_8888
CFLAGS += -std=c89 -pedantic -O2 -Wunused
SRC = main.c
OBJ = $(SRC:.c=.o)

View File

@ -35,7 +35,6 @@
#include <unistd.h>
#include <time.h>
#define RAWFB_XRGB_8888
#define NK_INCLUDE_FIXED_TYPES
#define NK_INCLUDE_STANDARD_IO
#define NK_INCLUDE_STANDARD_VARARGS
@ -152,6 +151,7 @@ main(void)
XWindow xw;
struct rawfb_context *rawfb;
void *fb = NULL;
rawfb_pl pl;
unsigned char tex_scratch[512 * 512];
/* X11 */
@ -180,12 +180,12 @@ main(void)
xw.height = (unsigned int)xw.attr.height;
/* Framebuffer emulator */
status = nk_xlib_init(xw.dpy, xw.vis, xw.screen, xw.win, xw.width, xw.height, &fb);
status = nk_xlib_init(xw.dpy, xw.vis, xw.screen, xw.win, xw.width, xw.height, &fb, &pl);
if (!status || !fb)
return 0;
/* GUI */
rawfb = nk_rawfb_init(fb, tex_scratch, xw.width, xw.height, xw.width * 4);
rawfb = nk_rawfb_init(fb, tex_scratch, xw.width, xw.height, xw.width * 4, pl);
if (!rawfb) running = 0;
#ifdef INCLUDE_STYLE

View File

@ -33,11 +33,18 @@
struct rawfb_context;
typedef enum rawfb_pixel_layout {
PIXEL_LAYOUT_XRGB_8888,
PIXEL_LAYOUT_RGBX_8888,
}
rawfb_pl;
/* 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);
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 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);
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);
#endif
/*
@ -48,10 +55,10 @@ NK_API void nk_rawfb_resize_fb(struct rawfb_context *rawfb, voi
* ===============================================================
*/
#ifdef NK_RAWFB_IMPLEMENTATION
struct rawfb_image {
void *pixels;
int w, h, pitch;
rawfb_pl pl;
enum nk_font_atlas_format format;
};
struct rawfb_context {
@ -70,42 +77,54 @@ struct rawfb_context {
#endif
static unsigned int
nk_rawfb_color2int(const struct nk_color c)
nk_rawfb_color2int(const struct nk_color c, rawfb_pl pl)
{
unsigned int res = 0;
#if defined(RAWFB_RGBX_8888) && !defined(RAWFB_XRGB_8888)
res |= c.r << 24;
res |= c.g << 16;
res |= c.b << 8;
res |= c.a;
#elif defined(RAWFB_XRGB_8888) && !defined(RAWFB_RGBX_8888)
res |= c.a << 24;
res |= c.r << 16;
res |= c.g << 8;
res |= c.b << 0;
#else
#error Define one of RAWFB_RGBX_8888 , RAWFB_XRGB_8888
#endif
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 << 0;
break;
default:
perror("Unsupported pixel layout.\n");
break;
}
return (res);
}
static struct nk_color
nk_rawfb_int2color(const unsigned int i)
nk_rawfb_int2color(const unsigned int i, rawfb_pl pl)
{
struct nk_color col;
#if defined(RAWFB_RGBX_8888) && !defined(RAWFB_XRGB_8888)
col.r = (i >> 24) & 0xff;
col.g = (i >> 16) & 0xff;
col.b = (i >> 8) & 0xff;
col.a = (i >> 0) & 0xff;
#elif defined(RAWFB_XRGB_8888) && !defined(RAWFB_RGBX_8888)
col.a = (i >> 24) & 0xff;
col.r = (i >> 16) & 0xff;
col.g = (i >> 8) & 0xff;
col.b = (i >> 0) & 0xff;
#else
#error Define one of RAWFB_RGBX_8888 , RAWFB_XRGB_8888
#endif
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 >> 0) & 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 >> 0) & 0xff;
break;
default:
perror("Unsupported pixel layout.\n");
break;
}
return col;
}
@ -113,7 +132,7 @@ static void
nk_rawfb_ctx_setpixel(const struct rawfb_context *rawfb,
const short x0, const short y0, const struct nk_color col)
{
unsigned int c = nk_rawfb_color2int(col);
unsigned int c = nk_rawfb_color2int(col, rawfb->fb.pl);
unsigned char *pixels = rawfb->fb.pixels;
unsigned int *ptr;
@ -144,7 +163,7 @@ nk_rawfb_line_horizontal(const struct rawfb_context *rawfb,
n = x1 - x0;
for (i = 0; i < sizeof(c) / sizeof(c[0]); i++)
c[i] = nk_rawfb_color2int(col);
c[i] = nk_rawfb_color2int(col, rawfb->fb.pl);
while (n > 16) {
memcpy((void *)ptr, c, sizeof(c));
@ -157,7 +176,7 @@ static void
nk_rawfb_img_setpixel(const struct rawfb_image *img,
const int x0, const int y0, const struct nk_color col)
{
unsigned int c = nk_rawfb_color2int(col);
unsigned int c = nk_rawfb_color2int(col, img->pl);
unsigned char *ptr;
unsigned int *pixel;
NK_ASSERT(img);
@ -191,7 +210,7 @@ nk_rawfb_img_getpixel(const struct rawfb_image *img, const int x0, const int y0)
} else {
pixel = ptr;
pixel += x0;
col = nk_rawfb_int2color(*pixel);
col = nk_rawfb_int2color(*pixel, img->pl);
}
} return col;
}
@ -799,7 +818,7 @@ 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 unsigned int pitch, const rawfb_pl pl)
{
const void *tex;
struct rawfb_context *rawfb;
@ -815,19 +834,30 @@ nk_rawfb_init(void *fb, void *tex_mem, const unsigned int w, const unsigned int
rawfb->fb.pixels = fb;
rawfb->fb.w= w;
rawfb->fb.h = h;
rawfb->fb.pl = pl;
#if defined(RAWFB_XRGB_8888) || defined(RAWFB_RGBX_8888)
if (pl == PIXEL_LAYOUT_RGBX_8888 || pl == PIXEL_LAYOUT_XRGB_8888) {
rawfb->fb.format = NK_FONT_ATLAS_RGBA32;
rawfb->fb.pitch = pitch;
#else
#error Fixme
#endif
}
else {
perror("Unsupported pixel layout.\n");
free(rawfb);
return NULL;
}
if (0 == nk_init_default(&rawfb->ctx, 0)) {
free(rawfb);
return NULL;
}
nk_init_default(&rawfb->ctx, 0);
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);
if (!tex) return 0;
if (!tex) {
free(rawfb);
return NULL;
}
switch(rawfb->font_tex.format) {
case NK_FONT_ATLAS_ALPHA8:
@ -988,9 +1018,11 @@ nk_rawfb_drawimage(const struct rawfb_context *rawfb,
NK_API void
nk_rawfb_shutdown(struct rawfb_context *rawfb)
{
nk_free(&rawfb->ctx);
nk_memset(rawfb, 0, sizeof(struct rawfb_context));
free(rawfb);
if (rawfb) {
nk_free(&rawfb->ctx);
nk_memset(rawfb, 0, sizeof(struct rawfb_context));
free(rawfb);
}
}
NK_API void
@ -998,12 +1030,14 @@ nk_rawfb_resize_fb(struct rawfb_context *rawfb,
void *fb,
const unsigned int w,
const unsigned int h,
const unsigned int pitch)
const unsigned int pitch,
const rawfb_pl pl)
{
rawfb->fb.w = w;
rawfb->fb.h = h;
rawfb->fb.pixels = fb;
rawfb->fb.pitch = pitch;
rawfb->fb.pl = pl;
}
NK_API void

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);
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_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);
@ -71,7 +71,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)
unsigned int w, unsigned int h, void **fb, rawfb_pl *pl)
{
unsigned int depth = XDefaultDepth(dpy, screen);
xlib.dpy = dpy;
@ -134,6 +134,24 @@ 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 {
printf("Unrecognized pixel layout.\n");
return 0;
}
return 1;
}
@ -238,13 +256,14 @@ nk_xlib_handle_event(Display *dpy, int screen, Window win, XEvent *evt, struct r
unsigned int width, height;
XWindowAttributes attr;
XGetWindowAttributes(dpy, win, &attr);
rawfb_pl pl;
width = (unsigned int)attr.width;
height = (unsigned int)attr.height;
nk_xlib_shutdown();
nk_xlib_init(dpy, XDefaultVisual(dpy, screen), screen, win, width, height, &fb);
nk_rawfb_resize_fb(rawfb, fb, width, height, width * 4);
nk_xlib_init(dpy, XDefaultVisual(dpy, screen), screen, win, width, height, &fb, &pl);
nk_rawfb_resize_fb(rawfb, fb, width, height, width * 4, pl);
} else if (evt->type == KeymapNotify) {
XRefreshKeyboardMapping(&evt->xmapping);
return 1;