|
|
1.1 root 1: /*
2: * Creation Date: <2002/10/23 20:26:40 samuel>
3: * Time-stamp: <2004/01/07 19:39:15 samuel>
4: *
5: * <video.c>
6: *
7: * Mac-on-Linux display node
8: *
9: * Copyright (C) 2002, 2003, 2004 Samuel Rydh ([email protected])
10: *
11: * This program is free software; you can redistribute it and/or
12: * modify it under the terms of the GNU General Public License
13: * as published by the Free Software Foundation
14: *
15: */
16:
17: #include "config.h"
18: #include "libopenbios/bindings.h"
19: #include "libc/diskio.h"
20: #include "libopenbios/ofmem.h"
21: #include "drivers/drivers.h"
22: #include "packages/video.h"
23: #include "libopenbios/console.h"
24: #include "drivers/vga.h"
25:
26: typedef struct osi_fb_info {
27: unsigned long mphys;
28: int rb, w, h, depth;
29: } osi_fb_info_t;
30:
31: static struct {
32: int has_video;
33: osi_fb_info_t fb;
34: unsigned long *pal; /* 256 elements */
35: } video;
36:
37:
38: int
39: video_get_res( int *w, int *h )
40: {
41: if( !video.has_video ) {
42: *w = *h = 0;
43: return -1;
44: }
45: *w = video.fb.w;
46: *h = video.fb.h;
47: return 0;
48: }
49:
50: static void
51: startup_splash( void )
52: {
53: #ifdef CONFIG_MOL
54: int fd, s, i, y, x, dx, dy;
55: int width, height;
56: char *pp, *p;
57: char buf[64];
58: #endif
59:
60: /* only draw logo in 24-bit mode (for now) */
61: if( video.fb.depth < 15 )
62: return;
63: #ifdef CONFIG_MOL
64: for( i=0; i<2; i++ ) {
65: if( !BootHGetStrResInd("bootlogo", buf, sizeof(buf), 0, i) )
66: return;
67: *(!i ? &width : &height) = atol(buf);
68: }
69:
70: if( (s=width * height * 3) > 0x20000 )
71: return;
72:
73: if( (fd=open_io("pseudo:,bootlogo")) >= 0 ) {
74: p = malloc( s );
75: if( read_io(fd, p, s) != s )
76: printk("bootlogo size error\n");
77: close_io( fd );
78:
79: dx = (video.fb.w - width)/2;
80: dy = (video.fb.h - height)/3;
81:
82: pp = (char*)video.fb.mphys + dy * video.fb.rb + dx * (video.fb.depth >= 24 ? 4 : 2);
83:
84: for( y=0 ; y<height; y++, pp += video.fb.rb ) {
85: if( video.fb.depth >= 24 ) {
86: unsigned long *d = (unsigned long*)pp;
87: for( x=0; x<width; x++, p+=3, d++ )
88: *d = ((int)p[0] << 16) | ((int)p[1] << 8) | p[2];
89: } else if( video.fb.depth == 15 ) {
90: unsigned short *d = (unsigned short*)pp;
91: for( x=0; x<width; x++, p+=3, d++ ) {
92: int col = ((int)p[0] << 16) | ((int)p[1] << 8) | p[2];
93: *d = ((col>>9) & 0x7c00) | ((col>>6) & 0x03e0) | ((col>>3) & 0x1f);
94: }
95: }
96: }
97: free( p );
98: }
99: #else
100: /* No bootlogo support yet on other platforms */
101: return;
102: #endif
103: }
104:
105: static unsigned long
106: get_color( int col_ind )
107: {
108: unsigned long col;
109: if( !video.has_video || col_ind < 0 || col_ind > 255 )
110: return 0;
111: if( video.fb.depth == 8 )
112: return col_ind;
113: col = video.pal[col_ind];
114: if( video.fb.depth == 24 || video.fb.depth == 32 )
115: return col;
116: if( video.fb.depth == 15 )
117: return ((col>>9) & 0x7c00) | ((col>>6) & 0x03e0) | ((col>>3) & 0x1f);
118: return 0;
119: }
120:
121: void
122: draw_pixel( int x, int y, int colind )
123: {
124: char *p = (char*)video.fb.mphys + video.fb.rb * y;
125: int color, d = video.fb.depth;
126:
127: if( x < 0 || y < 0 || x >= video.fb.w || y >=video.fb.h )
128: return;
129: color = get_color( colind );
130:
131: if( d >= 24 )
132: *((unsigned long*)p + x) = color;
133: else if( d >= 15 )
134: *((short*)p + x) = color;
135: else
136: *(p + x) = color;
137: }
138:
139: static void
140: fill_rect( int col_ind, int x, int y, int w, int h )
141: {
142: char *pp;
143: unsigned long col = get_color(col_ind);
144:
145: if (!video.has_video || x < 0 || y < 0 || w <= 0 || h <= 0 ||
146: x + w > video.fb.w || y + h > video.fb.h)
147: return;
148:
149: pp = (char*)video.fb.mphys + video.fb.rb * y;
150: for( ; h--; pp += video.fb.rb ) {
151: int ww = w;
152: if( video.fb.depth == 24 || video.fb.depth == 32 ) {
153: unsigned long *p = (unsigned long*)pp + x;
154: while( ww-- )
155: *p++ = col;
156: } else if( video.fb.depth == 16 || video.fb.depth == 15 ) {
157: unsigned short *p = (unsigned short*)pp + x;
158: while( ww-- )
159: *p++ = col;
160: } else {
161: char *p = (char *)((unsigned short*)pp + x);
162:
163: while( ww-- )
164: *p++ = col;
165: }
166: }
167: }
168:
169: static void
170: refresh_palette( void )
171: {
172: #ifdef CONFIG_MOL
173: if( video.fb.depth == 8 )
174: OSI_RefreshPalette();
175: #endif
176: }
177:
178: void
179: set_color( int ind, unsigned long color )
180: {
181: if( !video.has_video || ind < 0 || ind > 255 )
182: return;
183: video.pal[ind] = color;
184:
185: #ifdef CONFIG_MOL
186: if( video.fb.depth == 8 )
187: OSI_SetColor( ind, color );
188: #elif defined(CONFIG_SPARC32)
189: if( video.fb.depth == 8 ) {
190: dac[0] = ind << 24;
191: dac[1] = ((color >> 16) & 0xff) << 24; // Red
192: dac[1] = ((color >> 8) & 0xff) << 24; // Green
193: dac[1] = (color & 0xff) << 24; // Blue
194: }
195: #else
196: vga_set_color(ind, ((color >> 16) & 0xff),
197: ((color >> 8) & 0xff),
198: (color & 0xff));
199: #endif
200: }
201:
202: void
203: video_scroll( int height )
204: {
205: int i, offs, size, *dest, *src;
206:
207: if (height <= 0 || height >= video.fb.h) {
208: return;
209: }
210: offs = video.fb.rb * height;
211: size = (video.fb.h * video.fb.rb - offs)/16;
212: dest = (int*)video.fb.mphys;
213: src = (int*)(video.fb.mphys + offs);
214:
215: for( i=0; i<size; i++ ) {
216: dest[0] = src[0];
217: dest[1] = src[1];
218: dest[2] = src[2];
219: dest[3] = src[3];
220: dest += 4;
221: src += 4;
222: }
223: }
224:
225: /************************************************************************/
226: /* OF methods */
227: /************************************************************************/
228:
229: DECLARE_NODE( video, INSTALL_OPEN, 0, "Tdisplay" );
230:
231: /* ( -- width height ) (?) */
232: static void
233: video_dimensions( void )
234: {
235: int w, h;
236: (void) video_get_res( &w, &h );
237: PUSH( w );
238: PUSH( h );
239: }
240:
241: /* ( table start count -- ) (?) */
242: static void
243: video_set_colors( void )
244: {
245: int count = POP();
246: int start = POP();
247: unsigned char *p = (unsigned char*)cell2pointer(POP());
248: int i;
249:
250: for( i=0; i<count; i++, p+=3 ) {
251: unsigned long col = (p[0] << 16) | (p[1] << 8) | p[2];
252: set_color( i + start, col );
253: }
254: refresh_palette();
255: }
256:
257: /* ( r g b index -- ) */
258: static void
259: video_color_bang( void )
260: {
261: int index = POP();
262: int b = POP();
263: int g = POP();
264: int r = POP();
265: unsigned long col = ((r << 16) & 0xff0000) | ((g << 8) & 0x00ff00) | (b & 0xff);
266: /* printk("color!: %08lx %08lx %08lx %08lx\n", r, g, b, index ); */
267: set_color( index, col );
268: refresh_palette();
269: }
270:
271: /* ( color_ind x y width height -- ) (?) */
272: static void
273: video_fill_rect( void )
274: {
275: int h = POP();
276: int w = POP();
277: int y = POP();
278: int x = POP();
279: int color_ind = POP();
280:
281: fill_rect( color_ind, x, y, w, h );
282: }
283:
284: /* ( addr len -- actual ) */
285: static void
286: video_write(void)
287: {
288: char *addr;
289: int len;
290:
291: len = POP();
292: addr = (char *)cell2pointer(POP());
293:
294: console_draw_fstr(addr, len);
295: PUSH(len);
296: }
297:
298: NODE_METHODS( video ) = {
299: {"dimensions", video_dimensions },
300: {"set-colors", video_set_colors },
301: {"fill-rectangle", video_fill_rect },
302: {"color!", video_color_bang },
303: {"write", video_write },
304: };
305:
306:
307: /************************************************************************/
308: /* init */
309: /************************************************************************/
310:
311: void
312: init_video( unsigned long fb, int width, int height, int depth, int rb )
313: {
314: int i;
315: #ifdef CONFIG_PPC
316: int s, size;
317: #endif
318: phandle_t ph=0;
319:
320: video.fb.mphys = fb;
321: video.fb.w = width;
322: video.fb.h = height;
323: video.fb.depth = depth;
324: video.fb.rb = rb;
325: while( (ph=dt_iterate_type(ph, "display")) ) {
326: set_int_property( ph, "width", video.fb.w );
327: set_int_property( ph, "height", video.fb.h );
328: set_int_property( ph, "depth", video.fb.depth );
329: set_int_property( ph, "linebytes", video.fb.rb );
330: set_int_property( ph, "address", video.fb.mphys );
331: }
332: video.has_video = 1;
333: video.pal = malloc( 256 * sizeof(unsigned long) );
334:
335: #ifdef CONFIG_PPC
336: s = (video.fb.mphys & 0xfff);
337: size = ((video.fb.h * video.fb.rb + s) + 0xfff) & ~0xfff;
338:
339: ofmem_claim_phys( video.fb.mphys, size, 0 );
340: ofmem_claim_virt( video.fb.mphys, size, 0 );
341: ofmem_map( video.fb.mphys, video.fb.mphys, size, -1 );
342: #endif
343:
344: for( i=0; i<256; i++ )
345: set_color( i, i * 0x010101 );
346:
347: set_color( 254, 0xffffcc );
348: fill_rect( 254, 0, 0, video.fb.w, video.fb.h );
349:
350: refresh_palette();
351: startup_splash();
352:
353: REGISTER_NODE( video );
354: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.