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 #include <dix-config.h>
32 /* This file holds the driver allocated pixmaps + better initial placement code.
36 ExaGetPixmapAddress(PixmapPtr p
)
40 return pExaPixmap
->sys_ptr
;
44 * exaCreatePixmap() creates a new pixmap.
47 exaCreatePixmap_mixed(ScreenPtr pScreen
, int w
, int h
, int depth
,
51 ExaPixmapPrivPtr pExaPixmap
;
55 ExaScreenPriv(pScreen
);
57 if (w
> 32767 || h
> 32767)
60 swap(pExaScr
, pScreen
, CreatePixmap
);
61 pPixmap
= pScreen
->CreatePixmap(pScreen
, 0, 0, depth
, usage_hint
);
62 swap(pExaScr
, pScreen
, CreatePixmap
);
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)
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. */
92 exaCreateDriverPixmap_mixed(pPixmap
);
93 pExaPixmap
->use_gpu_copy
= exaPixmapHasGpuCopy(pPixmap
);
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
,
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
);
125 exaModifyPixmapHeader_mixed(PixmapPtr pPixmap
, int width
, int height
, int depth
,
126 int bitsPerPixel
, int devKind
, void *pPixData
)
129 ExaScreenPrivPtr pExaScr
;
130 ExaPixmapPrivPtr pExaPixmap
;
131 Bool ret
, has_gpu_copy
;
136 pScreen
= pPixmap
->drawable
.pScreen
;
137 pExaScr
= ExaGetScreenPriv(pScreen
);
138 pExaPixmap
= ExaGetPixmapPriv(pPixmap
);
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
);
158 width
= pPixmap
->drawable
.width
;
161 height
= pPixmap
->drawable
.height
;
163 if (bitsPerPixel
<= 0) {
165 bitsPerPixel
= pPixmap
->drawable
.bitsPerPixel
;
167 bitsPerPixel
= BitsPerPixel(depth
);
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
) {
179 pExaPixmap
->fb_pitch
= devKind
;
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 */
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
);
205 pPixmap
->devPrivate
.ptr
= pExaPixmap
->fb_ptr
;
206 pPixmap
->devKind
= pExaPixmap
->fb_pitch
;
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
,
222 swap(pExaScr
, pScreen
, ModifyPixmapHeader
);
223 ret
= pScreen
->ModifyPixmapHeader(pPixmap
, width
, height
, depth
,
224 bitsPerPixel
, devKind
, pPixData
);
225 swap(pExaScr
, pScreen
, ModifyPixmapHeader
);
229 pExaPixmap
->fb_ptr
= pPixmap
->devPrivate
.ptr
;
230 pExaPixmap
->fb_pitch
= pPixmap
->devKind
;
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
;
243 exaDestroyPixmap_mixed(PixmapPtr pPixmap
)
245 ScreenPtr pScreen
= pPixmap
->drawable
.pScreen
;
247 ExaScreenPriv(pScreen
);
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
);
277 exaPixmapHasGpuCopy_mixed(PixmapPtr pPixmap
)
279 ScreenPtr pScreen
= pPixmap
->drawable
.pScreen
;
281 ExaScreenPriv(pScreen
);
282 ExaPixmapPriv(pPixmap
);
286 if (!pExaPixmap
->driverPriv
)
289 saved_ptr
= pPixmap
->devPrivate
.ptr
;
290 pPixmap
->devPrivate
.ptr
= ExaGetPixmapAddress(pPixmap
);
291 ret
= pExaScr
->info
->PixmapIsOffscreen(pPixmap
);
292 pPixmap
->devPrivate
.ptr
= saved_ptr
;
298 exaSharePixmapBacking_mixed(PixmapPtr pPixmap
, ScreenPtr secondary
, void **handle_p
)
300 ScreenPtr pScreen
= pPixmap
->drawable
.pScreen
;
301 ExaScreenPriv(pScreen
);
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
);
313 exaSetSharedPixmapBacking_mixed(PixmapPtr pPixmap
, void *handle
)
315 ScreenPtr pScreen
= pPixmap
->drawable
.pScreen
;
316 ExaScreenPriv(pScreen
);
319 if (pExaScr
->info
->SetSharedPixmapBacking
)
320 ret
= pExaScr
->info
->SetSharedPixmapBacking(pPixmap
, handle
);
323 exaMoveInPixmap(pPixmap
);