~ubuntu-branches/ubuntu/jaunty/ghostscript/jaunty-updates

« back to all changes in this revision

Viewing changes to base/gdevsvga.c

  • Committer: Bazaar Package Importer
  • Author(s): Till Kamppeter
  • Date: 2009-01-20 16:40:45 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20090120164045-lnfhi0n30o5lwhwa
Tags: 8.64.dfsg.1~svn9377-0ubuntu1
* New upstream release (SVN rev 9377)
   o Fixes many bugs concerning PDF rendering, to make the PDF printing
     workflow correctly working.
   o Fixes long-standing bugs in many drivers, like input paper tray and
     duplex options not working for the built-in PCL 4, 5, 5c, 5e, and
     6/XL drivers, PDF input not working for bjc600, bjc800, and cups
     output devices, several options not working and uninitialized
     memory with cups output device.
   o Merged nearly all patches of the Ubuntu and Debian packages upstream.
   o Fixes LP: #317810, LP: #314439, LP: #314018.
* debian/patches/03_libpaper_support.dpatch,
  debian/patches/11_gs-cjk_font_glyph_handling_fix.dpatch,
  debian/patches/12_gs-cjk_vertical_writing_metrics_fix.dpatch,
  debian/patches/13_gs-cjk_cjkps_examples.dpatch,
  debian/patches/20_bbox_segv_fix.dpatch,
  debian/patches/21_brother_7x0_gdi_fix.dpatch,
  debian/patches/22_epsn_margin_workaround.dpatch,
  debian/patches/24_gs_man_fix.dpatch,
  debian/patches/25_toolbin_insecure_tmp_usage_fix.dpatch,
  debian/patches/26_assorted_script_fixes.dpatch,
  debian/patches/29_gs_css_fix.dpatch,
  debian/patches/30_ps2pdf_man_improvement.dpatch,
  debian/patches/31_fix-gc-sigbus.dpatch,
  debian/patches/34_ftbfs-on-hurd-fix.dpatch,
  debian/patches/35_disable_libcairo.dpatch,
  debian/patches/38_pxl-duplex.dpatch,
  debian/patches/39_pxl-resolution.dpatch,
  debian/patches/42_gs-init-ps-delaybind-fix.dpatch,
  debian/patches/45_bjc600-bjc800-pdf-input.dpatch,
  debian/patches/48_cups-output-device-pdf-duplex-uninitialized-memory-fix.dpatch,
  debian/patches/50_lips4-floating-point-exception.dpatch,
  debian/patches/52_cups-device-logging.dpatch,
  debian/patches/55_pcl-input-slot-fix.dpatch,
  debian/patches/57_pxl-input-slot-fix.dpatch,
  debian/patches/60_pxl-cups-driver-pdf.dpatch,
  debian/patches/62_onebitcmyk-pdf.dpatch,
  debian/patches/65_too-big-temp-files-1.dpatch,
  debian/patches/67_too-big-temp-files-2.dpatch,
  debian/patches/70_take-into-account-data-in-stream-buffer-before-refill.dpatch:
  Removed, applied upstream.
* debian/patches/01_docdir_fix_for_debian.dpatch,
  debian/patches/02_gs_man_fix_debian.dpatch,
  debian/patches/01_docdir-fix-for-debian.dpatch,
  debian/patches/02_docdir-fix-for-debian.dpatch: Renamed patches to
  make merging with Debian easier.
* debian/patches/32_improve-handling-of-media-size-changes-from-gv.dpatch, 
  debian/patches/33_bad-params-to-xinitimage-on-large-bitmaps.dpatch:
  regenerated for new source directory structure.
* debian/rules: Corrected paths to remove cidfmap (it is in Resource/Init/
  in GS 8.64) and to install headers (source paths are psi/ and base/ now).
* debian/rules: Remove all fontmaps, as DeFoMa replaces them.
* debian/local/pdftoraster/pdftoraster.c,
  debian/local/pdftoraster/pdftoraster.convs, debian/rules: Removed
  added pdftoraster filter and use the one which comes with Ghostscript.
* debian/ghostscript.links: s/8.63/8.64/

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2001-2007 Artifex Software, Inc.
 
2
   All Rights Reserved.
 
3
  
 
4
   This software is provided AS-IS with no warranty, either express or
 
5
   implied.
 
6
 
 
7
   This software is distributed under license and may not be copied, modified
 
8
   or distributed except as expressly authorized under the terms of that
 
9
   license.  Refer to licensing information at http://www.artifex.com/
 
10
   or contact Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134,
 
11
   San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
 
12
*/
 
13
 
 
14
/* $Id: gdevsvga.c 8468 2007-12-31 18:07:59Z giles $ */
 
15
/* SuperVGA display drivers */
 
16
#include "memory_.h"
 
17
#include "gx.h"
 
18
#include "gserrors.h"
 
19
#include "gxarith.h"            /* for ...log2 */
 
20
#include "gxdevice.h"
 
21
#include "gdevpccm.h"
 
22
#include "gdevpcfb.h"
 
23
#include "gdevsvga.h"
 
24
#include "gsparam.h"
 
25
 
 
26
/* The color map for dynamically assignable colors. */
 
27
#define first_dc_index 64
 
28
static int next_dc_index;
 
29
 
 
30
#define dc_hash_size 293        /* prime, >num_dc */
 
31
typedef struct {
 
32
    ushort rgb, index;
 
33
} dc_entry;
 
34
static dc_entry dynamic_colors[dc_hash_size + 1];
 
35
 
 
36
#define num_colors 255
 
37
 
 
38
/* Macro for casting gx_device argument */
 
39
#define fb_dev ((gx_device_svga *)dev)
 
40
 
 
41
/* Procedure records */
 
42
#define svga_procs(open) {\
 
43
        open, NULL /*get_initial_matrix*/,\
 
44
        NULL /*sync_output*/, NULL /*output_page*/, svga_close,\
 
45
        svga_map_rgb_color, svga_map_color_rgb,\
 
46
        svga_fill_rectangle, NULL /*tile_rectangle*/,\
 
