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 classic exa specific implementation. */
36 static _X_INLINE
void *
37 ExaGetPixmapAddress(PixmapPtr p
)
41 if (pExaPixmap
->use_gpu_copy
&& pExaPixmap
->fb_ptr
)
42 return pExaPixmap
->fb_ptr
;
44 return pExaPixmap
->sys_ptr
;
48 * exaCreatePixmap() creates a new pixmap.
50 * If width and height are 0, this won't be a full-fledged pixmap and it will
51 * get ModifyPixmapHeader() called on it later. So, we mark it as pinned, because
52 * ModifyPixmapHeader() would break migration. These types of pixmaps are used
53 * for scratch pixmaps, or to represent the visible screen.
56 exaCreatePixmap_classic(ScreenPtr pScreen
, int w
, int h
, int depth
,
60 ExaPixmapPrivPtr pExaPixmap
;
64 ExaScreenPriv(pScreen
);
66 if (w
> 32767 || h
> 32767)
69 swap(pExaScr
, pScreen
, CreatePixmap
);
70 pPixmap
= pScreen
->CreatePixmap(pScreen
, w
, h
, depth
, usage_hint
);
71 swap(pExaScr
, pScreen
, CreatePixmap
);
76 pExaPixmap
= ExaGetPixmapPriv(pPixmap
);
77 pExaPixmap
->driverPriv
= NULL
;
79 bpp
= pPixmap
->drawable
.bitsPerPixel
;
81 pExaPixmap
->driverPriv
= NULL
;
82 /* Scratch pixmaps may have w/h equal to zero, and may not be
86 pExaPixmap
->score
= EXA_PIXMAP_SCORE_PINNED
;
88 pExaPixmap
->score
= EXA_PIXMAP_SCORE_INIT
;
90 pExaPixmap
->sys_ptr
= pPixmap
->devPrivate
.ptr
;
91 pExaPixmap
->sys_pitch
= pPixmap
->devKind
;
93 pPixmap
->devPrivate
.ptr
= NULL
;
94 pExaPixmap
->use_gpu_copy
= FALSE
;
96 pExaPixmap
->fb_ptr
= NULL
;
97 exaSetFbPitch(pExaScr
, pExaPixmap
, w
, h
, bpp
);
98 pExaPixmap
->fb_size
= pExaPixmap
->fb_pitch
* h
;
100 if (pExaPixmap
->fb_pitch
> 131071) {
101 swap(pExaScr
, pScreen
, DestroyPixmap
);
102 pScreen
->DestroyPixmap(pPixmap
);
103 swap(pExaScr
, pScreen
, DestroyPixmap
);
107 /* Set up damage tracking */
108 pExaPixmap
->pDamage
= DamageCreate(NULL
, NULL
,
109 DamageReportNone
, TRUE
,
112 if (pExaPixmap
->pDamage
== NULL
) {
113 swap(pExaScr
, pScreen
, DestroyPixmap
);
114 pScreen
->DestroyPixmap(pPixmap
);
115 swap(pExaScr
, pScreen
, DestroyPixmap
);
119 DamageRegister(&pPixmap
->drawable
, pExaPixmap
->pDamage
);
120 /* This ensures that pending damage reflects the current operation. */
121 /* This is used by exa to optimize migration. */
122 DamageSetReportAfterOp(pExaPixmap
->pDamage
, TRUE
);
124 pExaPixmap
->area
= NULL
;
126 /* We set the initial pixmap as completely valid for a simple reason.
127 * Imagine a 1000x1000 pixmap, it has 1 million pixels, 250000 of which
128 * could form single pixel rects as part of a region. Setting the complete region
129 * as valid is a natural defragmentation of the region.
135 RegionInit(&pExaPixmap
->validSys
, &box
, 0);
136 RegionInit(&pExaPixmap
->validFB
, &box
, 0);
138 exaSetAccelBlock(pExaScr
, pExaPixmap
, w
, h
, bpp
);
140 /* During a fallback we must prepare access. */
141 if (pExaScr
->fallback_counter
)
142 exaPrepareAccess(&pPixmap
->drawable
, EXA_PREPARE_AUX_DEST
);
148 exaModifyPixmapHeader_classic(PixmapPtr pPixmap
, int width
, int height
,
149 int depth
, int bitsPerPixel
, int devKind
,
153 ExaScreenPrivPtr pExaScr
;
154 ExaPixmapPrivPtr pExaPixmap
;
160 pScreen
= pPixmap
->drawable
.pScreen
;
161 pExaScr
= ExaGetScreenPriv(pScreen
);
162 pExaPixmap
= ExaGetPixmapPriv(pPixmap
);
166 pExaPixmap
->sys_ptr
= pPixData
;
169 pExaPixmap
->sys_pitch
= devKind
;
173 * - Scratch pixmap with gpu memory.
175 if (pExaScr
->info
->memoryBase
&& pPixData
) {
176 if ((CARD8
*) pPixData
>= pExaScr
->info
->memoryBase
&&
177 ((CARD8
*) pPixData
- pExaScr
->info
->memoryBase
) <
178 pExaScr
->info
->memorySize
) {
179 pExaPixmap
->fb_ptr
= pPixData
;
180 pExaPixmap
->fb_pitch
= devKind
;
181 pExaPixmap
->use_gpu_copy
= TRUE
;
185 if (width
> 0 && height
> 0 && bitsPerPixel
> 0) {
186 exaSetFbPitch(pExaScr
, pExaPixmap
, width
, height
, bitsPerPixel
);
188 exaSetAccelBlock(pExaScr
, pExaPixmap
, width
, height
, bitsPerPixel
);
191 /* Pixmaps subject to ModifyPixmapHeader will be pinned to system or
192 * gpu memory, so there's no need to track damage.
194 if (pExaPixmap
->pDamage
) {
195 DamageUnregister(&pPixmap
->drawable
, pExaPixmap
->pDamage
);
196 DamageDestroy(pExaPixmap
->pDamage
);
197 pExaPixmap
->pDamage
= NULL
;
201 swap(pExaScr
, pScreen
, ModifyPixmapHeader
);
202 ret
= pScreen
->ModifyPixmapHeader(pPixmap
, width
, height
, depth
,
203 bitsPerPixel
, devKind
, pPixData
);
204 swap(pExaScr
, pScreen
, ModifyPixmapHeader
);
206 /* Always NULL this, we don't want lingering pointers. */
207 pPixmap
->devPrivate
.ptr
= NULL
;
213 exaDestroyPixmap_classic(PixmapPtr pPixmap
)
215 ScreenPtr pScreen
= pPixmap
->drawable
.pScreen
;
217 ExaScreenPriv(pScreen
);
220 if (pPixmap
->refcnt
== 1) {
221 ExaPixmapPriv(pPixmap
);
223 exaDestroyPixmap(pPixmap
);
225 if (pExaPixmap
->area
) {
226 DBG_PIXMAP(("-- 0x%p (0x%x) (%dx%d)\n",
227 (void *) pPixmap
->drawable
.id
,
228 ExaGetPixmapPriv(pPixmap
)->area
->offset
,
229 pPixmap
->drawable
.width
, pPixmap
->drawable
.height
));
230 /* Free the offscreen area */
231 exaOffscreenFree(pPixmap
->drawable
.pScreen
, pExaPixmap
->area
);
232 pPixmap
->devPrivate
.ptr
= pExaPixmap
->sys_ptr
;
233 pPixmap
->devKind
= pExaPixmap
->sys_pitch
;
235 RegionUninit(&pExaPixmap
->validSys
);
236 RegionUninit(&pExaPixmap
->validFB
);
239 swap(pExaScr
, pScreen
, DestroyPixmap
);
240 ret
= pScreen
->DestroyPixmap(pPixmap
);
241 swap(pExaScr
, pScreen
, DestroyPixmap
);
247 exaPixmapHasGpuCopy_classic(PixmapPtr pPixmap
)
249 ScreenPtr pScreen
= pPixmap
->drawable
.pScreen
;
251 ExaScreenPriv(pScreen
);
252 ExaPixmapPriv(pPixmap
);
255 if (pExaScr
->info
->PixmapIsOffscreen
) {
256 void *old_ptr
= pPixmap
->devPrivate
.ptr
;
258 pPixmap
->devPrivate
.ptr
= ExaGetPixmapAddress(pPixmap
);
259 ret
= pExaScr
->info
->PixmapIsOffscreen(pPixmap
);
260 pPixmap
->devPrivate
.ptr
= old_ptr
;
263 ret
= (pExaPixmap
->use_gpu_copy
&& pExaPixmap
->fb_ptr
);