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

Archive Download this file

Revision: 1840