47
        svga_copy_mono, svga_copy_color, NULL /*draw_line*/,\
 
48
        svga_get_bits, NULL /*get_params*/, svga_put_params,\
 
49
        NULL /*map_cmyk_color*/, NULL /*get_xfont_procs*/,\
 
50
        NULL /*get_xfont_device*/, NULL /*map_rgb_alpha_color*/,\
 
51
        gx_page_device_get_page_device, NULL /*get_alpha_bits*/,\
 
52
        svga_copy_alpha\
 
53
}
 
54
 
 
55
/* Save the controller mode */
 
56
static int svga_save_mode = -1;
 
57
 
 
58
/* ------ Internal routines ------ */
 
59
 
 
60
#define regen 0xa000
 
61
 
 
62
/* Construct a pointer for writing a pixel. */
 
63
/* Assume 64K pages, 64K granularity. */
 
64
/* We know that y is within bounds. */
 
65
#define set_pixel_ptr(ptr, fbdev, x, y, wnum)\
 
66
{       ulong index = (ulong)(y) * fbdev->raster + (uint)(x);\
 
67
        if ( (uint)(index >> 16) != fbdev->current_page )\
 
68
           {    (*fbdev->set_page)(fbdev, (fbdev->current_page = index >> 16), wnum);\
 
69
           }\
 
70
        ptr = (fb_ptr)MK_PTR(regen, (ushort)index);\
 
71
}
 
72
#define set_pixel_write_ptr(ptr, fbdev, x, y)\
 
73
  set_pixel_ptr(ptr, fbdev, x, y, fbdev->wnum_write)
 
74
#define set_pixel_read_ptr(ptr, fbdev, x, y)\
 
75
  set_pixel_ptr(ptr, fbdev, x, y, fbdev->wnum_read)
 
76
 
 
77
/* Find the graphics mode for a desired width and height. */
 
78
/* Set the mode in the device structure and return 0, */
 
79
/* or return an error code. */
 
80
int
 
81
svga_find_mode(gx_device * dev, const mode_info * mip)
 
82
{
 
83
    for (;; mip++) {
 
84
        if (mip->width >= fb_dev->width &&
 
85
            mip->height >= fb_dev->height ||
 
86
            mip[1].mode < 0
 
87
            ) {
 
88
            fb_dev->mode = mip;
 
89
            gx_device_adjust_resolution(dev, mip->width, mip->height, 1);
 
90
            fb_dev->raster = fb_dev->width;
 
91
            return 0;
 
92
        }
 
93
    }
 
94
    return_error(gs_error_rangecheck);
 
95
}
 
96
 
 
97
/* Set the index for writing into the color DAC. */
 
98
#define svga_dac_set_write_index(i) outportb(0x3c8, i)
 
99
 
 
100
/* Write 6-bit R,G,B values into the color DAC. */
 
101
#define svga_dac_write(r, g, b)\
 
102
  (outportb(0x3c9, r), outportb(0x3c9, g), outportb(0x3c9, b))
 
103
 
 
104
/* ------ Common procedures ------ */
 
105
 
 
106
#define cv_bits(v,n) (v >> (gx_color_value_bits - n))
 
107
 
 
108
/* Initialize the dynamic color table, if any. */
 
109
void
 
110
svga_init_colors(gx_device * dev)
 
111
{
 
112
    if (fb_dev->fixed_colors)
 
113
        next_dc_index = num_colors;
 
114
    else {
 
115
        memset(dynamic_colors, 0,
 
116
               (dc_hash_size + 1) * sizeof(dc_entry));
 
117
        next_dc_index = first_dc_index;
 
118
    }
 
119
}
 
120
 
 
121
/* Load the color DAC with the predefined colors. */
 
122
static void
 
123
svga_load_colors(gx_device * dev)
 
124
{
 
125
    int ci;
 
126
 
 
127
    svga_dac_set_write_index(0);
 
128
    if (fb_dev->fixed_colors)
 
129
        for (ci = 0; ci < num_colors; ci++) {
 
130
            gx_color_value rgb[3];
 
131
 
 
132
            pc_8bit_map_color_rgb(dev, (gx_color_index) ci, rgb);
 
133
            svga_dac_write(cv_bits(rgb[0], 6), cv_bits(rgb[1], 6),
 
134
                           cv_bits(rgb[2], 6));
 
135
    } else
 
136
        for (ci = 0; ci < 64; ci++) {
 
137
            static const byte c2[10] =
 
138
            {0, 42, 0, 0, 0, 0, 0, 0, 21, 63};
 
139
 
 
140
            svga_dac_write(c2[(ci >> 2) & 9], c2[(ci >> 1) & 9],
 
141
                           c2[ci & 9]);
 
142
        }
 
143
}
 
144
 
 
145
/* Initialize the device structure and the DACs. */
 
146
int
 
147
svga_open(gx_device * dev)
 
148
{
 
149
    fb_dev->x_pixels_per_inch =
 
150
        fb_dev->y_pixels_per_inch =
 
151
        fb_dev->height / PAGE_HEIGHT_INCHES;
 
152
    /* Set the display mode. */
 
153
    if (svga_save_mode < 0)
 
154
        svga_save_mode = (*fb_dev->get_mode) ();
 
155
    (*fb_dev->set_mode) (fb_dev->mode->mode);
 
156
    svga_init_colors(dev);
 
157
    svga_load_colors(dev);
 
158
    fb_dev->current_page = -1;
 
159
    return 0;
 
160
}
 
161
 
 
162
/* Close the device; reinitialize the display for text mode. */
 
163
int
 
164
svga_close(gx_device * dev)
 
165
{
 
166
    if (svga_save_mode >= 0)
 
167
        (*fb_dev->set_mode) (svga_save_mode);
 
168
    svga_save_mode = -1;
 
169
    return 0;
 
170
}
 
171
 
 
172
/* Map a r-g-b color to a palette index. */
 
173
/* The first 64 entries of the color map are set */
 
174
/* for compatibility with the older display modes: */
 
