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

« back to all changes in this revision

Viewing changes to src/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
 
}