summaryrefslogtreecommitdiff
path: root/src/fl_draw_image.cxx
diff options
context:
space:
mode:
authorLauri Kasanen <cand@gmx.com>2015-03-16 18:12:28 +0000
committerLauri Kasanen <cand@gmx.com>2015-03-16 18:12:28 +0000
commitc91e48149beda4538d47e5a3a3c393f7690d2aa4 (patch)
tree5555484e4251f56a891b6541ff555868aefadadc /src/fl_draw_image.cxx
parent4798d70ded21f88109944bdb525d978bf74fb36d (diff)
Add support for accelerated alpha blending under X11.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@10628 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src/fl_draw_image.cxx')
-rw-r--r--src/fl_draw_image.cxx55
1 files changed, 49 insertions, 6 deletions
diff --git a/src/fl_draw_image.cxx b/src/fl_draw_image.cxx
index 68ff5505d..2562e473e 100644
--- a/src/fl_draw_image.cxx
+++ b/src/fl_draw_image.cxx
@@ -316,6 +316,13 @@ static void xrgb_converter(const uchar *from, uchar *to, int w, int delta) {
INNARDS32((from[0]<<16)+(from[1]<<8)+(from[2]));
}
+static void argb_premul_converter(const uchar *from, uchar *to, int w, int delta) {
+ INNARDS32((from[3] << 24) +
+ (((from[0] * from[3]) / 255) << 16) +
+ (((from[1] * from[3]) / 255) << 8) +
+ ((from[2] * from[3]) / 255));
+}
+
static void bgrx_converter(const uchar *from, uchar *to, int w, int delta) {
INNARDS32((from[0]<<8)+(from[1]<<16)+(unsigned(from[2])<<24));
}
@@ -451,7 +458,8 @@ static void figure_out_visual() {
static void innards(const uchar *buf, int X, int Y, int W, int H,
int delta, int linedelta, int mono,
- Fl_Draw_Image_Cb cb, void* userdata)
+ Fl_Draw_Image_Cb cb, void* userdata,
+ const bool alpha)
{
if (!linedelta) linedelta = W*delta;
@@ -462,11 +470,28 @@ static void innards(const uchar *buf, int X, int Y, int W, int H,
dy -= Y;
if (!bytes_per_pixel) figure_out_visual();
+ const unsigned oldbpp = bytes_per_pixel;
+ const GC oldgc = fl_gc;
+ static GC gc32 = None;
xi.width = w;
xi.height = h;
void (*conv)(const uchar *from, uchar *to, int w, int delta) = converter;
if (mono) conv = mono_converter;
+ if (alpha) {
+ // This flag states the destination format is ARGB32 (big-endian), pre-multiplied.
+ bytes_per_pixel = 4;
+ conv = argb_premul_converter;
+ xi.depth = 32;
+ xi.bits_per_pixel = 32;
+
+ // Do we need a new GC?
+ if (fl_visual->depth != 32) {
+ if (gc32 == None)
+ gc32 = XCreateGC(fl_display, fl_window, 0, NULL);
+ fl_gc = gc32;
+ }
+ }
// See if the data is already in the right format. Unfortunately
// some 32-bit x servers (XFree86) care about the unknown 8 bits
@@ -534,21 +559,39 @@ static void innards(const uchar *buf, int X, int Y, int W, int H,
delete[] linebuf;
}
}
+
+ if (alpha) {
+ bytes_per_pixel = oldbpp;
+ xi.depth = fl_visual->depth;
+ xi.bits_per_pixel = oldbpp * 8;
+
+ if (fl_visual->depth != 32) {
+ fl_gc = oldgc;
+ }
+ }
}
void Fl_Xlib_Graphics_Driver::draw_image(const uchar* buf, int x, int y, int w, int h, int d, int l){
- innards(buf,x,y,w,h,d,l,(d<3&&d>-3),0,0);
+
+ const bool alpha = !!(d & FL_IMAGE_WITH_ALPHA);
+ d &= ~FL_IMAGE_WITH_ALPHA;
+
+ innards(buf,x,y,w,h,d,l,(d<3&&d>-3),0,0,alpha);
}
void Fl_Xlib_Graphics_Driver::draw_image(Fl_Draw_Image_Cb cb, void* data,
int x, int y, int w, int h,int d) {
- innards(0,x,y,w,h,d,0,(d<3&&d>-3),cb,data);
+
+ const bool alpha = !!(d & FL_IMAGE_WITH_ALPHA);
+ d &= ~FL_IMAGE_WITH_ALPHA;
+
+ innards(0,x,y,w,h,d,0,(d<3&&d>-3),cb,data,alpha);
}
void Fl_Xlib_Graphics_Driver::draw_image_mono(const uchar* buf, int x, int y, int w, int h, int d, int l){
- innards(buf,x,y,w,h,d,l,1,0,0);
+ innards(buf,x,y,w,h,d,l,1,0,0,0);
}
void Fl_Xlib_Graphics_Driver::draw_image_mono(Fl_Draw_Image_Cb cb, void* data,
int x, int y, int w, int h,int d) {
- innards(0,x,y,w,h,d,0,1,cb,data);
+ innards(0,x,y,w,h,d,0,1,cb,data,0);
}
void fl_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) {
@@ -558,7 +601,7 @@ void fl_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) {
} else {
uchar c[3];
c[0] = r; c[1] = g; c[2] = b;
- innards(c,x,y,w,h,0,0,0,0,0);
+ innards(c,x,y,w,h,0,0,0,0,0,0);
}
}