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 classic exa specific implementation. */ | |
35 | ||
36 | static _X_INLINE void * | |
37 | ExaGetPixmapAddress(PixmapPtr p) | |
38 | { | |
39 | ExaPixmapPriv(p); | |
40 | ||
41 | if (pExaPixmap->use_gpu_copy && pExaPixmap->fb_ptr) | |
42 | return pExaPixmap->fb_ptr; | |
43 | else | |
44 | return pExaPixmap->sys_ptr; | |
45 | } | |
46 | ||
47 | /** | |
48 | * exaCreatePixmap() creates a new pixmap. | |
49 | * | |
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. | |
54 | */ | |
55 | PixmapPtr | |
56 | exaCreatePixmap_classic(ScreenPtr pScreen, int w, int h, int depth, | |
57 | unsigned usage_hint) | |
58 | { | |
59 | PixmapPtr pPixmap; | |
60 | ExaPixmapPrivPtr pExaPixmap; | |
61 | BoxRec box; | |
62 | int bpp; | |
63 | ||
64 | ExaScreenPriv(pScreen); | |
65 | ||
66 | if (w > 32767 || h > 32767) | |
67 | return NullPixmap; | |
68 | ||
69 | swap(pExaScr, pScreen, CreatePixmap); | |
70 | pPixmap = pScreen->CreatePixmap(pScreen, w, h, depth, usage_hint); | |
71 | swap(pExaScr, pScreen, CreatePixmap); | |
72 | ||
73 | if (!pPixmap) | |
74 | return NULL; | |
75 | ||
76 | pExaPixmap = ExaGetPixmapPriv(pPixmap); | |
77 | pExaPixmap->driverPriv = NULL; | |
78 | ||
79 | bpp = pPixmap->drawable.bitsPerPixel; | |
80 | ||
81 | pExaPixmap->driverPriv = NULL; | |
82 | /* Scratch pixmaps may have w/h equal to zero, and may not be | |
83 | * migrated. | |
84 | */ | |
85 | if (!w || !h) | |
86 | pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED; | |
87 | else | |
88 | pExaPixmap->score = EXA_PIXMAP_SCORE_INIT; | |
89 | ||
90 | pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr; | |
91 | pExaPixmap->sys_pitch = pPixmap->devKind; | |
92 | ||
93 | pPixmap->devPrivate.ptr = NULL; | |
94 | pExaPixmap->use_gpu_copy = FALSE; | |
95 | ||
96 | pExaPixmap->fb_ptr = NULL; | |
97 | exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp); | |
98 | pExaPixmap->fb_size = pExaPixmap->fb_pitch * h; | |
99 | ||
100 | if (pExaPixmap->fb_pitch > 131071) { | |
101 | swap(pExaScr, pScreen, DestroyPixmap); | |
102 | pScreen->DestroyPixmap(pPixmap); | |
103 | swap(pExaScr, pScreen, DestroyPixmap); | |
104 | return NULL; | |
105 | } | |
106 | ||
107 | /* Set up damage tracking */ | |
108 | pExaPixmap->pDamage = DamageCreate(NULL, NULL, | |
109 | DamageReportNone, TRUE, | |
110 | pScreen, pPixmap); | |
111 | ||
112 | if (pExaPixmap->pDamage == NULL) { | |
113 | swap(pExaScr, pScreen, DestroyPixmap); | |
114 | pScreen->DestroyPixmap(pPixmap); | |
115 | swap(pExaScr, pScreen, DestroyPixmap); | |
116 | return NULL; | |
117 | } | |
118 | ||
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); | |
123 | ||
124 | pExaPixmap->area = NULL; | |
125 | ||
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. | |
130 | */ | |
131 | box.x1 = 0; | |
132 | box.y1 = 0; | |
133 | box.x2 = w; | |
134 | box.y2 = h; | |
135 | RegionInit(&pExaPixmap->validSys, &box, 0); | |
136 | RegionInit(&pExaPixmap->validFB, &box, 0); | |
137 | ||
138 | exaSetAccelBlock(pExaScr, pExaPixmap, w, h, bpp); | |
139 | ||
140 | /* During a fallback we must prepare access. */ | |
141 | if (pExaScr->fallback_counter) | |
142 | exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST); | |
143 | ||
144 | return pPixmap; | |
145 | } | |
146 | ||
147 | Bool | |
148 | exaModifyPixmapHeader_classic(PixmapPtr pPixmap, int width, int height, | |
149 | int depth, int bitsPerPixel, int devKind, | |
150 | pointer pPixData) | |
151 | { | |
152 | ScreenPtr pScreen; | |
153 | ExaScreenPrivPtr pExaScr; | |
154 | ExaPixmapPrivPtr pExaPixmap; | |
155 | Bool ret; | |
156 | ||
157 | if (!pPixmap) | |
158 | return FALSE; | |
159 | ||
160 | pScreen = pPixmap->drawable.pScreen; | |
161 | pExaScr = ExaGetScreenPriv(pScreen); | |
162 | pExaPixmap = ExaGetPixmapPriv(pPixmap); | |
163 | ||
164 | if (pExaPixmap) { | |
165 | if (pPixData) | |
166 | pExaPixmap->sys_ptr = pPixData; | |
167 | ||
168 | if (devKind > 0) | |
169 | pExaPixmap->sys_pitch = devKind; | |
170 | ||
171 | /* Classic EXA: | |
172 | * - Framebuffer. | |
173 | * - Scratch pixmap with gpu memory. | |
174 | */ | |
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; | |
182 | } | |
183 | } | |
184 | ||
185 | if (width > 0 && height > 0 && bitsPerPixel > 0) { | |
186 | exaSetFbPitch(pExaScr, pExaPixmap, width, height, bitsPerPixel); | |
187 | ||
188 | exaSetAccelBlock(pExaScr, pExaPixmap, width, height, bitsPerPixel); | |
189 | } | |
190 | ||
191 | /* Pixmaps subject to ModifyPixmapHeader will be pinned to system or | |
192 | * gpu memory, so there's no need to track damage. | |
193 | */ | |
194 | if (pExaPixmap->pDamage) { | |
195 | DamageDestroy(pExaPixmap->pDamage); | |
196 | pExaPixmap->pDamage = NULL; | |
197 | } | |
198 | } | |
199 | ||
200 | swap(pExaScr, pScreen, ModifyPixmapHeader); | |
201 | ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth, | |
202 | bitsPerPixel, devKind, pPixData); | |
203 | swap(pExaScr, pScreen, ModifyPixmapHeader); | |
204 | ||
205 | /* Always NULL this, we don't want lingering pointers. */ | |
206 | pPixmap->devPrivate.ptr = NULL; | |
207 | ||
208 | return ret; | |
209 | } | |
210 | ||
211 | Bool | |
212 | exaDestroyPixmap_classic(PixmapPtr pPixmap) | |
213 | { | |
214 | ScreenPtr pScreen = pPixmap->drawable.pScreen; | |
215 | ||
216 | ExaScreenPriv(pScreen); | |
217 | Bool ret; | |
218 | ||
219 | if (pPixmap->refcnt == 1) { | |
220 | ExaPixmapPriv(pPixmap); | |
221 | ||
222 | exaDestroyPixmap(pPixmap); | |
223 | ||
224 | if (pExaPixmap->area) { | |
225 | DBG_PIXMAP(("-- 0x%p (0x%x) (%dx%d)\n", | |
226 | (void *) pPixmap->drawable.id, | |
227 | ExaGetPixmapPriv(pPixmap)->area->offset, | |
228 | pPixmap->drawable.width, pPixmap->drawable.height)); | |
229 | /* Free the offscreen area */ | |
230 | exaOffscreenFree(pPixmap->drawable.pScreen, pExaPixmap->area); | |
231 | pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr; | |
232 | pPixmap->devKind = pExaPixmap->sys_pitch; | |
233 | } | |
234 | RegionUninit(&pExaPixmap->validSys); | |
235 | RegionUninit(&pExaPixmap->validFB); | |
236 | } | |
237 | ||
238 | swap(pExaScr, pScreen, DestroyPixmap); | |
239 | ret = pScreen->DestroyPixmap(pPixmap); | |
240 | swap(pExaScr, pScreen, DestroyPixmap); | |
241 | ||
242 | return ret; | |
243 | } | |
244 | ||
245 | Bool | |
246 | exaPixmapHasGpuCopy_classic(PixmapPtr pPixmap) | |
247 | { | |
248 | ScreenPtr pScreen = pPixmap->drawable.pScreen; | |
249 | ||
250 | ExaScreenPriv(pScreen); | |
251 | ExaPixmapPriv(pPixmap); | |
252 | Bool ret; | |
253 | ||
254 | if (pExaScr->info->PixmapIsOffscreen) { | |
255 | void *old_ptr = pPixmap->devPrivate.ptr; | |
256 | ||
257 | pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap); | |
258 | ret = pExaScr->info->PixmapIsOffscreen(pPixmap); | |
259 | pPixmap->devPrivate.ptr = old_ptr; | |
260 | } | |
261 | else | |
262 | ret = (pExaPixmap->use_gpu_copy && pExaPixmap->fb_ptr); | |
263 | ||
264 | return ret; | |
265 | } |