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 classic exa specific implementation. */
35 ExaGetPixmapAddress(PixmapPtr p
)
39 if (pExaPixmap
->use_gpu_copy
&& pExaPixmap
->fb_ptr
)
40 return pExaPixmap
->fb_ptr
;
42 return pExaPixmap
->sys_ptr
;
46 * exaCreatePixmap() creates a new pixmap.
48 * If width and height are 0, this won't be a full-fledged pixmap and it will
49 * get ModifyPixmapHeader() called on it later. So, we mark it as pinned, because
50 * ModifyPixmapHeader() would break migration. These types of pixmaps are used
51 * for scratch pixmaps, or to represent the visible screen.
54 exaCreatePixmap_classic(ScreenPtr pScreen
, int w
, int h
, int depth
,
58 ExaPixmapPrivPtr pExaPixmap
;
62 ExaScreenPriv(pScreen
);
64 if (w
> 32767 || h
> 32767)
67 swap(pExaScr
, pScreen
, CreatePixmap
);
68 pPixmap
= pScreen
->CreatePixmap(pScreen
, w
, h
, depth
, usage_hint
);
69 swap(pExaScr
, pScreen
, CreatePixmap
);
74 pExaPixmap
= ExaGetPixmapPriv(pPixmap
);
75 pExaPixmap
->driverPriv
= NULL
;
77 bpp
= pPixmap
->drawable
.bitsPerPixel
;
79 pExaPixmap
->driverPriv
= NULL
;
80 /* Scratch pixmaps may have w/h equal to zero, and may not be
84 pExaPixmap
->score
= EXA_PIXMAP_SCORE_PINNED
;
86 pExaPixmap
->score
= EXA_PIXMAP_SCORE_INIT
;
88 pExaPixmap
->sys_ptr
= pPixmap
->devPrivate
.ptr
;
89 pExaPixmap
->sys_pitch
= pPixmap
->devKind
;
91 pPixmap
->devPrivate
.ptr
= NULL
;
92 pExaPixmap
->use_gpu_copy
= FALSE
;
94 pExaPixmap
->fb_ptr
= NULL
;
95 exaSetFbPitch(pExaScr
, pExaPixmap
, w
, h
, bpp
);
96 pExaPixmap
->fb_size
= pExaPixmap
->fb_pitch
* h
;
98 if (pExaPixmap
->fb_pitch
> 131071) {
99 swap(pExaScr
, pScreen
, DestroyPixmap
);
100 pScreen
->DestroyPixmap(pPixmap
);
101 swap(pExaScr
, pScreen
, DestroyPixmap
);
105 /* Set up damage tracking */
106 pExaPixmap
->pDamage
= DamageCreate(NULL
, NULL
,
107 DamageReportNone
, TRUE
,
110 if (pExaPixmap
->pDamage
== NULL
) {
111 swap(pExaScr
, pScreen
, DestroyPixmap
);
112 pScreen
->DestroyPixmap(pPixmap
);
113 swap(pExaScr
, pScreen
, DestroyPixmap
);
117 DamageRegister(&pPixmap
->drawable
, pExaPixmap
->pDamage
);
118 /* This ensures that pending damage reflects the current operation. */
119 /* This is used by exa to optimize migration. */
120 DamageSetReportAfterOp(pExaPixmap
->pDamage
, TRUE
);
122 pExaPixmap
->area
= NULL
;
124 /* We set the initial pixmap as completely valid for a simple reason.
125 * Imagine a 1000x1000 pixmap, it has 1 million pixels, 250000 of which
126 * could form single pixel rects as part of a region. Setting the complete region
127 * as valid is a natural defragmentation of the region.
133 RegionInit(&pExaPixmap
->validSys
, &box
, 0);
134 RegionInit(&pExaPixmap
->validFB
, &box
, 0);
136 exaSetAccelBlock(pExaScr
, pExaPixmap
, w
, h
, bpp
);
138 /* During a fallback we must prepare access. */
139 if (pExaScr
->fallback_counter
)
140 exaPrepareAccess(&pPixmap
->drawable
, EXA_PREPARE_AUX_DEST
);
146 exaModifyPixmapHeader_classic(PixmapPtr pPixmap
, int width
, int height
,
147 int depth
, int bitsPerPixel
, int devKind
,
151 ExaScreenPrivPtr pExaScr
;
152 ExaPixmapPrivPtr pExaPixmap
;
158 pScreen
= pPixmap
->drawable
.pScreen
;
159 pExaScr
= ExaGetScreenPriv(pScreen
);
160 pExaPixmap
= ExaGetPixmapPriv(pPixmap
);
164 pExaPixmap
->sys_ptr
= pPixData
;
167 pExaPixmap
->sys_pitch
= devKind
;
171 * - Scratch pixmap with gpu memory.
173 if (pExaScr
->info
->memoryBase
&& pPixData
) {
174 if ((CARD8
*) pPixData
>= pExaScr
->info
->memoryBase
&&
175 ((CARD8
*) pPixData
- pExaScr
->info
->memoryBase
) <
176 pExaScr
->info
->memorySize
) {
177 pExaPixmap
->fb_ptr
= pPixData
;
178 pExaPixmap
->fb_pitch
= devKind
;
179 pExaPixmap
->use_gpu_copy
= TRUE
;
183 if (width
> 0 && height
> 0 && bitsPerPixel
> 0) {
184 exaSetFbPitch(pExaScr
, pExaPixmap
, width
, height
, bitsPerPixel
);
186 exaSetAccelBlock(pExaScr
, pExaPixmap
, width
, height
, bitsPerPixel
);
189 /* Pixmaps subject to ModifyPixmapHeader will be pinned to system or
190 * gpu memory, so there's no need to track damage.
192 if (pExaPixmap
->pDamage
) {
193 DamageDestroy(pExaPixmap
->pDamage
);
194 pExaPixmap
->pDamage
= NULL
;
198 swap(pExaScr
, pScreen
, ModifyPixmapHeader
);
199 ret
= pScreen
->ModifyPixmapHeader(pPixmap
, width
, height
, depth
,
200 bitsPerPixel
, devKind
, pPixData
);
201 swap(pExaScr
, pScreen
, ModifyPixmapHeader
);
203 /* Always NULL this, we don't want lingering pointers. */
204 pPixmap
->devPrivate
.ptr
= NULL
;
210 exaDestroyPixmap_classic(PixmapPtr pPixmap
)
212 ScreenPtr pScreen
= pPixmap
->drawable
.pScreen
;
214 ExaScreenPriv(pScreen
);
217 if (pPixmap
->refcnt
== 1) {
218 ExaPixmapPriv(pPixmap
);
220 exaDestroyPixmap(pPixmap
);
222 if (pExaPixmap
->area
) {
223 DBG_PIXMAP(("-- 0x%p (0x%x) (%dx%d)\n",
224 (void *) pPixmap
->drawable
.id
,
225 ExaGetPixmapPriv(pPixmap
)->area
->offset
,
226 pPixmap
->drawable
.width
, pPixmap
->drawable
.height
));
227 /* Free the offscreen area */
228 exaOffscreenFree(pPixmap
->drawable
.pScreen
, pExaPixmap
->area
);
229 pPixmap
->devPrivate
.ptr
= pExaPixmap
->sys_ptr
;
230 pPixmap
->devKind
= pExaPixmap
->sys_pitch
;
232 RegionUninit(&pExaPixmap
->validSys
);
233 RegionUninit(&pExaPixmap
->validFB
);
236 swap(pExaScr
, pScreen
, DestroyPixmap
);
237 ret
= pScreen
->DestroyPixmap(pPixmap
);
238 swap(pExaScr
, pScreen
, DestroyPixmap
);
244 exaPixmapHasGpuCopy_classic(PixmapPtr pPixmap
)
246 ScreenPtr pScreen
= pPixmap
->drawable
.pScreen
;
248 ExaScreenPriv(pScreen
);
249 ExaPixmapPriv(pPixmap
);
252 if (pExaScr
->info
->PixmapIsOffscreen
) {
253 void *old_ptr
= pPixmap
->devPrivate
.ptr
;
255 pPixmap
->devPrivate
.ptr
= ExaGetPixmapAddress(pPixmap
);
256 ret
= pExaScr
->info
->PixmapIsOffscreen(pPixmap
);
257 pPixmap
->devPrivate
.ptr
= old_ptr
;
260 ret
= (pExaPixmap
->use_gpu_copy
&& pExaPixmap
->fb_ptr
);