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>
36 #define EPHYR_TRACE_DRAW 0
39 #define TRACE_DRAW() ErrorF("%s\n", __FUNCTION__);
41 #define TRACE_DRAW() do { } while (0)
44 /* Use some oddball alignments, to expose issues in alignment handling in EXA. */
45 #define EPHYR_OFFSET_ALIGN 24
46 #define EPHYR_PITCH_ALIGN 24
48 #define EPHYR_OFFSCREEN_SIZE (16 * 1024 * 1024)
49 #define EPHYR_OFFSCREEN_BASE (1 * 1024 * 1024)
52 * Forces a real devPrivate.ptr for hidden pixmaps, so that we can call down to
56 ephyrPreparePipelinedAccess(PixmapPtr pPix
, int index
)
58 KdScreenPriv(pPix
->drawable
.pScreen
);
59 KdScreenInfo
*screen
= pScreenPriv
->screen
;
60 EphyrScrPriv
*scrpriv
= screen
->driver
;
61 EphyrFakexaPriv
*fakexa
= scrpriv
->fakexa
;
63 assert(fakexa
->saved_ptrs
[index
] == NULL
);
64 fakexa
->saved_ptrs
[index
] = pPix
->devPrivate
.ptr
;
66 if (pPix
->devPrivate
.ptr
!= NULL
)
69 pPix
->devPrivate
.ptr
= fakexa
->exa
->memoryBase
+ exaGetPixmapOffset(pPix
);
73 * Restores the original devPrivate.ptr of the pixmap from before we messed with
77 ephyrFinishPipelinedAccess(PixmapPtr pPix
, int index
)
79 KdScreenPriv(pPix
->drawable
.pScreen
);
80 KdScreenInfo
*screen
= pScreenPriv
->screen
;
81 EphyrScrPriv
*scrpriv
= screen
->driver
;
82 EphyrFakexaPriv
*fakexa
= scrpriv
->fakexa
;
84 pPix
->devPrivate
.ptr
= fakexa
->saved_ptrs
[index
];
85 fakexa
->saved_ptrs
[index
] = NULL
;
89 * Sets up a scratch GC for fbFill, and saves other parameters for the
90 * ephyrSolid implementation.
93 ephyrPrepareSolid(PixmapPtr pPix
, int alu
, Pixel pm
, Pixel fg
)
95 ScreenPtr pScreen
= pPix
->drawable
.pScreen
;
97 KdScreenPriv(pScreen
);
98 KdScreenInfo
*screen
= pScreenPriv
->screen
;
99 EphyrScrPriv
*scrpriv
= screen
->driver
;
100 EphyrFakexaPriv
*fakexa
= scrpriv
->fakexa
;
101 ChangeGCVal tmpval
[3];
103 ephyrPreparePipelinedAccess(pPix
, EXA_PREPARE_DEST
);
106 fakexa
->pGC
= GetScratchGC(pPix
->drawable
.depth
, pScreen
);
111 ChangeGC(NullClient
, 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
;
129 KdScreenPriv(pScreen
);
130 KdScreenInfo
*screen
= pScreenPriv
->screen
;
131 EphyrScrPriv
*scrpriv
= screen
->driver
;
132 EphyrFakexaPriv
*fakexa
= scrpriv
->fakexa
;
134 fbFill(&fakexa
->pDst
->drawable
, fakexa
->pGC
, x1
, y1
, x2
- x1
, y2
- y1
);
138 * Cleans up the scratch GC created in ephyrPrepareSolid.
141 ephyrDoneSolid(PixmapPtr pPix
)
143 ScreenPtr pScreen
= pPix
->drawable
.pScreen
;
145 KdScreenPriv(pScreen
);
146 KdScreenInfo
*screen
= pScreenPriv
->screen
;
147 EphyrScrPriv
*scrpriv
= screen
->driver
;
148 EphyrFakexaPriv
*fakexa
= scrpriv
->fakexa
;
150 FreeScratchGC(fakexa
->pGC
);
152 ephyrFinishPipelinedAccess(pPix
, EXA_PREPARE_DEST
);
156 * Sets up a scratch GC for fbCopyArea, and saves other parameters for the
157 * ephyrCopy implementation.
160 ephyrPrepareCopy(PixmapPtr pSrc
, PixmapPtr pDst
, int dx
, int dy
, int alu
,
163 ScreenPtr pScreen
= pDst
->drawable
.pScreen
;
165 KdScreenPriv(pScreen
);
166 KdScreenInfo
*screen
= pScreenPriv
->screen
;
167 EphyrScrPriv
*scrpriv
= screen
->driver
;
168 EphyrFakexaPriv
*fakexa
= scrpriv
->fakexa
;
169 ChangeGCVal tmpval
[2];
171 ephyrPreparePipelinedAccess(pDst
, EXA_PREPARE_DEST
);
172 ephyrPreparePipelinedAccess(pSrc
, EXA_PREPARE_SRC
);
176 fakexa
->pGC
= GetScratchGC(pDst
->drawable
.depth
, pScreen
);
180 ChangeGC(NullClient
, fakexa
->pGC
, GCFunction
| GCPlaneMask
, tmpval
);
182 ValidateGC(&pDst
->drawable
, fakexa
->pGC
);
190 * Does an fbCopyArea to take care of the requested copy.
193 ephyrCopy(PixmapPtr pDst
, int srcX
, int srcY
, int dstX
, int dstY
, int w
, int h
)
195 ScreenPtr pScreen
= pDst
->drawable
.pScreen
;
197 KdScreenPriv(pScreen
);
198 KdScreenInfo
*screen
= pScreenPriv
->screen
;
199 EphyrScrPriv
*scrpriv
= screen
->driver
;
200 EphyrFakexaPriv
*fakexa
= scrpriv
->fakexa
;
202 fbCopyArea(&fakexa
->pSrc
->drawable
, &fakexa
->pDst
->drawable
, fakexa
->pGC
,
203 srcX
, srcY
, w
, h
, dstX
, dstY
);
207 * Cleans up the scratch GC created in ephyrPrepareCopy.
210 ephyrDoneCopy(PixmapPtr pDst
)
212 ScreenPtr pScreen
= pDst
->drawable
.pScreen
;
214 KdScreenPriv(pScreen
);
215 KdScreenInfo
*screen
= pScreenPriv
->screen
;
216 EphyrScrPriv
*scrpriv
= screen
->driver
;
217 EphyrFakexaPriv
*fakexa
= scrpriv
->fakexa
;
219 FreeScratchGC(fakexa
->pGC
);
221 ephyrFinishPipelinedAccess(fakexa
->pSrc
, EXA_PREPARE_SRC
);
222 ephyrFinishPipelinedAccess(fakexa
->pDst
, EXA_PREPARE_DEST
);
226 * Reports that we can always accelerate the given operation. This may not be
227 * desirable from an EXA testing standpoint -- testing the fallback paths would
231 ephyrCheckComposite(int op
, PicturePtr pSrcPicture
, PicturePtr pMaskPicture
,
232 PicturePtr pDstPicture
)
234 /* Exercise the component alpha helper, so fail on this case like a normal
237 if (pMaskPicture
&& pMaskPicture
->componentAlpha
&& op
== PictOpOver
)
244 * Saves off the parameters for ephyrComposite.
247 ephyrPrepareComposite(int op
, PicturePtr pSrcPicture
, PicturePtr pMaskPicture
,
248 PicturePtr pDstPicture
, PixmapPtr pSrc
, PixmapPtr pMask
,
251 KdScreenPriv(pDst
->drawable
.pScreen
);
252 KdScreenInfo
*screen
= pScreenPriv
->screen
;
253 EphyrScrPriv
*scrpriv
= screen
->driver
;
254 EphyrFakexaPriv
*fakexa
= scrpriv
->fakexa
;
256 ephyrPreparePipelinedAccess(pDst
, EXA_PREPARE_DEST
);
257 ephyrPreparePipelinedAccess(pSrc
, EXA_PREPARE_SRC
);
259 ephyrPreparePipelinedAccess(pMask
, EXA_PREPARE_MASK
);
262 fakexa
->pSrcPicture
= pSrcPicture
;
263 fakexa
->pMaskPicture
= pMaskPicture
;
264 fakexa
->pDstPicture
= pDstPicture
;
266 fakexa
->pMask
= pMask
;
275 * Does an fbComposite to complete the requested drawing operation.
278 ephyrComposite(PixmapPtr pDst
, int srcX
, int srcY
, int maskX
, int maskY
,
279 int dstX
, int dstY
, int w
, int h
)
281 KdScreenPriv(pDst
->drawable
.pScreen
);
282 KdScreenInfo
*screen
= pScreenPriv
->screen
;
283 EphyrScrPriv
*scrpriv
= screen
->driver
;
284 EphyrFakexaPriv
*fakexa
= scrpriv
->fakexa
;
286 fbComposite(fakexa
->op
, fakexa
->pSrcPicture
, fakexa
->pMaskPicture
,
287 fakexa
->pDstPicture
, srcX
, srcY
, maskX
, maskY
, dstX
, dstY
,
292 ephyrDoneComposite(PixmapPtr pDst
)
294 KdScreenPriv(pDst
->drawable
.pScreen
);
295 KdScreenInfo
*screen
= pScreenPriv
->screen
;
296 EphyrScrPriv
*scrpriv
= screen
->driver
;
297 EphyrFakexaPriv
*fakexa
= scrpriv
->fakexa
;
299 if (fakexa
->pMask
!= NULL
)
300 ephyrFinishPipelinedAccess(fakexa
->pMask
, EXA_PREPARE_MASK
);
301 ephyrFinishPipelinedAccess(fakexa
->pSrc
, EXA_PREPARE_SRC
);
302 ephyrFinishPipelinedAccess(fakexa
->pDst
, EXA_PREPARE_DEST
);
306 * Does fake acceleration of DownloadFromScren using memcpy.
309 ephyrDownloadFromScreen(PixmapPtr pSrc
, int x
, int y
, int w
, int h
, char *dst
,
312 KdScreenPriv(pSrc
->drawable
.pScreen
);
313 KdScreenInfo
*screen
= pScreenPriv
->screen
;
314 EphyrScrPriv
*scrpriv
= screen
->driver
;
315 EphyrFakexaPriv
*fakexa
= scrpriv
->fakexa
;
319 if (pSrc
->drawable
.bitsPerPixel
< 8)
322 ephyrPreparePipelinedAccess(pSrc
, EXA_PREPARE_SRC
);
324 cpp
= pSrc
->drawable
.bitsPerPixel
/ 8;
325 src_pitch
= exaGetPixmapPitch(pSrc
);
326 src
= fakexa
->exa
->memoryBase
+ exaGetPixmapOffset(pSrc
);
327 src
+= y
* src_pitch
+ x
* cpp
;
330 memcpy(dst
, src
, w
* cpp
);
335 exaMarkSync(pSrc
->drawable
.pScreen
);
337 ephyrFinishPipelinedAccess(pSrc
, EXA_PREPARE_SRC
);
343 * Does fake acceleration of UploadToScreen using memcpy.
346 ephyrUploadToScreen(PixmapPtr pDst
, int x
, int y
, int w
, int h
, char *src
,
349 KdScreenPriv(pDst
->drawable
.pScreen
);
350 KdScreenInfo
*screen
= pScreenPriv
->screen
;
351 EphyrScrPriv
*scrpriv
= screen
->driver
;
352 EphyrFakexaPriv
*fakexa
= scrpriv
->fakexa
;
356 if (pDst
->drawable
.bitsPerPixel
< 8)
359 ephyrPreparePipelinedAccess(pDst
, EXA_PREPARE_DEST
);
361 cpp
= pDst
->drawable
.bitsPerPixel
/ 8;
362 dst_pitch
= exaGetPixmapPitch(pDst
);
363 dst
= fakexa
->exa
->memoryBase
+ exaGetPixmapOffset(pDst
);
364 dst
+= y
* dst_pitch
+ x
* cpp
;
367 memcpy(dst
, src
, w
* cpp
);
372 exaMarkSync(pDst
->drawable
.pScreen
);
374 ephyrFinishPipelinedAccess(pDst
, EXA_PREPARE_DEST
);
380 ephyrPrepareAccess(PixmapPtr pPix
, int index
)
382 /* Make sure we don't somehow end up with a pointer that is in framebuffer
383 * and hasn't been readied for us.
385 assert(pPix
->devPrivate
.ptr
!= NULL
);
391 * In fakexa, we currently only track whether we have synced to the latest
392 * "accelerated" drawing that has happened or not. It's not used for anything
396 ephyrMarkSync(ScreenPtr pScreen
)
398 KdScreenPriv(pScreen
);
399 KdScreenInfo
*screen
= pScreenPriv
->screen
;
400 EphyrScrPriv
*scrpriv
= screen
->driver
;
401 EphyrFakexaPriv
*fakexa
= scrpriv
->fakexa
;
403 fakexa
->is_synced
= FALSE
;
409 * Assumes that we're waiting on the latest marker. When EXA gets smarter and
410 * starts using markers in a fine-grained way (for example, waiting on drawing
411 * to required pixmaps to complete, rather than waiting for all drawing to
412 * complete), we'll want to make the ephyrMarkSync/ephyrWaitMarker
413 * implementation fine-grained as well.
416 ephyrWaitMarker(ScreenPtr pScreen
, int marker
)
418 KdScreenPriv(pScreen
);
419 KdScreenInfo
*screen
= pScreenPriv
->screen
;
420 EphyrScrPriv
*scrpriv
= screen
->driver
;
421 EphyrFakexaPriv
*fakexa
= scrpriv
->fakexa
;
423 fakexa
->is_synced
= TRUE
;
427 * This function initializes EXA to use the fake acceleration implementation
428 * which just falls through to software. The purpose is to have a reliable,
429 * correct driver with which to test changes to the EXA core.
432 ephyrDrawInit(ScreenPtr pScreen
)
434 KdScreenPriv(pScreen
);
435 KdScreenInfo
*screen
= pScreenPriv
->screen
;
436 EphyrScrPriv
*scrpriv
= screen
->driver
;
437 EphyrPriv
*priv
= screen
->card
->driver
;
438 EphyrFakexaPriv
*fakexa
;
441 fakexa
= calloc(1, sizeof(*fakexa
));
445 fakexa
->exa
= exaDriverAlloc();
446 if (fakexa
->exa
== NULL
) {
451 fakexa
->exa
->memoryBase
= (CARD8
*) (priv
->base
);
452 fakexa
->exa
->memorySize
= priv
->bytes_per_line
* ephyrBufferHeight(screen
);
453 fakexa
->exa
->offScreenBase
= priv
->bytes_per_line
* screen
->height
;
455 /* Since we statically link against EXA, we shouldn't have to be smart about
458 fakexa
->exa
->exa_major
= 2;
459 fakexa
->exa
->exa_minor
= 0;
461 fakexa
->exa
->PrepareSolid
= ephyrPrepareSolid
;
462 fakexa
->exa
->Solid
= ephyrSolid
;
463 fakexa
->exa
->DoneSolid
= ephyrDoneSolid
;
465 fakexa
->exa
->PrepareCopy
= ephyrPrepareCopy
;
466 fakexa
->exa
->Copy
= ephyrCopy
;
467 fakexa
->exa
->DoneCopy
= ephyrDoneCopy
;
469 fakexa
->exa
->CheckComposite
= ephyrCheckComposite
;
470 fakexa
->exa
->PrepareComposite
= ephyrPrepareComposite
;
471 fakexa
->exa
->Composite
= ephyrComposite
;
472 fakexa
->exa
->DoneComposite
= ephyrDoneComposite
;
474 fakexa
->exa
->DownloadFromScreen
= ephyrDownloadFromScreen
;
475 fakexa
->exa
->UploadToScreen
= ephyrUploadToScreen
;
477 fakexa
->exa
->MarkSync
= ephyrMarkSync
;
478 fakexa
->exa
->WaitMarker
= ephyrWaitMarker
;
480 fakexa
->exa
->PrepareAccess
= ephyrPrepareAccess
;
482 fakexa
->exa
->pixmapOffsetAlign
= EPHYR_OFFSET_ALIGN
;
483 fakexa
->exa
->pixmapPitchAlign
= EPHYR_PITCH_ALIGN
;
485 fakexa
->exa
->maxX
= 1023;
486 fakexa
->exa
->maxY
= 1023;
488 fakexa
->exa
->flags
= EXA_OFFSCREEN_PIXMAPS
;
490 success
= exaDriverInit(pScreen
, fakexa
->exa
);
492 ErrorF("Initialized fake EXA acceleration\n");
493 scrpriv
->fakexa
= fakexa
;
496 ErrorF("Failed to initialize EXA\n");
505 ephyrDrawEnable(ScreenPtr pScreen
)
510 ephyrDrawDisable(ScreenPtr pScreen
)
515 ephyrDrawFini(ScreenPtr pScreen
)
520 * exaDDXDriverInit is required by the top-level EXA module, and is used by
521 * the xorg DDX to hook in its EnableDisableFB wrapper. We don't need it, since
522 * we won't be enabling/disabling the FB.
525 exaDDXDriverInit(ScreenPtr pScreen
)
527 ExaScreenPriv(pScreen
);
529 pExaScr
->migration
= ExaMigrationSmart
;
530 pExaScr
->checkDirtyCorrectness
= TRUE
;