--- /dev/null
+/* vim: ts=4 sw=2 expandtab autoindent cindent
+ * ply-image.c - png file loader
+ *
+ * Copyright (C) 2006, 2007 Red Hat, Inc.
+ * Copyright (C) 2003 University of Southern California
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Some implementation taken from the cairo library.
+ *
+ * Written by: Kristian Høgsberg <krh@redhat.com>
+ * Ray Strode <rstrode@redhat.com>
+ * Carl D. Worth (cworth@cworth.org>
+ */
+#include "config.h"
+#include "ply-image.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <png.h>
+
+#include <linux/fb.h>
+
+#include "ply-utils.h"
+
+typedef union
+{
+ uint32_t *as_pixels;
+ png_byte *as_png_bytes;
+ char *address;
+} PlyImageLayout;
+
+struct _PlyImage
+{
+ char *filename;
+ FILE *fp;
+
+ PlyImageLayout layout;
+ size_t size;
+
+ long width;
+ long height;
+};
+
+static bool ply_image_open_file (PlyImage *image);
+static void ply_image_close_file (PlyImage *image);
+
+static bool
+ply_image_open_file (PlyImage *image)
+{
+ assert (image != NULL);
+
+ image->fp = fopen (image->filename, "r");
+
+ if (image->fp == NULL)
+ return false;
+ return true;
+}
+
+static void
+ply_image_close_file (PlyImage *image)
+{
+ assert (image != NULL);
+
+ if (image->fp == NULL)
+ return;
+ fclose (image->fp);
+ image->fp = NULL;
+}
+
+PlyImage *
+ply_image_new (const char *filename)
+{
+ PlyImage *image;
+
+ assert (filename != NULL);
+
+ image = calloc (1, sizeof (PlyImage));
+
+ image->filename = strdup (filename);
+ image->fp = NULL;
+ image->layout.address = NULL;
+ image->size = -1;
+ image->width = -1;
+ image->height = -1;
+
+ return image;
+}
+
+void
+ply_image_free (PlyImage *image)
+{
+ assert (image != NULL);
+ assert (image->filename != NULL);
+
+ if (image->layout.address != NULL)
+ {
+ free (image->layout.address);
+ image->layout.address = NULL;
+ }
+
+ free (image->filename);
+ free (image);
+}
+
+static void
+transform_to_argb32 (png_struct *png,
+ png_row_info *row_info,
+ png_byte *data)
+{
+ unsigned int i;
+
+ for (i = 0; i < row_info->rowbytes; i += 4)
+ {
+ uint8_t red, green, blue, alpha;
+ uint32_t pixel_value;
+
+ red = data[i + 0];
+ green = data[i + 1];
+ blue = data[i + 2];
+ alpha = data[i + 3];
+
+ red = (uint8_t) CLAMP (((red / 255.0) * (alpha / 255.0)) * 255.0, 0, 255.0);
+ green = (uint8_t) CLAMP (((green / 255.0) * (alpha / 255.0)) * 255.0,
+ 0, 255.0);
+ blue = (uint8_t) CLAMP (((blue / 255.0) * (alpha / 255.0)) * 255.0, 0, 255.0);
+
+ pixel_value = (alpha << 24) | (red << 16) | (green << 8) | (blue << 0);
+ memcpy (data + i, &pixel_value, sizeof (uint32_t));
+ }
+}
+
+bool
+ply_image_load (PlyImage *image)
+{
+ png_struct *png;
+ png_info *info;
+ png_uint_32 width, height, bytes_per_row, row;
+ int bits_per_pixel, color_type, interlace_method;
+ png_byte **rows;
+
+ assert (image != NULL);
+
+ if (!ply_image_open_file (image))
+ return false;
+
+ png = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ assert (png != NULL);
+
+ info = png_create_info_struct (png);
+ assert (info != NULL);
+
+ png_init_io (png, image->fp);
+
+ if (setjmp (png_jmpbuf (png)) != 0)
+ {
+ ply_image_close_file (image);
+ return false;
+ }
+
+ png_read_info (png, info);
+ png_get_IHDR (png, info,
+ &width, &height, &bits_per_pixel,
+ &color_type, &interlace_method, NULL, NULL);
+ bytes_per_row = 4 * width;
+
+ if (color_type == PNG_COLOR_TYPE_PALETTE)
+ png_set_palette_to_rgb (png);
+
+ if ((color_type == PNG_COLOR_TYPE_GRAY) && (bits_per_pixel < 8))
+ png_set_gray_1_2_4_to_8 (png);
+
+ if (png_get_valid (png, info, PNG_INFO_tRNS))
+ png_set_tRNS_to_alpha (png);
+
+ if (bits_per_pixel == 16)
+ png_set_strip_16 (png);
+
+ if (bits_per_pixel < 8)
+ png_set_packing (png);
+
+ if ((color_type == PNG_COLOR_TYPE_GRAY)
+ || (color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
+ png_set_gray_to_rgb (png);
+
+ if (interlace_method != PNG_INTERLACE_NONE)
+ png_set_interlace_handling (png);
+
+ png_set_filler (png, 0xff, PNG_FILLER_AFTER);
+
+ png_set_read_user_transform_fn (png, transform_to_argb32);
+
+ png_read_update_info (png, info);
+
+ rows = malloc (height * sizeof (png_byte *));
+ image->layout.address = malloc (height * bytes_per_row);
+
+ for (row = 0; row < height; row++)
+ rows[row] = &image->layout.as_png_bytes[row * bytes_per_row];
+
+ png_read_image (png, rows);
+
+ free (rows);
+ png_read_end (png, info);
+ ply_image_close_file (image);
+
+ image->width = width;
+ image->height = height;
+
+ return true;
+}
+
+uint32_t *
+ply_image_get_data (PlyImage *image)
+{
+ assert (image != NULL);
+
+ return image->layout.as_pixels;
+}
+
+ssize_t
+ply_image_get_size (PlyImage *image)
+{
+ assert (image != NULL);
+
+ return image->size;
+}
+
+long
+ply_image_get_width (PlyImage *image)
+{
+ assert (image != NULL);
+
+ return image->width;
+}
+
+long
+ply_image_get_height (PlyImage *image)
+{
+ assert (image != NULL);
+
+ return image->height;
+}
+
+#ifdef PLY_IMAGE_ENABLE_TEST
+
+#include "ply-video-buffer.h"
+
+#include <math.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+#ifndef FRAMES_PER_SECOND
+#define FRAMES_PER_SECOND 30
+#endif
+
+static double
+get_current_time (void)
+{
+ const double microseconds_per_second = 1000000.0;
+ double timestamp;
+ struct timeval now = { 0L, /* zero-filled */ };
+
+ gettimeofday (&now, NULL);
+ timestamp = ((microseconds_per_second * now.tv_sec) + now.tv_usec) /
+ microseconds_per_second;
+
+ return timestamp;
+}
+
+static void
+animate_at_time (PlyVideoBuffer *buffer,
+ PlyImage *image,
+ double time)
+{
+ PlyVideoBufferArea area;
+ uint32_t *data;
+ long width, height;
+ double opacity = 0.0;
+
+ data = ply_image_get_data (image);
+ width = ply_image_get_width (image);
+ height = ply_image_get_height (image);
+
+ ply_video_buffer_get_size (buffer, &area);
+ area.x = (area.width / 2) - (width / 2);
+ area.y = (area.height / 2) - (height / 2);
+ area.width = width;
+ area.height = height;
+
+ opacity = .5 * sin (time * (2 * M_PI)) + .5;
+ ply_video_buffer_pause_updates (buffer);
+ ply_video_buffer_fill_with_color (buffer, &area,
+ 60.0/256.0, 110.0/256.0, 180.0/256.0, 1.0);
+ ply_video_buffer_fill_with_argb32_data_at_opacity (buffer, &area,
+ 0, 0, width, height,
+ data, 0.3);
+ ply_video_buffer_unpause_updates (buffer);
+}
+
+int
+main (int argc,
+ char **argv)
+{
+ PlyImage *image;
+ PlyVideoBuffer *buffer;
+ int exit_code;
+ double start_time;
+
+ exit_code = 0;
+
+ image = ply_image_new ("booting.png");
+
+ if (!ply_image_load (image))
+ {
+ exit_code = errno;
+ perror ("could not load image");
+ return exit_code;
+ }
+
+ buffer = ply_video_buffer_new (NULL);
+
+ if (!ply_video_buffer_open (buffer))
+ {
+ exit_code = errno;
+ perror ("could not open framebuffer");
+ return exit_code;
+ }
+
+ start_time = get_current_time ();
+ ply_video_buffer_fill_with_color (buffer, NULL,
+ 60.0/256.0, 110.0/256.0, 180.0/256.0, 1.0);
+ while ("we want to see ad-hoc animations")
+ {
+ animate_at_time (buffer, image, get_current_time () - start_time);
+ usleep ((long) (1000000 / FRAMES_PER_SECOND));
+ }
+ ply_video_buffer_close (buffer);
+ ply_video_buffer_free (buffer);
+
+ ply_image_free (image);
+
+ return exit_code;
+}
+
+#endif /* PLY_IMAGE_ENABLE_TEST */
-/* vim: ts=4 sw=2 expandtab autoindent cindent
+/* vim: ts=4 sw=2 expandtab autoindent cindent cino={1s,(0
* ply-video-buffer.c - framebuffer abstraction
*
* Copyright (C) 2006, 2007 Red Hat, Inc.
#define PLY_VIDEO_BUFFER_DEFAULT_FB_DEVICE_NAME "/dev/fb"
#endif
-#define MIN(a,b) (a <= b? a : b)
-#define MAX(a,b) (a >= b? a : b)
-#define CLAMP(a,b,c) (((a) > (c)) ? (c) : (((a) < (b)) ? (b) : (a)))
-
-typedef union
-{
- uint16_t *for_16bpp;
- uint32_t *for_32bpp;
- char *address;
-} PlyVideoBufferPixelLayout;
-
struct _PlyVideoBuffer
{
- char *device_name;
- int device_fd;
+ char *device_name;
+ int device_fd;
+
+ char *map_address;
+ size_t size;
+
+ uint32_t *shadow_buffer;
- PlyVideoBufferPixelLayout layout;
- size_t layout_size;
+ uint32_t red_bit_position;
+ uint32_t green_bit_position;
+ uint32_t blue_bit_position;
+ uint32_t alpha_bit_position;
- PlyVideoBufferPixelLayout shadow_layout;
+ uint32_t bits_for_red;
+ uint32_t bits_for_green;
+ uint32_t bits_for_blue;
+ uint32_t bits_for_alpha;
unsigned int bits_per_pixel;
unsigned int bytes_per_pixel;
static bool ply_video_buffer_open_device (PlyVideoBuffer *buffer);
static void ply_video_buffer_close_device (PlyVideoBuffer *buffer);
static bool ply_video_buffer_query_device (PlyVideoBuffer *buffer);
-static bool ply_video_buffer_map_to_layout (PlyVideoBuffer *buffer);
-static uint32_t ply_video_buffer_convert_color_to_pixel_value (
+static bool ply_video_buffer_map_to_device (PlyVideoBuffer *buffer);
+static uint_least32_t ply_video_buffer_pixel_value_to_device_pixel_value (
PlyVideoBuffer *buffer,
- uint8_t red,
- uint8_t green,
- uint8_t blue,
- uint8_t alpha);
+ uint32_t pixel_value);
+
static uint32_t ply_video_buffer_get_value_at_pixel (PlyVideoBuffer *buffer,
int x,
int y);
int y,
uint32_t pixel_value);
static void ply_video_buffer_blend_value_at_pixel (PlyVideoBuffer *buffer,
- int x,
- int y,
- uint32_t pixel_value);
+ int x,
+ int y,
+ uint32_t pixel_value);
static void ply_video_buffer_set_area_to_pixel_value (
PlyVideoBuffer *buffer,
static void ply_video_buffer_add_area_to_flush_area (PlyVideoBuffer *buffer,
PlyVideoBufferArea *area);
+static bool ply_video_buffer_copy_to_device (PlyVideoBuffer *buffer,
+ unsigned long x,
+ unsigned long y,
+ unsigned long width,
+ unsigned long height);
+
static bool ply_video_buffer_flush (PlyVideoBuffer *buffer);
static bool
{
assert (buffer != NULL);
- if (buffer->layout.address != MAP_FAILED)
+ if (buffer->map_address != MAP_FAILED)
{
- munmap (buffer->layout.address, buffer->layout_size);
- buffer->layout.address = MAP_FAILED;
+ munmap (buffer->map_address, buffer->size);
+ buffer->map_address = MAP_FAILED;
}
if (buffer->device_fd >= 0)
buffer->area.width = variable_screen_info.xres;
buffer->area.height = variable_screen_info.yres;
+ buffer->red_bit_position = variable_screen_info.red.offset;
+ buffer->bits_for_red = variable_screen_info.red.length;
+
+ buffer->green_bit_position = variable_screen_info.green.offset;
+ buffer->bits_for_green = variable_screen_info.green.length;
+
+ buffer->blue_bit_position = variable_screen_info.blue.offset;
+ buffer->bits_for_blue = variable_screen_info.blue.length;
+
+ buffer->alpha_bit_position = variable_screen_info.transp.offset;
+ buffer->bits_for_alpha = variable_screen_info.transp.length;
+
if (ioctl(buffer->device_fd, FBIOGET_FSCREENINFO, &fixed_screen_info) < 0)
{
return false;
}
bytes_per_row = fixed_screen_info.line_length;
- buffer->layout_size = buffer->area.height * bytes_per_row;
+ buffer->size = buffer->area.height * bytes_per_row;
buffer->bytes_per_pixel = bytes_per_row / buffer->area.width;
return true;
}
static bool
-ply_video_buffer_map_to_layout (PlyVideoBuffer *buffer)
+ply_video_buffer_map_to_device (PlyVideoBuffer *buffer)
{
assert (buffer != NULL);
assert (buffer->device_fd >= 0);
- assert (buffer->layout_size > 0);
+ assert (buffer->size > 0);
- buffer->layout.address = mmap (NULL, buffer->layout_size, PROT_WRITE,
- MAP_SHARED, buffer->device_fd, 0);
+ buffer->map_address = mmap (NULL, buffer->size, PROT_WRITE,
+ MAP_SHARED, buffer->device_fd, 0);
- return buffer->layout.address != MAP_FAILED;
+ return buffer->map_address != MAP_FAILED;
}
-static uint32_t
-ply_video_buffer_convert_color_to_pixel_value (PlyVideoBuffer *buffer,
- uint8_t red,
- uint8_t green,
- uint8_t blue,
- uint8_t alpha)
+static uint_least32_t
+ply_video_buffer_pixel_value_to_device_pixel_value (PlyVideoBuffer *buffer,
+ uint32_t pixel_value)
{
- uint32_t pixel_value;
+ uint8_t r, g, b, a;
- assert (buffer != NULL);
+ a = pixel_value >> 24;
+ a >>= (8 - buffer->bits_for_alpha);
- switch (buffer->bytes_per_pixel)
- {
- case 2:
+ r = (pixel_value >> 16) & 0xff;
+ r >>= (8 - buffer->bits_for_red);
- red >>= 3;
- green >>= 2;
- blue >>= 3;
+ g = (pixel_value >> 8) & 0xff;
+ g >>= (8 - buffer->bits_for_green);
- pixel_value = (red << 11) | (green << 5) | blue;
- break;
+ b = pixel_value & 0xff;
+ b >>= (8 - buffer->bits_for_blue);
- case 3:
- pixel_value = (red << 16) | (green << 8) | blue;
- break;
-
- case 4:
- pixel_value = (alpha << 24) | (red << 16) | (green << 8) | blue;
- break;
-
- default:
- pixel_value = 0;
- assert ((buffer->bytes_per_pixel == 2)
- || (buffer->bytes_per_pixel == 3)
- || (buffer->bytes_per_pixel == 4));
- break;
- }
-
- return pixel_value;
+ return ((a << buffer->alpha_bit_position)
+ | (r << buffer->red_bit_position)
+ | (g << buffer->green_bit_position)
+ | (b << buffer->blue_bit_position));
}
static uint32_t
int x,
int y)
{
- unsigned long bytes_per_row;
- unsigned long offset;
uint32_t pixel_value;
assert (buffer != NULL);
- switch (buffer->bytes_per_pixel)
- {
- case 2:
- pixel_value =
- buffer->shadow_layout.for_16bpp[y * buffer->area.width + x];
- break;
-
- case 3:
- bytes_per_row = buffer->bytes_per_pixel * buffer->area.width;
- offset = (y * bytes_per_row) + (x * buffer->bytes_per_pixel);
-
- memcpy (&pixel_value, buffer->shadow_layout.address + offset,
- buffer->bytes_per_pixel);
- pixel_value = ntohl (pixel_value);
- break;
-
- case 4:
- pixel_value =
- buffer->shadow_layout.for_16bpp[y * buffer->area.width + x];
- break;
-
- default:
- assert ((buffer->bytes_per_pixel == 2)
- || (buffer->bytes_per_pixel == 3)
- || (buffer->bytes_per_pixel == 4));
- break;
- }
+ pixel_value = buffer->shadow_buffer[y * buffer->area.width + x];
return pixel_value;
}
int y,
uint32_t pixel_value)
{
- unsigned long bytes_per_row;
- unsigned long offset;
-
assert (buffer != NULL);
- switch (buffer->bytes_per_pixel)
- {
- case 2:
- buffer->shadow_layout.for_16bpp[y * buffer->area.width + x] =
- (uint16_t) pixel_value;
- break;
-
- case 3:
- bytes_per_row = buffer->bytes_per_pixel * buffer->area.width;
- offset = (y * bytes_per_row) + (x * buffer->bytes_per_pixel);
-
- /* FIXME: endianess issues here I think
- */
- memcpy (buffer->shadow_layout.address + offset, &pixel_value,
- buffer->bytes_per_pixel);
- break;
-
- case 4:
- buffer->shadow_layout.for_32bpp[y * buffer->area.width + x] = pixel_value;
- break;
-
- default:
- assert ((buffer->bytes_per_pixel == 2)
- || (buffer->bytes_per_pixel == 3)
- || (buffer->bytes_per_pixel == 4));
- break;
- }
+ /* FIXME: endianess issues here I think
+ */
+ memcpy (&buffer->shadow_buffer[y * buffer->area.width + x],
+ &pixel_value, sizeof (uint32_t));
+}
+
+static uint32_t
+blend_two_pixel_values (uint32_t pixel_value_1,
+ uint32_t pixel_value_2)
+{
+ double alpha, red, green, blue;
+ double alpha_2, red_2, green_2, blue_2;
+
+ alpha = (double) (pixel_value_1 >> 24) / 255.0;
+ red = (double) ((pixel_value_1 >> 16) & 0xff) / 255.0;
+ green = (double) ((pixel_value_1 >> 8) & 0xff) / 255.0;
+ blue = (double) (pixel_value_1 & 0xff) / 255.0;
+
+ alpha_2 = (double) (pixel_value_2 >> 24) / 255.0;
+ red_2 = (double) ((pixel_value_2 >> 26) & 0xff) / 255.0;
+ green_2 = (double) ((pixel_value_2 >> 8) & 0xff) / 255.0;
+ blue_2 = (double) (pixel_value_2 & 0xff) / 255.0;
+
+ red = red + red_2 * (1.0 - alpha);
+ green = green + green_2 * (1.0 - alpha);
+ blue = blue + blue_2 * (1.0 - alpha);
+ alpha = alpha + alpha_2 * (1.0 - alpha);
+
+ return PLY_VIDEO_BUFFER_COLOR_TO_PIXEL_VALUE (red, green, blue, alpha);
}
static void
int y,
uint32_t pixel_value)
{
- uint32_t old_pixel_value;
- double old_red, old_green, old_blue, old_alpha;
- double new_red, new_green, new_blue, new_alpha;
- uint32_t new_pixel_value;
+ uint32_t old_pixel_value, new_pixel_value;
old_pixel_value = ply_video_buffer_get_value_at_pixel (buffer, x, y);
-
- old_alpha = (old_pixel_value >> 24) / 255.0;
- old_red = ((old_pixel_value >> 16) & 0xff) / 255.0;
- old_green = ((old_pixel_value >> 8) & 0xff) / 255.0;
- old_blue = (old_pixel_value & 0xff) / 255.0;
-
- new_alpha = ((pixel_value >> 24) & 0xff) / 255.0;
- new_red = ((pixel_value >> 16) & 0xff) / 255.0;
- new_green = ((pixel_value >> 8) & 0xff) / 255.0;
- new_blue = (pixel_value & 0xff) / 255.0;
-
- new_red = new_red + old_red * (1.0 - new_alpha);
- new_green = new_green + old_green * (1.0 - new_alpha);
- new_blue = new_blue + old_blue * (1.0 - new_alpha);
- new_alpha = new_alpha + (1.0 - old_alpha);
-
- new_red = CLAMP (new_red * 255.0, 0, 255.0);
- new_green = CLAMP (new_green * 255.0, 0, 255.0);
- new_blue = CLAMP (new_blue * 255.0, 0, 255.0);
- new_alpha = CLAMP (new_alpha * 255.0, 0, 255.0);
-
- new_pixel_value = (((uint8_t) new_alpha) << 24)
- | (((uint8_t) new_red) << 16)
- | (((uint8_t) new_green) << 8)
- | ((uint8_t) new_blue);
+ new_pixel_value = blend_two_pixel_values (pixel_value, old_pixel_value);
ply_video_buffer_set_value_at_pixel (buffer, x, y, new_pixel_value);
}
buffer->area_to_flush.height = MAX (buffer->area_to_flush.height, area->height);
}
+static bool
+ply_video_buffer_copy_to_device (PlyVideoBuffer *buffer,
+ unsigned long x,
+ unsigned long y,
+ unsigned long width,
+ unsigned long height)
+{
+ unsigned long row, column;
+ unsigned long start_offset;
+ unsigned long size;
+
+ unsigned long bytes_per_row;
+
+ bytes_per_row = buffer->area.width * buffer->bytes_per_pixel;
+ start_offset = y * bytes_per_row + x * buffer->bytes_per_pixel;
+ size = width * height * buffer->bytes_per_pixel;
+
+ for (row = y; row < y + height; row++)
+ {
+ for (column = x; column < x + width; column++)
+ {
+ uint32_t pixel_value;
+ uint_least32_t device_pixel_value;
+ unsigned long offset;
+
+ pixel_value = buffer->shadow_buffer[width * row + column];
+
+ device_pixel_value =
+ ply_video_buffer_pixel_value_to_device_pixel_value (buffer,
+ pixel_value);
+
+ offset = row * bytes_per_row + column * buffer->bytes_per_pixel;
+
+ memcpy (buffer->map_address + offset, &device_pixel_value,
+ buffer->bits_per_pixel);
+ }
+ }
+
+ if (msync (buffer->map_address + start_offset, size, MS_SYNC) < 0)
+ return false;
+
+ return true;
+}
+
static bool
ply_video_buffer_flush (PlyVideoBuffer *buffer)
{
if (buffer->is_paused)
return true;
- bytes_per_row = buffer->bytes_per_pixel * buffer->area_to_flush.width;
- start_offset = (buffer->area_to_flush.y * bytes_per_row)
- + (buffer->area_to_flush.x * buffer->bytes_per_pixel);
- size = buffer->area_to_flush.width * buffer->area_to_flush.height
- * buffer->bytes_per_pixel;
+ start_offset = (buffer->area_to_flush.y * 4 * buffer->area_to_flush.width)
+ + (buffer->area_to_flush.x * 4);
+ size = buffer->area_to_flush.width * buffer->area_to_flush.height;
- memcpy (buffer->layout.address + start_offset,
- buffer->shadow_layout.address + start_offset, size);
- if (msync (buffer->layout.address + start_offset, size, MS_SYNC) < 0)
+ if (!ply_video_buffer_copy_to_device (buffer,
+ buffer->area_to_flush.x,
+ buffer->area_to_flush.y,
+ buffer->area_to_flush.width,
+ buffer->area_to_flush.height))
return false;
buffer->area_to_flush.x = 0;
buffer->device_name =
strdup (PLY_VIDEO_BUFFER_DEFAULT_FB_DEVICE_NAME);
- buffer->layout.address = MAP_FAILED;
- buffer->shadow_layout.address = NULL;
+ buffer->map_address = MAP_FAILED;
+ buffer->shadow_buffer = NULL;
buffer->is_paused = false;
ply_video_buffer_close (buffer);
free (buffer->device_name);
- free (buffer->shadow_layout.address);
+ free (buffer->shadow_buffer);
free (buffer);
}
goto out;
}
- if (!ply_video_buffer_map_to_layout (buffer))
+ if (!ply_video_buffer_map_to_device (buffer))
{
goto out;
}
- buffer->shadow_layout.address =
- realloc (buffer->shadow_layout.address,
- buffer->layout_size);
- memset (buffer->shadow_layout.address, 0, buffer->layout_size);
+ buffer->shadow_buffer =
+ realloc (buffer->shadow_buffer,
+ 4 * buffer->area.width * buffer->area.height);
+ memset (buffer->shadow_buffer, 0,
+ 4 * buffer->area.width * buffer->area.height);
ply_video_buffer_fill_with_color (buffer, NULL, 0.0, 0.0, 0.0, 1.0);
is_open = true;
ply_video_buffer_device_is_open (PlyVideoBuffer *buffer)
{
assert (buffer != NULL);
- return buffer->device_fd >= 0 && buffer->layout.address != MAP_FAILED;
+ return buffer->device_fd >= 0 && buffer->map_address != MAP_FAILED;
}
char *
green *= alpha;
blue *= alpha;
- pixel_value =
- ply_video_buffer_convert_color_to_pixel_value (buffer,
- CLAMP (red * 255.0, 0, 255),
- CLAMP (green * 255.0, 0, 255),
- CLAMP (blue * 255.0, 0, 255),
- CLAMP (alpha * 255.0, 0, 255));
+ pixel_value = PLY_VIDEO_BUFFER_COLOR_TO_PIXEL_VALUE (red, green, blue, alpha);
if (abs (alpha - 1.0) <= DBL_MIN)
ply_video_buffer_set_area_to_pixel_value (buffer, area, pixel_value);
}
bool
-ply_video_buffer_fill_with_argb32_data (PlyVideoBuffer *buffer,
- PlyVideoBufferArea *area,
- unsigned long x,
- unsigned long y,
- unsigned long width,
- unsigned long height,
- uint32_t *data)
+ply_video_buffer_fill_with_argb32_data_at_opacity (PlyVideoBuffer *buffer,
+ PlyVideoBufferArea *area,
+ unsigned long x,
+ unsigned long y,
+ unsigned long width,
+ unsigned long height,
+ uint32_t *data,
+ double opacity)
{
long row, column;
+ bool is_translucent;
+ uint32_t alpha_pixel_value;
assert (buffer != NULL);
assert (ply_video_buffer_device_is_open (buffer));
if (area == NULL)
area = &buffer->area;
+ if (abs (opacity - 1.0) > DBL_MIN)
+ {
+ uint8_t alpha;
+ alpha_pixel_value = 0x00000000;
+ alpha = (uint8_t) CLAMP (opacity * 255.0, 0.0, 255.0);
+ alpha_pixel_value |= alpha << 24;
+ is_translucent = true;
+ }
+ else
+ is_translucent = false;
+
for (row = y; row < y + height; row++)
{
for (column = x; column < x + width; column++)
{
- uint8_t alpha;
+ uint32_t pixel_value;
- alpha = data[width * row + column] >> 24;
- if (alpha == 0xff)
- ply_video_buffer_set_value_at_pixel (buffer,
+ pixel_value = data[width * row + column];
+
+ if (is_translucent)
+ {
+ pixel_value =
+ blend_two_pixel_values (alpha_pixel_value, pixel_value);
+ }
+ ply_video_buffer_blend_value_at_pixel (buffer,
area->x + (column - x),
area->y + (row - y),
- data[width * row + column]);
- else
- ply_video_buffer_blend_value_at_pixel (buffer,
- area->x + (column - x),
- area->y + (row - y),
- data[width * row + column]);
+ pixel_value);
}
}
return ply_video_buffer_flush (buffer);
}
+bool
+ply_video_buffer_fill_with_argb32_data (PlyVideoBuffer *buffer,
+ PlyVideoBufferArea *area,
+ unsigned long x,
+ unsigned long y,
+ unsigned long width,
+ unsigned long height,
+ uint32_t *data)
+{
+ return ply_video_buffer_fill_with_argb32_data_at_opacity (buffer, area,
+ x, y, width,
+ height, data, 1.0);
+}
+
#ifdef PLY_VIDEO_BUFFER_ENABLE_TEST
#include <math.h>
for (y = 0; y < 768; y++)
{
- int blue_offset;
+ int blue_bit_position;
uint8_t red, green, blue, alpha;
- blue_offset = (int) 64 * sin (time) + (255 - 64);
- blue = rand () % blue_offset;
+ blue_bit_position = (int) 64 * sin (time) + (255 - 64);
+ blue = rand () % blue_bit_position;
for (x = 0; x < 1024; x++)
{
alpha = 0xff;