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

Archive Download this file

Revision: 789