~lidaobing/+junk/zhcon

« back to all changes in this revision

Viewing changes to src/display/vgadev.cpp

  • Committer: LI Daobing
  • Date: 2008-11-04 04:39:18 UTC
  • Revision ID: lidaobing@gmail.com-20081104043918-nfwwvgfb0uied0mt
importĀ 1:0.2.6-5.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// vi:ts=4:shiftwidth=4:expandtab
 
2
/***************************************************************************
 
3
                          vgadev.cpp  -  description
 
4
                             -------------------
 
5
    begin                : Wed Sept 05 2001
 
6
    copyright            : (C) 2001 by rick, huyong
 
7
    email                : rick@chinaren.com
 
8
                           ccpaging@online.sh.cn
 
9
 
 
10
 ***************************************************************************/
 
11
 
 
12
/***************************************************************************
 
13
 *                                                                         *
 
14
 *   This program is free software; you can redistribute it and/or modify  *
 
15
 *   it under the terms of the GNU General Public License as published by  *
 
16
 *   the Free Software Foundation; either version 2 of the License, or     *
 
17
 *   (at your option) any later version.                                   *
 
18
 *                                                                         *
 
19
 ***************************************************************************/
 
20
 
 
21
#ifdef HAVE_CONFIG_H
 
22
#include <config.h>
 
23
#endif
 
24
 
 
25
 
 
26
#ifdef USING_VGA
 
27
#if defined(linux)
 
28
 
 
29
#include <stdio.h>
 
30
#include <unistd.h>
 
31
#include <fcntl.h>
 
32
#include <sys/ioctl.h>
 
33
#include <sys/mman.h>
 
34
#include <sys/io.h>
 
35
#include <cassert>
 
36
#include "debug.h"
 
37
#include "vgadev.h"
 
38
#include "lrmi.h"
 
39
 
 
40
#include <cstring>
 
41
 
 
42
#define GRAPH_BASE 0xA0000
 
43
#define GRAPH_ADDR  0x3ce
 
44
#define GRAPH_DATA  0x3cf
 
45
 
 
46
char *VGADev::mpBuf = NULL;
 
47
int VGADev::mBufLen = 0;
 
48
unsigned long VGADev::mNextLine = 0; // offset to one line below
 
49
int VGADev::mFd = -1;
 
50
 
 
51
bool VGADev::TryOpen() {
 
52
    if (!LRMI_init()) {
 
53
        fprintf(stderr, "\n(VGADev::TryOpen) LRMI_init() failed.\n");
 
54
        return false;
 
55
    }
 
56
 
 
57
    EnableIOPerm();
 
58
    if (!SetVideoMode(0x12)) {
 
59
        DisableIOPerm();
 
60
        fprintf(stderr, "\n(VGADev::TryOpen) LRMI_init() failed, can not set video mode 0x12\n");
 
61
        return false;
 
62
    }
 
63
 
 
64
    if ((mFd = open("/dev/mem", O_RDWR)) < 0) {
 
65
        DisableIOPerm();
 
66
        fprintf(stderr, "\n(VGADev::TryOpen) can not open /dev/mem in read/write mode\n");
 
67
        return false;
 
68
    }
 
69
 
 
70
    mXres = 640;
 
71
    mYres = 480;
 
72
    mBufLen = mXres * mYres / 8;
 
73
    mpBuf = static_cast<char *>(mmap((__ptr_t)0, mBufLen, PROT_READ | PROT_WRITE, MAP_SHARED,
 
74
                                mFd, GRAPH_BASE));
 
75
    if (mpBuf == MAP_FAILED) {
 
76
        DisableIOPerm();
 
77
        fprintf(stderr, "\n(VGADev::TryOpen) mmap() call failed\n");
 
78
        return false;
 
79
    }
 
80
 
 
81
    mpGraphDev = new VGADev;
 
82
    return true;
 
83
}
 
84
 
 
85
VGADev::VGADev() {
 
86
    mNextLine = mXres >> 3;
 
87
    EnableIOPerm();
 
88
    SetDefaultMode();
 
89
}
 
90
 
 
91
VGADev::~VGADev() {
 
92
    if (mpBuf != NULL)
 
93
        munmap(mpBuf, mBufLen);
 
94
    if (mFd >= 0)
 
95
        close(mFd);
 
96
    SetVideoMode(0x3);
 
97
    DisableIOPerm();
 
98
}
 
99
 
 
100
void VGADev::EnableIOPerm()
 
101
{
 
102
    ioperm(GRAPH_ADDR, 1, 1);
 
103
    ioperm(GRAPH_DATA, 1, 1);
 
104
    ioperm(0, 0x400, 1);
 
105
    iopl(3);
 
106
}
 
107
 
 
108
void VGADev::DisableIOPerm()
 
109
{
 
110
    ioperm(GRAPH_ADDR, 1, 0);
 
111
    ioperm(GRAPH_DATA, 1, 0);
 
112
    ioperm(0, 0x400, 0);
 
113
    iopl(3);
 
114
}
 
