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
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
25 #ifdef HAVE_DIX_CONFIG_H
26 #include <dix-config.h>
34 /* This file holds the driver allocated pixmaps + better initial placement code.
37 static _X_INLINE
void *
38 ExaGetPixmapAddress(PixmapPtr p
)
42 return pExaPixmap
->sys_ptr
;
46 * exaCreatePixmap() creates a new pixmap.
49 exaCreatePixmap_mixed(ScreenPtr pScreen
, int w
, int h
, int depth
,
53 ExaPixmapPrivPtr pExaPixmap
;
57 ExaScreenPriv(pScreen
);
59 if (w
> 32767 || h
> 32767)
62 swap(pExaScr
, pScreen
, CreatePixmap
);
63 pPixmap
= pScreen
->CreatePixmap(pScreen
, 0, 0, depth
, usage_hint
);
64 swap(pExaScr
, pScreen
, CreatePixmap
);
69 pExaPixmap
= ExaGetPixmapPriv(pPixmap
);
70 pExaPixmap
->driverPriv
= NULL
;
72 bpp
= pPixmap
->drawable
.bitsPerPixel
;
74 paddedWidth
= ((w
* bpp
+ FB_MASK
) >> FB_SHIFT
) * sizeof(FbBits
);
75 if (paddedWidth
/ 4 > 32767 || h
> 32767)
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
;
83 pExaPixmap
->area
= NULL
;
84 pExaPixmap
->fb_ptr
= NULL
;
85 pExaPixmap
->pDamage
= NULL
;
87 exaSetFbPitch(pExaScr
, pExaPixmap
, w
, h
, bpp
);
88 exaSetAccelBlock(pExaScr
, pExaPixmap
, w
, h
, bpp
);
90 (*pScreen
->ModifyPixmapHeader
) (pPixmap
, w
, h
, 0, 0, paddedWidth
, NULL
);
92 /* A scratch pixmap will become a driver pixmap right away. */
94 exaCreateDriverPixmap_mixed(pPixmap
);
95 pExaPixmap
->use_gpu_copy
= exaPixmapHasGpuCopy(pPixmap
);
98 pExaPixmap
->use_gpu_copy
= FALSE
;
100 if (w
== 1 && h
== 1) {
101 pExaPixmap
->sys_ptr
= malloc(paddedWidth
);
103 /* Set up damage tracking */
104 pExaPixmap
->pDamage
= DamageCreate(exaDamageReport_mixed
, NULL
,
105 DamageReportNonEmpty
, TRUE
,
106 pPixmap
->drawable
.pScreen
,
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.
114 DamageSetReportAfterOp(pExaPixmap
->pDamage
, TRUE
);
119 /* During a fallback we must prepare access. */
120 if (pExaScr
->fallback_counter
)
121 exaPrepareAccess(&pPixmap
->drawable
, EXA_PREPARE_AUX_DEST
);
127 exaModifyPixmapHeader_mixed(PixmapPtr pPixmap
, int width
, int height
, int depth
,
128 int bitsPerPixel
, int devKind
, pointer pPixData
)
131 ExaScreenPrivPtr pExaScr
;
132 ExaPixmapPrivPtr pExaPixmap
;
133 Bool ret
, has_gpu_copy
;
138 pScreen
= pPixmap
->drawable
.pScreen
;
139 pExaScr
= ExaGetScreenPriv(pScreen
);
140 pExaPixmap
= ExaGetPixmapPriv(pPixmap
);
143 if (pExaPixmap
->driverPriv
) {
144 if (pExaPixmap
->pDamage
) {
145 DamageDestroy(pExaPixmap
->pDamage
);
146 pExaPixmap
->pDamage
= NULL
;
149 pExaScr
->info
->DestroyPixmap(pScreen
, pExaPixmap
->driverPriv
);
150 pExaPixmap
->driverPriv
= NULL
;
153 pExaPixmap
->use_gpu_copy
= FALSE
;
154 pExaPixmap
->score
= EXA_PIXMAP_SCORE_PINNED
;
157 has_gpu_copy
= exaPixmapHasGpuCopy(pPixmap
);
160 width
= pPixmap
->drawable
.width
;
163 height
= pPixmap
->drawable
.height
;
165 if (bitsPerPixel
<= 0) {
167 bitsPerPixel
= pPixmap
->drawable
.bitsPerPixel
;
169 bitsPerPixel
= BitsPerPixel(depth
);
173 depth
= pPixmap
->drawable
.depth
;
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
) {
181 pExaPixmap
->fb_pitch
= devKind
;
183 exaSetFbPitch(pExaScr
, pExaPixmap
, width
, height
, bitsPerPixel
);
185 exaSetAccelBlock(pExaScr
, pExaPixmap
, width
, height
, bitsPerPixel
);
186 RegionEmpty(&pExaPixmap
->validFB
);
189 /* Need to re-create system copy if there's also a 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
);
198 if (pExaScr
->deferred_mixed_pixmap
== pPixmap
)
199 pExaScr
->deferred_mixed_pixmap
= NULL
;
202 pExaPixmap
->sys_pitch
= PixmapBytePad(width
, depth
);
207 pPixmap
->devPrivate
.ptr
= pExaPixmap
->fb_ptr
;
208 pPixmap
->devKind
= pExaPixmap
->fb_pitch
;
211 pPixmap
->devPrivate
.ptr
= pExaPixmap
->sys_ptr
;
212 pPixmap
->devKind
= pExaPixmap
->sys_pitch
;
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
,
224 swap(pExaScr
, pScreen
, ModifyPixmapHeader
);
225 ret
= pScreen
->ModifyPixmapHeader(pPixmap
, width
, height
, depth
,
226 bitsPerPixel
, devKind
, pPixData
);
227 swap(pExaScr
, pScreen
, ModifyPixmapHeader
);
231 pExaPixmap
->fb_ptr
= pPixmap
->devPrivate
.ptr
;
232 pExaPixmap
->fb_pitch
= pPixmap
->devKind
;
235 pExaPixmap
->sys_ptr
= pPixmap
->devPrivate
.ptr
;
236 pExaPixmap
->sys_pitch
= pPixmap
->devKind
;
238 /* Always NULL this, we don't want lingering pointers. */
239 pPixmap
->devPrivate
.ptr
= NULL
;
245 exaDestroyPixmap_mixed(PixmapPtr pPixmap
)
247 ScreenPtr pScreen
= pPixmap
->drawable
.pScreen
;
249 ExaScreenPriv(pScreen
);
252 if (pPixmap
->refcnt
== 1) {
253 ExaPixmapPriv(pPixmap
);
255 exaDestroyPixmap(pPixmap
);
257 if (pExaScr
->deferred_mixed_pixmap
== pPixmap
)
258 pExaScr
->deferred_mixed_pixmap
= NULL
;
260 if (pExaPixmap
->driverPriv
)
261 pExaScr
->info
->DestroyPixmap(pScreen
, pExaPixmap
->driverPriv
);
262 pExaPixmap
->driverPriv
= NULL
;
264 if (pExaPixmap
->pDamage
) {
265 free(pExaPixmap
->sys_ptr
);
266 pExaPixmap
->sys_ptr
= NULL
;
267 pExaPixmap
->pDamage
= NULL
;
271 swap(pExaScr
, pScreen
, DestroyPixmap
);
272 ret
= pScreen
->DestroyPixmap(pPixmap
);
273 swap(pExaScr
, pScreen
, DestroyPixmap
);
279 exaPixmapHasGpuCopy_mixed(PixmapPtr pPixmap
)
281 ScreenPtr pScreen
= pPixmap
->drawable
.pScreen
;
283 ExaScreenPriv(pScreen
);
284 ExaPixmapPriv(pPixmap
);
288 if (!pExaPixmap
->driverPriv
)
291 saved_ptr
= pPixmap
->devPrivate
.ptr
;
292 pPixmap
->devPrivate
.ptr
= ExaGetPixmapAddress(pPixmap
);
293 ret
= pExaScr
->info
->PixmapIsOffscreen(pPixmap
);
294 pPixmap
->devPrivate
.ptr
= saved_ptr
;
300 exaSharePixmapBacking_mixed(PixmapPtr pPixmap
, ScreenPtr slave
, void **handle_p
)
302 ScreenPtr pScreen
= pPixmap
->drawable
.pScreen
;
303 ExaScreenPriv(pScreen
);
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
);
315 exaSetSharedPixmapBacking_mixed(PixmapPtr pPixmap
, void *handle
)
317 ScreenPtr pScreen
= pPixmap
->drawable
.pScreen
;
318 ExaScreenPriv(pScreen
);
321 if (pExaScr
->info
->SetSharedPixmapBacking
)
322 ret
= pExaScr
->info
->SetSharedPixmapBacking(pPixmap
, handle
);
325 exaMoveInPixmap(pPixmap
);