aboutsummaryrefslogtreecommitdiffstats
path: root/src/gdisp/gdisp_pixmap.c
diff options
context:
space:
mode:
authorinmarket <andrewh@inmarket.com.au>2015-01-13 13:50:46 +1000
committerinmarket <andrewh@inmarket.com.au>2015-01-13 13:50:46 +1000
commitef00cac45de322ba9366731809c680056b5200b1 (patch)
tree1b9fe655aa6f0142988cf9a1e6e72da9599e00a9 /src/gdisp/gdisp_pixmap.c
parenta22a32e8db12e38e47d9cbd3ec62ddd2eabbe9a5 (diff)
downloaduGFX-ef00cac45de322ba9366731809c680056b5200b1.tar.gz
uGFX-ef00cac45de322ba9366731809c680056b5200b1.tar.bz2
uGFX-ef00cac45de322ba9366731809c680056b5200b1.zip
Add support and demo for pixmaps (in memory drawing)
Diffstat (limited to 'src/gdisp/gdisp_pixmap.c')
-rw-r--r--src/gdisp/gdisp_pixmap.c223
1 files changed, 223 insertions, 0 deletions
diff --git a/src/gdisp/gdisp_pixmap.c b/src/gdisp/gdisp_pixmap.c
new file mode 100644
index 00000000..19757757
--- /dev/null
+++ b/src/gdisp/gdisp_pixmap.c
@@ -0,0 +1,223 @@
+/*
+ * 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
+
+// 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/driver.h"
+#include "src/gdriver/sys_defs.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 */