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

Archive Download this file

Revision: 1899