179a1f325SMarc-André Lureau /*
279a1f325SMarc-André Lureau * SPDX-License-Identifier: MIT
379a1f325SMarc-André Lureau *
479a1f325SMarc-André Lureau * Tiny subset of PIXMAN API commonly used by QEMU.
579a1f325SMarc-André Lureau *
679a1f325SMarc-André Lureau * Copyright 1987, 1988, 1989, 1998 The Open Group
779a1f325SMarc-André Lureau * Copyright 1987, 1988, 1989 Digital Equipment Corporation
879a1f325SMarc-André Lureau * Copyright 1999, 2004, 2008 Keith Packard
979a1f325SMarc-André Lureau * Copyright 2000 SuSE, Inc.
1079a1f325SMarc-André Lureau * Copyright 2000 Keith Packard, member of The XFree86 Project, Inc.
1179a1f325SMarc-André Lureau * Copyright 2004, 2005, 2007, 2008, 2009, 2010 Red Hat, Inc.
1279a1f325SMarc-André Lureau * Copyright 2004 Nicholas Miell
1379a1f325SMarc-André Lureau * Copyright 2005 Lars Knoll & Zack Rusin, Trolltech
1479a1f325SMarc-André Lureau * Copyright 2005 Trolltech AS
1579a1f325SMarc-André Lureau * Copyright 2007 Luca Barbato
1679a1f325SMarc-André Lureau * Copyright 2008 Aaron Plattner, NVIDIA Corporation
1779a1f325SMarc-André Lureau * Copyright 2008 Rodrigo Kumpera
1879a1f325SMarc-André Lureau * Copyright 2008 André Tupinambá
1979a1f325SMarc-André Lureau * Copyright 2008 Mozilla Corporation
2079a1f325SMarc-André Lureau * Copyright 2008 Frederic Plourde
2179a1f325SMarc-André Lureau * Copyright 2009, Oracle and/or its affiliates. All rights reserved.
2279a1f325SMarc-André Lureau * Copyright 2009, 2010 Nokia Corporation
2379a1f325SMarc-André Lureau *
2479a1f325SMarc-André Lureau * Permission is hereby granted, free of charge, to any person obtaining a
2579a1f325SMarc-André Lureau * copy of this software and associated documentation files (the "Software"),
2679a1f325SMarc-André Lureau * to deal in the Software without restriction, including without limitation
2779a1f325SMarc-André Lureau * the rights to use, copy, modify, merge, publish, distribute, sublicense,
2879a1f325SMarc-André Lureau * and/or sell copies of the Software, and to permit persons to whom the
2979a1f325SMarc-André Lureau * Software is furnished to do so, subject to the following conditions:
3079a1f325SMarc-André Lureau *
3179a1f325SMarc-André Lureau * The above copyright notice and this permission notice (including the next
3279a1f325SMarc-André Lureau * paragraph) shall be included in all copies or substantial portions of the
3379a1f325SMarc-André Lureau * Software.
3479a1f325SMarc-André Lureau *
3579a1f325SMarc-André Lureau * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
3679a1f325SMarc-André Lureau * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
3779a1f325SMarc-André Lureau * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
3879a1f325SMarc-André Lureau * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
3979a1f325SMarc-André Lureau * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
4079a1f325SMarc-André Lureau * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
4179a1f325SMarc-André Lureau * DEALINGS IN THE SOFTWARE.
4279a1f325SMarc-André Lureau */
4379a1f325SMarc-André Lureau
4479a1f325SMarc-André Lureau #ifndef PIXMAN_MINIMAL_H
4579a1f325SMarc-André Lureau #define PIXMAN_MINIMAL_H
4679a1f325SMarc-André Lureau
4779a1f325SMarc-André Lureau #define PIXMAN_TYPE_OTHER 0
4879a1f325SMarc-André Lureau #define PIXMAN_TYPE_ARGB 2
4979a1f325SMarc-André Lureau #define PIXMAN_TYPE_ABGR 3
5079a1f325SMarc-André Lureau #define PIXMAN_TYPE_BGRA 8
5179a1f325SMarc-André Lureau #define PIXMAN_TYPE_RGBA 9
5279a1f325SMarc-André Lureau
5379a1f325SMarc-André Lureau #define PIXMAN_FORMAT(bpp, type, a, r, g, b) (((bpp) << 24) | \
5479a1f325SMarc-André Lureau ((type) << 16) | \
5579a1f325SMarc-André Lureau ((a) << 12) | \
5679a1f325SMarc-André Lureau ((r) << 8) | \
5779a1f325SMarc-André Lureau ((g) << 4) | \
5879a1f325SMarc-André Lureau ((b)))
5979a1f325SMarc-André Lureau
6079a1f325SMarc-André Lureau #define PIXMAN_FORMAT_RESHIFT(val, ofs, num) \
6179a1f325SMarc-André Lureau (((val >> (ofs)) & ((1 << (num)) - 1)) << ((val >> 22) & 3))
6279a1f325SMarc-André Lureau
6379a1f325SMarc-André Lureau #define PIXMAN_FORMAT_BPP(f) PIXMAN_FORMAT_RESHIFT(f, 24, 8)
6479a1f325SMarc-André Lureau #define PIXMAN_FORMAT_TYPE(f) (((f) >> 16) & 0x3f)
6579a1f325SMarc-André Lureau #define PIXMAN_FORMAT_A(f) PIXMAN_FORMAT_RESHIFT(f, 12, 4)
6679a1f325SMarc-André Lureau #define PIXMAN_FORMAT_R(f) PIXMAN_FORMAT_RESHIFT(f, 8, 4)
6779a1f325SMarc-André Lureau #define PIXMAN_FORMAT_G(f) PIXMAN_FORMAT_RESHIFT(f, 4, 4)
6879a1f325SMarc-André Lureau #define PIXMAN_FORMAT_B(f) PIXMAN_FORMAT_RESHIFT(f, 0, 4)
6979a1f325SMarc-André Lureau #define PIXMAN_FORMAT_DEPTH(f) (PIXMAN_FORMAT_A(f) + \
7079a1f325SMarc-André Lureau PIXMAN_FORMAT_R(f) + \
7179a1f325SMarc-André Lureau PIXMAN_FORMAT_G(f) + \
7279a1f325SMarc-André Lureau PIXMAN_FORMAT_B(f))
7379a1f325SMarc-André Lureau
7479a1f325SMarc-André Lureau typedef enum {
7579a1f325SMarc-André Lureau /* 32bpp formats */
7679a1f325SMarc-André Lureau PIXMAN_a8r8g8b8 = PIXMAN_FORMAT(32, PIXMAN_TYPE_ARGB, 8, 8, 8, 8),
7779a1f325SMarc-André Lureau PIXMAN_x8r8g8b8 = PIXMAN_FORMAT(32, PIXMAN_TYPE_ARGB, 0, 8, 8, 8),
7879a1f325SMarc-André Lureau PIXMAN_a8b8g8r8 = PIXMAN_FORMAT(32, PIXMAN_TYPE_ABGR, 8, 8, 8, 8),
7979a1f325SMarc-André Lureau PIXMAN_x8b8g8r8 = PIXMAN_FORMAT(32, PIXMAN_TYPE_ABGR, 0, 8, 8, 8),
8079a1f325SMarc-André Lureau PIXMAN_b8g8r8a8 = PIXMAN_FORMAT(32, PIXMAN_TYPE_BGRA, 8, 8, 8, 8),
8179a1f325SMarc-André Lureau PIXMAN_b8g8r8x8 = PIXMAN_FORMAT(32, PIXMAN_TYPE_BGRA, 0, 8, 8, 8),
8279a1f325SMarc-André Lureau PIXMAN_r8g8b8a8 = PIXMAN_FORMAT(32, PIXMAN_TYPE_RGBA, 8, 8, 8, 8),
8379a1f325SMarc-André Lureau PIXMAN_r8g8b8x8 = PIXMAN_FORMAT(32, PIXMAN_TYPE_RGBA, 0, 8, 8, 8),
8479a1f325SMarc-André Lureau /* 24bpp formats */
8579a1f325SMarc-André Lureau PIXMAN_r8g8b8 = PIXMAN_FORMAT(24, PIXMAN_TYPE_ARGB, 0, 8, 8, 8),
8679a1f325SMarc-André Lureau PIXMAN_b8g8r8 = PIXMAN_FORMAT(24, PIXMAN_TYPE_ABGR, 0, 8, 8, 8),
8779a1f325SMarc-André Lureau /* 16bpp formats */
8879a1f325SMarc-André Lureau PIXMAN_r5g6b5 = PIXMAN_FORMAT(16, PIXMAN_TYPE_ARGB, 0, 5, 6, 5),
8979a1f325SMarc-André Lureau PIXMAN_a1r5g5b5 = PIXMAN_FORMAT(16, PIXMAN_TYPE_ARGB, 1, 5, 5, 5),
9079a1f325SMarc-André Lureau PIXMAN_x1r5g5b5 = PIXMAN_FORMAT(16, PIXMAN_TYPE_ARGB, 0, 5, 5, 5),
9179a1f325SMarc-André Lureau } pixman_format_code_t;
9279a1f325SMarc-André Lureau
9379a1f325SMarc-André Lureau typedef struct pixman_image pixman_image_t;
9479a1f325SMarc-André Lureau
9579a1f325SMarc-André Lureau typedef void (*pixman_image_destroy_func_t)(pixman_image_t *image, void *data);
9679a1f325SMarc-André Lureau
9779a1f325SMarc-André Lureau struct pixman_image {
9879a1f325SMarc-André Lureau int ref_count;
9979a1f325SMarc-André Lureau pixman_format_code_t format;
10079a1f325SMarc-André Lureau int width;
10179a1f325SMarc-André Lureau int height;
10279a1f325SMarc-André Lureau int stride;
10379a1f325SMarc-André Lureau uint32_t *data;
10479a1f325SMarc-André Lureau uint32_t *free_me;
10579a1f325SMarc-André Lureau pixman_image_destroy_func_t destroy_func;
10679a1f325SMarc-André Lureau void *destroy_data;
10779a1f325SMarc-André Lureau };
10879a1f325SMarc-André Lureau
10979a1f325SMarc-André Lureau typedef struct pixman_color {
11079a1f325SMarc-André Lureau uint16_t red;
11179a1f325SMarc-André Lureau uint16_t green;
11279a1f325SMarc-André Lureau uint16_t blue;
11379a1f325SMarc-André Lureau uint16_t alpha;
11479a1f325SMarc-André Lureau } pixman_color_t;
11579a1f325SMarc-André Lureau
create_bits(pixman_format_code_t format,int width,int height,int * rowstride_bytes)116*e0c58720SManos Pitsidianakis static inline uint32_t *create_bits(pixman_format_code_t format,
117*e0c58720SManos Pitsidianakis int width,
118*e0c58720SManos Pitsidianakis int height,
119*e0c58720SManos Pitsidianakis int *rowstride_bytes)
120*e0c58720SManos Pitsidianakis {
121*e0c58720SManos Pitsidianakis int stride = 0;
122*e0c58720SManos Pitsidianakis size_t buf_size = 0;
123*e0c58720SManos Pitsidianakis int bpp = PIXMAN_FORMAT_BPP(format);
124*e0c58720SManos Pitsidianakis
125*e0c58720SManos Pitsidianakis /*
126*e0c58720SManos Pitsidianakis * Calculate the following while checking for overflow truncation:
127*e0c58720SManos Pitsidianakis * stride = ((width * bpp + 0x1f) >> 5) * sizeof(uint32_t);
128*e0c58720SManos Pitsidianakis */
129*e0c58720SManos Pitsidianakis
130*e0c58720SManos Pitsidianakis if (unlikely(__builtin_mul_overflow(width, bpp, &stride))) {
131*e0c58720SManos Pitsidianakis return NULL;
132*e0c58720SManos Pitsidianakis }
133*e0c58720SManos Pitsidianakis
134*e0c58720SManos Pitsidianakis if (unlikely(__builtin_add_overflow(stride, 0x1f, &stride))) {
135*e0c58720SManos Pitsidianakis return NULL;
136*e0c58720SManos Pitsidianakis }
137*e0c58720SManos Pitsidianakis
138*e0c58720SManos Pitsidianakis stride >>= 5;
139*e0c58720SManos Pitsidianakis
140*e0c58720SManos Pitsidianakis stride *= sizeof(uint32_t);
141*e0c58720SManos Pitsidianakis
142*e0c58720SManos Pitsidianakis if (unlikely(__builtin_mul_overflow((size_t) height,
143*e0c58720SManos Pitsidianakis (size_t) stride,
144*e0c58720SManos Pitsidianakis &buf_size))) {
145*e0c58720SManos Pitsidianakis return NULL;
146*e0c58720SManos Pitsidianakis }
147*e0c58720SManos Pitsidianakis
148*e0c58720SManos Pitsidianakis if (rowstride_bytes) {
149*e0c58720SManos Pitsidianakis *rowstride_bytes = stride;
150*e0c58720SManos Pitsidianakis }
151*e0c58720SManos Pitsidianakis
152*e0c58720SManos Pitsidianakis return g_malloc0(buf_size);
153*e0c58720SManos Pitsidianakis }
154*e0c58720SManos Pitsidianakis
pixman_image_create_bits(pixman_format_code_t format,int width,int height,uint32_t * bits,int rowstride_bytes)15579a1f325SMarc-André Lureau static inline pixman_image_t *pixman_image_create_bits(pixman_format_code_t format,
15679a1f325SMarc-André Lureau int width,
15779a1f325SMarc-André Lureau int height,
15879a1f325SMarc-André Lureau uint32_t *bits,
15979a1f325SMarc-André Lureau int rowstride_bytes)
16079a1f325SMarc-André Lureau {
16179a1f325SMarc-André Lureau pixman_image_t *i = g_new0(pixman_image_t, 1);
16279a1f325SMarc-André Lureau
16379a1f325SMarc-André Lureau i->width = width;
16479a1f325SMarc-André Lureau i->height = height;
16579a1f325SMarc-André Lureau i->format = format;
16679a1f325SMarc-André Lureau if (bits) {
16779a1f325SMarc-André Lureau i->data = bits;
16879a1f325SMarc-André Lureau } else {
169*e0c58720SManos Pitsidianakis i->free_me = i->data =
170*e0c58720SManos Pitsidianakis create_bits(format, width, height, &rowstride_bytes);
171*e0c58720SManos Pitsidianakis if (width && height) {
172*e0c58720SManos Pitsidianakis assert(i->data);
17379a1f325SMarc-André Lureau }
174*e0c58720SManos Pitsidianakis }
175*e0c58720SManos Pitsidianakis i->stride = rowstride_bytes ? rowstride_bytes :
176*e0c58720SManos Pitsidianakis width * DIV_ROUND_UP(PIXMAN_FORMAT_BPP(format), 8);
17779a1f325SMarc-André Lureau i->ref_count = 1;
17879a1f325SMarc-André Lureau
17979a1f325SMarc-André Lureau return i;
18079a1f325SMarc-André Lureau }
18179a1f325SMarc-André Lureau
pixman_image_ref(pixman_image_t * i)18279a1f325SMarc-André Lureau static inline pixman_image_t *pixman_image_ref(pixman_image_t *i)
18379a1f325SMarc-André Lureau {
18479a1f325SMarc-André Lureau i->ref_count++;
18579a1f325SMarc-André Lureau return i;
18679a1f325SMarc-André Lureau }
18779a1f325SMarc-André Lureau
pixman_image_unref(pixman_image_t * i)18879a1f325SMarc-André Lureau static inline bool pixman_image_unref(pixman_image_t *i)
18979a1f325SMarc-André Lureau {
19079a1f325SMarc-André Lureau i->ref_count--;
19179a1f325SMarc-André Lureau
19279a1f325SMarc-André Lureau if (i->ref_count == 0) {
19379a1f325SMarc-André Lureau if (i->destroy_func) {
19479a1f325SMarc-André Lureau i->destroy_func(i, i->destroy_data);
19579a1f325SMarc-André Lureau }
19679a1f325SMarc-André Lureau g_free(i->free_me);
19779a1f325SMarc-André Lureau g_free(i);
19879a1f325SMarc-André Lureau
19979a1f325SMarc-André Lureau return true;
20079a1f325SMarc-André Lureau }
20179a1f325SMarc-André Lureau
20279a1f325SMarc-André Lureau return false;
20379a1f325SMarc-André Lureau }
20479a1f325SMarc-André Lureau
pixman_image_set_destroy_function(pixman_image_t * i,pixman_image_destroy_func_t func,void * data)20579a1f325SMarc-André Lureau static inline void pixman_image_set_destroy_function(pixman_image_t *i,
20679a1f325SMarc-André Lureau pixman_image_destroy_func_t func,
20779a1f325SMarc-André Lureau void *data)
20879a1f325SMarc-André Lureau
20979a1f325SMarc-André Lureau {
21079a1f325SMarc-André Lureau i->destroy_func = func;
21179a1f325SMarc-André Lureau i->destroy_data = data;
21279a1f325SMarc-André Lureau }
21379a1f325SMarc-André Lureau
pixman_image_get_data(pixman_image_t * i)21479a1f325SMarc-André Lureau static inline uint32_t *pixman_image_get_data(pixman_image_t *i)
21579a1f325SMarc-André Lureau {
21679a1f325SMarc-André Lureau return i->data;
21779a1f325SMarc-André Lureau }
21879a1f325SMarc-André Lureau
pixman_image_get_height(pixman_image_t * i)21979a1f325SMarc-André Lureau static inline int pixman_image_get_height(pixman_image_t *i)
22079a1f325SMarc-André Lureau {
22179a1f325SMarc-André Lureau return i->height;
22279a1f325SMarc-André Lureau }
22379a1f325SMarc-André Lureau
pixman_image_get_width(pixman_image_t * i)22479a1f325SMarc-André Lureau static inline int pixman_image_get_width(pixman_image_t *i)
22579a1f325SMarc-André Lureau {
22679a1f325SMarc-André Lureau return i->width;
22779a1f325SMarc-André Lureau }
22879a1f325SMarc-André Lureau
pixman_image_get_stride(pixman_image_t * i)22979a1f325SMarc-André Lureau static inline int pixman_image_get_stride(pixman_image_t *i)
23079a1f325SMarc-André Lureau {
23179a1f325SMarc-André Lureau return i->stride;
23279a1f325SMarc-André Lureau }
23379a1f325SMarc-André Lureau
pixman_image_get_format(pixman_image_t * i)23479a1f325SMarc-André Lureau static inline pixman_format_code_t pixman_image_get_format(pixman_image_t *i)
23579a1f325SMarc-André Lureau {
23679a1f325SMarc-André Lureau return i->format;
23779a1f325SMarc-André Lureau }
23879a1f325SMarc-André Lureau
23979a1f325SMarc-André Lureau #endif /* PIXMAN_MINIMAL_H */
240