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

Archive Download this file

Revision: 1913