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

Archive Download this file

Revision: 2057