/[pearpc]/src/system/display.cc
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /src/system/display.cc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (hide annotations)
Wed Sep 5 17:11:21 2007 UTC (16 years, 6 months ago) by dpavlin
File size: 14544 byte(s)
import upstream CVS
1 dpavlin 1 /*
2     * PearPC
3     * display.cc
4     *
5     * Copyright (C) 1999-2002 Stefan Weyergraf
6     * Copyright (C) 2003,2004 Sebastian Biallas (sb@biallas.net)
7     *
8     * This program is free software; you can redistribute it and/or modify
9     * it under the terms of the GNU General Public License version 2 as
10     * published by the Free Software Foundation.
11     *
12     * This program is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with this program; if not, write to the Free Software
19     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20     */
21    
22     #include <new>
23     #include <cstdarg>
24     #include <cstdlib>
25     #include <cstring>
26    
27     #include "display.h"
28     #include "tools/snprintf.h"
29     #include "gif.h"
30    
31     // For key support
32     #include "io/cuda/cuda.h"
33     #include "system/sys.h"
34     #include "system/keyboard.h"
35    
36     byte * gFrameBuffer = NULL;
37     int gDamageAreaFirstAddr, gDamageAreaLastAddr;
38    
39     #define IS_FGTRANS(c) (VC_GET_BASECOLOR(VCP_FOREGROUND((c)))==VC_TRANSPARENT)
40     #define IS_BGTRANS(c) (VC_GET_BASECOLOR(VCP_BACKGROUND((c)))==VC_TRANSPARENT)
41    
42     static vcp mixColors(vcp base, vcp layer)
43     {
44     vc fg, bg;
45     if (IS_FGTRANS(layer)) {
46     fg = VCP_FOREGROUND(base);
47     } else {
48     fg = VCP_FOREGROUND(layer);
49     }
50     if (IS_BGTRANS(layer)) {
51     bg = VCP_BACKGROUND(base);
52     } else {
53     bg = VCP_BACKGROUND(layer);
54     }
55     if (IS_FGTRANS(layer) && (fg != VC_TRANSPARENT) && (fg == bg)) fg=(fg+1)%8;
56     if (IS_BGTRANS(layer) && (bg != VC_TRANSPARENT) && (fg == bg)) bg=(bg+1)%8;
57     return VCP(fg, bg);
58     }
59    
60     SystemDisplay *gDisplay = NULL;
61    
62     class MenuEntry: public Object {
63     int x, y, w, h;
64     void (*mCallback)(void *);
65     void *mCallbackParam;
66     public:
67     Gif *mPic;
68    
69     MenuEntry(int X, int Y, Gif *pic, void (*callback)(void *), void *callbackparam)
70     {
71     x = X; y = Y; w = pic->mWidth; h = pic->mHeight;
72     mPic = pic;
73     mCallback = callback;
74     mCallbackParam = callbackparam;
75     }
76    
77     virtual ~MenuEntry()
78     {
79     delete mPic;
80     }
81    
82     void check(int cx, int cy)
83     {
84     if (cx >= x && cy >= y && cx <= (x+w) && cy <= (y+h)) {
85     mCallback(mCallbackParam);
86     }
87     }
88     };
89    
90    
91     #include "vt100.h"
92     #include "font.h"
93    
94     static RGBA _16toRGBA[16] = {
95     MK_RGBA(0x22, 0x22, 0x22, 0xff),
96     MK_RGBA(0x00, 0x00, 0xaa, 0xff),
97     MK_RGBA(0x00, 0xaa, 0x00, 0xff),
98     MK_RGBA(0x00, 0xaa, 0xaa, 0xff),
99     MK_RGBA(0xaa, 0x00, 0x00, 0xff),
100     MK_RGBA(0xaa, 0x00, 0xaa, 0xff),
101     MK_RGBA(0xaa, 0xaa, 0x00, 0xff),
102     MK_RGBA(0xaa, 0xaa, 0xaa, 0xff),
103     MK_RGBA(0x55, 0x55, 0x55, 0xff),
104     MK_RGBA(0x55, 0x55, 0xff, 0xff),
105     MK_RGBA(0x55, 0xff, 0x55, 0xff),
106     MK_RGBA(0x55, 0xff, 0xff, 0xff),
107     MK_RGBA(0xff, 0x55, 0x55, 0xff),
108     MK_RGBA(0xff, 0x55, 0xff, 0xff),
109     MK_RGBA(0xff, 0xff, 0x55, 0xff),
110     MK_RGBA(0xff, 0xff, 0xff, 0xff)
111     };
112    
113     #define MASK(shift, size) (((1 << (size))-1)<<(shift))
114     void dumpDisplayChar(const DisplayCharacteristics &chr)
115     {
116     fprintf(stderr, "\tdimensions: %d x %d pixels\n", chr.width, chr.height);
117     fprintf(stderr, "\tpixel size in bytes: %d\n", chr.bytesPerPixel);
118     fprintf(stderr, "\tpixel size in bits: %d\n", chr.bytesPerPixel*8);
119     fprintf(stderr, "\tred_mask: %08x (%d bits)\n", MASK(chr.redShift, chr.redSize), chr.redSize);
120     fprintf(stderr, "\tgreen_mask: %08x (%d bits)\n", MASK(chr.greenShift, chr.greenSize), chr.greenSize);
121     fprintf(stderr, "\tblue_mask: %08x (%d bits)\n", MASK(chr.blueShift, chr.blueSize), chr.blueSize);
122     fprintf(stderr, "\tdepth: %d\n", chr.redSize + chr.greenSize + chr.blueSize);
123     }
124    
125     SystemDisplay::SystemDisplay(const DisplayCharacteristics &aClientChr, int redraw_ms)
126     {
127     mClientChar = aClientChr;
128     mRedraw_ms = redraw_ms;
129     mHWCursorX = 0;
130     mHWCursorY = 0;
131     mHWCursorVisible = false;
132     mHWCursorData = NULL;
133    
134     mMenu = new Array(true);
135     mMenuX = 0;
136     mMenuHeight = 20;
137     mMouseGrabbed = false;
138    
139     mFullscreenChanged = false;
140     mFullscreen = false;
141    
142     mExposed = false;
143     }
144    
145     SystemDisplay::~SystemDisplay()
146     {
147     delete mMenu;
148     }
149    
150     bool SystemDisplay::openVT(int width, int height, int dx, int dy, File &font)
151     {
152     mVTWidth = width;
153     mVTHeight = height;
154     mVTDX = dx;
155     mVTDY = dy;
156     mFont = new Font();
157     if (!((Font*)mFont)->loadFromFile(font)) return false;
158     buf = (BufferedChar*)malloc(sizeof (BufferedChar) * width * height);
159     vt = new VT100Display(width, height, this);
160     ((VT100Display*)vt)->setAutoNewLine(true);
161     return true;
162     }
163    
164     void SystemDisplay::closeVT()
165     {
166     delete vt;
167     free(buf);
168     }
169    
170     void SystemDisplay::setHWCursor(int x, int y, bool visible, byte *data)
171     {
172     mHWCursorX = x;
173     mHWCursorY = y;
174     mHWCursorVisible = visible;
175     mHWCursorData = data;
176     displayShow();
177     }
178    
179     void SystemDisplay::print(const char *s)
180     {
181     const void *x = s;
182     int xl = strlen(s);
183     ((VT100Display*)vt)->termWrite(x, xl);
184     }
185    
186     void SystemDisplay::printf(const char *s, ...)
187     {
188     va_list ap;
189     va_start(ap, s);
190     char buf[1024];
191     ht_vsnprintf(buf, sizeof buf, s, ap);
192     print(buf);
193     va_end(ap);
194     }
195    
196     void SystemDisplay::setAnsiColor(vcp color)
197     {
198     char ansiseq[32];
199     vcpToAnsi(ansiseq, color);
200     print(ansiseq);
201     }
202    
203     void SystemDisplay::fillAllVT(vcp color, byte chr)
204     {
205     fillVT(0, 0, mVTWidth, mVTHeight, color, chr);
206     }
207    
208     void SystemDisplay::drawChar(int x, int y, vcp color, byte chr)
209     {
210     buf[y*mVTWidth+x].rawchar = chr;
211     buf[y*mVTWidth+x].color = color;
212    
213     uint bg = VCP_BACKGROUND(color);
214     uint fg = VCP_FOREGROUND(color);
215     if (VC_GET_LIGHT(bg)) {
216     bg &= 0xf;
217     bg += 8;
218     }
219     if (VC_GET_LIGHT(fg)) {
220     fg &= 0xf;
221     fg += 8;
222     }
223     RGBA bg2 = _16toRGBA[bg];
224     RGBA fg2 = _16toRGBA[fg];
225     ((Font*)mFont)->drawFixedChar2(this, x, y, mVTDX, mVTDY, chr, fg2, bg2);
226     }
227    
228     void SystemDisplay::fillVT(int x, int y, int w, int h, vcp color, byte chr)
229     {
230     for (int iy = y; iy < y+h; iy++) {
231     if (iy >= mVTHeight) break;
232     BufferedChar *b = buf+x+ iy * mVTWidth;
233     for (int ix = x; ix < x+w; ix++) {
234     b->rawchar = chr;
235     b->color = mixColors(b->color, color);
236     b++;
237     }
238     }
239     for (int iy = 0; iy < mVTHeight; iy++) {
240     BufferedChar *b = buf+x+ iy * mVTWidth;
241     for (int ix = x; ix < mVTWidth; ix++) {
242     uint bg = VCP_BACKGROUND(b->color);
243     uint fg = VCP_FOREGROUND(b->color);
244     if (VC_GET_LIGHT(bg)) {
245     bg &= 0xf;
246     bg += 8;
247     }
248     if (VC_GET_LIGHT(fg)) {
249     fg &= 0xf;
250     fg += 8;
251     }
252     RGBA bg2 = _16toRGBA[bg];
253     RGBA fg2 = _16toRGBA[fg];
254     ((Font*)mFont)->drawFixedChar2(this, ix, iy, mVTDX, mVTDY, b->rawchar, fg2, bg2);
255     b++;
256     }
257     }
258     }
259    
260     /*void SystemDisplay::fill(int x, int y, int w, int h, RGB c)
261     {
262     uint color;
263     c = MK_RGB(0xff, 0xff, 0xff);
264     mixRGB((byte*)&color, c);
265     if (x > mClientChar.width) return;
266     if (y > mClientChar.height) return;
267     if (x < 0) {
268     w += x;
269     x = 0;
270     }
271     if (y < 0) {
272     h += y;
273     y = 0;
274     }
275     if (w <= 0) return;
276     if (h <= 0) return;
277     if (x+w > mClientChar.width) {
278     w = mClientChar.width-x;
279     if (!w) return;
280     }
281     if (y+h > mClientChar.height) {
282     h = mClientChar.height-y;
283     if (!h) return;
284     }
285     byte *f = framebuffer + ((y*mClientChar.width)+x)*mClientChar.bytesPerPixel;
286     switch (mClientChar.bytesPerPixel) {
287     case 2:
288     while (h--) {
289     for (int i=0; i<w; i++) {
290     *(f++) = (((color>>8)>>1)&0x7c)|(((color>>16)>>6) & 3);
291     *(f++) = (((color>>16)<<2)&0xe0)|(((color>>24)>>3) & 0x1f);
292     }
293     f += (mClientChar.width-w)*2;
294     }
295     break;
296     case 4:
297     while (h--) {
298     for (int i=0; i<w; i++) {
299     *(f++) = 0;
300     *(f++) = color>>8;
301     *(f++) = color>>16;
302     *(f++) = color>>24;
303     }
304     f += (mClientChar.width-w)*4;
305     }
306     break;
307     }
308     }*/
309    
310     void SystemDisplay::fillRGB(int x, int y, int w, int h, RGB rgb)
311     {
312     while (h--) {
313     for (int i=0; i<w; i++) {
314     putPixelRGB(x+i, y, rgb);
315     }
316     y++;
317     }
318     }
319    
320     void SystemDisplay::setColor(int idx, RGB color)
321     {
322     if (idx >= 0 && idx < 256) palette[idx] = color;
323     }
324    
325     RGB SystemDisplay::getColor(int idx)
326     {
327     if (idx >= 0 && idx < 256) return palette[idx];
328     return 0;
329     }
330    
331     void SystemDisplay::fillRGBA(int x, int y, int w, int h, RGBA rgba)
332     {
333     while (h--) {
334     for (int i=0; i<w; i++) {
335     putPixelRGBA(x+i, y, rgba);
336     }
337     y++;
338     }
339     }
340    
341     #include <math.h>
342     void SystemDisplay::drawCircleFilled(int x, int y, int w, int h, int cx, int cy, int r, RGBA fg, RGBA bg)
343     {
344     for (int iy=y; iy<y+h; iy++) {
345     for (int ix=x; ix<x+h; ix++) {
346     int rx = ix-cx;
347     int ry = iy-cy;
348     int d = rx*rx + ry*ry;
349     int c = 6;
350     if (d < r*r) {
351     putPixelRGBA(ix, iy, bg);
352     }
353     if ((d >= r*r-c*c) && (d <= r*r+c*c)) {
354     RGBA fg2 = fg;
355     int z = RGBA_A(fg);
356     // int q = (3*c*r-sqrt(3*3*c*c*d));
357     // if (q<0) z+=q; else z-=q;
358     // if (z < 0) z = 0; else if (z>255) z = 255;
359     fg2 = RGBA_SETA(fg2, z);
360     putPixelRGBA(ix, iy, fg2);
361     }
362     }
363     }
364     }
365    
366     void SystemDisplay::drawBox(int x, int y, int w, int h, RGBA fg, RGBA bg)
367     {
368     #if 1
369     fillRGBA(x, y, w, h, bg);
370     for (int xi=0; xi<w; xi++) {
371     putPixelRGBA(x+xi, y, fg);
372     putPixelRGBA(x+xi, y+h-1, fg);
373     }
374     for (int yi=1; yi<h-1; yi++) {
375     putPixelRGBA(x, y+yi, fg);
376     putPixelRGBA(x+w-1, y+yi, fg);
377     }
378     #else
379     uint RE = 5;
380     fillRGBA(x, y, w, h, bg);
381     // drawCircleFilled(x, y, RE, RE, x+RE, y+RE, RE, fg, bg);
382     drawCircleFilled(0, 0, 100, 100, 50, 50, 50, fg, bg);
383     for (uint xi=RE; xi<w-RE; xi++) {
384     putPixelRGBA(x+xi, y, fg);
385     putPixelRGBA(x+xi, y+h-1, fg);
386     }
387     for (uint yi=1+RE; yi<h-1-RE; yi++) {
388     putPixelRGBA(x, y+yi, fg);
389     putPixelRGBA(x+w-1, y+yi, fg);
390     }
391     #endif
392     }
393    
394     void SystemDisplay::insertMenuButton(Stream &str, void (*callback)(void *), void *p)
395     {
396     Gif *pic = new Gif(str);
397     mMenu->insert(new MenuEntry(mMenuX, 0, pic, callback, p));
398     mMenuX += pic->mWidth;
399     mMenuHeight = MAX(mMenuHeight, pic->mHeight);
400     }
401    
402     void SystemDisplay::drawMenu()
403     {
404     int x = 0;
405     for (int i=0; i < (int)mMenu->count(); i++) {
406     MenuEntry *e = (MenuEntry*)(*mMenu)[i];
407     e->mPic->draw(gDisplay, x, (mMenuHeight - e->mPic->mHeight) / 2);
408     x += e->mPic->mWidth;
409     }
410     }
411    
412     void SystemDisplay::clickMenu(int x, int y)
413     {
414     for (int i=0; i < (int)mMenu->count(); i++) {
415     MenuEntry *e = (MenuEntry*)(*mMenu)[i];
416     e->check(x, y);
417     }
418     }
419    
420     void SystemDisplay::composeKeyDialog()
421     {
422     return;
423     // Doesn't work since should get executed in the CPU thread
424     #if 0
425     byte *oldframebuffer = (byte*)malloc(mClientChar.scanLineLength * mClientChar.height);
426     memcpy(oldframebuffer, gFrameBuffer, mClientChar.scanLineLength * mClientChar.height);
427    
428     const int w = 400;
429     const int h = 200;
430     int x = (mClientChar.width-w)/2;
431     int y = (mClientChar.height-h)/2;
432    
433     uint keys[4];
434     int k=0;
435     const RGBA fg = MK_RGBA(0,0,0,0xff);
436     const RGBA bg = MK_RGBA(0xaa,0xee,0xee,0xb0);
437     const RGBA tr = MK_RGBA(0,0,0,0);
438    
439     bool regrabMouse = false;
440     if (isMouseGrabbed()) {
441     regrabMouse = true;
442     setMouseGrab(false);
443     }
444    
445     while (1) {
446     redo:
447     memcpy(gFrameBuffer, oldframebuffer, mClientChar.scanLineLength * mClientChar.height);
448     drawBox(x, y, w, h, fg, bg);
449     outText(x+10, y+10, fg, tr, "Press keys to compose key sequence...");
450    
451     String name;
452     for (int i=0; i<k; i++) {
453     String key_name;
454     SystemKeyboard::convertKeycodeToString(key_name, keys[i]);
455     name += key_name;
456     if (i+1 < k) name += " + ";
457     }
458    
459     outText(x+10, y+50, fg, tr, name);
460    
461     uint32 keycode;
462     do {
463     while (!cuda_prom_get_key(keycode)) sys_suspend();
464     } while (keycode & 0x80);
465    
466     if (keycode == KEY_F11) break;
467    
468     for (int i=0; i<k; i++) {
469     if (keys[i] == keycode) {
470     for (int j=i+1; j<k; j++) {
471     keys[j-1] = keys[j];
472     }
473     k--;
474     goto redo;
475     }
476     }
477    
478     if (k<4) {
479     keys[k] = keycode;
480     k++;
481     }
482     }
483    
484     SystemEvent ev;
485     ev.type = sysevKey;
486     ev.key.pressed = true;
487     for (int i=0; i<k; i++) {
488     ev.key.keycode = keys[i];
489     gKeyboard->handleEvent(ev);
490     }
491     ev.key.pressed = false;
492     for (int i=k-1; i>=0; i--) {
493     ev.key.keycode = keys[i];
494     gKeyboard->handleEvent(ev);
495     }
496    
497     memcpy(gFrameBuffer, oldframebuffer, mClientChar.scanLineLength * mClientChar.height);
498     free(oldframebuffer);
499     if (regrabMouse) setMouseGrab(true);
500     damageFrameBufferAll();
501     #endif
502     }
503    
504     void SystemDisplay::outText(int x, int y, RGBA fg, RGBA bg, const char *text)
505     {
506     while (*text) {
507     ((Font*)mFont)->drawChar2(this, x, y, *text, fg, bg);
508     text++;
509     x+=8;
510     }
511     }
512    
513     void SystemDisplay::mixRGB(byte *pixel, RGB rgb)
514     {
515     uint r = RGB_R(rgb);
516     uint g = RGB_G(rgb);
517     uint b = RGB_B(rgb);
518     convertBaseColor(r, 8, mClientChar.redSize);
519     convertBaseColor(g, 8, mClientChar.greenSize);
520     convertBaseColor(b, 8, mClientChar.blueSize);
521     uint p = (r << mClientChar.redShift) | (g << mClientChar.greenShift)
522     | (b << mClientChar.blueShift);
523     switch (mClientChar.bytesPerPixel) {
524     case 1:
525     pixel[0] = rgb;
526     break;
527     case 2:
528     pixel[0] = p>>8;
529     pixel[1] = p;
530     break;
531     case 4:
532     pixel[0] = p>>24;
533     pixel[1] = p>>16;
534     pixel[2] = p>>8;
535     pixel[3] = p;
536     break;
537     }
538     }
539    
540     void SystemDisplay::mixRGBA(byte *pixel, RGBA rgba)
541     {
542     uint r = RGBA_R(rgba);
543     uint g = RGBA_G(rgba);
544     uint b = RGBA_B(rgba);
545     uint a = RGBA_A(rgba);
546     convertBaseColor(r, 8, mClientChar.redSize);
547     convertBaseColor(g, 8, mClientChar.greenSize);
548     convertBaseColor(b, 8, mClientChar.blueSize);
549     uint p;
550     switch (mClientChar.bytesPerPixel) {
551     case 1:
552     p = pixel[0];
553     break;
554     case 2:
555     p = (pixel[0] << 8) | pixel[1];
556     break;
557     case 4:
558     p = (pixel[0] << 24) | (pixel[1] << 16) | (pixel[2] << 8) | pixel[3];
559     break;
560     default:
561     ht_printf("internal error in %s:%d\n", __FILE__, __LINE__);
562     exit(1);
563     break;
564     }
565     uint sr = (p>>mClientChar.redShift) & ((1<<mClientChar.redSize)-1);
566     uint sg = (p>>mClientChar.greenShift) & ((1<<mClientChar.greenSize)-1);
567     uint sb = (p>>mClientChar.blueShift) & ((1<<mClientChar.blueSize)-1);
568     sr = (r*a + sr*(255-a))/255;
569     sg = (g*a + sg*(255-a))/255;
570     sb = (b*a + sb*(255-a))/255;
571     p = (sr << mClientChar.redShift) | (sg << mClientChar.greenShift)
572     | (sb << mClientChar.blueShift);
573     switch (mClientChar.bytesPerPixel) {
574     case 1:
575     pixel[0] = p;
576     break;
577     case 2:
578     pixel[0] = p>>8;
579     pixel[1] = p;
580     break;
581     case 4:
582     pixel[0] = p>>24;
583     pixel[1] = p>>16;
584     pixel[2] = p>>8;
585     pixel[3] = p;
586     break;
587     }
588     }
589    
590     void SystemDisplay::putPixelRGB(int x, int y, RGB rgb)
591     {
592     uint addr = x*mClientChar.bytesPerPixel + y*mClientChar.scanLineLength;
593     mixRGB(&gFrameBuffer[addr], rgb);
594     damageFrameBuffer(addr);
595     }
596    
597     void SystemDisplay::putPixelRGBA(int x, int y, RGBA rgba)
598     {
599     uint addr = x*mClientChar.bytesPerPixel + y*mClientChar.scanLineLength;
600     mixRGBA(&gFrameBuffer[addr], rgba);
601     damageFrameBuffer(addr);
602     }
603    
604     void SystemDisplay::setMouseGrab(bool mouseGrab)
605     {
606     mMouseGrabbed = mouseGrab;
607     if (!mFullscreenChanged) updateTitle();
608     }
609    
610     bool SystemDisplay::setFullscreenMode(bool fullscreen)
611     {
612     mFullscreen = fullscreen;
613     changeResolution(mClientChar);
614     if (mFullscreenChanged) {
615     setMouseGrab(true);
616     } else {
617     setMouseGrab(false);
618     }
619     return mFullscreenChanged;
620     }

  ViewVC Help
Powered by ViewVC 1.1.26