3 #include <lib/gdi/gpixmap.h>
4 #include <lib/gdi/region.h>
5 #include <lib/gdi/accel.h>
9 #error "no BYTE_ORDER defined!"
17 gLookup::gLookup(int size, const gPalette &pal, const gRGB &start, const gRGB &end)
20 build(size, pal, start, end);
23 void gLookup::build(int _size, const gPalette &pal, const gRGB &start, const gRGB &end)
34 lookup=new gColor[size];
36 for (int i=0; i<size; i++)
41 int rdiff=-start.r+end.r;
42 int gdiff=-start.g+end.g;
43 int bdiff=-start.b+end.b;
44 int adiff=-start.a+end.a;
45 rdiff*=i; rdiff/=(size-1);
46 gdiff*=i; gdiff/=(size-1);
47 bdiff*=i; bdiff/=(size-1);
48 adiff*=i; adiff/=(size-1);
55 lookup[i]=pal.findColor(col);
73 gSurface::gSurface(eSize size, int _bpp, int accel)
88 case 24: // never use 24bit mode
110 if (gAccel::getInstance())
111 eDebug("accel memory: %d", gAccel::getInstance()->accelAlloc(data, data_phys, y * stride + pal_size));
113 eDebug("no accel available");
120 data = new unsigned char [y * stride];
125 gSurface::~gSurface()
130 gAccel::getInstance()->accelFree(data_phys);
132 delete [] (unsigned char*)data;
138 gPixmap *gPixmap::lock()
144 void gPixmap::unlock()
146 contentlock.unlock(1);
149 void gPixmap::fill(const gRegion ®ion, const gColor &color)
152 for (i=0; i<region.rects.size(); ++i)
154 const eRect &area = region.rects[i];
158 if (surface->bpp == 8)
160 for (int y=area.top(); y<area.bottom(); y++)
161 memset(((__u8*)surface->data)+y*surface->stride+area.left(), color.color, area.width());
162 } else if (surface->bpp == 16)
166 if (surface->clut.data && color < surface->clut.colors)
167 icol=(surface->clut.data[color].a<<24)|(surface->clut.data[color].r<<16)|(surface->clut.data[color].g<<8)|(surface->clut.data[color].b);
170 #if BYTE_ORDER == LITTLE_ENDIAN
171 __u16 col = bswap_16(((icol & 0xFF) >> 3) << 11 | ((icol & 0xFF00) >> 10) << 5 | (icol & 0xFF0000) >> 19);
173 __u16 col = ((icol & 0xFF) >> 3) << 11 | ((icol & 0xFF00) >> 10) << 5 | (icol & 0xFF0000) >> 19;
175 for (int y=area.top(); y<area.bottom(); y++)
177 __u16 *dst=(__u16*)(((__u8*)surface->data)+y*surface->stride+area.left()*surface->bypp);
182 } else if (surface->bpp == 32)
186 if (surface->clut.data && color < surface->clut.colors)
187 col=(surface->clut.data[color].a<<24)|(surface->clut.data[color].r<<16)|(surface->clut.data[color].g<<8)|(surface->clut.data[color].b);
193 if (surface->data_phys && gAccel::getInstance())
194 if (!gAccel::getInstance()->fill(surface, area, col))
197 for (int y=area.top(); y<area.bottom(); y++)
199 __u32 *dst=(__u32*)(((__u8*)surface->data)+y*surface->stride+area.left()*surface->bypp);
205 eWarning("couldn't fill %d bpp", surface->bpp);
209 void gPixmap::fill(const gRegion ®ion, const gRGB &color)
212 for (i=0; i<region.rects.size(); ++i)
214 const eRect &area = region.rects[i];
218 if (surface->bpp == 32)
225 if (surface->data_phys && gAccel::getInstance())
226 if (!gAccel::getInstance()->fill(surface, area, col))
229 for (int y=area.top(); y<area.bottom(); y++)
231 __u32 *dst=(__u32*)(((__u8*)surface->data)+y*surface->stride+area.left()*surface->bypp);
236 } else if (surface->bpp == 16)
238 __u32 icol = color.argb();
239 #if BYTE_ORDER == LITTLE_ENDIAN
240 __u16 col = bswap_16(((icol & 0xFF) >> 3) << 11 | ((icol & 0xFF00) >> 10) << 5 | (icol & 0xFF0000) >> 19);
242 __u16 col = ((icol & 0xFF) >> 3) << 11 | ((icol & 0xFF00) >> 10) << 5 | (icol & 0xFF0000) >> 19;
244 for (int y=area.top(); y<area.bottom(); y++)
246 __u16 *dst=(__u16*)(((__u8*)surface->data)+y*surface->stride+area.left()*surface->bypp);
252 eWarning("couldn't rgbfill %d bpp", surface->bpp);
256 static inline void blit_8i_to_32(__u32 *dst, __u8 *src, __u32 *pal, int width)
262 static inline void blit_8i_to_32_at(__u32 *dst, __u8 *src, __u32 *pal, int width)
266 if (!(pal[*src]&0x80000000))
275 static inline void blit_8i_to_16(__u16 *dst, __u8 *src, __u32 *pal, int width)
278 *dst++=pal[*src++] & 0xFFFF;
281 static inline void blit_8i_to_16_at(__u16 *dst, __u8 *src, __u32 *pal, int width)
285 if (!(pal[*src]&0x80000000))
290 *dst++=pal[*src++] & 0xFFFF;
294 /* WARNING, this function is not endian safe! */
295 static void blit_8i_to_32_ab(__u32 *dst, __u8 *src, __u32 *pal, int width)
299 #define BLEND(x, y, a) (y + (((x-y) * a)>>8))
300 __u32 srccol = pal[*src++];
302 unsigned char sb = srccol & 0xFF;
303 unsigned char sg = (srccol >> 8) & 0xFF;
304 unsigned char sr = (srccol >> 16) & 0xFF;
305 unsigned char sa = (srccol >> 24) & 0xFF;
307 unsigned char db = dstcol & 0xFF;
308 unsigned char dg = (dstcol >> 8) & 0xFF;
309 unsigned char dr = (dstcol >> 16) & 0xFF;
310 unsigned char da = (dstcol >> 24) & 0xFF;
312 da = BLEND(0xFF, da, sa) & 0xFF;
313 dr = BLEND(sr, dr, sa) & 0xFF;
314 dg = BLEND(sg, dg, sa) & 0xFF;
315 db = BLEND(sb, db, sa) & 0xFF;
318 *dst++ = db | (dg << 8) | (dr << 16) | (da << 24);
325 void gPixmap::blit(const gPixmap &src, const eRect &_pos, const gRegion &clip, int flag)
327 // eDebug("blit: -> %d.%d %d:%d -> %d.%d %d:%d, flags=%d",
328 // _pos.x(), _pos.y(), _pos.width(), _pos.height(),
329 // clip.extends.x(), clip.extends.y(), clip.extends.width(), clip.extends.height(),
333 // eDebug("source size: %d %d", src.size().width(), src.size().height());
335 if (!(flag & blitScale)) /* pos' size is valid only when scaling */
336 pos = eRect(pos.topLeft(), src.size());
337 else if (pos.size() == src.size()) /* no scaling required */
340 int scale_x = FIX, scale_y = FIX;
342 if (flag & blitScale)
344 ASSERT(src.size().width());
345 ASSERT(src.size().height());
346 scale_x = pos.size().width() * FIX / src.size().width();
347 scale_y = pos.size().height() * FIX / src.size().height();
350 // eDebug("SCALE %x %x", scale_x, scale_y);
352 for (unsigned int i=0; i<clip.rects.size(); ++i)
354 // eDebug("clip rect: %d %d %d %d", clip.rects[i].x(), clip.rects[i].y(), clip.rects[i].width(), clip.rects[i].height());
355 eRect area = pos; /* pos is the virtual (pre-clipping) area on the dest, which can be larger/smaller than src if scaling is enabled */
357 area&=eRect(ePoint(0, 0), size());
362 eRect srcarea = area;
363 srcarea.moveBy(-pos.x(), -pos.y());
365 // eDebug("srcarea before scale: %d %d %d %d",
366 // srcarea.x(), srcarea.y(), srcarea.width(), srcarea.height());
368 if (flag & blitScale)
369 srcarea = eRect(srcarea.x() * FIX / scale_x, srcarea.y() * FIX / scale_y, srcarea.width() * FIX / scale_x, srcarea.height() * FIX / scale_y);
371 // eDebug("srcarea after scale: %d %d %d %d",
372 // srcarea.x(), srcarea.y(), srcarea.width(), srcarea.height());
374 if ((surface->data_phys && src.surface->data_phys) && (gAccel::getInstance()))
375 if (!gAccel::getInstance()->blit(surface, src.surface, area, srcarea, flag))
378 if (flag & blitScale)
380 eWarning("unimplemented: scale on non-accel surfaces");
384 #ifdef SET_RIGHT_HALF_VFD_SKIN
385 if ((surface->bpp == 8) && (src.surface->bpp==8))
387 __u8 *srcptr=(__u8*)src.surface->data;
388 __u8 *dstptr=(__u8*)surface->data;
389 __u8 *nomptr = new __u8[area.width()];
390 unsigned char gray_max = 0;
391 unsigned char gray_min = 255;
392 unsigned char index = 0;
393 unsigned char gray_value = 0;
395 // printf("[bilt]srcarea.left:%d, src.surface->bypp : %d,srcarea.top() :%d,src.surface->stride : %d\n",srcarea.left(),src.surface->bypp,srcarea.top(),src.surface->stride);
396 srcptr+=srcarea.left()*src.surface->bypp+srcarea.top()*src.surface->stride;
397 // nomptr+=srcarea.left()*src.surface->bypp+srcarea.top()*src.surface->stride;
398 dstptr+=area.left()*surface->bypp+area.top()*surface->stride;
399 if(src.surface->clut.colors != 0)
401 for (int y=0; y<area.height(); y++)
403 for(int x=0;x<area.width();x++)
405 index = (unsigned char)(*(srcptr+x+y*src.surface->stride));
406 pixdata = src.surface->clut.data[index];
407 gray_value = ((pixdata.r+pixdata.g +pixdata.b)/3);
408 // printf("%3d ",gray_value);
409 if(gray_value > gray_max)
410 gray_max = gray_value;
411 if(gray_value < gray_min)
412 gray_min = gray_value;
417 // printf("\n[bilt] ### gray_min : %d, gray_max : %d\n\n",gray_min,gray_max);
418 for (int y=0; y<area.height(); y++)
420 if(src.surface->clut.colors != 0)
422 for(int x=0;x<area.width();x++)
424 pixdata = src.surface->clut.data[*(srcptr+x)];
425 gray_value = ((pixdata.r+pixdata.g +pixdata.b)/3);
426 if(gray_max==gray_min)
427 *(nomptr+x)=gray_value;
428 /* else if(y == 0 || y == area.height()-1 || x == 0 || x == area.width()-1)
431 *(nomptr+x)=( ((gray_value - gray_min)*255)/(gray_max-gray_min) );
432 // printf("%3d ",*(nomptr+x));
438 for(int x=0;x<area.width();x++)
440 /* if(y == 0 || y == area.height()-1 || x == 0 || x == area.width()-1)
443 *(nomptr+x)=*(srcptr+x);*/
444 *(nomptr+x)=*(srcptr+x);
445 // printf("%3d ",*(nomptr+x));
449 if (flag & (blitAlphaTest|blitAlphaBlend))
451 // no real alphatest yet
452 int width=area.width();
453 // unsigned char *src=(unsigned char*)srcptr;
454 unsigned char *src=(unsigned char*)nomptr;
455 unsigned char *dst=(unsigned char*)dstptr;
456 // use duff's device here!
467 // memcpy(dstptr, srcptr, area.width()*surface->bypp);
468 memcpy(dstptr, nomptr, area.width()*surface->bypp);
469 srcptr+=src.surface->stride;
470 dstptr+=surface->stride;
474 if ((surface->bpp == 8) && (src.surface->bpp==8))
476 __u8 *srcptr=(__u8*)src.surface->data;
477 __u8 *dstptr=(__u8*)surface->data;
479 srcptr+=srcarea.left()*src.surface->bypp+srcarea.top()*src.surface->stride;
480 dstptr+=area.left()*surface->bypp+area.top()*surface->stride;
481 for (int y=0; y<area.height(); y++)
483 if (flag & (blitAlphaTest|blitAlphaBlend))
485 // no real alphatest yet
486 int width=area.width();
487 unsigned char *src=(unsigned char*)srcptr;
488 unsigned char *dst=(unsigned char*)dstptr;
489 // use duff's device here!
500 memcpy(dstptr, srcptr, area.width()*surface->bypp);
501 srcptr+=src.surface->stride;
502 dstptr+=surface->stride;
505 } else if ((surface->bpp == 32) && (src.surface->bpp==32))
507 __u32 *srcptr=(__u32*)src.surface->data;
508 __u32 *dstptr=(__u32*)surface->data;
510 srcptr+=srcarea.left()+srcarea.top()*src.surface->stride/4;
511 dstptr+=area.left()+area.top()*surface->stride/4;
512 for (int y=0; y<area.height(); y++)
514 if (flag & blitAlphaTest)
516 int width=area.width();
517 unsigned long *src=(unsigned long*)srcptr;
518 unsigned long *dst=(unsigned long*)dstptr;
522 if (!((*src)&0xFF000000))
529 } else if (flag & blitAlphaBlend)
531 // uh oh. this is only until hardware accel is working.
533 int width=area.width();
535 unsigned char *src=(unsigned char*)srcptr;
536 unsigned char *dst=(unsigned char*)dstptr;
538 #define BLEND(x, y, a) (y + ((x-y) * a)/256)
541 unsigned char sa = src[3];
542 unsigned char sr = src[2];
543 unsigned char sg = src[1];
544 unsigned char sb = src[0];
546 unsigned char da = dst[3];
547 unsigned char dr = dst[2];
548 unsigned char dg = dst[1];
549 unsigned char db = dst[0];
551 dst[3] = BLEND(0xFF, da, sa);
552 dst[2] = BLEND(sr, dr, sa);
553 dst[1] = BLEND(sg, dg, sa);
554 dst[0] = BLEND(sb, db, sa);
560 memcpy(dstptr, srcptr, area.width()*surface->bypp);
561 srcptr+=src.surface->stride/4;
562 dstptr+=surface->stride/4;
564 } else if ((surface->bpp == 32) && (src.surface->bpp==8))
566 __u8 *srcptr=(__u8*)src.surface->data;
567 __u8 *dstptr=(__u8*)surface->data; // !!
570 for (int i=0; i<256; ++i)
572 if (src.surface->clut.data && (i<src.surface->clut.colors))
573 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);
579 srcptr+=srcarea.left()*src.surface->bypp+srcarea.top()*src.surface->stride;
580 dstptr+=area.left()*surface->bypp+area.top()*surface->stride;
581 for (int y=0; y<area.height(); y++)
583 int width=area.width();
584 unsigned char *psrc=(unsigned char*)srcptr;
585 __u32 *dst=(__u32*)dstptr;
586 if (flag & blitAlphaTest)
587 blit_8i_to_32_at(dst, psrc, pal, width);
588 else if (flag & blitAlphaBlend)
589 blit_8i_to_32_ab(dst, psrc, pal, width);
591 blit_8i_to_32(dst, psrc, pal, width);
592 srcptr+=src.surface->stride;
593 dstptr+=surface->stride;
595 } else if ((surface->bpp == 16) && (src.surface->bpp==8))
597 __u8 *srcptr=(__u8*)src.surface->data;
598 __u8 *dstptr=(__u8*)surface->data; // !!
601 for (int i=0; i<256; ++i)
604 if (src.surface->clut.data && (i<src.surface->clut.colors))
605 icol=(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);
608 #if BYTE_ORDER == LITTLE_ENDIAN
609 pal[i] = bswap_16(((icol & 0xFF) >> 3) << 11 | ((icol & 0xFF00) >> 10) << 5 | (icol & 0xFF0000) >> 19);
611 pal[i] = ((icol & 0xFF) >> 3) << 11 | ((icol & 0xFF00) >> 10) << 5 | (icol & 0xFF0000) >> 19;
616 srcptr+=srcarea.left()*src.surface->bypp+srcarea.top()*src.surface->stride;
617 dstptr+=area.left()*surface->bypp+area.top()*surface->stride;
619 if (flag & blitAlphaBlend)
620 eWarning("ignore unsupported 8bpp -> 16bpp alphablend!");
622 for (int y=0; y<area.height(); y++)
624 int width=area.width();
625 unsigned char *psrc=(unsigned char*)srcptr;
626 __u16 *dst=(__u16*)dstptr;
627 if (flag & blitAlphaTest)
628 blit_8i_to_16_at(dst, psrc, pal, width);
630 blit_8i_to_16(dst, psrc, pal, width);
631 srcptr+=src.surface->stride;
632 dstptr+=surface->stride;
634 } else if ((surface->bpp == 16) && (src.surface->bpp==32))
636 __u8 *srcptr=(__u8*)src.surface->data;
637 __u8 *dstptr=(__u8*)surface->data;
639 srcptr+=srcarea.left()+srcarea.top()*src.surface->stride;
640 dstptr+=area.left()+area.top()*surface->stride;
642 if (flag & blitAlphaBlend)
643 eWarning("ignore unsupported 32bpp -> 16bpp alphablend!");
645 for (int y=0; y<area.height(); y++)
647 int width=area.width();
648 __u32 *srcp=(__u32*)srcptr;
649 __u16 *dstp=(__u16*)dstptr;
651 if (flag & blitAlphaTest)
655 if (!((*srcp)&0xFF000000))
661 __u32 icol = *srcp++;
662 #if BYTE_ORDER == LITTLE_ENDIAN
663 *dstp++ = bswap_16(((icol & 0xFF) >> 3) << 11 | ((icol & 0xFF00) >> 10) << 5 | (icol & 0xFF0000) >> 19);
665 *dstp++ = ((icol & 0xFF) >> 3) << 11 | ((icol & 0xFF00) >> 10) << 5 | (icol & 0xFF0000) >> 19;
673 __u32 icol = *srcp++;
674 #if BYTE_ORDER == LITTLE_ENDIAN
675 *dstp++ = bswap_16(((icol & 0xFF) >> 3) << 11 | ((icol & 0xFF00) >> 10) << 5 | (icol & 0xFF0000) >> 19);
677 *dstp++ = ((icol & 0xFF) >> 3) << 11 | ((icol & 0xFF00) >> 10) << 5 | (icol & 0xFF0000) >> 19;
681 srcptr+=src.surface->stride;
682 dstptr+=surface->stride;
685 eWarning("cannot blit %dbpp from %dbpp", surface->bpp, src.surface->bpp);
691 void gPixmap::mergePalette(const gPixmap &target)
693 if ((!surface->clut.colors) || (!target.surface->clut.colors))
696 gColor *lookup=new gColor[surface->clut.colors];
698 for (int i=0; i<surface->clut.colors; i++)
699 lookup[i].color=target.surface->clut.findColor(surface->clut.data[i]);
701 delete [] surface->clut.data;
702 surface->clut.colors=target.surface->clut.colors;
703 surface->clut.data=new gRGB[surface->clut.colors];
704 memcpy(surface->clut.data, target.surface->clut.data, sizeof(gRGB)*surface->clut.colors);
706 __u8 *dstptr=(__u8*)surface->data;
708 for (int ay=0; ay<surface->y; ay++)
710 for (int ax=0; ax<surface->x; ax++)
711 dstptr[ax]=lookup[dstptr[ax]];
712 dstptr+=surface->stride;
718 static inline int sgn(int a)
728 void gPixmap::line(const gRegion &clip, ePoint start, ePoint dst, gColor color)
733 int stride = surface->stride;
735 if (clip.rects.empty())
740 if (surface->bpp == 8)
741 srf8 = (__u8*)surface->data;
744 srf32 = (__u32*)surface->data;
745 if (surface->clut.data && color < surface->clut.colors)
746 col=(surface->clut.data[color].a<<24)|(surface->clut.data[color].r<<16)|(surface->clut.data[color].g<<8)|(surface->clut.data[color].b);
752 if (surface->bpp == 16)
753 #if BYTE_ORDER == LITTLE_ENDIAN
754 col16=bswap_16(((col & 0xFF) >> 3) << 11 | ((col & 0xFF00) >> 10) << 5 | (col & 0xFF0000) >> 19);
756 col16=((col & 0xFF) >> 3) << 11 | ((col & 0xFF00) >> 10) << 5 | (col & 0xFF0000) >> 19;
759 int xa = start.x(), ya = start.y(), xb = dst.x(), yb = dst.y();
760 int dx, dy, x, y, s1, s2, e, temp, swap, i;
780 /* i don't like this clipping loop, but the only */
781 /* other choice i see is to calculate the intersections */
782 /* before iterating through the pixels. */
784 /* one could optimize this because of the ordering */
790 /* if last pixel was invisble, first check bounding box */
793 /* check if we just got into the bbox again */
794 if (clip.extends.contains(x, y))
798 } else if (!clip.rects[a].contains(x, y))
803 if ((unsigned int)a == clip.rects.size())
810 } while (!clip.rects[a].contains(x, y));
815 srf8[y * stride + x] = color;
817 srf16[y * stride/2 + x] = col16;
819 srf32[y * stride/4 + x] = col;
838 gColor gPalette::findColor(const gRGB &rgb) const
842 return (rgb.r + rgb.g + rgb.b) / 3;
844 int difference=1<<30, best_choice=0;
845 for (int t=0; t<colors; t++)
848 int td=(signed)(rgb.r-data[t].r); td*=td; td*=(255-data[t].a);
852 td=(signed)(rgb.g-data[t].g); td*=td; td*=(255-data[t].a);
856 td=(signed)(rgb.b-data[t].b); td*=td; td*=(255-data[t].a);
860 td=(signed)(rgb.a-data[t].a); td*=td; td*=255;
876 if (must_delete_surface)
880 gPixmap::gPixmap(gSurface *surface)
881 :surface(surface), must_delete_surface(false)
885 gPixmap::gPixmap(eSize size, int bpp, int accel)
886 :must_delete_surface(true)
888 surface = new gSurface(size, bpp, accel);