xref: /qemu/include/ui/pixman-minimal.h (revision c14ae763d548842c6abd1afaf5dc7ce7322ed901)
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