Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/i386/boot2/graphics.c

1/*
2 * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 2.0 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24/*
25 * Copyright 1993 NeXT, Inc.
26 * All rights reserved.
27 */
28
29#include "boot.h"
30#include "graphics.h"
31#include "vbe.h"
32#include "appleClut8.h"
33#include "bootstruct.h"
34#include "modules.h"
35
36#define VIDEO(x) (bootArgs->Video.v_ ## x)
37
38#define MIN(x, y) ((x) < (y) ? (x) : (y))
39
40static void setupPalette( VBEPalette * p, const unsigned char * g );
41static int
42setVESATextMode( unsigned short cols,
43unsigned short rows,
44unsigned char bitsPerPixel );
45
46static int initGraphicsMode (void);
47
48static unsigned long lookUpCLUTIndex( unsigned char index,
49 unsigned char depth );
50
51static void * stosl(void * dst, long val, long len);
52
53int
54__convertImage( unsigned short width,
55 unsigned short height,
56 const unsigned char *imageData,
57 unsigned char **newImageData )
58{
59 int cnt;
60 unsigned char *img = 0;
61 unsigned short *img16;
62 unsigned long *img32;
63
64 switch ( VIDEO(depth) ) {
65case 16 :
66img16 = malloc(width * height * 2);
67if ( !img16 ) break;
68for (cnt = 0; cnt < (width * height); cnt++)
69img16[cnt] = lookUpCLUTIndex(imageData[cnt], 16);
70img = (unsigned char *)img16;
71break;
72
73case 32 :
74img32 = malloc(width * height * 4);
75if ( !img32 ) break;
76for (cnt = 0; cnt < (width * height); cnt++)
77img32[cnt] = lookUpCLUTIndex(imageData[cnt], 32);
78img = (unsigned char *)img32;
79break;
80
81default :
82img = malloc(width * height);
83bcopy(imageData, img, width * height);
84break;
85 }
86 *newImageData = img;
87 return 0;
88}
89
90//==========================================================================
91// drawDataRectangle
92
93void __drawDataRectangle( unsigned short x,
94 unsigned short y,
95 unsigned short width,
96 unsigned short height,
97 unsigned char * data )
98{
99 unsigned short drawWidth;
100 long pixelBytes = VIDEO(depth) / 8;
101 unsigned char * vram = (unsigned char *) VIDEO(baseAddr) +
102VIDEO(rowBytes) * y + pixelBytes * x;
103
104 drawWidth = MIN(width, VIDEO(width) - x);
105 height = MIN(height, VIDEO(height) - y);
106 while ( height-- ) {
107 bcopy( data, vram, drawWidth * pixelBytes );
108 vram += VIDEO(rowBytes);
109 data += width * pixelBytes;
110 }
111}
112
113//==========================================================================
114// getVESAModeWithProperties
115//
116// Return the VESA mode that matches the properties specified.
117// If a mode is not found, then return the "best" available mode.
118
119unsigned short
120__getVESAModeWithProperties( unsigned short width,
121 unsigned short height,
122 unsigned char bitsPerPixel,
123 unsigned short attributesSet,
124 unsigned short attributesClear,
125 VBEModeInfoBlock * outModeInfo,
126 unsigned short * vesaVersion )
127{
128 VBEInfoBlock vbeInfo;
129 unsigned short * modePtr;
130 VBEModeInfoBlock modeInfo;
131 unsigned char modeBitsPerPixel;
132 unsigned short matchedMode = modeEndOfList;
133 int err;
134
135 // Clear output mode info.
136
137 //bzero( outModeInfo, sizeof(*outModeInfo) );
138bzero( outModeInfo, sizeof(VBEModeInfoBlock) );
139
140 // Get VBE controller info containing the list of supported modes.
141
142 //bzero( &vbeInfo, sizeof(vbeInfo) );
143 bzero( &vbeInfo, sizeof(VBEInfoBlock) );
144
145 strcpy( (char*)&vbeInfo, "VBE2" );
146 err = getVBEInfo( &vbeInfo );
147 if ( err != errSuccess )
148 {
149 return modeEndOfList;
150 }
151
152 // Report the VESA major/minor version number.
153
154 if (vesaVersion) *vesaVersion = vbeInfo.VESAVersion;
155
156 // Loop through the mode list, and find the matching mode.
157
158 for ( modePtr = VBEDecodeFP( unsigned short *, vbeInfo.VideoModePtr );
159 *modePtr != modeEndOfList; modePtr++ )
160 {
161 // Get mode information.
162
163 //bzero( &modeInfo, sizeof(modeInfo) );
164 bzero( &modeInfo, sizeof(VBEModeInfoBlock) );
165
166 err = getVBEModeInfo( *modePtr, &modeInfo );
167 if ( err != errSuccess )
168 {
169 continue;
170 }
171
172#if DEBUG
173 printf("Mode %x: %dx%dx%d mm:%d attr:%x\n",
174 *modePtr, modeInfo.XResolution, modeInfo.YResolution,
175 modeInfo.BitsPerPixel, modeInfo.MemoryModel,
176 modeInfo.ModeAttributes);
177#endif
178
179 // Filter out unwanted modes based on mode attributes.
180
181 if ( ( ( modeInfo.ModeAttributes & attributesSet ) != attributesSet )
182|| ( ( modeInfo.ModeAttributes & attributesClear ) != 0 ) )
183 {
184 continue;
185 }
186
187 // Pixel depth in bits.
188
189 modeBitsPerPixel = modeInfo.BitsPerPixel;
190
191 if ( ( modeBitsPerPixel == 4 ) && ( modeInfo.MemoryModel == 0 ) )
192 {
193 // Text mode, 16 colors.
194 }
195 else if ( ( modeBitsPerPixel == 8 ) && ( modeInfo.MemoryModel == 4 ) )
196 {
197 // Packed pixel, 256 colors.
198 }
199 else if ( ( ( modeBitsPerPixel == 16 ) || ( modeBitsPerPixel == 15 ) )
200 && ( modeInfo.MemoryModel == 6 )
201 && ( modeInfo.RedMaskSize == 5 )
202 && ( modeInfo.GreenMaskSize == 5 )
203 && ( modeInfo.BlueMaskSize == 5 ) )
204 {
205 // Direct color, 16 bpp (1:5:5:5).
206 modeInfo.BitsPerPixel = modeBitsPerPixel = 16;
207 }
208 else if ( ( modeBitsPerPixel == 32 )
209 && ( modeInfo.MemoryModel == 6 )
210 && ( modeInfo.RedMaskSize == 8 )
211 && ( modeInfo.GreenMaskSize == 8 )
212 && ( modeInfo.BlueMaskSize == 8 ) )
213 {
214 // Direct color, 32 bpp (8:8:8:8).
215 }
216 else
217 {
218 continue; // Not a supported mode.
219 }
220
221 // Modes larger than the specified dimensions are skipped.
222
223 if ( ( modeInfo.XResolution > width ) ||
224( modeInfo.YResolution > height ) )
225 {
226 continue;
227 }
228
229 // Perfect match, we're done looking.
230
231 if ( ( modeInfo.XResolution == width ) &&
232( modeInfo.YResolution == height ) &&
233( modeBitsPerPixel == bitsPerPixel ) )
234 {
235 matchedMode = *modePtr;
236 //bcopy( &modeInfo, outModeInfo, sizeof(modeInfo) );
237 bcopy( &modeInfo, outModeInfo, sizeof(VBEModeInfoBlock) );
238
239 break;
240 }
241
242 // Save the next "best" mode in case a perfect match is not found.
243
244 if ( modeInfo.XResolution == outModeInfo->XResolution &&
245modeInfo.YResolution == outModeInfo->YResolution &&
246modeBitsPerPixel <= outModeInfo->BitsPerPixel )
247 {
248 continue; // Saved mode has more depth.
249 }
250 if ( modeInfo.XResolution < outModeInfo->XResolution ||
251modeInfo.YResolution < outModeInfo->YResolution ||
252modeBitsPerPixel < outModeInfo->BitsPerPixel )
253 {
254 continue; // Saved mode has more resolution.
255 }
256
257 matchedMode = *modePtr;
258 //bcopy( &modeInfo, outModeInfo, sizeof(modeInfo) );
259 bcopy( &modeInfo, outModeInfo, sizeof(VBEModeInfoBlock) );
260
261 }
262
263 return matchedMode;
264}
265
266//==========================================================================
267// setupPalette
268
269static void setupPalette( VBEPalette * p, const unsigned char * g )
270{
271 int i;
272 unsigned char * source = (unsigned char *) g;
273
274 for (i = 0; i < 256; i++)
275 {
276 (*p)[i] = 0;
277 (*p)[i] |= ((unsigned long)((*source++) >> 2)) << 16; // Red
278 (*p)[i] |= ((unsigned long)((*source++) >> 2)) << 8; // Green
279 (*p)[i] |= ((unsigned long)((*source++) >> 2)); // Blue
280
281 }
282}
283
284//==========================================================================
285// setVESAGraphicsMode
286#if UNUSED
287int __setVESAGraphicsMode( unsigned short width, unsigned short height, unsigned char bitsPerPixel, unsigned short refreshRate )
288#else
289int __setVESAGraphicsMode( unsigned short width, unsigned short height, unsigned char bitsPerPixel)
290#endif
291{
292 VBEModeInfoBlock minfo;
293 unsigned short mode;
294 unsigned short vesaVersion;
295 int err = errFuncNotSupported;
296
297 do {
298 mode = __getVESAModeWithProperties( width, height, bitsPerPixel,
299 maColorModeBit |
300 maModeIsSupportedBit |
301 maGraphicsModeBit |
302 maLinearFrameBufferAvailBit,
303 0,
304 &minfo, &vesaVersion );
305 if ( mode == modeEndOfList )
306 {
307 break;
308 }
309#if UNUSED
310//
311// FIXME : generateCRTCTiming() causes crash.
312//
313
314// if ( (vesaVersion >> 8) >= 3 && refreshRate >= 60 &&
315// (get_env(envgBootMode) & kBootModeSafe) == 0 )
316// {
317// VBECRTCInfoBlock timing;
318//
319// // Generate CRTC timing for given refresh rate.
320//
321// generateCRTCTiming( minfo.XResolution, minfo.YResolution,
322// refreshRate, kCRTCParamRefreshRate,
323// &timing );
324//
325// // Find the actual pixel clock supported by the hardware.
326//
327// getVBEPixelClock( mode, &timing.PixelClock );
328//
329// // Re-compute CRTC timing based on actual pixel clock.
330//
331// generateCRTCTiming( minfo.XResolution, minfo.YResolution,
332// timing.PixelClock, kCRTCParamPixelClock,
333// &timing );
334//
335// // Set the video mode and use specified CRTC timing.
336//
337// err = setVBEMode( mode | kLinearFrameBufferBit |
338// kCustomRefreshRateBit, &timing );
339// }
340// else
341// {
342// // Set the mode with default refresh rate.
343//
344// err = setVBEMode( mode | kLinearFrameBufferBit, NULL );
345// }
346#endif
347 // Set the mode with default refresh rate.
348
349 err = setVBEMode( mode | kLinearFrameBufferBit, NULL );
350
351 if ( err != errSuccess )
352 {
353 break;
354 }
355
356 // Set 8-bit color palette.
357
358 if ( minfo.BitsPerPixel == 8 )
359 {
360 VBEPalette palette;
361 setupPalette( &palette, appleClut8 );
362 if ((err = setVBEPalette(palette)) != errSuccess)
363 {
364 break;
365 }
366 }
367
368 // Is this required for buggy Video BIOS implementations?
369 // On which adapter?
370
371 if ( minfo.BytesPerScanline == 0 )
372minfo.BytesPerScanline = ( minfo.XResolution *
373 minfo.BitsPerPixel ) >> 3;
374
375 // Update KernBootStruct using info provided by the selected
376 // VESA mode.
377
378 Boot_VideoVideo;/* Video Information */
379
380 Video.v_display = GRAPHICS_MODE;
381 Video.v_width = minfo.XResolution;
382 Video.v_height = minfo.YResolution;
383 Video.v_depth = minfo.BitsPerPixel;
384 Video.v_rowBytes = minfo.BytesPerScanline;
385 Video.v_baseAddr = VBEMakeUInt32(minfo.PhysBasePtr);
386
387setBootArgsVideoStruct(&Video);
388
389 }
390 while ( 0 );
391
392 return err;
393}
394
395
396//==========================================================================
397// Simple decompressor for boot images encoded in RLE format.
398
399char * __decodeRLE( const void * rleData, int rleBlocks, int outBytes )
400{
401 char *out, *cp;
402
403 struct RLEBlock {
404 unsigned char count;
405 unsigned char value;
406 } * bp = (struct RLEBlock *) rleData;
407
408 out = cp = malloc( outBytes );
409 if ( out == NULL ) return NULL;
410
411 while ( rleBlocks-- )
412 {
413 memset( cp, bp->value, bp->count );
414 cp += bp->count;
415 bp++;
416 }
417
418 return out;
419}
420
421//==========================================================================
422// LookUpCLUTIndex
423
424static unsigned long lookUpCLUTIndex( unsigned char index,
425 unsigned char depth )
426{
427 long result, red, green, blue;
428
429 red = appleClut8[index * 3 + 0];
430 green = appleClut8[index * 3 + 1];
431 blue = appleClut8[index * 3 + 2];
432
433 switch (depth) {
434 case 16 :
435 result = ((red & 0xF8) << 7) |
436((green & 0xF8) << 2) |
437((blue & 0xF8) >> 3);
438 result |= (result << 16);
439 break;
440
441 case 32 :
442 result = (red << 16) | (green << 8) | blue;
443 break;
444
445 default :
446 result = index | (index << 8);
447 result |= (result << 16);
448 break;
449 }
450
451 return result;
452}
453
454//==========================================================================
455// drawColorRectangle
456
457static void * stosl(void * dst, long val, long len)
458{
459 asm volatile ( "rep; stosl"
460 : "=c" (len), "=D" (dst)
461 : "0" (len), "1" (dst), "a" (val)
462 : "memory" );
463
464 return dst;
465}
466
467void __drawColorRectangle( unsigned short x,
468 unsigned short y,
469 unsigned short width,
470 unsigned short height,
471 unsigned char colorIndex )
472{
473 long pixelBytes;
474 long color = lookUpCLUTIndex( colorIndex, VIDEO(depth) );
475 char * vram;
476
477 pixelBytes = VIDEO(depth) / 8;
478 vram = (char *) VIDEO(baseAddr) +
479VIDEO(rowBytes) * y + pixelBytes * x;
480
481 width = MIN(width, VIDEO(width) - x);
482 height = MIN(height, VIDEO(height) - y);
483
484 while ( height-- )
485 {
486 int rem = ( pixelBytes * width ) % 4;
487 if ( rem ) bcopy( &color, vram, rem );
488 stosl( vram + rem, color, pixelBytes * width / 4 );
489 vram += VIDEO(rowBytes);
490 }
491}
492
493//==========================================================================
494// setVESATextMode
495
496static int
497setVESATextMode( unsigned short cols,
498unsigned short rows,
499unsigned char bitsPerPixel )
500{
501 VBEModeInfoBlock minfo;
502 unsigned short mode = modeEndOfList;
503
504 if ( (cols != 80) || (rows != 25) ) // not 80x25 mode
505 {
506 mode = __getVESAModeWithProperties( cols, rows, bitsPerPixel,
507 maColorModeBit |
508 maModeIsSupportedBit,
509 maGraphicsModeBit,
510 &minfo, NULL );
511 }
512
513 if ( ( mode == modeEndOfList ) || ( setVBEMode(mode, NULL) != errSuccess ) )
514 {
515 video_mode( 2 ); // VGA BIOS, 80x25 text mode.
516 minfo.XResolution = 80;
517 minfo.YResolution = 25;
518 }
519
520 // Update KernBootStruct using info provided by the selected
521 // VESA mode.
522
523 Boot_VideoVideo;/* Video Information */
524
525 Video.v_display = VGA_TEXT_MODE;
526 Video.v_width = 0xb8000;
527 Video.v_height = minfo.XResolution;
528 Video.v_depth = minfo.YResolution;
529 Video.v_rowBytes = 8;
530 Video.v_baseAddr = 0x8000;
531
532 setBootArgsVideoStruct(&Video);
533
534 return errSuccess; // always return success
535}
536
537//==========================================================================
538// getNumberArrayFromProperty
539
540int
541__getNumberArrayFromProperty( const char * propKey,
542 unsigned long numbers[],
543 unsigned long maxArrayCount )
544{
545 char * propStr;
546 unsigned long count = 0;
547
548 propStr = newStringForKey( (char *) propKey , DEFAULT_BOOT_CONFIG );
549 if ( propStr )
550 {
551 char * delimiter = propStr;
552 char * p = propStr;
553
554 while ( count < maxArrayCount && *p != '\0' )
555 {
556 unsigned long val = strtoul( p, &delimiter, 10 );
557 if ( p != delimiter )
558 {
559 numbers[count++] = val;
560 p = delimiter;
561 }
562 while ( ( *p != '\0' ) && !isdigit(*p) )
563 p++;
564 }
565
566 free( propStr );
567 }
568
569 return count;
570}
571
572static int initGraphicsMode (void)
573{
574unsigned long params[4];
575int count;
576
577params[3] = 0;
578count = __getNumberArrayFromProperty( kGraphicsModeKey, params, 4 );
579
580// Try to find a resolution if "Graphics Mode" setting is not available.
581if ( count < 3 )
582{
583params[0] = DEFAULT_SCREEN_WIDTH;
584params[1] = DEFAULT_SCREEN_HEIGHT;
585params[2] = 32;
586}
587
588// Map from pixel format to bits per pixel.
589
590if ( params[2] == 256 ) params[2] = 8;
591if ( params[2] == 555 ) params[2] = 16;
592if ( params[2] == 888 ) params[2] = 32;
593#if UNUSED
594return __setVESAGraphicsMode( params[0], params[1], params[2], params[3] );
595#else
596return __setVESAGraphicsMode( params[0], params[1], params[2] );
597#endif
598}
599
600//==========================================================================
601// setVideoMode
602//
603// Set the video mode to VGA_TEXT_MODE or GRAPHICS_MODE.
604#if UNUSED
605void
606__setVideoMode( int mode, int drawgraphics)
607#else
608void
609__setVideoMode( int mode)
610#endif
611{
612 unsigned long params[4];
613 int count;
614 int err = errSuccess;
615
616 if ( mode == GRAPHICS_MODE )
617 {
618 if ( (err=initGraphicsMode ()) == errSuccess ) {
619if (gVerboseMode) {
620// Tell the kernel to use text mode on a linear frame buffer display
621bootArgs->Video.v_display = FB_TEXT_MODE;
622} else {
623bootArgs->Video.v_display = GRAPHICS_MODE;
624}
625}
626 }
627
628 if ( (mode == VGA_TEXT_MODE) || (err != errSuccess) )
629 {
630 count = __getNumberArrayFromProperty( kTextModeKey, params, 2 );
631 if ( count < 2 )
632 {
633 params[0] = 80; // Default text mode is 80x25.
634 params[1] = 25;
635 }
636
637setVESATextMode( params[0], params[1], 4 );
638 bootArgs->Video.v_display = VGA_TEXT_MODE;
639 }
640}

Archive Download this file

Revision: 1913