Chameleon

Chameleon Svn Source Tree

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

Source at commit 533 created 13 years 7 months ago.
By meklort, GUI module should now work in the four main cases (combo of embededtheme and /Extra/Themes). Only tested on my machines.
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 "IOHibernatePrivate.h"
35
36/*
37 * for spinning disk
38 */
39static int currentIndicator = 0;
40
41int previewTotalSectors = 0;
42int previewLoadedSectors = 0;
43uint8_t *previewSaveunder = 0;
44
45#define VIDEO(x) (bootArgs->Video.v_ ## x)
46
47#define MIN(x, y) ((x) < (y) ? (x) : (y))
48
49//==========================================================================
50// getVBEInfoString
51
52char *getVBEInfoString()
53{
54VBEInfoBlock vbeInfo;
55int err, small;
56char *buff = malloc(sizeof(char)*256);
57if(!buff) return 0;
58
59bzero( &vbeInfo, sizeof(vbeInfo) );
60strcpy( (char*)&vbeInfo, "VBE2" );
61err = getVBEInfo( &vbeInfo );
62if (err != errSuccess)
63return 0;
64
65if ( strncmp( (char *)vbeInfo.VESASignature, "VESA", 4 ) )
66return 0;
67
68small = (vbeInfo.TotalMemory < 16);
69
70sprintf(buff, "VESA v%d.%d %d%s (%s)\n",
71vbeInfo.VESAVersion >> 8,
72vbeInfo.VESAVersion & 0xf,
73small ? (vbeInfo.TotalMemory * 64) : (vbeInfo.TotalMemory / 16),
74small ? "KB" : "MB",
75VBEDecodeFP(const char *, vbeInfo.OEMStringPtr) );
76
77return buff;
78}
79
80//==========================================================================
81//
82
83void
84printVBEModeInfo()
85{
86 VBEInfoBlock vbeInfo;
87 unsigned short * modePtr;
88 VBEModeInfoBlock modeInfo;
89 int err;
90 int line;
91
92 bzero( &vbeInfo, sizeof(vbeInfo) );
93 strcpy( (char*)&vbeInfo, "VBE2" );
94 err = getVBEInfo( &vbeInfo );
95 if ( err != errSuccess )
96 return;
97
98 line = 0;
99
100 // Activate and clear page 1
101 setActiveDisplayPage(1);
102 clearScreenRows(0, 24);
103 setCursorPosition( 0, 0, 1 );
104
105 printf( getVBEInfoString() );
106printf("Video modes supported:\n", VBEDecodeFP(const char *, vbeInfo.OEMStringPtr));
107
108// Loop through the mode list, and find the matching mode.
109
110 for ( modePtr = VBEDecodeFP( unsigned short *, vbeInfo.VideoModePtr );
111 *modePtr != modeEndOfList; modePtr++ )
112 {
113 // Get mode information.
114
115 bzero( &modeInfo, sizeof(modeInfo) );
116 err = getVBEModeInfo( *modePtr, &modeInfo );
117 if ( err != errSuccess )
118 {
119 continue;
120 }
121
122 printf("Mode %x: %dx%dx%d mm:%d attr:%x\n",
123 *modePtr, modeInfo.XResolution, modeInfo.YResolution,
124 modeInfo.BitsPerPixel, modeInfo.MemoryModel,
125 modeInfo.ModeAttributes);
126
127 if (line++ >= 20) {
128 pause();
129 line = 0;
130 clearScreenRows(0, 24);
131 setCursorPosition( 0, 0, 1 );
132 }
133 }
134 if (line != 0) {
135 pause();
136 }
137 setActiveDisplayPage(0);
138}
139
140char *getVBEModeInfoString()
141{
142VBEInfoBlock vbeInfo;
143 unsigned short * modePtr;
144 VBEModeInfoBlock modeInfo;
145 int err;
146
147 bzero( &vbeInfo, sizeof(vbeInfo) );
148 strcpy( (char*)&vbeInfo, "VBE2" );
149 err = getVBEInfo( &vbeInfo );
150 if ( err != errSuccess )
151 return 0;
152
153char *buff=malloc(sizeof(char)*3072);
154if(!buff) return 0;
155
156// Loop through the mode list, and find the matching mode.
157 for ( modePtr = VBEDecodeFP( unsigned short *, vbeInfo.VideoModePtr );
158 *modePtr != modeEndOfList; modePtr++ )
159 {
160 // Get mode information.
161
162 bzero( &modeInfo, sizeof(modeInfo) );
163 err = getVBEModeInfo( *modePtr, &modeInfo );
164 if ( err != errSuccess )
165 {
166 continue;
167 }
168
169 sprintf(buff+strlen(buff), "Mode %x: %dx%dx%d mm:%d attr:%x\n",
170*modePtr, modeInfo.XResolution, modeInfo.YResolution,
171modeInfo.BitsPerPixel, modeInfo.MemoryModel,
172modeInfo.ModeAttributes);
173
174 }
175return buff;
176}
177
178//==========================================================================
179// getVESAModeWithProperties
180//
181// Return the VESA mode that matches the properties specified.
182// If a mode is not found, then return the "best" available mode.
183
184static unsigned short
185getVESAModeWithProperties( unsigned short width,
186 unsigned short height,
187 unsigned char bitsPerPixel,
188 unsigned short attributesSet,
189 unsigned short attributesClear,
190 VBEModeInfoBlock * outModeInfo,
191 unsigned short * vesaVersion )
192{
193 VBEInfoBlock vbeInfo;
194 unsigned short * modePtr;
195 VBEModeInfoBlock modeInfo;
196 unsigned char modeBitsPerPixel;
197 unsigned short matchedMode = modeEndOfList;
198 int err;
199
200 // Clear output mode info.
201
202 bzero( outModeInfo, sizeof(*outModeInfo) );
203
204 // Get VBE controller info containing the list of supported modes.
205
206 bzero( &vbeInfo, sizeof(vbeInfo) );
207 strcpy( (char*)&vbeInfo, "VBE2" );
208 err = getVBEInfo( &vbeInfo );
209 if ( err != errSuccess )
210 {
211 return modeEndOfList;
212 }
213
214 // Report the VESA major/minor version number.
215
216 if (vesaVersion) *vesaVersion = vbeInfo.VESAVersion;
217
218 // Loop through the mode list, and find the matching mode.
219
220 for ( modePtr = VBEDecodeFP( unsigned short *, vbeInfo.VideoModePtr );
221 *modePtr != modeEndOfList; modePtr++ )
222 {
223 // Get mode information.
224
225 bzero( &modeInfo, sizeof(modeInfo) );
226 err = getVBEModeInfo( *modePtr, &modeInfo );
227 if ( err != errSuccess )
228 {
229 continue;
230 }
231
232#if DEBUG
233 printf("Mode %x: %dx%dx%d mm:%d attr:%x\n",
234 *modePtr, modeInfo.XResolution, modeInfo.YResolution,
235 modeInfo.BitsPerPixel, modeInfo.MemoryModel,
236 modeInfo.ModeAttributes);
237#endif
238
239 // Filter out unwanted modes based on mode attributes.
240
241 if ( ( ( modeInfo.ModeAttributes & attributesSet ) != attributesSet )
242|| ( ( modeInfo.ModeAttributes & attributesClear ) != 0 ) )
243 {
244 continue;
245 }
246
247 // Pixel depth in bits.
248
249 modeBitsPerPixel = modeInfo.BitsPerPixel;
250
251 if ( ( modeBitsPerPixel == 4 ) && ( modeInfo.MemoryModel == 0 ) )
252 {
253 // Text mode, 16 colors.
254 }
255 else if ( ( modeBitsPerPixel == 8 ) && ( modeInfo.MemoryModel == 4 ) )
256 {
257 // Packed pixel, 256 colors.
258 }
259 else if ( ( ( modeBitsPerPixel == 16 ) || ( modeBitsPerPixel == 15 ) )
260 && ( modeInfo.MemoryModel == 6 )
261 && ( modeInfo.RedMaskSize == 5 )
262 && ( modeInfo.GreenMaskSize == 5 )
263 && ( modeInfo.BlueMaskSize == 5 ) )
264 {
265 // Direct color, 16 bpp (1:5:5:5).
266 modeInfo.BitsPerPixel = modeBitsPerPixel = 16;
267 }
268 else if ( ( modeBitsPerPixel == 32 )
269 && ( modeInfo.MemoryModel == 6 )
270 && ( modeInfo.RedMaskSize == 8 )
271 && ( modeInfo.GreenMaskSize == 8 )
272 && ( modeInfo.BlueMaskSize == 8 ) )
273 {
274 // Direct color, 32 bpp (8:8:8:8).
275 }
276 else
277 {
278 continue; // Not a supported mode.
279 }
280
281 // Modes larger than the specified dimensions are skipped.
282
283 if ( ( modeInfo.XResolution > width ) ||
284( modeInfo.YResolution > height ) )
285 {
286 continue;
287 }
288
289 // Perfect match, we're done looking.
290
291 if ( ( modeInfo.XResolution == width ) &&
292( modeInfo.YResolution == height ) &&
293( modeBitsPerPixel == bitsPerPixel ) )
294 {
295 matchedMode = *modePtr;
296 bcopy( &modeInfo, outModeInfo, sizeof(modeInfo) );
297 break;
298 }
299
300 // Save the next "best" mode in case a perfect match is not found.
301
302 if ( modeInfo.XResolution == outModeInfo->XResolution &&
303modeInfo.YResolution == outModeInfo->YResolution &&
304modeBitsPerPixel <= outModeInfo->BitsPerPixel )
305 {
306 continue; // Saved mode has more depth.
307 }
308 if ( modeInfo.XResolution < outModeInfo->XResolution ||
309modeInfo.YResolution < outModeInfo->YResolution ||
310modeBitsPerPixel < outModeInfo->BitsPerPixel )
311 {
312 continue; // Saved mode has more resolution.
313 }
314
315 matchedMode = *modePtr;
316 bcopy( &modeInfo, outModeInfo, sizeof(modeInfo) );
317 }
318
319 return matchedMode;
320}
321
322//==========================================================================
323// setupPalette
324
325static void setupPalette( VBEPalette * p, const unsigned char * g )
326{
327 int i;
328 unsigned char * source = (unsigned char *) g;
329
330 for (i = 0; i < 256; i++)
331 {
332 (*p)[i] = 0;
333 (*p)[i] |= ((unsigned long)((*source++) >> 2)) << 16; // Red
334 (*p)[i] |= ((unsigned long)((*source++) >> 2)) << 8; // Green
335 (*p)[i] |= ((unsigned long)((*source++) >> 2)); // Blue
336 }
337}
338
339//==========================================================================
340// Simple decompressor for boot images encoded in RLE format.
341
342char * decodeRLE( const void * rleData, int rleBlocks, int outBytes )
343{
344 char *out, *cp;
345
346 struct RLEBlock {
347 unsigned char count;
348 unsigned char value;
349 } * bp = (struct RLEBlock *) rleData;
350
351 out = cp = malloc( outBytes );
352 if ( out == NULL ) return NULL;
353
354 while ( rleBlocks-- )
355 {
356 memset( cp, bp->value, bp->count );
357 cp += bp->count;
358 bp++;
359 }
360
361 return out;
362}
363
364//==========================================================================
365// setVESAGraphicsMode
366
367int setVESAGraphicsMode( unsigned short width, unsigned short height, unsigned char bitsPerPixel, unsigned short refreshRate )
368{
369 VBEModeInfoBlock minfo;
370 unsigned short mode;
371 unsigned short vesaVersion;
372 int err = errFuncNotSupported;
373
374 do {
375 mode = getVESAModeWithProperties( width, height, bitsPerPixel,
376 maColorModeBit |
377 maModeIsSupportedBit |
378 maGraphicsModeBit |
379 maLinearFrameBufferAvailBit,
380 0,
381 &minfo, &vesaVersion );
382 if ( mode == modeEndOfList )
383 {
384 break;
385 }
386
387//
388// FIXME : generateCRTCTiming() causes crash.
389//
390
391// if ( (vesaVersion >> 8) >= 3 && refreshRate >= 60 &&
392// (gBootMode & kBootModeSafe) == 0 )
393// {
394// VBECRTCInfoBlock timing;
395//
396// // Generate CRTC timing for given refresh rate.
397//
398// generateCRTCTiming( minfo.XResolution, minfo.YResolution,
399// refreshRate, kCRTCParamRefreshRate,
400// &timing );
401//
402// // Find the actual pixel clock supported by the hardware.
403//
404// getVBEPixelClock( mode, &timing.PixelClock );
405//
406// // Re-compute CRTC timing based on actual pixel clock.
407//
408// generateCRTCTiming( minfo.XResolution, minfo.YResolution,
409// timing.PixelClock, kCRTCParamPixelClock,
410// &timing );
411//
412// // Set the video mode and use specified CRTC timing.
413//
414// err = setVBEMode( mode | kLinearFrameBufferBit |
415// kCustomRefreshRateBit, &timing );
416// }
417// else
418// {
419// // Set the mode with default refresh rate.
420//
421// err = setVBEMode( mode | kLinearFrameBufferBit, NULL );
422// }
423
424 // Set the mode with default refresh rate.
425
426 err = setVBEMode( mode | kLinearFrameBufferBit, NULL );
427
428 if ( err != errSuccess )
429 {
430 break;
431 }
432
433 // Set 8-bit color palette.
434
435 if ( minfo.BitsPerPixel == 8 )
436 {
437 VBEPalette palette;
438 setupPalette( &palette, appleClut8 );
439 if ((err = setVBEPalette(palette)) != errSuccess)
440 {
441 break;
442 }
443 }
444
445 // Is this required for buggy Video BIOS implementations?
446 // On which adapter?
447
448 if ( minfo.BytesPerScanline == 0 )
449minfo.BytesPerScanline = ( minfo.XResolution *
450 minfo.BitsPerPixel ) >> 3;
451
452 // Update KernBootStruct using info provided by the selected
453 // VESA mode.
454
455 bootArgs->Video.v_display = GRAPHICS_MODE;
456 bootArgs->Video.v_width = minfo.XResolution;
457 bootArgs->Video.v_height = minfo.YResolution;
458 bootArgs->Video.v_depth = minfo.BitsPerPixel;
459 bootArgs->Video.v_rowBytes = minfo.BytesPerScanline;
460 bootArgs->Video.v_baseAddr = VBEMakeUInt32(minfo.PhysBasePtr);
461
462 }
463 while ( 0 );
464
465 return err;
466}
467
468int
469convertImage( unsigned short width,
470 unsigned short height,
471 const unsigned char *imageData,
472 unsigned char **newImageData )
473{
474 int cnt;
475 unsigned char *img = 0;
476 unsigned short *img16;
477 unsigned long *img32;
478
479 switch ( VIDEO(depth) ) {
480case 16 :
481img16 = malloc(width * height * 2);
482if ( !img16 ) break;
483for (cnt = 0; cnt < (width * height); cnt++)
484img16[cnt] = lookUpCLUTIndex(imageData[cnt], 16);
485img = (unsigned char *)img16;
486break;
487
488case 32 :
489img32 = malloc(width * height * 4);
490if ( !img32 ) break;
491for (cnt = 0; cnt < (width * height); cnt++)
492img32[cnt] = lookUpCLUTIndex(imageData[cnt], 32);
493img = (unsigned char *)img32;
494break;
495
496default :
497img = malloc(width * height);
498bcopy(imageData, img, width * height);
499break;
500 }
501 *newImageData = img;
502 return 0;
503}
504
505
506void blendImage(uint16_t x, uint16_t y, uint16_t width, uint16_t height,
507uint8_t *data)
508{
509 uint16_t drawWidth;
510 uint8_t *vram = (uint8_t *) VIDEO(baseAddr) + VIDEO(rowBytes) * y + 4 * x;
511
512 drawWidth = MIN(width, VIDEO(width) - x);
513 height = MIN(height, VIDEO(height) - y);
514 while (height--) {
515switch (VIDEO (depth))
516{
517case 32: /* Optimized version*/
518{
519uint32_t s; uint32_t* d; // Source (img) and destination (bkgd) pixels
520uint32_t a; // Alpha
521uint32_t dstrb, dstg, srcrb, srcg, drb, dg, rb, g, tempB; // Intermediate variables
522uint16_t pos;
523
524for (pos = 0; pos < drawWidth * 4; pos += 4) {
525// Fast pseudo-vector alpha blending, adapted from: http://www.stereopsis.com/doubleblend.html
526s = *((uint32_t*) (data + pos));
527d = (uint32_t*) (vram + pos);
528
529// Flip B and R in source
530// TODO: use XCHG and inline assembly to do this in a faster, saner way
531tempB = (s & 0xFF0000); // save B
532s = (s & 0xFF00FFFF) | ((s & 0xFF) << 16); // put R in B
533s = (s & 0xFFFFFF00) | (tempB >> 16); // put B in R
534
535a = (s >> 24) + 1;
536
537dstrb = *d & 0xFF00FF; dstg = *d & 0xFF00;
538srcrb = s & 0xFF00FF; srcg = s & 0xFF00;
539
540drb = srcrb - dstrb;
541dg = srcg - dstg;
542drb *= a; dg *= a;
543drb >>= 8; dg >>= 8;
544
545rb = (drb + dstrb) & 0xFF00FF;
546g = (dg + dstg) & 0xFF00;
547
548*d = rb | g;
549}
550}
551break;
552
553default: /*Universal version*/
554{
555uint32_t s;
556uint32_t a; // Alpha
557uint32_t dr, dg, db, sr, sg, sb; // Intermediate variables
558uint16_t pos;
559int bpp = (VIDEO (depth) + 7)/8;
560
561for (pos = 0; pos < drawWidth; pos ++) {
562// Fast pseudo-vector alpha blending, adapted from: http://www.stereopsis.com/doubleblend.html
563s = *((uint32_t*) (data + 4*pos));
564
565sb = (s & 0xFF0000) >> 16;
566sg = (s & 0xFF00) >> 8;
567sr = (s & 0xFF);
568
569a = (s >> 24) + 1;
570
571switch (VIDEO (depth))
572{
573case 24:
574db = ((*(uint32_t *)(vram + bpp*pos))&0xff);
575dg = ((*(uint32_t *)(vram + bpp*pos))&0xff00)>>8;
576dr = ((*(uint32_t *)(vram + bpp*pos))&0xff0000)>>16;
577break;
578case 16://16-bit seems to be 15-bit
579/*db = ((*(uint16_t *)(vram + bpp*pos))&0x1f)<<3;
580 dg = ((*(uint16_t *)(vram + bpp*pos))&0x07e0)>>3;
581 dr = ((*(uint16_t *)(vram + bpp*pos))&0xf800)>>8;
582 break;*/
583case 15:
584db = ((*(uint16_t *)(vram + bpp*pos))&0x1f)<<3;
585dg = ((*(uint16_t *)(vram + bpp*pos))&0x03e0)>>2;
586dr = ((*(uint16_t *)(vram + bpp*pos))&0x7c00)>>7;
587break;
588default:
589return;
590}
591
592dr = (((sr - dr) * a) >> 8) + dr;
593dg = (((sg - dg) * a) >> 8) + dg;
594db = (((sb - db) * a) >> 8) + db;
595switch (VIDEO (depth))
596{
597case 24:
598*(uint32_t *)(vram + bpp*pos) = (*(uint32_t *)(vram + bpp*pos) &0xff000000)
599| (db&0xff) | ((dg&0xff)<<8) | ((dr&0xff)<<16);
600break;
601case 16:
602//*(uint16_t *)(vram + bpp*pos) = ((db&0xf8)>>3) | ((dg&0xfc)<<3) | ((dr&0xf8)<<8);
603//break;
604case 15:
605*(uint16_t *)(vram + bpp*pos) = ((db&0xf8)>>3) | ((dg&0xf8)<<2) | ((dr&0xf8)<<7);
606break;
607}
608
609}
610}
611break;
612 }
613 vram += VIDEO(rowBytes);
614 data += width * 4;
615 }
616}
617
618void drawCheckerBoard()
619{
620 uint32_t *vram = (uint32_t *) VIDEO(baseAddr);
621 uint16_t x, y;
622 uint8_t color;
623
624 for (y = 0; y < VIDEO(height); y++, vram += VIDEO(width)) {
625 for (x = 0; x < VIDEO(width); x++) {
626 color = 204 + 51 * (((x / 8) % 2) == ((y / 8) % 2));
627 vram[x] = (color << 16) | (color << 8) | color;
628 }
629 }
630}
631
632//==========================================================================
633// LookUpCLUTIndex
634
635unsigned long lookUpCLUTIndex( unsigned char index,
636 unsigned char depth )
637{
638 long result, red, green, blue;
639
640 red = appleClut8[index * 3 + 0];
641 green = appleClut8[index * 3 + 1];
642 blue = appleClut8[index * 3 + 2];
643
644 switch (depth) {
645 case 16 :
646 result = ((red & 0xF8) << 7) |
647((green & 0xF8) << 2) |
648((blue & 0xF8) >> 3);
649 result |= (result << 16);
650 break;
651
652 case 32 :
653 result = (red << 16) | (green << 8) | blue;
654 break;
655
656 default :
657 result = index | (index << 8);
658 result |= (result << 16);
659 break;
660 }
661
662 return result;
663}
664
665//==========================================================================
666// drawColorRectangle
667
668void * stosl(void * dst, long val, long len)
669{
670 asm volatile ( "rep; stosl"
671 : "=c" (len), "=D" (dst)
672 : "0" (len), "1" (dst), "a" (val)
673 : "memory" );
674
675 return dst;
676}
677
678void drawColorRectangle( unsigned short x,
679unsigned short y,
680unsigned short width,
681unsigned short height,
682unsigned char colorIndex )
683{
684 long pixelBytes;
685 long color = lookUpCLUTIndex( colorIndex, VIDEO(depth) );
686 char * vram;
687
688 pixelBytes = VIDEO(depth) / 8;
689 vram = (char *) VIDEO(baseAddr) +
690VIDEO(rowBytes) * y + pixelBytes * x;
691
692 width = MIN(width, VIDEO(width) - x);
693 height = MIN(height, VIDEO(height) - y);
694
695 while ( height-- )
696 {
697 int rem = ( pixelBytes * width ) % 4;
698 if ( rem ) bcopy( &color, vram, rem );
699 stosl( vram + rem, color, pixelBytes * width / 4 );
700 vram += VIDEO(rowBytes);
701 }
702}
703
704//==========================================================================
705// drawDataRectangle
706
707void drawDataRectangle( unsigned short x,
708 unsigned short y,
709 unsigned short width,
710 unsigned short height,
711 unsigned char * data )
712{
713 unsigned short drawWidth;
714 long pixelBytes = VIDEO(depth) / 8;
715 unsigned char * vram = (unsigned char *) VIDEO(baseAddr) +
716VIDEO(rowBytes) * y + pixelBytes * x;
717
718 drawWidth = MIN(width, VIDEO(width) - x);
719 height = MIN(height, VIDEO(height) - y);
720 while ( height-- ) {
721 bcopy( data, vram, drawWidth * pixelBytes );
722 vram += VIDEO(rowBytes);
723 data += width * pixelBytes;
724 }
725}
726
727void
728loadImageScale (void *input, int iw, int ih, int ip, void *output, int ow, int oh, int op, int or)
729{
730int x,y, off;
731int red=0x7f, green=0x7f, blue=0x7f;
732for (x=0;x<ow;x++)
733for (y=0;y<oh;y++)
734{
735off=(x*iw)/ow+((y*ih)/oh)*iw;
736switch (ip)
737{
738case 16:
739{
740uint16_t val;
741val=((uint16_t *)input)[off];
742red=(val>>7)&0xf8;
743green=(val>>2)&0xf8;
744blue=(val<<3)&0xf8;
745break;
746}
747case 32:
748{
749uint32_t val;
750val=((uint32_t *)input)[off];
751red=(val>>16)&0xff;
752green=(val>>8)&0xff;
753blue=(val)&0xff;
754break;
755}
756}
757char *ptr=(char *)output+x*(op/8)+y*or;
758switch (op)
759{
760case 16:
761*((uint16_t *)ptr) = ((red & 0xF8) << 7) |
762((green & 0xF8) << 2) |
763((blue & 0xF8) >> 3);
764break;
765case 32 :
766*((uint32_t *)ptr) = (red << 16) | (green << 8) | blue;
767break;
768}
769}
770}
771
772DECLARE_IOHIBERNATEPROGRESSALPHA
773
774void drawPreview(void *src, uint8_t * saveunder)
775{
776uint8_t * screen;
777uint32_t rowBytes, pixelShift;
778uint32_t x, y;
779int32_t blob;
780uint32_t alpha, in, color, result;
781uint8_t * out;
782void *uncomp;
783int origwidth, origheight, origbpx;
784uint32_t saveindex[kIOHibernateProgressCount] = { 0 };
785
786if (src && (uncomp=DecompressData(src, &origwidth, &origheight, &origbpx)))
787{
788if (!setVESAGraphicsMode(origwidth, origheight, origbpx, 0))
789if (initGraphicsMode () != errSuccess)
790return;
791screen = (uint8_t *) VIDEO (baseAddr);
792rowBytes = VIDEO (rowBytes);
793loadImageScale (uncomp, origwidth, origheight, origbpx, screen, VIDEO(width), VIDEO(height), VIDEO(depth), VIDEO (rowBytes));
794}
795else
796{
797if (initGraphicsMode () != errSuccess)
798return;
799screen = (uint8_t *) VIDEO (baseAddr);
800rowBytes = VIDEO (rowBytes);
801// Set the screen to 75% grey.
802 drawColorRectangle(0, 0, VIDEO(width), VIDEO(height), 0x01 /* color index */);
803}
804
805
806pixelShift = VIDEO (depth) >> 4;
807if (pixelShift < 1) return;
808
809screen += ((VIDEO (width)
810- kIOHibernateProgressCount * (kIOHibernateProgressWidth + kIOHibernateProgressSpacing)) << (pixelShift - 1))
811+ (VIDEO (height) - kIOHibernateProgressOriginY - kIOHibernateProgressHeight) * rowBytes;
812
813for (y = 0; y < kIOHibernateProgressHeight; y++)
814{
815out = screen + y * rowBytes;
816for (blob = 0; blob < kIOHibernateProgressCount; blob++)
817{
818color = blob ? kIOHibernateProgressDarkGray : kIOHibernateProgressMidGray;
819for (x = 0; x < kIOHibernateProgressWidth; x++)
820{
821alpha = gIOHibernateProgressAlpha[y][x];
822result = color;
823if (alpha)
824{
825if (0xff != alpha)
826{
827if (1 == pixelShift)
828{
829in = *((uint16_t *)out) & 0x1f;// 16
830in = (in << 3) | (in >> 2);
831}
832else
833in = *((uint32_t *)out) & 0xff;// 32
834saveunder[blob * kIOHibernateProgressSaveUnderSize + saveindex[blob]++] = in;
835result = ((255 - alpha) * in + alpha * result + 0xff) >> 8;
836}
837if (1 == pixelShift)
838{
839result >>= 3;
840*((uint16_t *)out) = (result << 10) | (result << 5) | result;// 16
841}
842else
843*((uint32_t *)out) = (result << 16) | (result << 8) | result;// 32
844}
845out += (1 << pixelShift);
846}
847out += (kIOHibernateProgressSpacing << pixelShift);
848}
849}
850}
851
852void updateProgressBar(uint8_t * saveunder, int32_t firstBlob, int32_t select)
853{
854uint8_t * screen;
855uint32_t rowBytes, pixelShift;
856uint32_t x, y;
857int32_t blob, lastBlob;
858uint32_t alpha, in, color, result;
859uint8_t * out;
860uint32_t saveindex[kIOHibernateProgressCount] = { 0 };
861
862pixelShift = VIDEO(depth) >> 4;
863if (pixelShift < 1) return;
864screen = (uint8_t *) VIDEO (baseAddr);
865rowBytes = VIDEO (rowBytes);
866
867screen += ((VIDEO (width)
868- kIOHibernateProgressCount * (kIOHibernateProgressWidth + kIOHibernateProgressSpacing)) << (pixelShift - 1))
869+ (VIDEO (height) - kIOHibernateProgressOriginY - kIOHibernateProgressHeight) * rowBytes;
870
871lastBlob = (select < kIOHibernateProgressCount) ? select : (kIOHibernateProgressCount - 1);
872
873screen += (firstBlob * (kIOHibernateProgressWidth + kIOHibernateProgressSpacing)) << pixelShift;
874
875for (y = 0; y < kIOHibernateProgressHeight; y++)
876{
877out = screen + y * rowBytes;
878for (blob = firstBlob; blob <= lastBlob; blob++)
879{
880color = (blob < select) ? kIOHibernateProgressLightGray : kIOHibernateProgressMidGray;
881for (x = 0; x < kIOHibernateProgressWidth; x++)
882{
883alpha = gIOHibernateProgressAlpha[y][x];
884result = color;
885if (alpha)
886{
887if (0xff != alpha)
888{
889in = saveunder[blob * kIOHibernateProgressSaveUnderSize + saveindex[blob]++];
890result = ((255 - alpha) * in + alpha * result + 0xff) / 255;
891}
892if (1 == pixelShift)
893{
894result >>= 3;
895*((uint16_t *)out) = (result << 10) | (result << 5) | result;// 16
896}
897else
898*((uint32_t *)out) = (result << 16) | (result << 8) | result;// 32
899}
900out += (1 << pixelShift);
901}
902out += (kIOHibernateProgressSpacing << pixelShift);
903}
904}
905}
906
907
908//==========================================================================
909// setVESATextMode
910
911static int
912setVESATextMode( unsigned short cols,
913unsigned short rows,
914unsigned char bitsPerPixel )
915{
916 VBEModeInfoBlock minfo;
917 unsigned short mode = modeEndOfList;
918
919 if ( (cols != 80) || (rows != 25) ) // not 80x25 mode
920 {
921 mode = getVESAModeWithProperties( cols, rows, bitsPerPixel,
922 maColorModeBit |
923 maModeIsSupportedBit,
924 maGraphicsModeBit,
925 &minfo, NULL );
926 }
927
928 if ( ( mode == modeEndOfList ) || ( setVBEMode(mode, NULL) != errSuccess ) )
929 {
930 video_mode( 2 ); // VGA BIOS, 80x25 text mode.
931 minfo.XResolution = 80;
932 minfo.YResolution = 25;
933 }
934
935 // Update KernBootStruct using info provided by the selected
936 // VESA mode.
937
938 bootArgs->Video.v_display = VGA_TEXT_MODE;
939 bootArgs->Video.v_baseAddr = 0xb8000;
940 bootArgs->Video.v_width = minfo.XResolution;
941 bootArgs->Video.v_height = minfo.YResolution;
942 bootArgs->Video.v_depth = 8;
943 bootArgs->Video.v_rowBytes = 0x8000;
944
945 return errSuccess; // always return success
946}
947
948//==========================================================================
949// getNumberArrayFromProperty
950
951int
952getNumberArrayFromProperty( const char * propKey,
953 unsigned long numbers[],
954 unsigned long maxArrayCount )
955{
956 char * propStr;
957 unsigned long count = 0;
958
959 propStr = newStringForKey( (char *) propKey , &bootInfo->bootConfig );
960 if ( propStr )
961 {
962 char * delimiter = propStr;
963 char * p = propStr;
964
965 while ( count < maxArrayCount && *p != '\0' )
966 {
967 unsigned long val = strtoul( p, &delimiter, 10 );
968 if ( p != delimiter )
969 {
970 numbers[count++] = val;
971 p = delimiter;
972 }
973 while ( ( *p != '\0' ) && !isdigit(*p) )
974 p++;
975 }
976
977 free( propStr );
978 }
979
980 return count;
981}
982
983int initGraphicsMode ()
984{
985unsigned long params[4];
986int count;
987
988params[3] = 0;
989count = getNumberArrayFromProperty( kGraphicsModeKey, params, 4 );
990
991// Try to find a resolution if "Graphics Mode" setting is not available.
992if ( count < 3 )
993{
994params[0] = DEFAULT_SCREEN_WIDTH;
995params[1] = DEFAULT_SCREEN_HEIGHT;
996params[2] = 32;
997}
998
999// Map from pixel format to bits per pixel.
1000
1001if ( params[2] == 256 ) params[2] = 8;
1002if ( params[2] == 555 ) params[2] = 16;
1003if ( params[2] == 888 ) params[2] = 32;
1004
1005return setVESAGraphicsMode( params[0], params[1], params[2], params[3] );
1006}
1007
1008//==========================================================================
1009// setVideoMode
1010//
1011// Set the video mode to VGA_TEXT_MODE or GRAPHICS_MODE.
1012
1013void
1014setVideoMode( int mode, int drawgraphics)
1015{
1016 unsigned long params[4];
1017 int count;
1018 int err = errSuccess;
1019
1020 if ( mode == GRAPHICS_MODE )
1021 {
1022 if ( (err=initGraphicsMode ()) == errSuccess ) {
1023if (gVerboseMode) {
1024// Tell the kernel to use text mode on a linear frame buffer display
1025bootArgs->Video.v_display = FB_TEXT_MODE;
1026} else {
1027bootArgs->Video.v_display = GRAPHICS_MODE;
1028}
1029}
1030 }
1031
1032 if ( (mode == VGA_TEXT_MODE) || (err != errSuccess) )
1033 {
1034 count = getNumberArrayFromProperty( kTextModeKey, params, 2 );
1035 if ( count < 2 )
1036 {
1037 params[0] = 80; // Default text mode is 80x25.
1038 params[1] = 25;
1039 }
1040
1041setVESATextMode( params[0], params[1], 4 );
1042 bootArgs->Video.v_display = VGA_TEXT_MODE;
1043 }
1044
1045 currentIndicator = 0;
1046}
1047
1048void getGraphicModeParams(unsigned long params[]) {
1049
1050params[3] = 0;
1051
1052VBEModeInfoBlock minfo;
1053
1054 unsigned short vesaVersion;
1055 unsigned short mode = modeEndOfList;
1056
1057getNumberArrayFromProperty( kGraphicsModeKey, params, 4);
1058
1059mode = getVESAModeWithProperties( params[0], params[1], params[2],
1060 maColorModeBit |
1061 maModeIsSupportedBit |
1062 maGraphicsModeBit |
1063 maLinearFrameBufferAvailBit,
1064 0,
1065 &minfo, &vesaVersion );
1066
1067params[0] = minfo.XResolution;
1068params[1] = minfo.YResolution;
1069params[2] = 32;
1070}
1071
1072//==========================================================================
1073// Return the current video mode, VGA_TEXT_MODE or GRAPHICS_MODE.
1074
1075int getVideoMode(void)
1076{
1077 return bootArgs->Video.v_display;
1078}
1079
1080//==========================================================================
1081// Display and clear the activity indicator.
1082
1083static char indicator[] = {'-', '\\', '|', '/', '-', '\\', '|', '/', '\0'};
1084
1085// To prevent a ridiculously fast-spinning indicator,
1086// ensure a minimum of 1/9 sec between animation frames.
1087#define MIN_TICKS 2
1088
1089void
1090spinActivityIndicator(int sectors)
1091{
1092 static unsigned long lastTickTime = 0, currentTickTime;
1093
1094if (previewTotalSectors && previewSaveunder)
1095{
1096int blob, lastBlob;
1097
1098lastBlob = (previewLoadedSectors * kIOHibernateProgressCount) / previewTotalSectors;
1099previewLoadedSectors+=sectors;
1100blob = (previewLoadedSectors * kIOHibernateProgressCount) / previewTotalSectors;
1101
1102if (blob!=lastBlob)
1103updateProgressBar (previewSaveunder, lastBlob, blob);
1104return;
1105}
1106
1107currentTickTime = time18(); // late binding
1108if (currentTickTime < lastTickTime + MIN_TICKS)
1109{
1110return;
1111}
1112else
1113{
1114lastTickTime = currentTickTime;
1115}
1116
1117if (getVideoMode() == VGA_TEXT_MODE)
1118{
1119if (currentIndicator >= sizeof(indicator))
1120{
1121currentIndicator = 0;
1122}
1123putc(indicator[currentIndicator++]);
1124putc('\b');
1125}
1126}
1127
1128void
1129clearActivityIndicator( void )
1130{
1131 if ( getVideoMode() == VGA_TEXT_MODE )
1132 {
1133putc(' ');
1134putc('\b');
1135 }
1136}
1137
1138

Archive Download this file

Revision: 533