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 "boot.h"
7#include "graphic_utils.h"
8#include "graphics.h"
9#include "vbe.h"
10#include "gui.h"
11
12#define VIDEO(x) (bootArgs->Video.v_ ## x)
13
14#define MIN(x, y) ((x) < (y) ? (x) : (y))
15
16
17
18#ifdef OPTION_ROM
19int
20convertImage( unsigned short width,
21 unsigned short height,
22 const unsigned char *imageData,
23 unsigned char **newImageData )
24{
25 int cnt;
26 unsigned char *img = 0;
27 unsigned short *img16;
28 unsigned long *img32;
29
30 switch ( VIDEO(depth) ) {
31case 16 :
32img16 = malloc(width * height * 2);
33if ( !img16 ) break;
34for (cnt = 0; cnt < (width * height); cnt++)
35img16[cnt] = lookUpCLUTIndex(imageData[cnt], 16);
36img = (unsigned char *)img16;
37break;
38
39case 32 :
40img32 = malloc(width * height * 4);
41if ( !img32 ) break;
42for (cnt = 0; cnt < (width * height); cnt++)
43img32[cnt] = lookUpCLUTIndex(imageData[cnt], 32);
44img = (unsigned char *)img32;
45break;
46
47default :
48img = malloc(width * height);
49bcopy(imageData, img, width * height);
50break;
51 }
52 *newImageData = img;
53 return 0;
54}
55
56//==========================================================================
57// drawDataRectangle
58
59void drawDataRectangle( unsigned short x,
60 unsigned short y,
61 unsigned short width,
62 unsigned short height,
63 unsigned char * data )
64{
65 unsigned short drawWidth;
66 long pixelBytes = VIDEO(depth) / 8;
67 unsigned char * vram = (unsigned char *) VIDEO(baseAddr) +
68VIDEO(rowBytes) * y + pixelBytes * x;
69
70 drawWidth = MIN(width, VIDEO(width) - x);
71 height = MIN(height, VIDEO(height) - y);
72 while ( height-- ) {
73 bcopy( data, vram, drawWidth * pixelBytes );
74 vram += VIDEO(rowBytes);
75 data += width * pixelBytes;
76 }
77}
78#endif
79
80
81//==========================================================================
82//
83void
84printVBEModeInfo()
85{
86 VBEInfoBlock vbeInfo;
87 unsigned short * modePtr;
88 VBEModeInfoBlock modeInfo;
89 int err;
90 int line;
91
92 //bzero( &vbeInfo, sizeof(vbeInfo) );
93 bzero( &vbeInfo, sizeof(VBEInfoBlock) );
94
95 strcpy( (char*)&vbeInfo, "VBE2" );
96 err = getVBEInfo( &vbeInfo );
97 if ( err != errSuccess )
98 return;
99
100 line = 0;
101
102 // Activate and clear page 1
103 setActiveDisplayPage(1);
104 clearScreenRows(0, 24);
105 setCursorPosition( 0, 0, 1 );
106
107printf("Video modes supported:\n", VBEDecodeFP(const char *, vbeInfo.OEMStringPtr));
108
109// Loop through the mode list, and find the matching mode.
110
111 for ( modePtr = VBEDecodeFP( unsigned short *, vbeInfo.VideoModePtr );
112 *modePtr != modeEndOfList; modePtr++ )
113 {
114 // Get mode information.
115
116 //bzero( &modeInfo, sizeof(modeInfo) );
117 bzero( &modeInfo, sizeof(VBEModeInfoBlock) );
118
119 err = getVBEModeInfo( *modePtr, &modeInfo );
120 if ( err != errSuccess )
121 {
122 continue;
123 }
124
125 printf("Mode %x: %dx%dx%d mm:%d attr:%x\n",
126 *modePtr, modeInfo.XResolution, modeInfo.YResolution,
127 modeInfo.BitsPerPixel, modeInfo.MemoryModel,
128 modeInfo.ModeAttributes);
129
130 if (line++ >= 20) {
131 pause();
132 line = 0;
133 clearScreenRows(0, 24);
134 setCursorPosition( 0, 0, 1 );
135 }
136 }
137 if (line != 0) {
138 pause();
139 }
140 setActiveDisplayPage(0);
141}
142
143
144
145char *getVBEModeInfoString()
146{
147VBEInfoBlock vbeInfo;
148 unsigned short * modePtr;
149 VBEModeInfoBlock modeInfo;
150 int err;
151
152 //bzero( &vbeInfo, sizeof(vbeInfo) );
153 bzero( &vbeInfo, sizeof(VBEInfoBlock) );
154
155 strcpy( (char*)&vbeInfo, "VBE2" );
156 err = getVBEInfo( &vbeInfo );
157 if ( err != errSuccess )
158 return 0;
159
160char *buff=malloc(sizeof(char)*3072);
161if(!buff) return 0;
162
163// Loop through the mode list, and find the matching mode.
164 for ( modePtr = VBEDecodeFP( unsigned short *, vbeInfo.VideoModePtr );
165 *modePtr != modeEndOfList; modePtr++ )
166 {
167 // Get mode information.
168
169 //bzero( &modeInfo, sizeof(modeInfo) );
170 bzero( &modeInfo, sizeof(VBEModeInfoBlock) );
171
172 err = getVBEModeInfo( *modePtr, &modeInfo );
173 if ( err != errSuccess )
174 {
175 continue;
176 }
177
178 sprintf(buff+strlen(buff), "Mode %x: %dx%dx%d mm:%d attr:%x\n",
179*modePtr, modeInfo.XResolution, modeInfo.YResolution,
180modeInfo.BitsPerPixel, modeInfo.MemoryModel,
181modeInfo.ModeAttributes);
182
183 }
184return buff;
185}
186
187
188void blendImage(uint16_t x, uint16_t y, uint16_t width, uint16_t height,
189uint8_t *data)
190{
191 uint16_t drawWidth;
192 uint8_t *vram = (uint8_t *) VIDEO(baseAddr) + VIDEO(rowBytes) * y + 4 * x;
193
194 drawWidth = MIN(width, VIDEO(width) - x);
195 height = MIN(height, VIDEO(height) - y);
196 while (height--) {
197switch (VIDEO (depth))
198{
199case 32: /* Optimized version*/
200{
201uint32_t s; uint32_t* d; // Source (img) and destination (bkgd) pixels
202uint32_t a; // Alpha
203uint32_t dstrb, dstg, srcrb, srcg, drb, dg, rb, g, tempB; // Intermediate variables
204uint16_t pos;
205
206for (pos = 0; pos < drawWidth * 4; pos += 4) {
207// Fast pseudo-vector alpha blending, adapted from: http://www.stereopsis.com/doubleblend.html
208s = *((uint32_t*) (data + pos));
209d = (uint32_t*) (vram + pos);
210
211// Flip B and R in source
212// TODO: use XCHG and inline assembly to do this in a faster, saner way
213tempB = (s & 0xFF0000); // save B
214s = (s & 0xFF00FFFF) | ((s & 0xFF) << 16); // put R in B
215s = (s & 0xFFFFFF00) | (tempB >> 16); // put B in R
216
217a = (s >> 24) + 1;
218
219dstrb = *d & 0xFF00FF; dstg = *d & 0xFF00;
220srcrb = s & 0xFF00FF; srcg = s & 0xFF00;
221
222drb = srcrb - dstrb;
223dg = srcg - dstg;
224drb *= a; dg *= a;
225drb >>= 8; dg >>= 8;
226
227rb = (drb + dstrb) & 0xFF00FF;
228g = (dg + dstg) & 0xFF00;
229
230*d = rb | g;
231}
232}
233break;
234
235default: /*Universal version*/
236{
237uint32_t s;
238uint32_t a; // Alpha
239uint32_t dr, dg, db, sr, sg, sb; // Intermediate variables
240uint16_t pos;
241int bpp = (VIDEO (depth) + 7)/8;
242
243for (pos = 0; pos < drawWidth; pos ++) {
244// Fast pseudo-vector alpha blending, adapted from: http://www.stereopsis.com/doubleblend.html
245s = *((uint32_t*) (data + 4*pos));
246
247sb = (s & 0xFF0000) >> 16;
248sg = (s & 0xFF00) >> 8;
249sr = (s & 0xFF);
250
251a = (s >> 24) + 1;
252
253switch (VIDEO (depth))
254{
255case 24:
256db = ((*(uint32_t *)(vram + bpp*pos))&0xff);
257dg = ((*(uint32_t *)(vram + bpp*pos))&0xff00)>>8;
258dr = ((*(uint32_t *)(vram + bpp*pos))&0xff0000)>>16;
259break;
260case 16://16-bit seems to be 15-bit
261/*db = ((*(uint16_t *)(vram + bpp*pos))&0x1f)<<3;
262 dg = ((*(uint16_t *)(vram + bpp*pos))&0x07e0)>>3;
263 dr = ((*(uint16_t *)(vram + bpp*pos))&0xf800)>>8;
264 break;*/
265case 15:
266db = ((*(uint16_t *)(vram + bpp*pos))&0x1f)<<3;
267dg = ((*(uint16_t *)(vram + bpp*pos))&0x03e0)>>2;
268dr = ((*(uint16_t *)(vram + bpp*pos))&0x7c00)>>7;
269break;
270default:
271return;
272}
273
274dr = (((sr - dr) * a) >> 8) + dr;
275dg = (((sg - dg) * a) >> 8) + dg;
276db = (((sb - db) * a) >> 8) + db;
277switch (VIDEO (depth))
278{
279case 24:
280*(uint32_t *)(vram + bpp*pos) = (*(uint32_t *)(vram + bpp*pos) &0xff000000)
281| (db&0xff) | ((dg&0xff)<<8) | ((dr&0xff)<<16);
282break;
283case 16:
284//*(uint16_t *)(vram + bpp*pos) = ((db&0xf8)>>3) | ((dg&0xfc)<<3) | ((dr&0xf8)<<8);
285//break;
286case 15:
287*(uint16_t *)(vram + bpp*pos) = ((db&0xf8)>>3) | ((dg&0xf8)<<2) | ((dr&0xf8)<<7);
288break;
289default:
290break;
291}
292
293}
294}
295break;
296 }
297 vram += VIDEO(rowBytes);
298 data += width * 4;
299 }
300}
301
302void drawCheckerBoard()
303{
304 uint32_t *vram = (uint32_t *) VIDEO(baseAddr);
305 uint16_t x, y;
306 uint8_t color;
307
308 for (y = 0; y < VIDEO(height); y++, vram += VIDEO(width)) {
309 for (x = 0; x < VIDEO(width); x++) {
310 color = 204 + 51 * (((x / 8) % 2) == ((y / 8) % 2));
311 vram[x] = (color << 16) | (color << 8) | color;
312 }
313 }
314}
315
316void getGraphicModeParams(unsigned long params[]) {
317
318params[3] = 0;
319
320VBEModeInfoBlock minfo;
321
322 unsigned short vesaVersion;
323 unsigned short mode = modeEndOfList;
324
325getNumberArrayFromProperty( kGraphicsModeKey, params, 4);
326
327mode = getVESAModeWithProperties( params[0], params[1], params[2],
328 maColorModeBit |
329 maModeIsSupportedBit |
330 maGraphicsModeBit |
331 maLinearFrameBufferAvailBit,
332 0,
333 &minfo, &vesaVersion );
334
335params[0] = minfo.XResolution;
336params[1] = minfo.YResolution;
337params[2] = 32;
338}
339
340
341//==========================================================================
342// getVBEInfoString
343
344char *getVBEInfoString()
345{
346VBEInfoBlock vbeInfo;
347int err, small;
348char *buff = malloc(sizeof(char)*256);
349if(!buff) return 0;
350
351//bzero( &vbeInfo, sizeof(vbeInfo) );
352 bzero( &vbeInfo, sizeof(VBEInfoBlock) );
353
354strcpy( (char*)&vbeInfo, "VBE2" );
355err = getVBEInfo( &vbeInfo );
356if (err != errSuccess)
357return 0;
358
359if ( strncmp( (char *)vbeInfo.VESASignature, "VESA", 4 ) )
360return 0;
361
362small = (vbeInfo.TotalMemory < 16);
363
364sprintf(buff, "VESA v%d.%d %d%s (%s)\n",
365vbeInfo.VESAVersion >> 8,
366vbeInfo.VESAVersion & 0xf,
367small ? (vbeInfo.TotalMemory * 64) : (vbeInfo.TotalMemory / 16),
368small ? "KB" : "MB",
369VBEDecodeFP(const char *, vbeInfo.OEMStringPtr) );
370
371return buff;
372}
373
374void blend( const pixmap_t *blendThis, // Source image
375 pixmap_t *blendInto, // Dest image
376 const position_t position) // Where to place the source image
377{
378 uint16_t sx, sy, dx, dy;
379 uint32_t dstrb, dstag, srcrb, srcag, drb, dag, rb, ag, alpha;
380
381uint16_t width = (blendThis->width + position.x < blendInto->width) ? blendThis->width: blendInto->width-position.x;
382uint16_t height = (blendThis->height + position.y < blendInto->height) ? blendThis->height: blendInto->height-position.y;
383
384for (dy = position.y, sy = 0; sy < height; dy++, sy++)
385{
386 for (dx = position.x, sx = 0; sx < width; dx++, sx++)
387{
388 alpha = (pixel(blendThis, sx, sy).ch.a);
389
390/* Skip blending for fully transparent pixel */
391if (alpha == 0) continue;
392
393/* For fully opaque pixel, there is no need to interpolate */
394if (alpha == 255)
395{
396pixel(blendInto, dx, dy).value = pixel(blendThis, sx, sy).value;
397continue;
398}
399
400/* For semi-transparent pixels, do a full blend */
401//alpha++
402/* This is needed to spread the alpha over [0..256] instead of [0..255]
403 Boundary conditions were handled above */
404 dstrb = pixel(blendInto, dx, dy).value & 0xFF00FF;
405 dstag = (pixel(blendInto, dx, dy).value >> 8) & 0xFF00FF;
406 srcrb = pixel(blendThis, sx, sy).value & 0xFF00FF;
407 srcag = (pixel(blendThis, sx, sy).value >> 8) & 0xFF00FF;
408 drb = srcrb - dstrb;
409 dag = srcag - dstag;
410 drb *= alpha; dag *= alpha;
411 drb >>= 8; dag >>= 8;
412 rb = (drb + dstrb) & 0x00FF00FF;
413 ag = ((dag + dstag) << 8) & 0xFF00FF00;
414 pixel(blendInto, dx, dy).value = (rb | ag);
415 }
416 }
417}
418
419position_t centeredIn( const pixmap_t *background, const pixmap_t *toCenter )
420{
421 position_t centered;
422 centered.x = ( background->width - toCenter->width ) / 2;
423 centered.y = ( background->height - toCenter->height ) / 2;
424 return centered;
425}
426
427position_t centeredAt( const pixmap_t *pixmap, const position_t center )
428{
429 position_t topleft;
430 topleft.x = center.x - (pixmap->width / 2);
431 topleft.y = center.y - (pixmap->height / 2);
432 return topleft;
433}
434
435position_t pos(const uint16_t x, const uint16_t y) { position_t p; p.x = x; p.y = y; return p; }
436
437void flipRB(pixmap_t *p)
438{
439//if(testForQemu()) return;
440
441uint32_t x;
442 register uint8_t tempB;
443for (x = 0; x < (unsigned long)(p->height) * (p->width) ; x++) {
444tempB = (p->pixels[x]).ch.b;
445 (p->pixels[x]).ch.b = (p->pixels[x]).ch.r;
446 (p->pixels[x]).ch.r = tempB;
447}
448}
449

Archive Download this file

Revision: 1468