175
/* these are indexed as 0.0.R0.G0.B0.R1.G1.B1. */
 
176
gx_color_index
 
177
svga_map_rgb_color(gx_device * dev, const gx_color_value cv[])
 
178
{
 
179
    ushort rgb;
 
180
    gx_color_value r = cv[0], g = cv[1], b = cv[2];
 
181
 
 
182
    if (fb_dev->fixed_colors) {
 
183
        gx_color_index ci = pc_8bit_map_rgb_color(dev, cv);
 
184
 
 
185
        /* Here is where we should permute the index to match */
 
186
        /* the old color map... but we don't yet. */
 
187
        return ci;
 
188
    } {
 
189
        ushort r5 = cv_bits(r, 5), g5 = cv_bits(g, 5), b5 = cv_bits(b, 5);
 
190
        static const byte cube_bits[32] =
 
191
        {0, 128, 128, 128, 128, 128, 128, 128, 128, 128,
 
192
         8, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
 
193
         1, 128, 128, 128, 128, 128, 128, 128, 128, 128,
 
194
         9
 
195
        };
 
196
        uint cx = ((uint) cube_bits[r5] << 2) +
 
197
        ((uint) cube_bits[g5] << 1) +
 
198
        (uint) cube_bits[b5];
 
199
 
 
200
        /* Check for a color on the cube. */
 
201
        if (cx < 64)
 
202
            return (gx_color_index) cx;
 
203
        /* Not on the cube, check the dynamic color table. */
 
204
        rgb = (r5 << 10) + (g5 << 5) + b5;
 
205
    }
 
206
    {
 
207
        register dc_entry *pdc;
 
208
 
 
209
        for (pdc = &dynamic_colors[rgb % dc_hash_size];
 
210
             pdc->rgb != 0; pdc++
 
211
            )
 
212
            if (pdc->rgb == rgb)
 
213
                return (gx_color_index) (pdc->index);
 
214
        if (pdc == &dynamic_colors[dc_hash_size]) {     /* Wraparound */
 
215
            for (pdc = &dynamic_colors[0]; pdc->rgb != 0; pdc++)
 
216
                if (pdc->rgb == rgb)
 
217
                    return (gx_color_index) (pdc->index);
 
218
        }
 
219
        if (next_dc_index == num_colors) {      /* No space left, report failure. */
 
220
            return gx_no_color_index;
 
221
        }
 
222
        /* Not on the cube, and not in the dynamic table. */
 
223
        /* Put in the dynamic table if space available. */
 
224
        {
 
225
            int i = next_dc_index++;
 
226
 
 
227
            pdc->rgb = rgb;
 
228
            pdc->index = i;
 
229
            svga_dac_set_write_index(i);
 
230
            svga_dac_write(cv_bits(r, 6), cv_bits(g, 6),
 
231
                           cv_bits(b, 6));
 
232
            return (gx_color_index) i;
 
233
        }
 
234
    }
 
235
}
 
236
 
 
237
/* Map a color code to r-g-b. */
 
238
/* This routine must invert the transformation of the one above. */
 
239
/* Since this is practically never used, we just read the DAC. */
 
240
int
 
241
svga_map_color_rgb(gx_device * dev, gx_color_index color,
 
242
                   gx_color_value prgb[3])
 
243
{
 
244
    uint cval;
 
245
 
 
246
    outportb(0x3c7, (byte) color);
 
247
#define dacin() (cval = inportb(0x3c9) >> 1,\
 
248
  ((cval << 11) + (cval << 6) + (cval << 1) + (cval >> 4)) >>\
 
249
   (16 - gx_color_value_bits))
 
250
    prgb[0] = dacin();
 
251
    prgb[1] = dacin();
 
252
    prgb[2] = dacin();
 
253
#undef dacin
 
254
    return 0;
 
255
}
 
256
 
 
257
/* Fill a rectangle. */
 
258
int
 
259
svga_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
 
260
                    gx_color_index color)
 
261
{
 
262
    uint raster = fb_dev->raster;
 
263
    ushort limit = (ushort) - raster;
 
264
    int yi;
 
265
    fb_ptr ptr;
 
266
 
 
267
    fit_fill(dev, x, y, w, h);
 
268
    set_pixel_write_ptr(ptr, fb_dev, x, y);
 
269
    /* Most fills are very small and don't cross a page boundary. */
 
270
    yi = h;
 
271
    switch (w) {
 
272
        case 0:
 
273
            return 0;           /* no-op */
 
274
        case 1:
 
275
            while (--yi >= 0 && PTR_OFF(ptr) < limit)
 
276
                ptr[0] = (byte) color,
 
277
                    ptr += raster;
 
278
            if (!++yi)
 
279
                return 0;
 
280
            break;
 
281
        case 2:
 
282
            while (--yi >= 0 && PTR_OFF(ptr) < limit)
 
283
                ptr[0] = ptr[1] = (byte) color,
 
284
                    ptr += raster;
 
285
            if (!++yi)
 
286
                return 0;
 
287
            break;
 
288
        case 3:
 
289
            while (--yi >= 0 && PTR_OFF(ptr) < limit)
 
290
                ptr[0] = ptr[1] = ptr[2] = (byte) color,
 
291
                    ptr += raster;
 
292
            if (!++yi)
 
293
                return 0;
 
294
            break;
 
295
        case 4:
 
296
            while (--yi >= 0 && PTR_OFF(ptr) < limit)
 
297
                ptr[0] = ptr[1] = ptr[2] = ptr[3] = (byte) color,
 
298
                    ptr += raster;
 
299
            if (!++yi)
 
300
                return 0;
 
301
            break;
 
302
        default:
 
303
            if (w < 0)
 
304
                return 0;
 
305
            /* Check for erasepage. */
 
306
            if (w == dev->width && h == dev->height &&
 
307
                color < first_dc_index
 
308
                )
 
309
                svga_init_colors(dev);
 
310
    }
 
311
    while (--yi >= 0) {
 
312
        if (PTR_OFF(ptr) < limit) {
 
313
            memset(ptr, (byte) color, w);
 
314
            ptr += raster;
 
315
        } else if (PTR_OFF(ptr) <= (ushort) (-w)) {
 
316
            memset(ptr, (byte) color, w);
 
317
            if (yi > 0)
 
318
                set_pixel_write_ptr(ptr, fb_dev, x, y + h - yi);
 
319
        } else {
 
320
            uint left = (uint) 0x10000 - PTR_OFF(ptr);
 
321
 
 
322
            memset(ptr, (byte) color, left);
 
323
            set_pixel_write_ptr(ptr, fb_dev, x + left, y + h - 1 - yi);
 
324
            memset(ptr, (byte) color, w - left);
 
325
            ptr += raster - left;
 
326
        }
 
327
    }
 
328
    return 0;
 
329
}
 