115
 
 
116
inline bool VGADev::SetVideoMode(int mode)
 
117
{
 
118
    struct LRMI_regs r;
 
119
    memset(&r, 0, sizeof(r));
 
120
    r.eax = mode;
 
121
    return LRMI_int(0x10, &r);
 
122
}
 
123
 
 
124
inline void VGADev::SetDefaultMode() {
 
125
    SetWriteMode(3);
 
126
    SetOper(0);
 
127
    SetBitMask(0xff);
 
128
}
 
129
 
 
130
inline void VGADev::SetBitMask(char mask) {
 
131
    outb(9, GRAPH_ADDR);
 
132
    outb(mask, GRAPH_DATA);
 
133
}
 
134
 
 
135
inline void VGADev::SetOper(int op) {
 
136
    outb(3, GRAPH_ADDR);
 
137
    outb(op, GRAPH_DATA);
 
138
}
 
139
 
 
140
inline void VGADev::SetWriteMode(int mode) {
 
141
    outb(5, GRAPH_ADDR);
 
142
    outb(mode, GRAPH_DATA);
 
143
}
 
144
 
 
145
inline void VGADev::SetColor(int color) {
 
146
    outb(0, GRAPH_ADDR);
 
147
    outb(color, GRAPH_DATA);
 
148
}
 
149
 
 
150
void VGADev::PutPixel(int x,int y,int color) {
 
151
    static int prevColor = -1;
 
152
    if (prevColor != color) {
 
153
        prevColor = color;
 
154
        SetColor(color);
 
155
    }
 
156
 
 
157
    __u8* dest = (__u8*)mpBuf + mNextLine * y + (x>>3);
 
158
    fb_readb(dest);
 
159
    *dest = 0x80 >> (x & 7);
 
160
}
 
161
 
 
162
void VGADev::FillRect(int x1,int y1,int x2,int y2,int color) {
 
163
    assert( x1 >= 0 && x1 < mXres && y1 >=0 && y1 < mYres);
 
164
    assert( x2 >= 0 && x2 < mXres && y2 >=0 && y2 < mYres);
 
165
    assert(x1 <= x2 && y1 <= y2);
 
166
 
 
167
#ifndef NDEBUG
 
168
    //debug<<"FillRect ("<<x1<<","<<y1<<")-("<<x2<<","<<y2<<")"<<endl;
 
169
#endif
 
170
    SetColor(color);
 
171
 
 
172
    __u8* destorig = (__u8*)mpBuf + mNextLine * y1 + (x1>>3);
 
173
    __u8* dest = destorig;
 
174
 
 
175
    int width = x2 - x1 + 1;
 
176
    int left, right, midbytes;
 
177
    left = 8 - (x1 & 7);
 
178
    // left maybe 8
 
179
    if (left == 8) left = 0;
 
180
 
 
181
    if (left >= width) {
 
182
        right = 0;
 
183
        midbytes = 0;
 
184
    } else {
 
185
        right = (x1 + width) & 7;
 
186
        midbytes = (width - left - right) / 8;
 
187
    }
 
188
#ifndef NDEBUG
 
189
    if (left + right > width || midbytes < 0) {
 
190
        debug<<"FillRect x1="<<x1<<" width="<<width<<" left="<<left;
 
191
        debug<<" midbytes="<<midbytes<<" right="<<right<<endl;
 
192
    }
 
193
#endif
 
194
    
 
195
    int height;
 
196
    if (left) {
 
197
        __u8 leftmask = 0xff >> (8 - left);
 
198
        if (left > width) leftmask &= 0xff << (left - width);
 
199
        for (height = y2 - y1 + 1; height--; dest += mNextLine) {
 
200
            fb_readb(dest); // fill latches
 
201
            *dest = leftmask;
 
202
        }
 
203
        destorig++;
 
204
    }
 
205
    if (midbytes) {
 
206
        dest = destorig;
 
207
        for (height = y2 - y1 + 1; height--; dest += mNextLine) {
 
208
            memset(dest, 0xff, midbytes);
 
209
        }
 
210
        destorig += midbytes;
 
211
    }
 
212
    if (right) {
 
213
        dest = destorig;
 
214
        __u8 rightmask = 0xff << (8 - right);
 
215
        for (height = y2 - y1 + 1; height--; dest += mNextLine) {
 
216
            fb_readb(dest); // fill latches
 
217
            *dest = rightmask;
 
218
        }
 
219
    }
 
220
}
 
