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 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 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 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 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 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 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 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 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 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 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