1 #include <lib/gdi/gpixmap.h>
2 #include <lib/gdi/region.h>
3 #include <lib/gdi/accel.h>
10 gLookup::gLookup(int size, const gPalette &pal, const gRGB &start, const gRGB &end)
13 build(size, pal, start, end);
16 void gLookup::build(int _size, const gPalette &pal, const gRGB &start, const gRGB &end)
27 lookup=new gColor[size];
29 for (int i=0; i<size; i++)
34 int rdiff=-start.r+end.r;
35 int gdiff=-start.g+end.g;
36 int bdiff=-start.b+end.b;
37 int adiff=-start.a+end.a;
38 rdiff*=i; rdiff/=(size-1);
39 gdiff*=i; gdiff/=(size-1);
40 bdiff*=i; bdiff/=(size-1);
41 adiff*=i; adiff/=(size-1);
48 lookup[i]=pal.findColor(col);
66 gSurface::gSurface(eSize size, int _bpp, int accel)
81 case 24: // never use 24bit mode
99 if (gAccel::getInstance())
100 eDebug("accel memory: %d", gAccel::getInstance()->accelAlloc(data, data_phys, y * stride));
102 eDebug("no accel available");
109 data = malloc(y * stride);
114 gSurface::~gSurface()
119 gAccel::getInstance()->accelFree(data_phys);
127 gPixmap *gPixmap::lock()
133 void gPixmap::unlock()
135 contentlock.unlock(1);
138 void gPixmap::fill(const gRegion ®ion, const gColor &color)
141 for (i=0; i<region.rects.size(); ++i)
143 const eRect &area = region.rects[i];
144 if ((area.height()<=0) || (area.width()<=0))
147 if (surface->bpp == 8)
149 for (int y=area.top(); y<area.bottom(); y++)
150 memset(((__u8*)surface->data)+y*surface->stride+area.left(), color.color, area.width());
151 } else if (surface->bpp == 32)
155 if (surface->clut.data && color < surface->clut.colors)
156 col=(surface->clut.data[color].a<<24)|(surface->clut.data[color].r<<16)|(surface->clut.data[color].g<<8)|(surface->clut.data[color].b);
162 if (surface->data_phys && gAccel::getInstance())
163 if (!gAccel::getInstance()->fill(surface, area, col))
166 for (int y=area.top(); y<area.bottom(); y++)
168 __u32 *dst=(__u32*)(((__u8*)surface->data)+y*surface->stride+area.left()*surface->bypp);
174 eWarning("couldn't fill %d bpp", surface->bpp);
178 void gPixmap::blit(const gPixmap &src, ePoint pos, const gRegion &clip, int flag)
180 for (unsigned int i=0; i<clip.rects.size(); ++i)
182 eRect area=eRect(pos, src.size());
184 if (!(flag & blitAlphaTest)) // HACK !!
187 area&=eRect(ePoint(0, 0), size());
188 if ((area.width()<0) || (area.height()<0))
192 srcarea.moveBy(-pos.x(), -pos.y());
194 if ((surface->data_phys && src.surface->data_phys) && (gAccel::getInstance()))
195 if (!gAccel::getInstance()->blit(surface, src.surface, area.topLeft(), srcarea, flag))
197 flag &= ~ blitAlphaBlend;
199 if ((surface->bpp == 8) && (src.surface->bpp==8))
201 __u8 *srcptr=(__u8*)src.surface->data;
202 __u8 *dstptr=(__u8*)surface->data;
204 srcptr+=srcarea.left()*src.surface->bypp+srcarea.top()*src.surface->stride;
205 dstptr+=area.left()*surface->bypp+area.top()*surface->stride;
206 for (int y=0; y<area.height(); y++)
208 if (flag & blitAlphaTest)
210 // no real alphatest yet
211 int width=area.width();
212 unsigned char *src=(unsigned char*)srcptr;
213 unsigned char *dst=(unsigned char*)dstptr;
214 // use duff's device here!
225 memcpy(dstptr, srcptr, area.width()*surface->bypp);
226 srcptr+=src.surface->stride;
227 dstptr+=surface->stride;
229 } else if ((surface->bpp == 32) && (src.surface->bpp==32))
231 __u32 *srcptr=(__u32*)src.surface->data;
232 __u32 *dstptr=(__u32*)surface->data;
234 srcptr+=srcarea.left()+srcarea.top()*src.surface->stride/4;
235 dstptr+=area.left()+area.top()*surface->stride/4;
236 for (int y=0; y<area.height(); y++)
238 if (flag & blitAlphaTest)
240 int width=area.width();
241 unsigned long *src=(unsigned long*)srcptr;
242 unsigned long *dst=(unsigned long*)dstptr;
246 if (!((*src)&0xFF000000))
253 } else if (flag & blitAlphaBlend)
255 // uh oh. this is only until hardware accel is working.
257 int width=area.width();
259 unsigned char *src=(unsigned char*)srcptr;
260 unsigned char *dst=(unsigned char*)dstptr;
262 #define BLEND(x, y, a) (y + ((x-y) * a)/256)
265 unsigned char sa = src[3];
266 unsigned char sr = src[2];
267 unsigned char sg = src[1];
268 unsigned char sb = src[0];
270 unsigned char da = dst[3];
271 unsigned char dr = dst[2];
272 unsigned char dg = dst[1];
273 unsigned char db = dst[0];
275 dst[3] = BLEND(0xFF, da, sa);
276 dst[2] = BLEND(sr, dr, sa);
277 dst[1] = BLEND(sg, dg, sa);
278 dst[0] = BLEND(sb, db, sa);
283 memcpy(dstptr, srcptr, area.width()*surface->bypp);
284 srcptr+=src.surface->stride/4;
285 dstptr+=surface->stride/4;
287 } else if ((surface->bpp == 32) && (src.surface->bpp==8))
289 __u8 *srcptr=(__u8*)src.surface->data;
290 __u8 *dstptr=(__u8*)surface->data; // !!
293 for (int i=0; i<256; ++i)
295 if (src.surface->clut.data && (i<src.surface->clut.colors))
296 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);
302 srcptr+=srcarea.left()*src.surface->bypp+srcarea.top()*src.surface->stride;
303 dstptr+=area.left()*surface->bypp+area.top()*surface->stride;
304 for (int y=0; y<area.height(); y++)
306 if (flag & blitAlphaTest)
308 // no real alphatest yet
309 int width=area.width();
310 unsigned char *src=(unsigned char*)srcptr;
311 __u32 *dst=(__u32*)dstptr;
312 // use duff's device here!
324 int width=area.width();
325 unsigned char *src=(unsigned char*)srcptr;
326 __u32 *dst=(__u32*)dstptr;
330 srcptr+=src.surface->stride;
331 dstptr+=surface->stride;
334 eFatal("cannot blit %dbpp from %dbpp", surface->bpp, src.surface->bpp);
338 void gPixmap::mergePalette(const gPixmap &target)
340 if ((!surface->clut.colors) || (!target.surface->clut.colors))
343 gColor *lookup=new gColor[surface->clut.colors];
345 for (int i=0; i<surface->clut.colors; i++)
346 lookup[i].color=target.surface->clut.findColor(surface->clut.data[i]);
348 delete [] surface->clut.data;
349 surface->clut.colors=target.surface->clut.colors;
350 surface->clut.data=new gRGB[surface->clut.colors];
351 memcpy(surface->clut.data, target.surface->clut.data, sizeof(gRGB)*surface->clut.colors);
353 __u8 *dstptr=(__u8*)surface->data;
355 for (int ay=0; ay<surface->y; ay++)
357 for (int ax=0; ax<surface->x; ax++)
358 dstptr[ax]=lookup[dstptr[ax]];
359 dstptr+=surface->stride;
365 static inline int sgn(int a)
375 void gPixmap::line(const gRegion &clip, ePoint start, ePoint dst, gColor color)
379 int stride = surface->stride;
381 if (clip.rects.empty())
385 if (surface->bpp == 8)
387 srf8 = (__u8*)surface->data;
388 } else if (surface->bpp == 32)
390 srf32 = (__u32*)surface->data;
392 if (surface->clut.data && color < surface->clut.colors)
393 col=(surface->clut.data[color].a<<24)|(surface->clut.data[color].r<<16)|(surface->clut.data[color].g<<8)|(surface->clut.data[color].b);
399 int xa = start.x(), ya = start.y(), xb = dst.x(), yb = dst.y();
400 int dx, dy, x, y, s1, s2, e, temp, swap, i;
420 /* i don't like this clipping loop, but the only */
421 /* other choice i see is to calculate the intersections */
422 /* before iterating through the pixels. */
424 /* one could optimize this because of the ordering */
430 /* if last pixel was invisble, first check bounding box */
433 /* check if we just got into the bbox again */
434 if (clip.extends.contains(x, y))
438 } else if (!clip.rects[a].contains(x, y))
443 if (a == clip.rects.size())
450 } while (!clip.rects[a].contains(x, y));
455 srf8[y * stride + x] = color;
457 srf32[y * stride/4 + x] = col;
473 gColor gPalette::findColor(const gRGB &rgb) const
477 return (rgb.r + rgb.g + rgb.b) / 3;
479 int difference=1<<30, best_choice=0;
480 for (int t=0; t<colors; t++)
483 int td=(signed)(rgb.r-data[t].r); td*=td; td*=(255-data[t].a);
487 td=(signed)(rgb.g-data[t].g); td*=td; td*=(255-data[t].a);
491 td=(signed)(rgb.b-data[t].b); td*=td; td*=(255-data[t].a);
495 td=(signed)(rgb.a-data[t].a); td*=td; td*=255;
513 gPixmap::gPixmap(gSurface *surface): surface(surface)
517 gPixmap::gPixmap(eSize size, int bpp, int accel)
519 surface = new gSurface(size, bpp, accel);