Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/i386/modules/GUI/graphic_utils.c

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

Archive Download this file

Revision: 2118