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

Archive Download this file

Revision: 1804