dependencies. It was nearly abstract enough already to be used by multiple DDXes. This will be useful for EXA development through providing a fake acceleration implementation within Xephyr, so that testing can be done on new EXA code without worrying about buggy drivers.
312 lines
8.6 KiB
C
312 lines
8.6 KiB
C
/*
|
|
* Copyright © 2001 Keith Packard
|
|
*
|
|
* Partly based on code that is Copyright © The XFree86 Project Inc.
|
|
*
|
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
* documentation for any purpose is hereby granted without fee, provided that
|
|
* the above copyright notice appear in all copies and that both that
|
|
* copyright notice and this permission notice appear in supporting
|
|
* documentation, and that the name of Keith Packard not be used in
|
|
* advertising or publicity pertaining to distribution of the software without
|
|
* specific, written prior permission. Keith Packard makes no
|
|
* representations about the suitability of this software for any purpose. It
|
|
* is provided "as is" without express or implied warranty.
|
|
*
|
|
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
* PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
|
|
#ifdef HAVE_DIX_CONFIG_H
|
|
#include <dix-config.h>
|
|
#endif
|
|
|
|
#include <string.h>
|
|
|
|
#include "exa_priv.h"
|
|
#include <X11/fonts/fontstruct.h>
|
|
#include "dixfontstr.h"
|
|
#include "exa.h"
|
|
#include "cw.h"
|
|
|
|
#if DEBUG_MIGRATE
|
|
#define DBG_MIGRATE(a) ErrorF a
|
|
#else
|
|
#define DBG_MIGRATE(a)
|
|
#endif
|
|
|
|
static void
|
|
exaPixmapSave (ScreenPtr pScreen, ExaOffscreenArea *area)
|
|
{
|
|
PixmapPtr pPixmap = area->privData;
|
|
ExaScreenPriv (pScreen);
|
|
ExaPixmapPriv(pPixmap);
|
|
int dst_pitch, src_pitch, bytes;
|
|
char *dst, *src;
|
|
int i;
|
|
|
|
DBG_MIGRATE (("Save %p (%p) (%dx%d)\n",
|
|
(void*)pPixmap->drawable.id,
|
|
(void*)(ExaGetPixmapPriv(pPixmap)->area ?
|
|
ExaGetPixmapPriv(pPixmap)->area->offset : 0),
|
|
pPixmap->drawable.width,
|
|
pPixmap->drawable.height));
|
|
|
|
src_pitch = pPixmap->devKind;
|
|
dst_pitch = pExaPixmap->devKind;
|
|
|
|
src = pPixmap->devPrivate.ptr;
|
|
dst = pExaPixmap->devPrivate.ptr;
|
|
|
|
if (pExaPixmap->dirty) {
|
|
if (pExaScr->info->accel.DownloadFromScreen &&
|
|
(*pExaScr->info->accel.DownloadFromScreen) (pPixmap,
|
|
pPixmap->drawable.x,
|
|
pPixmap->drawable.y,
|
|
pPixmap->drawable.width,
|
|
pPixmap->drawable.height,
|
|
dst,
|
|
dst_pitch)) {
|
|
|
|
} else {
|
|
exaWaitSync (pPixmap->drawable.pScreen);
|
|
|
|
bytes = src_pitch < dst_pitch ? src_pitch : dst_pitch;
|
|
|
|
i = pPixmap->drawable.height;
|
|
while (i--) {
|
|
memcpy (dst, src, bytes);
|
|
dst += dst_pitch;
|
|
src += src_pitch;
|
|
}
|
|
}
|
|
}
|
|
|
|
pPixmap->devKind = dst_pitch;
|
|
pPixmap->devPrivate.ptr = pExaPixmap->devPrivate.ptr;
|
|
pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
|
|
pExaPixmap->area = NULL;
|
|
/* Mark it dirty now, to say that there is important data in the
|
|
* system-memory copy.
|
|
*/
|
|
pExaPixmap->dirty = TRUE;
|
|
}
|
|
|
|
static int
|
|
exaLog2(int val)
|
|
{
|
|
int bits;
|
|
|
|
if (!val)
|
|
return 0;
|
|
for (bits = 0; val != 0; bits++)
|
|
val >>= 1;
|
|
return bits - 1;
|
|
}
|
|
|
|
static Bool
|
|
exaPixmapAllocArea (PixmapPtr pPixmap)
|
|
{
|
|
ScreenPtr pScreen = pPixmap->drawable.pScreen;
|
|
ExaScreenPriv (pScreen);
|
|
ExaPixmapPriv (pPixmap);
|
|
int bpp = pPixmap->drawable.bitsPerPixel;
|
|
CARD16 h = pPixmap->drawable.height;
|
|
CARD16 w = pPixmap->drawable.width;
|
|
int pitch;
|
|
|
|
if (pExaScr->info->card.flags & EXA_OFFSCREEN_ALIGN_POT && w != 1)
|
|
w = 1 << (exaLog2(w - 1) + 1);
|
|
pitch = (w * bpp / 8) + (pExaScr->info->card.pixmapPitchAlign - 1);
|
|
pitch -= pitch % pExaScr->info->card.pixmapPitchAlign;
|
|
|
|
pExaPixmap->size = pitch * h;
|
|
pExaPixmap->devKind = pPixmap->devKind;
|
|
pExaPixmap->devPrivate = pPixmap->devPrivate;
|
|
pExaPixmap->area = exaOffscreenAlloc (pScreen, pitch * h,
|
|
pExaScr->info->card.pixmapOffsetAlign,
|
|
FALSE,
|
|
exaPixmapSave, (pointer) pPixmap);
|
|
if (!pExaPixmap->area)
|
|
return FALSE;
|
|
|
|
DBG_PIXMAP(("++ 0x%lx (0x%x) (%dx%d)\n", pPixmap->drawable.id,
|
|
(ExaGetPixmapPriv(pPixmap)->area ?
|
|
ExaGetPixmapPriv(pPixmap)->area->offset : 0),
|
|
pPixmap->drawable.width,
|
|
pPixmap->drawable.height));
|
|
pPixmap->devKind = pitch;
|
|
|
|
pPixmap->devPrivate.ptr = (pointer) ((CARD8 *) pExaScr->info->card.memoryBase + pExaPixmap->area->offset);
|
|
pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
exaMoveInPixmap (PixmapPtr pPixmap)
|
|
{
|
|
ScreenPtr pScreen = pPixmap->drawable.pScreen;
|
|
ExaScreenPriv (pScreen);
|
|
ExaPixmapPriv (pPixmap);
|
|
int dst_pitch, src_pitch, bytes;
|
|
char *dst, *src;
|
|
int i;
|
|
|
|
DBG_MIGRATE (("-> 0x%lx (0x%x) (%dx%d)\n", pPixmap->drawable.id,
|
|
(ExaGetPixmapPriv(pPixmap)->area ?
|
|
ExaGetPixmapPriv(pPixmap)->area->offset : 0),
|
|
pPixmap->drawable.width,
|
|
pPixmap->drawable.height));
|
|
|
|
src = pPixmap->devPrivate.ptr;
|
|
src_pitch = pPixmap->devKind;
|
|
|
|
if (!exaPixmapAllocArea (pPixmap)) {
|
|
DBG_MIGRATE (("failed to allocate fb for pixmap %p (%dx%dx%d)\n",
|
|
(pointer)pPixmap,
|
|
pPixmap->drawable.width, pPixmap->drawable.height,
|
|
pPixmap->drawable.bitsPerPixel));
|
|
return;
|
|
}
|
|
|
|
/* If the "dirty" flag has never been set on the in-memory pixmap, then
|
|
* nothing has been written to it, so the contents are undefined and we can
|
|
* avoid the upload.
|
|
*/
|
|
if (!pExaPixmap->dirty) {
|
|
DBG_MIGRATE(("saved upload of %dx%d\n", pPixmap->drawable.width,
|
|
pPixmap->drawable.height));
|
|
return;
|
|
}
|
|
|
|
pExaPixmap->dirty = FALSE;
|
|
|
|
if (pExaScr->info->accel.UploadToScreen)
|
|
{
|
|
if (pExaScr->info->accel.UploadToScreen(pPixmap, 0, 0,
|
|
pPixmap->drawable.width,
|
|
pPixmap->drawable.height,
|
|
src, src_pitch))
|
|
return;
|
|
}
|
|
|
|
dst = pPixmap->devPrivate.ptr;
|
|
dst_pitch = pPixmap->devKind;
|
|
|
|
bytes = src_pitch < dst_pitch ? src_pitch : dst_pitch;
|
|
|
|
exaWaitSync (pPixmap->drawable.pScreen);
|
|
|
|
i = pPixmap->drawable.height;
|
|
DBG_PIXMAP(("dst = %p, src = %p,(%d, %d) height = %d, mem_base = %p, offset = %d\n",
|
|
dst, src, dst_pitch, src_pitch,
|
|
i, pExaScr->info->card.memoryBase, ExaGetPixmapPriv(pPixmap)->area->offset));
|
|
|
|
while (i--) {
|
|
memcpy (dst, src, bytes);
|
|
dst += dst_pitch;
|
|
src += src_pitch;
|
|
}
|
|
}
|
|
|
|
void
|
|
exaMoveOutPixmap (PixmapPtr pPixmap)
|
|
{
|
|
ExaPixmapPriv (pPixmap);
|
|
ExaOffscreenArea *area = pExaPixmap->area;
|
|
|
|
DBG_MIGRATE (("<- 0x%p (0x%p) (%dx%d)\n",
|
|
(void*)pPixmap->drawable.id,
|
|
(void*)(ExaGetPixmapPriv(pPixmap)->area ?
|
|
ExaGetPixmapPriv(pPixmap)->area->offset : 0),
|
|
pPixmap->drawable.width,
|
|
pPixmap->drawable.height));
|
|
if (area)
|
|
{
|
|
exaPixmapSave (pPixmap->drawable.pScreen, area);
|
|
exaOffscreenFree (pPixmap->drawable.pScreen, area);
|
|
}
|
|
}
|
|
|
|
void
|
|
exaDrawableUseScreen(DrawablePtr pDrawable)
|
|
{
|
|
exaPixmapUseScreen (exaGetDrawablePixmap (pDrawable));
|
|
}
|
|
|
|
void
|
|
exaDrawableUseMemory(DrawablePtr pDrawable)
|
|
{
|
|
exaPixmapUseMemory (exaGetDrawablePixmap (pDrawable));
|
|
}
|
|
|
|
void
|
|
exaPixmapUseScreen (PixmapPtr pPixmap)
|
|
{
|
|
ExaPixmapPriv (pPixmap);
|
|
|
|
if (pExaPixmap == NULL) {
|
|
DBG_MIGRATE(("UseScreen: ignoring exa-uncontrolled pixmap %p (%s)\n",
|
|
(pointer)pPixmap,
|
|
exaPixmapIsOffscreen(pPixmap) ? "s" : "m"));
|
|
return;
|
|
}
|
|
|
|
if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED) {
|
|
DBG_MIGRATE(("UseScreen: not migrating pinned pixmap %p\n",
|
|
(pointer)pPixmap));
|
|
return;
|
|
}
|
|
|
|
DBG_MIGRATE(("UseScreen %p score %d\n",
|
|
(pointer)pPixmap, pExaPixmap->score));
|
|
|
|
if (pExaPixmap->score == EXA_PIXMAP_SCORE_INIT) {
|
|
exaMoveInPixmap(pPixmap);
|
|
pExaPixmap->score = 0;
|
|
}
|
|
|
|
if (pExaPixmap->score < EXA_PIXMAP_SCORE_MAX)
|
|
pExaPixmap->score++;
|
|
|
|
if (pExaPixmap->score >= EXA_PIXMAP_SCORE_MOVE_IN &&
|
|
!exaPixmapIsOffscreen(pPixmap))
|
|
{
|
|
exaMoveInPixmap (pPixmap);
|
|
}
|
|
|
|
ExaOffscreenMarkUsed (pPixmap);
|
|
}
|
|
|
|
void
|
|
exaPixmapUseMemory (PixmapPtr pPixmap)
|
|
{
|
|
ExaPixmapPriv (pPixmap);
|
|
|
|
if (pExaPixmap == NULL) {
|
|
DBG_MIGRATE(("UseMem: ignoring exa-uncontrolled pixmap %p (%s)\n",
|
|
(pointer)pPixmap,
|
|
exaPixmapIsOffscreen(pPixmap) ? "s" : "m"));
|
|
return;
|
|
}
|
|
|
|
DBG_MIGRATE(("UseMem: %p score %d\n", (pointer)pPixmap, pExaPixmap->score));
|
|
|
|
if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED)
|
|
return;
|
|
|
|
if (pExaPixmap->score == EXA_PIXMAP_SCORE_INIT)
|
|
pExaPixmap->score = 0;
|
|
|
|
if (pExaPixmap->score > EXA_PIXMAP_SCORE_MIN)
|
|
pExaPixmap->score--;
|
|
|
|
if (pExaPixmap->score <= EXA_PIXMAP_SCORE_MOVE_OUT && pExaPixmap->area)
|
|
exaMoveOutPixmap (pPixmap);
|
|
}
|