330
 
 
331
/* Copy a monochrome bitmap.  The colors are given explicitly. */
 
332
/* Color = gx_no_color_index means transparent (no effect on the image). */
 
333
int
 
334
svga_copy_mono(gx_device * dev,
 
335
               const byte * base, int sourcex, int sraster, gx_bitmap_id id,
 
336
      int x, int y, int w, int h, gx_color_index czero, gx_color_index cone)
 
337
{
 
338
    uint raster = fb_dev->raster;
 
339
    ushort limit;
 
340
    register int wi;
 
341
    uint skip;
 
342
    int yi;
 
343
    register fb_ptr ptr = (fb_ptr) 0;
 
344
    const byte *srow;
 
345
    uint invert;
 
346
 
 
347
    fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
 
348
    limit = (ushort) - w;
 
349
    skip = raster - w + 1;
 
350
    srow = base + (sourcex >> 3);
 
351
#define izero (int)czero
 
352
#define ione (int)cone
 
353
    if (ione == no_color) {
 
354
        gx_color_index temp;
 
355
 
 
356
        if (izero == no_color)
 
357
            return 0;           /* no-op */
 
358
        temp = czero;
 
359
        czero = cone;
 
360
        cone = temp;
 
361
        invert = ~0;
 
362
    } else
 
363
        invert = 0;
 
364
    /* Pre-filling saves us a test in the loop, */
 
365
    /* and since tiling is uncommon, we come out ahead. */
 
366
    if (izero != no_color)
 
367
        svga_fill_rectangle(dev, x, y, w, h, czero);
 
368
    for (yi = 0; yi < h; yi++) {
 
369
        const byte *sptr = srow;
 
370
        uint bits;
 
371
        int bitno = sourcex & 7;
 
372
 
 
373
        wi = w;
 
374
        if (PTR_OFF(ptr) <= skip) {
 
375
            set_pixel_write_ptr(ptr, fb_dev, x, y + yi);
 
376
        } else if (PTR_OFF(ptr) > limit) {      /* We're crossing a page boundary. */
 
377
            /* This is extremely rare, so it doesn't matter */
 
378
            /* how slow it is. */
 
379
            int xi = (ushort) - PTR_OFF(ptr);
 
380
 
 
381
            svga_copy_mono(dev, srow, sourcex & 7, sraster,
 
382
                           gx_no_bitmap_id, x, y + yi, xi, 1,
 
383
                           gx_no_color_index, cone);
 
384
            set_pixel_write_ptr(ptr, fb_dev, x + xi, y + yi);
 
385
            sptr = srow - (sourcex >> 3) + ((sourcex + xi) >> 3);
 
386
            bitno = (sourcex + xi) & 7;
 
387
            wi -= xi;
 
388
        }
 
389
        bits = *sptr ^ invert;
 
390
        switch (bitno) {
 
391
#define ifbit(msk)\
 
392
  if ( bits & msk ) *ptr = (byte)ione;\
 
393
  if ( !--wi ) break; ptr++
 
394
            case 0:
 
395
              bit0:ifbit(0x80);
 
396
            case 1:
 
397
                ifbit(0x40);
 
398
            case 2:
 
399
                ifbit(0x20);
 
400
            case 3:
 
401
                ifbit(0x10);
 
402
            case 4:
 
403
                ifbit(0x08);
 
404
            case 5:
 
405
                ifbit(0x04);
 
406
            case 6:
 
407
                ifbit(0x02);
 
408
            case 7:
 
409
                ifbit(0x01);
 
410
#undef ifbit
 
411
                bits = *++sptr ^ invert;
 
412
                goto bit0;
 
413
        }
 
414
        ptr += skip;
 
415
        srow += sraster;
 
416
    }
 
417
#undef izero
 
418
#undef ione
 
419
    return 0;
 
420
}
 
421
 
 
422
/* Copy a color pixelmap.  This is just like a bitmap, */
 
423
/* except that each pixel takes 8 bits instead of 1. */
 
424
int
 
425
svga_copy_color(gx_device * dev,
 
426
                const byte * base, int sourcex, int sraster, gx_bitmap_id id,
 
427
                int x, int y, int w, int h)
 
428
{
 
429
    int xi, yi;
 
430
    int skip;
 
431
    const byte *sptr;
 
432
    fb_ptr ptr;
 
433
 
 
434
    fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
 
435
    skip = sraster - w;
 
436
    sptr = base + sourcex;
 
437
    for (yi = y; yi - y < h; yi++) {
 
438
        ptr = 0;
 
439
        for (xi = x; xi - x < w; xi++) {
 
440
            if (PTR_OFF(ptr) == 0)
 
441
                set_pixel_write_ptr(ptr, fb_dev, xi, yi);
 
442
            *ptr++ = *sptr++;
 
443
        }
 
444
        sptr += skip;
 
445
    }
 
446
    return 0;
 
447
}
 
448
 
 
449
/* Put parameters. */
 
450
int
 
451
svga_put_params(gx_device * dev, gs_param_list * plist)
 
452
{
 
453
    int ecode = 0;
 
454
    int code;
 
455
    const char *param_name;
 
456
 
 
457
    if ((code = ecode) < 0 ||
 
458
        (code = gx_default_put_params(dev, plist)) < 0
 
459
        ) {
 
460
    }
 
461
    return code;
 
462
}
 
