📄 scr_x11.c
字号:
/*
* Copyright (c) 2000, 2001 Greg Haerr <greg@censoft.com>
* Copyright (c) 1999 Tony Rogvall <tony@bluetail.com>
* Rewritten to avoid multiple function calls by Greg Haerr
* Alpha blending added by Erik Hill
* (brought to life in a dark laboratory on a stormy night
* in an ancient castle by Dr. Frankenstein)
*
* X11 screen driver for Microwindows
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <assert.h>
#include "device.h"
#include "fb.h"
#include "genmem.h"
#include "genfont.h"
/* define the Casio E-15 (allow override) */
#ifdef SCREEN_E15
#ifndef SCREEN_WIDTH
#define SCREEN_WIDTH 200
#endif
#ifndef SCREEN_HEIGHT
#define SCREEN_HEIGHT 320
#endif
#ifndef SCREEN_DEPTH
#define SCREEN_DEPTH 4
#endif
#ifndef MWPIXEL_FORMAT
#define MWPIXEL_FORMAT MWPF_PALETTE
#endif
#endif
#ifndef SCREEN_WIDTH
#define SCREEN_WIDTH 200
#endif
#ifndef SCREEN_HEIGHT
#define SCREEN_HEIGHT 320
#endif
#ifndef SCREEN_DEPTH
#define SCREEN_DEPTH 4
#endif
#ifndef MWPIXEL_FORMAT
#if SCREEN_DEPTH <= 8
#define MWPIXEL_FORMAT MWPF_PALETTE
#elif SCREEN_DEPTH == 16
#define MWPIXEL_FORMAT MWPF_TRUECOLOR565
#elif SCREEN_DEPTH == 15
#define MWPIXEL_FORMAT MWPF_TRUECOLOR555
#elif SCREEN_DEPTH == 24
#define MWPIXEL_FORMAT MWPF_TRUECOLOR888
#elif SCREEN_DEPTH == 32
#define MWPIXEL_FORMAT MWPF_TRUECOLOR0888
#else
#error "bad screen depth"
#endif
#endif
/* specific x11 driver entry points*/
static PSD X11_open(PSD psd);
static void X11_close(PSD psd);
static void X11_getscreeninfo(PSD psd,PMWSCREENINFO psi);
static void X11_setpalette(PSD psd,int first,int count,MWPALENTRY *pal);
static void X11_drawpixel(PSD psd,MWCOORD x, MWCOORD y, MWPIXELVAL c);
static MWPIXELVAL X11_readpixel(PSD psd,MWCOORD x, MWCOORD y);
static void X11_drawhline(PSD psd,MWCOORD x1, MWCOORD x2, MWCOORD y, MWPIXELVAL c);
static void X11_drawvline(PSD psd,MWCOORD x, MWCOORD y1, MWCOORD y2, MWPIXELVAL c);
static void X11_fillrect(PSD psd,MWCOORD x1,MWCOORD y1,MWCOORD x2,MWCOORD y2,MWPIXELVAL c);
static void X11_blit(PSD dstpsd,MWCOORD destx,MWCOORD desty,MWCOORD w,MWCOORD h,
PSD srcpsd,MWCOORD srcx,MWCOORD srcy,long op);
static void X11_preselect(PSD psd);
SCREENDEVICE scrdev = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL,
X11_open,
X11_close,
X11_getscreeninfo,
X11_setpalette,
X11_drawpixel,
X11_readpixel,
X11_drawhline,
X11_drawvline,
X11_fillrect,
gen_fonts,
X11_blit,
X11_preselect,
NULL, /* DrawArea*/
NULL, /* SetIOPermissions*/
gen_allocatememgc,
fb_mapmemgc,
gen_freememgc,
NULL, /* StretchBlit subdriver*/
NULL /* SetPortrait*/
};
/* called from keyboard/mouse/screen */
Display* x11_dpy;
int x11_scr;
Visual* x11_vis;
Colormap x11_colormap;
Window x11_win;
GC x11_gc;
unsigned int x11_event_mask;
static int x11_colormap_installed = 0;
static SCREENDEVICE savebits; /* permanent offscreen drawing buffer*/
DEFINE_applyOpR /* define inline rop calculator*/
/* Color cache for true color lookups
** FIXME: for 24 bit i belive we could do the pixel direct but...
*/
#define COLOR_CACHE_SIZE 1001
struct color_cache {
int init; /* 1 if first use */
unsigned short r;
unsigned short g;
unsigned short b;
XColor c;
};
static struct color_cache ccache[COLOR_CACHE_SIZE];
/* color palette for color indexe */
static XColor x11_palette[256];
static int x11_pal_max = 0;
static int x11_pixtype;
static unsigned long
lookup_color(unsigned short r, unsigned short g, unsigned short b)
{
int ix = ((r << 16) + (g << 8) + b) % COLOR_CACHE_SIZE;
if (ccache[ix].init ||
(ccache[ix].r != r) || (ccache[ix].g != g) || (ccache[ix].b != b)) {
char spec[20];
XColor exact;
XColor def;
ccache[ix].init = 0;
ccache[ix].r = r;
ccache[ix].g = g;
ccache[ix].b = b;
sprintf(spec, "#%02x%02x%02x", r, g, b);
XLookupColor(x11_dpy, x11_colormap, spec, &exact, &def);
XAllocColor(x11_dpy, x11_colormap, &def);
ccache[ix].c = def;
/* DPRINTF("lookup: exact(%d,%d,%d) = %d, def(%d,%d,%d)=%d\n",
exact.red>>8, exact.green>>8, exact.blue>>8, exact.pixel,
def.red>>8, def.green>>8, def.blue>>8, def.pixel); */
}
return (unsigned long) ccache[ix].c.pixel;
}
static unsigned long
PIXELVAL_to_pixel(MWPIXELVAL c, int type)
{
assert (type == MWPIXEL_FORMAT);
#if (MWPIXEL_FORMAT == MWPF_TRUECOLOR0888) || (MWPIXEL_FORMAT == MWPF_TRUECOLOR888)
/* calc truecolor conversions directly*/
if (x11_vis->class >= TrueColor) {
switch (x11_vis->bits_per_rgb) {
case 8:
return c;
case 6:
return RGB2PIXEL565(PIXEL888RED(c), PIXEL888GREEN(c),
PIXEL888BLUE(c));
case 5:
return RGB2PIXEL555(PIXEL888RED(c), PIXEL888GREEN(c),
PIXEL888BLUE(c));
case 3:
case 2:
return RGB2PIXEL332(PIXEL888RED(c), PIXEL888GREEN(c),
PIXEL888BLUE(c));
}
}
return lookup_color(PIXEL888RED(c), PIXEL888GREEN(c), PIXEL888BLUE(c));
#endif
#if MWPIXEL_FORMAT == MWPF_TRUECOLOR565
/* calc truecolor conversions directly*/
if (x11_vis->class >= TrueColor) {
switch (x11_vis->bits_per_rgb) {
case 8:
return RGB2PIXEL888(PIXEL565RED(c)<<3,
PIXEL565GREEN(c)<<2, PIXEL565BLUE(c)<<3);
case 6:
case 5:
return c;
case 3:
case 2:
return RGB2PIXEL332(PIXEL565RED(c)<<3,
PIXEL565GREEN(c)<<2, PIXEL565BLUE(c)<<3);
}
}
return lookup_color(PIXEL565RED(c)<<3, PIXEL565GREEN(c)<<2,
PIXEL565BLUE(c)<<3);
#endif
#if MWPIXEL_FORMAT == MWPF_TRUECOLOR555
/* calc truecolor conversions directly*/
if (x11_vis->class >= TrueColor) {
switch (x11_vis->bits_per_rgb) {
case 8:
return RGB2PIXEL888(PIXEL555RED(c)<<3,
PIXEL555GREEN(c)<<3, PIXEL555BLUE(c)<<3);
case 6:
case 5:
return c;
case 3:
case 2:
return RGB2PIXEL332(PIXEL555RED(c)<<3,
PIXEL555GREEN(c)<<3, PIXEL555BLUE(c)<<3);
}
}
return lookup_color(PIXEL555RED(c)<<3, PIXEL555GREEN(c)<<3,
PIXEL555BLUE(c)<<3);
#endif
#if MWPIXEL_FORMAT == MWPF_TRUECOLOR332
/* calc truecolor conversions directly*/
if (x11_vis->class >= TrueColor) {
switch (x11_vis->bits_per_rgb) {
case 8:
return RGB2PIXEL888(PIXEL332RED(c)<<5,
PIXEL332GREEN(c)<<5, PIXEL332BLUE(c)<<6);
case 6:
return RGB2PIXEL565(PIXEL332RED(c)<<5,
PIXEL332GREEN(c)<<5, PIXEL332BLUE(c)<<6);
case 5:
return RGB2PIXEL555(PIXEL332RED(c)<<5,
PIXEL332GREEN(c)<<5, PIXEL332BLUE(c)<<6);
case 3:
case 2:
return c;
}
}
return lookup_color(PIXEL332RED(c)<<5, PIXEL332GREEN(c)<<5,
PIXEL332BLUE(c)<<6);
#endif
#if MWPIXEL_FORMAT == MWPF_PALETTE
if (c > x11_pal_max) {
DPRINTF("Warning: palette index out of range (%ld)\n", c);
return 0;
}
return x11_palette[c].pixel;
#endif
#if 0
switch(type) {
case MWPF_TRUECOLOR0888:
case MWPF_TRUECOLOR888:
r = PIXEL888RED(c);
g = PIXEL888GREEN(c);
b = PIXEL888BLUE(c);
return lookup_color(r, g, b);
case MWPF_TRUECOLOR565:
r = PIXEL565RED(c) << 3;
g = PIXEL565GREEN(c) << 2;
b = PIXEL565BLUE(c) << 3;
return lookup_color(r, g, b);
case MWPF_TRUECOLOR555:
r = PIXEL555RED(c) << 3;
g = PIXEL555GREEN(c) << 3;
b = PIXEL555BLUE(c) << 3;
return lookup_color(r, g, b);
case MWPF_TRUECOLOR332:
r = PIXEL332RED(c) << 5;
g = PIXEL332GREEN(c) << 5;
b = PIXEL332BLUE(c) << 6;
return lookup_color(r, g, b);
case MWPF_PALETTE:
if (c > x11_pal_max) {
DPRINTF("Warning: palette index out of range (%ld)\n", c);
return 0;
}
return x11_palette[c].pixel;
}
#endif
return 0;
}
static void set_color(MWPIXELVAL c)
{
static unsigned long oldc = 0x80000001;
if (c != oldc) {
oldc = c;
XSetForeground(x11_dpy, x11_gc, PIXELVAL_to_pixel(c, x11_pixtype));
}
}
static void set_mode(int new_mode)
{
static int old_mode = -1;
if (new_mode != old_mode) {
int func = GXcopy;
switch(new_mode) {
case MWMODE_COPY: func = GXcopy; break;
case MWMODE_XOR: func = GXxor; break;
case MWMODE_OR: func = GXor; break;
case MWMODE_AND: func = GXand; break;
case MWMODE_CLEAR: func = GXclear; break;
case MWMODE_SETTO1: func = GXset; break;
case MWMODE_EQUIV: func = GXequiv; break;
case MWMODE_NOR : func = GXnor; break;
case MWMODE_NAND: func = GXnand; break;
case MWMODE_INVERT: func = GXinvert; break;
case MWMODE_COPYINVERTED: func = GXcopyInverted; break;
case MWMODE_ORINVERTED: func = GXorInverted; break;
case MWMODE_ANDINVERTED: func = GXandInverted; break;
case MWMODE_ORREVERSE: func = GXorReverse; break;
case MWMODE_ANDREVERSE: func = GXandReverse; break;
case MWMODE_NOOP: func = GXnoop; break;
default: return;
}
XSetFunction(x11_dpy, x11_gc, func);
old_mode = new_mode;
}
}
#ifdef USE_EXPOSURE
static void _expose(int _x, int _y, int w, int h)
{
XImage* img;
int depth = XDefaultDepth(x11_dpy, x11_scr);
int x = _x, y = _y;
char* data;
/* allocate buffer */
if (depth >= 24)
data = malloc(w*4*h);
else if (depth > 8) /* 15, 16 */
data = malloc(w*2*h);
else /* 1,2,4,8 */
data = malloc((w*depth+7)/8 * h);
/* copy from offscreen to screen */
img = XCreateImage(x11_dpy, x11_vis, depth, ZPixmap,
0, data, w, h, 8, 0);
for (y = _y; y < h + _y; y++) {
for (x = _x; x < w + _x; x++) {
MWPIXELVAL c = savebits.ReadPixel(&savebits,x,y);
unsigned long pixel = PIXELVAL_to_pixel(c, savebits.pixtype);
XPutPixel(img, x - _x, y - _y, pixel);
}
}
XPutImage(x11_dpy, x11_win, x11_gc, img, 0, 0, _x, _y, w, h);
XDestroyImage(img);
}
#endif
/* called from mou_x11 (handels x11_event_mask events) */
void x11_handle_event(XEvent* ev)
{
static int inited = 0;
if (ev->type == ColormapNotify) {
if (ev->xcolormap.window == x11_win) {
if (ev->xcolormap.state == ColormapInstalled) {
DPRINTF("colormap uninstalled\n");
x11_colormap_installed = 0;
}
else if (ev->xcolormap.state == ColormapInstalled) {
x11_colormap_installed = 1;
DPRINTF("colormap installed\n");
}
}
}
else if (ev->type == FocusIn) {
if (!x11_colormap_installed) {
DPRINTF("setting colormap\n");
XInstallColormap(x11_dpy, x11_colormap);
inited = 1;
}
}
else if(ev->type == MappingNotify) {
DPRINTF("Refreshing keyboard mapping\n");
XRefreshKeyboardMapping(&ev->xmapping);
}
#if 0
else if (ev->type == EnterNotify) {
if(inited)
GdShowCursor(&scrdev);
} else if (ev->type == LeaveNotify) {
if(inited)
GdHideCursor(&scrdev);
}
#endif
#ifdef USE_EXPOSURE
else if(ev->type == Expose) {
_expose(ev->xexpose.x,ev->xexpose.y, ev->xexpose.width,ev->xexpose.height);
}
#endif
}
static int x11_error(Display* dpy, XErrorEvent* ev)
{
char err_string[256];
XGetErrorText(dpy, ev->error_code, err_string, 256);
EPRINTF("X11 error: %s\n", err_string);
return 0;
}
char* classnm[] = { "StaticGray", "GrayScale", "StaticColor",
"PseudoColor", "TrueColor", "DirectColor" };
static void show_visual(Visual* v)
{
char* name = ((v->class < 0) || (v->class > 5)) ? "???" :
classnm[v->class];
DPRINTF(" Visual class: %s (%d)\n", name, v->class);
DPRINTF(" id: %ld\n", v->visualid);
DPRINTF(" bits_per_rgb: %d\n", v->bits_per_rgb);
DPRINTF(" map_entries: %d\n", v->map_entries);
}
static Visual* select_visual(Display* dpy, int scr)
{
Visual* vis = XDefaultVisual(dpy, scr);
Screen* screen = XScreenOfDisplay(dpy, scr);
int d;
DPRINTF("XDefaultVisual:\n");
show_visual(vis);
DPRINTF("Screen RootDepth: %d\n", screen->root_depth);
DPRINTF("Screen RootVisual\n");
show_visual(screen->root_visual);
/* print all depths/visuals */
for (d = 0; d < screen->ndepths; d++) {
Depth* dp = screen->depths + d;
int v;
DPRINTF("Depth: %d\n", dp->depth);
for (v = 0; v < dp->nvisuals; v++) {
DPRINTF("Visual: %d\n", v);
show_visual(dp->visuals + v);
}
}
return vis;
}
int x11_setup_display()
{
static int setup_needed = 1;
if (setup_needed) {
char* name;
int i;
if ((name = getenv("DISPLAY")) == NULL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -