1*593dc095SDavid du Colombier /* Copyright (C) 1989-2005 artofcode LLC. All rights reserved.
27dd7cddfSDavid du Colombier
3*593dc095SDavid du Colombier This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier implied.
57dd7cddfSDavid du Colombier
6*593dc095SDavid du Colombier This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier of the license contained in the file LICENSE in this distribution.
97dd7cddfSDavid du Colombier
10*593dc095SDavid du Colombier For more information about licensing, please refer to
11*593dc095SDavid du Colombier http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier San Rafael, CA 94903, U.S.A., +1(415)492-9861.
157dd7cddfSDavid du Colombier */
167dd7cddfSDavid du Colombier
17*593dc095SDavid du Colombier /* $Id: gdevpcfb.c,v 1.7 2005/08/09 20:23:07 giles Exp $ */
187dd7cddfSDavid du Colombier /* IBM PC frame buffer (EGA/VGA) drivers */
197dd7cddfSDavid du Colombier #include "memory_.h"
207dd7cddfSDavid du Colombier #include "gconfigv.h" /* for USE_ASM */
217dd7cddfSDavid du Colombier #include "gx.h"
227dd7cddfSDavid du Colombier #include "gserrors.h"
237dd7cddfSDavid du Colombier #include "gsparam.h"
247dd7cddfSDavid du Colombier #include "gxdevice.h"
257dd7cddfSDavid du Colombier #include "gdevpccm.h"
267dd7cddfSDavid du Colombier #include "gdevpcfb.h"
277dd7cddfSDavid du Colombier
287dd7cddfSDavid du Colombier /* We may compile this in a non-segmented environment.... */
297dd7cddfSDavid du Colombier #ifndef _ss
307dd7cddfSDavid du Colombier #define _ss
317dd7cddfSDavid du Colombier #endif
327dd7cddfSDavid du Colombier
337dd7cddfSDavid du Colombier /* Macro for casting gx_device argument */
347dd7cddfSDavid du Colombier #define fb_dev ((gx_device_ega *)dev)
357dd7cddfSDavid du Colombier
367dd7cddfSDavid du Colombier /* Procedure record */
377dd7cddfSDavid du Colombier private dev_proc_map_rgb_color(ega0_map_rgb_color);
387dd7cddfSDavid du Colombier private dev_proc_map_rgb_color(ega1_map_rgb_color);
397dd7cddfSDavid du Colombier #define ega2_map_rgb_color pc_4bit_map_rgb_color
407dd7cddfSDavid du Colombier private dev_proc_map_color_rgb(ega01_map_color_rgb);
417dd7cddfSDavid du Colombier #define ega2_map_color_rgb pc_4bit_map_color_rgb
427dd7cddfSDavid du Colombier #if ega_bits_of_color == 0
437dd7cddfSDavid du Colombier # define ega_map_rgb_color ega0_map_rgb_color
447dd7cddfSDavid du Colombier # define ega_map_color_rgb ega01_map_color_rgb
457dd7cddfSDavid du Colombier #else
467dd7cddfSDavid du Colombier # if ega_bits_of_color == 1
477dd7cddfSDavid du Colombier # define ega_map_rgb_color ega1_map_rgb_color
487dd7cddfSDavid du Colombier # define ega_map_color_rgb ega01_map_color_rgb
497dd7cddfSDavid du Colombier # else
507dd7cddfSDavid du Colombier # define ega_map_rgb_color ega2_map_rgb_color
517dd7cddfSDavid du Colombier # define ega_map_color_rgb ega2_map_color_rgb
527dd7cddfSDavid du Colombier # endif
537dd7cddfSDavid du Colombier #endif
547dd7cddfSDavid du Colombier #define ega_std_procs(get_params, put_params)\
557dd7cddfSDavid du Colombier ega_open,\
567dd7cddfSDavid du Colombier NULL, /* get_initial_matrix */\
577dd7cddfSDavid du Colombier NULL, /* sync_output */\
587dd7cddfSDavid du Colombier NULL, /* output_page */\
597dd7cddfSDavid du Colombier ega_close,\
607dd7cddfSDavid du Colombier ega_map_rgb_color,\
617dd7cddfSDavid du Colombier ega_map_color_rgb,\
627dd7cddfSDavid du Colombier ega_fill_rectangle,\
637dd7cddfSDavid du Colombier ega_tile_rectangle,\
647dd7cddfSDavid du Colombier ega_copy_mono,\
657dd7cddfSDavid du Colombier ega_copy_color,\
667dd7cddfSDavid du Colombier NULL, /* draw_line */\
677dd7cddfSDavid du Colombier ega_get_bits,\
687dd7cddfSDavid du Colombier get_params,\
697dd7cddfSDavid du Colombier put_params,\
707dd7cddfSDavid du Colombier NULL, /* map_cmyk_color */\
717dd7cddfSDavid du Colombier NULL, /* get_xfont_procs */\
727dd7cddfSDavid du Colombier NULL, /* get_xfont_device */\
737dd7cddfSDavid du Colombier NULL, /* map_rgb_alpha_color */\
747dd7cddfSDavid du Colombier gx_page_device_get_page_device
757dd7cddfSDavid du Colombier
767dd7cddfSDavid du Colombier private const gx_device_procs ega_procs =
777dd7cddfSDavid du Colombier {
787dd7cddfSDavid du Colombier ega_std_procs(NULL, NULL)
797dd7cddfSDavid du Colombier };
807dd7cddfSDavid du Colombier
817dd7cddfSDavid du Colombier private dev_proc_get_params(svga16_get_params);
827dd7cddfSDavid du Colombier private dev_proc_put_params(svga16_put_params);
837dd7cddfSDavid du Colombier private const gx_device_procs svga16_procs =
847dd7cddfSDavid du Colombier {
857dd7cddfSDavid du Colombier ega_std_procs(svga16_get_params, svga16_put_params)
867dd7cddfSDavid du Colombier };
877dd7cddfSDavid du Colombier
887dd7cddfSDavid du Colombier /* All the known instances */
897dd7cddfSDavid du Colombier /* EGA */
907dd7cddfSDavid du Colombier gx_device_ega far_data gs_ega_device =
917dd7cddfSDavid du Colombier ega_device("ega", ega_procs, 80, 350, 48.0 / 35.0, 0x10);
927dd7cddfSDavid du Colombier
937dd7cddfSDavid du Colombier /* VGA */
947dd7cddfSDavid du Colombier gx_device_ega far_data gs_vga_device =
957dd7cddfSDavid du Colombier ega_device("vga", ega_procs, 80, 480, 1.0, 0x12);
967dd7cddfSDavid du Colombier
977dd7cddfSDavid du Colombier /* Generic SuperVGA, 800x600, 16-color mode */
987dd7cddfSDavid du Colombier gx_device_ega far_data gs_svga16_device =
997dd7cddfSDavid du Colombier ega_device("svga16", svga16_procs, 100, 600, 1.0, 0x29 /*Tseng */ );
1007dd7cddfSDavid du Colombier
1017dd7cddfSDavid du Colombier /* Save the BIOS state */
1027dd7cddfSDavid du Colombier private pcfb_bios_state pcfb_save_state =
1037dd7cddfSDavid du Colombier {-1};
1047dd7cddfSDavid du Colombier
1057dd7cddfSDavid du Colombier /* Initialize the EGA for graphics mode */
1067dd7cddfSDavid du Colombier int
ega_open(gx_device * dev)1077dd7cddfSDavid du Colombier ega_open(gx_device * dev)
1087dd7cddfSDavid du Colombier { /* Adjust the device resolution. */
1097dd7cddfSDavid du Colombier /* This is a hack, pending refactoring of the put_params machinery. */
1107dd7cddfSDavid du Colombier switch (fb_dev->video_mode) {
1117dd7cddfSDavid du Colombier case 0x10: /* EGA */
1127dd7cddfSDavid du Colombier gx_device_adjust_resolution(dev, 640, 350, 1);
1137dd7cddfSDavid du Colombier break;
1147dd7cddfSDavid du Colombier case 0x12: /* VGA */
1157dd7cddfSDavid du Colombier gx_device_adjust_resolution(dev, 640, 480, 1);
1167dd7cddfSDavid du Colombier break;
1177dd7cddfSDavid du Colombier default: /* 800x600 SuperVGA */
1187dd7cddfSDavid du Colombier gx_device_adjust_resolution(dev, 800, 600, 1);
1197dd7cddfSDavid du Colombier break;
1207dd7cddfSDavid du Colombier }
1217dd7cddfSDavid du Colombier if (pcfb_save_state.display_mode < 0)
1227dd7cddfSDavid du Colombier pcfb_get_state(&pcfb_save_state);
1237dd7cddfSDavid du Colombier /* Do implementation-specific initialization */
1247dd7cddfSDavid du Colombier pcfb_set_signals(dev);
1257dd7cddfSDavid du Colombier pcfb_set_mode(fb_dev->video_mode);
1267dd7cddfSDavid du Colombier set_s_map(-1); /* enable all maps */
1277dd7cddfSDavid du Colombier return 0;
1287dd7cddfSDavid du Colombier }
1297dd7cddfSDavid du Colombier
1307dd7cddfSDavid du Colombier /* Reinitialize the EGA for text mode */
1317dd7cddfSDavid du Colombier int
ega_close(gx_device * dev)1327dd7cddfSDavid du Colombier ega_close(gx_device * dev)
1337dd7cddfSDavid du Colombier {
1347dd7cddfSDavid du Colombier if (pcfb_save_state.display_mode >= 0)
1357dd7cddfSDavid du Colombier pcfb_set_state(&pcfb_save_state);
1367dd7cddfSDavid du Colombier return 0;
1377dd7cddfSDavid du Colombier }
1387dd7cddfSDavid du Colombier
1397dd7cddfSDavid du Colombier /* Get/put the display mode parameter. */
1407dd7cddfSDavid du Colombier private int
svga16_get_params(gx_device * dev,gs_param_list * plist)1417dd7cddfSDavid du Colombier svga16_get_params(gx_device * dev, gs_param_list * plist)
1427dd7cddfSDavid du Colombier {
1437dd7cddfSDavid du Colombier int code = gx_default_get_params(dev, plist);
1447dd7cddfSDavid du Colombier
1457dd7cddfSDavid du Colombier if (code < 0)
1467dd7cddfSDavid du Colombier return code;
1477dd7cddfSDavid du Colombier return param_write_int(plist, "DisplayMode", &fb_dev->video_mode);
1487dd7cddfSDavid du Colombier }
1497dd7cddfSDavid du Colombier private int
svga16_put_params(gx_device * dev,gs_param_list * plist)1507dd7cddfSDavid du Colombier svga16_put_params(gx_device * dev, gs_param_list * plist)
1517dd7cddfSDavid du Colombier {
1527dd7cddfSDavid du Colombier int ecode = 0;
1537dd7cddfSDavid du Colombier int code;
1547dd7cddfSDavid du Colombier int imode = fb_dev->video_mode;
1557dd7cddfSDavid du Colombier const char *param_name;
1567dd7cddfSDavid du Colombier
1577dd7cddfSDavid du Colombier switch (code = param_read_int(plist, (param_name = "DisplayMode"), &imode)) {
1587dd7cddfSDavid du Colombier default:
1597dd7cddfSDavid du Colombier ecode = code;
1607dd7cddfSDavid du Colombier param_signal_error(plist, param_name, ecode);
1617dd7cddfSDavid du Colombier case 0:
1627dd7cddfSDavid du Colombier case 1:
1637dd7cddfSDavid du Colombier break;
1647dd7cddfSDavid du Colombier }
1657dd7cddfSDavid du Colombier
1667dd7cddfSDavid du Colombier if (ecode < 0)
1677dd7cddfSDavid du Colombier return ecode;
1687dd7cddfSDavid du Colombier code = gx_default_put_params(dev, plist);
1697dd7cddfSDavid du Colombier if (code < 0)
1707dd7cddfSDavid du Colombier return code;
1717dd7cddfSDavid du Colombier
1727dd7cddfSDavid du Colombier if (imode != fb_dev->video_mode) {
1737dd7cddfSDavid du Colombier if (dev->is_open)
1747dd7cddfSDavid du Colombier gs_closedevice(dev);
1757dd7cddfSDavid du Colombier fb_dev->video_mode = imode;
1767dd7cddfSDavid du Colombier }
1777dd7cddfSDavid du Colombier return 0;
1787dd7cddfSDavid du Colombier }
1797dd7cddfSDavid du Colombier
1807dd7cddfSDavid du Colombier /* Map a r-g-b color to an EGA color code. */
1817dd7cddfSDavid du Colombier private gx_color_index
ega0_map_rgb_color(gx_device * dev,const gx_color_value cv[])182*593dc095SDavid du Colombier ega0_map_rgb_color(gx_device * dev, const gx_color_value cv[])
1837dd7cddfSDavid du Colombier {
184*593dc095SDavid du Colombier return pc_4bit_map_rgb_color(dev, cv);
1857dd7cddfSDavid du Colombier }
1867dd7cddfSDavid du Colombier private gx_color_index
ega1_map_rgb_color(gx_device * dev,const gx_color_value cv[])187*593dc095SDavid du Colombier ega1_map_rgb_color(gx_device * dev, const gx_color_value cv[])
1887dd7cddfSDavid du Colombier {
189*593dc095SDavid du Colombier const gx_color_value cvtop = (1 << (gx_color_value_bits - 1));
190*593dc095SDavid du Colombier gx_color_value cvt[3];
191*593dc095SDavid du Colombier cvt[0] = cv[0] & cvtop;
192*593dc095SDavid du Colombier cvt[1] = cv[1] & cvtop;
193*593dc095SDavid du Colombier cvt[2] = cv[2] & cvtop;
194*593dc095SDavid du Colombier return pc_4bit_map_rgb_color(dev, cvt);
1957dd7cddfSDavid du Colombier }
1967dd7cddfSDavid du Colombier
1977dd7cddfSDavid du Colombier /* Map a color code to r-g-b. */
1987dd7cddfSDavid du Colombier #define icolor (int)color
1997dd7cddfSDavid du Colombier private int
ega01_map_color_rgb(gx_device * dev,gx_color_index color,gx_color_value prgb[3])2007dd7cddfSDavid du Colombier ega01_map_color_rgb(gx_device * dev, gx_color_index color,
2017dd7cddfSDavid du Colombier gx_color_value prgb[3])
2027dd7cddfSDavid du Colombier {
2037dd7cddfSDavid du Colombier #define one (gx_max_color_value / 2 + 1)
2047dd7cddfSDavid du Colombier prgb[0] = (icolor & 4 ? one : 0);
2057dd7cddfSDavid du Colombier prgb[1] = (icolor & 2 ? one : 0);
2067dd7cddfSDavid du Colombier prgb[2] = (icolor & 1 ? one : 0);
2077dd7cddfSDavid du Colombier return 0;
2087dd7cddfSDavid du Colombier #undef one
2097dd7cddfSDavid du Colombier }
2107dd7cddfSDavid du Colombier #undef icolor
2117dd7cddfSDavid du Colombier
2127dd7cddfSDavid du Colombier /* ------ Internal routines ------ */
2137dd7cddfSDavid du Colombier
2147dd7cddfSDavid du Colombier /* Structure for operation parameters. */
2157dd7cddfSDavid du Colombier /* Note that this structure is known to assembly code. */
2167dd7cddfSDavid du Colombier /* Not all parameters are used for every operation. */
2177dd7cddfSDavid du Colombier typedef struct rop_params_s {
2187dd7cddfSDavid du Colombier fb_ptr dest; /* pointer to frame buffer */
2197dd7cddfSDavid du Colombier int draster; /* raster of frame buffer */
2207dd7cddfSDavid du Colombier const byte *src; /* pointer to source data */
2217dd7cddfSDavid du Colombier int sraster; /* source raster */
2227dd7cddfSDavid du Colombier int width; /* width in bytes */
2237dd7cddfSDavid du Colombier int height; /* height in scan lines */
2247dd7cddfSDavid du Colombier int shift; /* amount to right shift source */
2257dd7cddfSDavid du Colombier int invert; /* 0 or -1 to invert source */
2267dd7cddfSDavid du Colombier int data; /* data for fill */
2277dd7cddfSDavid du Colombier } rop_params;
2287dd7cddfSDavid du Colombier typedef rop_params _ss *rop_ptr;
2297dd7cddfSDavid du Colombier
2307dd7cddfSDavid du Colombier /* Assembly language routines */
2317dd7cddfSDavid du Colombier
2327dd7cddfSDavid du Colombier #if USE_ASM
233*593dc095SDavid du Colombier void memsetcol(rop_ptr); /* dest, draster, height, data */
2347dd7cddfSDavid du Colombier #else
2357dd7cddfSDavid du Colombier #define memsetcol cmemsetcol
2367dd7cddfSDavid du Colombier private void
cmemsetcol(rop_ptr rop)2377dd7cddfSDavid du Colombier cmemsetcol(rop_ptr rop)
2387dd7cddfSDavid du Colombier {
2397dd7cddfSDavid du Colombier byte *addr = rop->dest;
2407dd7cddfSDavid du Colombier int yc = rop->height;
2417dd7cddfSDavid du Colombier byte data = rop->data;
2427dd7cddfSDavid du Colombier int draster = rop->draster;
2437dd7cddfSDavid du Colombier
2447dd7cddfSDavid du Colombier while (yc--) {
2457dd7cddfSDavid du Colombier byte_discard(*addr);
2467dd7cddfSDavid du Colombier *addr = data;
2477dd7cddfSDavid du Colombier addr += draster;
2487dd7cddfSDavid du Colombier }
2497dd7cddfSDavid du Colombier }
2507dd7cddfSDavid du Colombier #endif
2517dd7cddfSDavid du Colombier
2527dd7cddfSDavid du Colombier #if USE_ASM
253*593dc095SDavid du Colombier void memsetrect(rop_ptr); /* dest, draster, width, height, data */
2547dd7cddfSDavid du Colombier #else
2557dd7cddfSDavid du Colombier #define memsetrect cmemsetrect
2567dd7cddfSDavid du Colombier private void
cmemsetrect(rop_ptr rop)2577dd7cddfSDavid du Colombier cmemsetrect(rop_ptr rop)
2587dd7cddfSDavid du Colombier {
2597dd7cddfSDavid du Colombier int yc = rop->height;
2607dd7cddfSDavid du Colombier int width = rop->width;
2617dd7cddfSDavid du Colombier
2627dd7cddfSDavid du Colombier if (yc <= 0 || width <= 0)
2637dd7cddfSDavid du Colombier return;
2647dd7cddfSDavid du Colombier {
2657dd7cddfSDavid du Colombier byte *addr = rop->dest;
2667dd7cddfSDavid du Colombier byte data = rop->data;
2677dd7cddfSDavid du Colombier
2687dd7cddfSDavid du Colombier if (width > 5) { /* use memset */
2697dd7cddfSDavid du Colombier int skip = rop->draster;
2707dd7cddfSDavid du Colombier
2717dd7cddfSDavid du Colombier do {
2727dd7cddfSDavid du Colombier memset(addr, data, width);
2737dd7cddfSDavid du Colombier addr += skip;
2747dd7cddfSDavid du Colombier }
2757dd7cddfSDavid du Colombier while (--yc);
2767dd7cddfSDavid du Colombier } else { /* avoid the fixed overhead */
2777dd7cddfSDavid du Colombier int skip = rop->draster - width;
2787dd7cddfSDavid du Colombier
2797dd7cddfSDavid du Colombier do {
2807dd7cddfSDavid du Colombier int cnt = width;
2817dd7cddfSDavid du Colombier
2827dd7cddfSDavid du Colombier do {
2837dd7cddfSDavid du Colombier *addr++ = data;
2847dd7cddfSDavid du Colombier } while (--cnt);
2857dd7cddfSDavid du Colombier addr += skip;
2867dd7cddfSDavid du Colombier }
2877dd7cddfSDavid du Colombier while (--yc);
2887dd7cddfSDavid du Colombier }
2897dd7cddfSDavid du Colombier }
2907dd7cddfSDavid du Colombier }
2917dd7cddfSDavid du Colombier #endif
2927dd7cddfSDavid du Colombier
2937dd7cddfSDavid du Colombier #if USE_ASM
294*593dc095SDavid du Colombier void memrwcol(rop_ptr); /* dest, draster, src, sraster, height, shift, invert */
2957dd7cddfSDavid du Colombier # define memrwcol0(rop) memrwcol(rop) /* same except shift = 0 */
2967dd7cddfSDavid du Colombier #else
2977dd7cddfSDavid du Colombier # define memrwcol cmemrwcol
2987dd7cddfSDavid du Colombier # define memrwcol0 cmemrwcol0
2997dd7cddfSDavid du Colombier private void
cmemrwcol(rop_ptr rop)3007dd7cddfSDavid du Colombier cmemrwcol(rop_ptr rop)
3017dd7cddfSDavid du Colombier {
3027dd7cddfSDavid du Colombier byte *dp = rop->dest;
3037dd7cddfSDavid du Colombier const byte *sp = rop->src;
3047dd7cddfSDavid du Colombier int yc = rop->height;
3057dd7cddfSDavid du Colombier int shift = rop->shift;
3067dd7cddfSDavid du Colombier byte invert = rop->invert;
3077dd7cddfSDavid du Colombier int sraster = rop->sraster, draster = rop->draster;
3087dd7cddfSDavid du Colombier
3097dd7cddfSDavid du Colombier while (yc--) {
3107dd7cddfSDavid du Colombier byte_discard(*dp);
3117dd7cddfSDavid du Colombier *dp = ((*sp >> shift) + (*sp << (8 - shift))) ^ invert;
3127dd7cddfSDavid du Colombier dp += draster, sp += sraster;
3137dd7cddfSDavid du Colombier }
3147dd7cddfSDavid du Colombier }
3157dd7cddfSDavid du Colombier private void
cmemrwcol0(rop_ptr rop)3167dd7cddfSDavid du Colombier cmemrwcol0(rop_ptr rop)
3177dd7cddfSDavid du Colombier {
3187dd7cddfSDavid du Colombier byte *dp = rop->dest;
3197dd7cddfSDavid du Colombier const byte *sp = rop->src;
3207dd7cddfSDavid du Colombier int yc = rop->height;
3217dd7cddfSDavid du Colombier byte invert = rop->invert;
3227dd7cddfSDavid du Colombier int sraster = rop->sraster, draster = rop->draster;
3237dd7cddfSDavid du Colombier
3247dd7cddfSDavid du Colombier if (yc > 0)
3257dd7cddfSDavid du Colombier do {
3267dd7cddfSDavid du Colombier byte_discard(*dp);
3277dd7cddfSDavid du Colombier *dp = *sp ^ invert;
3287dd7cddfSDavid du Colombier dp += draster, sp += sraster;
3297dd7cddfSDavid du Colombier }
3307dd7cddfSDavid du Colombier while (--yc);
3317dd7cddfSDavid du Colombier }
3327dd7cddfSDavid du Colombier #endif
3337dd7cddfSDavid du Colombier
3347dd7cddfSDavid du Colombier #if USE_ASM
335*593dc095SDavid du Colombier void memrwcol2(rop_ptr); /* dest, draster, src, sraster, height, shift, invert */
3367dd7cddfSDavid du Colombier #else
3377dd7cddfSDavid du Colombier #define memrwcol2 cmemrwcol2
3387dd7cddfSDavid du Colombier private void
cmemrwcol2(rop_ptr rop)3397dd7cddfSDavid du Colombier cmemrwcol2(rop_ptr rop)
3407dd7cddfSDavid du Colombier {
3417dd7cddfSDavid du Colombier byte *dp = rop->dest;
3427dd7cddfSDavid du Colombier const byte *sp = rop->src;
3437dd7cddfSDavid du Colombier int yc = rop->height;
3447dd7cddfSDavid du Colombier int shift = rop->shift;
3457dd7cddfSDavid du Colombier byte invert = rop->invert;
3467dd7cddfSDavid du Colombier int sraster = rop->sraster, draster = rop->draster;
3477dd7cddfSDavid du Colombier
3487dd7cddfSDavid du Colombier while (yc--) {
3497dd7cddfSDavid du Colombier byte_discard(*dp);
3507dd7cddfSDavid du Colombier *dp = ((sp[1] >> shift) + (*sp << (8 - shift))) ^ invert;
3517dd7cddfSDavid du Colombier dp += draster, sp += sraster;
3527dd7cddfSDavid du Colombier }
3537dd7cddfSDavid du Colombier }
3547dd7cddfSDavid du Colombier #endif
3557dd7cddfSDavid du Colombier
3567dd7cddfSDavid du Colombier /* Forward definitions */
357*593dc095SDavid du Colombier int ega_write_dot(gx_device *, int, int, gx_color_index);
358*593dc095SDavid du Colombier private void fill_rectangle(rop_ptr, int, int, int);
359*593dc095SDavid du Colombier private void fill_row_only(byte *, int, int, int);
3607dd7cddfSDavid du Colombier
3617dd7cddfSDavid du Colombier /* Clean up after writing */
3627dd7cddfSDavid du Colombier #define dot_end()\
3637dd7cddfSDavid du Colombier set_g_mask(0xff) /* all bits on */
3647dd7cddfSDavid du Colombier
3657dd7cddfSDavid du Colombier /* Write a dot using the EGA color codes. */
3667dd7cddfSDavid du Colombier /* This doesn't have to be efficient. */
3677dd7cddfSDavid du Colombier int
ega_write_dot(gx_device * dev,int x,int y,gx_color_index color)3687dd7cddfSDavid du Colombier ega_write_dot(gx_device * dev, int x, int y, gx_color_index color)
3697dd7cddfSDavid du Colombier {
3707dd7cddfSDavid du Colombier byte data[4];
3717dd7cddfSDavid du Colombier
3727dd7cddfSDavid du Colombier data[0] = (byte) color;
3737dd7cddfSDavid du Colombier return ega_copy_color(dev, data, 1, 4, gx_no_bitmap_id, x, y, 1, 1);
3747dd7cddfSDavid du Colombier }
3757dd7cddfSDavid du Colombier
3767dd7cddfSDavid du Colombier /* Macro for testing bit-inclusion */
3777dd7cddfSDavid du Colombier #define bit_included_in(x,y) !((x)&~(y))
3787dd7cddfSDavid du Colombier
3797dd7cddfSDavid du Colombier /* Copy a monochrome bitmap. The colors are given explicitly. */
3807dd7cddfSDavid du Colombier /* Color = gx_no_color_index means transparent (no effect on the image). */
3817dd7cddfSDavid du Colombier int
ega_copy_mono(gx_device * dev,const byte * base,int sourcex,int raster,gx_bitmap_id id,int x,int y,int w,int h,gx_color_index izero,gx_color_index ione)3827dd7cddfSDavid du Colombier ega_copy_mono(gx_device * dev,
3837dd7cddfSDavid du Colombier const byte * base, int sourcex, int raster, gx_bitmap_id id,
3847dd7cddfSDavid du Colombier int x, int y, int w, int h, gx_color_index izero, gx_color_index ione)
3857dd7cddfSDavid du Colombier {
3867dd7cddfSDavid du Colombier rop_params params;
3877dd7cddfSDavid du Colombier
3887dd7cddfSDavid du Colombier #define czero (int)izero
3897dd7cddfSDavid du Colombier #define cone (int)ione
3907dd7cddfSDavid du Colombier int dleft, count;
3917dd7cddfSDavid du Colombier byte mask, rmask;
3927dd7cddfSDavid du Colombier fb_ptr save_dest;
3937dd7cddfSDavid du Colombier int other_color = -1;
3947dd7cddfSDavid du Colombier
3957dd7cddfSDavid du Colombier fit_copy(dev, base, sourcex, raster, id, x, y, w, h);
3967dd7cddfSDavid du Colombier params.dest = mk_fb_ptr(x, y);
3977dd7cddfSDavid du Colombier params.draster = fb_dev->raster;
3987dd7cddfSDavid du Colombier params.src = base + (sourcex >> 3);
3997dd7cddfSDavid du Colombier params.sraster = raster;
4007dd7cddfSDavid du Colombier params.height = h;
4017dd7cddfSDavid du Colombier params.shift = (x - sourcex) & 7;
4027dd7cddfSDavid du Colombier /* Analyze the 16 possible cases: each of izero and ione may be */
4037dd7cddfSDavid du Colombier /* 0, 0xf, transparent, or some other color. */
4047dd7cddfSDavid du Colombier switch (czero) {
4057dd7cddfSDavid du Colombier case no_color:
4067dd7cddfSDavid du Colombier switch (cone) {
4077dd7cddfSDavid du Colombier default: /* (T, other) */
4087dd7cddfSDavid du Colombier /* Must do 2 passes */
4097dd7cddfSDavid du Colombier other_color = cone;
4107dd7cddfSDavid du Colombier save_dest = params.dest;
4117dd7cddfSDavid du Colombier /* falls through */
4127dd7cddfSDavid du Colombier case 0: /* (T, 0) */
4137dd7cddfSDavid du Colombier set_g_function(gf_AND);
4147dd7cddfSDavid du Colombier params.invert = -1;
4157dd7cddfSDavid du Colombier break;
4167dd7cddfSDavid du Colombier case 0xf: /* (T, 0xf) */
4177dd7cddfSDavid du Colombier set_g_function(gf_OR);
4187dd7cddfSDavid du Colombier params.invert = 0;
4197dd7cddfSDavid du Colombier break;
4207dd7cddfSDavid du Colombier case no_color: /* (T, T) */
4217dd7cddfSDavid du Colombier return 0; /* nothing to do */
4227dd7cddfSDavid du Colombier }
4237dd7cddfSDavid du Colombier break;
4247dd7cddfSDavid du Colombier case 0:
4257dd7cddfSDavid du Colombier params.invert = 0;
4267dd7cddfSDavid du Colombier switch (cone) {
4277dd7cddfSDavid du Colombier default: /* (0, other) */
4287dd7cddfSDavid du Colombier set_g_const(0);
4297dd7cddfSDavid du Colombier set_g_const_map(cone ^ 0xf);
4307dd7cddfSDavid du Colombier /* falls through */
4317dd7cddfSDavid du Colombier case 0xf: /* (0, 0xf) */
4327dd7cddfSDavid du Colombier break;
4337dd7cddfSDavid du Colombier case no_color: /* (0, T) */
4347dd7cddfSDavid du Colombier set_g_function(gf_AND);
4357dd7cddfSDavid du Colombier break;
4367dd7cddfSDavid du Colombier }
4377dd7cddfSDavid du Colombier break;
4387dd7cddfSDavid du Colombier case 0xf:
4397dd7cddfSDavid du Colombier params.invert = -1;
4407dd7cddfSDavid du Colombier switch (cone) {
4417dd7cddfSDavid du Colombier case 0: /* (0xf, 0) */
4427dd7cddfSDavid du Colombier break;
4437dd7cddfSDavid du Colombier default: /* (0xf, other) */
4447dd7cddfSDavid du Colombier set_g_const(0xf);
4457dd7cddfSDavid du Colombier set_g_const_map(cone);
4467dd7cddfSDavid du Colombier break;
4477dd7cddfSDavid du Colombier case no_color: /* (0xf, T) */
4487dd7cddfSDavid du Colombier set_g_function(gf_OR);
4497dd7cddfSDavid du Colombier /* falls through */
4507dd7cddfSDavid du Colombier }
4517dd7cddfSDavid du Colombier break;
4527dd7cddfSDavid du Colombier default:
4537dd7cddfSDavid du Colombier switch (cone) {
4547dd7cddfSDavid du Colombier default: /* (other, not T) */
4557dd7cddfSDavid du Colombier if (bit_included_in(czero, cone)) {
4567dd7cddfSDavid du Colombier set_g_const(czero);
4577dd7cddfSDavid du Colombier set_g_const_map(czero ^ cone ^ 0xf);
4587dd7cddfSDavid du Colombier params.invert = 0;
4597dd7cddfSDavid du Colombier break;
4607dd7cddfSDavid du Colombier } else if (bit_included_in(cone, czero)) {
4617dd7cddfSDavid du Colombier set_g_const(cone);
4627dd7cddfSDavid du Colombier set_g_const_map(cone ^ czero ^ 0xf);
4637dd7cddfSDavid du Colombier params.invert = -1;
4647dd7cddfSDavid du Colombier break;
4657dd7cddfSDavid du Colombier }
4667dd7cddfSDavid du Colombier /* No way around it, fill with one color first. */
4677dd7cddfSDavid du Colombier save_dest = params.dest;
4687dd7cddfSDavid du Colombier fill_rectangle((rop_ptr) & params, x & 7, w, cone);
4697dd7cddfSDavid du Colombier params.dest = save_dest;
4707dd7cddfSDavid du Colombier set_g_function(gf_XOR);
4717dd7cddfSDavid du Colombier set_s_map(czero ^ cone);
4727dd7cddfSDavid du Colombier other_color = -2; /* must reset s_map at end */
4737dd7cddfSDavid du Colombier params.invert = -1;
4747dd7cddfSDavid du Colombier break;
4757dd7cddfSDavid du Colombier case no_color: /* (other, T) */
4767dd7cddfSDavid du Colombier /* Must do 2 passes */
4777dd7cddfSDavid du Colombier other_color = czero;
4787dd7cddfSDavid du Colombier save_dest = params.dest;
4797dd7cddfSDavid du Colombier set_g_function(gf_AND);
4807dd7cddfSDavid du Colombier params.invert = 0;
4817dd7cddfSDavid du Colombier break;
4827dd7cddfSDavid du Colombier }
4837dd7cddfSDavid du Colombier break;
4847dd7cddfSDavid du Colombier }
4857dd7cddfSDavid du Colombier /* Actually copy the bits. */
4867dd7cddfSDavid du Colombier dleft = 8 - (x & 7);
4877dd7cddfSDavid du Colombier mask = 0xff >> (8 - dleft);
4887dd7cddfSDavid du Colombier count = w - dleft;
4897dd7cddfSDavid du Colombier if (count < 0)
4907dd7cddfSDavid du Colombier mask -= mask >> w,
4917dd7cddfSDavid du Colombier rmask = 0;
4927dd7cddfSDavid du Colombier else
4937dd7cddfSDavid du Colombier rmask = 0xff00 >> (count & 7);
4947dd7cddfSDavid du Colombier /* params: dest, src, sraster, height, shift, invert */
4957dd7cddfSDavid du Colombier /* Smashes params.src, params.dest, count. */
4967dd7cddfSDavid du Colombier copy:set_g_mask(mask);
4977dd7cddfSDavid du Colombier if (params.shift == 0) { /* optimize the aligned case *//* Do left column */
4987dd7cddfSDavid du Colombier memrwcol0((rop_ptr) & params);
4997dd7cddfSDavid du Colombier /* Do center */
5007dd7cddfSDavid du Colombier if ((count -= 8) >= 0) {
5017dd7cddfSDavid du Colombier out_g_mask(0xff);
5027dd7cddfSDavid du Colombier do {
5037dd7cddfSDavid du Colombier params.src++, params.dest++;
5047dd7cddfSDavid du Colombier memrwcol0((rop_ptr) & params);
5057dd7cddfSDavid du Colombier }
5067dd7cddfSDavid du Colombier while ((count -= 8) >= 0);
5077dd7cddfSDavid du Colombier }
5087dd7cddfSDavid du Colombier /* Do right column */
5097dd7cddfSDavid du Colombier if (rmask) {
5107dd7cddfSDavid du Colombier params.src++, params.dest++;
5117dd7cddfSDavid du Colombier out_g_mask(rmask);
5127dd7cddfSDavid du Colombier memrwcol0((rop_ptr) & params);
5137dd7cddfSDavid du Colombier }
5147dd7cddfSDavid du Colombier } else { /* Do left column */
5157dd7cddfSDavid du Colombier int sleft = 8 - (sourcex & 7);
5167dd7cddfSDavid du Colombier
5177dd7cddfSDavid du Colombier if (sleft >= dleft) { /* Source fits in one byte */
5187dd7cddfSDavid du Colombier memrwcol((rop_ptr) & params);
5197dd7cddfSDavid du Colombier } else if (w <= sleft) { /* Source fits in one byte, thin case */
5207dd7cddfSDavid du Colombier memrwcol((rop_ptr) & params);
5217dd7cddfSDavid du Colombier goto fin;
5227dd7cddfSDavid du Colombier } else {
5237dd7cddfSDavid du Colombier memrwcol2((rop_ptr) & params);
5247dd7cddfSDavid du Colombier params.src++;
5257dd7cddfSDavid du Colombier }
5267dd7cddfSDavid du Colombier /* Do center */
5277dd7cddfSDavid du Colombier if ((count -= 8) >= 0) {
5287dd7cddfSDavid du Colombier out_g_mask(0xff);
5297dd7cddfSDavid du Colombier do {
5307dd7cddfSDavid du Colombier params.dest++;
5317dd7cddfSDavid du Colombier memrwcol2((rop_ptr) & params);
5327dd7cddfSDavid du Colombier params.src++;
5337dd7cddfSDavid du Colombier }
5347dd7cddfSDavid du Colombier while ((count -= 8) >= 0);
5357dd7cddfSDavid du Colombier }
5367dd7cddfSDavid du Colombier /* Do right column */
5377dd7cddfSDavid du Colombier if (rmask) {
5387dd7cddfSDavid du Colombier out_g_mask(rmask);
5397dd7cddfSDavid du Colombier params.dest++;
5407dd7cddfSDavid du Colombier if (count + 8 <= params.shift)
5417dd7cddfSDavid du Colombier memrwcol((rop_ptr) & params);
5427dd7cddfSDavid du Colombier else
5437dd7cddfSDavid du Colombier memrwcol2((rop_ptr) & params);
5447dd7cddfSDavid du Colombier }
5457dd7cddfSDavid du Colombier }
5467dd7cddfSDavid du Colombier fin:if (other_color != -1) {
5477dd7cddfSDavid du Colombier if (other_color >= 0) { /* Do the second pass on (T, other) or (other, T). */
5487dd7cddfSDavid du Colombier count = w - dleft;
5497dd7cddfSDavid du Colombier params.src = base + (sourcex >> 3);
5507dd7cddfSDavid du Colombier params.dest = save_dest;
5517dd7cddfSDavid du Colombier params.invert ^= -1;
5527dd7cddfSDavid du Colombier set_s_map(other_color);
5537dd7cddfSDavid du Colombier set_g_function(gf_OR);
5547dd7cddfSDavid du Colombier other_color = -2;
5557dd7cddfSDavid du Colombier goto copy;
5567dd7cddfSDavid du Colombier } else { /* Finished second pass, restore s_map */
5577dd7cddfSDavid du Colombier set_s_map(-1);
5587dd7cddfSDavid du Colombier }
5597dd7cddfSDavid du Colombier }
5607dd7cddfSDavid du Colombier set_g_function(gf_WRITE);
5617dd7cddfSDavid du Colombier set_g_const_map(0);
5627dd7cddfSDavid du Colombier dot_end();
5637dd7cddfSDavid du Colombier return 0;
5647dd7cddfSDavid du Colombier #undef czero
5657dd7cddfSDavid du Colombier #undef cone
5667dd7cddfSDavid du Colombier }
5677dd7cddfSDavid du Colombier
5687dd7cddfSDavid du Colombier /* Copy a color pixelmap. This is just like a bitmap, */
5697dd7cddfSDavid du Colombier /* except that each pixel takes 4 bits instead of 1. */
5707dd7cddfSDavid du Colombier int
ega_copy_color(gx_device * dev,const byte * base,int sourcex,int raster,gx_bitmap_id id,int x,int y,int w,int h)5717dd7cddfSDavid du Colombier ega_copy_color(gx_device * dev,
5727dd7cddfSDavid du Colombier const byte * base, int sourcex, int raster, gx_bitmap_id id,
5737dd7cddfSDavid du Colombier int x, int y, int w, int h)
5747dd7cddfSDavid du Colombier {
5757dd7cddfSDavid du Colombier const byte *line = base + (sourcex >> 1);
5767dd7cddfSDavid du Colombier unsigned mask = 0x80 >> (x & 7);
5777dd7cddfSDavid du Colombier int px = sourcex & 1;
5787dd7cddfSDavid du Colombier fb_ptr fb_line;
5797dd7cddfSDavid du Colombier int fb_raster = fb_dev->raster;
5807dd7cddfSDavid du Colombier
5817dd7cddfSDavid du Colombier fit_copy(dev, base, sourcex, raster, id, x, y, w, h);
5827dd7cddfSDavid du Colombier fb_line = mk_fb_ptr(x, y);
5837dd7cddfSDavid du Colombier set_g_mode(gm_FILL);
5847dd7cddfSDavid du Colombier select_g_mask();
5857dd7cddfSDavid du Colombier for (;; px++) {
5867dd7cddfSDavid du Colombier const byte *bptr = line;
5877dd7cddfSDavid du Colombier fb_ptr fbptr = fb_line;
5887dd7cddfSDavid du Colombier int py = h;
5897dd7cddfSDavid du Colombier
5907dd7cddfSDavid du Colombier out_g_mask(mask);
5917dd7cddfSDavid du Colombier if (px & 1) {
5927dd7cddfSDavid du Colombier do {
5937dd7cddfSDavid du Colombier byte_discard(*fbptr); /* latch frame buffer data */
5947dd7cddfSDavid du Colombier *fbptr = *bptr;
5957dd7cddfSDavid du Colombier bptr += raster;
5967dd7cddfSDavid du Colombier fbptr += fb_raster;
5977dd7cddfSDavid du Colombier }
5987dd7cddfSDavid du Colombier while (--py);
5997dd7cddfSDavid du Colombier line++;
6007dd7cddfSDavid du Colombier } else {
6017dd7cddfSDavid du Colombier do {
6027dd7cddfSDavid du Colombier byte_discard(*fbptr); /* latch frame buffer data */
6037dd7cddfSDavid du Colombier *fbptr = *bptr >> 4;
6047dd7cddfSDavid du Colombier bptr += raster;
6057dd7cddfSDavid du Colombier fbptr += fb_raster;
6067dd7cddfSDavid du Colombier }
6077dd7cddfSDavid du Colombier while (--py);
6087dd7cddfSDavid du Colombier }
6097dd7cddfSDavid du Colombier if (!--w)
6107dd7cddfSDavid du Colombier break;
6117dd7cddfSDavid du Colombier if ((mask >>= 1) == 0)
6127dd7cddfSDavid du Colombier mask = 0x80, fb_line++;
6137dd7cddfSDavid du Colombier }
6147dd7cddfSDavid du Colombier set_g_mode(gm_DATA);
6157dd7cddfSDavid du Colombier dot_end();
6167dd7cddfSDavid du Colombier return 0;
6177dd7cddfSDavid du Colombier }
6187dd7cddfSDavid du Colombier
6197dd7cddfSDavid du Colombier /* Fill a rectangle. */
6207dd7cddfSDavid du Colombier int
ega_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)6217dd7cddfSDavid du Colombier ega_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
6227dd7cddfSDavid du Colombier gx_color_index color)
6237dd7cddfSDavid du Colombier {
6247dd7cddfSDavid du Colombier rop_params params;
6257dd7cddfSDavid du Colombier
6267dd7cddfSDavid du Colombier fit_fill(dev, x, y, w, h);
6277dd7cddfSDavid du Colombier params.dest = mk_fb_ptr(x, y);
6287dd7cddfSDavid du Colombier if (h == 1)
6297dd7cddfSDavid du Colombier fill_row_only(params.dest, x & 7, w, (int)color);
6307dd7cddfSDavid du Colombier else {
6317dd7cddfSDavid du Colombier params.draster = fb_dev->raster;
6327dd7cddfSDavid du Colombier params.height = h;
6337dd7cddfSDavid du Colombier fill_rectangle((rop_ptr) & params, x & 7, w, (int)color);
6347dd7cddfSDavid du Colombier dot_end();
6357dd7cddfSDavid du Colombier }
6367dd7cddfSDavid du Colombier return 0;
6377dd7cddfSDavid du Colombier }
6387dd7cddfSDavid du Colombier
6397dd7cddfSDavid du Colombier /* Tile a rectangle. Note that the two colors must both be supplied, */
6407dd7cddfSDavid du Colombier /* i.e. neither one can be gx_no_color_index (transparent): */
6417dd7cddfSDavid du Colombier /* a transparent color means that the tile is colored, not a mask. */
6427dd7cddfSDavid du Colombier int
ega_tile_rectangle(gx_device * dev,const gx_tile_bitmap * tile,int x,int y,int w,int h,gx_color_index czero,gx_color_index cone,int px,int py)6437dd7cddfSDavid du Colombier ega_tile_rectangle(gx_device * dev, const gx_tile_bitmap * tile,
6447dd7cddfSDavid du Colombier int x, int y, int w, int h, gx_color_index czero, gx_color_index cone,
6457dd7cddfSDavid du Colombier int px, int py)
6467dd7cddfSDavid du Colombier #define zero (int)czero
6477dd7cddfSDavid du Colombier #define one (int)cone
6487dd7cddfSDavid du Colombier {
6497dd7cddfSDavid du Colombier rop_params params;
6507dd7cddfSDavid du Colombier int xmod, width_bytes;
6517dd7cddfSDavid du Colombier int tile_height = tile->size.y;
6527dd7cddfSDavid du Colombier int xbit;
6537dd7cddfSDavid du Colombier int lcount;
6547dd7cddfSDavid du Colombier int mask, rmask;
6557dd7cddfSDavid du Colombier byte narrow;
6567dd7cddfSDavid du Colombier byte again;
6577dd7cddfSDavid du Colombier int const_bits, maps;
6587dd7cddfSDavid du Colombier int ymod, yleft;
6597dd7cddfSDavid du Colombier
6607dd7cddfSDavid du Colombier fit_fill(dev, x, y, w, h);
6617dd7cddfSDavid du Colombier /* We only handle the easiest cases directly. */
6627dd7cddfSDavid du Colombier if ((tile->size.x & 7) || one == -1 || zero == -1 || px || py)
6637dd7cddfSDavid du Colombier return gx_default_tile_rectangle(dev, tile, x, y, w, h,
6647dd7cddfSDavid du Colombier czero, cone, px, py);
6657dd7cddfSDavid du Colombier /* Following is similar to aligned case of copy_mono */
6667dd7cddfSDavid du Colombier params.dest = mk_fb_ptr(x, y);
6677dd7cddfSDavid du Colombier params.draster = fb_dev->raster;
6687dd7cddfSDavid du Colombier params.sraster = tile->raster;
6697dd7cddfSDavid du Colombier params.shift = 0;
6707dd7cddfSDavid du Colombier xbit = x & 7;
6717dd7cddfSDavid du Colombier /* Set up the graphics registers */
6727dd7cddfSDavid du Colombier const_bits = (zero ^ one) ^ 0xf;
6737dd7cddfSDavid du Colombier if (const_bits) {
6747dd7cddfSDavid du Colombier set_g_const(zero); /* either color will do */
6757dd7cddfSDavid du Colombier set_g_const_map(const_bits);
6767dd7cddfSDavid du Colombier }
6777dd7cddfSDavid du Colombier if ((maps = zero & ~one) != 0) {
6787dd7cddfSDavid du Colombier set_s_map(maps += const_bits);
6797dd7cddfSDavid du Colombier params.invert = -1;
6807dd7cddfSDavid du Colombier again = one & ~zero;
6817dd7cddfSDavid du Colombier } else {
6827dd7cddfSDavid du Colombier maps = one & ~zero;
6837dd7cddfSDavid du Colombier set_s_map(maps += const_bits);
6847dd7cddfSDavid du Colombier params.invert = 0;
6857dd7cddfSDavid du Colombier again = 0;
6867dd7cddfSDavid du Colombier }
6877dd7cddfSDavid du Colombier xmod = (x % tile->size.x) >> 3;
6887dd7cddfSDavid du Colombier width_bytes = tile->size.x >> 3;
6897dd7cddfSDavid du Colombier mask = 0xff >> xbit;
6907dd7cddfSDavid du Colombier if (w + xbit <= 8)
6917dd7cddfSDavid du Colombier mask -= mask >> w,
6927dd7cddfSDavid du Colombier rmask = 0,
6937dd7cddfSDavid du Colombier narrow = 1;
6947dd7cddfSDavid du Colombier else {
6957dd7cddfSDavid du Colombier rmask = (0xff00 >> ((w + x) & 7)) & 0xff;
6967dd7cddfSDavid du Colombier if (xbit)
6977dd7cddfSDavid du Colombier w += xbit - 8;
6987dd7cddfSDavid du Colombier else
6997dd7cddfSDavid du Colombier mask = 0, --xmod, --params.dest;
7007dd7cddfSDavid du Colombier narrow = 0;
7017dd7cddfSDavid du Colombier }
7027dd7cddfSDavid du Colombier ymod = y % tile_height;
7037dd7cddfSDavid du Colombier tile:yleft = tile_height - ymod;
7047dd7cddfSDavid du Colombier params.src = tile->data + ymod * params.sraster + xmod;
7057dd7cddfSDavid du Colombier lcount = h;
7067dd7cddfSDavid du Colombier if (narrow) { /* Optimize narrow case */
7077dd7cddfSDavid du Colombier set_g_mask(mask);
7087dd7cddfSDavid du Colombier if (lcount > yleft) {
7097dd7cddfSDavid du Colombier params.height = yleft;
7107dd7cddfSDavid du Colombier memrwcol0((rop_ptr) & params);
7117dd7cddfSDavid du Colombier params.dest += yleft * params.draster;
7127dd7cddfSDavid du Colombier params.src = tile->data + xmod;
7137dd7cddfSDavid du Colombier params.height = tile_height;
7147dd7cddfSDavid du Colombier lcount -= yleft;
7157dd7cddfSDavid du Colombier while (lcount >= tile_height) {
7167dd7cddfSDavid du Colombier memrwcol0((rop_ptr) & params);
7177dd7cddfSDavid du Colombier params.dest += tile_height * params.draster;
7187dd7cddfSDavid du Colombier lcount -= tile_height;
7197dd7cddfSDavid du Colombier }
7207dd7cddfSDavid du Colombier }
7217dd7cddfSDavid du Colombier if (lcount) {
7227dd7cddfSDavid du Colombier params.height = lcount;
7237dd7cddfSDavid du Colombier memrwcol0((rop_ptr) & params);
7247dd7cddfSDavid du Colombier }
7257dd7cddfSDavid du Colombier } else {
7267dd7cddfSDavid du Colombier fb_ptr line = params.dest;
7277dd7cddfSDavid du Colombier int xpos = width_bytes - xmod;
7287dd7cddfSDavid du Colombier
7297dd7cddfSDavid du Colombier while (1) {
7307dd7cddfSDavid du Colombier int xleft = xpos;
7317dd7cddfSDavid du Colombier int count = w;
7327dd7cddfSDavid du Colombier
7337dd7cddfSDavid du Colombier params.height = (lcount > yleft ? yleft : lcount);
7347dd7cddfSDavid du Colombier /* Do first byte, if not a full byte. */
7357dd7cddfSDavid du Colombier if (mask) {
7367dd7cddfSDavid du Colombier set_g_mask(mask);
7377dd7cddfSDavid du Colombier memrwcol0((rop_ptr) & params);
7387dd7cddfSDavid du Colombier }
7397dd7cddfSDavid du Colombier /* Do full bytes */
7407dd7cddfSDavid du Colombier if ((count -= 8) >= 0) {
7417dd7cddfSDavid du Colombier set_g_mask(0xff);
7427dd7cddfSDavid du Colombier do {
7437dd7cddfSDavid du Colombier if (!--xleft)
7447dd7cddfSDavid du Colombier xleft = width_bytes,
7457dd7cddfSDavid du Colombier params.src -= width_bytes;
7467dd7cddfSDavid du Colombier ++params.src, ++params.dest;
7477dd7cddfSDavid du Colombier memrwcol0((rop_ptr) & params);
7487dd7cddfSDavid du Colombier }
7497dd7cddfSDavid du Colombier while ((count -= 8) >= 0);
7507dd7cddfSDavid du Colombier }
7517dd7cddfSDavid du Colombier /* Do last byte */
7527dd7cddfSDavid du Colombier if (rmask) {
7537dd7cddfSDavid du Colombier if (!--xleft)
7547dd7cddfSDavid du Colombier xleft = width_bytes,
7557dd7cddfSDavid du Colombier params.src -= width_bytes;
7567dd7cddfSDavid du Colombier set_g_mask(rmask);
7577dd7cddfSDavid du Colombier ++params.src, ++params.dest;
7587dd7cddfSDavid du Colombier memrwcol0((rop_ptr) & params);
7597dd7cddfSDavid du Colombier }
7607dd7cddfSDavid du Colombier if ((lcount -= params.height) == 0)
7617dd7cddfSDavid du Colombier break;
7627dd7cddfSDavid du Colombier params.dest = line += params.height * params.draster;
7637dd7cddfSDavid du Colombier params.src = tile->data + xmod;
7647dd7cddfSDavid du Colombier yleft = tile_height;
7657dd7cddfSDavid du Colombier }
7667dd7cddfSDavid du Colombier }
7677dd7cddfSDavid du Colombier /* Now do the second color if needed */
7687dd7cddfSDavid du Colombier if (again) {
7697dd7cddfSDavid du Colombier maps = again + const_bits;
7707dd7cddfSDavid du Colombier set_s_map(maps);
7717dd7cddfSDavid du Colombier again = 0;
7727dd7cddfSDavid du Colombier params.dest = mk_fb_ptr(x, y);
7737dd7cddfSDavid du Colombier if (mask == 0)
7747dd7cddfSDavid du Colombier params.dest--;
7757dd7cddfSDavid du Colombier params.invert = 0;
7767dd7cddfSDavid du Colombier goto tile;
7777dd7cddfSDavid du Colombier }
7787dd7cddfSDavid du Colombier if (maps != 0xf)
7797dd7cddfSDavid du Colombier set_s_map(-1);
7807dd7cddfSDavid du Colombier if (const_bits)
7817dd7cddfSDavid du Colombier set_g_const_map(0);
7827dd7cddfSDavid du Colombier dot_end();
7837dd7cddfSDavid du Colombier return 0;
7847dd7cddfSDavid du Colombier }
7857dd7cddfSDavid du Colombier
7867dd7cddfSDavid du Colombier /* Read scan lines back from the frame buffer. */
7877dd7cddfSDavid du Colombier int
ega_get_bits(gx_device * dev,int y,byte * data,byte ** actual_data)7887dd7cddfSDavid du Colombier ega_get_bits(gx_device * dev, int y, byte * data, byte ** actual_data)
7897dd7cddfSDavid du Colombier { /* The maximum width for an EGA/VGA device is 800 pixels.... */
7907dd7cddfSDavid du Colombier int width_bytes = (dev->width + 7) >> 3;
7917dd7cddfSDavid du Colombier int i;
7927dd7cddfSDavid du Colombier bits32 *dest;
7937dd7cddfSDavid du Colombier const byte *src;
7947dd7cddfSDavid du Colombier const byte *end;
7957dd7cddfSDavid du Colombier byte planes[100 * 4];
7967dd7cddfSDavid du Colombier
7977dd7cddfSDavid du Colombier /* Plane 0 is the least significant plane. */
7987dd7cddfSDavid du Colombier /* We know we're on a little-endian machine.... */
7997dd7cddfSDavid du Colombier #define spread4(v)\
8007dd7cddfSDavid du Colombier v+0x00000000, v+0x08000000, v+0x80000000, v+0x88000000,\
8017dd7cddfSDavid du Colombier v+0x00080000, v+0x08080000, v+0x80080000, v+0x88080000,\
8027dd7cddfSDavid du Colombier v+0x00800000, v+0x08800000, v+0x80800000, v+0x88800000,\
8037dd7cddfSDavid du Colombier v+0x00880000, v+0x08880000, v+0x80880000, v+0x88880000
8047dd7cddfSDavid du Colombier static const bits32 spread8[256] =
8057dd7cddfSDavid du Colombier {spread4(0x0000), spread4(0x0800),
8067dd7cddfSDavid du Colombier spread4(0x8000), spread4(0x8800),
8077dd7cddfSDavid du Colombier spread4(0x0008), spread4(0x0808),
8087dd7cddfSDavid du Colombier spread4(0x8008), spread4(0x8808),
8097dd7cddfSDavid du Colombier spread4(0x0080), spread4(0x0880),
8107dd7cddfSDavid du Colombier spread4(0x8080), spread4(0x8880),
8117dd7cddfSDavid du Colombier spread4(0x0088), spread4(0x0888),
8127dd7cddfSDavid du Colombier spread4(0x8088), spread4(0x8888)
8137dd7cddfSDavid du Colombier };
8147dd7cddfSDavid du Colombier
8157dd7cddfSDavid du Colombier if (y < 0 || y >= dev->height || dev->width > 800)
8167dd7cddfSDavid du Colombier return_error(gs_error_rangecheck);
8177dd7cddfSDavid du Colombier /* Read 4 planes into the holding buffer. */
8187dd7cddfSDavid du Colombier for (i = 0; i < 4; ++i) {
8197dd7cddfSDavid du Colombier set_g_read_plane(i);
8207dd7cddfSDavid du Colombier memcpy(planes + 100 * i, mk_fb_ptr(0, y), width_bytes);
8217dd7cddfSDavid du Colombier }
8227dd7cddfSDavid du Colombier /* Now assemble the final data from the planes. */
8237dd7cddfSDavid du Colombier for (dest = (bits32 *) data, src = planes, end = src + width_bytes;
8247dd7cddfSDavid du Colombier src < end; ++dest, ++src
8257dd7cddfSDavid du Colombier )
8267dd7cddfSDavid du Colombier *dest = (((((spread8[src[0]] >> 1) | spread8[src[100]]) >> 1) |
8277dd7cddfSDavid du Colombier spread8[src[200]]) >> 1) | spread8[src[300]];
8287dd7cddfSDavid du Colombier if (actual_data != 0)
8297dd7cddfSDavid du Colombier *actual_data = data;
8307dd7cddfSDavid du Colombier return 0;
8317dd7cddfSDavid du Colombier }
8327dd7cddfSDavid du Colombier
8337dd7cddfSDavid du Colombier /* ------ Internal routines ------ */
8347dd7cddfSDavid du Colombier
8357dd7cddfSDavid du Colombier /* Mask table for rectangle fill. */
8367dd7cddfSDavid du Colombier static const byte rmask_tab[9] =
8377dd7cddfSDavid du Colombier {0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff
8387dd7cddfSDavid du Colombier };
8397dd7cddfSDavid du Colombier
8407dd7cddfSDavid du Colombier /* Fill a rectangle specified by pointer into frame buffer, */
8417dd7cddfSDavid du Colombier /* starting bit within byte, width, and height. */
8427dd7cddfSDavid du Colombier /* Smashes rop->dest. */
8437dd7cddfSDavid du Colombier private void
fill_rectangle(register rop_ptr rop,int bit,int w,int color)8447dd7cddfSDavid du Colombier fill_rectangle(register rop_ptr rop, int bit, int w, int color)
8457dd7cddfSDavid du Colombier /* rop: dest, draster, height */
8467dd7cddfSDavid du Colombier {
8477dd7cddfSDavid du Colombier set_g_const(color);
8487dd7cddfSDavid du Colombier set_g_const_map(0xf);
8497dd7cddfSDavid du Colombier select_g_mask();
8507dd7cddfSDavid du Colombier if (bit + w <= 8) { /* Less than one byte */
8517dd7cddfSDavid du Colombier out_g_mask(rmask_tab[w] >> bit);
8527dd7cddfSDavid du Colombier memsetcol(rop);
8537dd7cddfSDavid du Colombier } else {
8547dd7cddfSDavid du Colombier byte right_mask;
8557dd7cddfSDavid du Colombier
8567dd7cddfSDavid du Colombier if (bit) {
8577dd7cddfSDavid du Colombier out_g_mask(0xff >> bit);
8587dd7cddfSDavid du Colombier memsetcol(rop);
8597dd7cddfSDavid du Colombier rop->dest++;
8607dd7cddfSDavid du Colombier w += bit - 8;
8617dd7cddfSDavid du Colombier }
8627dd7cddfSDavid du Colombier if (w >= 8) {
8637dd7cddfSDavid du Colombier out_g_mask(0xff); /* all bits */
8647dd7cddfSDavid du Colombier rop->width = w >> 3;
8657dd7cddfSDavid du Colombier memsetrect(rop);
8667dd7cddfSDavid du Colombier rop->dest += rop->width;
8677dd7cddfSDavid du Colombier w &= 7;
8687dd7cddfSDavid du Colombier }
8697dd7cddfSDavid du Colombier if ((right_mask = rmask_tab[w]) != 0) {
8707dd7cddfSDavid du Colombier out_g_mask(right_mask);
8717dd7cddfSDavid du Colombier memsetcol(rop);
8727dd7cddfSDavid du Colombier }
8737dd7cddfSDavid du Colombier }
8747dd7cddfSDavid du Colombier set_g_const_map(0);
8757dd7cddfSDavid du Colombier }
8767dd7cddfSDavid du Colombier
8777dd7cddfSDavid du Colombier /* Fill a single row specified by pointer into frame buffer, */
8787dd7cddfSDavid du Colombier /* starting bit within byte, and width; clean up afterwards. */
8797dd7cddfSDavid du Colombier #define r_m_w(ptr) (*(ptr))++ /* read & write, data irrelevant */
8807dd7cddfSDavid du Colombier private void
fill_row_only(byte * dest,int bit,int w,int color)8817dd7cddfSDavid du Colombier fill_row_only(byte * dest, int bit, int w, int color)
8827dd7cddfSDavid du Colombier /* rop: dest */
8837dd7cddfSDavid du Colombier {
8847dd7cddfSDavid du Colombier if (bit + w <= 8) { /* Less than one byte. */
8857dd7cddfSDavid du Colombier /* Optimize filling with black or white. */
8867dd7cddfSDavid du Colombier switch (color) {
8877dd7cddfSDavid du Colombier case 0:
8887dd7cddfSDavid du Colombier set_g_mask(rmask_tab[w] >> bit);
8897dd7cddfSDavid du Colombier *dest &= color; /* read, then write 0s; */
8907dd7cddfSDavid du Colombier /* some compilers optimize &= 0 to a store. */
8917dd7cddfSDavid du Colombier out_g_mask(0xff); /* dot_end */
8927dd7cddfSDavid du Colombier break;
8937dd7cddfSDavid du Colombier case 0xf:
8947dd7cddfSDavid du Colombier set_g_mask(rmask_tab[w] >> bit);
8957dd7cddfSDavid du Colombier *dest |= 0xff; /* read, then write 1s; */
8967dd7cddfSDavid du Colombier /* some compilers optimize &= 0 to a store. */
8977dd7cddfSDavid du Colombier out_g_mask(0xff); /* dot_end */
8987dd7cddfSDavid du Colombier break;
8997dd7cddfSDavid du Colombier default:
9007dd7cddfSDavid du Colombier set_g_const(color);
9017dd7cddfSDavid du Colombier set_g_const_map(0xf);
9027dd7cddfSDavid du Colombier set_g_mask(rmask_tab[w] >> bit);
9037dd7cddfSDavid du Colombier r_m_w(dest);
9047dd7cddfSDavid du Colombier out_g_mask(0xff); /* dot_end */
9057dd7cddfSDavid du Colombier set_g_const_map(0);
9067dd7cddfSDavid du Colombier }
9077dd7cddfSDavid du Colombier } else {
9087dd7cddfSDavid du Colombier byte right_mask;
9097dd7cddfSDavid du Colombier int byte_count;
9107dd7cddfSDavid du Colombier
9117dd7cddfSDavid du Colombier set_g_const(color);
9127dd7cddfSDavid du Colombier set_g_const_map(0xf);
9137dd7cddfSDavid du Colombier select_g_mask();
9147dd7cddfSDavid du Colombier if (bit) {
9157dd7cddfSDavid du Colombier out_g_mask(0xff >> bit);
9167dd7cddfSDavid du Colombier r_m_w(dest);
9177dd7cddfSDavid du Colombier dest++;
9187dd7cddfSDavid du Colombier w += bit - 8;
9197dd7cddfSDavid du Colombier }
9207dd7cddfSDavid du Colombier byte_count = w >> 3;
9217dd7cddfSDavid du Colombier if ((right_mask = rmask_tab[w & 7]) != 0) {
9227dd7cddfSDavid du Colombier out_g_mask(right_mask);
9237dd7cddfSDavid du Colombier r_m_w(dest + byte_count);
9247dd7cddfSDavid du Colombier }
9257dd7cddfSDavid du Colombier out_g_mask(0xff);
9267dd7cddfSDavid du Colombier if (byte_count) {
9277dd7cddfSDavid du Colombier memset(dest, 0, byte_count); /* data irrelevant */
9287dd7cddfSDavid du Colombier }
9297dd7cddfSDavid du Colombier set_g_const_map(0);
9307dd7cddfSDavid du Colombier }
9317dd7cddfSDavid du Colombier }
932