463
 
 
464
/* Read scan lines back from the frame buffer. */
 
465
int
 
466
svga_get_bits(gx_device * dev, int y, byte * data, byte ** actual_data)
 
467
{
 
468
    uint bytes_per_row = dev->width;
 
469
    ushort limit = (ushort) - bytes_per_row;
 
470
    fb_ptr src;
 
471
 
 
472
    if (y < 0 || y >= dev->height)
 
473
        return gs_error_rangecheck;
 
474
    set_pixel_read_ptr(src, fb_dev, 0, y);
 
475
    /* The logic here is similar to fill_rectangle. */
 
476
    if (PTR_OFF(src) <= limit)
 
477
        memcpy(data, src, bytes_per_row);
 
478
    else {
 
479
        uint left = (uint) 0x10000 - PTR_OFF(src);
 
480
 
 
481
        memcpy(data, src, left);
 
482
        set_pixel_read_ptr(src, fb_dev, left, y);
 
483
        memcpy(data + left, src, bytes_per_row - left);
 
484
    }
 
485
    if (actual_data != 0)
 
486
        *actual_data = data;
 
487
    return 0;
 
488
}
 
489
 
 
490
/* Copy an alpha-map to the screen. */
 
491
/* Depth is 1, 2, or 4. */
 
492
static int
 
493
svga_copy_alpha(gx_device * dev, const byte * base, int sourcex,
 
494
                int sraster, gx_bitmap_id id, int x, int y, int w, int h,
 
495
                gx_color_index color, int depth)
 
496
{
 
497
    int xi, yi;
 
498
    int skip;
 
499
    const byte *sptr;
 
500
    byte mask;
 
501
    int ishift;
 
502
 
 
503
    /* We fake alpha by interpreting it as saturation, i.e., */
 
504
    /* alpha = 0 is white, alpha = 1 is the full color. */
 
505
    byte shades[16];
 
506
    gx_color_value rgb[3];
 
507
    int log2_depth = depth >> 1;        /* works for 1,2,4 */
 
508
    int n1 = (1 << depth) - 1;
 
509
 
 
510
    fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
 
511
    shades[0] = (byte) svga_map_rgb_color(dev, gx_max_color_value,
 
512
                                          gx_max_color_value,
 
513
                                          gx_max_color_value);
 
514
    shades[n1] = (byte) color;
 
515
    if (n1 > 1) {
 
516
        memset(shades + 1, 255, n1 - 1);
 
517
        svga_map_color_rgb(dev, color, rgb);
 
518
    }
 
519
    skip = sraster - ((w * depth) >> 3);
 
520
    sptr = base + (sourcex >> (3 - log2_depth));
 
521
    mask = n1;
 
522
    ishift = (~sourcex & (7 >> log2_depth)) << log2_depth;
 
523
    for (yi = y; yi - y < h; yi++) {
 
524
        fb_ptr ptr = 0;
 
525
        int shift = ishift;
 
526
 
 
527
        for (xi = x; xi - x < w; xi++, ptr++) {
 
528
            uint a = (*sptr >> shift) & mask;
 
529
 
 
530
            if (PTR_OFF(ptr) == 0)
 
531
                set_pixel_write_ptr(ptr, fb_dev, xi, yi);
 
532
          map:if (a != 0) {
 
533
                byte ci = shades[a];
 
534
 
 
535
                if (ci == 255) {        /* Map the color now. */
 
536
#define make_shade(v, alpha, n1)\
 
537
  (gx_max_color_value -\
 
538
   ((ulong)(gx_max_color_value - (v)) * (alpha) / (n1)))
 
539
                    gx_color_value r =
 
540
                    make_shade(rgb[0], a, n1);
 
541
                    gx_color_value g =
 
542
                    make_shade(rgb[1], a, n1);
 
543
                    gx_color_value b =
 
544
                    make_shade(rgb[2], a, n1);
 
545
                    gx_color_index sci =
 
546
                    svga_map_rgb_color(dev, r, g, b);
 
547
 
 
548
                    if (sci == gx_no_color_index) {
 
549
                        a += (n1 + 1 - a) >> 1;
 
550
                        goto map;
 
551
                    }
 
552
                    shades[a] = ci = (byte) sci;
 
553
                }
 
554
                *ptr = ci;
 
555
            }
 
556
            if (shift == 0)
 
557
                shift = 8 - depth, sptr++;
 
558
            else
 
559
                shift -= depth;
 
560
        }
 
561
        sptr += skip;
 
562
    }
 
563
    return 0;
 
564
}
 
565
 
 
566
/* ------ The VESA device ------ */
 
567
 
 
568
static dev_proc_open_device(vesa_open);
 
569
static const gx_device_procs vesa_procs = svga_procs(vesa_open);
 
570
int vesa_get_mode(void);
 
571
void vesa_set_mode(int);
 
572
static void vesa_set_page(gx_device_svga *, int, int);
 
573
gx_device_svga far_data gs_vesa_device =
 
574
svga_device(vesa_procs, "vesa", vesa_get_mode, vesa_set_mode, vesa_set_page);
 
575
 
 
576
/* Define the structures for information returned by the BIOS. */
 
577
#define bits_include(a, m) !(~(a) & (m))
 
578
/* Information about the BIOS capabilities. */
 
579
typedef struct {
 
580
    byte vesa_signature[4];     /* "VESA" */
 
581
    ushort vesa_version;
 
582
    char *product_info;         /* product name string */
 
583
    byte capabilities[4];       /* (undefined) */
 
584
    ushort *mode_list;          /* supported video modes, -1 ends */
 
585
} vga_bios_info;
 
586
 
 
587
/* Information about an individual VESA mode. */
 
588
typedef enum {
 
589
    m_supported = 1,
 
590
    m_graphics = 0x10
 
591
} mode_attribute;
 
592
typedef enum {
 
593
    w_supported = 1,
 
594
    w_readable = 2,
 
595
    w_writable = 4
 
596
} win_attribute;
 
