/[gxemul]/trunk/src/x11.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /trunk/src/x11.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 22 - (hide annotations)
Mon Oct 8 16:19:37 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 25543 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1121 2006/02/18 21:03:08 debug Exp $
20051126	Cobalt and PReP now work with the 21143 NIC.
		Continuing on Alpha dyntrans things.
		Fixing some more left-shift-by-24 to unsigned.
20051127	Working on OpenFirmware emulation; major cleanup/redesign.
		Progress on MacPPC emulation: NetBSD detects two CPUs (when
		running with -n 2), framebuffer output (for text) works.
		Adding quick-hack Bandit PCI controller and "gc" interrupt
		controller for MacPPC.
20051128	Changing from a Bandit to a Uni-North controller for macppc.
		Continuing on OpenFirmware and MacPPC emulation in general
		(obio controller, and wdc attached to the obio seems to work).
20051129	More work on MacPPC emulation (adding a dummy ADB controller).
		Continuing the PCI bus cleanup (endianness and tag composition)
		and rewriting all PCI controllers' access functions.
20051130	Various minor PPC dyntrans optimizations.
		Manually inlining some parts of the framebuffer redraw routine.
		Slowly beginning the conversion of the old MIPS emulation into
		dyntrans (but this will take quite some time to get right).
		Generalizing quick_pc_to_pointers.
20051201	Documentation update (David Muse has made available a kernel
		which simplifies Debian/DECstation installation).
		Continuing on the ADB bus controller.
20051202	Beginning a rewrite of the Zilog serial controller (dev_zs).
20051203	Continuing on the zs rewrite (now called dev_z8530); conversion
		to devinit style.
		Reworking some of the input-only vs output-only vs input-output
		details of src/console.c, better warning messages, and adding
		a debug dump.
		Removing the concept of "device state"; it wasn't really used.
		Changing some debug output (-vv should now be used to show all
		details about devices and busses; not shown during normal
		startup anymore).
		Beginning on some SPARC instruction disassembly support.
20051204	Minor PPC updates (WALNUT skeleton stuff).
		Continuing on the MIPS dyntrans rewrite.
		More progress on the ADB controller (a keyboard is "detected"
		by NetBSD and OpenBSD).
		Downgrading OpenBSD/arc as a guest OS from "working" to
		"almost working" in the documentation.
		Progress on Algor emulation ("v3" PCI controller).
20051205	Minor updates.
20051207	Sorting devices according to address; this reduces complexity
		of device lookups from O(n) to O(log n) in memory_rw (but no
		real performance increase (yet) in experiments).
20051210	Beginning the work on native dyntrans backends (by making a
		simple skeleton; so far only for Alpha hosts).
20051211	Some very minor SPARC updates.
20051215	Fixing a bug in the MIPS mul (note: not mult) instruction,
		so it also works with non-64-bit emulation. (Thanks to Alec
		Voropay for noticing the problem.)
20051216	More work on the fake/empty/simple/skeleton/whatever backend;
		performance doesn't increase, so this isn't really worth it,
		but it was probably worth it to prepare for a real backend
		later.
20051219	More instr call statistics gathering and analysis stuff.
20051220	Another fix for MIPS 'mul'. Also converting mul and {d,}cl{o,z}
		to dyntrans.
		memory_ppc.c syntax error fix (noticed by Peter Valchev).
		Beginning to move out machines from src/machine.c into
		individual files in src/machines (in a way similar to the
		autodev system for devices).
20051222	Updating the documentation regarding NetBSD/pmax 3.0.
20051223	- " - NetBSD/cats 3.0.
20051225	- " - NetBSD/hpcmips 3.0.
20051226	Continuing on the machine registry redesign.
		Adding support for ARM rrx (33-bit rotate).
		Fixing some signed/unsigned issues (exposed by gcc -W).
20051227	Fixing the bug which prevented a NetBSD/prep 3.0 install kernel
		from starting (triggered when an mtmsr was the last instruction
		on a page). Unfortunately not enough to get the kernel to run
		as well as the 2.1 kernels did.
20051230	Some dyntrans refactoring.
20051231	Continuing on the machine registry redesign.
20060101-10	Continuing... moving more machines. Moving MD interrupt stuff
		from machine.c into a new src/machines/interrupts.c.
20060114	Adding various mvmeppc machine skeletons.
20060115	Continuing on mvme* stuff. NetBSD/mvmeppc prints boot messages
		(for MVME1600) and reaches the root device prompt, but no
		specific hardware devices are emulated yet.
20060116	Minor updates to the mvme1600 emulation mode; the Eagle PCI bus
		seems to work without much modification, and a 21143 can be
		detected, interrupts might work (but untested so far).
		Adding a fake MK48Txx (mkclock) device, for NetBSD/mvmeppc.
20060121	Adding an aux control register for ARM. (A BIG thank you to
		Olivier Houchard for tracking down this bug.)
