2 * Copyright © 2006 Intel Corporation
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
24 * Eric Anholt <eric@anholt.net>
29 #include <kdrive-config.h>
31 #undef NDEBUG /* No, really. The whole point of this module is to crash. */
37 #define EPHYR_TRACE_DRAW 0
40 #define TRACE_DRAW() ErrorF("%s\n", __FUNCTION__);
42 #define TRACE_DRAW() do { } while (0)
45 /* Use some oddball alignments, to expose issues in alignment handling in EXA. */
46 #define EPHYR_OFFSET_ALIGN 24
47 #define EPHYR_PITCH_ALIGN 24
49 #define EPHYR_OFFSCREEN_SIZE (16 * 1024 * 1024)
50 #define EPHYR_OFFSCREEN_BASE (1 * 1024 * 1024)
53 * Forces a real devPrivate.ptr for hidden pixmaps, so that we can call down to
57 ephyrPreparePipelinedAccess(PixmapPtr pPix
, int index
)
59 KdScreenPriv(pPix
->drawable
.pScreen
);
60 KdScreenInfo
*screen
= pScreenPriv
->screen
;
61 EphyrScrPriv
*scrpriv
= screen
->driver
;
62 EphyrFakexaPriv
*fakexa
= scrpriv
->fakexa
;
64 assert(fakexa
->saved_ptrs
[index
] == NULL
);
65 fakexa
->saved_ptrs
[index
] = pPix
->devPrivate
.ptr
;
67 if (pPix
->devPrivate
.ptr
!= NULL
)
70 pPix
->devPrivate
.ptr
= fakexa
->exa
->memoryBase
+ exaGetPixmapOffset(pPix
);
74 * Restores the original devPrivate.ptr of the pixmap from before we messed with
78 ephyrFinishPipelinedAccess(PixmapPtr pPix
, int index
)
80 KdScreenPriv(pPix
->drawable
.pScreen
);
81 KdScreenInfo
*screen
= pScreenPriv
->screen
;
82 EphyrScrPriv
*scrpriv
= screen
->driver
;
83 EphyrFakexaPriv
*fakexa
= scrpriv
->fakexa
;
85 pPix
->devPrivate
.ptr
= fakexa
->saved_ptrs
[index
];
86 fakexa
->saved_ptrs
[index
] = NULL
;
90 * Sets up a scratch GC for fbFill, and saves other parameters for the
91 * ephyrSolid implementation.
94 ephyrPrepareSolid(PixmapPtr pPix
, int alu
, Pixel pm
, Pixel fg
)
96 ScreenPtr pScreen
= pPix
->drawable
.pScreen
;
97 KdScreenPriv(pScreen
);
98 KdScreenInfo
*screen
= pScreenPriv
->screen
;
99 EphyrScrPriv
*scrpriv
= screen
->driver
;
100 EphyrFakexaPriv
*fakexa
= scrpriv
->fakexa
;
103 ephyrPreparePipelinedAccess(pPix
, EXA_PREPARE_DEST
);
106 fakexa
->pGC
= GetScratchGC(pPix
->drawable
.depth
, pScreen
);
111 ChangeGC(fakexa
->pGC
, GCFunction
| GCPlaneMask
| GCForeground
,
114 ValidateGC(&pPix
->drawable
, fakexa
->pGC
);
122 * Does an fbFill of the rectangle to be drawn.
125 ephyrSolid(PixmapPtr pPix
, int x1
, int y1
, int x2
, int y2
)
127 ScreenPtr pScreen
= pPix
->drawable
.pScreen
;
128 KdScreenPriv(pScreen
);
129 KdScreenInfo
*screen
= pScreenPriv
->screen
;
130 EphyrScrPriv
*scrpriv
= screen
->driver
;
131 EphyrFakexaPriv
*fakexa
= scrpriv
->fakexa
;
133 fbFill(&fakexa
->pDst
->drawable
, fakexa
->pGC
, x1
, y1
, x2
- x1
, y2
- y1
);
137 * Cleans up the scratch GC created in ephyrPrepareSolid.
140 ephyrDoneSolid(PixmapPtr pPix
)
142 ScreenPtr pScreen
= pPix
->drawable
.pScreen
;
143 KdScreenPriv(pScreen
);
144 KdScreenInfo
*screen
= pScreenPriv
->screen
;
145 EphyrScrPriv
*scrpriv
= screen
->driver
;
146 EphyrFakexaPriv
*fakexa
= scrpriv
->fakexa
;
148 FreeScratchGC(fakexa
->pGC
);
150 ephyrFinishPipelinedAccess(pPix
, EXA_PREPARE_DEST
);
154 * Sets up a scratch GC for fbCopyArea, and saves other parameters for the
155 * ephyrCopy implementation.
158 ephyrPrepareCopy(PixmapPtr pSrc
, PixmapPtr pDst
, int dx
, int dy
, int alu
,
161 ScreenPtr pScreen
= pDst
->drawable
.pScreen
;
162 KdScreenPriv(pScreen
);
163 KdScreenInfo
*screen
= pScreenPriv
->screen
;
164 EphyrScrPriv
*scrpriv
= screen
->driver
;
165 EphyrFakexaPriv
*fakexa
= scrpriv
->fakexa
;
168 ephyrPreparePipelinedAccess(pDst
, EXA_PREPARE_DEST
);
169 ephyrPreparePipelinedAccess(pSrc
, EXA_PREPARE_SRC
);
173 fakexa
->pGC
= GetScratchGC(pDst
->drawable
.depth
, pScreen
);
177 ChangeGC (fakexa
->pGC
, GCFunction
| GCPlaneMask
, tmpval
);
179 ValidateGC(&pDst
->drawable
, fakexa
->pGC
);
187 * Does an fbCopyArea to take care of the requested copy.
190 ephyrCopy(PixmapPtr pDst
, int srcX
, int srcY
, int dstX
, int dstY
, int w
, int h
)
192 ScreenPtr pScreen
= pDst
->drawable
.pScreen
;
193 KdScreenPriv(pScreen
);
194 KdScreenInfo
*screen
= pScreenPriv
->screen
;
195 EphyrScrPriv
*scrpriv
= screen
->driver
;
196 EphyrFakexaPriv
*fakexa
= scrpriv
->fakexa
;
198 fbCopyArea(&fakexa
->pSrc
->drawable
, &fakexa
->pDst
->drawable
, fakexa
->pGC
,
199 srcX
, srcY
, w
, h
, dstX
, dstY
);
203 * Cleans up the scratch GC created in ephyrPrepareCopy.
206 ephyrDoneCopy(PixmapPtr pDst
)
208 ScreenPtr pScreen
= pDst
->drawable
.pScreen
;
209 KdScreenPriv(pScreen
);
210 KdScreenInfo
*screen
= pScreenPriv
->screen
;
211 EphyrScrPriv
*scrpriv
= screen
->driver
;
212 EphyrFakexaPriv
*fakexa
= scrpriv
->fakexa
;
214 FreeScratchGC (fakexa
->pGC
);
216 ephyrFinishPipelinedAccess(fakexa
->pSrc
, EXA_PREPARE_SRC
);
217 ephyrFinishPipelinedAccess(fakexa
->pDst
, EXA_PREPARE_DEST
);
221 * Reports that we can always accelerate the given operation. This may not be
222 * desirable from an EXA testing standpoint -- testing the fallback paths would
226 ephyrCheckComposite(int op
, PicturePtr pSrcPicture
, PicturePtr pMaskPicture
,
227 PicturePtr pDstPicture
)
229 /* Exercise the component alpha helper, so fail on this case like a normal
232 if (pMaskPicture
&& pMaskPicture
->componentAlpha
&& op
== PictOpOver
)
239 * Saves off the parameters for ephyrComposite.
242 ephyrPrepareComposite(int op
, PicturePtr pSrcPicture
, PicturePtr pMaskPicture
,
243 PicturePtr pDstPicture
, PixmapPtr pSrc
, PixmapPtr pMask
,
246 KdScreenPriv(pDst
->drawable
.pScreen
);
247 KdScreenInfo
*screen
= pScreenPriv
->screen
;
248 EphyrScrPriv
*scrpriv
= screen
->driver
;
249 EphyrFakexaPriv
*fakexa
= scrpriv
->fakexa
;
251 ephyrPreparePipelinedAccess(pDst
, EXA_PREPARE_DEST
);
252 ephyrPreparePipelinedAccess(pSrc
, EXA_PREPARE_SRC
);
254 ephyrPreparePipelinedAccess(pMask
, EXA_PREPARE_MASK
);
257 fakexa
->pSrcPicture
= pSrcPicture
;
258 fakexa
->pMaskPicture
= pMaskPicture
;
259 fakexa
->pDstPicture
= pDstPicture
;
261 fakexa
->pMask
= pMask
;
270 * Does an fbComposite to complete the requested drawing operation.
273 ephyrComposite(PixmapPtr pDst
, int srcX
, int srcY
, int maskX
, int maskY
,
274 int dstX
, int dstY
, int w
, int h
)
276 KdScreenPriv(pDst
->drawable
.pScreen
);
277 KdScreenInfo
*screen
= pScreenPriv
->screen
;
278 EphyrScrPriv
*scrpriv
= screen
->driver
;
279 EphyrFakexaPriv
*fakexa
= scrpriv
->fakexa
;
281 fbComposite(fakexa
->op
, fakexa
->pSrcPicture
, fakexa
->pMaskPicture
,
282 fakexa
->pDstPicture
, srcX
, srcY
, maskX
, maskY
, dstX
, dstY
,
287 ephyrDoneComposite(PixmapPtr pDst
)
289 KdScreenPriv(pDst
->drawable
.pScreen
);
290 KdScreenInfo
*screen
= pScreenPriv
->screen
;
291 EphyrScrPriv
*scrpriv
= screen
->driver
;
292 EphyrFakexaPriv
*fakexa
= scrpriv
->fakexa
;
294 if (fakexa
->pMask
!= NULL
)
295 ephyrFinishPipelinedAccess(fakexa
->pMask
, EXA_PREPARE_MASK
);
296 ephyrFinishPipelinedAccess(fakexa
->pSrc
, EXA_PREPARE_SRC
);
297 ephyrFinishPipelinedAccess(fakexa
->pDst
, EXA_PREPARE_DEST
);
301 * Does fake acceleration of DownloadFromScren using memcpy.
304 ephyrDownloadFromScreen(PixmapPtr pSrc
, int x
, int y
, int w
, int h
, char *dst
,
307 KdScreenPriv(pSrc
->drawable
.pScreen
);
308 KdScreenInfo
*screen
= pScreenPriv
->screen
;
309 EphyrScrPriv
*scrpriv
= screen
->driver
;
310 EphyrFakexaPriv
*fakexa
= scrpriv
->fakexa
;
314 if (pSrc
->drawable
.bitsPerPixel
< 8)
317 ephyrPreparePipelinedAccess(pSrc
, EXA_PREPARE_SRC
);
319 cpp
= pSrc
->drawable
.bitsPerPixel
/ 8;
320 src_pitch
= exaGetPixmapPitch(pSrc
);
321 src
= fakexa
->exa
->memoryBase
+ exaGetPixmapOffset(pSrc
);
322 src
+= y
* src_pitch
+ x
* cpp
;
325 memcpy(dst
, src
, w
* cpp
);
330 exaMarkSync(pSrc
->drawable
.pScreen
);
332 ephyrFinishPipelinedAccess(pSrc
, EXA_PREPARE_SRC
);
338 * Does fake acceleration of UploadToScreen using memcpy.
341 ephyrUploadToScreen(PixmapPtr pDst
, int x
, int y
, int w
, int h
, char *src
,
344 KdScreenPriv(pDst
->drawable
.pScreen
);
345 KdScreenInfo
*screen
= pScreenPriv
->screen
;
346 EphyrScrPriv
*scrpriv
= screen
->driver
;
347 EphyrFakexaPriv
*fakexa
= scrpriv
->fakexa
;
351 if (pDst
->drawable
.bitsPerPixel
< 8)
354 ephyrPreparePipelinedAccess(pDst
, EXA_PREPARE_DEST
);
356 cpp
= pDst
->drawable
.bitsPerPixel
/ 8;
357 dst_pitch
= exaGetPixmapPitch(pDst
);
358 dst
= fakexa
->exa
->memoryBase
+ exaGetPixmapOffset(pDst
);
359 dst
+= y
* dst_pitch
+ x
* cpp
;
362 memcpy(dst
, src
, w
* cpp
);
367 exaMarkSync(pDst
->drawable
.pScreen
);
369 ephyrFinishPipelinedAccess(pDst
, EXA_PREPARE_DEST
);
375 ephyrPrepareAccess(PixmapPtr pPix
, int index
)
377 /* Make sure we don't somehow end up with a pointer that is in framebuffer
378 * and hasn't been readied for us.
380 assert(pPix
->devPrivate
.ptr
!= NULL
);
386 * In fakexa, we currently only track whether we have synced to the latest
387 * "accelerated" drawing that has happened or not. It's not used for anything
391 ephyrMarkSync(ScreenPtr pScreen
)
393 KdScreenPriv(pScreen
);
394 KdScreenInfo
*screen
= pScreenPriv
->screen
;
395 EphyrScrPriv
*scrpriv
= screen
->driver
;
396 EphyrFakexaPriv
*fakexa
= scrpriv
->fakexa
;
398 fakexa
->is_synced
= FALSE
;
404 * Assumes that we're waiting on the latest marker. When EXA gets smarter and
405 * starts using markers in a fine-grained way (for example, waiting on drawing
406 * to required pixmaps to complete, rather than waiting for all drawing to
407 * complete), we'll want to make the ephyrMarkSync/ephyrWaitMarker
408 * implementation fine-grained as well.
411 ephyrWaitMarker(ScreenPtr pScreen
, int marker
)
413 KdScreenPriv(pScreen
);
414 KdScreenInfo
*screen
= pScreenPriv
->screen
;
415 EphyrScrPriv
*scrpriv
= screen
->driver
;
416 EphyrFakexaPriv
*fakexa
= scrpriv
->fakexa
;
418 fakexa
->is_synced
= TRUE
;
422 * This function initializes EXA to use the fake acceleration implementation
423 * which just falls through to software. The purpose is to have a reliable,
424 * correct driver with which to test changes to the EXA core.
427 ephyrDrawInit(ScreenPtr pScreen
)
429 KdScreenPriv(pScreen
);
430 KdScreenInfo
*screen
= pScreenPriv
->screen
;
431 EphyrScrPriv
*scrpriv
= screen
->driver
;
432 EphyrFakexaPriv
*fakexa
;
435 fakexa
= xcalloc(1, sizeof(*fakexa
));
439 fakexa
->exa
= exaDriverAlloc();
440 if (fakexa
->exa
== NULL
) {
445 fakexa
->exa
->memoryBase
= screen
->memory_base
;
446 fakexa
->exa
->memorySize
= screen
->memory_size
;
447 fakexa
->exa
->offScreenBase
= screen
->off_screen_base
;
449 /* Since we statically link against EXA, we shouldn't have to be smart about
452 fakexa
->exa
->exa_major
= 2;
453 fakexa
->exa
->exa_minor
= 0;
455 fakexa
->exa
->PrepareSolid
= ephyrPrepareSolid
;
456 fakexa
->exa
->Solid
= ephyrSolid
;
457 fakexa
->exa
->DoneSolid
= ephyrDoneSolid
;
459 fakexa
->exa
->PrepareCopy
= ephyrPrepareCopy
;
460 fakexa
->exa
->Copy
= ephyrCopy
;
461 fakexa
->exa
->DoneCopy
= ephyrDoneCopy
;
463 fakexa
->exa
->CheckComposite
= ephyrCheckComposite
;
464 fakexa
->exa
->PrepareComposite
= ephyrPrepareComposite
;
465 fakexa
->exa
->Composite
= ephyrComposite
;
466 fakexa
->exa
->DoneComposite
= ephyrDoneComposite
;
468 fakexa
->exa
->DownloadFromScreen
= ephyrDownloadFromScreen
;
469 fakexa
->exa
->UploadToScreen
= ephyrUploadToScreen
;
471 fakexa
->exa
->MarkSync
= ephyrMarkSync
;
472 fakexa
->exa
->WaitMarker
= ephyrWaitMarker
;
474 fakexa
->exa
->PrepareAccess
= ephyrPrepareAccess
;
476 fakexa
->exa
->pixmapOffsetAlign
= EPHYR_OFFSET_ALIGN
;
477 fakexa
->exa
->pixmapPitchAlign
= EPHYR_PITCH_ALIGN
;
479 fakexa
->exa
->maxX
= 1023;
480 fakexa
->exa
->maxY
= 1023;
482 fakexa
->exa
->flags
= EXA_OFFSCREEN_PIXMAPS
;
484 success
= exaDriverInit(pScreen
, fakexa
->exa
);
486 ErrorF("Initialized fake EXA acceleration\n");
487 scrpriv
->fakexa
= fakexa
;
489 ErrorF("Failed to initialize EXA\n");
498 ephyrDrawEnable(ScreenPtr pScreen
)
503 ephyrDrawDisable(ScreenPtr pScreen
)
508 ephyrDrawFini(ScreenPtr pScreen
)
513 * exaDDXDriverInit is required by the top-level EXA module, and is used by
514 * the xorg DDX to hook in its EnableDisableFB wrapper. We don't need it, since
515 * we won't be enabling/disabling the FB.
518 exaDDXDriverInit(ScreenPtr pScreen
)
520 ExaScreenPriv(pScreen
);
522 pExaScr
->migration
= ExaMigrationSmart
;
523 pExaScr
->hideOffscreenPixmapData
= TRUE
;
524 pExaScr
->checkDirtyCorrectness
= TRUE
;