diff options
author | Gerd Hoffmann <kraxel@redhat.com> | 2019-02-01 23:01:03 +0100 |
---|---|---|
committer | Gerd Hoffmann <kraxel@redhat.com> | 2019-02-01 23:01:03 +0100 |
commit | b8e5897b4edb640012f43dc87b7c84194163a153 (patch) | |
tree | 0ad9b3858b615ed53f9598481249e5c28e07d189 | |
parent | 83a73a82f5c91c0ab223649a0e9af5430cfa3b9a (diff) | |
download | fbida-b8e5897b4edb640012f43dc87b7c84194163a153.tar.gz |
use pixman for image blit+blend
-rw-r--r-- | fb-gui.c | 62 | ||||
-rw-r--r-- | fb-gui.h | 6 | ||||
-rw-r--r-- | fbi.c | 26 | ||||
-rw-r--r-- | readers.c | 2 |
4 files changed, 38 insertions, 58 deletions
@@ -8,8 +8,11 @@ #include <sys/ioctl.h> #include <linux/fb.h> +#include <pixman.h> + #include "vt.h" #include "fbtools.h" +#include "readers.h" #include "fb-gui.h" static int ys = 3; @@ -25,6 +28,7 @@ static unsigned int *sdirty,swidth,sheight; static cairo_t *context; static cairo_surface_t *surface; +static pixman_image_t *pixman; static unsigned char *framebuffer; static cairo_font_extents_t extents; @@ -106,12 +110,19 @@ void shadow_render(gfxstate *gfx) void shadow_clear_lines(int first, int last) { +#if 0 + /* FIXME: segfaults */ + cairo_rectangle(context, 0, first, swidth, last - first + 1); + cairo_set_source_rgb(context, 0, 0, 0); + cairo_fill(context); +#else int i; for (i = first; i <= last; i++) { memset(shadow[i],0,4*swidth); sdirty[i]++; } +#endif } void shadow_clear(void) @@ -153,6 +164,9 @@ void shadow_init(gfxstate *gfx) swidth, sheight, swidth * 4); context = cairo_create(surface); + pixman = pixman_image_create_bits(PIXMAN_x8r8g8b8, swidth, sheight, + (void*)framebuffer, swidth * 4); + /* init rendering */ switch (gfx->bits_per_pixel) { @@ -208,40 +222,28 @@ void shadow_draw_rect(int x1, int x2, int y1, int y2) shadow_set_dirty_range(y1, (y2 - y1) + 1); } -void shadow_draw_rgbdata(int x, int y, int pixels, unsigned char *rgb) +void shadow_composite_image(struct ida_image *img, + int xoff, int yoff, int weight) { - unsigned char *dest = shadow[y] + 4*x; - int i; - - for (i = 0; i < pixels; i++) { - dest[0] = rgb[2]; - dest[1] = rgb[1]; - dest[2] = rgb[0]; - dest += 4; - rgb += 3; + if (weight == 100) { + pixman_image_composite(PIXMAN_OP_SRC, img->p, NULL, pixman, + 0, 0, 0, 0, + xoff, yoff, + img->i.width, img->i.height); + } else { + pixman_color_t color = { + .alpha = weight * 0xffff / 100, + }; + pixman_image_t *mask = pixman_image_create_solid_fill(&color); + + pixman_image_composite(PIXMAN_OP_OVER, img->p, mask, pixman, + 0, 0, 0, 0, + xoff, yoff, + img->i.width, img->i.height); + pixman_image_unref(mask); } - sdirty[y]++; } -void shadow_merge_rgbdata(int x, int y, int pixels, int weight, - unsigned char *rgb) -{ - unsigned char *dest = shadow[y] + 4*x; - int i; - - weight = weight * 256 / 100; - - for (i = 0; i < pixels; i++) { - dest[0] += rgb[2] * weight >> 8; - dest[1] += rgb[1] * weight >> 8; - dest[2] += rgb[0] * weight >> 8; - dest += 4; - rgb += 3; - } - sdirty[y]++; -} - - void shadow_darkify(int x1, int x2, int y1,int y2, int percent) { cairo_rectangle(context, x1, y1, @@ -12,10 +12,8 @@ void shadow_fini(void); void shadow_draw_line(int x1, int x2, int y1,int y2); void shadow_draw_rect(int x1, int x2, int y1,int y2); -void shadow_draw_rgbdata(int x, int y, int pixels, - unsigned char *rgb); -void shadow_merge_rgbdata(int x, int y, int pixels, int weight, - unsigned char *rgb); +void shadow_composite_image(struct ida_image *img, + int xoff, int yoff, int weight); void shadow_darkify(int x1, int x2, int y1,int y2, int percent); int shadow_draw_string(int x, int y, char *str, int align); @@ -365,41 +365,21 @@ static void shadow_draw_image(struct ida_image *img, int xoff, int yoff, unsigned int first, unsigned int last, int weight) { - unsigned int dwidth = MIN(img->i.width, gfx->hdisplay); - unsigned int dheight = MIN(img->i.height, gfx->vdisplay); - unsigned int data, offset, y, xs, ys; + unsigned int xs, ys; if (100 == weight) shadow_clear_lines(first, last); else shadow_darkify(0, gfx->hdisplay-1, first, last, 100 - weight); - /* offset for image data (image > screen, select visible area) */ - offset = (yoff * img->i.width + xoff) * 3; - - /* offset for video memory (image < screen, center image) */ + /* image < screen: center image */ xs = 0, ys = 0; if (img->i.width < gfx->hdisplay) xs += (gfx->hdisplay - img->i.width) / 2; if (img->i.height < gfx->vdisplay) ys += (gfx->vdisplay - img->i.height) / 2; - /* go ! */ - for (data = 0, y = 0; - data < img->i.width * img->i.height * 3 - && data / img->i.width / 3 < dheight; - data += img->i.width * 3, y++) { - if (ys+y < first) - continue; - if (ys+y > last) - continue; - if (100 == weight) - shadow_draw_rgbdata(xs, ys+y, dwidth, - ida_image_scanline(img, y) + offset); - else - shadow_merge_rgbdata(xs, ys+y, dwidth, weight, - ida_image_scanline(img, y) + offset); - } + shadow_composite_image(img, xs - xoff, ys - yoff, weight); } static void status_prepare(void) @@ -130,7 +130,7 @@ int load_free_extras(struct ida_image_info *info) void ida_image_alloc(struct ida_image *img) { assert(img->p == NULL); - img->p = pixman_image_create_bits(PIXMAN_r8g8b8, + img->p = pixman_image_create_bits(/* PIXMAN_r8g8b8 */ PIXMAN_b8g8r8, img->i.width, img->i.height, NULL, 0); } |