1 /*
2 * SPDX-License-Identifier: MIT
3 *
4 * Tiny subset of PIXMAN API commonly used by QEMU.
5 *
6 * Copyright 1987, 1988, 1989, 1998 The Open Group
7 * Copyright 1987, 1988, 1989 Digital Equipment Corporation
8 * Copyright 1999, 2004, 2008 Keith Packard
9 * Copyright 2000 SuSE, Inc.
10 * Copyright 2000 Keith Packard, member of The XFree86 Project, Inc.
11 * Copyright 2004, 2005, 2007, 2008, 2009, 2010 Red Hat, Inc.
12 * Copyright 2004 Nicholas Miell
13 * Copyright 2005 Lars Knoll & Zack Rusin, Trolltech
14 * Copyright 2005 Trolltech AS
15 * Copyright 2007 Luca Barbato
16 * Copyright 2008 Aaron Plattner, NVIDIA Corporation
17 * Copyright 2008 Rodrigo Kumpera
18 * Copyright 2008 André Tupinambá
19 * Copyright 2008 Mozilla Corporation
20 * Copyright 2008 Frederic Plourde
21 * Copyright 2009, Oracle and/or its affiliates. All rights reserved.
22 * Copyright 2009, 2010 Nokia Corporation
23 *
24 * Permission is hereby granted, free of charge, to any person obtaining a
25 * copy of this software and associated documentation files (the "Software"),
26 * to deal in the Software without restriction, including without limitation
27 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
28 * and/or sell copies of the Software, and to permit persons to whom the
29 * Software is furnished to do so, subject to the following conditions:
30 *
31 * The above copyright notice and this permission notice (including the next
32 * paragraph) shall be included in all copies or substantial portions of the
33 * Software.
34 *
35 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
36 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
37 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
38 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
39 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
40 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
41 * DEALINGS IN THE SOFTWARE.
42 */
43
44 #ifndef PIXMAN_MINIMAL_H
45 #define PIXMAN_MINIMAL_H
46
47 #define PIXMAN_TYPE_OTHER 0
48 #define PIXMAN_TYPE_ARGB 2
49 #define PIXMAN_TYPE_ABGR 3
50 #define PIXMAN_TYPE_BGRA 8
51 #define PIXMAN_TYPE_RGBA 9
52
53 #define PIXMAN_FORMAT(bpp, type, a, r, g, b) (((bpp) << 24) | \
54 ((type) << 16) | \
55 ((a) << 12) | \
56 ((r) << 8) | \
57 ((g) << 4) | \
58 ((b)))
59
60 #define PIXMAN_FORMAT_RESHIFT(val, ofs, num) \
61 (((val >> (ofs)) & ((1 << (num)) - 1)) << ((val >> 22) & 3))
62
63 #define PIXMAN_FORMAT_BPP(f) PIXMAN_FORMAT_RESHIFT(f, 24, 8)
64 #define PIXMAN_FORMAT_TYPE(f) (((f) >> 16) & 0x3f)
65 #define PIXMAN_FORMAT_A(f) PIXMAN_FORMAT_RESHIFT(f, 12, 4)
66 #define PIXMAN_FORMAT_R(f) PIXMAN_FORMAT_RESHIFT(f, 8, 4)
67 #define PIXMAN_FORMAT_G(f) PIXMAN_FORMAT_RESHIFT(f, 4, 4)
68 #define PIXMAN_FORMAT_B(f) PIXMAN_FORMAT_RESHIFT(f, 0, 4)
69 #define PIXMAN_FORMAT_DEPTH(f) (PIXMAN_FORMAT_A(f) + \
70 PIXMAN_FORMAT_R(f) + \
71 PIXMAN_FORMAT_G(f) + \
72 PIXMAN_FORMAT_B(f))
73
74 typedef enum {
75 /* 32bpp formats */
76 PIXMAN_a8r8g8b8 = PIXMAN_FORMAT(32, PIXMAN_TYPE_ARGB, 8, 8, 8, 8),
77 PIXMAN_x8r8g8b8 = PIXMAN_FORMAT(32, PIXMAN_TYPE_ARGB, 0, 8, 8, 8),
78 PIXMAN_a8b8g8r8 = PIXMAN_FORMAT(32, PIXMAN_TYPE_ABGR, 8, 8, 8, 8),
79 PIXMAN_x8b8g8r8 = PIXMAN_FORMAT(32, PIXMAN_TYPE_ABGR, 0, 8, 8, 8),
80 PIXMAN_b8g8r8a8 = PIXMAN_FORMAT(32, PIXMAN_TYPE_BGRA, 8, 8, 8, 8),
81 PIXMAN_b8g8r8x8 = PIXMAN_FORMAT(32, PIXMAN_TYPE_BGRA, 0, 8, 8, 8),
82 PIXMAN_r8g8b8a8 = PIXMAN_FORMAT(32, PIXMAN_TYPE_RGBA, 8, 8, 8, 8),
83 PIXMAN_r8g8b8x8 = PIXMAN_FORMAT(32, PIXMAN_TYPE_RGBA, 0, 8, 8, 8),
84 /* 24bpp formats */
85 PIXMAN_r8g8b8 = PIXMAN_FORMAT(24, PIXMAN_TYPE_ARGB, 0, 8, 8, 8),
86 PIXMAN_b8g8r8 = PIXMAN_FORMAT(24, PIXMAN_TYPE_ABGR, 0, 8, 8, 8),
87 /* 16bpp formats */
88 PIXMAN_r5g6b5 = PIXMAN_FORMAT(16, PIXMAN_TYPE_ARGB, 0, 5, 6, 5),
89 PIXMAN_a1r5g5b5 = PIXMAN_FORMAT(16, PIXMAN_TYPE_ARGB, 1, 5, 5, 5),
90 PIXMAN_x1r5g5b5 = PIXMAN_FORMAT(16, PIXMAN_TYPE_ARGB, 0, 5, 5, 5),
91 } pixman_format_code_t;
92
93 typedef struct pixman_image pixman_image_t;
94
95 typedef void (*pixman_image_destroy_func_t)(pixman_image_t *image, void *data);
96
97 struct pixman_image {
98 int ref_count;
99 pixman_format_code_t format;
100 int width;
101 int height;
102 int stride;
103 uint32_t *data;
104 uint32_t *free_me;
105 pixman_image_destroy_func_t destroy_func;
106 void *destroy_data;
107 };
108
109 typedef struct pixman_color {
110 uint16_t red;
111 uint16_t green;
112 uint16_t blue;
113 uint16_t alpha;
114 } pixman_color_t;
115
create_bits(pixman_format_code_t format,int width,int height,int * rowstride_bytes)116 static inline uint32_t *create_bits(pixman_format_code_t format,
117 int width,
118 int height,
119 int *rowstride_bytes)
120 {
121 int stride = 0;
122 size_t buf_size = 0;
123 int bpp = PIXMAN_FORMAT_BPP(format);
124
125 /*
126 * Calculate the following while checking for overflow truncation:
127 * stride = ((width * bpp + 0x1f) >> 5) * sizeof(uint32_t);
128 */
129
130 if (unlikely(__builtin_mul_overflow(width, bpp, &stride))) {
131 return NULL;
132 }
133
134 if (unlikely(__builtin_add_overflow(stride, 0x1f, &stride))) {
135 return NULL;
136 }
137
138 stride >>= 5;
139
140 stride *= sizeof(uint32_t);
141
142 if (unlikely(__builtin_mul_overflow((size_t) height,
143 (size_t) stride,
144 &buf_size))) {
145 return NULL;
146 }
147
148 if (rowstride_bytes) {
149 *rowstride_bytes = stride;
150 }
151
152 return g_malloc0(buf_size);
153 }
154
pixman_image_create_bits(pixman_format_code_t format,int width,int height,uint32_t * bits,int rowstride_bytes)155 static inline pixman_image_t *pixman_image_create_bits(pixman_format_code_t format,
156 int width,
157 int height,
158 uint32_t *bits,
159 int rowstride_bytes)
160 {
161 pixman_image_t *i = g_new0(pixman_image_t, 1);
162
163 i->width = width;
164 i->height = height;
165 i->format = format;
166 if (bits) {
167 i->data = bits;
168 } else {
169 i->free_me = i->data =
170 create_bits(format, width, height, &rowstride_bytes);
171 if (width && height) {
172 assert(i->data);
173 }
174 }
175 i->stride = rowstride_bytes ? rowstride_bytes :
176 width * DIV_ROUND_UP(PIXMAN_FORMAT_BPP(format), 8);
177 i->ref_count = 1;
178
179 return i;
180 }
181
pixman_image_ref(pixman_image_t * i)182 static inline pixman_image_t *pixman_image_ref(pixman_image_t *i)
183 {
184 i->ref_count++;
185 return i;
186 }
187
pixman_image_unref(pixman_image_t * i)188 static inline bool pixman_image_unref(pixman_image_t *i)
189 {
190 i->ref_count--;
191
192 if (i->ref_count == 0) {
193 if (i->destroy_func) {
194 i->destroy_func(i, i->destroy_data);
195 }
196 g_free(i->free_me);
197 g_free(i);
198
199 return true;
200 }
201
202 return false;
203 }
204
pixman_image_set_destroy_function(pixman_image_t * i,pixman_image_destroy_func_t func,void * data)205 static inline void pixman_image_set_destroy_function(pixman_image_t *i,
206 pixman_image_destroy_func_t func,
207 void *data)
208
209 {
210 i->destroy_func = func;
211 i->destroy_data = data;
212 }
213
pixman_image_get_data(pixman_image_t * i)214 static inline uint32_t *pixman_image_get_data(pixman_image_t *i)
215 {
216 return i->data;
217 }
218
pixman_image_get_height(pixman_image_t * i)219 static inline int pixman_image_get_height(pixman_image_t *i)
220 {
221 return i->height;
222 }
223
pixman_image_get_width(pixman_image_t * i)224 static inline int pixman_image_get_width(pixman_image_t *i)
225 {
226 return i->width;
227 }
228
pixman_image_get_stride(pixman_image_t * i)229 static inline int pixman_image_get_stride(pixman_image_t *i)
230 {
231 return i->stride;
232 }
233
pixman_image_get_format(pixman_image_t * i)234 static inline pixman_format_code_t pixman_image_get_format(pixman_image_t *i)
235 {
236 return i->format;
237 }
238
239 #endif /* PIXMAN_MINIMAL_H */
240