aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/multiple/X/gdisp_lld.c
diff options
context:
space:
mode:
authorAndrew Hannam <andrewh@inmarket.com.au>2013-05-16 02:06:53 +1000
committerAndrew Hannam <andrewh@inmarket.com.au>2013-05-16 02:07:02 +1000
commitb5ce2405501aa693fc4c134e3425e74ba0ff7589 (patch)
treec6b939769fb773f90c2695848bfc3b0b6c55d458 /drivers/multiple/X/gdisp_lld.c
parent9ad0d079239662646bcef9b0629b48443da748e6 (diff)
downloaduGFX-b5ce2405501aa693fc4c134e3425e74ba0ff7589.tar.gz
uGFX-b5ce2405501aa693fc4c134e3425e74ba0ff7589.tar.bz2
uGFX-b5ce2405501aa693fc4c134e3425e74ba0ff7589.zip
X driver for GDISP and GINPUT_MOUSE
Diffstat (limited to 'drivers/multiple/X/gdisp_lld.c')
-rw-r--r--drivers/multiple/X/gdisp_lld.c324
1 files changed, 324 insertions, 0 deletions
diff --git a/drivers/multiple/X/gdisp_lld.c b/drivers/multiple/X/gdisp_lld.c
new file mode 100644
index 00000000..139cc420
--- /dev/null
+++ b/drivers/multiple/X/gdisp_lld.c
@@ -0,0 +1,324 @@
+/*
+ * This file is subject to the terms of the GFX License, v1.0. If a copy of
+ * the license was not distributed with this file, you can obtain one at:
+ *
+ * http://chibios-gfx.com/license.html
+ */
+
+/**
+ * @file drivers/multiple/X/gdisp_lld.c
+ * @brief GDISP Graphics Driver subsystem low level driver source for X.
+ */
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if GFX_USE_GDISP
+
+/* Our threading model - ChibiOS or POSIX */
+#ifndef GDISP_THREAD_CHIBIOS
+ #define GDISP_THREAD_CHIBIOS TRUE
+#endif
+
+/**
+ * Our color model - Default or 24 bit only.
+ *
+ * At present we don't define this as we don't need to.
+ * It may however be useful later if we implement bitblits.
+ * As this may be dead code we don't include it in gdisp/options.h
+ */
+#ifndef GDISP_FORCE_24BIT
+ #define GDISP_FORCE_24BIT FALSE
+#endif
+
+#if GINPUT_NEED_MOUSE
+ /* Include mouse support code */
+ #include "ginput/lld/mouse.h"
+#endif
+
+/* Include the emulation code for things we don't support */
+#include "gdisp/lld/emulation.c"
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <stdio.h>
+#include <stdlib.h>
+#if !GDISP_THREAD_CHIBIOS
+ #include <pthread.h>
+#endif
+
+#ifndef GDISP_SCREEN_HEIGHT
+ #define GDISP_SCREEN_HEIGHT 480
+#endif
+#ifndef GDISP_SCREEN_WIDTH
+ #define GDISP_SCREEN_WIDTH 640
+#endif
+
+Display *dis;
+int scr;
+Window win;
+Pixmap pix;
+XEvent evt;
+GC gc;
+Colormap cmap;
+XVisualInfo vis;
+int depth;
+#if GINPUT_NEED_MOUSE
+ coord_t mousex, mousey;
+ uint16_t mousebuttons;
+#endif
+
+static void ProcessEvent(void) {
+ XColor col;
+
+ switch(evt.type) {
+ case Expose:
+ XCopyArea(dis, pix, win, gc,
+ evt.xexpose.x, evt.xexpose.y,
+ evt.xexpose.width, evt.xexpose.height,
+ evt.xexpose.x, evt.xexpose.y);
+ break;
+#if GINPUT_NEED_MOUSE
+ case ButtonPress:
+ mousex = evt.xbutton.x;
+ mousey = evt.xbutton.y;
+ switch(evt.xbutton.button){
+ case 1: mousebuttons |= GINPUT_MOUSE_BTN_LEFT; break;
+ case 2: mousebuttons |= GINPUT_MOUSE_BTN_MIDDLE; break;
+ case 3: mousebuttons |= GINPUT_MOUSE_BTN_RIGHT; break;
+ case 4: mousebuttons |= GINPUT_MOUSE_BTN_4; break;
+ }
+ #if GINPUT_MOUSE_POLL_PERIOD == TIME_INFINITE
+ ginputMouseWakeup();
+ #endif
+ break;
+ case ButtonRelease:
+ mousex = evt.xbutton.x;
+ mousey = evt.xbutton.y;
+ switch(evt.xbutton.button){
+ case 1: mousebuttons &= ~GINPUT_MOUSE_BTN_LEFT; break;
+ case 2: mousebuttons &= ~GINPUT_MOUSE_BTN_MIDDLE; break;
+ case 3: mousebuttons &= ~GINPUT_MOUSE_BTN_RIGHT; break;
+ case 4: mousebuttons &= ~GINPUT_MOUSE_BTN_4; break;
+ }
+ #if GINPUT_MOUSE_POLL_PERIOD == TIME_INFINITE
+ ginputMouseWakeup();
+ #endif
+ break;
+ case MotionNotify:
+ mousex = evt.xmotion.x;
+ mousey = evt.xmotion.y;
+ #if GINPUT_MOUSE_POLL_PERIOD == TIME_INFINITE
+ ginputMouseWakeup();
+ #endif
+ break;
+#endif
+ }
+}
+
+/* this is the X11 thread which keeps track of all events */
+#if GDISP_THREAD_CHIBIOS
+ static WORKING_AREA(waXThread, 1024);
+ static msg_t ThreadX(void *arg) {
+ (void)arg;
+
+ while(1) {
+ chThdSleepMilliseconds(100);
+ while(XPending(dis)) {
+ XNextEvent(dis, &evt);
+ ProcessEvent();
+ }
+ }
+ return 0;
+ }
+#else
+ static void * ThreadX(void *arg) {
+ (void)arg;
+
+ while(1) {
+ pthread_yield(); // This could be a 100ms delay
+ while(XPending(dis)) {
+ XNextEvent(dis, &evt);
+ ProcessEvent();
+ }
+ }
+ return 0;
+ }
+#endif
+
+static int FatalXIOError(Display *d) {
+ (void) d;
+
+ /* The window has closed */
+ fprintf(stderr, "GFX Window closed!\n");
+ exit(0);
+}
+
+bool_t gdisp_lld_init(void)
+{
+ XSizeHints *pSH;
+ XSetWindowAttributes xa;
+ XTextProperty WindowTitle;
+ char * WindowTitleText;
+ #if !GDISP_THREAD_CHIBIOS
+ pthread_attr_t thattr;
+ pthread_t thid;
+ #endif
+
+ #if !GDISP_THREAD_CHIBIOS
+ XInitThreads();
+ #endif
+
+ dis = XOpenDisplay(NULL);
+ scr = DefaultScreen(dis);
+
+ #if GDISP_FORCE_24BIT
+ if (!XMatchVisualInfo(dis, scr, 24, TrueColor, &vis)) {
+ fprintf(stderr, "Your display has no TrueColor mode\n");
+ XCloseDisplay(dis);
+ return FALSE;
+ }
+ cmap = XCreateColormap(dis, RootWindow(dis, scr),
+ vis.visual, AllocNone);
+ #else
+ vis.visual = CopyFromParent;
+ vis.depth = DefaultDepth(dis, scr);
+ cmap = DefaultColormap(dis, scr);
+ #endif
+ fprintf(stderr, "Running GFX Window in %d bit color\n", vis.depth);
+
+ xa.colormap = cmap;
+ xa.border_pixel = 0xFFFFFF;
+ xa.background_pixel = 0x000000;
+
+ win = XCreateWindow(dis, RootWindow(dis, scr), 16, 16,
+ GDISP_SCREEN_WIDTH, GDISP_SCREEN_HEIGHT,
+ 0, vis.depth, InputOutput, vis.visual,
+ CWBackPixel|CWColormap|CWBorderPixel, &xa);
+ XSync(dis, TRUE);
+
+ WindowTitleText = "GFX";
+ XStringListToTextProperty(&WindowTitleText, 1, &WindowTitle);
+ XSetWMName(dis, win, &WindowTitle);
+ XSetWMIconName(dis, win, &WindowTitle);
+ XSync(dis, TRUE);
+
+ pSH = XAllocSizeHints();
+ pSH->flags = PSize | PMinSize | PMaxSize;
+ pSH->min_width = pSH->max_width = pSH->base_width = GDISP_SCREEN_WIDTH;
+ pSH->min_height = pSH->max_height = pSH->base_height = GDISP_SCREEN_HEIGHT;
+ XSetWMNormalHints(dis, win, pSH);
+ XFree(pSH);
+ XSync(dis, TRUE);
+
+ pix = XCreatePixmap(dis, win,
+ GDISP_SCREEN_WIDTH, GDISP_SCREEN_HEIGHT, vis.depth);
+ XSync(dis, TRUE);
+
+ gc = XCreateGC(dis, win, 0, 0);
+ XSetBackground(dis, gc, BlackPixel(dis, scr));
+ XSync(dis, TRUE);
+
+ XSelectInput(dis, win, StructureNotifyMask);
+ XMapWindow(dis, win);
+ do { XNextEvent(dis, &evt); } while (evt.type != MapNotify);
+
+ /* start the X11 thread */
+ XSetIOErrorHandler(FatalXIOError);
+ XSelectInput(dis, win,
+ ExposureMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask);
+
+ #if GDISP_THREAD_CHIBIOS
+ if (!chThdCreateStatic(waXThread, sizeof(waXThread), HIGHPRIO, ThreadX, 0)) {
+ #else
+ if (pthread_attr_init(&thattr)
+ || pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_DETACHED)
+ || pthread_create(&thid, &thattr, ThreadX, 0)) {
+ #endif
+ fprintf(stderr, "Cannot start X Thread\n");
+ XCloseDisplay(dis);
+ exit(0);
+ }
+
+ /* Initialise the GDISP structure to match */
+ GDISP.Orientation = GDISP_ROTATE_0;
+ GDISP.Powermode = powerOn;
+ GDISP.Backlight = 100;
+ GDISP.Contrast = 50;
+ GDISP.Width = GDISP_SCREEN_WIDTH;
+ GDISP.Height = GDISP_SCREEN_HEIGHT;
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ GDISP.clipx0 = 0;
+ GDISP.clipy0 = 0;
+ GDISP.clipx1 = GDISP.Width;
+ GDISP.clipy1 = GDISP.Height;
+ #endif
+ return TRUE;
+}
+
+void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color)
+{
+ XColor col;
+
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ // Clip pre orientation change
+ if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ #endif
+
+ col.red = RED_OF(color) << 8;
+ col.green = GREEN_OF(color) << 8;
+ col.blue = BLUE_OF(color) << 8;
+ XAllocColor(dis, cmap, &col);
+ XSetForeground(dis, gc, col.pixel);
+ XDrawPoint(dis, pix, gc, (int)x, (int)y );
+ XDrawPoint(dis, win, gc, (int)x, (int)y );
+ XFlush(dis);
+}
+
+void gdisp_lld_fill_area(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
+ XColor col;
+
+ #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+ // Clip pre orientation change
+ if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
+ if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
+ if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+ if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x;
+ if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y;
+ #endif
+
+ col.red = RED_OF(color) << 8;
+ col.green = GREEN_OF(color) << 8;
+ col.blue = BLUE_OF(color) << 8;
+ XAllocColor(dis, cmap, &col);
+ XSetForeground(dis, gc, col.pixel);
+ XFillRectangle(dis, pix, gc, x, y, cx, cy);
+ XFillRectangle(dis, win, gc, x, y, cx, cy);
+ XFlush(dis);
+}
+
+// Start of Bitblit code
+//XImage bitmap;
+//pixel_t *bits;
+// bits = malloc(vis.depth * GDISP_SCREEN_WIDTH * GDISP_SCREEN_HEIGHT);
+// bitmap = XCreateImage(dis, vis, vis.depth, ZPixmap,
+// 0, bits, GDISP_SCREEN_WIDTH, GDISP_SCREEN_HEIGHT,
+// 0, 0);
+
+#if GINPUT_NEED_MOUSE
+
+ void ginput_lld_mouse_init(void) {}
+
+ void ginput_lld_mouse_get_reading(MouseReading *pt) {
+ pt->x = mousex;
+ pt->y = mousey;
+ pt->z = (mousebuttons & GINPUT_MOUSE_BTN_LEFT) ? 100 : 0;
+ pt->buttons = mousebuttons;
+ }
+
+#endif /* GINPUT_NEED_MOUSE */
+
+#endif /* GFX_USE_GDISP */
+/** @} */
+