Bug Summary

File:exa/exa.c
Location:line 1043, column 9
Description:Access to field 'Glyphs' results in a dereference of a null pointer (loaded from variable 'ps')

Annotated Source Code

1/*
2 * Copyright © 2001 Keith Packard
3 *
4 * Partly based on code that is Copyright © The XFree86 Project Inc.
5 *
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of Keith Packard not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission. Keith Packard makes no
13 * representations about the suitability of this software for any purpose. It
14 * is provided "as is" without express or implied warranty.
15 *
16 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 * PERFORMANCE OF THIS SOFTWARE.
23 */
24
25/** @file
26 * This file covers the initialization and teardown of EXA, and has various
27 * functions not responsible for performing rendering, pixmap migration, or
28 * memory management.
29 */
30
31#ifdef HAVE_DIX_CONFIG_H1
32#include <dix-config.h>
33#endif
34
35#include <stdlib.h>
36
37#include "exa_priv.h"
38#include "exa.h"
39
40DevPrivateKeyRec exaScreenPrivateKeyRec;
41
42#ifdef MITSHM1
43static ShmFuncs exaShmFuncs = { NULL((void*)0), NULL((void*)0) };
44#endif
45
46/**
47 * exaGetPixmapOffset() returns the offset (in bytes) within the framebuffer of
48 * the beginning of the given pixmap.
49 *
50 * Note that drivers are free to, and often do, munge this offset as necessary
51 * for handing to the hardware -- for example, translating it into a different
52 * aperture. This function may need to be extended in the future if we grow
53 * support for having multiple card-accessible offscreen, such as an AGP memory
54 * pool alongside the framebuffer pool.
55 */
56unsigned long
57exaGetPixmapOffset(PixmapPtr pPix)
58{
59 ExaScreenPriv(pPix->drawable.pScreen)ExaScreenPrivPtr pExaScr = ((ExaScreenPrivPtr)dixGetPrivate(&
(pPix->drawable.pScreen)->devPrivates, (&exaScreenPrivateKeyRec
)))
;
60 ExaPixmapPriv(pPix)ExaPixmapPrivPtr pExaPixmap = ((ExaPixmapPrivPtr)dixGetPrivateAddr
(&(pPix)->devPrivates, &((ExaScreenPrivPtr)dixGetPrivate
(&((pPix)->drawable.pScreen)->devPrivates, (&exaScreenPrivateKeyRec
)))->pixmapPrivateKeyRec))
;
61
62 return (CARD8 *) pExaPixmap->fb_ptr - pExaScr->info->memoryBase;
63}
64
65void *
66exaGetPixmapDriverPrivate(PixmapPtr pPix)
67{
68 ExaPixmapPriv(pPix)ExaPixmapPrivPtr pExaPixmap = ((ExaPixmapPrivPtr)dixGetPrivateAddr
(&(pPix)->devPrivates, &((ExaScreenPrivPtr)dixGetPrivate
(&((pPix)->drawable.pScreen)->devPrivates, (&exaScreenPrivateKeyRec
)))->pixmapPrivateKeyRec))
;
69
70 return pExaPixmap->driverPriv;
71}
72
73/**
74 * exaGetPixmapPitch() returns the pitch (in bytes) of the given pixmap.
75 *
76 * This is a helper to make driver code more obvious, due to the rather obscure
77 * naming of the pitch field in the pixmap.
78 */
79unsigned long
80exaGetPixmapPitch(PixmapPtr pPix)
81{
82 return pPix->devKind;
83}
84
85/**
86 * exaGetPixmapSize() returns the size in bytes of the given pixmap in video
87 * memory. Only valid when the pixmap is currently in framebuffer.
88 */
89unsigned long
90exaGetPixmapSize(PixmapPtr pPix)
91{
92 ExaPixmapPrivPtr pExaPixmap;
93
94 pExaPixmap = ExaGetPixmapPriv(pPix)((ExaPixmapPrivPtr)dixGetPrivateAddr(&(pPix)->devPrivates
, &((ExaScreenPrivPtr)dixGetPrivate(&((pPix)->drawable
.pScreen)->devPrivates, (&exaScreenPrivateKeyRec)))->
pixmapPrivateKeyRec))
;
95 if (pExaPixmap != NULL((void*)0))
96 return pExaPixmap->fb_size;
97 return 0;
98}
99
100/**
101 * exaGetDrawablePixmap() returns a backing pixmap for a given drawable.
102 *
103 * @param pDrawable the drawable being requested.
104 *
105 * This function returns the backing pixmap for a drawable, whether it is a
106 * redirected window, unredirected window, or already a pixmap. Note that
107 * coordinate translation is needed when drawing to the backing pixmap of a
108 * redirected window, and the translation coordinates are provided by calling
109 * exaGetOffscreenPixmap() on the drawable.
110 */
111PixmapPtr
112exaGetDrawablePixmap(DrawablePtr pDrawable)
113{
114 if (pDrawable->type == DRAWABLE_WINDOW0)
115 return pDrawable->pScreen->GetWindowPixmap((WindowPtr) pDrawable);
116 else
117 return (PixmapPtr) pDrawable;
118}
119
120/**
121 * Sets the offsets to add to coordinates to make them address the same bits in
122 * the backing drawable. These coordinates are nonzero only for redirected
123 * windows.
124 */
125void
126exaGetDrawableDeltas(DrawablePtr pDrawable, PixmapPtr pPixmap, int *xp, int *yp)
127{
128#ifdef COMPOSITE
129 if (pDrawable->type == DRAWABLE_WINDOW0) {
130 *xp = -pPixmap->screen_x;
131 *yp = -pPixmap->screen_y;
132 return;
133 }
134#endif
135
136 *xp = 0;
137 *yp = 0;
138}
139
140/**
141 * exaPixmapDirty() marks a pixmap as dirty, allowing for
142 * optimizations in pixmap migration when no changes have occurred.
143 */
144void
145exaPixmapDirty(PixmapPtr pPix, int x1, int y1, int x2, int y2)
146{
147 BoxRec box;
148 RegionRec region;
149
150 box.x1 = max(x1, 0)(((x1) > (0)) ? (x1) : (0));
151 box.y1 = max(y1, 0)(((y1) > (0)) ? (y1) : (0));
152 box.x2 = min(x2, pPix->drawable.width)(((x2) < (pPix->drawable.width)) ? (x2) : (pPix->drawable
.width))
;
153 box.y2 = min(y2, pPix->drawable.height)(((y2) < (pPix->drawable.height)) ? (y2) : (pPix->drawable
.height))
;
154
155 if (box.x1 >= box.x2 || box.y1 >= box.y2)
156 return;
157
158 RegionInit(&region, &box, 1);
159 DamageDamageRegion(&pPix->drawable, &region);
160 RegionUninit(&region);
161}
162
163static int
164exaLog2(int val)
165{
166 int bits;
167
168 if (val <= 0)
169 return 0;
170 for (bits = 0; val != 0; bits++)
171 val >>= 1;
172 return bits - 1;
173}
174
175void
176exaSetAccelBlock(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
177 int w, int h, int bpp)
178{
179 pExaPixmap->accel_blocked = 0;
180
181 if (pExaScr->info->maxPitchPixels) {
182 int max_pitch = pExaScr->info->maxPitchPixels * bits_to_bytes(bpp);
183
184 if (pExaPixmap->fb_pitch > max_pitch)
185 pExaPixmap->accel_blocked |= EXA_RANGE_PITCH(1 << 0);
186 }
187
188 if (pExaScr->info->maxPitchBytes &&
189 pExaPixmap->fb_pitch > pExaScr->info->maxPitchBytes)
190 pExaPixmap->accel_blocked |= EXA_RANGE_PITCH(1 << 0);
191
192 if (w > pExaScr->info->maxX)
193 pExaPixmap->accel_blocked |= EXA_RANGE_WIDTH(1 << 1);
194
195 if (h > pExaScr->info->maxY)
196 pExaPixmap->accel_blocked |= EXA_RANGE_HEIGHT(1 << 2);
197}
198
199void
200exaSetFbPitch(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
201 int w, int h, int bpp)
202{
203 if (pExaScr->info->flags & EXA_OFFSCREEN_ALIGN_POT(1 << 1) && w != 1)
204 pExaPixmap->fb_pitch = bits_to_bytes((1 << (exaLog2(w - 1) + 1)) * bpp);
205 else
206 pExaPixmap->fb_pitch = bits_to_bytes(w * bpp);
207
208 pExaPixmap->fb_pitch = EXA_ALIGN(pExaPixmap->fb_pitch,(((pExaPixmap->fb_pitch) + (pExaScr->info->pixmapPitchAlign
) - 1) - (((pExaPixmap->fb_pitch) + (pExaScr->info->
pixmapPitchAlign) - 1) % (pExaScr->info->pixmapPitchAlign
)))
209 pExaScr->info->pixmapPitchAlign)(((pExaPixmap->fb_pitch) + (pExaScr->info->pixmapPitchAlign
) - 1) - (((pExaPixmap->fb_pitch) + (pExaScr->info->
pixmapPitchAlign) - 1) % (pExaScr->info->pixmapPitchAlign
)))
;
210}
211
212/**
213 * Returns TRUE if the pixmap is not movable. This is the case where it's a
214 * pixmap which has no private (almost always bad) or it's a scratch pixmap created by
215 * some X Server internal component (the score says it's pinned).
216 */
217Bool
218exaPixmapIsPinned(PixmapPtr pPix)
219{
220 ExaPixmapPriv(pPix)ExaPixmapPrivPtr pExaPixmap = ((ExaPixmapPrivPtr)dixGetPrivateAddr
(&(pPix)->devPrivates, &((ExaScreenPrivPtr)dixGetPrivate
(&((pPix)->drawable.pScreen)->devPrivates, (&exaScreenPrivateKeyRec
)))->pixmapPrivateKeyRec))
;
221
222 if (pExaPixmap == NULL((void*)0))
223 EXA_FatalErrorDebugWithRet(("EXA bug: exaPixmapIsPinned was called on a non-exa pixmap.\n"), TRUE)do { ErrorF ("EXA bug: exaPixmapIsPinned was called on a non-exa pixmap.\n"
); return 1; } while (0)
;
224
225 return pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED1000;
226}
227
228/**
229 * exaPixmapHasGpuCopy() is used to determine if a pixmap is in offscreen
230 * memory, meaning that acceleration could probably be done to it, and that it
231 * will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it
232 * with the CPU.
233 *
234 * Note that except for UploadToScreen()/DownloadFromScreen() (which explicitly
235 * deal with moving pixmaps in and out of system memory), EXA will give drivers
236 * pixmaps as arguments for which exaPixmapHasGpuCopy() is TRUE.
237 *
238 * @return TRUE if the given drawable is in framebuffer memory.
239 */
240Bool
241exaPixmapHasGpuCopy(PixmapPtr pPixmap)
242{
243 ScreenPtr pScreen = pPixmap->drawable.pScreen;
244
245 ExaScreenPriv(pScreen)ExaScreenPrivPtr pExaScr = ((ExaScreenPrivPtr)dixGetPrivate(&
(pScreen)->devPrivates, (&exaScreenPrivateKeyRec)))
;
246
247 if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS(1 << 0)))
248 return FALSE0;
249
250 return (*pExaScr->pixmap_has_gpu_copy) (pPixmap);
251}
252
253/**
254 * exaDrawableIsOffscreen() is a convenience wrapper for exaPixmapHasGpuCopy().
255 */
256Bool
257exaDrawableIsOffscreen(DrawablePtr pDrawable)
258{
259 return exaPixmapHasGpuCopy(exaGetDrawablePixmap(pDrawable));
260}
261
262/**
263 * Returns the pixmap which backs a drawable, and the offsets to add to
264 * coordinates to make them address the same bits in the backing drawable.
265 */
266PixmapPtr
267exaGetOffscreenPixmap(DrawablePtr pDrawable, int *xp, int *yp)
268{
269 PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);
270
271 exaGetDrawableDeltas(pDrawable, pPixmap, xp, yp);
272
273 if (exaPixmapHasGpuCopy(pPixmap))
274 return pPixmap;
275 else
276 return NULL((void*)0);
277}
278
279/**
280 * Returns TRUE if the pixmap GPU copy is being accessed.
281 */
282Bool
283ExaDoPrepareAccess(PixmapPtr pPixmap, int index)
284{
285 ScreenPtr pScreen = pPixmap->drawable.pScreen;
286
287 ExaScreenPriv(pScreen)ExaScreenPrivPtr pExaScr = ((ExaScreenPrivPtr)dixGetPrivate(&
(pScreen)->devPrivates, (&exaScreenPrivateKeyRec)))
;
288 ExaPixmapPriv(pPixmap)ExaPixmapPrivPtr pExaPixmap = ((ExaPixmapPrivPtr)dixGetPrivateAddr
(&(pPixmap)->devPrivates, &((ExaScreenPrivPtr)dixGetPrivate
(&((pPixmap)->drawable.pScreen)->devPrivates, (&
exaScreenPrivateKeyRec)))->pixmapPrivateKeyRec))
;
289 Bool has_gpu_copy, ret;
290 int i;
291
292 if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS(1 << 0)))
293 return FALSE0;
294
295 if (pExaPixmap == NULL((void*)0))
296 EXA_FatalErrorDebugWithRet(("EXA bug: ExaDoPrepareAccess was called on a non-exa pixmap.\n"), FALSE)do { ErrorF ("EXA bug: ExaDoPrepareAccess was called on a non-exa pixmap.\n"
); return 0; } while (0)
;
297
298 /* Handle repeated / nested calls. */
299 for (i = 0; i < EXA_NUM_PREPARE_INDICES6; i++) {
300 if (pExaScr->access[i].pixmap == pPixmap) {
301 pExaScr->access[i].count++;
302 return pExaScr->access[i].retval;
303 }
304 }
305
306 /* If slot for this index is taken, find an empty slot */
307 if (pExaScr->access[index].pixmap) {
308 for (index = EXA_NUM_PREPARE_INDICES6 - 1; index >= 0; index--)
309 if (!pExaScr->access[index].pixmap)
310 break;
311 }
312
313 /* Access to this pixmap hasn't been prepared yet, so data pointer should be NULL. */
314 if (pPixmap->devPrivate.ptr != NULL((void*)0)) {
315 EXA_FatalErrorDebug(("EXA bug: pPixmap->devPrivate.ptr was %p, but should have been NULL.\n", pPixmap->devPrivate.ptr))ErrorF ("EXA bug: pPixmap->devPrivate.ptr was %p, but should have been NULL.\n"
, pPixmap->devPrivate.ptr)
;
316 }
317
318 has_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
319
320 if (has_gpu_copy && pExaPixmap->fb_ptr) {
321 pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
322 ret = TRUE1;
323 }
324 else {
325 pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
326 ret = FALSE0;
327 }
328
329 /* Store so we can handle repeated / nested calls. */
330 pExaScr->access[index].pixmap = pPixmap;
331 pExaScr->access[index].count = 1;
332
333 if (!has_gpu_copy)
334 goto out;
335
336 exaWaitSync(pScreen);
337
338 if (pExaScr->info->PrepareAccess == NULL((void*)0))
339 goto out;
340
341 if (index >= EXA_PREPARE_AUX_DEST3 &&
342 !(pExaScr->info->flags & EXA_SUPPORTS_PREPARE_AUX(1 << 4))) {
343 if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED1000)
344 FatalError("Unsupported AUX indices used on a pinned pixmap.\n");
345 exaMoveOutPixmap(pPixmap);
346 ret = FALSE0;
347 goto out;
348 }
349
350 if (!(*pExaScr->info->PrepareAccess) (pPixmap, index)) {
351 if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED1000 &&
352 !(pExaScr->info->flags & EXA_MIXED_PIXMAPS(1 << 6)))
353 FatalError("Driver failed PrepareAccess on a pinned pixmap.\n");
354 exaMoveOutPixmap(pPixmap);
355 ret = FALSE0;
356 goto out;
357 }
358
359 ret = TRUE1;
360
361 out:
362 pExaScr->access[index].retval = ret;
363 return ret;
364}
365
366/**
367 * exaPrepareAccess() is EXA's wrapper for the driver's PrepareAccess() handler.
368 *
369 * It deals with waiting for synchronization with the card, determining if
370 * PrepareAccess() is necessary, and working around PrepareAccess() failure.
371 */
372void
373exaPrepareAccess(DrawablePtr pDrawable, int index)
374{
375 PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);
376
377 ExaScreenPriv(pDrawable->pScreen)ExaScreenPrivPtr pExaScr = ((ExaScreenPrivPtr)dixGetPrivate(&
(pDrawable->pScreen)->devPrivates, (&exaScreenPrivateKeyRec
)))
;
378
379 if (pExaScr->prepare_access_reg)
380 pExaScr->prepare_access_reg(pPixmap, index, NULL((void*)0));
381 else
382 (void) ExaDoPrepareAccess(pPixmap, index);
383}
384
385/**
386 * exaFinishAccess() is EXA's wrapper for the driver's FinishAccess() handler.
387 *
388 * It deals with calling the driver's FinishAccess() only if necessary.
389 */
390void
391exaFinishAccess(DrawablePtr pDrawable, int index)
392{
393 ScreenPtr pScreen = pDrawable->pScreen;
394
395 ExaScreenPriv(pScreen)ExaScreenPrivPtr pExaScr = ((ExaScreenPrivPtr)dixGetPrivate(&
(pScreen)->devPrivates, (&exaScreenPrivateKeyRec)))
;
396 PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);
397
398 ExaPixmapPriv(pPixmap)ExaPixmapPrivPtr pExaPixmap = ((ExaPixmapPrivPtr)dixGetPrivateAddr
(&(pPixmap)->devPrivates, &((ExaScreenPrivPtr)dixGetPrivate
(&((pPixmap)->drawable.pScreen)->devPrivates, (&
exaScreenPrivateKeyRec)))->pixmapPrivateKeyRec))
;
399 int i;
400
401 if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS(1 << 0)))
402 return;
403
404 if (pExaPixmap == NULL((void*)0))
405 EXA_FatalErrorDebugWithRet(("EXA bug: exaFinishAccesss was called on a non-exa pixmap.\n"),)do { ErrorF ("EXA bug: exaFinishAccesss was called on a non-exa pixmap.\n"
); return ; } while (0)
;
406
407 /* Handle repeated / nested calls. */
408 for (i = 0; i < EXA_NUM_PREPARE_INDICES6; i++) {
409 if (pExaScr->access[i].pixmap == pPixmap) {
410 if (--pExaScr->access[i].count > 0)
411 return;
412 break;
413 }
414 }
415
416 /* Catch unbalanced Prepare/FinishAccess calls. */
417 if (i == EXA_NUM_PREPARE_INDICES6)
418 EXA_FatalErrorDebugWithRet(("EXA bug: FinishAccess called without PrepareAccess for pixmap 0x%p.\n", pPixmap),)do { ErrorF ("EXA bug: FinishAccess called without PrepareAccess for pixmap 0x%p.\n"
, pPixmap); return ; } while (0)
;
419
420 pExaScr->access[i].pixmap = NULL((void*)0);
421
422 /* We always hide the devPrivate.ptr. */
423 pPixmap->devPrivate.ptr = NULL((void*)0);
424
425 /* Only call FinishAccess if PrepareAccess was called and succeeded. */
426 if (!pExaScr->info->FinishAccess || !pExaScr->access[i].retval)
427 return;
428
429 if (i >= EXA_PREPARE_AUX_DEST3 &&
430 !(pExaScr->info->flags & EXA_SUPPORTS_PREPARE_AUX(1 << 4))) {
431 ErrorF("EXA bug: Trying to call driver FinishAccess hook with "
432 "unsupported index EXA_PREPARE_AUX*\n");
433 return;
434 }
435
436 (*pExaScr->info->FinishAccess) (pPixmap, i);
437}
438
439/**
440 * Helper for things common to all schemes when a pixmap is destroyed
441 */
442void
443exaDestroyPixmap(PixmapPtr pPixmap)
444{
445 ExaScreenPriv(pPixmap->drawable.pScreen)ExaScreenPrivPtr pExaScr = ((ExaScreenPrivPtr)dixGetPrivate(&
(pPixmap->drawable.pScreen)->devPrivates, (&exaScreenPrivateKeyRec
)))
;
446 int i;
447
448 /* Finish access if it was prepared (e.g. pixmap created during
449 * software fallback)
450 */
451 for (i = 0; i < EXA_NUM_PREPARE_INDICES6; i++) {
452 if (pExaScr->access[i].pixmap == pPixmap) {
453 exaFinishAccess(&pPixmap->drawable, i);
454 pExaScr->access[i].pixmap = NULL((void*)0);
455 break;
456 }
457 }
458}
459
460/**
461 * Here begins EXA's GC code.
462 * Do not ever access the fb/mi layer directly.
463 */
464
465static void
466 exaValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable);
467
468static void
469 exaDestroyGC(GCPtr pGC);
470
471static void
472 exaChangeGC(GCPtr pGC, unsigned long mask);
473
474static void
475 exaCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst);
476
477static void
478 exaChangeClip(GCPtr pGC, int type, void *pvalue, int nrects);
479
480static void
481 exaCopyClip(GCPtr pGCDst, GCPtr pGCSrc);
482
483static void
484 exaDestroyClip(GCPtr pGC);
485
486const GCFuncs exaGCFuncs = {
487 exaValidateGC,
488 exaChangeGC,
489 exaCopyGC,
490 exaDestroyGC,
491 exaChangeClip,
492 exaDestroyClip,
493 exaCopyClip
494};
495
496static void
497exaValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
498{
499 /* fbValidateGC will do direct access to pixmaps if the tiling has changed.
500 * Do a few smart things so fbValidateGC can do it's work.
501 */
502
503 ScreenPtr pScreen = pDrawable->pScreen;
504
505 ExaScreenPriv(pScreen)ExaScreenPrivPtr pExaScr = ((ExaScreenPrivPtr)dixGetPrivate(&
(pScreen)->devPrivates, (&exaScreenPrivateKeyRec)))
;
506 ExaGCPriv(pGC)ExaGCPrivPtr pExaGC = ((ExaGCPrivPtr)dixGetPrivateAddr(&(
pGC)->devPrivates, &((ExaScreenPrivPtr)dixGetPrivate(&
(pGC->pScreen)->devPrivates, (&exaScreenPrivateKeyRec
)))->gcPrivateKeyRec))
;
507 PixmapPtr pTile = NULL((void*)0);
508 Bool finish_current_tile = FALSE0;
509
510 /* Either of these conditions is enough to trigger access to a tile pixmap. */
511 /* With pGC->tileIsPixel == 1, you run the risk of dereferencing an invalid tile pixmap pointer. */
512 if (pGC->fillStyle == FillTiled1 ||
513 ((changes & GCTile(1L<<10)) && !pGC->tileIsPixel)) {
514 pTile = pGC->tile.pixmap;
515
516 /* Sometimes tile pixmaps are swapped, you need access to:
517 * - The current tile if it depth matches.
518 * - Or the rotated tile if that one matches depth and !(changes & GCTile).
519 * - Or the current tile pixmap and a newly created one.
520 */
521 if (pTile && pTile->drawable.depth != pDrawable->depth &&
522 !(changes & GCTile(1L<<10))) {
523 PixmapPtr pRotatedTile = fbGetRotatedPixmap(pGC)((pGC)->pRotatedPixmap);
524
525 if (pRotatedTile &&
526 pRotatedTile->drawable.depth == pDrawable->depth)
527 pTile = pRotatedTile;
528 else
529 finish_current_tile = TRUE1; /* CreatePixmap will be called. */
530 }
531 }
532
533 if (pGC->stipple)
534 exaPrepareAccess(&pGC->stipple->drawable, EXA_PREPARE_MASK2);
535 if (pTile)
536 exaPrepareAccess(&pTile->drawable, EXA_PREPARE_SRC1);
537
538 /* Calls to Create/DestroyPixmap have to be identified as special. */
539 pExaScr->fallback_counter++;
540 swap(pExaGC, pGC, funcs){ typeof(pGC->funcs) tmp = pExaGC->Savedfuncs; pExaGC->
Savedfuncs = pGC->funcs; pGC->funcs = tmp; }
;
541 (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable);
542 swap(pExaGC, pGC, funcs){ typeof(pGC->funcs) tmp = pExaGC->Savedfuncs; pExaGC->
Savedfuncs = pGC->funcs; pGC->funcs = tmp; }
;
543 pExaScr->fallback_counter--;
544
545 if (pTile)
546 exaFinishAccess(&pTile->drawable, EXA_PREPARE_SRC1);
547 if (finish_current_tile && pGC->tile.pixmap)
548 exaFinishAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_AUX_DEST3);
549 if (pGC->stipple)
550 exaFinishAccess(&pGC->stipple->drawable, EXA_PREPARE_MASK2);
551}
552
553/* Is exaPrepareAccessGC() needed? */
554static void
555exaDestroyGC(GCPtr pGC)
556{
557 ExaGCPriv(pGC)ExaGCPrivPtr pExaGC = ((ExaGCPrivPtr)dixGetPrivateAddr(&(
pGC)->devPrivates, &((ExaScreenPrivPtr)dixGetPrivate(&
(pGC->pScreen)->devPrivates, (&exaScreenPrivateKeyRec
)))->gcPrivateKeyRec))
;
558 swap(pExaGC, pGC, funcs){ typeof(pGC->funcs) tmp = pExaGC->Savedfuncs; pExaGC->
Savedfuncs = pGC->funcs; pGC->funcs = tmp; }
;
559 (*pGC->funcs->DestroyGC) (pGC);
560 swap(pExaGC, pGC, funcs){ typeof(pGC->funcs) tmp = pExaGC->Savedfuncs; pExaGC->
Savedfuncs = pGC->funcs; pGC->funcs = tmp; }
;
561}
562
563static void
564exaChangeGC(GCPtr pGC, unsigned long mask)
565{
566 ExaGCPriv(pGC)ExaGCPrivPtr pExaGC = ((ExaGCPrivPtr)dixGetPrivateAddr(&(
pGC)->devPrivates, &((ExaScreenPrivPtr)dixGetPrivate(&
(pGC->pScreen)->devPrivates, (&exaScreenPrivateKeyRec
)))->gcPrivateKeyRec))
;
567 swap(pExaGC, pGC, funcs){ typeof(pGC->funcs) tmp = pExaGC->Savedfuncs; pExaGC->
Savedfuncs = pGC->funcs; pGC->funcs = tmp; }
;
568 (*pGC->funcs->ChangeGC) (pGC, mask);
569 swap(pExaGC, pGC, funcs){ typeof(pGC->funcs) tmp = pExaGC->Savedfuncs; pExaGC->
Savedfuncs = pGC->funcs; pGC->funcs = tmp; }
;
570}
571
572static void
573exaCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst)
574{
575 ExaGCPriv(pGCDst)ExaGCPrivPtr pExaGC = ((ExaGCPrivPtr)dixGetPrivateAddr(&(
pGCDst)->devPrivates, &((ExaScreenPrivPtr)dixGetPrivate
(&(pGCDst->pScreen)->devPrivates, (&exaScreenPrivateKeyRec
)))->gcPrivateKeyRec))
;
576 swap(pExaGC, pGCDst, funcs){ typeof(pGCDst->funcs) tmp = pExaGC->Savedfuncs; pExaGC
->Savedfuncs = pGCDst->funcs; pGCDst->funcs = tmp; }
;
577 (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
578 swap(pExaGC, pGCDst, funcs){ typeof(pGCDst->funcs) tmp = pExaGC->Savedfuncs; pExaGC
->Savedfuncs = pGCDst->funcs; pGCDst->funcs = tmp; }
;
579}
580
581static void
582exaChangeClip(GCPtr pGC, int type, void *pvalue, int nrects)
583{
584 ExaGCPriv(pGC)ExaGCPrivPtr pExaGC = ((ExaGCPrivPtr)dixGetPrivateAddr(&(
pGC)->devPrivates, &((ExaScreenPrivPtr)dixGetPrivate(&
(pGC->pScreen)->devPrivates, (&exaScreenPrivateKeyRec
)))->gcPrivateKeyRec))
;
585 swap(pExaGC, pGC, funcs){ typeof(pGC->funcs) tmp = pExaGC->Savedfuncs; pExaGC->
Savedfuncs = pGC->funcs; pGC->funcs = tmp; }
;
586 (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
587 swap(pExaGC, pGC, funcs){ typeof(pGC->funcs) tmp = pExaGC->Savedfuncs; pExaGC->
Savedfuncs = pGC->funcs; pGC->funcs = tmp; }
;
588}
589
590static void
591exaCopyClip(GCPtr pGCDst, GCPtr pGCSrc)
592{
593 ExaGCPriv(pGCDst)ExaGCPrivPtr pExaGC = ((ExaGCPrivPtr)dixGetPrivateAddr(&(
pGCDst)->devPrivates, &((ExaScreenPrivPtr)dixGetPrivate
(&(pGCDst->pScreen)->devPrivates, (&exaScreenPrivateKeyRec
)))->gcPrivateKeyRec))
;
594 swap(pExaGC, pGCDst, funcs){ typeof(pGCDst->funcs) tmp = pExaGC->Savedfuncs; pExaGC
->Savedfuncs = pGCDst->funcs; pGCDst->funcs = tmp; }
;
595 (*pGCDst->funcs->CopyClip) (pGCDst, pGCSrc);
596 swap(pExaGC, pGCDst, funcs){ typeof(pGCDst->funcs) tmp = pExaGC->Savedfuncs; pExaGC
->Savedfuncs = pGCDst->funcs; pGCDst->funcs = tmp; }
;
597}
598
599static void
600exaDestroyClip(GCPtr pGC)
601{
602 ExaGCPriv(pGC)ExaGCPrivPtr pExaGC = ((ExaGCPrivPtr)dixGetPrivateAddr(&(
pGC)->devPrivates, &((ExaScreenPrivPtr)dixGetPrivate(&
(pGC->pScreen)->devPrivates, (&exaScreenPrivateKeyRec
)))->gcPrivateKeyRec))
;
603 swap(pExaGC, pGC, funcs){ typeof(pGC->funcs) tmp = pExaGC->Savedfuncs; pExaGC->
Savedfuncs = pGC->funcs; pGC->funcs = tmp; }
;
604 (*pGC->funcs->DestroyClip) (pGC);
605 swap(pExaGC, pGC, funcs){ typeof(pGC->funcs) tmp = pExaGC->Savedfuncs; pExaGC->
Savedfuncs = pGC->funcs; pGC->funcs = tmp; }
;
606}
607
608/**
609 * exaCreateGC makes a new GC and hooks up its funcs handler, so that
610 * exaValidateGC() will get called.
611 */
612static int
613exaCreateGC(GCPtr pGC)
614{
615 ScreenPtr pScreen = pGC->pScreen;
616
617 ExaScreenPriv(pScreen)ExaScreenPrivPtr pExaScr = ((ExaScreenPrivPtr)dixGetPrivate(&
(pScreen)->devPrivates, (&exaScreenPrivateKeyRec)))
;
618 ExaGCPriv(pGC)ExaGCPrivPtr pExaGC = ((ExaGCPrivPtr)dixGetPrivateAddr(&(
pGC)->devPrivates, &((ExaScreenPrivPtr)dixGetPrivate(&
(pGC->pScreen)->devPrivates, (&exaScreenPrivateKeyRec
)))->gcPrivateKeyRec))
;
619 Bool ret;
620
621 swap(pExaScr, pScreen, CreateGC){ typeof(pScreen->CreateGC) tmp = pExaScr->SavedCreateGC
; pExaScr->SavedCreateGC = pScreen->CreateGC; pScreen->
CreateGC = tmp; }
;
622 if ((ret = (*pScreen->CreateGC) (pGC))) {
623 wrap(pExaGC, pGC, funcs, &exaGCFuncs){ pExaGC->Savedfuncs = pGC->funcs; pGC->funcs = &
exaGCFuncs; }
;
624 wrap(pExaGC, pGC, ops, &exaOps){ pExaGC->Savedops = pGC->ops; pGC->ops = &exaOps
; }
;
625 }
626 swap(pExaScr, pScreen, CreateGC){ typeof(pScreen->CreateGC) tmp = pExaScr->SavedCreateGC
; pExaScr->SavedCreateGC = pScreen->CreateGC; pScreen->
CreateGC = tmp; }
;
627
628 return ret;
629}
630
631static Bool
632exaChangeWindowAttributes(WindowPtr pWin, unsigned long mask)
633{
634 Bool ret;
635 ScreenPtr pScreen = pWin->drawable.pScreen;
636
637 ExaScreenPriv(pScreen)ExaScreenPrivPtr pExaScr = ((ExaScreenPrivPtr)dixGetPrivate(&
(pScreen)->devPrivates, (&exaScreenPrivateKeyRec)))
;
638
639 if ((mask & CWBackPixmap(1L<<0)) && pWin->backgroundState == BackgroundPixmap3L)
640 exaPrepareAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC1);
641
642 if ((mask & CWBorderPixmap(1L<<2)) && pWin->borderIsPixel == FALSE0)
643 exaPrepareAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK2);
644
645 pExaScr->fallback_counter++;
646 swap(pExaScr, pScreen, ChangeWindowAttributes){ typeof(pScreen->Darwin_X_ChangeWindowAttributes) tmp = pExaScr
->SavedChangeWindowAttributes; pExaScr->SavedChangeWindowAttributes
= pScreen->Darwin_X_ChangeWindowAttributes; pScreen->Darwin_X_ChangeWindowAttributes
= tmp; }
;
647 ret = pScreen->ChangeWindowAttributesDarwin_X_ChangeWindowAttributes(pWin, mask);
648 swap(pExaScr, pScreen, ChangeWindowAttributes){ typeof(pScreen->Darwin_X_ChangeWindowAttributes) tmp = pExaScr
->SavedChangeWindowAttributes; pExaScr->SavedChangeWindowAttributes
= pScreen->Darwin_X_ChangeWindowAttributes; pScreen->Darwin_X_ChangeWindowAttributes
= tmp; }
;
649 pExaScr->fallback_counter--;
650
651 if ((mask & CWBackPixmap(1L<<0)) && pWin->backgroundState == BackgroundPixmap3L)
652 exaFinishAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC1);
653 if ((mask & CWBorderPixmap(1L<<2)) && pWin->borderIsPixel == FALSE0)
654 exaFinishAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK2);
655
656 return ret;
657}
658
659static RegionPtr
660exaBitmapToRegion(PixmapPtr pPix)
661{
662 RegionPtr ret;
663 ScreenPtr pScreen = pPix->drawable.pScreen;
664
665 ExaScreenPriv(pScreen)ExaScreenPrivPtr pExaScr = ((ExaScreenPrivPtr)dixGetPrivate(&
(pScreen)->devPrivates, (&exaScreenPrivateKeyRec)))
;
666
667 exaPrepareAccess(&pPix->drawable, EXA_PREPARE_SRC1);
668 swap(pExaScr, pScreen, BitmapToRegion){ typeof(pScreen->BitmapToRegion) tmp = pExaScr->SavedBitmapToRegion
; pExaScr->SavedBitmapToRegion = pScreen->BitmapToRegion
; pScreen->BitmapToRegion = tmp; }
;
669 ret = (*pScreen->BitmapToRegion) (pPix);
670 swap(pExaScr, pScreen, BitmapToRegion){ typeof(pScreen->BitmapToRegion) tmp = pExaScr->SavedBitmapToRegion
; pExaScr->SavedBitmapToRegion = pScreen->BitmapToRegion
; pScreen->BitmapToRegion = tmp; }
;
671 exaFinishAccess(&pPix->drawable, EXA_PREPARE_SRC1);
672
673 return ret;
674}
675
676static Bool
677exaCreateScreenResources(ScreenPtr pScreen)
678{
679 ExaScreenPriv(pScreen)ExaScreenPrivPtr pExaScr = ((ExaScreenPrivPtr)dixGetPrivate(&
(pScreen)->devPrivates, (&exaScreenPrivateKeyRec)))
;
680 PixmapPtr pScreenPixmap;
681 Bool b;
682
683 swap(pExaScr, pScreen, CreateScreenResources){ typeof(pScreen->CreateScreenResources) tmp = pExaScr->
SavedCreateScreenResources; pExaScr->SavedCreateScreenResources
= pScreen->CreateScreenResources; pScreen->CreateScreenResources
= tmp; }
;
684 b = pScreen->CreateScreenResources(pScreen);
685 swap(pExaScr, pScreen, CreateScreenResources){ typeof(pScreen->CreateScreenResources) tmp = pExaScr->
SavedCreateScreenResources; pExaScr->SavedCreateScreenResources
= pScreen->CreateScreenResources; pScreen->CreateScreenResources
= tmp; }
;
686
687 if (!b)
688 return FALSE0;
689
690 pScreenPixmap = pScreen->GetScreenPixmap(pScreen);
691
692 if (pScreenPixmap) {
693 ExaPixmapPriv(pScreenPixmap)ExaPixmapPrivPtr pExaPixmap = ((ExaPixmapPrivPtr)dixGetPrivateAddr
(&(pScreenPixmap)->devPrivates, &((ExaScreenPrivPtr
)dixGetPrivate(&((pScreenPixmap)->drawable.pScreen)->
devPrivates, (&exaScreenPrivateKeyRec)))->pixmapPrivateKeyRec
))
;
694
695 exaSetAccelBlock(pExaScr, pExaPixmap,
696 pScreenPixmap->drawable.width,
697 pScreenPixmap->drawable.height,
698 pScreenPixmap->drawable.bitsPerPixel);
699 }
700
701 return TRUE1;
702}
703
704static void
705ExaBlockHandler(ScreenPtr pScreen, void *pTimeout,
706 void *pReadmask)
707{
708 ExaScreenPriv(pScreen)ExaScreenPrivPtr pExaScr = ((ExaScreenPrivPtr)dixGetPrivate(&
(pScreen)->devPrivates, (&exaScreenPrivateKeyRec)))
;
709
710 /* Move any deferred results from a software fallback to the driver pixmap */
711 if (pExaScr->deferred_mixed_pixmap)
712 exaMoveInPixmap_mixed(pExaScr->deferred_mixed_pixmap);
713
714 unwrap(pExaScr, pScreen, BlockHandler){ pScreen->BlockHandler = pExaScr->SavedBlockHandler; };
715 (*pScreen->BlockHandler) (pScreen, pTimeout, pReadmask);
716 wrap(pExaScr, pScreen, BlockHandler, ExaBlockHandler){ pExaScr->SavedBlockHandler = pScreen->BlockHandler; pScreen
->BlockHandler = ExaBlockHandler; }
;
717
718 /* The rest only applies to classic EXA */
719 if (pExaScr->info->flags & EXA_HANDLES_PIXMAPS(1 << 3))
720 return;
721
722 /* Try and keep the offscreen memory area tidy every now and then (at most
723 * once per second) when the server has been idle for at least 100ms.
724 */
725 if (pExaScr->numOffscreenAvailable > 1) {
726 CARD32 now = GetTimeInMillis();
727
728 pExaScr->nextDefragment = now +
729 max(100, (INT32) (pExaScr->lastDefragment + 1000 - now))(((100) > ((INT32) (pExaScr->lastDefragment + 1000 - now
))) ? (100) : ((INT32) (pExaScr->lastDefragment + 1000 - now
)))
;
730 AdjustWaitForDelay(pTimeout, pExaScr->nextDefragment - now);
731 }
732}
733
734static void
735ExaWakeupHandler(ScreenPtr pScreen, unsigned long result,
736 void *pReadmask)
737{
738 ExaScreenPriv(pScreen)ExaScreenPrivPtr pExaScr = ((ExaScreenPrivPtr)dixGetPrivate(&
(pScreen)->devPrivates, (&exaScreenPrivateKeyRec)))
;
739
740 unwrap(pExaScr, pScreen, WakeupHandler){ pScreen->WakeupHandler = pExaScr->SavedWakeupHandler;
}
;
741 (*pScreen->WakeupHandler) (pScreen, result, pReadmask);
742 wrap(pExaScr, pScreen, WakeupHandler, ExaWakeupHandler){ pExaScr->SavedWakeupHandler = pScreen->WakeupHandler;
pScreen->WakeupHandler = ExaWakeupHandler; }
;
743
744 if (result == 0 && pExaScr->numOffscreenAvailable > 1) {
745 CARD32 now = GetTimeInMillis();
746
747 if ((int) (now - pExaScr->nextDefragment) > 0) {
748 ExaOffscreenDefragment(pScreen);
749 pExaScr->lastDefragment = now;
750 }
751 }
752}
753
754/**
755 * exaCloseScreen() unwraps its wrapped screen functions and tears down EXA's
756 * screen private, before calling down to the next CloseSccreen.
757 */
758static Bool
759exaCloseScreen(ScreenPtr pScreen)
760{
761 ExaScreenPriv(pScreen)ExaScreenPrivPtr pExaScr = ((ExaScreenPrivPtr)dixGetPrivate(&
(pScreen)->devPrivates, (&exaScreenPrivateKeyRec)))
;
762 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen)(dixPrivateKeyRegistered((&PictureScreenPrivateKeyRec)) ?
((PictureScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates
, (&PictureScreenPrivateKeyRec))) : ((void*)0))
;
763
764 if (ps->Glyphs == exaGlyphs)
765 exaGlyphsFini(pScreen);
766
767 if (pScreen->BlockHandler == ExaBlockHandler)
768 unwrap(pExaScr, pScreen, BlockHandler){ pScreen->BlockHandler = pExaScr->SavedBlockHandler; };
769 if (pScreen->WakeupHandler == ExaWakeupHandler)
770 unwrap(pExaScr, pScreen, WakeupHandler){ pScreen->WakeupHandler = pExaScr->SavedWakeupHandler;
}
;
771 unwrap(pExaScr, pScreen, CreateGC){ pScreen->CreateGC = pExaScr->SavedCreateGC; };
772 unwrap(pExaScr, pScreen, CloseScreen){ pScreen->CloseScreen = pExaScr->SavedCloseScreen; };
773 unwrap(pExaScr, pScreen, GetImage){ pScreen->GetImage = pExaScr->SavedGetImage; };
774 unwrap(pExaScr, pScreen, GetSpans){ pScreen->GetSpans = pExaScr->SavedGetSpans; };
775 if (pExaScr->SavedCreatePixmap)
776 unwrap(pExaScr, pScreen, CreatePixmap){ pScreen->CreatePixmap = pExaScr->SavedCreatePixmap; };
777 if (pExaScr->SavedDestroyPixmap)
778 unwrap(pExaScr, pScreen, DestroyPixmap){ pScreen->DestroyPixmap = pExaScr->SavedDestroyPixmap;
}
;
779 if (pExaScr->SavedModifyPixmapHeader)
780 unwrap(pExaScr, pScreen, ModifyPixmapHeader){ pScreen->ModifyPixmapHeader = pExaScr->SavedModifyPixmapHeader
; }
;
781 unwrap(pExaScr, pScreen, CopyWindow){ pScreen->CopyWindow = pExaScr->SavedCopyWindow; };
782 unwrap(pExaScr, pScreen, ChangeWindowAttributes){ pScreen->Darwin_X_ChangeWindowAttributes = pExaScr->SavedChangeWindowAttributes
; }
;
783 unwrap(pExaScr, pScreen, BitmapToRegion){ pScreen->BitmapToRegion = pExaScr->SavedBitmapToRegion
; }
;
784 unwrap(pExaScr, pScreen, CreateScreenResources){ pScreen->CreateScreenResources = pExaScr->SavedCreateScreenResources
; }
;
785 if (pExaScr->SavedSharePixmapBacking)
786 unwrap(pExaScr, pScreen, SharePixmapBacking){ pScreen->SharePixmapBacking = pExaScr->SavedSharePixmapBacking
; }
;
787 if (pExaScr->SavedSetSharedPixmapBacking)
788 unwrap(pExaScr, pScreen, SetSharedPixmapBacking){ pScreen->SetSharedPixmapBacking = pExaScr->SavedSetSharedPixmapBacking
; }
;
789 unwrap(pExaScr, ps, Composite){ ps->Composite = pExaScr->SavedComposite; };
790 if (pExaScr->SavedGlyphs)
791 unwrap(pExaScr, ps, Glyphs){ ps->Glyphs = pExaScr->SavedGlyphs; };
792 unwrap(pExaScr, ps, Trapezoids){ ps->Trapezoids = pExaScr->SavedTrapezoids; };
793 unwrap(pExaScr, ps, Triangles){ ps->Triangles = pExaScr->SavedTriangles; };
794 unwrap(pExaScr, ps, AddTraps){ ps->AddTraps = pExaScr->SavedAddTraps; };
795
796 free(pExaScr);
797
798 return (*pScreen->CloseScreen) (pScreen);
799}
800
801/**
802 * This function allocates a driver structure for EXA drivers to fill in. By
803 * having EXA allocate the structure, the driver structure can be extended
804 * without breaking ABI between EXA and the drivers. The driver's
805 * responsibility is to check beforehand that the EXA module has a matching
806 * major number and sufficient minor. Drivers are responsible for freeing the
807 * driver structure using free().
808 *
809 * @return a newly allocated, zero-filled driver structure
810 */
811ExaDriverPtr
812exaDriverAlloc(void)
813{
814 return calloc(1, sizeof(ExaDriverRec));
815}
816
817/**
818 * @param pScreen screen being initialized
819 * @param pScreenInfo EXA driver record
820 *
821 * exaDriverInit sets up EXA given a driver record filled in by the driver.
822 * pScreenInfo should have been allocated by exaDriverAlloc(). See the
823 * comments in _ExaDriver for what must be filled in and what is optional.
824 *
825 * @return TRUE if EXA was successfully initialized.
826 */
827Bool
828exaDriverInit(ScreenPtr pScreen, ExaDriverPtr pScreenInfo)
829{
830 ExaScreenPrivPtr pExaScr;
831 PictureScreenPtr ps;
832
833 if (!pScreenInfo)
1
Assuming 'pScreenInfo' is non-null
2
Taking false branch
834 return FALSE0;
835
836 if (pScreenInfo->exa_major != EXA_VERSION_MAJOR2 ||
3
Taking false branch
837 pScreenInfo->exa_minor > EXA_VERSION_MINOR6) {
838 LogMessage(X_ERROR, "EXA(%d): driver's EXA version requirements "
839 "(%d.%d) are incompatible with EXA version (%d.%d)\n",
840 pScreen->myNum,
841 pScreenInfo->exa_major, pScreenInfo->exa_minor,
842 EXA_VERSION_MAJOR2, EXA_VERSION_MINOR6);
843 return FALSE0;
844 }
845
846 if (!pScreenInfo->CreatePixmap && !pScreenInfo->CreatePixmap2) {
847 if (!pScreenInfo->memoryBase) {
848 LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::memoryBase "
849 "must be non-zero\n", pScreen->myNum);
850 return FALSE0;
851 }
852
853 if (!pScreenInfo->memorySize) {
854 LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::memorySize must be "
855 "non-zero\n", pScreen->myNum);
856 return FALSE0;
857 }
858
859 if (pScreenInfo->offScreenBase > pScreenInfo->memorySize) {
860 LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::offScreenBase must "
861 "be <= ExaDriverRec::memorySize\n", pScreen->myNum);
862 return FALSE0;
863 }
864 }
865
866 if (!pScreenInfo->PrepareSolid) {
4
Taking false branch
867 LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::PrepareSolid must be "
868 "non-NULL\n", pScreen->myNum);
869 return FALSE0;
870 }
871
872 if (!pScreenInfo->PrepareCopy) {
5
Taking false branch
873 LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::PrepareCopy must be "
874 "non-NULL\n", pScreen->myNum);
875 return FALSE0;
876 }
877
878 if (!pScreenInfo->WaitMarker) {
6
Taking false branch
879 LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::WaitMarker must be "
880 "non-NULL\n", pScreen->myNum);
881 return FALSE0;
882 }
883
884 /* If the driver doesn't set any max pitch values, we'll just assume
885 * that there's a limitation by pixels, and that it's the same as
886 * maxX.
887 *
888 * We want maxPitchPixels or maxPitchBytes to be set so we can check
889 * pixmaps against the max pitch in exaCreatePixmap() -- it matters
890 * whether a pixmap is rejected because of its pitch or
891 * because of its width.
892 */
893 if (!pScreenInfo->maxPitchPixels && !pScreenInfo->maxPitchBytes) {
894 pScreenInfo->maxPitchPixels = pScreenInfo->maxX;
895 }
896
897 ps = GetPictureScreenIfSet(pScreen)(dixPrivateKeyRegistered((&PictureScreenPrivateKeyRec)) ?
((PictureScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates
, (&PictureScreenPrivateKeyRec))) : ((void*)0))
;
7
Null pointer value stored to 'ps'
898
899 if (!dixRegisterPrivateKey(&exaScreenPrivateKeyRec, PRIVATE_SCREEN, 0)) {
8
Taking false branch
900 LogMessage(X_WARNING, "EXA(%d): Failed to register screen private\n",
901 pScreen->myNum);
902 return FALSE0;
903 }
904
905 pExaScr = calloc(sizeof(ExaScreenPrivRec), 1);
906 if (!pExaScr) {
9
Assuming 'pExaScr' is non-null
10
Taking false branch
907 LogMessage(X_WARNING, "EXA(%d): Failed to allocate screen private\n",
908 pScreen->myNum);
909 return FALSE0;
910 }
911
912 pExaScr->info = pScreenInfo;
913
914 dixSetPrivate(&pScreen->devPrivates, exaScreenPrivateKey(&exaScreenPrivateKeyRec), pExaScr);
915
916 pExaScr->migration = ExaMigrationAlways;
917
918 exaDDXDriverInit(pScreen);
919
920 if (!dixRegisterScreenSpecificPrivateKey
11
Taking false branch
921 (pScreen, &pExaScr->gcPrivateKeyRec, PRIVATE_GC, sizeof(ExaGCPrivRec))) {
922 LogMessage(X_WARNING, "EXA(%d): Failed to allocate GC private\n",
923 pScreen->myNum);
924 return FALSE0;
925 }
926
927 /*
928 * Replace various fb screen functions
929 */
930 if ((pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS(1 << 0)) &&
931 (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS(1 << 3)) ||
932 (pExaScr->info->flags & EXA_MIXED_PIXMAPS(1 << 6))))
933 wrap(pExaScr, pScreen, BlockHandler, ExaBlockHandler){ pExaScr->SavedBlockHandler = pScreen->BlockHandler; pScreen
->BlockHandler = ExaBlockHandler; }
;
934 if ((pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS(1 << 0)) &&
935 !(pExaScr->info->flags & EXA_HANDLES_PIXMAPS(1 << 3)))
936 wrap(pExaScr, pScreen, WakeupHandler, ExaWakeupHandler){ pExaScr->SavedWakeupHandler = pScreen->WakeupHandler;
pScreen->WakeupHandler = ExaWakeupHandler; }
;
937 wrap(pExaScr, pScreen, CreateGC, exaCreateGC){ pExaScr->SavedCreateGC = pScreen->CreateGC; pScreen->
CreateGC = exaCreateGC; }
;
938 wrap(pExaScr, pScreen, CloseScreen, exaCloseScreen){ pExaScr->SavedCloseScreen = pScreen->CloseScreen; pScreen
->CloseScreen = exaCloseScreen; }
;
939 wrap(pExaScr, pScreen, GetImage, exaGetImage){ pExaScr->SavedGetImage = pScreen->GetImage; pScreen->
GetImage = exaGetImage; }
;
940 wrap(pExaScr, pScreen, GetSpans, ExaCheckGetSpans){ pExaScr->SavedGetSpans = pScreen->GetSpans; pScreen->
GetSpans = ExaCheckGetSpans; }
;
941 wrap(pExaScr, pScreen, CopyWindow, exaCopyWindow){ pExaScr->SavedCopyWindow = pScreen->CopyWindow; pScreen
->CopyWindow = exaCopyWindow; }
;
942 wrap(pExaScr, pScreen, ChangeWindowAttributes, exaChangeWindowAttributes){ pExaScr->SavedChangeWindowAttributes = pScreen->Darwin_X_ChangeWindowAttributes
; pScreen->Darwin_X_ChangeWindowAttributes = exaChangeWindowAttributes
; }
;
943 wrap(pExaScr, pScreen, BitmapToRegion, exaBitmapToRegion){ pExaScr->SavedBitmapToRegion = pScreen->BitmapToRegion
; pScreen->BitmapToRegion = exaBitmapToRegion; }
;
944 wrap(pExaScr, pScreen, CreateScreenResources, exaCreateScreenResources){ pExaScr->SavedCreateScreenResources = pScreen->CreateScreenResources
; pScreen->CreateScreenResources = exaCreateScreenResources
; }
;
945
946 if (ps) {
12
Taking false branch
947 wrap(pExaScr, ps, Composite, exaComposite){ pExaScr->SavedComposite = ps->Composite; ps->Composite
= exaComposite; }
;
948 if (pScreenInfo->PrepareComposite) {
949 wrap(pExaScr, ps, Glyphs, exaGlyphs){ pExaScr->SavedGlyphs = ps->Glyphs; ps->Glyphs = exaGlyphs
; }
;
950 }
951 else {
952 wrap(pExaScr, ps, Glyphs, ExaCheckGlyphs){ pExaScr->SavedGlyphs = ps->Glyphs; ps->Glyphs = ExaCheckGlyphs
; }
;
953 }
954 wrap(pExaScr, ps, Trapezoids, exaTrapezoids){ pExaScr->SavedTrapezoids = ps->Trapezoids; ps->Trapezoids
= exaTrapezoids; }
;
955 wrap(pExaScr, ps, Triangles, exaTriangles){ pExaScr->SavedTriangles = ps->Triangles; ps->Triangles
= exaTriangles; }
;
956 wrap(pExaScr, ps, AddTraps, ExaCheckAddTraps){ pExaScr->SavedAddTraps = ps->AddTraps; ps->AddTraps
= ExaCheckAddTraps; }
;
957 }
958
959#ifdef MITSHM1
960 /*
961 * Don't allow shared pixmaps.
962 */
963 ShmRegisterFuncs(pScreen, &exaShmFuncs);
964#endif
965 /*
966 * Hookup offscreen pixmaps
967 */
968 if (pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS(1 << 0)) {
13
Taking false branch
969 if (!dixRegisterScreenSpecificPrivateKey
970 (pScreen, &pExaScr->pixmapPrivateKeyRec, PRIVATE_PIXMAP,
971 sizeof(ExaPixmapPrivRec))) {
972 LogMessage(X_WARNING,
973 "EXA(%d): Failed to allocate pixmap private\n",
974 pScreen->myNum);
975 return FALSE0;
976 }
977 if (pExaScr->info->flags & EXA_HANDLES_PIXMAPS(1 << 3)) {
978 if (pExaScr->info->flags & EXA_MIXED_PIXMAPS(1 << 6)) {
979 wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_mixed){ pExaScr->SavedCreatePixmap = pScreen->CreatePixmap; pScreen
->CreatePixmap = exaCreatePixmap_mixed; }
;
980 wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_mixed){ pExaScr->SavedDestroyPixmap = pScreen->DestroyPixmap;
pScreen->DestroyPixmap = exaDestroyPixmap_mixed; }
;
981 wrap(pExaScr, pScreen, ModifyPixmapHeader,{ pExaScr->SavedModifyPixmapHeader = pScreen->ModifyPixmapHeader
; pScreen->ModifyPixmapHeader = exaModifyPixmapHeader_mixed
; }
982 exaModifyPixmapHeader_mixed){ pExaScr->SavedModifyPixmapHeader = pScreen->ModifyPixmapHeader
; pScreen->ModifyPixmapHeader = exaModifyPixmapHeader_mixed
; }
;
983 wrap(pExaScr, pScreen, SharePixmapBacking, exaSharePixmapBacking_mixed){ pExaScr->SavedSharePixmapBacking = pScreen->SharePixmapBacking
; pScreen->SharePixmapBacking = exaSharePixmapBacking_mixed
; }
;
984 wrap(pExaScr, pScreen, SetSharedPixmapBacking, exaSetSharedPixmapBacking_mixed){ pExaScr->SavedSetSharedPixmapBacking = pScreen->SetSharedPixmapBacking
; pScreen->SetSharedPixmapBacking = exaSetSharedPixmapBacking_mixed
; }
;
985
986 pExaScr->do_migration = exaDoMigration_mixed;
987 pExaScr->pixmap_has_gpu_copy = exaPixmapHasGpuCopy_mixed;
988 pExaScr->do_move_in_pixmap = exaMoveInPixmap_mixed;
989 pExaScr->do_move_out_pixmap = NULL((void*)0);
990 pExaScr->prepare_access_reg = exaPrepareAccessReg_mixed;
991 }
992 else {
993 wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_driver){ pExaScr->SavedCreatePixmap = pScreen->CreatePixmap; pScreen
->CreatePixmap = exaCreatePixmap_driver; }
;
994 wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_driver){ pExaScr->SavedDestroyPixmap = pScreen->DestroyPixmap;
pScreen->DestroyPixmap = exaDestroyPixmap_driver; }
;
995 wrap(pExaScr, pScreen, ModifyPixmapHeader,{ pExaScr->SavedModifyPixmapHeader = pScreen->ModifyPixmapHeader
; pScreen->ModifyPixmapHeader = exaModifyPixmapHeader_driver
; }
996 exaModifyPixmapHeader_driver){ pExaScr->SavedModifyPixmapHeader = pScreen->ModifyPixmapHeader
; pScreen->ModifyPixmapHeader = exaModifyPixmapHeader_driver
; }
;
997 pExaScr->do_migration = NULL((void*)0);
998 pExaScr->pixmap_has_gpu_copy = exaPixmapHasGpuCopy_driver;
999 pExaScr->do_move_in_pixmap = NULL((void*)0);
1000 pExaScr->do_move_out_pixmap = NULL((void*)0);
1001 pExaScr->prepare_access_reg = NULL((void*)0);
1002 }
1003 }
1004 else {
1005 wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_classic){ pExaScr->SavedCreatePixmap = pScreen->CreatePixmap; pScreen
->CreatePixmap = exaCreatePixmap_classic; }
;
1006 wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_classic){ pExaScr->SavedDestroyPixmap = pScreen->DestroyPixmap;
pScreen->DestroyPixmap = exaDestroyPixmap_classic; }
;
1007 wrap(pExaScr, pScreen, ModifyPixmapHeader,{ pExaScr->SavedModifyPixmapHeader = pScreen->ModifyPixmapHeader
; pScreen->ModifyPixmapHeader = exaModifyPixmapHeader_classic
; }
1008 exaModifyPixmapHeader_classic){ pExaScr->SavedModifyPixmapHeader = pScreen->ModifyPixmapHeader
; pScreen->ModifyPixmapHeader = exaModifyPixmapHeader_classic
; }
;
1009 pExaScr->do_migration = exaDoMigration_classic;
1010 pExaScr->pixmap_has_gpu_copy = exaPixmapHasGpuCopy_classic;
1011 pExaScr->do_move_in_pixmap = exaMoveInPixmap_classic;
1012 pExaScr->do_move_out_pixmap = exaMoveOutPixmap_classic;
1013 pExaScr->prepare_access_reg = exaPrepareAccessReg_classic;
1014 }
1015 if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS(1 << 3))) {
1016 LogMessage(X_INFO, "EXA(%d): Offscreen pixmap area of %lu bytes\n",
1017 pScreen->myNum,
1018 pExaScr->info->memorySize -
1019 pExaScr->info->offScreenBase);
1020 }
1021 else {
1022 LogMessage(X_INFO, "EXA(%d): Driver allocated offscreen pixmaps\n",
1023 pScreen->myNum);
1024
1025 }
1026 }
1027 else
1028 LogMessage(X_INFO, "EXA(%d): No offscreen pixmaps\n", pScreen->myNum);
1029
1030 if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS(1 << 3))) {
14
Taking false branch
1031 DBG_PIXMAP(("============== %ld < %ld\n", pExaScr->info->offScreenBase,
1032 pExaScr->info->memorySize));
1033 if (pExaScr->info->offScreenBase < pExaScr->info->memorySize) {
1034 if (!exaOffscreenInit(pScreen)) {
1035 LogMessage(X_WARNING,
1036 "EXA(%d): Offscreen pixmap setup failed\n",
1037 pScreen->myNum);
1038 return FALSE0;
1039 }
1040 }
1041 }
1042
1043 if (ps->Glyphs == exaGlyphs)
15
Access to field 'Glyphs' results in a dereference of a null pointer (loaded from variable 'ps')
1044 exaGlyphsInit(pScreen);
1045
1046 LogMessage(X_INFO, "EXA(%d): Driver registered support for the following"
1047 " operations:\n", pScreen->myNum);
1048 assert(pScreenInfo->PrepareSolid != NULL)(__builtin_expect(!(pScreenInfo->PrepareSolid != ((void*)0
)), 0) ? __assert_rtn(__func__, "exa.c", 1048, "pScreenInfo->PrepareSolid != NULL"
) : (void)0)
;
1049 LogMessage(X_INFO, " Solid\n");
1050 assert(pScreenInfo->PrepareCopy != NULL)(__builtin_expect(!(pScreenInfo->PrepareCopy != ((void*)0)
), 0) ? __assert_rtn(__func__, "exa.c", 1050, "pScreenInfo->PrepareCopy != NULL"
) : (void)0)
;
1051 LogMessage(X_INFO, " Copy\n");
1052 if (pScreenInfo->PrepareComposite != NULL((void*)0)) {
1053 LogMessage(X_INFO, " Composite (RENDER acceleration)\n");
1054 }
1055 if (pScreenInfo->UploadToScreen != NULL((void*)0)) {
1056 LogMessage(X_INFO, " UploadToScreen\n");
1057 }
1058 if (pScreenInfo->DownloadFromScreen != NULL((void*)0)) {
1059 LogMessage(X_INFO, " DownloadFromScreen\n");
1060 }
1061
1062 return TRUE1;
1063}
1064
1065/**
1066 * exaDriverFini tears down EXA on a given screen.
1067 *
1068 * @param pScreen screen being torn down.
1069 */
1070void
1071exaDriverFini(ScreenPtr pScreen)
1072{
1073 /*right now does nothing */
1074}
1075
1076/**
1077 * exaMarkSync() should be called after any asynchronous drawing by the hardware.
1078 *
1079 * @param pScreen screen which drawing occurred on
1080 *
1081 * exaMarkSync() sets a flag to indicate that some asynchronous drawing has
1082 * happened and a WaitSync() will be necessary before relying on the contents of
1083 * offscreen memory from the CPU's perspective. It also calls an optional
1084 * driver MarkSync() callback, the return value of which may be used to do partial
1085 * synchronization with the hardware in the future.
1086 */
1087void
1088exaMarkSync(ScreenPtr pScreen)
1089{
1090 ExaScreenPriv(pScreen)ExaScreenPrivPtr pExaScr = ((ExaScreenPrivPtr)dixGetPrivate(&
(pScreen)->devPrivates, (&exaScreenPrivateKeyRec)))
;
1091
1092 pExaScr->info->needsSync = TRUE1;
1093 if (pExaScr->info->MarkSync != NULL((void*)0)) {
1094 pExaScr->info->lastMarker = (*pExaScr->info->MarkSync) (pScreen);
1095 }
1096}
1097
1098/**
1099 * exaWaitSync() ensures that all drawing has been completed.
1100 *
1101 * @param pScreen screen being synchronized.
1102 *
1103 * Calls down into the driver to ensure that all previous drawing has completed.
1104 * It should always be called before relying on the framebuffer contents
1105 * reflecting previous drawing, from a CPU perspective.
1106 */
1107void
1108exaWaitSync(ScreenPtr pScreen)
1109{
1110 ExaScreenPriv(pScreen)ExaScreenPrivPtr pExaScr = ((ExaScreenPrivPtr)dixGetPrivate(&
(pScreen)->devPrivates, (&exaScreenPrivateKeyRec)))
;
1111
1112 if (pExaScr->info->needsSync && !pExaScr->swappedOut) {
1113 (*pExaScr->info->WaitMarker) (pScreen, pExaScr->info->lastMarker);
1114 pExaScr->info->needsSync = FALSE0;
1115 }
1116}
1117
1118/**
1119 * Performs migration of the pixmaps according to the operation information
1120 * provided in pixmaps and can_accel and the migration scheme chosen in the
1121 * config file.
1122 */
1123void
1124exaDoMigration(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
1125{
1126 ScreenPtr pScreen = pixmaps[0].pPix->drawable.pScreen;
1127
1128 ExaScreenPriv(pScreen)ExaScreenPrivPtr pExaScr = ((ExaScreenPrivPtr)dixGetPrivate(&
(pScreen)->devPrivates, (&exaScreenPrivateKeyRec)))
;
1129
1130 if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS(1 << 0)))
1131 return;
1132
1133 if (pExaScr->do_migration)
1134 (*pExaScr->do_migration) (pixmaps, npixmaps, can_accel);
1135}
1136
1137void
1138exaMoveInPixmap(PixmapPtr pPixmap)
1139{
1140 ScreenPtr pScreen = pPixmap->drawable.pScreen;
1141
1142 ExaScreenPriv(pScreen)ExaScreenPrivPtr pExaScr = ((ExaScreenPrivPtr)dixGetPrivate(&
(pScreen)->devPrivates, (&exaScreenPrivateKeyRec)))
;
1143
1144 if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS(1 << 0)))
1145 return;
1146
1147 if (pExaScr->do_move_in_pixmap)
1148 (*pExaScr->do_move_in_pixmap) (pPixmap);
1149}
1150
1151void
1152exaMoveOutPixmap(PixmapPtr pPixmap)
1153{
1154 ScreenPtr pScreen = pPixmap->drawable.pScreen;
1155
1156 ExaScreenPriv(pScreen)ExaScreenPrivPtr pExaScr = ((ExaScreenPrivPtr)dixGetPrivate(&
(pScreen)->devPrivates, (&exaScreenPrivateKeyRec)))
;
1157
1158 if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS(1 << 0)))
1159 return;
1160
1161 if (pExaScr->do_move_out_pixmap)
1162 (*pExaScr->do_move_out_pixmap) (pPixmap);
1163}