597
typedef struct {
 
598
    ushort mode_attributes;
 
599
    byte win_a_attributes;
 
600
    byte win_b_attributes;
 
601
    ushort win_granularity;
 
602
    ushort win_size;
 
603
    ushort win_a_segment;
 
604
    ushort win_b_segment;
 
605
    void (*win_func_ptr) (int, int);
 
606
    ushort bytes_per_line;
 
607
    /* Optional information */
 
608
    ushort x_resolution;
 
609
    ushort y_resolution;
 
610
    byte x_char_size;
 
611
    byte y_char_size;
 
612
    byte number_of_planes;
 
613
    byte bits_per_pixel;
 
614
    byte number_of_banks;
 
615
    byte memory_model;
 
616
    byte bank_size;
 
617
    /* Padding to 256 bytes */
 
618
    byte _padding[256 - 29];
 
619
} vesa_info;
 
620
 
 
621
/* Read the device mode */
 
622
int
 
623
vesa_get_mode(void)
 
624
{
 
625
    registers regs;
 
626
 
 
627
    regs.h.ah = 0x4f;
 
628
    regs.h.al = 0x03;
 
629
    int86(0x10, &regs, &regs);
 
630
    return regs.rshort.bx;
 
631
}
 
632
 
 
633
/* Set the device mode */
 
634
void
 
635
vesa_set_mode(int mode)
 
636
{
 
637
    registers regs;
 
638
 
 
639
    regs.h.ah = 0x4f;
 
640
    regs.h.al = 0x02;
 
641
    regs.rshort.bx = mode;
 
642
    int86(0x10, &regs, &regs);
 
643
}
 
644
 
 
645
/* Read information about a device mode */
 
646
static int
 
647
vesa_get_info(int mode, vesa_info _ss * info)
 
648
{
 
649
    registers regs;
 
650
    struct SREGS sregs;
 
651
 
 
652
    regs.h.ah = 0x4f;
 
653
    regs.h.al = 0x01;
 
654
    regs.rshort.cx = mode;
 
655
    segread(&sregs);
 
656
    sregs.es = sregs.ss;
 
657
    regs.rshort.di = PTR_OFF(info);
 
658
    int86x(0x10, &regs, &regs, &sregs);
 
659
#ifdef DEBUG
 
660
    if (regs.h.ah == 0 && regs.h.al == 0x4f)
 
661
        dlprintf8("vesa_get_info(%x): ma=%x wa=%x/%x wg=%x ws=%x wseg=%x/%x\n",
 
662
                  mode, info->mode_attributes,
 
663
                  info->win_a_attributes, info->win_b_attributes,
 
664
                  info->win_granularity, info->win_size,
 
665
                  info->win_a_segment, info->win_b_segment);
 
666
    else
 
667
        dlprintf3("vesa_get_info(%x) failed: ah=%x al=%x\n",
 
668
                  mode, regs.h.ah, regs.h.al);
 
669
#endif
 
670
    return (regs.h.ah == 0 && regs.h.al == 0x4f ? 0 : -1);
 
671
}
 
672
 
 
673
/* Initialize the graphics mode. */
 
674
/* Shared routine to look up a VESA-compatible BIOS mode. */
 
675
static int
 
676
vesa_find_mode(gx_device * dev, const mode_info * mode_table)
 
677
{                               /* Select the proper video mode */
 
678
    vesa_info info;
 
679
    const mode_info *mip;
 
680
 
 
681
    for (mip = mode_table; mip->mode >= 0; mip++) {
 
682
        if (mip->width >= fb_dev->width &&
 
683
            mip->height >= fb_dev->height &&
 
684
            vesa_get_info(mip->mode, &info) >= 0 &&
 
685
            bits_include(info.mode_attributes,
 
686
                         m_supported | m_graphics) &&
 
687
            info.win_granularity <= 64 &&
 
688
            (info.win_granularity & (info.win_granularity - 1)) == 0 &&
 
689
            info.win_size == 64 &&
 
690
            bits_include(info.win_a_attributes,
 
691
                         w_supported) &&
 
692
            info.win_a_segment == regen
 
693
            ) {                 /* Make sure we can both read & write. */
 
694
            /* Initialize for the default case. */
 
695
            fb_dev->wnum_read = 0;
 
696
            fb_dev->wnum_write = 0;
 
697
            if (bits_include(info.win_a_attributes,
 
698
                             w_readable | w_writable)
 
699
                )
 
700
                break;
 
701
            else if (info.win_b_segment == regen &&
 
702
                     bits_include(info.win_b_attributes,
 
703
                                  w_supported) &&
 
704
                     bits_include(info.win_a_attributes |
 
705
                                  info.win_b_attributes,
 
706
                                  w_readable | w_writable)
 
707
                ) {             /* Two superimposed windows. */
 
708
                if (!bits_include(info.win_a_attributes,
 
709
                                  w_writable)
 
710
                    )
 
711
                    fb_dev->wnum_write = 1;
 
712
                else
 
713
                    fb_dev->wnum_read = 1;
 
714
            }
 
715
            break;
 
716
        }
 
717
    }
 
718
    if (mip->mode < 0)
 
719
        return_error(gs_error_rangecheck);      /* mode not available */
 
720
    fb_dev->mode = mip;
 
721
    gx_device_adjust_resolution(dev, mip->width, mip->height, 1);
 
722
    fb_dev->info.vesa.bios_set_page = info.win_func_ptr;
 
723
    fb_dev->info.vesa.pn_shift = ilog2(64 / info.win_granularity);
 
724
    /* Reset the raster per the VESA info. */
 
725
    fb_dev->raster = info.bytes_per_line;
 
726
    return 0;
 
727
}
 
728
static int
 
729
vesa_open(gx_device * dev)
 
730
{
 
731
    static const mode_info mode_table[] =
 
732
    {
 
733
        {640, 400, 0x100},
 
734
        {640, 480, 0x101},
 
735
        {800, 600, 0x103},
 
736
        {1024, 768, 0x105},
 
737
        {1280, 1024, 0x107},
 
738
        {-1, -1, -1}
 
739
    };
 
740
    int code = vesa_find_mode(dev, mode_table);
 
741
 
 
742
    if (code < 0)
 
743
        return code;
 
744
    return svga_open(dev);
 
745
}
 
