aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--demos/modules/gdisp/pixmaps/demo.mk3
-rw-r--r--demos/modules/gdisp/pixmaps/gfxconf.h48
-rw-r--r--demos/modules/gdisp/pixmaps/main.c83
-rw-r--r--gfxconf.example.h3
-rw-r--r--src/gdisp/driver.h125
-rw-r--r--src/gdisp/gdisp_colors.h2
-rw-r--r--src/gdisp/gdisp_gdisp.c2
-rw-r--r--src/gdisp/gdisp_pixmap.c223
-rw-r--r--src/gdisp/gdisp_pixmap.h87
-rw-r--r--src/gdisp/sys_defs.h4
-rw-r--r--src/gdisp/sys_make.mk1
-rw-r--r--src/gdisp/sys_options.h16
12 files changed, 584 insertions, 13 deletions
diff --git a/demos/modules/gdisp/pixmaps/demo.mk b/demos/modules/gdisp/pixmaps/demo.mk
new file mode 100644
index 00000000..9e4858ec
--- /dev/null
+++ b/demos/modules/gdisp/pixmaps/demo.mk
@@ -0,0 +1,3 @@
+DEMODIR = $(GFXLIB)/demos/modules/gdisp/pixmaps
+GFXINC += $(DEMODIR)
+GFXSRC += $(DEMODIR)/main.c
diff --git a/demos/modules/gdisp/pixmaps/gfxconf.h b/demos/modules/gdisp/pixmaps/gfxconf.h
new file mode 100644
index 00000000..ddd7d1ec
--- /dev/null
+++ b/demos/modules/gdisp/pixmaps/gfxconf.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012, 2013, Joel Bodenmann aka Tectu <joel@unormal.org>
+ * Copyright (c) 2012, 2013, Andrew Hannam aka inmarket
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the <organization> nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _GFXCONF_H
+#define _GFXCONF_H
+
+/* The operating system to use. One of these must be defined - preferably in your Makefile */
+//#define GFX_USE_OS_CHIBIOS FALSE
+//#define GFX_USE_OS_WIN32 FALSE
+//#define GFX_USE_OS_LINUX FALSE
+//#define GFX_USE_OS_OSX FALSE
+
+/* GFX sub-systems to turn on */
+#define GFX_USE_GDISP TRUE
+
+/* Features for the GDISP sub-system. */
+#define GDISP_NEED_VALIDATION TRUE
+#define GDISP_NEED_CLIP TRUE
+#define GDISP_NEED_PIXMAP TRUE
+
+#endif /* _GFXCONF_H */
+
diff --git a/demos/modules/gdisp/pixmaps/main.c b/demos/modules/gdisp/pixmaps/main.c
new file mode 100644
index 00000000..3adcf03f
--- /dev/null
+++ b/demos/modules/gdisp/pixmaps/main.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2012, 2013, Joel Bodenmann aka Tectu <joel@unormal.org>
+ * Copyright (c) 2012, 2013, Andrew Hannam aka inmarket
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the <organization> nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "gfx.h"
+
+#define PIXMAP_WIDTH 40
+#define PIXMAP_HEIGHT 10
+
+static GDisplay *pix;
+static pixel_t *surface;
+
+int main(void) {
+ coord_t width, height;
+ coord_t i, j;
+
+ // Initialize and clear the display
+ gfxInit();
+
+ // Get the screen size
+ width = gdispGetWidth();
+ height = gdispGetHeight();
+
+ // Create a pixmap and get a pointer to the bits
+ pix = gdispCreatePixmap(PIXMAP_WIDTH, PIXMAP_HEIGHT);
+ surface = gdispGetPixmapBits(pix);
+
+ // A pixmap can be treated either as a virtual display or as a memory framebuffer surface.
+ // We demonstrate writing to it using both methods.
+
+ // First demo drawing onto the surface directly
+ for(j = 0; j < PIXMAP_HEIGHT; j++)
+ for(i = 0; i < PIXMAP_WIDTH; i++)
+ surface[j*PIXMAP_WIDTH + i] = RGB2COLOR(0, 255-i*(256/PIXMAP_WIDTH), j*(256/PIXMAP_HEIGHT));
+
+ // Secondly, show drawing a line on it like a virtual display
+ gdispGDrawLine(pix, 0, 0, gdispGGetWidth(pix)-1, gdispGGetHeight(pix)-1, White);
+
+ i = j = 0;
+ while(TRUE) {
+ // Clear the old position
+ gdispFillArea(i, j, PIXMAP_WIDTH, PIXMAP_HEIGHT, Black);
+
+ // Change the position
+ i += PIXMAP_WIDTH/2;
+ if (i >= width - PIXMAP_WIDTH/2) {
+ i %= width - PIXMAP_WIDTH/2;
+ j = (j + PIXMAP_HEIGHT/2) % (height - PIXMAP_HEIGHT/2);
+ }
+
+ // Blit the pixmap to the real display at the new position
+ gdispBlitArea(i, j, PIXMAP_WIDTH, PIXMAP_HEIGHT, surface);
+
+ // Wait
+ gfxSleepMilliseconds(100);
+ }
+}
+
diff --git a/gfxconf.example.h b/gfxconf.example.h
index 4d18d37c..3a91d21a 100644
--- a/gfxconf.example.h
+++ b/gfxconf.example.h
@@ -104,6 +104,9 @@
// #define GDISP_NEED_IMAGE_PNG FALSE
// #define GDISP_NEED_IMAGE_ACCOUNTING FALSE
+//#define GDISP_NEED_PIXMAP FALSE
+// #define GDISP_NEED_PIXMAP_IMAGE FALSE
+
//#define GDISP_DEFAULT_ORIENTATION GDISP_ROTATE_LANDSCAPE // If not defined the native hardware orientation is used.
//#define GDISP_LINEBUF_SIZE 128
//#define GDISP_STARTUP_COLOR Black
diff --git a/src/gdisp/driver.h b/src/gdisp/driver.h
index 8d22135d..db626a69 100644
--- a/src/gdisp/driver.h
+++ b/src/gdisp/driver.h
@@ -21,17 +21,47 @@
// Include the GDRIVER infrastructure
#include "src/gdriver/sys_defs.h"
+// Are we currently compiling the driver itself?
+#if defined(GDISP_DRIVER_VMT)
+ #define IN_DRIVER TRUE
+#else
+ #define IN_DRIVER FALSE
+#endif
+
+// Is this a multiple driver situation?
+#if defined(GDISP_DRIVER_LIST)
+ #define IS_MULTIPLE TRUE
+#else
+ #define IS_MULTIPLE FALSE
+#endif
+
+// Do we need to use VMT calling rather than direct calls to the driver?
+#if IS_MULTIPLE || GDISP_NEED_PIXMAP
+ #define USE_VMT TRUE
+#else
+ #define USE_VMT FALSE
+#endif
+
+// Are we in the pixmap virtual driver
+#ifndef IN_PIXMAP_DRIVER
+ #define IN_PIXMAP_DRIVER FALSE
+#endif
+
+//------------------------------------------------------------------------------------------------------------
+
// Our special auto-detect hardware code which uses the VMT.
#define HARDWARE_AUTODETECT 2
-#if defined(GDISP_DRIVER_LIST) && !defined(GDISP_DRIVER_VMT)
+#if USE_VMT && !IN_DRIVER
// Multiple controllers the default is to hardware detect
#define HARDWARE_DEFAULT HARDWARE_AUTODETECT
#else
- // The default is to call the routines directly
+ // The default is not to include code functions that aren't needed
#define HARDWARE_DEFAULT FALSE
#endif
+//------------------------------------------------------------------------------------------------------------
+
/**
* @name GDISP hardware accelerated support
* @{
@@ -191,9 +221,66 @@
#endif
/** @} */
-/*===========================================================================*/
-/* External declarations. */
-/*===========================================================================*/
+//------------------------------------------------------------------------------------------------------------
+
+// For pixmaps certain routines MUST not be FALSE as they are needed for pixmap drawing
+// Similarly some routines MUST not be TRUE as pixmap's don't provide them.
+#if GDISP_NEED_PIXMAP && !IN_DRIVER
+ #if !GDISP_HARDWARE_DEINIT
+ #undef GDISP_HARDWARE_DEINIT
+ #define GDISP_HARDWARE_DEINIT HARDWARE_AUTODETECT
+ #endif
+ #if !GDISP_HARDWARE_DRAWPIXEL
+ #undef GDISP_HARDWARE_DRAWPIXEL
+ #define GDISP_HARDWARE_DRAWPIXEL HARDWARE_AUTODETECT
+ #endif
+ #if !GDISP_HARDWARE_PIXELREAD
+ #undef GDISP_HARDWARE_PIXELREAD
+ #define GDISP_HARDWARE_PIXELREAD HARDWARE_AUTODETECT
+ #endif
+ #if !GDISP_HARDWARE_CONTROL
+ #undef GDISP_HARDWARE_CONTROL
+ #define GDISP_HARDWARE_CONTROL HARDWARE_AUTODETECT
+ #endif
+ #if GDISP_HARDWARE_FLUSH == TRUE
+ #undef GDISP_HARDWARE_FLUSH
+ #define GDISP_HARDWARE_FLUSH HARDWARE_AUTODETECT
+ #endif
+ #if GDISP_HARDWARE_STREAM_WRITE == TRUE
+ #undef GDISP_HARDWARE_STREAM_WRITE
+ #define GDISP_HARDWARE_STREAM_WRITE HARDWARE_AUTODETECT
+ #endif
+ #if GDISP_HARDWARE_STREAM_READ == TRUE
+ #undef GDISP_HARDWARE_STREAM_READ
+ #define GDISP_HARDWARE_STREAM_READ HARDWARE_AUTODETECT
+ #endif
+ #if GDISP_HARDWARE_CLEARS == TRUE
+ #undef GDISP_HARDWARE_CLEARS
+ #define GDISP_HARDWARE_CLEARS HARDWARE_AUTODETECT
+ #endif
+ #if GDISP_HARDWARE_FILLS == TRUE
+ #undef GDISP_HARDWARE_FILLS
+ #define GDISP_HARDWARE_FILLS HARDWARE_AUTODETECT
+ #endif
+ #if GDISP_HARDWARE_BITFILLS == TRUE
+ #undef GDISP_HARDWARE_BITFILLS
+ #define GDISP_HARDWARE_BITFILLS HARDWARE_AUTODETECT
+ #endif
+ #if GDISP_HARDWARE_SCROLL == TRUE
+ #undef GDISP_HARDWARE_SCROLL
+ #define GDISP_HARDWARE_SCROLL HARDWARE_AUTODETECT
+ #endif
+ #if GDISP_HARDWARE_QUERY == TRUE
+ #undef GDISP_HARDWARE_QUERY
+ #define GDISP_HARDWARE_QUERY HARDWARE_AUTODETECT
+ #endif
+ #if GDISP_HARDWARE_CLIP == TRUE
+ #undef GDISP_HARDWARE_CLIP
+ #define GDISP_HARDWARE_CLIP HARDWARE_AUTODETECT
+ #endif
+#endif
+
+//------------------------------------------------------------------------------------------------------------
/* Verify information for packed pixels and define a non-packed pixel macro */
#if !GDISP_PACKED_PIXELS
@@ -224,6 +311,8 @@
void gdispPackPixels(const pixel_t *buf, coord_t cx, coord_t x, coord_t y, color_t color);
#endif
+//------------------------------------------------------------------------------------------------------------
+
struct GDisplay {
struct GDriver d; // This must be the first element
#define gvmt(g) ((const GDISPVMT const *)((g)->d.vmt)) // For ease of access to the vmt member
@@ -309,14 +398,16 @@ typedef struct GDISPVMT {
void (*flush)(GDisplay *g); // Uses no parameters
} GDISPVMT;
+//------------------------------------------------------------------------------------------------------------
+
// Do we need function definitions or macro's (via the VMT)
-#if !defined(GDISP_DRIVER_LIST) || defined(GDISP_DRIVER_VMT) || defined(__DOXYGEN__)
+#if IN_DRIVER || !USE_VMT || defined(__DOXYGEN__)
#ifdef __cplusplus
extern "C" {
#endif
// Should the driver routines should be static or not
- #if defined(GDISP_DRIVER_LIST)
+ #if USE_VMT
#define LLDSPEC static
#else
#define LLDSPEC
@@ -325,8 +416,8 @@ typedef struct GDISPVMT {
/**
* @brief Initialize the driver.
* @return TRUE if successful.
- * @param[in] g The driver structure
- * @param[out] g->g The driver must fill in the GDISPControl structure
+ * @param[in] g The driver structure
+ * @param[out] g->g The driver must fill in the GDISPControl structure
*/
LLDSPEC bool_t gdisp_lld_init(GDisplay *g);
@@ -602,16 +693,18 @@ typedef struct GDISPVMT {
#define gdisp_lld_set_clip(g) gvmt(g)->setclip(g)
#endif
+//------------------------------------------------------------------------------------------------------------
+
// If compiling the driver then build the VMT and set the low level driver color macros.
-#ifdef GDISP_DRIVER_VMT
+#if IN_DRIVER
// Make sure the driver has a valid model
#if !GDISP_HARDWARE_STREAM_WRITE && !GDISP_HARDWARE_DRAWPIXEL
#error "GDISP Driver: Either GDISP_HARDWARE_STREAM_WRITE or GDISP_HARDWARE_DRAWPIXEL must be TRUE"
#endif
- // If we are not using multiple displays then hard-code the VMT name
- #if !defined(GDISP_DRIVER_LIST)
+ // If we are not using multiple displays then hard-code the VMT name (except for the pixmap driver)
+ #if !IS_MULTIPLE && !IN_PIXMAP_DRIVER
#undef GDISP_DRIVER_VMT
#define GDISP_DRIVER_VMT GDISPVMT_OnlyOne
#endif
@@ -707,6 +800,8 @@ typedef struct GDISPVMT {
#endif
}};
+ //--------------------------------------------------------------------------------------------------------
+
/* Low level driver pixel format information */
//-------------------------
// True-Color color system
@@ -956,6 +1051,12 @@ typedef struct GDISPVMT {
#endif
+//------------------------------------------------------------------------------------------------------------
+
+#undef IN_PIXMAP_DRIVER
+#undef IS_MULTIPLE
+#undef IN_DRIVER
+#undef USE_VMT
#endif /* GFX_USE_GDISP */
#endif /* _GDISP_LLD_H */
diff --git a/src/gdisp/gdisp_colors.h b/src/gdisp/gdisp_colors.h
index addd9fa9..6f89b3c4 100644
--- a/src/gdisp/gdisp_colors.h
+++ b/src/gdisp/gdisp_colors.h
@@ -23,6 +23,8 @@
#if GFX_USE_GDISP || defined(__DOXYGEN__)
+typedef uint16_t colorformat;
+
/**
* @name Color system masks
*
diff --git a/src/gdisp/gdisp_gdisp.c b/src/gdisp/gdisp_gdisp.c
index 99861571..74fb0883 100644
--- a/src/gdisp/gdisp_gdisp.c
+++ b/src/gdisp/gdisp_gdisp.c
@@ -625,12 +625,12 @@ void _gdispDeinit(void)
bool_t _gdispInitDriver(GDriver *g, void *param, unsigned driverinstance, unsigned systeminstance) {
#define gd ((GDisplay *)g)
bool_t ret;
- (void) param;
// Intialise fields
gd->systemdisplay = systeminstance;
gd->controllerdisplay = driverinstance;
gd->flags = 0;
+ gd->priv = param;
MUTEX_INIT(gd);
// Call the driver init
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 */
diff --git a/src/gdisp/gdisp_pixmap.h b/src/gdisp/gdisp_pixmap.h
new file mode 100644
index 00000000..e933a550
--- /dev/null
+++ b/src/gdisp/gdisp_pixmap.h
@@ -0,0 +1,87 @@
+/*
+ * 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
+ */
+
+/**
+ * @file src/gdisp/gdisp_pixmap.h
+ * @brief GDISP image header file.
+ *
+ * @defgroup Pixmap Pixmap
+ * @ingroup GDISP
+ *
+ * @note A Pixmap is an off-screen virtual display that can be drawn to just like any other
+ * display. It can then be copied to a real display using the standard gdispGBlitArea() call.
+ * @pre GDISP_NEED_PIXMAP must be TRUE in your gfxconf.h
+ * @{
+ */
+
+#ifndef _GDISP_PIXMAP_H
+#define _GDISP_PIXMAP_H
+
+#if (GFX_USE_GDISP && GDISP_NEED_PIXMAP) || defined(__DOXYGEN__)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ /**
+ * @brief Create an off-screen pixmap that can be drawn to just like a normal display
+ *
+ * @param[in] width The width of the pixmap to be created
+ * @param[in] height The height of the pixmap to be created
+ *
+ * @note Once created, an off-screen pixmap can be drawn on using the standard gdispGxxxx calls.
+ * @note It must be destroyed using @p gdispDeleteOffscreenPixmap
+ * @note Because the RAM for the display area is allocated, on small micros only very small pixmaps should be considered.
+ * For example a 100x100 at 16 bits per pixel would be 20K of RAM (plus some overheads).
+ */
+ GDisplay *gdispCreatePixmap(coord_t width, coord_t height);
+
+ /**
+ * @brief Destroy an off-screen pixmap
+ *
+ * @param[in] g The pixmap virtual display to delete
+ *
+ * @note If a normal display is passed to this routine, it will be ignored.
+ */
+ void gdispDeletePixmap(GDisplay *g);
+
+ /**
+ * @brief Get a pointer to the pixels of the display surface.
+ * @return The pointer to the pixmap display surface or NULL if this display is not a pixmap.
+ *
+ * @param[in] g The pixmap virtual display
+ *
+ * @note The pointer returned can be used for calls to @p gdispGBlitArea() or can be read or written to directly
+ * by the application code. For any one particular pixmap the pointer will not change over the life of the pixmap
+ * (although different pixmaps will have different pixel pointers). Once a pixmap is deleted, the pixel pointer
+ * should not be used by the application.
+ */
+ pixel_t *gdispGetPixmapBits(GDisplay *g);
+
+ #if GDISP_NEED_PIXMAP_IMAGE || defined(__DOXYGEN__)
+ /**
+ * @brief Get a pointer to a native format gdispImage.
+ * @return A pointer to a NATIVE format gdispImage in memory or NULL if this display is not a pixmap.
+ * @pre GDISP_NEED_PIXAMP_IMAGE must be TRUE in your gfxconf.h
+ *
+ * @param[in] g The pixmap virtual display
+ *
+ * @note The pointer returned can be passed to @p gdispImageOpenMemory() or to @gfileOpenMemory().
+ * @note If you are just wanting to copy to a real display it is more efficient to use @p gdispGetPixmapBits() and @p gdispGBlitArea().
+ * @note Like @p gdispGetPixmapBits(), the pointer returned is valid for the life of the pixmap.
+ */
+ void *gdispGetPixmapMemoryImage(GDisplay *g);
+ #endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GFX_USE_GDISP && GDISP_NEED_PIXMAP */
+#endif /* _GDISP_PIXMAP_H */
+/** @} */
+
diff --git a/src/gdisp/sys_defs.h b/src/gdisp/sys_defs.h
index f952e41b..6b77bab8 100644
--- a/src/gdisp/sys_defs.h
+++ b/src/gdisp/sys_defs.h
@@ -1113,6 +1113,10 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
#if GDISP_NEED_IMAGE || defined(__DOXYGEN__)
#include "gdisp_image.h"
#endif
+#if GDISP_NEED_PIXMAP || defined(__DOXYGEN__)
+ #include "gdisp_pixmap.h"
+#endif
+
#endif /* GFX_USE_GDISP */
diff --git a/src/gdisp/sys_make.mk b/src/gdisp/sys_make.mk
index cbce4224..34710597 100644
--- a/src/gdisp/sys_make.mk
+++ b/src/gdisp/sys_make.mk
@@ -1,5 +1,6 @@
GFXSRC += $(GFXLIB)/src/gdisp/gdisp_gdisp.c \
$(GFXLIB)/src/gdisp/gdisp_fonts.c \
+ $(GFXLIB)/src/gdisp/gdisp_pixmap.c \
$(GFXLIB)/src/gdisp/gdisp_image.c \
$(GFXLIB)/src/gdisp/gdisp_image_native.c \
$(GFXLIB)/src/gdisp/gdisp_image_gif.c \
diff --git a/src/gdisp/sys_options.h b/src/gdisp/sys_options.h
index 98be1a46..ebb054e1 100644
--- a/src/gdisp/sys_options.h
+++ b/src/gdisp/sys_options.h
@@ -177,6 +177,13 @@
#ifndef GDISP_NEED_IMAGE
#define GDISP_NEED_IMAGE FALSE
#endif
+ /**
+ * @brief Is the image interface required.
+ * @details Defaults to FALSE
+ */
+ #ifndef GDISP_NEED_PIXMAP
+ #define GDISP_NEED_PIXMAP FALSE
+ #endif
/**
* @}
*
@@ -340,6 +347,15 @@
/**
* @}
*
+ * @name GDISP Pixmap Options
+ * @{
+ */
+ #ifndef GDISP_NEED_PIXMAP_IMAGE
+ #define GDISP_NEED_PIXMAP_IMAGE FALSE
+ #endif
+/**
+ * @}
+ *
* @name GDISP Optional Low Level Driver Defines
* @{
*/