/[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

Contents of /src/system/display.cc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (show 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 /*
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