ugfx/src/gdisp/gdisp_pixmap.c

225 lines
6.1 KiB
C

/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#include "gfx.h"
#if GFX_USE_GDISP && GDISP_NEED_PIXMAP
// We undef everything because the system may think we are in a single controller situation
// but the pixmap supports adds another virtual display
#undef GDISP_HARDWARE_DEINIT
#undef GDISP_HARDWARE_FLUSH
#undef GDISP_HARDWARE_STREAM_WRITE
#undef GDISP_HARDWARE_STREAM_READ
#undef GDISP_HARDWARE_STREAM_POS
#undef GDISP_HARDWARE_DRAWPIXEL
#undef GDISP_HARDWARE_CLEARS
#undef GDISP_HARDWARE_FILLS
#undef GDISP_HARDWARE_BITFILLS
#undef GDISP_HARDWARE_SCROLL
#undef GDISP_HARDWARE_PIXELREAD
#undef GDISP_HARDWARE_CONTROL
#undef GDISP_HARDWARE_QUERY
#undef GDISP_HARDWARE_CLIP
#define GDISP_HARDWARE_DEINIT TRUE
#define GDISP_HARDWARE_DRAWPIXEL TRUE
#define GDISP_HARDWARE_PIXELREAD TRUE
#define GDISP_HARDWARE_CONTROL TRUE
#define IN_PIXMAP_DRIVER TRUE
#define GDISP_DRIVER_VMT GDISPVMT_pixmap
#define GDISP_DRIVER_VMT_FLAGS (GDISP_VFLG_DYNAMICONLY|GDISP_VFLG_PIXMAP)
// This pseudo driver currently only supports unpacked formats with more than 8 bits per pixel
// that is, we only support GRAY_SCALE and PALETTE with 8 bits per pixel or any unpacked TRUE_COLOR format.
#if (GDISP_LLD_PIXELFORMAT & GDISP_COLORSYSTEM_GRAYSCALE) && (GDISP_LLD_PIXELFORMAT & 0xFF) != 8
#error "GDISP Pixmap: Pixmap's do not currently support the specified GDISP_LLD_PIXELFORMAT"
#endif
#include "src/gdisp/gdisp_driver.h"
#include "src/gdriver/gdriver.h"
typedef struct pixmap {
#if GDISP_NEED_PIXMAP_IMAGE
uint8_t imghdr[8]; // This field must come just before the data member.
#endif
color_t pixels[1]; // We really want pixels[0] but some compilers don't allow that even though it is C standard.
} pixmap;
GDisplay *gdispCreatePixmap(coord_t width, coord_t height) {
GDisplay *g;
pixmap *p;
unsigned i;
// Calculate the size of the display surface in bytes
i = width*height*sizeof(color_t);
if (i < 2*sizeof(coord_t))
i = 2*sizeof(coord_t);
// Allocate the pixmap
if (!(p = gfxAlloc(i+sizeof(pixmap)-sizeof(p->pixels))))
return 0;
// Fill in the image header (if required)
#if GDISP_NEED_PIXMAP_IMAGE
p->imghdr[0] = 'N';
p->imghdr[1] = 'I';
p->imghdr[2] = (uint8_t)(width >> 8);
p->imghdr[3] = (uint8_t)width;
p->imghdr[4] = (uint8_t)(height >> 8);
p->imghdr[5] = (uint8_t)height;
p->imghdr[6] = (uint8_t)(GDISP_PIXELFORMAT >> 8);
p->imghdr[7] = (uint8_t)(GDISP_PIXELFORMAT);
#endif
// Save the width and height so the driver can retrieve it.
((coord_t *)p->pixels)[0] = width;
((coord_t *)p->pixels)[1] = height;
// Register the driver
g = (GDisplay *)gdriverRegister(&GDISPVMT_pixmap->d, p);
if (!g)
gfxFree(p);
return g;
}
void gdispDeletePixmap(GDisplay *g) {
if (gvmt(g) != GDISPVMT_pixmap)
return;
gdriverUnRegister(&g->d);
}
pixel_t *gdispGetPixmapBits(GDisplay *g) {
if (gvmt(g) != GDISPVMT_pixmap)
return 0;
return ((pixmap *)g->priv)->pixels;
}
#if GDISP_NEED_PIXMAP_IMAGE
void *gdispGetPixmapMemoryImage(GDisplay *g) {
if (gvmt(g) != GDISPVMT_pixmap)
return 0;
return ((pixmap *)g->priv)->imghdr;
}
#endif
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
// The user api function should have already allocated and initialised the pixmap
// structure and put it into the priv member during driver initialisation.
if (!g->priv)
return FALSE;
// Initialize the GDISP structure
// Width and height were saved into the start of the framebuffer.
g->g.Width = ((coord_t *)((pixmap *)g->priv)->pixels)[0];
g->g.Height = ((coord_t *)((pixmap *)g->priv)->pixels)[1];
g->g.Backlight = 100;
g->g.Contrast = 50;
g->g.Orientation = GDISP_ROTATE_0;
g->g.Powermode = powerOn;
g->board = 0;
return TRUE;
}
LLDSPEC void gdisp_lld_deinit(GDisplay *g) {
gfxFree(g->priv);
}
LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) {
unsigned pos;
#if GDISP_NEED_CONTROL
switch(g->g.Orientation) {
case GDISP_ROTATE_0:
default:
pos = g->p.y * g->g.Width + g->p.x;
break;
case GDISP_ROTATE_90:
pos = (g->g.Width-g->p.x-1) * g->g.Height + g->p.y;
break;
case GDISP_ROTATE_180:
pos = (g->g.Height-g->p.y-1) * g->g.Width + g->g.Width-g->p.x-1;
break;
case GDISP_ROTATE_270:
pos = g->p.x * g->g.Height + g->g.Height-g->p.y-1;
break;
}
#else
pos = g->p.y * g->g.Width + g->p.x;
#endif
((pixmap *)(g)->priv)->pixels[pos] = g->p.color;
}
LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay *g) {
unsigned pos;
#if GDISP_NEED_CONTROL
switch(g->g.Orientation) {
case GDISP_ROTATE_0:
default:
pos = g->p.y * g->g.Width + g->p.x;
break;
case GDISP_ROTATE_90:
pos = (g->g.Width-g->p.x-1) * g->g.Height + g->p.y;
break;
case GDISP_ROTATE_180:
pos = (g->g.Height-g->p.y-1) * g->g.Width + g->g.Width-g->p.x-1;
break;
case GDISP_ROTATE_270:
pos = g->p.x * g->g.Height + g->g.Height-g->p.y-1;
break;
}
#else
pos = g->p.y * g->g.Width + g->p.x;
#endif
return ((pixmap *)(g)->priv)->pixels[pos];
}
#if GDISP_NEED_CONTROL
LLDSPEC void gdisp_lld_control(GDisplay *g) {
switch(g->p.x) {
case GDISP_CONTROL_ORIENTATION:
if (g->g.Orientation == (orientation_t)g->p.ptr)
return;
switch((orientation_t)g->p.ptr) {
case GDISP_ROTATE_0:
case GDISP_ROTATE_180:
if (g->g.Orientation == GDISP_ROTATE_90 || g->g.Orientation == GDISP_ROTATE_270) {
coord_t tmp;
tmp = g->g.Width;
g->g.Width = g->g.Height;
g->g.Height = tmp;
}
break;
case GDISP_ROTATE_90:
case GDISP_ROTATE_270:
if (g->g.Orientation == GDISP_ROTATE_0 || g->g.Orientation == GDISP_ROTATE_180) {
coord_t tmp;
tmp = g->g.Width;
g->g.Width = g->g.Height;
g->g.Height = tmp;
}
break;
default:
return;
}
g->g.Orientation = (orientation_t)g->p.ptr;
return;
}
}
#endif
#endif /* GFX_USE_GDISP */