mirror of
https://gitlab.freedesktop.org/plymouth/plymouth.git
synced 2026-05-08 12:28:12 +02:00
pixel-buffer: Add the concept of device rotation
On some devices the LCD panel is mounted in the casing in such a way that the up/top side of the panel does not match with the top side of the device (e.g. it is mounted upside-down). This commit adds support to the ply-pixel-buffer code to create buffers which take device rotation into account and which will rotate the picture to compensate. https://bugs.freedesktop.org/show_bug.cgi?id=104714
This commit is contained in:
parent
da27e42316
commit
0e4e268844
2 changed files with 110 additions and 8 deletions
|
|
@ -50,6 +50,7 @@ struct _ply_pixel_buffer
|
|||
ply_region_t *updated_areas; /* in device pixels */
|
||||
uint32_t is_opaque : 1;
|
||||
int device_scale;
|
||||
int device_rotation;
|
||||
};
|
||||
|
||||
static inline void ply_pixel_buffer_blend_value_at_pixel (ply_pixel_buffer_t *buffer,
|
||||
|
|
@ -153,6 +154,52 @@ make_pixel_value_translucent (uint32_t pixel_value,
|
|||
return (alpha << 24) | (red << 16) | (green << 8) | blue;
|
||||
}
|
||||
|
||||
static inline void ply_pixel_buffer_set_pixel (ply_pixel_buffer_t *buffer,
|
||||
int x,
|
||||
int y,
|
||||
uint32_t pixel_value)
|
||||
{
|
||||
switch (buffer->device_rotation) {
|
||||
case PLY_PIXEL_BUFFER_ROTATE_UPRIGHT:
|
||||
buffer->bytes[y * buffer->area.width + x] = pixel_value;
|
||||
break;
|
||||
case PLY_PIXEL_BUFFER_ROTATE_UPSIDE_DOWN:
|
||||
x = (buffer->area.width - 1) - x;
|
||||
y = (buffer->area.height - 1) - y;
|
||||
buffer->bytes[y * buffer->area.width + x] = pixel_value;
|
||||
break;
|
||||
case PLY_PIXEL_BUFFER_ROTATE_CLOCKWISE:
|
||||
y = (buffer->area.height - 1) - y;
|
||||
buffer->bytes[x * buffer->area.height + y] = pixel_value;
|
||||
break;
|
||||
case PLY_PIXEL_BUFFER_ROTATE_COUNTER_CLOCKWISE:
|
||||
x = (buffer->area.width - 1) - x;
|
||||
buffer->bytes[x * buffer->area.height + y] = pixel_value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t ply_pixel_buffer_get_pixel (ply_pixel_buffer_t *buffer,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
switch (buffer->device_rotation) {
|
||||
case PLY_PIXEL_BUFFER_ROTATE_UPRIGHT:
|
||||
return buffer->bytes[y * buffer->area.width + x];
|
||||
case PLY_PIXEL_BUFFER_ROTATE_UPSIDE_DOWN:
|
||||
x = (buffer->area.width - 1) - x;
|
||||
y = (buffer->area.height - 1) - y;
|
||||
return buffer->bytes[y * buffer->area.width + x];
|
||||
case PLY_PIXEL_BUFFER_ROTATE_CLOCKWISE:
|
||||
y = (buffer->area.height - 1) - y;
|
||||
return buffer->bytes[x * buffer->area.height + y];
|
||||
case PLY_PIXEL_BUFFER_ROTATE_COUNTER_CLOCKWISE:
|
||||
x = (buffer->area.width - 1) - x;
|
||||
return buffer->bytes[x * buffer->area.height + y];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ply_pixel_buffer_blend_value_at_pixel (ply_pixel_buffer_t *buffer,
|
||||
int x,
|
||||
|
|
@ -162,12 +209,12 @@ ply_pixel_buffer_blend_value_at_pixel (ply_pixel_buffer_t *buffer,
|
|||
uint32_t old_pixel_value;
|
||||
|
||||
if ((pixel_value >> 24) != 0xff) {
|
||||
old_pixel_value = buffer->bytes[y * buffer->area.width + x];
|
||||
old_pixel_value = ply_pixel_buffer_get_pixel (buffer, x, y);
|
||||
|
||||
pixel_value = blend_two_pixel_values (pixel_value, old_pixel_value);
|
||||
}
|
||||
|
||||
buffer->bytes[y * buffer->area.width + x] = pixel_value;
|
||||
ply_pixel_buffer_set_pixel (buffer, x, y, pixel_value);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -222,6 +269,35 @@ ply_pixel_buffer_crop_area_to_clip_area (ply_pixel_buffer_t *buffer,
|
|||
}
|
||||
}
|
||||
|
||||
static void ply_pixel_buffer_add_updated_area (ply_pixel_buffer_t *buffer,
|
||||
ply_rectangle_t *area)
|
||||
{
|
||||
ply_rectangle_t updated_area = *area;
|
||||
|
||||
switch (buffer->device_rotation) {
|
||||
case PLY_PIXEL_BUFFER_ROTATE_UPRIGHT:
|
||||
break;
|
||||
case PLY_PIXEL_BUFFER_ROTATE_UPSIDE_DOWN:
|
||||
updated_area.x = buffer->area.width - area->width - area->x;
|
||||
updated_area.y = buffer->area.height - area->height - area->y;
|
||||
break;
|
||||
case PLY_PIXEL_BUFFER_ROTATE_CLOCKWISE:
|
||||
updated_area.x = buffer->area.height - area->height - area->y;
|
||||
updated_area.y = area->x;
|
||||
updated_area.height = area->width;
|
||||
updated_area.width = area->height;
|
||||
break;
|
||||
case PLY_PIXEL_BUFFER_ROTATE_COUNTER_CLOCKWISE:
|
||||
updated_area.x = area->y;
|
||||
updated_area.y = buffer->area.width - area->width - area->x;
|
||||
updated_area.height = area->width;
|
||||
updated_area.width = area->height;
|
||||
break;
|
||||
}
|
||||
|
||||
ply_region_add_rectangle (buffer->updated_areas, &updated_area);
|
||||
}
|
||||
|
||||
static void
|
||||
ply_pixel_buffer_fill_area_with_pixel_value (ply_pixel_buffer_t *buffer,
|
||||
ply_rectangle_t *fill_area,
|
||||
|
|
@ -251,7 +327,7 @@ ply_pixel_buffer_fill_area_with_pixel_value (ply_pixel_buffer_t *buffer,
|
|||
}
|
||||
}
|
||||
|
||||
ply_region_add_rectangle (buffer->updated_areas, &cropped_area);
|
||||
ply_pixel_buffer_add_updated_area (buffer, &cropped_area);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -281,9 +357,24 @@ ply_pixel_buffer_pop_clip_area (ply_pixel_buffer_t *buffer)
|
|||
ply_pixel_buffer_t *
|
||||
ply_pixel_buffer_new (unsigned long width,
|
||||
unsigned long height)
|
||||
{
|
||||
return ply_pixel_buffer_new_with_device_rotation (
|
||||
width, height, PLY_PIXEL_BUFFER_ROTATE_UPRIGHT);
|
||||
}
|
||||
|
||||
ply_pixel_buffer_t *
|
||||
ply_pixel_buffer_new_with_device_rotation (unsigned long width,
|
||||
unsigned long height,
|
||||
int device_rotation)
|
||||
{
|
||||
ply_pixel_buffer_t *buffer;
|
||||
|
||||
if (device_rotation >= PLY_PIXEL_BUFFER_ROTATE_CLOCKWISE) {
|
||||
unsigned long tmp = width;
|
||||
width = height;
|
||||
height = tmp;
|
||||
}
|
||||
|
||||
buffer = calloc (1, sizeof(ply_pixel_buffer_t));
|
||||
|
||||
buffer->updated_areas = ply_region_new ();
|
||||
|
|
@ -292,6 +383,7 @@ ply_pixel_buffer_new (unsigned long width,
|
|||
buffer->area.height = height;
|
||||
buffer->logical_area = buffer->area;
|
||||
buffer->device_scale = 1;
|
||||
buffer->device_rotation = device_rotation;
|
||||
|
||||
buffer->clip_areas = ply_list_new ();
|
||||
ply_pixel_buffer_push_clip_area (buffer, &buffer->area);
|
||||
|
|
@ -447,7 +539,7 @@ ply_pixel_buffer_fill_with_gradient (ply_pixel_buffer_t *buffer,
|
|||
|
||||
for (y = buffer->area.y; y < buffer->area.y + buffer->area.height; y++) {
|
||||
if (cropped_area.y <= y && y < cropped_area.y + cropped_area.height) {
|
||||
if (cropped_area.width < UNROLLED_PIXEL_COUNT) {
|
||||
if (cropped_area.width < UNROLLED_PIXEL_COUNT || buffer->device_rotation) {
|
||||
for (x = cropped_area.x; x < cropped_area.x + cropped_area.width; x++) {
|
||||
pixel = 0xff000000;
|
||||
RANDOMIZE (noise);
|
||||
|
|
@ -457,7 +549,7 @@ ply_pixel_buffer_fill_with_gradient (ply_pixel_buffer_t *buffer,
|
|||
RANDOMIZE (noise);
|
||||
pixel |= (((blue + noise) & COLOR_MASK) >> BLUE_SHIFT);
|
||||
|
||||
buffer->bytes[y * buffer->area.width + x] = pixel;
|
||||
ply_pixel_buffer_set_pixel (buffer, x, y, pixel);
|
||||
}
|
||||
} else {
|
||||
uint32_t shaded_set[UNROLLED_PIXEL_COUNT];
|
||||
|
|
@ -485,7 +577,7 @@ ply_pixel_buffer_fill_with_gradient (ply_pixel_buffer_t *buffer,
|
|||
blue += blue_step;
|
||||
}
|
||||
|
||||
ply_region_add_rectangle (buffer->updated_areas, &cropped_area);
|
||||
ply_pixel_buffer_add_updated_area (buffer, &cropped_area);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -671,7 +763,7 @@ ply_pixel_buffer_fill_with_argb32_data_at_opacity_with_clip_and_scale (ply_pixel
|
|||
}
|
||||
}
|
||||
|
||||
ply_region_add_rectangle (buffer->updated_areas, &cropped_area);
|
||||
ply_pixel_buffer_add_updated_area (buffer, &cropped_area);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -756,7 +848,8 @@ ply_pixel_buffer_fill_with_buffer_at_opacity_with_clip (ply_pixel_buffer_t *canv
|
|||
|
||||
/* Fast path to memcpy if we need no blending or scaling */
|
||||
if (opacity == 1.0 && ply_pixel_buffer_is_opaque (source) &&
|
||||
canvas->device_scale == source->device_scale) {
|
||||
canvas->device_scale == source->device_scale &&
|
||||
canvas->device_rotation == PLY_PIXEL_BUFFER_ROTATE_UPRIGHT) {
|
||||
ply_rectangle_t cropped_area;
|
||||
|
||||
cropped_area.x = x_offset;
|
||||
|
|
|
|||
|
|
@ -37,9 +37,18 @@ typedef struct _ply_pixel_buffer ply_pixel_buffer_t;
|
|||
| ((uint8_t) (CLAMP (g * 255.0, 0.0, 255.0)) << 8) \
|
||||
| ((uint8_t) (CLAMP (b * 255.0, 0.0, 255.0))))
|
||||
|
||||
#define PLY_PIXEL_BUFFER_ROTATE_UPRIGHT 0
|
||||
#define PLY_PIXEL_BUFFER_ROTATE_UPSIDE_DOWN 1
|
||||
#define PLY_PIXEL_BUFFER_ROTATE_CLOCKWISE 2
|
||||
#define PLY_PIXEL_BUFFER_ROTATE_COUNTER_CLOCKWISE 3
|
||||
|
||||
#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
|
||||
ply_pixel_buffer_t *ply_pixel_buffer_new (unsigned long width,
|
||||
unsigned long height);
|
||||
ply_pixel_buffer_t *
|
||||
ply_pixel_buffer_new_with_device_rotation (unsigned long width,
|
||||
unsigned long height,
|
||||
int device_rotation);
|
||||
void ply_pixel_buffer_free (ply_pixel_buffer_t *buffer);
|
||||
void ply_pixel_buffer_get_size (ply_pixel_buffer_t *buffer,
|
||||
ply_rectangle_t *size);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue