/* * 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 drivers/multiple/X/gdisp_lld.c * @brief GDISP Graphics Driver subsystem low level driver source for X. */ #include "gfx.h" #if GFX_USE_GDISP #define GDISP_LLD_DECLARATIONS #include "gdisp/lld/gdisp_lld.h" /** * 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 #ifndef GDISP_SCREEN_HEIGHT #define GDISP_SCREEN_HEIGHT 480 #endif #ifndef GDISP_SCREEN_WIDTH #define GDISP_SCREEN_WIDTH 640 #endif #if GINPUT_NEED_MOUSE /* Include mouse support code */ #include "ginput/lld/mouse.h" #endif #include #include #include #include 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) { 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 */ static DECLARE_THREAD_STACK(waXThread, 1024); static DECLARE_THREAD_FUNCTION(ThreadX, arg) { (void)arg; while(1) { gfxSleepMilliseconds(100); while(XPending(dis)) { XNextEvent(dis, &evt); ProcessEvent(); } } return 0; } static int FatalXIOError(Display *d) { (void) d; /* The window has closed */ fprintf(stderr, "GFX Window closed!\n"); exit(0); } LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) { XSizeHints *pSH; XSetWindowAttributes xa; XTextProperty WindowTitle; char * WindowTitleText; gfxThreadHandle hth; #if GFX_USE_OS_LINUX || GFX_USE_OS_OSX 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 (!(hth = gfxThreadCreate(waXThread, sizeof(waXThread), HIGH_PRIORITY, ThreadX, 0))) { fprintf(stderr, "Cannot start X Thread\n"); XCloseDisplay(dis); exit(0); } #if GFX_USE_OS_LINUX || GFX_USE_OS_OSX pthread_detach(hth); #endif gfxThreadClose(hth); /* Initialise the GDISP structure to match */ g->g.Orientation = GDISP_ROTATE_0; g->g.Powermode = powerOn; g->g.Backlight = 100; g->g.Contrast = 50; g->g.Width = GDISP_SCREEN_WIDTH; g->g.Height = GDISP_SCREEN_HEIGHT; return TRUE; } LLDSPEC void gdisp_lld_draw_pixel(GDISPDriver *g) { XColor col; col.red = RED_OF(g->p.color) << 8; col.green = GREEN_OF(g->p.color) << 8; col.blue = BLUE_OF(g->p.color) << 8; XAllocColor(dis, cmap, &col); XSetForeground(dis, gc, col.pixel); XDrawPoint(dis, pix, gc, (int)g->p.x, (int)g->p.y ); XDrawPoint(dis, win, gc, (int)g->p.x, (int)g->p.y ); XFlush(dis); } #if GDISP_HARDWARE_FILLS LLDSPEC void gdisp_lld_fill_area(GDISPDriver *g) { XColor col; col.red = RED_OF(g->p.color) << 8; col.green = GREEN_OF(g->p.color) << 8; col.blue = BLUE_OF(g->p.color) << 8; XAllocColor(dis, cmap, &col); XSetForeground(dis, gc, col.pixel); XFillRectangle(dis, pix, gc, g->p.x, g->p.y, g->p.cx, g->p.cy); XFillRectangle(dis, win, gc, g->p.x, g->p.y, g->p.cx, g->p.cy); XFlush(dis); } #endif #if 0 && GDISP_HARDWARE_BITFILLS LLDSPEC void gdisp_lld_blit_area(GDISPDriver *g) { // 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); } #endif #if GDISP_HARDWARE_PIXELREAD LLDSPEC color_t gdisp_lld_get_pixel_color(GDISPDriver *g) { XColor color; XImage *img; img = XGetImage (dis, pix, g->p.x, g->p.y, 1, 1, AllPlanes, XYPixmap); color.pixel = XGetPixel (img, 0, 0); XFree(img); XQueryColor(dis, cmap, &color); return RGB2COLOR(color.red>>8, color.green>>8, color.blue>>8); } #endif #if GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL LLDSPEC void gdisp_lld_vertical_scroll(GDISPDriver *g) { if (g->p.y1 > 0) { XCopyArea(dis, pix, pix, gc, g->p.x, g->p.y+g->p.y1, g->p.cx, g->p.cy-g->p.y1, g->p.x, g->p.y); XCopyArea(dis, pix, win, gc, g->p.x, g->p.y, g->p.cx, g->p.cy-g->p.y1, g->p.x, g->p.y); } else { XCopyArea(dis, pix, pix, gc, g->p.x, g->p.y, g->p.cx, g->p.cy+g->p.y1, g->p.x, g->p.y-g->p.y1); XCopyArea(dis, pix, win, gc, g->p.x, g->p.y-g->p.y1, g->p.cx, g->p.cy+g->p.y1, g->p.x, g->p.y-g->p.y1); } } #endif #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 */ /** @} */