Commit | Line | Data |
---|---|---|
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 | ||
37 | static _X_INLINE void * | |
38 | ExaGetPixmapAddress(PixmapPtr p) | |
39 | { | |
40 | ExaPixmapPriv(p); | |
41 | ||
42 | return pExaPixmap->sys_ptr; | |
43 | } | |
44 | ||
45 | /** | |
46 | * exaCreatePixmap() creates a new pixmap. | |
47 | */ | |
48 | PixmapPtr | |
49 | exaCreatePixmap_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 | ||
126 | Bool | |
127 | exaModifyPixmapHeader_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 | ||
244 | Bool | |
245 | exaDestroyPixmap_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 | ||
278 | Bool | |
279 | exaPixmapHasGpuCopy_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 | ||
299 | Bool | |
300 | exaSharePixmapBacking_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 | ||
314 | Bool | |
315 | exaSetSharedPixmapBacking_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 |