746
 
 
747
/* Set the current display page. */
 
748
static void
 
749
vesa_set_page(gx_device_svga * dev, int pn, int wnum)
 
750
{
 
751
    registers regs;
 
752
 
 
753
    regs.rshort.dx = pn << dev->info.vesa.pn_shift;
 
754
    regs.h.ah = 0x4f;
 
755
    regs.h.al = 5;
 
756
    regs.rshort.bx = wnum;
 
757
    int86(0x10, &regs, &regs);
 
758
}
 
759
 
 
760
/* ------ The ATI Wonder device ------ */
 
761
 
 
762
static dev_proc_open_device(atiw_open);
 
763
static const gx_device_procs atiw_procs = svga_procs(atiw_open);
 
764
static int atiw_get_mode(void);
 
765
static void atiw_set_mode(int);
 
766
static void atiw_set_page(gx_device_svga *, int, int);
 
767
gx_device_svga far_data gs_atiw_device =
 
768
svga_device(atiw_procs, "atiw", atiw_get_mode, atiw_set_mode, atiw_set_page);
 
769
 
 
770
/* Read the device mode */
 
771
static int
 
772
atiw_get_mode(void)
 
773
{
 
774
    registers regs;
 
775
 
 
776
    regs.h.ah = 0xf;
 
777
    int86(0x10, &regs, &regs);
 
778
    return regs.h.al;
 
779
}
 
780
 
 
781
/* Set the device mode */
 
782
static void
 
783
atiw_set_mode(int mode)
 
784
{
 
785
    registers regs;
 
786
 
 
787
    regs.h.ah = 0;
 
788
    regs.h.al = mode;
 
789
    int86(0x10, &regs, &regs);
 
790
}
 
791
 
 
792
/* Initialize the graphics mode. */
 
793
static int
 
794
atiw_open(gx_device * dev)
 
795
{                               /* Select the proper video mode */
 
796
    {
 
797
        static const mode_info mode_table[] =
 
798
        {
 
799
            {640, 400, 0x61},
 
800
            {640, 480, 0x62},
 
801
            {800, 600, 0x63},
 
802
            {1024, 768, 0x64},
 
803
            {-1, -1, -1}
 
804
        };
 
805
        int code = svga_find_mode(dev, mode_table);
 
806
 
 
807
        if (code < 0)
 
808
            return code;        /* mode not available */
 
809
        fb_dev->info.atiw.select_reg = *(int *)MK_PTR(0xc000, 0x10);
 
810
        return svga_open(dev);
 
811
    }
 
812
}
 
813
 
 
814
/* Set the current display page. */
 
815
static void
 
816
atiw_set_page(gx_device_svga * dev, int pn, int wnum)
 
817
{
 
818
    int select_reg = dev->info.atiw.select_reg;
 
819
    byte reg;
 
820
 
 
821
    disable();
 
822
    outportb(select_reg, 0xb2);
 
823
    reg = inportb(select_reg + 1);
 
824
    outportb(select_reg, 0xb2);
 
825
    outportb(select_reg + 1, (reg & 0xe1) + (pn << 1));
 
826
    enable();
 
827
}
 
828
 
 
829
/* ------ The Trident device ------ */
 
830
 
 
831
static dev_proc_open_device(tvga_open);
 
832
static const gx_device_procs tvga_procs = svga_procs(tvga_open);
 
833
 
 
834
/* We can use the atiw_get/set_mode procedures. */
 
835
static void tvga_set_page(gx_device_svga *, int, int);
 
836
gx_device_svga far_data gs_tvga_device =
 
837
svga_device(tvga_procs, "tvga", atiw_get_mode, atiw_set_mode, tvga_set_page);
 
838
 
 
839
/* Initialize the graphics mode. */
 
840
static int
 
841
tvga_open(gx_device * dev)
 
842
{
 
843
    fb_dev->wnum_read = 1;
 
844
    fb_dev->wnum_write = 0;
 
845
    /* Select the proper video mode */
 
846
    {
 
847
        static const mode_info mode_table[] =
 
848
        {
 
849
            {640, 400, 0x5c},
 
850
            {640, 480, 0x5d},
 
851
            {800, 600, 0x5e},
 
852
            {1024, 768, 0x62},
 
853
            {-1, -1, -1}
 
854
        };
 
855
        int code = svga_find_mode(dev, mode_table);
 
856
 
 
857
        if (code < 0)
 
858
            return code;        /* mode not available */
 
859
        return svga_open(dev);
 
860
    }
 
861
}
 
862
 
 
863
/* Set the current display page. */
 
864
static void
 
865
tvga_set_page(gx_device_svga * dev, int pn, int wnum)
 
866
{
 
867
    /* new mode */
 
868
    outportb(0x3c4, 0x0b);
 
869
    inportb(0x3c4);
 
870
 
 
871
    outportb(0x3c4, 0x0e);
 
872
    outportb(0x3c5, pn ^ 2);
 
873
}
 
874
 
 
875
/* ------ The Tseng Labs ET3000/4000 devices ------ */
 
876
 
 
877
static dev_proc_open_device(tseng_open);
 
878
static const gx_device_procs tseng_procs =
 
879
svga_procs(tseng_open);
 
880
 
 
881
/* We can use the atiw_get/set_mode procedures. */
 
882
static void tseng_set_page(gx_device_svga *, int, int);
 
883
 
 
884
/* The 256-color Tseng device */
 
885
gx_device_svga far_data gs_tseng_device =
 
886
svga_device(tseng_procs, "tseng", atiw_get_mode, atiw_set_mode, tseng_set_page);
 
887
 
 
888
/* Initialize the graphics mode. */
 
889
static int
 
890
tseng_open(gx_device * dev)
 
