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;
629 unsigned short mode = modeEndOfList;
630
631 if ( (cols != 80) || (rows != 25) ) // not 80x25 mode
632 {
633 mode = getVESAModeWithProperties( cols, rows, bitsPerPixel,
634 maColorModeBit |
635 maModeIsSupportedBit,
636 maGraphicsModeBit,
637 &minfo, NULL );
638 }
639
640 if ( ( mode == modeEndOfList ) || ( setVBEMode(mode, NULL) != errSuccess ) )
641 {
642 video_mode( 2 ); // VGA BIOS, 80x25 text mode.
643 minfo.XResolution = 80;
644 minfo.YResolution = 25;
645 }
646
647 // Update KernBootStruct using info provided by the selected
648 // VESA mode.
649
650 Boot_VideoVideo;/* Video Information */
651
652
653 Video.v_display = VGA_TEXT_MODE;
654 Video.v_width = 0xb8000;
655 Video.v_height = minfo.XResolution;
656 Video.v_depth = minfo.YResolution;
657 Video.v_rowBytes = 8;
658 Video.v_baseAddr = 0x8000;
659
660 setBootArgsVideoStruct(&Video);
661
662 return errSuccess; // always return success
663}
664
665//==========================================================================
666// setVideoMode
667//
668// Set the video mode to VGA_TEXT_MODE or GRAPHICS_MODE.
669#if UNUSED
670void
671setVideoMode( int mode, int drawgraphics)
672#else
673void
674setVideoMode( int mode)
675#endif
676{
677 unsigned long params[4];
678 int count;
679 int err = errSuccess;
680
681 if ( mode == GRAPHICS_MODE )
682 {
683 if ( (err=GUI_initGraphicsMode ()) == errSuccess ) {
684if (gVerboseMode) {
685// Tell the kernel to use text mode on a linear frame buffer display
686 setBootArgsVideoMode(FB_TEXT_MODE);
687
688} else {
689 setBootArgsVideoMode(GRAPHICS_MODE);
690
691}
692}
693 }
694
695 if ( (mode == VGA_TEXT_MODE) || (err != errSuccess) )
696 {
697 count = getNumberArrayFromProperty( kTextModeKey, params, 2 );
698 if ( count < 2 )
699 {
700 params[0] = 80; // Default text mode is 80x25.
701 params[1] = 25;
702 }
703
704setVESATextMode( params[0], params[1], 4 );
705 setBootArgsVideoMode(VGA_TEXT_MODE);
706 }
707
708}
709
710//==========================================================================
711// setupPalette
712
713static void setupPalette( VBEPalette * p, const unsigned char * g )
714{
715 int i;
716 unsigned char * source = (unsigned char *) g;
717
718 for (i = 0; i < 256; i++)
719 {
720 (*p)[i] = 0;
721 (*p)[i] |= ((unsigned long)((*source++) >> 2)) << 16; // Red
722 (*p)[i] |= ((unsigned long)((*source++) >> 2)) << 8; // Green
723 (*p)[i] |= ((unsigned long)((*source++) >> 2)); // Blue
724
725 }
726}
727
728
729//==========================================================================
730// setVESAGraphicsMode
731#if UNUSED
732int setVESAGraphicsMode( unsigned short width, unsigned short height, unsigned char bitsPerPixel, unsigned short refreshRate )
733#else
734int setVESAGraphicsMode( unsigned short width, unsigned short height, unsigned char bitsPerPixel)
735#endif
736{
737 VBEModeInfoBlock minfo;
738 unsigned short mode;
739 unsigned short vesaVersion;
740 int err = errFuncNotSupported;
741
742 do {
743 mode = getVESAModeWithProperties( width, height, bitsPerPixel,
744 maColorModeBit |
745 maModeIsSupportedBit |
746 maGraphicsModeBit |
747 maLinearFrameBufferAvailBit,
748 0,
749 &minfo, &vesaVersion );
750 if ( mode == modeEndOfList )
751 {
752 break;
753 }
754#if UNUSED
755//
756// FIXME : generateCRTCTiming() causes crash.
757//
758
759// if ( (vesaVersion >> 8) >= 3 && refreshRate >= 60 &&
760// (gBootMode & kBootModeSafe) == 0 )
761// {
762// VBECRTCInfoBlock timing;
763//
764// // Generate CRTC timing for given refresh rate.
765//
766// generateCRTCTiming( minfo.XResolution, minfo.YResolution,
767// refreshRate, kCRTCParamRefreshRate,
768// &timing );
769//
770// // Find the actual pixel clock supported by the hardware.
771//
772// getVBEPixelClock( mode, &timing.PixelClock );
773//
774// // Re-compute CRTC timing based on actual pixel clock.
775//
776// generateCRTCTiming( minfo.XResolution, minfo.YResolution,
777// timing.PixelClock, kCRTCParamPixelClock,
778// &timing );
779//
780// // Set the video mode and use specified CRTC timing.
781//
782// err = setVBEMode( mode | kLinearFrameBufferBit |
783// kCustomRefreshRateBit, &timing );
784// }
785// else
786// {
787// // Set the mode with default refresh rate.
788//
789// err = setVBEMode( mode | kLinearFrameBufferBit, NULL );
790// }
791#endif
792 // Set the mode with default refresh rate.
793
794 err = setVBEMode( mode | kLinearFrameBufferBit, NULL );
795
796 if ( err != errSuccess )
797 {
798 break;
799 }
800
801 // Set 8-bit color palette.
802
803 if ( minfo.BitsPerPixel == 8 )
804 {
805 VBEPalette palette;
806 setupPalette( &palette, appleClut8 );
807 if ((err = setVBEPalette(palette)) != errSuccess)
808 {
809 break;
810 }
811 }
812
813 // Is this required for buggy Video BIOS implementations?
814 // On which adapter?
815
816 if ( minfo.BytesPerScanline == 0 )
817minfo.BytesPerScanline = ( minfo.XResolution *
818 minfo.BitsPerPixel ) >> 3;
819
820 // Update KernBootStruct using info provided by the selected
821 // VESA mode.
822
823 Boot_VideoVideo;/* Video Information */
824
825
826 Video.v_display = GRAPHICS_MODE;
827 Video.v_width = minfo.XResolution;
828 Video.v_height = minfo.YResolution;
829 Video.v_depth = minfo.BitsPerPixel;
830 Video.v_rowBytes = minfo.BytesPerScanline;
831 Video.v_baseAddr = VBEMakeUInt32(minfo.PhysBasePtr);
832
833
834setBootArgsVideoStruct(&Video);
835
836 }
837 while ( 0 );
838
839 return err;
840}
841
842void getGraphicModeParams(unsigned long params[]) {
843
844params[3] = 0;
845
846VBEModeInfoBlock minfo;
847
848 unsigned short vesaVersion;
849 //unsigned short mode = modeEndOfList;
850
851getNumberArrayFromProperty( kGraphicsModeKey, params, 4);
852
853/* mode = */getVESAModeWithProperties( params[0], params[1], params[2],
854 maColorModeBit |
855 maModeIsSupportedBit |
856 maGraphicsModeBit |
857 maLinearFrameBufferAvailBit,
858 0,
859 &minfo, &vesaVersion );
860
861params[0] = minfo.XResolution;
862params[1] = minfo.YResolution;
863params[2] = 32;
864}
865
866
867//==========================================================================
868// getVBEInfoString
869
870char *getVBEInfoString(void)
871{
872VBEInfoBlock vbeInfo;
873int err, small;
874char *buff = malloc(sizeof(char)*256);
875if(!buff) return 0;
876
877//bzero( &vbeInfo, sizeof(vbeInfo) );
878 bzero( &vbeInfo, sizeof(VBEInfoBlock) );
879
880strcpy( (char*)&vbeInfo, "VBE2" );
881err = getVBEInfo( &vbeInfo );
882if (err != errSuccess)
883goto error;
884
885if ( strncmp( (char *)vbeInfo.VESASignature, "VESA", 4 ) )
886goto error;
887
888small = (vbeInfo.TotalMemory < 16);
889
890sprintf(buff, "VESA v%d.%d %d%s (%s)\n",
891vbeInfo.VESAVersion >> 8,
892vbeInfo.VESAVersion & 0xf,
893small ? (vbeInfo.TotalMemory * 64) : (vbeInfo.TotalMemory / 16),
894small ? "KB" : "MB",
895VBEDecodeFP(const char *, vbeInfo.OEMStringPtr) );
896
897return buff;
898error:
899 free(buff);
900 return 0;
901}
902
903void blend( const pixmap_t *blendThis, // Source image
904 pixmap_t *blendInto, // Dest image
905 const position_t position) // Where to place the source image
906{
907 uint16_t sx, sy, dx, dy;
908 uint32_t dstrb, dstag, srcrb, srcag, drb, dag, rb, ag, alpha;
909
910uint16_t width = (blendThis->width + position.x < blendInto->width) ? blendThis->width: blendInto->width-position.x;
911uint16_t height = (blendThis->height + position.y < blendInto->height) ? blendThis->height: blendInto->height-position.y;
912
913for (dy = position.y, sy = 0; sy < height; dy++, sy++)
914{
915 for (dx = position.x, sx = 0; sx < width; dx++, sx++)
916{
917 alpha = (pixel(blendThis, sx, sy).ch.a);
918
919/* Skip blending for fully transparent pixel */
920if (alpha == 0) continue;
921
922/* For fully opaque pixel, there is no need to interpolate */
923if (alpha == 255)
924{
925pixel(blendInto, dx, dy).value = pixel(blendThis, sx, sy).value;
926continue;
927}
928
929/* For semi-transparent pixels, do a full blend */
930//alpha++
931/* This is needed to spread the alpha over [0..256] instead of [0..255]
932 Boundary conditions were handled above */
933 dstrb = pixel(blendInto, dx, dy).value & 0xFF00FF;
934 dstag = (pixel(blendInto, dx, dy).value >> 8) & 0xFF00FF;
935 srcrb = pixel(blendThis, sx, sy).value & 0xFF00FF;
936 srcag = (pixel(blendThis, sx, sy).value >> 8) & 0xFF00FF;
937 drb = srcrb - dstrb;
938 dag = srcag - dstag;
939 drb *= alpha; dag *= alpha;
940 drb >>= 8; dag >>= 8;
941 rb = (drb + dstrb) & 0x00FF00FF;
942 ag = ((dag + dstag) << 8) & 0xFF00FF00;
943 pixel(blendInto, dx, dy).value = (rb | ag);
944 }
945 }
946}
947
948position_t centeredIn( const pixmap_t *background, const pixmap_t *toCenter )
949{
950 position_t centered;
951 centered.x = ( background->width - toCenter->width ) / 2;
952 centered.y = ( background->height - toCenter->height ) / 2;
953 return centered;
954}
955
956position_t centeredAt( const pixmap_t *pixmap, const position_t center )
957{
958 position_t topleft;
959 topleft.x = center.x - (pixmap->width / 2);
960 topleft.y = center.y - (pixmap->height / 2);
961 return topleft;
962}
963
964position_t pos(const uint16_t x, const uint16_t y) { position_t p; p.x = x; p.y = y; return p; }
965
966void flipRB(pixmap_t *p)
967{
968//if(testForQemu()) return;
969
970uint32_t x;
971 register uint8_t tempB;
972for (x = 0; x < (unsigned long)(p->height) * (p->width) ; x++) {
973tempB = (p->pixels[x]).ch.b;
974 (p->pixels[x]).ch.b = (p->pixels[x]).ch.r;
975 (p->pixels[x]).ch.r = tempB;
976}
977}
978

Archive Download this file

Revision: 1919