Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/i386/modules/HibernateEnabler/graphic_utils.c

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

Archive Download this file

Revision: 1899