891
{
 
892
    fb_dev->wnum_read = 1;
 
893
    fb_dev->wnum_write = 0;
 
894
    /* Select the proper video mode */
 
895
    {
 
896
        static const mode_info mode_table[] =
 
897
        {
 
898
            {640, 350, 0x2d},
 
899
            {640, 480, 0x2e},
 
900
            {800, 600, 0x30},
 
901
            {1024, 768, 0x38},
 
902
            {-1, -1, -1}
 
903
        };
 
904
        int code = svga_find_mode(dev, mode_table);
 
905
        volatile_fb_ptr p0 = (volatile_fb_ptr) MK_PTR(regen, 0);
 
906
 
 
907
        if (code < 0)
 
908
            return code;        /* mode not available */
 
909
        code = svga_open(dev);
 
910
        if (code < 0)
 
911
            return 0;
 
912
        /* Figure out whether we have an ET3000 or an ET4000 */
 
913
        /* by playing with the segment register. */
 
914
        outportb(0x3cd, 0x44);
 
915
        *p0 = 4;                /* byte 0, page 4 */
 
916
        outportb(0x3cd, 0x40);
 
917
        *p0 = 3;                /* byte 0, page 0 */
 
918
        fb_dev->info.tseng.et_model = *p0;
 
919
        /* read page 0 if ET3000, */
 
920
        /* page 4 if ET4000 */
 
921
        return 0;
 
922
    }
 
923
}
 
924
 
 
925
/* Set the current display page. */
 
926
static void
 
927
tseng_set_page(gx_device_svga * dev, int pn, int wnum)
 
928
{                               /* The ET3000 has read page = 5:3, write page = 2:0; */
 
929
    /* the ET4000 has read page = 7:4, write page = 3:0. */
 
930
    int shift = dev->info.tseng.et_model;
 
931
    int mask = (1 << shift) - 1;
 
932
 
 
933
    if (wnum)
 
934
        pn <<= shift, mask <<= shift;
 
935
    outportb(0x3cd, (inportb(0x3cd) & ~mask) + pn);
 
936
}
 
937
/* ------ The Cirrus device (CL-GD54XX) ------ */
 
938
/* Written by Piotr Strzelczyk, BOP s.c., Gda\'nsk, Poland, */
 
939
/* e-mail contact via B.Jackowski@GUST.org.pl */
 
940
 
 
941
static dev_proc_open_device(cirr_open);
 
942
static gx_device_procs cirr_procs = svga_procs(cirr_open);
 
943
 
 
944
/* We can use the atiw_get/set_mode procedures. */
 
945
static void cirr_set_page(gx_device_svga *, int, int);
 
946
gx_device_svga gs_cirr_device =
 
947
svga_device(cirr_procs, "cirr", atiw_get_mode, atiw_set_mode, cirr_set_page);
 
948
 
 
949
/* Initialize the graphics mode. */
 
950
static int
 
951
cirr_open(gx_device * dev)
 
952
{
 
953
    fb_dev->wnum_read = 1;
 
954
    fb_dev->wnum_write = 0;
 
955
    /* Select the proper video mode */
 
956
    {
 
957
        static const mode_info mode_table[] =
 
958
        {
 
959
            {640, 400, 0x5e},
 
960
            {640, 480, 0x5f},
 
961
            {800, 600, 0x5c},
 
962
            {1024, 768, 0x60},
 
963
            {-1, -1, -1}
 
964
        };
 
965
        int code = svga_find_mode(dev, mode_table);
 
966
 
 
967
        if (code < 0)
 
968
            return code;        /* mode not available */
 
969
        outportb(0x3c4, 0x06);
 
970
        outportb(0x3c5, 0x12);
 
971
        outportb(0x3ce, 0x0b);
 
972
        outportb(0x3cf, (inportb(0x3cf) & 0xde));
 
973
        return svga_open(dev);
 
974
    }
 
975
}
 
976
 
 
977
/* Set the current display page. */
 
978
static void
 
979
cirr_set_page(gx_device_svga * dev, int pn, int wnum)
 
980
{
 
981
    outportb(0x3ce, 0x09);
 
982
    outportb(0x3cf, pn << 4);
 
983
}
 
984
 
 
985
/* ------ The Avance Logic device (mostly experimental) ------ */
 
986
/* For questions about this device, please contact Stefan Freund */
 
987
/* <freund@ikp.uni-koeln.de>. */
 
988
 
 
989
static dev_proc_open_device(ali_open);
 
990
static const gx_device_procs ali_procs = svga_procs(ali_open);
 
991
 
 
992
/* We can use the atiw_get/set_mode procedures. */
 
993
static void ali_set_page(gx_device_svga *, int, int);
 
994
 
 
995
/* The 256-color Avance Logic device */
 
996
gx_device_svga gs_ali_device =
 
997
svga_device(ali_procs, "ali", atiw_get_mode, atiw_set_mode,
 
998
            ali_set_page);
 
999
 
 
1000
/* Initialize the graphics mode. */
 
1001
static int
 
1002
ali_open(gx_device * dev)
 
1003
{
 
1004
    fb_dev->wnum_read = 1;
 
1005
    fb_dev->wnum_write = 0;
 
1006
    /* Select the proper video mode */
 
1007
    {
 
1008
        static const mode_info mode_table[] =
 
1009
        {
 
1010
            {640, 400, 0x29},
 
1011
            {640, 480, 0x2a},
 
1012
            {800, 600, 0x2c},
 
1013
            {1024, 768, 0x31},
 
1014
            {-1, -1, -1}
 
1015
        };
 
1016
        int code = svga_find_mode(dev, mode_table);
 
1017
 
 
1018
        if (code < 0)
 
1019
            return code;        /* mode not available */
 
1020
        return svga_open(dev);
 
1021
    }
 
1022
 
 
1023
}
 
1024
 
 
1025
/* Set the current display page. */
 
1026
static void
 
1027
ali_set_page(gx_device_svga * dev, int pn, int wnum)
 
1028
{
 
1029
    outportb(0x3d6, pn);        /* read  */
 
1030
    outportb(0x3d7, pn);        /* write */
 
1031
}