Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/i386/modules/GUI/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 "appleClut8.h"
10#include "vbe.h"
11#include "gui.h"
12#include "platform.h"
13
14#define VIDEO(x) (((boot_args*)getBootArgs())->Video.v_ ## x)
15
16#define MIN(x, y) ((x) < (y) ? (x) : (y))
17static unsigned long lookUpCLUTIndex( unsigned char index,
18 unsigned char depth );
19
20static int
21setVESATextMode( unsigned short cols,
22unsigned short rows,
23unsigned char bitsPerPixel );
24
25static void setupPalette( VBEPalette * p, const unsigned char * g );
26static unsigned long lookUpCLUTIndex( unsigned char index,
27 unsigned char depth );
28static unsigned short
29getVESAModeWithProperties( unsigned short width,
30 unsigned short height,
31 unsigned char bitsPerPixel,
32 unsigned short attributesSet,
33 unsigned short attributesClear,
34 VBEModeInfoBlock * outModeInfo,
35 unsigned short * vesaVersion );
36//==========================================================================
37// LookUpCLUTIndex
38
39static unsigned long lookUpCLUTIndex( unsigned char index,
40 unsigned char depth )
41{
42 long result, red, green, blue;
43
44 red = appleClut8[index * 3 + 0];
45 green = appleClut8[index * 3 + 1];
46 blue = appleClut8[index * 3 + 2];
47
48 switch (depth) {
49 case 16 :
50 result = ((red & 0xF8) << 7) |
51((green & 0xF8) << 2) |
52((blue & 0xF8) >> 3);
53 result |= (result << 16);
54 break;
55
56 case 32 :
57 result = (red << 16) | (green << 8) | blue;
58 break;
59
60 default :
61 result = index | (index << 8);
62 result |= (result << 16);
63 break;
64 }
65
66 return result;
67}
68
69int
70convertImage( unsigned short width,
71 unsigned short height,
72 const unsigned char *imageData,
73 unsigned char **newImageData )
74{
75 int cnt;
76 unsigned char *img;
77 unsigned short *img16;
78 unsigned long *img32;
79
80 switch ( VIDEO(depth) ) {
81case 16 :
82 {
83img16 = malloc(width * height * 2);
84if ( !img16 ) return 1;
85for (cnt = 0; cnt < (width * height); cnt++)
86img16[cnt] = lookUpCLUTIndex(imageData[cnt], 16);
87img = (unsigned char *)img16;
88 *newImageData = img;
89break;
90 }
91case 32 :
92 {
93img32 = malloc(width * height * 4);
94if ( !img32 ) return 1;
95for (cnt = 0; cnt < (width * height); cnt++)
96img32[cnt] = lookUpCLUTIndex(imageData[cnt], 32);
97img = (unsigned char *)img32;
98 *newImageData = img;
99break;
100 }
101default :
102 {
103img = malloc(width * height);
104 if ( !img ) return 1;
105bcopy(imageData, img, width * height);
106 *newImageData = img;
107break;
108 }
109 }
110 return 0;
111}
112
113//==========================================================================
114// drawDataRectangle
115
116void drawDataRectangle( unsigned short x,
117 unsigned short y,
118 unsigned short width,
119 unsigned short height,
120 unsigned char * data )
121{
122 unsigned short drawWidth;
123 long pixelBytes = VIDEO(depth) / 8;
124 unsigned char * vram = (unsigned char *) VIDEO(baseAddr) +
125VIDEO(rowBytes) * y + pixelBytes * x;
126
127 drawWidth = MIN(width, VIDEO(width) - x);
128 height = MIN(height, VIDEO(height) - y);
129 while ( height-- ) {
130 bcopy( data, vram, drawWidth * pixelBytes );
131 vram += VIDEO(rowBytes);
132 data += width * pixelBytes;
133 }
134}
135
136//==========================================================================
137//
138void
139printVBEModeInfo(void)
140{
141 VBEInfoBlock vbeInfo;
142 unsigned short * modePtr;
143 VBEModeInfoBlock modeInfo;
144 int err;
145 int line;
146
147 //bzero( &vbeInfo, sizeof(vbeInfo) );
148 bzero( &vbeInfo, sizeof(VBEInfoBlock) );
149
150 strcpy( (char*)&vbeInfo, "VBE2" );
151 err = getVBEInfo( &vbeInfo );
152 if ( err != errSuccess )
153 return;
154
155 line = 0;
156
157 // Activate and clear page 1
158 setActiveDisplayPage(1);
159 clearScreenRows(0, 24);
160 setCursorPosition( 0, 0, 1 );
161
162printf("Video modes supported:\n", VBEDecodeFP(const char *, vbeInfo.OEMStringPtr));
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 printf("Mode %x: %dx%dx%d mm:%d attr:%x\n",
181 *modePtr, modeInfo.XResolution, modeInfo.YResolution,
182 modeInfo.BitsPerPixel, modeInfo.MemoryModel,
183 modeInfo.ModeAttributes);
184
185 if (line++ >= 20) {
186 pause();
187 line = 0;
188 clearScreenRows(0, 24);
189 setCursorPosition( 0, 0, 1 );
190 }
191 }
192 if (line != 0) {
193 pause();
194 }
195 setActiveDisplayPage(0);
196}
197
198
199
200char *getVBEModeInfoString(void)
201{
202VBEInfoBlock vbeInfo;
203 unsigned short * modePtr;
204 VBEModeInfoBlock modeInfo;
205 int err;
206
207 //bzero( &vbeInfo, sizeof(vbeInfo) );
208 bzero( &vbeInfo, sizeof(VBEInfoBlock) );
209
210 strcpy( (char*)&vbeInfo, "VBE2" );
211 err = getVBEInfo( &vbeInfo );
212 if ( err != errSuccess )
213 return 0;
214
215char *buff=malloc(sizeof(char)*3072);
216if(!buff) return 0;
217
218// Loop through the mode list, and find the matching mode.
219 for ( modePtr = VBEDecodeFP( unsigned short *, vbeInfo.VideoModePtr );
220 *modePtr != modeEndOfList; modePtr++ )
221 {
222 // Get mode information.
223
224 //bzero( &modeInfo, sizeof(modeInfo) );
225 bzero( &modeInfo, sizeof(VBEModeInfoBlock) );
226
227 err = getVBEModeInfo( *modePtr, &modeInfo );
228 if ( err != errSuccess )
229 {
230 continue;
231 }
232
233 sprintf(buff+strlen(buff), "Mode %x: %dx%dx%d mm:%d attr:%x\n",
234*modePtr, modeInfo.XResolution, modeInfo.YResolution,
235modeInfo.BitsPerPixel, modeInfo.MemoryModel,
236modeInfo.ModeAttributes);
237
238 }
239return buff;
240}
241
242
243void blendImage(uint16_t x, uint16_t y, uint16_t width, uint16_t height,
244uint8_t *data)
245{
246 uint16_t drawWidth;
247 uint8_t *vram = (uint8_t *) VIDEO(baseAddr) + VIDEO(rowBytes) * y + 4 * x;
248
249 drawWidth = MIN(width, VIDEO(width) - x);
250 height = MIN(height, VIDEO(height) - y);
251 while (height--) {
252switch (VIDEO (depth))
253{
254case 32: /* Optimized version*/
255{
256uint32_t s; uint32_t* d; // Source (img) and destination (bkgd) pixels
257uint32_t a; // Alpha
258uint32_t dstrb, dstg, srcrb, srcg, drb, dg, rb, g, tempB; // Intermediate variables
259uint16_t pos;
260
261for (pos = 0; pos < drawWidth * 4; pos += 4) {
262// Fast pseudo-vector alpha blending, adapted from: http://www.stereopsis.com/doubleblend.html
263s = *((uint32_t*) (data + pos));
264d = (uint32_t*) (vram + pos);
265
266// Flip B and R in source
267// TODO: use XCHG and inline assembly to do this in a faster, saner way
268tempB = (s & 0xFF0000); // save B
269s = (s & 0xFF00FFFF) | ((s & 0xFF) << 16); // put R in B
270s = (s & 0xFFFFFF00) | (tempB >> 16); // put B in R
271
272a = (s >> 24) + 1;
273
274dstrb = *d & 0xFF00FF; dstg = *d & 0xFF00;
275srcrb = s & 0xFF00FF; srcg = s & 0xFF00;
276
277drb = srcrb - dstrb;
278dg = srcg - dstg;
279drb *= a; dg *= a;
280drb >>= 8; dg >>= 8;
281
282rb = (drb + dstrb) & 0xFF00FF;
283g = (dg + dstg) & 0xFF00;
284
285*d = rb | g;
286}
287}
288break;
289
290default: /*Universal version*/
291{
292uint32_t s;
293uint32_t a; // Alpha
294uint32_t dr, dg, db, sr, sg, sb; // Intermediate variables
295uint16_t pos;
296int bpp = (VIDEO (depth) + 7)/8;
297
298for (pos = 0; pos < drawWidth; pos ++) {
299// Fast pseudo-vector alpha blending, adapted from: http://www.stereopsis.com/doubleblend.html
300s = *((uint32_t*) (data + 4*pos));
301
302sb = (s & 0xFF0000) >> 16;
303sg = (s & 0xFF00) >> 8;
304sr = (s & 0xFF);
305
306a = (s >> 24) + 1;
307
308switch (VIDEO (depth))
309{
310case 24:
311db = ((*(uint32_t *)(vram + bpp*pos))&0xff);
312dg = ((*(uint32_t *)(vram + bpp*pos))&0xff00)>>8;
313dr = ((*(uint32_t *)(vram + bpp*pos))&0xff0000)>>16;
314break;
315case 16://16-bit seems to be 15-bit
316/*db = ((*(uint16_t *)(vram + bpp*pos))&0x1f)<<3;
317 dg = ((*(uint16_t *)(vram + bpp*pos))&0x07e0)>>3;
318 dr = ((*(uint16_t *)(vram + bpp*pos))&0xf800)>>8;
319 break;*/
320case 15:
321db = ((*(uint16_t *)(vram + bpp*pos))&0x1f)<<3;
322dg = ((*(uint16_t *)(vram + bpp*pos))&0x03e0)>>2;
323dr = ((*(uint16_t *)(vram + bpp*pos))&0x7c00)>>7;
324break;
325default:
326return;
327}
328
329dr = (((sr - dr) * a) >> 8) + dr;
330dg = (((sg - dg) * a) >> 8) + dg;
331db = (((sb - db) * a) >> 8) + db;
332switch (VIDEO (depth))
333{
334case 24:
335*(uint32_t *)(vram + bpp*pos) = (*(uint32_t *)(vram + bpp*pos) &0xff000000)
336| (db&0xff) | ((dg&0xff)<<8) | ((dr&0xff)<<16);
337break;
338case 16:
339//*(uint16_t *)(vram + bpp*pos) = ((db&0xf8)>>3) | ((dg&0xfc)<<3) | ((dr&0xf8)<<8);
340//break;
341case 15:
342*(uint16_t *)(vram + bpp*pos) = ((db&0xf8)>>3) | ((dg&0xf8)<<2) | ((dr&0xf8)<<7);
343break;
344default:
345break;
346}
347
348}
349}
350break;
351 }
352 vram += VIDEO(rowBytes);
353 data += width * 4;
354 }
355}
356
357void drawCheckerBoard(void)
358{
359 uint32_t *vram = (uint32_t *) VIDEO(baseAddr);
360 uint16_t x, y;
361 uint8_t color;
362
363 for (y = 0; y < VIDEO(height); y++, vram += VIDEO(width)) {
364 for (x = 0; x < VIDEO(width); x++) {
365 color = 204 + 51 * (((x / 8) % 2) == ((y / 8) % 2));
366 vram[x] = (color << 16) | (color << 8) | color;
367 }
368 }
369}
370
371//==========================================================================
372// getNumberArrayFromProperty
373
374int
375getNumberArrayFromProperty( const char * propKey,
376 unsigned long numbers[],
377 unsigned long maxArrayCount )
378{
379 char * propStr;
380 unsigned long count = 0;
381
382 propStr = newStringForKey( (char *) propKey , DEFAULT_BOOT_CONFIG );
383 if ( propStr )
384 {
385 char * delimiter = propStr;
386 char * p = propStr;
387
388 while ( count < maxArrayCount && *p != '\0' )
389 {
390 unsigned long val = strtoul( p, &delimiter, 10 );
391 if ( p != delimiter )
392 {
393 numbers[count++] = val;
394 p = delimiter;
395 }
396 while ( ( *p != '\0' ) && !isdigit(*p) )
397 p++;
398 }
399
400 free( propStr );
401 }
402
403 return count;
404}
405
406//==========================================================================
407// Simple decompressor for boot images encoded in RLE format.
408
409char * decodeRLE( const void * rleData, int rleBlocks, int outBytes )
410{
411 char *out, *cp;
412
413 struct RLEBlock {
414 unsigned char count;
415 unsigned char value;
416 } * bp = (struct RLEBlock *) rleData;
417
418 out = cp = malloc( outBytes );
419 if ( out == NULL ) return NULL;
420
421 while ( rleBlocks-- )
422 {
423 memset( cp, bp->value, bp->count );
424 cp += bp->count;
425 bp++;
426 }
427
428 return out;
429}
430
431static void * stosl(void * dst, long val, long len)
432{
433 asm volatile ( "rep; stosl"
434 : "=c" (len), "=D" (dst)
435 : "0" (len), "1" (dst), "a" (val)
436 : "memory" );
437
438 return dst;
439}
440
441void drawColorRectangle( unsigned short x,
442 unsigned short y,
443 unsigned short width,
444 unsigned short height,
445 unsigned char colorIndex )
446{
447 long pixelBytes;
448 long color = lookUpCLUTIndex( colorIndex, VIDEO(depth) );
449 char * vram;
450
451 pixelBytes = VIDEO(depth) / 8;
452 vram = (char *) VIDEO(baseAddr) +
453VIDEO(rowBytes) * y + pixelBytes * x;
454
455 width = MIN(width, VIDEO(width) - x);
456 height = MIN(height, VIDEO(height) - y);
457
458 while ( height-- )
459 {
460 int rem = ( pixelBytes * width ) % 4;
461 if ( rem ) bcopy( &color, vram, rem );
462 stosl( vram + rem, color, pixelBytes * width / 4 );
463 vram += VIDEO(rowBytes);
464 }
465}
466
467
468
469//==========================================================================
470// getVESAModeWithProperties
471//
472// Return the VESA mode that matches the properties specified.
473// If a mode is not found, then return the "best" available mode.
474
475static unsigned short
476getVESAModeWithProperties( unsigned short width,
477 unsigned short height,
478 unsigned char bitsPerPixel,
479 unsigned short attributesSet,
480 unsigned short attributesClear,
481 VBEModeInfoBlock * outModeInfo,
482 unsigned short * vesaVersion )
483{
484 VBEInfoBlock vbeInfo;
485 unsigned short * modePtr;
486 VBEModeInfoBlock modeInfo;
487 unsigned char modeBitsPerPixel;
488 unsigned short matchedMode = modeEndOfList;
489 int err;
490
491 // Clear output mode info.
492
493 //bzero( outModeInfo, sizeof(*outModeInfo) );
494bzero( outModeInfo, sizeof(VBEModeInfoBlock) );
495
496 // Get VBE controller info containing the list of supported modes.
497
498 //bzero( &vbeInfo, sizeof(vbeInfo) );
499 bzero( &vbeInfo, sizeof(VBEInfoBlock) );
500
501 strcpy( (char*)&vbeInfo, "VBE2" );
502 err = getVBEInfo( &vbeInfo );
503 if ( err != errSuccess )
504 {
505 return modeEndOfList;
506 }
507
508 // Report the VESA major/minor version number.
509
510 if (vesaVersion) *vesaVersion = vbeInfo.VESAVersion;
511
512 // Loop through the mode list, and find the matching mode.
513
514 for ( modePtr = VBEDecodeFP( unsigned short *, vbeInfo.VideoModePtr );
515 *modePtr != modeEndOfList; modePtr++ )
516 {
517 // Get mode information.
518
519 //bzero( &modeInfo, sizeof(modeInfo) );
520 bzero( &modeInfo, sizeof(VBEModeInfoBlock) );
521
522 err = getVBEModeInfo( *modePtr, &modeInfo );
523 if ( err != errSuccess )
524 {
525 continue;
526 }
527
528#if DEBUG
529 printf("Mode %x: %dx%dx%d mm:%d attr:%x\n",
530 *modePtr, modeInfo.XResolution, modeInfo.YResolution,
531 modeInfo.BitsPerPixel, modeInfo.MemoryModel,
532 modeInfo.ModeAttributes);
533#endif
534
535 // Filter out unwanted modes based on mode attributes.
536
537 if ( ( ( modeInfo.ModeAttributes & attributesSet ) != attributesSet )
538|| ( ( modeInfo.ModeAttributes & attributesClear ) != 0 ) )
539 {
540 continue;
541 }
542
543 // Pixel depth in bits.
544
545 modeBitsPerPixel = modeInfo.BitsPerPixel;
546
547 if ( ( modeBitsPerPixel == 4 ) && ( modeInfo.MemoryModel == 0 ) )
548 {
549 // Text mode, 16 colors.
550 }
551 else if ( ( modeBitsPerPixel == 8 ) && ( modeInfo.MemoryModel == 4 ) )
552 {
553 // Packed pixel, 256 colors.
554 }
555 else if ( ( ( modeBitsPerPixel == 16 ) || ( modeBitsPerPixel == 15 ) )
556 && ( modeInfo.MemoryModel == 6 )
557 && ( modeInfo.RedMaskSize == 5 )
558 && ( modeInfo.GreenMaskSize == 5 )
559 && ( modeInfo.BlueMaskSize == 5 ) )
560 {
561 // Direct color, 16 bpp (1:5:5:5).
562 modeInfo.BitsPerPixel = modeBitsPerPixel = 16;
563 }
564 else if ( ( modeBitsPerPixel == 32 )
565 && ( modeInfo.MemoryModel == 6 )
566 && ( modeInfo.RedMaskSize == 8 )
567 && ( modeInfo.GreenMaskSize == 8 )
568 && ( modeInfo.BlueMaskSize == 8 ) )
569 {
570 // Direct color, 32 bpp (8:8:8:8).
571 }
572 else
573 {
574 continue; // Not a supported mode.
575 }
576
577 // Modes larger than the specified dimensions are skipped.
578
579 if ( ( modeInfo.XResolution > width ) ||
580( modeInfo.YResolution > height ) )
581 {
582 continue;
583 }
584
585 // Perfect match, we're done looking.
586
587 if ( ( modeInfo.XResolution == width ) &&
588( modeInfo.YResolution == height ) &&
589( modeBitsPerPixel == bitsPerPixel ) )
590 {
591 matchedMode = *modePtr;
592 //bcopy( &modeInfo, outModeInfo, sizeof(modeInfo) );
593 bcopy( &modeInfo, outModeInfo, sizeof(VBEModeInfoBlock) );
594
595 break;
596 }
597
598 // Save the next "best" mode in case a perfect match is not found.
599
600 if ( modeInfo.XResolution == outModeInfo->XResolution &&
601modeInfo.YResolution == outModeInfo->YResolution &&
602modeBitsPerPixel <= outModeInfo->BitsPerPixel )
603 {
604 continue; // Saved mode has more depth.
605 }
606 if ( modeInfo.XResolution < outModeInfo->XResolution ||
607modeInfo.YResolution < outModeInfo->YResolution ||
608modeBitsPerPixel < outModeInfo->BitsPerPixel )
609 {
610 continue; // Saved mode has more resolution.
611 }
612
613 matchedMode = *modePtr;
614 bcopy( &modeInfo, outModeInfo, sizeof(VBEModeInfoBlock) );
615
616 }
617
618 return matchedMode;
619}
620
621//==========================================================================
622// setVESATextMode
623
624static int
625setVESATextMode( unsigned short cols,
626unsigned short rows,
627unsigned char bitsPerPixel )
628{
629 VBEModeInfoBlock minfo;
630minfo.XResolution = 0;
631 minfo.YResolution = 0;
632 unsigned short mode = modeEndOfList;
633
634 minfo.XResolution = 0;
635 minfo.YResolution = 0;
636
637 if ( (cols != 80) || (rows != 25) ) // not 80x25 mode
638 {
639 mode = getVESAModeWithProperties( cols, rows, bitsPerPixel,
640 maColorModeBit |
641 maModeIsSupportedBit,
642 maGraphicsModeBit,
643 &minfo, NULL );
644 }
645
646 if ( ( mode == modeEndOfList ) || ( setVBEMode(mode, NULL) != errSuccess ) )
647 {
648 video_mode( 2 ); // VGA BIOS, 80x25 text mode.
649 minfo.XResolution = 80;
650 minfo.YResolution = 25;
651 }
652
653 // Update KernBootStruct using info provided by the selected
654 // VESA mode.
655
656 Boot_VideoVideo;/* Video Information */
657
658
659 Video.v_display = VGA_TEXT_MODE;
660 Video.v_width = 0xb8000;
661 Video.v_height = minfo.XResolution;
662 Video.v_depth = minfo.YResolution;
663 Video.v_rowBytes = 8;
664 Video.v_baseAddr = 0x8000;
665
666 setBootArgsVideoStruct(&Video);
667
668 return errSuccess; // always return success
669}
670
671//==========================================================================
672// setVideoMode
673//
674// Set the video mode to VGA_TEXT_MODE or GRAPHICS_MODE.
675
676void
677setVideoMode( int mode)
678{
679 unsigned long params[4];
680 int count;
681 int err = errSuccess;
682
683 if ( mode == GRAPHICS_MODE )
684 {
685 if ( (err=GUI_initGraphicsMode ()) == errSuccess ) {
686if (get_env(envgVerboseMode)) {
687// Tell the kernel to use text mode on a linear frame buffer display
688 setBootArgsVideoMode(FB_TEXT_MODE);
689
690} else {
691 setBootArgsVideoMode(GRAPHICS_MODE);
692
693}
694}
695 }
696
697 if ( (mode == VGA_TEXT_MODE) || (err != errSuccess) )
698 {
699 count = getNumberArrayFromProperty( kTextModeKey, params, 2 );
700 if ( count < 2 )
701 {
702 params[0] = 80; // Default text mode is 80x25.
703 params[1] = 25;
704 }
705
706setVESATextMode( params[0], params[1], 4 );
707 setBootArgsVideoMode(VGA_TEXT_MODE);
708 }
709
710}
711
712//==========================================================================
713// setupPalette
714
715static void setupPalette( VBEPalette * p, const unsigned char * g )
716{
717 int i;
718 unsigned char * source = (unsigned char *) g;
719
720 for (i = 0; i < 256; i++)
721 {
722 (*p)[i] = 0;
723 (*p)[i] |= ((unsigned long)((*source++) >> 2)) << 16; // Red
724 (*p)[i] |= ((unsigned long)((*source++) >> 2)) << 8; // Green
725 (*p)[i] |= ((unsigned long)((*source++) >> 2)); // Blue
726
727 }
728}
729
730
731//==========================================================================
732// setVESAGraphicsMode
733
734int setVESAGraphicsMode( unsigned short width, unsigned short height, unsigned char bitsPerPixel)
735{
736 VBEModeInfoBlock minfo;
737 unsigned short mode;
738 unsigned short vesaVersion;
739 int err = errFuncNotSupported;
740
741 do {
742 mode = getVESAModeWithProperties( width, height, bitsPerPixel,
743 maColorModeBit |
744 maModeIsSupportedBit |
745 maGraphicsModeBit |
746 maLinearFrameBufferAvailBit,
747 0,
748 &minfo, &vesaVersion );
749 if ( mode == modeEndOfList )
750 {
751 break;
752 }
753#if UNUSED
754//
755// FIXME : generateCRTCTiming() causes crash.
756//
757
758// if ( (vesaVersion >> 8) >= 3 && refreshRate >= 60 &&
759// (gBootMode & kBootModeSafe) == 0 )
760// {
761// VBECRTCInfoBlock timing;
762//
763// // Generate CRTC timing for given refresh rate.
764//
765// generateCRTCTiming( minfo.XResolution, minfo.YResolution,
766// refreshRate, kCRTCParamRefreshRate,
767// &timing );
768//
769// // Find the actual pixel clock supported by the hardware.
770//
771// getVBEPixelClock( mode, &timing.PixelClock );
772//
773// // Re-compute CRTC timing based on actual pixel clock.
774//
775// generateCRTCTiming( minfo.XResolution, minfo.YResolution,
776// timing.PixelClock, kCRTCParamPixelClock,
777// &timing );
778//
779// // Set the video mode and use specified CRTC timing.
780//
781// err = setVBEMode( mode | kLinearFrameBufferBit |
782// kCustomRefreshRateBit, &timing );
783// }
784// else
785// {
786// // Set the mode with default refresh rate.
787//
788// err = setVBEMode( mode | kLinearFrameBufferBit, NULL );
789// }
790#endif
791 // Set the mode with default refresh rate.
792
793 err = setVBEMode( mode | kLinearFrameBufferBit, NULL );
794
795 if ( err != errSuccess )
796 {
797 break;
798 }
799
800 // Set 8-bit color palette.
801
802 if ( minfo.BitsPerPixel == 8 )
803 {
804 VBEPalette palette;
805 setupPalette( &palette, appleClut8 );
806 if ((err = setVBEPalette(palette)) != errSuccess)
807 {
808 break;
809 }
810 }
811
812 // Is this required for buggy Video BIOS implementations?
813 // On which adapter?
814
815 if ( minfo.BytesPerScanline == 0 )
816minfo.BytesPerScanline = ( minfo.XResolution *
817 minfo.BitsPerPixel ) >> 3;
818
819 // Update KernBootStruct using info provided by the selected
820 // VESA mode.
821
822 Boot_VideoVideo;/* Video Information */
823
824
825 Video.v_display = GRAPHICS_MODE;
826 Video.v_width = minfo.XResolution;
827 Video.v_height = minfo.YResolution;
828 Video.v_depth = minfo.BitsPerPixel;
829 Video.v_rowBytes = minfo.BytesPerScanline;
830 Video.v_baseAddr = VBEMakeUInt32(minfo.PhysBasePtr);
831
832
833setBootArgsVideoStruct(&Video);
834
835 }
836 while ( 0 );
837
838 return err;
839}
840
841void getGraphicModeParams(unsigned long params[]) {
842
843params[3] = 0;
844
845VBEModeInfoBlock minfo;
846
847 unsigned short vesaVersion;
848 //unsigned short mode = modeEndOfList;
849
850getNumberArrayFromProperty( kGraphicsModeKey, params, 4);
851
852/* mode = */getVESAModeWithProperties( params[0], params[1], params[2],
853 maColorModeBit |
854 maModeIsSupportedBit |
855 maGraphicsModeBit |
856 maLinearFrameBufferAvailBit,
857 0,
858 &minfo, &vesaVersion );
859
860params[0] = minfo.XResolution;
861params[1] = minfo.YResolution;
862params[2] = 32;
863}
864
865
866//==========================================================================
867// getVBEInfoString
868
869char *getVBEInfoString(void)
870{
871VBEInfoBlock vbeInfo;
872int err, small;
873char *buff = malloc(sizeof(char)*256);
874if(!buff) return 0;
875
876//bzero( &vbeInfo, sizeof(vbeInfo) );
877 bzero( &vbeInfo, sizeof(VBEInfoBlock) );
878
879strcpy( (char*)&vbeInfo, "VBE2" );
880err = getVBEInfo( &vbeInfo );
881if (err != errSuccess)
882goto error;
883
884if ( strncmp( (char *)vbeInfo.VESASignature, "VESA", 4 ) )
885goto error;
886
887small = (vbeInfo.TotalMemory < 16);
888
889sprintf(buff, "VESA v%d.%d %d%s (%s)\n",
890vbeInfo.VESAVersion >> 8,
891vbeInfo.VESAVersion & 0xf,
892small ? (vbeInfo.TotalMemory * 64) : (vbeInfo.TotalMemory / 16),
893small ? "KB" : "MB",
894VBEDecodeFP(const char *, vbeInfo.OEMStringPtr) );
895
896return buff;
897error:
898 free(buff);
899 return 0;
900}
901
902void blend( const pixmap_t *blendThis, // Source image
903 pixmap_t *blendInto, // Dest image
904 const position_t position) // Where to place the source image
905{
906 uint16_t sx, sy, dx, dy;
907 uint32_t dstrb, dstag, srcrb, srcag, drb, dag, rb, ag, alpha;
908
909uint16_t width = (blendThis->width + position.x < blendInto->width) ? blendThis->width: blendInto->width-position.x;
910uint16_t height = (blendThis->height + position.y < blendInto->height) ? blendThis->height: blendInto->height-position.y;
911
912for (dy = position.y, sy = 0; sy < height; dy++, sy++)
913{
914 for (dx = position.x, sx = 0; sx < width; dx++, sx++)
915{
916 alpha = (pixel(blendThis, sx, sy).ch.a);
917
918/* Skip blending for fully transparent pixel */
919if (alpha == 0) continue;
920
921/* For fully opaque pixel, there is no need to interpolate */
922if (alpha == 255)
923{
924pixel(blendInto, dx, dy).value = pixel(blendThis, sx, sy).value;
925continue;
926}
927
928/* For semi-transparent pixels, do a full blend */
929//alpha++
930/* This is needed to spread the alpha over [0..256] instead of [0..255]
931 Boundary conditions were handled above */
932 dstrb = pixel(blendInto, dx, dy).value & 0xFF00FF;
933 dstag = (pixel(blendInto, dx, dy).value >> 8) & 0xFF00FF;
934 srcrb = pixel(blendThis, sx, sy).value & 0xFF00FF;
935 srcag = (pixel(blendThis, sx, sy).value >> 8) & 0xFF00FF;
936 drb = srcrb - dstrb;
937 dag = srcag - dstag;
938 drb *= alpha; dag *= alpha;
939 drb >>= 8; dag >>= 8;
940 rb = (drb + dstrb) & 0x00FF00FF;
941 ag = ((dag + dstag) << 8) & 0xFF00FF00;
942 pixel(blendInto, dx, dy).value = (rb | ag);
943 }
944 }
945}
946
947position_t centeredIn( const pixmap_t *background, const pixmap_t *toCenter )
948{
949 position_t centered;
950 centered.x = ( background->width - toCenter->width ) / 2;
951 centered.y = ( background->height - toCenter->height ) / 2;
952 return centered;
953}
954
955position_t centeredAt( const pixmap_t *pixmap, const position_t center )
956{
957 position_t topleft;
958 topleft.x = center.x - (pixmap->width / 2);
959 topleft.y = center.y - (pixmap->height / 2);
960 return topleft;
961}
962
963position_t pos(const uint16_t x, const uint16_t y) { position_t p; p.x = x; p.y = y; return p; }
964
965void flipRB(pixmap_t *p)
966{
967//if(testForQemu()) return;
968
969uint32_t x;
970 register uint8_t tempB;
971for (x = 0; x < (unsigned long)(p->height) * (p->width) ; x++) {
972tempB = (p->pixels[x]).ch.b;
973 (p->pixels[x]).ch.b = (p->pixels[x]).ch.r;
974 (p->pixels[x]).ch.r = tempB;
975}
976}
977

Archive Download this file

Revision: 2006