Commit a34cb719 authored by Maarten Lankhorst's avatar Maarten Lankhorst Committed by Bryce Harrington

Add support for RGBA128F and RGB96F formats.

IGT wants to add support for planes with a bit depth >10, which
requires a higher precision format than we have currently.

I'm using RGBA as format, because of its existence in OpenGL.
With the new formats we can directly convert our bytes to half float,
or multiply a colro vector with a matrix to go to the Y'CbCr colorspace.

This requires pixman 0.36.0, so bump the version requirement.
Signed-off-by: default avatarMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Reviewed-by: Bryce Harrington's avatarBryce Harrington <bryce@bryceharrington.org>
parent 87c1c191
......@@ -685,7 +685,7 @@ CAIRO_ENABLE(test_surfaces, test surfaces, no)
dnl ===========================================================================
CAIRO_ENABLE_SURFACE_BACKEND(image, image, always, [
pixman_REQUIRES="pixman-1 >= 0.30.0"
pixman_REQUIRES="pixman-1 >= 0.36.0"
PKG_CHECK_MODULES(pixman, $pixman_REQUIRES, ,
[use_image="no (requires $pixman_REQUIRES https://cairographics.org/releases/)"])
image_REQUIRES=$pixman_REQUIRES
......
......@@ -92,6 +92,8 @@ direct (cairo_t *cr, int width, int height, int loops)
case CAIRO_FORMAT_RGB24:
case CAIRO_FORMAT_RGB30:
case CAIRO_FORMAT_ARGB32: bpp = 32; break;
case CAIRO_FORMAT_RGB96F: bpp = 96; break;
case CAIRO_FORMAT_RGBA128F: bpp = 128; break;
}
cairo_perf_timer_start ();
......
......@@ -51,6 +51,8 @@ pixel_direct (cairo_t *cr, int width, int height, int loops)
case CAIRO_FORMAT_RGB24:
case CAIRO_FORMAT_RGB30:
case CAIRO_FORMAT_ARGB32: bpp = 32; break;
case CAIRO_FORMAT_RGB96F: bpp = 96; break;
case CAIRO_FORMAT_RGBA128F: bpp = 128; break;
}
cairo_perf_timer_start ();
......
......@@ -131,6 +131,12 @@ _cairo_debug_check_image_surface_is_defined (const cairo_surface_t *surface)
case CAIRO_FORMAT_ARGB32:
width = image->width*4;
break;
case CAIRO_FORMAT_RGB96F:
width = image->width*12;
break;
case CAIRO_FORMAT_RGBA128F:
width = image->width*16;
break;
case CAIRO_FORMAT_INVALID:
default:
/* XXX compute width from pixman bpp */
......
......@@ -2845,6 +2845,8 @@ inplace_renderer_init (cairo_image_span_renderer_t *r,
case CAIRO_FORMAT_A1:
case CAIRO_FORMAT_RGB16_565:
case CAIRO_FORMAT_RGB30:
case CAIRO_FORMAT_RGB96F:
case CAIRO_FORMAT_RGBA128F:
case CAIRO_FORMAT_INVALID:
default: break;
}
......@@ -2860,6 +2862,8 @@ inplace_renderer_init (cairo_image_span_renderer_t *r,
case CAIRO_FORMAT_A1:
case CAIRO_FORMAT_RGB16_565:
case CAIRO_FORMAT_RGB30:
case CAIRO_FORMAT_RGB96F:
case CAIRO_FORMAT_RGBA128F:
case CAIRO_FORMAT_INVALID:
default: break;
}
......
......@@ -455,6 +455,7 @@ static pixman_image_t *
_pixel_to_solid (cairo_image_surface_t *image, int x, int y)
{
uint32_t pixel;
float *rgba;
pixman_color_t color;
TRACE ((stderr, "%s\n", __FUNCTION__));
......@@ -523,6 +524,32 @@ _pixel_to_solid (cairo_image_surface_t *image, int x, int y)
color.green = (pixel >> 8 & 0xff) | (pixel & 0xff00);
color.blue = (pixel & 0xff) | (pixel << 8 & 0xff00);
return pixman_image_create_solid_fill (&color);
case CAIRO_FORMAT_RGB96F:
case CAIRO_FORMAT_RGBA128F:
if (image->format == CAIRO_FORMAT_RGBA128F)
{
rgba = (float *)&image->data[y * image->stride + 16 * x];
color.alpha = 65535.f * rgba[3];
if (color.alpha == 0)
return _pixman_transparent_image ();
}
else
{
rgba = (float *)&image->data[y * image->stride + 12 * x];
color.alpha = 0xffff;
}
if (color.alpha == 0xffff && rgba[0] == 0.f && rgba[1] == 0.f && rgba[2] == 0.f)
return _pixman_black_image ();
if (color.alpha == 0xffff && rgba[0] == 1.f && rgba[1] == 1.f && rgba[2] == 1.f)
return _pixman_white_image ();
color.red = rgba[0] * 65535.f;
color.green = rgba[1] * 65535.f;
color.blue = rgba[2] * 65535.f;
return pixman_image_create_solid_fill (&color);
}
}
......
......@@ -93,6 +93,10 @@ cairo_format_t
_cairo_format_from_pixman_format (pixman_format_code_t pixman_format)
{
switch (pixman_format) {
case PIXMAN_rgba_float:
return CAIRO_FORMAT_RGBA128F;
case PIXMAN_rgb_float:
return CAIRO_FORMAT_RGB96F;
case PIXMAN_a8r8g8b8:
return CAIRO_FORMAT_ARGB32;
case PIXMAN_x2r10g10b10:
......@@ -322,6 +326,12 @@ _cairo_format_to_pixman_format_code (cairo_format_t format)
case CAIRO_FORMAT_RGB16_565:
ret = PIXMAN_r5g6b5;
break;
case CAIRO_FORMAT_RGB96F:
ret = PIXMAN_rgb_float;
break;
case CAIRO_FORMAT_RGBA128F:
ret = PIXMAN_rgba_float;
break;
case CAIRO_FORMAT_ARGB32:
case CAIRO_FORMAT_INVALID:
default:
......@@ -693,8 +703,10 @@ _cairo_format_from_content (cairo_content_t content)
_cairo_content_from_format (cairo_format_t format)
{
switch (format) {
case CAIRO_FORMAT_RGBA128F:
case CAIRO_FORMAT_ARGB32:
return CAIRO_CONTENT_COLOR_ALPHA;
case CAIRO_FORMAT_RGB96F:
case CAIRO_FORMAT_RGB30:
return CAIRO_CONTENT_COLOR;
case CAIRO_FORMAT_RGB24:
......@@ -716,6 +728,10 @@ _cairo_content_from_format (cairo_format_t format)
_cairo_format_bits_per_pixel (cairo_format_t format)
{
switch (format) {
case CAIRO_FORMAT_RGBA128F:
return 128;
case CAIRO_FORMAT_RGB96F:
return 96;
case CAIRO_FORMAT_ARGB32:
case CAIRO_FORMAT_RGB30:
case CAIRO_FORMAT_RGB24:
......
......@@ -265,6 +265,8 @@ write_png (cairo_surface_t *surface,
break;
case CAIRO_FORMAT_INVALID:
case CAIRO_FORMAT_RGB16_565:
case CAIRO_FORMAT_RGB96F:
case CAIRO_FORMAT_RGBA128F:
default:
status = _cairo_error (CAIRO_STATUS_INVALID_FORMAT);
goto BAIL4;
......
......@@ -871,6 +871,8 @@ static const char *
_format_to_string (cairo_format_t format)
{
switch (format) {
case CAIRO_FORMAT_RGBA128F: return "RGBA128F";
case CAIRO_FORMAT_RGB96F: return "RGB96F";
case CAIRO_FORMAT_ARGB32: return "ARGB32";
case CAIRO_FORMAT_RGB30: return "RGB30";
case CAIRO_FORMAT_RGB24: return "RGB24";
......@@ -1315,6 +1317,18 @@ _write_image_surface (cairo_output_stream_t *output,
data += stride;
}
break;
case CAIRO_FORMAT_RGB96F:
for (row = image->height; row--; ) {
_cairo_output_stream_write (output, data, 12*width);
data += stride;
}
break;
case CAIRO_FORMAT_RGBA128F:
for (row = image->height; row--; ) {
_cairo_output_stream_write (output, data, 16*width);
data += stride;
}
break;
case CAIRO_FORMAT_INVALID:
default:
ASSERT_NOT_REACHED;
......@@ -1421,6 +1435,12 @@ _emit_image_surface (cairo_script_surface_t *surface,
case CAIRO_FORMAT_ARGB32:
len = clone->width * 4;
break;
case CAIRO_FORMAT_RGB96F:
len = clone->width * 12;
break;
case CAIRO_FORMAT_RGBA128F:
len = clone->width * 16;
break;
case CAIRO_FORMAT_INVALID:
default:
ASSERT_NOT_REACHED;
......
......@@ -383,6 +383,10 @@ _cairo_xlib_display_get_xrender_format_for_pixman(cairo_xlib_display_t *display,
XRenderPictFormat tmpl;
int mask;
/* No equivalent in X11 yet. */
if (format == PIXMAN_rgba_float || format == PIXMAN_rgb_float)
return NULL;
#define MASK(x) ((1<<(x))-1)
tmpl.depth = PIXMAN_FORMAT_DEPTH(format);
......@@ -510,6 +514,14 @@ _cairo_xlib_display_get_xrender_format (cairo_xlib_display_t *display,
xrender_format = _cairo_xlib_display_get_xrender_format_for_pixman(display,
PIXMAN_x2r10g10b10);
break;
case CAIRO_FORMAT_RGBA128F:
xrender_format = _cairo_xlib_display_get_xrender_format_for_pixman(display,
PIXMAN_rgba_float);
break;
case CAIRO_FORMAT_RGB96F:
xrender_format = _cairo_xlib_display_get_xrender_format_for_pixman(display,
PIXMAN_rgb_float);
break;
case CAIRO_FORMAT_INVALID:
default:
ASSERT_NOT_REACHED;
......
......@@ -405,6 +405,8 @@ typedef enum _cairo_content {
* with red in the upper 5 bits, then green in the middle
* 6 bits, and blue in the lower 5 bits. (Since 1.2)
* @CAIRO_FORMAT_RGB30: like RGB24 but with 10bpc. (Since 1.12)
* @CAIRO_FORMAT_RGB96F: 3 floats, R, G, B. (Since 1.16)
* @CAIRO_FORMAT_RGBA128F: 4 floats, R, G, B, A. (Since 1.16)
*
* #cairo_format_t is used to identify the memory format of
* image data.
......@@ -420,7 +422,9 @@ typedef enum _cairo_format {
CAIRO_FORMAT_A8 = 2,
CAIRO_FORMAT_A1 = 3,
CAIRO_FORMAT_RGB16_565 = 4,
CAIRO_FORMAT_RGB30 = 5
CAIRO_FORMAT_RGB30 = 5,
CAIRO_FORMAT_RGB96F = 6,
CAIRO_FORMAT_RGBA128F = 7
} cairo_format_t;
......
......@@ -1536,7 +1536,7 @@ _cairo_surface_release_device_reference (cairo_surface_t *surface);
* in cairo-xlib-surface.c--again see -Wswitch-enum).
*/
#define CAIRO_FORMAT_VALID(format) ((format) >= CAIRO_FORMAT_ARGB32 && \
(format) <= CAIRO_FORMAT_RGB30)
(format) <= CAIRO_FORMAT_RGBA128F)
/* pixman-required stride alignment in bytes. */
#define CAIRO_STRIDE_ALIGNMENT (sizeof (uint32_t))
......
......@@ -201,6 +201,8 @@ write_ppm (cairo_surface_t *surface, int fd)
case CAIRO_FORMAT_A1:
case CAIRO_FORMAT_RGB16_565:
case CAIRO_FORMAT_RGB30:
case CAIRO_FORMAT_RGB96F:
case CAIRO_FORMAT_RGBA128F:
case CAIRO_FORMAT_INVALID:
default:
return "unhandled image format";
......
......@@ -45,6 +45,8 @@ set_pixel_black(uint8_t *data, int stride,
case CAIRO_FORMAT_RGB16_565:
*(uint16_t *)(data + y * stride + 2*x) = black_pixel;
break;
case CAIRO_FORMAT_RGBA128F:
case CAIRO_FORMAT_RGB96F:
case CAIRO_FORMAT_RGB30:
case CAIRO_FORMAT_A8:
case CAIRO_FORMAT_A1:
......
......@@ -60,6 +60,8 @@ format_to_string (cairo_format_t format)
case CAIRO_FORMAT_RGB24: return "rgb24";
case CAIRO_FORMAT_RGB30: return "rgb30";
case CAIRO_FORMAT_ARGB32: return "argb32";
case CAIRO_FORMAT_RGB96F: return "rgb96f";
case CAIRO_FORMAT_RGBA128F: return "rgba128f";
case CAIRO_FORMAT_INVALID:
default: return "???";
}
......
......@@ -2967,6 +2967,12 @@ _image_read_raw (csi_t *ctx,
case CAIRO_FORMAT_ARGB32:
instride = rowlen = 4 * width;
break;
case CAIRO_FORMAT_RGB96F:
instride = rowlen = 12 * width;
break;
case CAIRO_FORMAT_RGBA128F:
instride = rowlen = 16 * width;
break;
}
len = rowlen * height;
......@@ -3066,6 +3072,8 @@ err_decompress:
#endif
}
break;
case CAIRO_FORMAT_RGB96F:
case CAIRO_FORMAT_RGBA128F:
case CAIRO_FORMAT_RGB30:
case CAIRO_FORMAT_INVALID:
case CAIRO_FORMAT_ARGB32:
......@@ -3155,6 +3163,8 @@ err_decompress:
#endif
}
break;
case CAIRO_FORMAT_RGBA128F:
case CAIRO_FORMAT_RGB96F:
case CAIRO_FORMAT_RGB30:
case CAIRO_FORMAT_INVALID:
case CAIRO_FORMAT_ARGB32:
......@@ -3191,6 +3201,8 @@ err_decompress:
case CAIRO_FORMAT_A8:
break;
case CAIRO_FORMAT_RGBA128F:
case CAIRO_FORMAT_RGB96F:
case CAIRO_FORMAT_RGB30:
case CAIRO_FORMAT_RGB24:
case CAIRO_FORMAT_INVALID:
......
......@@ -1510,6 +1510,8 @@ _format_to_string (cairo_format_t format)
#define f(name) case CAIRO_FORMAT_ ## name: return #name
switch (format) {
f(INVALID);
f(RGBA128F);
f(RGB96F);
f(ARGB32);
f(RGB30);
f(RGB24);
......@@ -1527,8 +1529,10 @@ _format_to_content_string (cairo_format_t format)
switch (format) {
case CAIRO_FORMAT_INVALID:
return "INVALID";
case CAIRO_FORMAT_RGBA128F:
case CAIRO_FORMAT_ARGB32:
return "COLOR_ALPHA";
case CAIRO_FORMAT_RGB96F:
case CAIRO_FORMAT_RGB30:
case CAIRO_FORMAT_RGB24:
case CAIRO_FORMAT_RGB16_565:
......@@ -1673,6 +1677,8 @@ _emit_image (cairo_surface_t *image,
case CAIRO_FORMAT_RGB30:
case CAIRO_FORMAT_INVALID:
case CAIRO_FORMAT_ARGB32: len = 4*width; break;
case CAIRO_FORMAT_RGB96F: len = 12*width; break;
case CAIRO_FORMAT_RGBA128F: len = 16*width; break;
}
_trace_printf (" /source ");
......@@ -1696,6 +1702,8 @@ _emit_image (cairo_surface_t *image,
case CAIRO_FORMAT_RGB16_565:
case CAIRO_FORMAT_RGB30:
case CAIRO_FORMAT_ARGB32:
case CAIRO_FORMAT_RGB96F:
case CAIRO_FORMAT_RGBA128F:
for (row = height; row--; ) {
_write_data (&stream, data, len);
data += stride;
......@@ -1754,6 +1762,8 @@ _emit_image (cairo_surface_t *image,
data += stride;
}
break;
case CAIRO_FORMAT_RGB96F:
case CAIRO_FORMAT_RGBA128F:
case CAIRO_FORMAT_RGB30:
case CAIRO_FORMAT_ARGB32:
for (row = height; row--; ) {
......@@ -1766,7 +1776,7 @@ _emit_image (cairo_surface_t *image,
data += stride;
}
break;
case CAIRO_FORMAT_INVALID:
case CAIRO_FORMAT_INVALID:
default:
break;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment