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

Archive Download this file

Revision: 1929