3 #include <lib/gdi/gpixmap.h>
4 #include <lib/gdi/region.h>
5 #include <lib/gdi/accel.h>
12 gLookup::gLookup(int size, const gPalette &pal, const gRGB &start, const gRGB &end)
15 build(size, pal, start, end);
18 void gLookup::build(int _size, const gPalette &pal, const gRGB &start, const gRGB &end)
29 lookup=new gColor[size];
31 for (int i=0; i<size; i++)
36 int rdiff=-start.r+end.r;
37 int gdiff=-start.g+end.g;
38 int bdiff=-start.b+end.b;
39 int adiff=-start.a+end.a;
40 rdiff*=i; rdiff/=(size-1);
41 gdiff*=i; gdiff/=(size-1);
42 bdiff*=i; bdiff/=(size-1);
43 adiff*=i; adiff/=(size-1);
50 lookup[i]=pal.findColor(col);
68 gSurface::gSurface(eSize size, int _bpp, int accel)
83 case 24: // never use 24bit mode
101 if (gAccel::getInstance())
102 eDebug("accel memory: %d", gAccel::getInstance()->accelAlloc(data, data_phys, y * stride));
104 eDebug("no accel available");
111 data = new unsigned char [y * stride];
116 gSurface::~gSurface()
121 gAccel::getInstance()->accelFree(data_phys);
123 delete [] (unsigned char*)data;
129 gPixmap *gPixmap::lock()
135 void gPixmap::unlock()
137 contentlock.unlock(1);
140 void gPixmap::fill(const gRegion ®ion, const gColor &color)
143 for (i=0; i<region.rects.size(); ++i)
145 const eRect &area = region.rects[i];
146 if ((area.height()<=0) || (area.width()<=0))
149 if (surface->bpp == 8)
151 for (int y=area.top(); y<area.bottom(); y++)
152 memset(((__u8*)surface->data)+y*surface->stride+area.left(), color.color, area.width());
153 } else if (surface->bpp == 32)
157 if (surface->clut.data && color < surface->clut.colors)
158 col=(surface->clut.data[color].a<<24)|(surface->clut.data[color].r<<16)|(surface->clut.data[color].g<<8)|(surface->clut.data[color].b);
164 if (surface->data_phys && gAccel::getInstance())
165 if (!gAccel::getInstance()->fill(surface, area, col))
168 for (int y=area.top(); y<area.bottom(); y++)
170 __u32 *dst=(__u32*)(((__u8*)surface->data)+y*surface->stride+area.left()*surface->bypp);
176 eWarning("couldn't fill %d bpp", surface->bpp);
180 void gPixmap::fill(const gRegion ®ion, const gRGB &color)
183 for (i=0; i<region.rects.size(); ++i)
185 const eRect &area = region.rects[i];
186 if ((area.height()<=0) || (area.width()<=0))
189 if (surface->bpp == 32)
196 if (surface->data_phys && gAccel::getInstance())
197 if (!gAccel::getInstance()->fill(surface, area, col))
200 for (int y=area.top(); y<area.bottom(); y++)
202 __u32 *dst=(__u32*)(((__u8*)surface->data)+y*surface->stride+area.left()*surface->bypp);
208 eWarning("couldn't rgbfill %d bpp", surface->bpp);
212 static void blit_8i_to_32(__u32 *dst, __u8 *src, __u32 *pal, int width)
218 static void blit_8i_to_32_at(__u32 *dst, __u8 *src, __u32 *pal, int width)
222 if (!(pal[*src]&0x80000000))
231 /* WARNING, this function is not endian safe! */
232 static void blit_8i_to_32_ab(__u32 *dst, __u8 *src, __u32 *pal, int width)
236 #define BLEND(x, y, a) (y + (((x-y) * a)>>8))
237 __u32 srccol = pal[*src++];
239 unsigned char sb = srccol & 0xFF;
240 unsigned char sg = (srccol >> 8) & 0xFF;
241 unsigned char sr = (srccol >> 16) & 0xFF;
242 unsigned char sa = (srccol >> 24) & 0xFF;
244 unsigned char db = dstcol & 0xFF;
245 unsigned char dg = (dstcol >> 8) & 0xFF;
246 unsigned char dr = (dstcol >> 16) & 0xFF;
247 unsigned char da = (dstcol >> 24) & 0xFF;
249 da = BLEND(0xFF, da, sa) & 0xFF;
250 dr = BLEND(sr, dr, sa) & 0xFF;
251 dg = BLEND(sg, dg, sa) & 0xFF;
252 db = BLEND(sb, db, sa) & 0xFF;
255 *dst++ = db | (dg << 8) | (dr << 16) | (da << 24);
260 void gPixmap::blit(const gPixmap &src, ePoint pos, const gRegion &clip, int flag)
262 for (unsigned int i=0; i<clip.rects.size(); ++i)
264 eRect area=eRect(pos, src.size());
266 area&=eRect(ePoint(0, 0), size());
268 if ((area.width()<0) || (area.height()<0))
272 srcarea.moveBy(-pos.x(), -pos.y());
274 if ((surface->data_phys && src.surface->data_phys) && (gAccel::getInstance()))
275 if (!gAccel::getInstance()->blit(surface, src.surface, area.topLeft(), srcarea, flag))
278 if ((surface->bpp == 8) && (src.surface->bpp==8))
280 __u8 *srcptr=(__u8*)src.surface->data;
281 __u8 *dstptr=(__u8*)surface->data;
283 srcptr+=srcarea.left()*src.surface->bypp+srcarea.top()*src.surface->stride;
284 dstptr+=area.left()*surface->bypp+area.top()*surface->stride;
285 for (int y=0; y<area.height(); y++)
287 if (flag & (blitAlphaTest|blitAlphaBlend))
289 // no real alphatest yet
290 int width=area.width();
291 unsigned char *src=(unsigned char*)srcptr;
292 unsigned char *dst=(unsigned char*)dstptr;
293 // use duff's device here!
304 memcpy(dstptr, srcptr, area.width()*surface->bypp);
305 srcptr+=src.surface->stride;
306 dstptr+=surface->stride;
308 } else if ((surface->bpp == 32) && (src.surface->bpp==32))
310 __u32 *srcptr=(__u32*)src.surface->data;
311 __u32 *dstptr=(__u32*)surface->data;
313 srcptr+=srcarea.left()+srcarea.top()*src.surface->stride/4;
314 dstptr+=area.left()+area.top()*surface->stride/4;
315 for (int y=0; y<area.height(); y++)
317 if (flag & blitAlphaTest)
319 int width=area.width();
320 unsigned long *src=(unsigned long*)srcptr;
321 unsigned long *dst=(unsigned long*)dstptr;
325 if (!((*src)&0xFF000000))
332 } else if (flag & blitAlphaBlend)
334 // uh oh. this is only until hardware accel is working.
336 int width=area.width();
338 unsigned char *src=(unsigned char*)srcptr;
339 unsigned char *dst=(unsigned char*)dstptr;
341 #define BLEND(x, y, a) (y + ((x-y) * a)/256)
344 unsigned char sa = src[3];
345 unsigned char sr = src[2];
346 unsigned char sg = src[1];
347 unsigned char sb = src[0];
349 unsigned char da = dst[3];
350 unsigned char dr = dst[2];
351 unsigned char dg = dst[1];
352 unsigned char db = dst[0];
354 dst[3] = BLEND(0xFF, da, sa);
355 dst[2] = BLEND(sr, dr, sa);
356 dst[1] = BLEND(sg, dg, sa);
357 dst[0] = BLEND(sb, db, sa);
363 memcpy(dstptr, srcptr, area.width()*surface->bypp);
364 srcptr+=src.surface->stride/4;
365 dstptr+=surface->stride/4;
367 } else if ((surface->bpp == 32) && (src.surface->bpp==8))
369 __u8 *srcptr=(__u8*)src.surface->data;
370 __u8 *dstptr=(__u8*)surface->data; // !!
373 for (int i=0; i<256; ++i)
375 if (src.surface->clut.data && (i<src.surface->clut.colors))
376 pal[i]=(src.surface->clut.data[i].a<<24)|(src.surface->clut.data[i].r<<16)|(src.surface->clut.data[i].g<<8)|(src.surface->clut.data[i].b);
382 srcptr+=srcarea.left()*src.surface->bypp+srcarea.top()*src.surface->stride;
383 dstptr+=area.left()*surface->bypp+area.top()*surface->stride;
384 for (int y=0; y<area.height(); y++)
386 int width=area.width();
387 unsigned char *psrc=(unsigned char*)srcptr;
388 __u32 *dst=(__u32*)dstptr;
389 if (flag & blitAlphaTest)
390 blit_8i_to_32_at(dst, psrc, pal, width);
391 else if (flag & blitAlphaBlend)
392 blit_8i_to_32_ab(dst, psrc, pal, width);
394 blit_8i_to_32(dst, psrc, pal, width);
395 srcptr+=src.surface->stride;
396 dstptr+=surface->stride;
399 eWarning("cannot blit %dbpp from %dbpp", surface->bpp, src.surface->bpp);
403 void gPixmap::mergePalette(const gPixmap &target)
405 if ((!surface->clut.colors) || (!target.surface->clut.colors))
408 gColor *lookup=new gColor[surface->clut.colors];
410 for (int i=0; i<surface->clut.colors; i++)
411 lookup[i].color=target.surface->clut.findColor(surface->clut.data[i]);
413 delete [] surface->clut.data;
414 surface->clut.colors=target.surface->clut.colors;
415 surface->clut.data=new gRGB[surface->clut.colors];
416 memcpy(surface->clut.data, target.surface->clut.data, sizeof(gRGB)*surface->clut.colors);
418 __u8 *dstptr=(__u8*)surface->data;
420 for (int ay=0; ay<surface->y; ay++)
422 for (int ax=0; ax<surface->x; ax++)
423 dstptr[ax]=lookup[dstptr[ax]];
424 dstptr+=surface->stride;
430 static inline int sgn(int a)
440 void gPixmap::line(const gRegion &clip, ePoint start, ePoint dst, gColor color)
444 int stride = surface->stride;
446 if (clip.rects.empty())
450 if (surface->bpp == 8)
452 srf8 = (__u8*)surface->data;
453 } else if (surface->bpp == 32)
455 srf32 = (__u32*)surface->data;
457 if (surface->clut.data && color < surface->clut.colors)
458 col=(surface->clut.data[color].a<<24)|(surface->clut.data[color].r<<16)|(surface->clut.data[color].g<<8)|(surface->clut.data[color].b);
464 int xa = start.x(), ya = start.y(), xb = dst.x(), yb = dst.y();
465 int dx, dy, x, y, s1, s2, e, temp, swap, i;
485 /* i don't like this clipping loop, but the only */
486 /* other choice i see is to calculate the intersections */
487 /* before iterating through the pixels. */
489 /* one could optimize this because of the ordering */
495 /* if last pixel was invisble, first check bounding box */
498 /* check if we just got into the bbox again */
499 if (clip.extends.contains(x, y))
503 } else if (!clip.rects[a].contains(x, y))
508 if ((unsigned int)a == clip.rects.size())
515 } while (!clip.rects[a].contains(x, y));
520 srf8[y * stride + x] = color;
522 srf32[y * stride/4 + x] = col;
538 gColor gPalette::findColor(const gRGB &rgb) const
542 return (rgb.r + rgb.g + rgb.b) / 3;
544 int difference=1<<30, best_choice=0;
545 for (int t=0; t<colors; t++)
548 int td=(signed)(rgb.r-data[t].r); td*=td; td*=(255-data[t].a);
552 td=(signed)(rgb.g-data[t].g); td*=td; td*=(255-data[t].a);
556 td=(signed)(rgb.b-data[t].b); td*=td; td*=(255-data[t].a);
560 td=(signed)(rgb.a-data[t].a); td*=td; td*=255;
576 if (must_delete_surface)
580 gPixmap::gPixmap(gSurface *surface)
581 :surface(surface), must_delete_surface(false)
585 gPixmap::gPixmap(eSize size, int bpp, int accel)
586 :must_delete_surface(true)
588 surface = new gSurface(size, bpp, accel);