Chameleon

Chameleon Svn Source Tree

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

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

Archive Download this file

Revision: 1931