20060122	Adding more ARM instructions (smulXY), and dev_iq80321_7seg.
20060124	Adding disassembly of more ARM instructions (mia*, mra/mar),
		and some semi-bogus XScale and i80321 registers.
20060201-02	Various minor updates. Moving the last machines out of
		machine.c.
20060204	Adding a -c command line option, for running debugger commands
		before the simulation starts, but after all files have been
		loaded.
		Minor iq80321-related updates.
20060209	Minor hacks (DEVINIT macro, etc).
		Preparing for the generalization of the 64-bit dyntrans address
		translation subsystem.
20060216	Adding ARM ldrd (double-register load).
20060217	Continuing on various ARM-related stuff.
20060218	More progress on the ATA/wdc emulation for NetBSD/iq80321.
		NetBSD/evbarm can now be installed :-)  Updating the docs, etc.
		Continuing on Algor emulation.

==============  RELEASE 0.3.8  ==============


1 dpavlin 2 /*
2 dpavlin 22 * Copyright (C) 2003-2006 Anders Gavare. All rights reserved.
3 dpavlin 2 *
4     * Redistribution and use in source and binary forms, with or without
5     * modification, are permitted provided that the following conditions are met:
6     *
7     * 1. Redistributions of source code must retain the above copyright
8     * notice, this list of conditions and the following disclaimer.
9     * 2. Redistributions in binary form must reproduce the above copyright
10     * notice, this list of conditions and the following disclaimer in the
11     * documentation and/or other materials provided with the distribution.
12     * 3. The name of the author may not be used to endorse or promote products
13     * derived from this software without specific prior written permission.
14     *
15     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18     * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25     * SUCH DAMAGE.
26     *
27     *
28 dpavlin 22 * $Id: x11.c,v 1.61 2006/01/14 12:51:59 debug Exp $
29 dpavlin 2 *
30     * X11-related functions.
31     */
32    
33     #include <stdio.h>
34     #include <stdlib.h>
35     #include <string.h>
36    
37     #include "console.h"
38     #include "emul.h"
39     #include "machine.h"
40     #include "misc.h"
41     #include "x11.h"
42    
43    
44     #ifndef WITH_X11
45    
46    
47     /* Dummy functions: */
48     void x11_redraw_cursor(struct machine *m, int i) { }
49     void x11_redraw(struct machine *m, int x) { }
50     void x11_putpixel_fb(struct machine *m, int fb, int x, int y, int color) { }
51     void x11_init(struct machine *machine) { }
52     struct fb_window *x11_fb_init(int xsize, int ysize, char *name,
53     int scaledown, struct machine *machine)
54     { return NULL; }
55     void x11_check_event(struct emul **emuls, int n_emuls) { }
56    
57    
58     #else /* WITH_X11 */
59    
60    
61     #include <X11/Xlib.h>
62     #include <X11/Xutil.h>
63     #include <X11/cursorfont.h>
64    
65    
66     /*
67     * x11_redraw_cursor():
68     *
69     * Redraw a framebuffer's X11 cursor.
70 dpavlin 22 *
71     * NOTE: It is up to the caller to call XFlush.
72 dpavlin 2 */
73     void x11_redraw_cursor(struct machine *m, int i)
74     {
75     int last_color_used = 0;
76     int n_colors_used = 0;
77    
78     /* Remove old cursor, if any: */
79     if (m->fb_windows[i]->x11_display != NULL &&
80     m->fb_windows[i]->OLD_cursor_on) {
81     XPutImage(m->fb_windows[i]->x11_display,
82     m->fb_windows[i]->x11_fb_window,
83     m->fb_windows[i]->x11_fb_gc, m->fb_windows[i]->fb_ximage,
84     m->fb_windows[i]->OLD_cursor_x/m->fb_windows[i]->scaledown,
85     m->fb_windows[i]->OLD_cursor_y/m->fb_windows[i]->scaledown,
86     m->fb_windows[i]->OLD_cursor_x/m->fb_windows[i]->scaledown,
87     m->fb_windows[i]->OLD_cursor_y/m->fb_windows[i]->scaledown,
88     m->fb_windows[i]->OLD_cursor_xsize/
89     m->fb_windows[i]->scaledown + 1,
90     m->fb_windows[i]->OLD_cursor_ysize/
91     m->fb_windows[i]->scaledown + 1);
92     }
93    
94     if (m->fb_windows[i]->x11_display != NULL &&
95     m->fb_windows[i]->cursor_on) {
96     int x, y, subx, suby;
97     XImage *xtmp;
98    
99     xtmp = XSubImage(m->fb_windows[i]->fb_ximage,
100     m->fb_windows[i]->cursor_x/m->fb_windows[i]->scaledown,
101     m->fb_windows[i]->cursor_y/m->fb_windows[i]->scaledown,
102     m->fb_windows[i]->cursor_xsize/
103     m->fb_windows[i]->scaledown + 1,
104     m->fb_windows[i]->cursor_ysize/
105     m->fb_windows[i]->scaledown + 1);
106     if (xtmp == NULL) {
107     fatal("out of memory in x11_redraw_cursor()\n");
108     return;
109     }
110    
111     for (y=0; y<m->fb_windows[i]->cursor_ysize;
112     y+=m->fb_windows[i]->scaledown)
113     for (x=0; x<m->fb_windows[i]->cursor_xsize;
114     x+=m->fb_windows[i]->scaledown) {
115     int px = x/m->fb_windows[i]->scaledown;
116     int py = y/m->fb_windows[i]->scaledown;
117     int p = 0, n = 0, c = 0;
118     unsigned long oldcol;
119    
120     for (suby=0; suby<m->fb_windows[i]->scaledown;
121     suby++)
122     for (subx=0; subx<m->fb_windows[i]->
123     scaledown; subx++) {
124     c = m->fb_windows[i]->
125     cursor_pixels[y+suby]
126     [x+subx];
127     if (c >= 0) {
128     p += c;
129     n++;
130     }
131     }
132     if (n > 0)
133     p /= n;
134     else
135     p = c;
136    
137     if (n_colors_used == 0) {
138     last_color_used = p;
139     n_colors_used = 1;
140     } else
141     if (p != last_color_used)
142     n_colors_used = 2;
143    
144     switch (p) {
145     case CURSOR_COLOR_TRANSPARENT:
146     break;
147     case CURSOR_COLOR_INVERT:
148     oldcol = XGetPixel(xtmp, px, py);
149     if (oldcol != m->fb_windows[i]->
150     x11_graycolor[N_GRAYCOLORS-1].pixel)
151     oldcol = m->fb_windows[i]->
152     x11_graycolor[N_GRAYCOLORS
153     -1].pixel;
154     else
155     oldcol = m->fb_windows[i]->
156     x11_graycolor[0].pixel;
157     XPutPixel(xtmp, px, py, oldcol);
158     break;
159     default: /* Normal grayscale: */
160     XPutPixel(xtmp, px, py, m->fb_windows[
161     i]->x11_graycolor[p].pixel);
162     }
163     }
164    
165     XPutImage(m->fb_windows[i]->x11_display,
166     m->fb_windows[i]->x11_fb_window,
167     m->fb_windows[i]->x11_fb_gc,
168     xtmp, 0, 0,
169     m->fb_windows[i]->cursor_x/m->fb_windows[i]->scaledown,
170     m->fb_windows[i]->cursor_y/m->fb_windows[i]->scaledown,
171     m->fb_windows[i]->cursor_xsize/m->fb_windows[i]->scaledown,
172     m->fb_windows[i]->cursor_ysize/m->fb_windows[i]->scaledown);
173    
174     XDestroyImage(xtmp);
175    
176     m->fb_windows[i]->OLD_cursor_on = m->fb_windows[i]->cursor_on;
177     m->fb_windows[i]->OLD_cursor_x = m->fb_windows[i]->cursor_x;
178     m->fb_windows[i]->OLD_cursor_y = m->fb_windows[i]->cursor_y;
179     m->fb_windows[i]->OLD_cursor_xsize =
180     m->fb_windows[i]->cursor_xsize;
181     m->fb_windows[i]->OLD_cursor_ysize =
182     m->fb_windows[i]->cursor_ysize;
183     }
184    
185     /* printf("n_colors_used = %i\n", n_colors_used); */
186    
187     if (m->fb_windows[i]->host_cursor != 0 && n_colors_used < 2) {
188     /* Remove the old X11 host cursor: */
189     XUndefineCursor(m->fb_windows[i]->x11_display,
190     m->fb_windows[i]->x11_fb_window);
191     XFreeCursor(m->fb_windows[i]->x11_display,
192     m->fb_windows[i]->host_cursor);
193     m->fb_windows[i]->host_cursor = 0;
194     }
195    
196     if (n_colors_used >= 2 && m->fb_windows[i]->host_cursor == 0) {
197     GC tmpgc;
198    
199     /* Create a new X11 host cursor: */
200     /* cursor = XCreateFontCursor(m->fb_windows[i]->x11_display,
201     XC_coffee_mug); :-) */
202     if (m->fb_windows[i]->host_cursor_pixmap != 0) {
203     XFreePixmap(m->fb_windows[i]->x11_display,
204     m->fb_windows[i]->host_cursor_pixmap);
205     m->fb_windows[i]->host_cursor_pixmap = 0;
206     }
207     m->fb_windows[i]->host_cursor_pixmap =
208     XCreatePixmap(m->fb_windows[i]->x11_display,
209     m->fb_windows[i]->x11_fb_window, 1, 1, 1);
210     XSetForeground(m->fb_windows[i]->x11_display,
211     m->fb_windows[i]->x11_fb_gc,
212     m->fb_windows[i]->x11_graycolor[0].pixel);
213    
214     tmpgc = XCreateGC(m->fb_windows[i]->x11_display,
215     m->fb_windows[i]->host_cursor_pixmap, 0,0);
216    
217     XDrawPoint(m->fb_windows[i]->x11_display,
218     m->fb_windows[i]->host_cursor_pixmap,
219     tmpgc, 0, 0);
220    
221     XFreeGC(m->fb_windows[i]->x11_display, tmpgc);
222    
223     m->fb_windows[i]->host_cursor =
224     XCreatePixmapCursor(m->fb_windows[i]->x11_display,
225     m->fb_windows[i]->host_cursor_pixmap,
226     m->fb_windows[i]->host_cursor_pixmap,
227     &m->fb_windows[i]->x11_graycolor[N_GRAYCOLORS-1],
228     &m->fb_windows[i]->x11_graycolor[N_GRAYCOLORS-1],
229     0, 0);
230     if (m->fb_windows[i]->host_cursor != 0) {
231     XDefineCursor(m->fb_windows[i]->x11_display,
232     m->fb_windows[i]->x11_fb_window,
233     m->fb_windows[i]->host_cursor);
234     }
235     }
236     }
237    
238    
239     /*
240     * x11_redraw():
241     *
242     * Redraw X11 windows.
243     */
244     void x11_redraw(struct machine *m, int i)
245     {
246     if (i < 0 || i >= m->n_fb_windows ||
247     m->fb_windows[i]->x11_fb_winxsize <= 0)
248     return;
249    
250     x11_putimage_fb(m, i);
251     x11_redraw_cursor(m, i);
252     XFlush(m->fb_windows[i]->x11_display);
253     }
254    
255    
256     /*
257     * x11_putpixel_fb():
258     *
259     * Output a framebuffer pixel. i is the framebuffer number.
260     */
261     void x11_putpixel_fb(struct machine *m, int i, int x, int y, int color)
262     {
263     if (i < 0 || i >= m->n_fb_windows ||
264     m->fb_windows[i]->x11_fb_winxsize <= 0)
265     return;
266    
267     if (color)
268     XSetForeground(m->fb_windows[i]->x11_display,
269     m->fb_windows[i]->x11_fb_gc, m->fb_windows[i]->fg_color);
270     else
271     XSetForeground(m->fb_windows[i]->x11_display,
272     m->fb_windows[i]->x11_fb_gc, m->fb_windows[i]->bg_color);
273    
274     XDrawPoint(m->fb_windows[i]->x11_display,
275     m->fb_windows[i]->x11_fb_window, m->fb_windows[i]->x11_fb_gc, x, y);
276    
277     XFlush(m->fb_windows[i]->x11_display);
278     }
279    
280    
281     /*
282     * x11_putimage_fb():
283     *
284     * Output an entire XImage to a framebuffer window. i is the
285     * framebuffer number.
286     */
287     void x11_putimage_fb(struct machine *m, int i)
288     {
289     if (i < 0 || i >= m->n_fb_windows ||
290     m->fb_windows[i]->x11_fb_winxsize <= 0)
291     return;
292    
293     XPutImage(m->fb_windows[i]->x11_display,
294     m->fb_windows[i]->x11_fb_window,
295     m->fb_windows[i]->x11_fb_gc, m->fb_windows[i]->fb_ximage, 0,0, 0,0,
296     m->fb_windows[i]->x11_fb_winxsize,
297     m->fb_windows[i]->x11_fb_winysize);
298     XFlush(m->fb_windows[i]->x11_display);
299     }
300    
301    
302     /*
303     * x11_init():
304     *
305     * Initialize X11 stuff (but doesn't create any windows).
306     *
307     * It is then up to individual drivers, for example framebuffer devices,
308     * to initialize their own windows.
309     */
310     void x11_init(struct machine *m)
311     {
312     m->n_fb_windows = 0;
313    
314     if (m->x11_n_display_names > 0) {
315     int i;
316     for (i=0; i<m->x11_n_display_names; i++)
317     fatal("Using X11 display: %s\n",
318     m->x11_display_names[i]);
319     }
320    
321     m->x11_current_display_name_nr = 0;
322     }
323    
324    
325     /*
326 dpavlin 6 * x11_fb_resize():
327     *
328     * Set a new size for an X11 framebuffer window. (NOTE: I didn't think of
329     * this kind of functionality during the initial design, so it is probably
330     * buggy. It also needs some refactoring.)
331     */
332     void x11_fb_resize(struct fb_window *win, int new_xsize, int new_ysize)
333     {
334     int alloc_depth;
335    
336     if (win == NULL) {
337     fatal("x11_fb_resize(): win == NULL\n");
338     return;
339     }
340    
341     win->x11_fb_winxsize = new_xsize;
342     win->x11_fb_winysize = new_ysize;
343    
344     alloc_depth = win->x11_screen_depth;
345     if (alloc_depth == 24)
346     alloc_depth = 32;
347     if (alloc_depth == 15)
348     alloc_depth = 16;
349    
350     /* Note: ximage_data seems to be freed by XDestroyImage below. */
351     /* if (win->ximage_data != NULL)
352     free(win->ximage_data); */
353     win->ximage_data = malloc(new_xsize * new_ysize * alloc_depth / 8);
354     if (win->ximage_data == NULL) {
355     fprintf(stderr, "x11_fb_resize(): out of memory "
356     "allocating ximage_data\n");
357     exit(1);
358     }
359    
360     /* TODO: clear for non-truecolor modes */
361     memset(win->ximage_data, 0, new_xsize * new_ysize * alloc_depth / 8);
362    
363     if (win->fb_ximage != NULL)
364     XDestroyImage(win->fb_ximage);
365     win->fb_ximage = XCreateImage(win->x11_display, CopyFromParent,
366     win->x11_screen_depth, ZPixmap, 0, (char *)win->ximage_data,
367     new_xsize, new_ysize, 8, new_xsize * alloc_depth / 8);
368     if (win->fb_ximage == NULL) {
369     fprintf(stderr, "x11_fb_resize(): out of memory "
370     "allocating fb_ximage\n");
371     exit(1);
372     }
373    
374     XResizeWindow(win->x11_display, win->x11_fb_window,
375     new_xsize, new_ysize);
376     }
377    
378    
379     /*
380 dpavlin 2 * x11_fb_init():
381     *
382     * Initialize a framebuffer window.
383     */
384     struct fb_window *x11_fb_init(int xsize, int ysize, char *name,
385     int scaledown, struct machine *m)
386     {
387     Display *x11_display;
388     int x, y, fb_number = 0;
389     size_t alloclen, alloc_depth;
390     XColor tmpcolor;
391     int i;
392     char fg[80], bg[80];
393     char *display_name;
394    
395     fb_number = m->n_fb_windows;
396    
397     m->fb_windows = realloc(m->fb_windows,
398     sizeof(struct fb_window *) * (m->n_fb_windows + 1));
399     if (m->fb_windows == NULL) {
400     fprintf(stderr, "x11_fb_init(): out of memory\n");
401     exit(1);
402     }
403     m->fb_windows[fb_number] = malloc(sizeof(struct fb_window));
404     if (m->fb_windows[fb_number] == NULL) {
405     fprintf(stderr, "x11_fb_init(): out of memory\n");
406     exit(1);
407     }
408    
409     m->n_fb_windows ++;
410    
411     memset(m->fb_windows[fb_number], 0, sizeof(struct fb_window));
412    
413     m->fb_windows[fb_number]->x11_fb_winxsize = xsize;
414     m->fb_windows[fb_number]->x11_fb_winysize = ysize;
415    
416     /* Which display name? */
417     display_name = NULL;
418     if (m->x11_n_display_names > 0) {
419     display_name = m->x11_display_names[
420     m->x11_current_display_name_nr];
421     m->x11_current_display_name_nr ++;
422     m->x11_current_display_name_nr %= m->x11_n_display_names;
423     }
424    
425     if (display_name != NULL)
426     debug("[ x11_fb_init(): framebuffer window %i, %ix%i, DISPLAY"
427     "=%s ]\n", fb_number, xsize, ysize, display_name);
428    
429     x11_display = XOpenDisplay(display_name);
430    
431     if (x11_display == NULL) {
432     fatal("x11_fb_init(\"%s\"): couldn't open display\n", name);
433     if (display_name != NULL)
434     fatal("display_name = '%s'\n", display_name);
435     exit(1);
436     }
437    
438     m->fb_windows[fb_number]->x11_screen = DefaultScreen(x11_display);
439     m->fb_windows[fb_number]->x11_screen_depth = DefaultDepth(x11_display,
440     m->fb_windows[fb_number]->x11_screen);
441    
442     if (m->fb_windows[fb_number]->x11_screen_depth != 8 &&
443     m->fb_windows[fb_number]->x11_screen_depth != 15 &&
444     m->fb_windows[fb_number]->x11_screen_depth != 16 &&
445     m->fb_windows[fb_number]->x11_screen_depth != 24) {
446     fatal("\n***\n*** WARNING! Your X server is running %i-bit "
447     "color mode. This is not really\n",
448     m->fb_windows[fb_number]->x11_screen_depth);
449     fatal("*** supported yet. 8, 15, 16, and 24 bits should "
450     "work.\n*** 24-bit server gives color. Any other bit "
451     "depth gives undefined result!\n***\n\n");
452     }
453    
454     if (m->fb_windows[fb_number]->x11_screen_depth <= 8)
455     debug("WARNING! X11 screen depth is not enough for color; "
456     "using only 16 grayscales instead\n");
457    
458 dpavlin 10 strlcpy(bg, "Black", sizeof(bg));
459     strlcpy(fg, "White", sizeof(fg));
460 dpavlin 2
461     XParseColor(x11_display, DefaultColormap(x11_display,
462     m->fb_windows[fb_number]->x11_screen), fg, &tmpcolor);
463     XAllocColor(x11_display, DefaultColormap(x11_display,
464     m->fb_windows[fb_number]->x11_screen), &tmpcolor);
465     m->fb_windows[fb_number]->fg_color = tmpcolor.pixel;
466     XParseColor(x11_display, DefaultColormap(x11_display,
467     m->fb_windows[fb_number]->x11_screen), bg, &tmpcolor);
468     XAllocColor(x11_display, DefaultColormap(x11_display,
469     m->fb_windows[fb_number]->x11_screen), &tmpcolor);
470     m->fb_windows[fb_number]->bg_color = tmpcolor.pixel;
471    
472     for (i=0; i<N_GRAYCOLORS; i++) {
473     char cname[8];
474     cname[0] = '#';
475     cname[1] = cname[2] = cname[3] =
476     cname[4] = cname[5] = cname[6] =
477     "0123456789ABCDEF"[i];
478     cname[7] = '\0';
479     XParseColor(x11_display, DefaultColormap(x11_display,
480     m->fb_windows[fb_number]->x11_screen), cname,
481     &m->fb_windows[fb_number]->x11_graycolor[i]);
482     XAllocColor(x11_display, DefaultColormap(x11_display,
483     m->fb_windows[fb_number]->x11_screen),
484     &m->fb_windows[fb_number]->x11_graycolor[i]);
485     }
486    
487     XFlush(x11_display);
488    
489     alloc_depth = m->fb_windows[fb_number]->x11_screen_depth;
490    
491     if (alloc_depth == 24)
492     alloc_depth = 32;
493     if (alloc_depth == 15)
494     alloc_depth = 16;
495    
496     m->fb_windows[fb_number]->x11_fb_window = XCreateWindow(
497     x11_display, DefaultRootWindow(x11_display),
498     0, 0, m->fb_windows[fb_number]->x11_fb_winxsize,
499     m->fb_windows[fb_number]->x11_fb_winysize,
500     0, CopyFromParent, InputOutput, CopyFromParent, 0,0);
501    
502     XSetStandardProperties(x11_display,
503     m->fb_windows[fb_number]->x11_fb_window, name,
504     #ifdef VERSION
505     "GXemul-" VERSION,
506     #else
507     "GXemul",
508     #endif
509     None, NULL, 0, NULL);
510     XSelectInput(x11_display, m->fb_windows[fb_number]->x11_fb_window,
511     StructureNotifyMask | ExposureMask | ButtonPressMask |
512     ButtonReleaseMask | PointerMotionMask | KeyPressMask);
513     m->fb_windows[fb_number]->x11_fb_gc = XCreateGC(x11_display,
514     m->fb_windows[fb_number]->x11_fb_window, 0,0);
515    
516     /* Make sure the window is mapped: */
517     XMapRaised(x11_display, m->fb_windows[fb_number]->x11_fb_window);
518    
519     XSetBackground(x11_display, m->fb_windows[fb_number]->x11_fb_gc,
520     m->fb_windows[fb_number]->bg_color);
521     XSetForeground(x11_display, m->fb_windows[fb_number]->x11_fb_gc,
522     m->fb_windows[fb_number]->bg_color);
523     XFillRectangle(x11_display, m->fb_windows[fb_number]->x11_fb_window,
524     m->fb_windows[fb_number]->x11_fb_gc, 0,0,
525     m->fb_windows[fb_number]->x11_fb_winxsize,
526     m->fb_windows[fb_number]->x11_fb_winysize);
527    
528     m->fb_windows[fb_number]->x11_display = x11_display;
529     m->fb_windows[fb_number]->scaledown = scaledown;
530    
531     m->fb_windows[fb_number]->fb_number = fb_number;
532    
533     alloclen = xsize * ysize * alloc_depth / 8;
534     m->fb_windows[fb_number]->ximage_data = malloc(alloclen);
535     if (m->fb_windows[fb_number]->ximage_data == NULL) {
536     fprintf(stderr, "out of memory allocating ximage_data\n");
537     exit(1);
538     }
539    
540     m->fb_windows[fb_number]->fb_ximage = XCreateImage(
541     m->fb_windows[fb_number]->x11_display, CopyFromParent,
542     m->fb_windows[fb_number]->x11_screen_depth, ZPixmap, 0,
543     (char *)m->fb_windows[fb_number]->ximage_data,
544     xsize, ysize, 8, xsize * alloc_depth / 8);
545     if (m->fb_windows[fb_number]->fb_ximage == NULL) {
546     fprintf(stderr, "out of memory allocating ximage\n");
547     exit(1);
548     }
549    
550     /* Fill the ximage with black pixels: */
551     if (m->fb_windows[fb_number]->x11_screen_depth > 8)
552     memset(m->fb_windows[fb_number]->ximage_data, 0, alloclen);
553     else {
554     debug("x11_fb_init(): clearing the XImage\n");
555     for (y=0; y<ysize; y++)
556     for (x=0; x<xsize; x++)
557     XPutPixel(m->fb_windows[fb_number]->fb_ximage,
558     x, y, m->fb_windows[fb_number]->
559     x11_graycolor[0].pixel);
560     }
561    
562     x11_putimage_fb(m, fb_number);
563    
564     /* Fill the 64x64 "hardware" cursor with white pixels: */
565     xsize = ysize = 64;
566    
567     /* Fill the cursor ximage with white pixels: */
568     for (y=0; y<ysize; y++)
569     for (x=0; x<xsize; x++)
570     m->fb_windows[fb_number]->cursor_pixels[y][x] =
571     N_GRAYCOLORS-1;
572    
573     return m->fb_windows[fb_number];
574     }
575    
576    
577     /*
578     * x11_check_events_machine():
579     *
580     * Check for X11 events on a specific machine.
581     *
582     * TODO: Yuck! This has to be rewritten. Each display should be checked,
583     * and _then_ only those windows that are actually exposed should
584     * be redrawn!
585     */
586     static void x11_check_events_machine(struct emul **emuls, int n_emuls,
587     struct machine *m)
588     {
589     int fb_nr;
590    
591     for (fb_nr=0; fb_nr<m->n_fb_windows; fb_nr++) {
592     XEvent event;
593     int need_redraw = 0, found, i, j, k;
594    
595     while (XPending(m->fb_windows[fb_nr]->x11_display)) {
596     XNextEvent(m->fb_windows[fb_nr]->x11_display, &event);
597    
598     if (event.type==ConfigureNotify) {
599     need_redraw = 1;
600     }
601    
602     if (event.type==Expose && event.xexpose.count==0) {
603     /*
604     * TODO: the xexpose struct has x,y,width,
605     * height. Those could be used to only redraw
606     * the part of the framebuffer that was
607     * exposed. Note that the (mouse) cursor must
608     * be redrawn too.
609     */
610     /* x11_winxsize = event.xexpose.width;
611     x11_winysize = event.xexpose.height; */
612     need_redraw = 1;
613     }
614    
615     if (event.type == MotionNotify) {
616     /* debug("[ X11 MotionNotify: %i,%i ]\n",
617     event.xmotion.x, event.xmotion.y); */
618    
619     /* Which window in which machine in
620     which emulation? */
621     found = -1;
622     for (k=0; k<n_emuls; k++)
623     for (j=0; j<emuls[k]->n_machines; j++) {
624     struct machine *m2 = emuls[k]->
625     machines[j];
626     for (i=0; i<m2->n_fb_windows;
627     i++)
628     if (m->fb_windows[
629     fb_nr]->
630     x11_display == m2->
631     fb_windows[i]->
632     x11_display &&
633     event.xmotion.
634     window == m2->
635     fb_windows[i]->
636     x11_fb_window)
637     found = i;
638     }
639     if (found < 0) {
640     printf("Internal error in x11.c.\n");
641     exit(1);
642     }
643     console_mouse_coordinates(event.xmotion.x *
644     m->fb_windows[found]->scaledown,
645     event.xmotion.y * m->fb_windows[found]->
646     scaledown, found);
647     }
648    
649     if (event.type == ButtonPress) {
650     debug("[ X11 ButtonPress: %i ]\n",
651     event.xbutton.button);
652     /* button = 1,2,3 = left,middle,right */
653    
654     console_mouse_button(event.xbutton.button, 1);
655     }
656    
657     if (event.type == ButtonRelease) {
658     debug("[ X11 ButtonRelease: %i ]\n",
659     event.xbutton.button);
660     /* button = 1,2,3 = left,middle,right */
661    
662     console_mouse_button(event.xbutton.button, 0);
663     }
664    
665     if (event.type==KeyPress) {
666     char text[15];
667     KeySym key;
668     XKeyPressedEvent *ke = &event.xkey;
669    
670     memset(text, sizeof(text), 0);
671    
672     if (XLookupString(&event.xkey, text,
673     sizeof(text), &key, 0) == 1) {
674     console_makeavail(
675     m->main_console_handle, text[0]);
676     } else {
677     int x = ke->keycode;
678     /*
679     * Special key codes:
680     *
681     * NOTE/TODO: I'm hardcoding these to
682     * work with my key map. Maybe they
683     * should be read from some file...
684     *
685     * Important TODO 2: It would be MUCH
686     * better if these were converted into
687     * 'native scancodes', for example for
688     * the DECstation's keyboard or the
689     * PC-style 8042 controller.
690     */
691     switch (x) {
692     case 9: /* Escape */
693     console_makeavail(m->
694     main_console_handle, 27);
695     break;
696     #if 0
697     /* TODO */
698    
699     /* The numeric keypad: */
700     90=Ins('0') 91=Del(',')
701    
702     /* Above the cursor keys: */
703     106=Ins 107=Del
704     #endif
705     /* F1..F4: */
706     case 67: /* F1 */
707     case 68: /* F2 */
708     case 69: /* F3 */
709     case 70: /* F4 */
710     console_makeavail(m->
711     main_console_handle, 27);
712     console_makeavail(m->
713     main_console_handle, '[');
714     console_makeavail(m->
715     main_console_handle, 'O');
716     console_makeavail(m->
717     main_console_handle, 'P' +
718     x - 67);
719     break;
720     case 71: /* F5 */
721     console_makeavail(m->
722     main_console_handle, 27);
723     console_makeavail(m->
724     main_console_handle, '[');
725     console_makeavail(m->
726     main_console_handle, '1');
727     console_makeavail(m->
728     main_console_handle, '5');
729     break;
730     case 72: /* F6 */
731     case 73: /* F7 */
732     case 74: /* F8 */
733     console_makeavail(m->
734     main_console_handle, 27);
735     console_makeavail(m->
736     main_console_handle, '[');
737     console_makeavail(m->
738     main_console_handle, '1');
739     console_makeavail(m->
740     main_console_handle, '7' +
741     x - 72);
742     break;
743     case 75: /* F9 */
744     case 76: /* F10 */
745     console_makeavail(m->
746     main_console_handle, 27);
747     console_makeavail(m->
748     main_console_handle, '[');
749     console_makeavail(m->
750     main_console_handle, '2');
751     console_makeavail(m->
752     main_console_handle, '1' +
753     x - 68);
754     break;
755     case 95: /* F11 */
756     case 96: /* F12 */
757     console_makeavail(m->
758     main_console_handle, 27);
759     console_makeavail(m->
760     main_console_handle, '[');
761     console_makeavail(m->
762     main_console_handle, '2');
763     console_makeavail(m->
764     main_console_handle, '3' +
765     x - 95);
766     break;
767     /* Cursor keys: */
768     case 98: /* Up */
769     case 104: /* Down */
770     case 100: /* Left */
771     case 102: /* Right */
772     console_makeavail(m->
773     main_console_handle, 27);
774     console_makeavail(m->
775     main_console_handle, '[');
776     console_makeavail(m->
777     main_console_handle,
778     x == 98? 'A' : (
779     x == 104? 'B' : (
780     x == 102? 'C' : (
781     'D'))));
782     break;
783     /* Numeric keys: */
784     case 80: /* Up */
785     case 88: /* Down */
786     case 83: /* Left */
787     case 85: /* Right */
788     console_makeavail(m->
789     main_console_handle, 27);
790     console_makeavail(m->
791     main_console_handle, '[');
792     console_makeavail(m->
793     main_console_handle,
794     x == 80? 'A' : (
795     x == 88? 'B' : (
796     x == 85? 'C' : (
797     'D'))));
798     break;
799     case 97: /* Cursor Home */
800     case 79: /* Numeric Home */
801     console_makeavail(m->
802     main_console_handle, 27);
803     console_makeavail(m->
804     main_console_handle, '[');
805     console_makeavail(m->
806     main_console_handle, 'H');
807     break;
808     case 103: /* Cursor End */
809     case 87: /* Numeric End */
810     console_makeavail(m->
811     main_console_handle, 27);
812     console_makeavail(m->
813     main_console_handle, '[');
814     console_makeavail(m->
815     main_console_handle, 'F');
816     break;
817     case 99: /* Cursor PgUp */
818     case 81: /* Numeric PgUp */
819     console_makeavail(m->
820     main_console_handle, 27);
821     console_makeavail(m->
822     main_console_handle, '[');
823     console_makeavail(m->
824     main_console_handle, '5');
825     console_makeavail(m->
826     main_console_handle, '~');
827     break;
828     case 105: /* Cursor PgUp */
829     case 89: /* Numeric PgDn */
830     console_makeavail(m->
831     main_console_handle, 27);
832     console_makeavail(m->
833     main_console_handle, '[');
834     console_makeavail(m->
835     main_console_handle, '6');
836     console_makeavail(m->
837     main_console_handle, '~');
838     break;
839     default:
840     debug("[ unimplemented X11 "
841     "keycode %i ]\n", x);
842     }
843     }
844     }
845     }
846    
847     if (need_redraw)
848     x11_redraw(m, fb_nr);
849     }
850     }
851    
852    
853     /*
854     * x11_check_event():
855     *
856     * Check for X11 events.
857     */
858     void x11_check_event(struct emul **emuls, int n_emuls)
859     {
860     int i, j;
861    
862     for (i=0; i<n_emuls; i++)
863     for (j=0; j<emuls[i]->n_machines; j++)
864     x11_check_events_machine(emuls, n_emuls,
865     emuls[i]->machines[j]);
866     }
867    
868     #endif /* WITH_X11 */

  ViewVC Help
Powered by ViewVC 1.1.26