221
 
 
222
void VGADev::RevRect(int x1,int y1,int x2,int y2) {
 
223
    assert( x1 >= 0 && x1 < Width() && y1 >=0 && y1 < Height());
 
224
    assert( x2 >= 0 && x2 < Width() && y2 >=0 && y2 < Height());
 
225
    assert(x1 <= x2 && y1 <= y2);
 
226
 
 
227
    __u8* dest = (__u8*)mpBuf + mNextLine * y1 + (x1>>3);
 
228
    __u8* dest8;
 
229
 
 
230
    SetWriteMode(3);
 
231
    SetOper(0x18);
 
232
    SetColor(0xf);
 
233
    SetBitMask(0xff);
 
234
    
 
235
    int width = x2 - x1 + 1;
 
236
    int left, right, midbytes;
 
237
    left = 8 - (x1 & 7);
 
238
    // left maybe 8
 
239
    if (left == 8) left = 0;
 
240
 
 
241
    if (left >= width) {
 
242
        right = 0;
 
243
        midbytes = 0;
 
244
    } else {
 
245
        right = (x1 + width) & 7;
 
246
        midbytes = (width - left - right) / 8;
 
247
    }
 
248
 
 
249
    __u8 leftmask = 0xff >> (8 - left);
 
250
    if (left > width) leftmask &= 0xff << (left - width);
 
251
    __u8 rightmask = 0xff << (8 - right);
 
252
    int cnt;
 
253
    for(int height = y2 - y1 + 1; height--; dest += mNextLine) {
 
254
        dest8 = dest;
 
255
        if (left) {
 
256
            fb_readb(dest8);
 
257
            fb_writeb(leftmask, dest8++);
 
258
        }
 
259
        if (midbytes) {
 
260
            for(cnt = midbytes; cnt--; ) {
 
261
                fb_readb(dest8);
 
262
                fb_writeb(0xff, dest8++);
 
263
            }
 
264
        }
 
265
        if (right) {
 
266
            fb_readb(dest8);
 
267
            fb_writeb(rightmask, dest8);
 
268
        }
 
269
    }
 
270
    SetDefaultMode();
 
271
}
 
272
 
 
273
void VGADev::DrawChar(int x,int y,int fg,int bg,struct CharBitMap* pFont) {
 
274
    __u8* destorig = (__u8*)mpBuf + mNextLine * y + (x >> 3);
 
275
    __u8* dest;
 
276
    __u8* dest8;
 
277
 
 
278
    int LeftShift = x & 7;
 
279
    int FillBytes = (LeftShift + pFont->w + 7) >> 3;
 
280
    // maxium 24 pixel width font
 
281
    if (FillBytes > 3) FillBytes = 3;
 
282
 
 
283
    __u8* cdat8;
 
284
    int rows, cnt;
 
285
    union {
 
286
        char ch[4];
 
287
        __u32 l;
 
288
    } UniLine;
 
289
 
 
290
    UniLine.l = (0xffffffff >> LeftShift)
 
291
                & (0xffffffff << (32 - LeftShift - pFont->w));
 
292
 
 
293
    SetColor(bg);
 
294
    dest = destorig;
 
295
    for (rows = mBlockHeight; rows-- ; dest += mNextLine) {
 
296
        dest8 = dest;
 
297
        cdat8 = (__u8*)&UniLine.ch[3];
 
298
        for (cnt = FillBytes; cnt--;) {
 
299
            fb_readb(dest8);
 
300
            fb_writeb(*cdat8--, dest8++);
 
301
        }
 
302
    }
 
303
        
 
304
    SetColor(fg);
 
305
    dest = destorig;
 
306
    char *pFontLine = pFont->pBuf;
 
307
    if (LeftShift == 0) {
 
308
        for (rows = mBlockHeight; rows-- ; dest += mNextLine) {
 
309
            dest8 = dest;
 
310
            UniLine.l = 0;
 
311
            memcpy(&UniLine, pFontLine, pFont->wBytes);
 
312
            cdat8 = (__u8*)&UniLine;
 
313
            for (cnt = FillBytes; cnt--;) {
 
314
                fb_readb(dest8);
 
315
                fb_writeb(*cdat8++, dest8++);
 
316
            }
 
317
            pFontLine += pFont->wBytes;
 
318
        }
 
319
        return;
 
320
    }
 
321
 
 
322
    for (rows = mBlockHeight; rows-- ; dest += mNextLine) {
 
323
        dest8 = dest;
 
324
 
 
325
        // for little endian
 
326
        UniLine.l = 0;
 
327
        cdat8 = (__u8*)pFontLine;
 
328
        for (cnt = 0; cnt < pFont->wBytes; cnt++) {
 
329
            UniLine.ch[3 - cnt] = *cdat8++;
 
330
        }
 
331
        UniLine.l >>= LeftShift;
 
332
        cdat8 = (__u8*)&UniLine.ch[3];
 
333
        for (cnt = FillBytes; cnt--;) {
 
334
             fb_readb(dest8);
 
335
             fb_writeb(*cdat8--, dest8++);
 
336
        }
 
337
        pFontLine += pFont->wBytes;
 
338
    }
 
339
}
 
340
 
 
341
void VGADev::SwitchToGraph() {
 
342
    SetVideoMode(0x12);
 
343
    SetDefaultMode();
 
344
}
 
345
 
 
346
void VGADev::SwitchToText() {
 
347
    SetVideoMode(0x3);
 
348
}
 
349
#endif
 
350
 
 
351
#endif //USING_VGA