Imported Upstream version 1.15.1
[deb_xorg-server.git] / exa / exa_mixed.c
CommitLineData
a09e091a
JB
1/*
2 * Copyright © 2009 Maarten Maathuis
3 *
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:
10 *
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.
14 *
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.
22 *
23 */
24
25#ifdef HAVE_DIX_CONFIG_H
26#include <dix-config.h>
27#endif
28
29#include <string.h>
30
31#include "exa_priv.h"
32#include "exa.h"
33
34/* This file holds the driver allocated pixmaps + better initial placement code.
35 */
36
37static _X_INLINE void *
38ExaGetPixmapAddress(PixmapPtr p)
39{
40 ExaPixmapPriv(p);
41
42 return pExaPixmap->sys_ptr;
43}
44
45/**
46 * exaCreatePixmap() creates a new pixmap.
47 */
48PixmapPtr
49exaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int depth,
50 unsigned usage_hint)
51{
52 PixmapPtr pPixmap;
53 ExaPixmapPrivPtr pExaPixmap;
54 int bpp;
55 size_t paddedWidth;
56
57 ExaScreenPriv(pScreen);
58
59 if (w > 32767 || h > 32767)
60 return NullPixmap;
61
62 swap(pExaScr, pScreen, CreatePixmap);
63 pPixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, usage_hint);
64 swap(pExaScr, pScreen, CreatePixmap);
65
66 if (!pPixmap)
67 return NULL;
68
69 pExaPixmap = ExaGetPixmapPriv(pPixmap);
70 pExaPixmap->driverPriv = NULL;
71
72 bpp = pPixmap->drawable.bitsPerPixel;
73
74 paddedWidth = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
75 if (paddedWidth / 4 > 32767 || h > 32767)
76 return NullPixmap;
77
78 /* We will allocate the system pixmap later if needed. */
79 pPixmap->devPrivate.ptr = NULL;
80 pExaPixmap->sys_ptr = NULL;
81 pExaPixmap->sys_pitch = paddedWidth;
82
83 pExaPixmap->area = NULL;
84 pExaPixmap->fb_ptr = NULL;
85 pExaPixmap->pDamage = NULL;
86
87 exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
88 exaSetAccelBlock(pExaScr, pExaPixmap, w, h, bpp);
89
90 (*pScreen->ModifyPixmapHeader) (pPixmap, w, h, 0, 0, paddedWidth, NULL);
91
92 /* A scratch pixmap will become a driver pixmap right away. */
93 if (!w || !h) {
94 exaCreateDriverPixmap_mixed(pPixmap);
95 pExaPixmap->use_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
96 }
97 else {
98 pExaPixmap->use_gpu_copy = FALSE;
99
100 if (w == 1 && h == 1) {
101 pExaPixmap->sys_ptr = malloc(paddedWidth);
102
103 /* Set up damage tracking */
104 pExaPixmap->pDamage = DamageCreate(exaDamageReport_mixed, NULL,
105 DamageReportNonEmpty, TRUE,
106 pPixmap->drawable.pScreen,
107 pPixmap);
108
109 if (pExaPixmap->pDamage) {
110 DamageRegister(&pPixmap->drawable, pExaPixmap->pDamage);
111 /* This ensures that pending damage reflects the current
112 * operation. This is used by exa to optimize migration.
113 */
114 DamageSetReportAfterOp(pExaPixmap->pDamage, TRUE);
115 }
116 }
117 }
118
119 /* During a fallback we must prepare access. */
120 if (pExaScr->fallback_counter)
121 exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST);
122
123 return pPixmap;
124}
125
126Bool
127exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth,
128 int bitsPerPixel, int devKind, pointer pPixData)
129{
130 ScreenPtr pScreen;
131 ExaScreenPrivPtr pExaScr;
132 ExaPixmapPrivPtr pExaPixmap;
133 Bool ret, has_gpu_copy;
134
135 if (!pPixmap)
136 return FALSE;
137
138 pScreen = pPixmap->drawable.pScreen;
139 pExaScr = ExaGetScreenPriv(pScreen);
140 pExaPixmap = ExaGetPixmapPriv(pPixmap);
141
142 if (pPixData) {
143 if (pExaPixmap->driverPriv) {
144 if (pExaPixmap->pDamage) {
145 DamageDestroy(pExaPixmap->pDamage);
146 pExaPixmap->pDamage = NULL;
147 }
148
149 pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
150 pExaPixmap->driverPriv = NULL;
151 }
152
153 pExaPixmap->use_gpu_copy = FALSE;
154 pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
155 }
156
157 has_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
158
159 if (width <= 0)
160 width = pPixmap->drawable.width;
161
162 if (height <= 0)
163 height = pPixmap->drawable.height;
164
165 if (bitsPerPixel <= 0) {
166 if (depth <= 0)
167 bitsPerPixel = pPixmap->drawable.bitsPerPixel;
168 else
169 bitsPerPixel = BitsPerPixel(depth);
170 }
171
172 if (depth <= 0)
173 depth = pPixmap->drawable.depth;
174
175 if (width != pPixmap->drawable.width ||
176 height != pPixmap->drawable.height ||
177 depth != pPixmap->drawable.depth ||
178 bitsPerPixel != pPixmap->drawable.bitsPerPixel) {
179 if (pExaPixmap->driverPriv) {
180 if (devKind > 0)
181 pExaPixmap->fb_pitch = devKind;
182 else
183 exaSetFbPitch(pExaScr, pExaPixmap, width, height, bitsPerPixel);
184
185 exaSetAccelBlock(pExaScr, pExaPixmap, width, height, bitsPerPixel);
186 RegionEmpty(&pExaPixmap->validFB);
187 }
188
189 /* Need to re-create system copy if there's also a GPU copy */
190 if (has_gpu_copy) {
191 if (pExaPixmap->sys_ptr) {
192 free(pExaPixmap->sys_ptr);
193 pExaPixmap->sys_ptr = NULL;
194 DamageDestroy(pExaPixmap->pDamage);
195 pExaPixmap->pDamage = NULL;
196 RegionEmpty(&pExaPixmap->validSys);
197
198 if (pExaScr->deferred_mixed_pixmap == pPixmap)
199 pExaScr->deferred_mixed_pixmap = NULL;
200 }
201
202 pExaPixmap->sys_pitch = PixmapBytePad(width, depth);
203 }
204 }
205
206 if (has_gpu_copy) {
207 pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
208 pPixmap->devKind = pExaPixmap->fb_pitch;
209 }
210 else {
211 pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
212 pPixmap->devKind = pExaPixmap->sys_pitch;
213 }
214
215 /* Only pass driver pixmaps to the driver. */
216 if (pExaScr->info->ModifyPixmapHeader && pExaPixmap->driverPriv) {
217 ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth,
218 bitsPerPixel, devKind,
219 pPixData);
220 if (ret == TRUE)
221 goto out;
222 }
223
224 swap(pExaScr, pScreen, ModifyPixmapHeader);
225 ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth,
226 bitsPerPixel, devKind, pPixData);
227 swap(pExaScr, pScreen, ModifyPixmapHeader);
228
229 out:
230 if (has_gpu_copy) {
231 pExaPixmap->fb_ptr = pPixmap->devPrivate.ptr;
232 pExaPixmap->fb_pitch = pPixmap->devKind;
233 }
234 else {
235 pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
236 pExaPixmap->sys_pitch = pPixmap->devKind;
237 }
238 /* Always NULL this, we don't want lingering pointers. */
239 pPixmap->devPrivate.ptr = NULL;
240
241 return ret;
242}
243
244Bool
245exaDestroyPixmap_mixed(PixmapPtr pPixmap)
246{
247 ScreenPtr pScreen = pPixmap->drawable.pScreen;
248
249 ExaScreenPriv(pScreen);
250 Bool ret;
251
252 if (pPixmap->refcnt == 1) {
253 ExaPixmapPriv(pPixmap);
254
255 exaDestroyPixmap(pPixmap);
256
257 if (pExaScr->deferred_mixed_pixmap == pPixmap)
258 pExaScr->deferred_mixed_pixmap = NULL;
259
260 if (pExaPixmap->driverPriv)
261 pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
262 pExaPixmap->driverPriv = NULL;
263
264 if (pExaPixmap->pDamage) {
265 free(pExaPixmap->sys_ptr);
266 pExaPixmap->sys_ptr = NULL;
267 pExaPixmap->pDamage = NULL;
268 }
269 }
270
271 swap(pExaScr, pScreen, DestroyPixmap);
272 ret = pScreen->DestroyPixmap(pPixmap);
273 swap(pExaScr, pScreen, DestroyPixmap);
274
275 return ret;
276}
277
278Bool
279exaPixmapHasGpuCopy_mixed(PixmapPtr pPixmap)
280{
281 ScreenPtr pScreen = pPixmap->drawable.pScreen;
282
283 ExaScreenPriv(pScreen);
284 ExaPixmapPriv(pPixmap);
285 pointer saved_ptr;
286 Bool ret;
287
288 if (!pExaPixmap->driverPriv)
289 return FALSE;
290
291 saved_ptr = pPixmap->devPrivate.ptr;
292 pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap);
293 ret = pExaScr->info->PixmapIsOffscreen(pPixmap);
294 pPixmap->devPrivate.ptr = saved_ptr;
295
296 return ret;
297}
298
299Bool
300exaSharePixmapBacking_mixed(PixmapPtr pPixmap, ScreenPtr slave, void **handle_p)
301{
302 ScreenPtr pScreen = pPixmap->drawable.pScreen;
303 ExaScreenPriv(pScreen);
304 Bool ret = FALSE;
305
306 exaMoveInPixmap(pPixmap);
307 /* get the driver to give us a handle */
308 if (pExaScr->info->SharePixmapBacking)
309 ret = pExaScr->info->SharePixmapBacking(pPixmap, slave, handle_p);
310
311 return ret;
312}
313
314Bool
315exaSetSharedPixmapBacking_mixed(PixmapPtr pPixmap, void *handle)
316{
317 ScreenPtr pScreen = pPixmap->drawable.pScreen;
318 ExaScreenPriv(pScreen);
319 Bool ret = FALSE;
320
321 if (pExaScr->info->SetSharedPixmapBacking)
322 ret = pExaScr->info->SetSharedPixmapBacking(pPixmap, handle);
323
324 if (ret == TRUE)
325 exaMoveInPixmap(pPixmap);
326
327 return ret;
328}
329
330