xwayland: Add xdg-system-bell support
[xserver.git] / exa / exa_mixed.c
blobf1aeacd48967e52675e9e1213c0ce4d9cf68211b
1 /*
2 * Copyright © 2009 Maarten Maathuis
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
25 #include <dix-config.h>
27 #include <string.h>
29 #include "exa_priv.h"
30 #include "exa.h"
32 /* This file holds the driver allocated pixmaps + better initial placement code.
35 static inline void *
36 ExaGetPixmapAddress(PixmapPtr p)
38 ExaPixmapPriv(p);
40 return pExaPixmap->sys_ptr;
43 /**
44 * exaCreatePixmap() creates a new pixmap.
46 PixmapPtr
47 exaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int depth,
48 unsigned usage_hint)
50 PixmapPtr pPixmap;
51 ExaPixmapPrivPtr pExaPixmap;
52 int bpp;
53 size_t paddedWidth;
55 ExaScreenPriv(pScreen);
57 if (w > 32767 || h > 32767)
58 return NullPixmap;
60 swap(pExaScr, pScreen, CreatePixmap);
61 pPixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, usage_hint);
62 swap(pExaScr, pScreen, CreatePixmap);
64 if (!pPixmap)
65 return NULL;
67 pExaPixmap = ExaGetPixmapPriv(pPixmap);
68 pExaPixmap->driverPriv = NULL;
70 bpp = pPixmap->drawable.bitsPerPixel;
72 paddedWidth = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
73 if (paddedWidth / 4 > 32767)
74 return NullPixmap;
76 /* We will allocate the system pixmap later if needed. */
77 pPixmap->devPrivate.ptr = NULL;
78 pExaPixmap->sys_ptr = NULL;
79 pExaPixmap->sys_pitch = paddedWidth;
81 pExaPixmap->area = NULL;
82 pExaPixmap->fb_ptr = NULL;
83 pExaPixmap->pDamage = NULL;
85 exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
86 exaSetAccelBlock(pExaScr, pExaPixmap, w, h, bpp);
88 (*pScreen->ModifyPixmapHeader) (pPixmap, w, h, 0, 0, paddedWidth, NULL);
90 /* A scratch pixmap will become a driver pixmap right away. */
91 if (!w || !h) {
92 exaCreateDriverPixmap_mixed(pPixmap);
93 pExaPixmap->use_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
95 else {
96 pExaPixmap->use_gpu_copy = FALSE;
98 if (w == 1 && h == 1) {
99 pExaPixmap->sys_ptr = malloc(paddedWidth);
101 /* Set up damage tracking */
102 pExaPixmap->pDamage = DamageCreate(exaDamageReport_mixed, NULL,
103 DamageReportNonEmpty, TRUE,
104 pPixmap->drawable.pScreen,
105 pPixmap);
107 if (pExaPixmap->pDamage) {
108 DamageRegister(&pPixmap->drawable, pExaPixmap->pDamage);
109 /* This ensures that pending damage reflects the current
110 * operation. This is used by exa to optimize migration.
112 DamageSetReportAfterOp(pExaPixmap->pDamage, TRUE);
117 /* During a fallback we must prepare access. */
118 if (pExaScr->fallback_counter)
119 exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST);
121 return pPixmap;
124 Bool
125 exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth,
126 int bitsPerPixel, int devKind, void *pPixData)
128 ScreenPtr pScreen;
129 ExaScreenPrivPtr pExaScr;
130 ExaPixmapPrivPtr pExaPixmap;
131 Bool ret, has_gpu_copy;
133 if (!pPixmap)
134 return FALSE;
136 pScreen = pPixmap->drawable.pScreen;
137 pExaScr = ExaGetScreenPriv(pScreen);
138 pExaPixmap = ExaGetPixmapPriv(pPixmap);
140 if (pPixData) {
141 if (pExaPixmap->driverPriv) {
142 if (pExaPixmap->pDamage) {
143 DamageDestroy(pExaPixmap->pDamage);
144 pExaPixmap->pDamage = NULL;
147 pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
148 pExaPixmap->driverPriv = NULL;
151 pExaPixmap->use_gpu_copy = FALSE;
152 pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
155 has_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
157 if (width <= 0)
158 width = pPixmap->drawable.width;
160 if (height <= 0)
161 height = pPixmap->drawable.height;
163 if (bitsPerPixel <= 0) {
164 if (depth <= 0)
165 bitsPerPixel = pPixmap->drawable.bitsPerPixel;
166 else
167 bitsPerPixel = BitsPerPixel(depth);
170 if (depth <= 0)
171 depth = pPixmap->drawable.depth;
173 if (width != pPixmap->drawable.width ||
174 height != pPixmap->drawable.height ||
175 depth != pPixmap->drawable.depth ||
176 bitsPerPixel != pPixmap->drawable.bitsPerPixel) {
177 if (pExaPixmap->driverPriv) {
178 if (devKind > 0)
179 pExaPixmap->fb_pitch = devKind;
180 else
181 exaSetFbPitch(pExaScr, pExaPixmap, width, height, bitsPerPixel);
183 exaSetAccelBlock(pExaScr, pExaPixmap, width, height, bitsPerPixel);
184 RegionEmpty(&pExaPixmap->validFB);
187 /* Need to re-create system copy if there's also a GPU copy */
188 if (has_gpu_copy) {
189 if (pExaPixmap->sys_ptr) {
190 free(pExaPixmap->sys_ptr);
191 pExaPixmap->sys_ptr = NULL;
192 DamageDestroy(pExaPixmap->pDamage);
193 pExaPixmap->pDamage = NULL;
194 RegionEmpty(&pExaPixmap->validSys);
196 if (pExaScr->deferred_mixed_pixmap == pPixmap)
197 pExaScr->deferred_mixed_pixmap = NULL;
200 pExaPixmap->sys_pitch = PixmapBytePad(width, depth);
204 if (has_gpu_copy) {
205 pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
206 pPixmap->devKind = pExaPixmap->fb_pitch;
208 else {
209 pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
210 pPixmap->devKind = pExaPixmap->sys_pitch;
213 /* Only pass driver pixmaps to the driver. */
214 if (pExaScr->info->ModifyPixmapHeader && pExaPixmap->driverPriv) {
215 ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth,
216 bitsPerPixel, devKind,
217 pPixData);
218 if (ret == TRUE)
219 goto out;
222 swap(pExaScr, pScreen, ModifyPixmapHeader);
223 ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth,
224 bitsPerPixel, devKind, pPixData);
225 swap(pExaScr, pScreen, ModifyPixmapHeader);
227 out:
228 if (has_gpu_copy) {
229 pExaPixmap->fb_ptr = pPixmap->devPrivate.ptr;
230 pExaPixmap->fb_pitch = pPixmap->devKind;
232 else {
233 pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
234 pExaPixmap->sys_pitch = pPixmap->devKind;
236 /* Always NULL this, we don't want lingering pointers. */
237 pPixmap->devPrivate.ptr = NULL;
239 return ret;
242 Bool
243 exaDestroyPixmap_mixed(PixmapPtr pPixmap)
245 ScreenPtr pScreen = pPixmap->drawable.pScreen;
247 ExaScreenPriv(pScreen);
248 Bool ret;
250 if (pPixmap->refcnt == 1) {
251 ExaPixmapPriv(pPixmap);
253 exaDestroyPixmap(pPixmap);
255 if (pExaScr->deferred_mixed_pixmap == pPixmap)
256 pExaScr->deferred_mixed_pixmap = NULL;
258 if (pExaPixmap->driverPriv)
259 pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
260 pExaPixmap->driverPriv = NULL;
262 if (pExaPixmap->pDamage) {
263 free(pExaPixmap->sys_ptr);
264 pExaPixmap->sys_ptr = NULL;
265 pExaPixmap->pDamage = NULL;
269 swap(pExaScr, pScreen, DestroyPixmap);
270 ret = pScreen->DestroyPixmap(pPixmap);
271 swap(pExaScr, pScreen, DestroyPixmap);
273 return ret;
276 Bool
277 exaPixmapHasGpuCopy_mixed(PixmapPtr pPixmap)
279 ScreenPtr pScreen = pPixmap->drawable.pScreen;
281 ExaScreenPriv(pScreen);
282 ExaPixmapPriv(pPixmap);
283 void *saved_ptr;
284 Bool ret;
286 if (!pExaPixmap->driverPriv)
287 return FALSE;
289 saved_ptr = pPixmap->devPrivate.ptr;
290 pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap);
291 ret = pExaScr->info->PixmapIsOffscreen(pPixmap);
292 pPixmap->devPrivate.ptr = saved_ptr;
294 return ret;
297 Bool
298 exaSharePixmapBacking_mixed(PixmapPtr pPixmap, ScreenPtr secondary, void **handle_p)
300 ScreenPtr pScreen = pPixmap->drawable.pScreen;
301 ExaScreenPriv(pScreen);
302 Bool ret = FALSE;
304 exaMoveInPixmap(pPixmap);
305 /* get the driver to give us a handle */
306 if (pExaScr->info->SharePixmapBacking)
307 ret = pExaScr->info->SharePixmapBacking(pPixmap, secondary, handle_p);
309 return ret;
312 Bool
313 exaSetSharedPixmapBacking_mixed(PixmapPtr pPixmap, void *handle)
315 ScreenPtr pScreen = pPixmap->drawable.pScreen;
316 ExaScreenPriv(pScreen);
317 Bool ret = FALSE;
319 if (pExaScr->info->SetSharedPixmapBacking)
320 ret = pExaScr->info->SetSharedPixmapBacking(pPixmap, handle);
322 if (ret == TRUE)
323 exaMoveInPixmap(pPixmap);
325 return ret;