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

Archive Download this file

Revision: 1919