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 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 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 182 static inline pixman_image_t *pixman_image_ref(pixman_image_t *i) 183 { 184 i->ref_count++; 185 return i; 186 } 187 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 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 214 static inline uint32_t *pixman_image_get_data(pixman_image_t *i) 215 { 216 return i->data; 217 } 218 219 static inline int pixman_image_get_height(pixman_image_t *i) 220 { 221 return i->height; 222 } 223 224 static inline int pixman_image_get_width(pixman_image_t *i) 225 { 226 return i->width; 227 } 228 229 static inline int pixman_image_get_stride(pixman_image_t *i) 230 { 231 return i->stride; 232 } 233 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