Change EXA so that exaMoveOutPixmap() retains the framebuffer copy of the
pixmap, and damage is tracked so that a later exaMoveInPixmap won't result in an upload if no upload is necessary. This will likely improve the performance of the "Always" migration scheme significantly, and is a step in the path to more exact damage tracking between framebuffer and system memory.
This commit is contained in:
parent
d0d336efd5
commit
14aafc258c
14
ChangeLog
14
ChangeLog
|
@ -1,3 +1,17 @@
|
|||
2006-03-16 Eric Anholt <anholt@FreeBSD.org>
|
||||
|
||||
* exa/exa.c: (exaGetPixmapSize), (exaDestroyPixmap), (exaLog2),
|
||||
(exaCreatePixmap):
|
||||
* exa/exa_migration.c: (exaCopyDirtyToSys), (exaCopyDirtyToFb),
|
||||
(exaPixmapSave), (exaMoveInPixmap), (exaMoveOutPixmap):
|
||||
* exa/exa_priv.h:
|
||||
Change EXA so that exaMoveOutPixmap() retains the framebuffer copy of
|
||||
the pixmap, and damage is tracked so that a later exaMoveInPixmap won't
|
||||
result in an upload if no upload is necessary. This will likely improve
|
||||
the performance of the "Always" migration scheme significantly, and is
|
||||
a step in the path to more exact damage tracking between framebuffer and
|
||||
system memory.
|
||||
|
||||
2006-03-16 Daniel Stone <daniel@freedesktop.org>
|
||||
|
||||
* hw/xfree86/common/xf86PciInfo.h:
|
||||
|
|
38
exa/exa.c
38
exa/exa.c
|
@ -86,7 +86,7 @@ exaGetPixmapSize(PixmapPtr pPix)
|
|||
|
||||
pExaPixmap = ExaGetPixmapPriv(pPix);
|
||||
if (pExaPixmap != NULL)
|
||||
return pExaPixmap->size;
|
||||
return pExaPixmap->fb_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -139,13 +139,25 @@ exaDestroyPixmap (PixmapPtr pPixmap)
|
|||
pPixmap->drawable.height));
|
||||
/* Free the offscreen area */
|
||||
exaOffscreenFree (pPixmap->drawable.pScreen, pExaPixmap->area);
|
||||
pPixmap->devPrivate = pExaPixmap->devPrivate;
|
||||
pPixmap->devKind = pExaPixmap->devKind;
|
||||
pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
|
||||
pPixmap->devKind = pExaPixmap->sys_pitch;
|
||||
}
|
||||
}
|
||||
return fbDestroyPixmap (pPixmap);
|
||||
}
|
||||
|
||||
static int
|
||||
exaLog2(int val)
|
||||
{
|
||||
int bits;
|
||||
|
||||
if (!val)
|
||||
return 0;
|
||||
for (bits = 0; val != 0; bits++)
|
||||
val >>= 1;
|
||||
return bits - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* exaCreatePixmap() creates a new pixmap.
|
||||
*
|
||||
|
@ -170,6 +182,8 @@ exaCreatePixmap(ScreenPtr pScreen, int w, int h, int depth)
|
|||
return NULL;
|
||||
pExaPixmap = ExaGetPixmapPriv(pPixmap);
|
||||
|
||||
bpp = pPixmap->drawable.bitsPerPixel;
|
||||
|
||||
/* Glyphs have w/h equal to zero, and may not be migrated. See exaGlyphs. */
|
||||
if (!w || !h)
|
||||
pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
|
||||
|
@ -177,6 +191,24 @@ exaCreatePixmap(ScreenPtr pScreen, int w, int h, int depth)
|
|||
pExaPixmap->score = EXA_PIXMAP_SCORE_INIT;
|
||||
|
||||
pExaPixmap->area = NULL;
|
||||
|
||||
pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
|
||||
pExaPixmap->sys_pitch = pPixmap->devKind;
|
||||
|
||||
pExaPixmap->fb_ptr = NULL;
|
||||
if (pExaScr->info->flags & EXA_OFFSCREEN_ALIGN_POT && w != 1)
|
||||
pExaPixmap->fb_pitch = (1 << (exaLog2(w - 1) + 1)) * bpp / 8;
|
||||
else
|
||||
pExaPixmap->fb_pitch = w * bpp / 8;
|
||||
pExaPixmap->fb_pitch = EXA_ALIGN(pExaPixmap->fb_pitch,
|
||||
pExaScr->info->pixmapPitchAlign);
|
||||
pExaPixmap->fb_size = pExaPixmap->fb_pitch * h;
|
||||
|
||||
if (pExaPixmap->fb_pitch > 32767) {
|
||||
fbDestroyPixmap(pPixmap);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pExaPixmap->dirty = FALSE;
|
||||
|
||||
return pPixmap;
|
||||
|
|
|
@ -1,25 +1,28 @@
|
|||
/*
|
||||
* Copyright © 2001 Keith Packard
|
||||
* Copyright © 2006 Intel Corporation
|
||||
*
|
||||
* Partly based on code that is Copyright © The XFree86 Project Inc.
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* 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.
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*
|
||||
* 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
|
||||
|
@ -54,15 +57,131 @@ exaPixmapIsPinned (PixmapPtr pPix)
|
|||
return pExaPixmap == NULL || pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the pixmap is currently dirty, this copies at least the dirty area from
|
||||
* the framebuffer memory copy to the system memory copy. Both areas must be
|
||||
* allocated.
|
||||
*/
|
||||
static void
|
||||
exaCopyDirtyToSys (PixmapPtr pPixmap)
|
||||
{
|
||||
ExaScreenPriv (pPixmap->drawable.pScreen);
|
||||
ExaPixmapPriv (pPixmap);
|
||||
CARD8 *save_ptr;
|
||||
int save_pitch;
|
||||
|
||||
if (!pExaPixmap->dirty)
|
||||
return;
|
||||
|
||||
save_ptr = pPixmap->devPrivate.ptr;
|
||||
save_pitch = pPixmap->devKind;
|
||||
pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
|
||||
pPixmap->devKind = pExaPixmap->fb_pitch;
|
||||
|
||||
if (pExaScr->info->DownloadFromScreen == NULL ||
|
||||
!pExaScr->info->DownloadFromScreen (pPixmap,
|
||||
0,
|
||||
0,
|
||||
pPixmap->drawable.width,
|
||||
pPixmap->drawable.height,
|
||||
pExaPixmap->sys_ptr,
|
||||
pExaPixmap->sys_pitch))
|
||||
{
|
||||
char *src, *dst;
|
||||
int src_pitch, dst_pitch, i, bytes;
|
||||
|
||||
exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
|
||||
|
||||
dst = pExaPixmap->sys_ptr;
|
||||
dst_pitch = pExaPixmap->sys_pitch;
|
||||
src = pExaPixmap->fb_ptr;
|
||||
src_pitch = pExaPixmap->fb_pitch;
|
||||
bytes = src_pitch < dst_pitch ? src_pitch : dst_pitch;
|
||||
|
||||
for (i = 0; i < pPixmap->drawable.height; i++) {
|
||||
memcpy (dst, src, bytes);
|
||||
dst += dst_pitch;
|
||||
src += src_pitch;
|
||||
}
|
||||
exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
|
||||
}
|
||||
|
||||
/* Make sure the bits have actually landed, since we don't necessarily sync
|
||||
* when accessing pixmaps in system memory.
|
||||
*/
|
||||
exaWaitSync (pPixmap->drawable.pScreen);
|
||||
|
||||
pPixmap->devPrivate.ptr = save_ptr;
|
||||
pPixmap->devKind = save_pitch;
|
||||
|
||||
pExaPixmap->dirty = FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the pixmap is currently dirty, this copies at least the dirty area from
|
||||
* the system memory copy to the framebuffer memory copy. Both areas must be
|
||||
* allocated.
|
||||
*/
|
||||
static void
|
||||
exaCopyDirtyToFb (PixmapPtr pPixmap)
|
||||
{
|
||||
ExaScreenPriv (pPixmap->drawable.pScreen);
|
||||
ExaPixmapPriv (pPixmap);
|
||||
CARD8 *save_ptr;
|
||||
int save_pitch;
|
||||
|
||||
if (!pExaPixmap->dirty)
|
||||
return;
|
||||
|
||||
save_ptr = pPixmap->devPrivate.ptr;
|
||||
save_pitch = pPixmap->devKind;
|
||||
pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
|
||||
pPixmap->devKind = pExaPixmap->fb_pitch;
|
||||
|
||||
if (pExaScr->info->UploadToScreen == NULL ||
|
||||
!pExaScr->info->UploadToScreen (pPixmap,
|
||||
0,
|
||||
0,
|
||||
pPixmap->drawable.width,
|
||||
pPixmap->drawable.height,
|
||||
pExaPixmap->sys_ptr,
|
||||
pExaPixmap->sys_pitch))
|
||||
{
|
||||
char *src, *dst;
|
||||
int src_pitch, dst_pitch, i, bytes;
|
||||
|
||||
exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_DEST);
|
||||
|
||||
dst = pExaPixmap->fb_ptr;
|
||||
dst_pitch = pExaPixmap->fb_pitch;
|
||||
src = pExaPixmap->sys_ptr;
|
||||
src_pitch = pExaPixmap->sys_pitch;
|
||||
bytes = src_pitch < dst_pitch ? src_pitch : dst_pitch;
|
||||
|
||||
for (i = 0; i < pPixmap->drawable.height; i++) {
|
||||
memcpy (dst, src, bytes);
|
||||
dst += dst_pitch;
|
||||
src += src_pitch;
|
||||
}
|
||||
exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_DEST);
|
||||
}
|
||||
|
||||
pPixmap->devPrivate.ptr = save_ptr;
|
||||
pPixmap->devKind = save_pitch;
|
||||
|
||||
pExaPixmap->dirty = FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies out important pixmap data and removes references to framebuffer area.
|
||||
* Called when the memory manager decides it's time to kick the pixmap out of
|
||||
* framebuffer entirely.
|
||||
*/
|
||||
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,
|
||||
|
@ -71,171 +190,99 @@ exaPixmapSave (ScreenPtr pScreen, ExaOffscreenArea *area)
|
|||
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->DownloadFromScreen &&
|
||||
(*pExaScr->info->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;
|
||||
}
|
||||
}
|
||||
if (pPixmap->devPrivate.ptr == pExaPixmap->fb_ptr) {
|
||||
exaCopyDirtyToSys (pPixmap);
|
||||
pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
|
||||
pPixmap->devKind = pExaPixmap->sys_pitch;
|
||||
pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
|
||||
}
|
||||
|
||||
pPixmap->devKind = dst_pitch;
|
||||
pPixmap->devPrivate.ptr = pExaPixmap->devPrivate.ptr;
|
||||
pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
|
||||
pExaPixmap->fb_ptr = NULL;
|
||||
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->flags & EXA_OFFSCREEN_ALIGN_POT && w != 1)
|
||||
w = 1 << (exaLog2(w - 1) + 1);
|
||||
pitch = (w * bpp / 8) + (pExaScr->info->pixmapPitchAlign - 1);
|
||||
pitch -= pitch % pExaScr->info->pixmapPitchAlign;
|
||||
|
||||
pExaPixmap->size = pitch * h;
|
||||
pExaPixmap->devKind = pPixmap->devKind;
|
||||
pExaPixmap->devPrivate = pPixmap->devPrivate;
|
||||
pExaPixmap->area = exaOffscreenAlloc (pScreen, pitch * h,
|
||||
pExaScr->info->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->memoryBase +
|
||||
pExaPixmap->area->offset);
|
||||
pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates a framebuffer copy of the pixmap if necessary, and then copies
|
||||
* any necessary pixmap data into the framebuffer copy and points the pixmap at
|
||||
* it.
|
||||
*
|
||||
* Note that when first allocated, a pixmap will have FALSE dirty flag.
|
||||
* This is intentional because pixmap data starts out undefined. So if we move
|
||||
* it in due to the first operation against it being accelerated, it will have
|
||||
* undefined framebuffer contents that we didn't have to upload. If we do
|
||||
* moveouts (and moveins) after the first movein, then we will only have to copy
|
||||
* back and forth if the pixmap was written to after the last synchronization of
|
||||
* the two copies. Then, at exaPixmapSave (when the framebuffer copy goes away)
|
||||
* we mark the pixmap dirty, so that the next exaMoveInPixmap will actually move
|
||||
* all the data, since it's almost surely all valid now.
|
||||
*/
|
||||
void
|
||||
exaMoveInPixmap (PixmapPtr pPixmap)
|
||||
{
|
||||
ScreenPtr pScreen = pPixmap->drawable.pScreen;
|
||||
ExaScreenPriv (pScreen);
|
||||
ExaPixmapPriv (pPixmap);
|
||||
int dst_pitch, src_pitch, bytes;
|
||||
char *dst, *src;
|
||||
int i;
|
||||
|
||||
/* If we're VT-switched away, no touching card memory allowed. */
|
||||
if (pExaScr->swappedOut)
|
||||
return;
|
||||
|
||||
/* If we're already in FB, our work is done. */
|
||||
if (pPixmap->devPrivate.ptr == pExaPixmap->fb_ptr)
|
||||
return;
|
||||
|
||||
/* If we're not allowed to move, then fail. */
|
||||
if (exaPixmapIsPinned(pPixmap))
|
||||
return;
|
||||
|
||||
/* Don't migrate in pixmaps which are less than 8bpp. This avoids a lot of
|
||||
* fragility in EXA, and <8bpp is probably not used enough any more to care
|
||||
* (at least, not in acceleratd paths).
|
||||
*/
|
||||
if (pPixmap->drawable.bitsPerPixel < 8)
|
||||
return;
|
||||
|
||||
if (pExaPixmap->area == NULL) {
|
||||
pExaPixmap->area =
|
||||
exaOffscreenAlloc (pScreen, pExaPixmap->fb_size,
|
||||
pExaScr->info->pixmapOffsetAlign, FALSE,
|
||||
exaPixmapSave, (pointer) pPixmap);
|
||||
if (pExaPixmap->area == NULL)
|
||||
return;
|
||||
|
||||
pExaPixmap->fb_ptr = (CARD8 *) pExaScr->info->memoryBase +
|
||||
pExaPixmap->area->offset;
|
||||
}
|
||||
|
||||
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;
|
||||
exaCopyDirtyToFb (pPixmap);
|
||||
|
||||
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->UploadToScreen)
|
||||
{
|
||||
if (pExaScr->info->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->memoryBase, pExaPixmap->area->offset));
|
||||
|
||||
while (i--) {
|
||||
memcpy (dst, src, bytes);
|
||||
dst += dst_pitch;
|
||||
src += src_pitch;
|
||||
}
|
||||
pPixmap->devPrivate.ptr = (pointer) pExaPixmap->fb_ptr;
|
||||
pPixmap->devKind = pExaPixmap->fb_pitch;
|
||||
pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Switches the current active location of the pixmap to system memory, copying
|
||||
* updated data out if necessary.
|
||||
*/
|
||||
void
|
||||
exaMoveOutPixmap (PixmapPtr pPixmap)
|
||||
{
|
||||
ExaPixmapPriv (pPixmap);
|
||||
ExaOffscreenArea *area = pExaPixmap->area;
|
||||
|
||||
if (exaPixmapIsPinned(pPixmap))
|
||||
return;
|
||||
|
||||
DBG_MIGRATE (("<- 0x%p (0x%p) (%dx%d)\n",
|
||||
(void*)pPixmap->drawable.id,
|
||||
|
@ -243,10 +290,13 @@ exaMoveOutPixmap (PixmapPtr pPixmap)
|
|||
ExaGetPixmapPriv(pPixmap)->area->offset : 0),
|
||||
pPixmap->drawable.width,
|
||||
pPixmap->drawable.height));
|
||||
if (area)
|
||||
{
|
||||
exaPixmapSave (pPixmap->drawable.pScreen, area);
|
||||
exaOffscreenFree (pPixmap->drawable.pScreen, area);
|
||||
|
||||
if (pPixmap->devPrivate.ptr == pExaPixmap->fb_ptr) {
|
||||
exaCopyDirtyToSys (pPixmap);
|
||||
|
||||
pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
|
||||
pPixmap->devKind = pExaPixmap->sys_pitch;
|
||||
pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -123,6 +123,12 @@ extern int exaPixmapPrivateIndex;
|
|||
#define ExaGetScreenPriv(s) ((ExaScreenPrivPtr)(s)->devPrivates[exaScreenPrivateIndex].ptr)
|
||||
#define ExaScreenPriv(s) ExaScreenPrivPtr pExaScr = ExaGetScreenPriv(s)
|
||||
|
||||
/** Align an offset to an arbitrary alignment */
|
||||
#define EXA_ALIGN(offset, align) (((offset) + (align) - 1) - \
|
||||
(((offset) + (align) - 1) % (align)))
|
||||
/** Align an offset to a power-of-two alignment */
|
||||
#define EXA_ALIGN2(offset, align) (((offset) + (align) - 1) & ~((align) - 1))
|
||||
|
||||
#define EXA_PIXMAP_SCORE_MOVE_IN 10
|
||||
#define EXA_PIXMAP_SCORE_MAX 20
|
||||
#define EXA_PIXMAP_SCORE_MOVE_OUT -10
|
||||
|
@ -136,19 +142,26 @@ extern int exaPixmapPrivateIndex;
|
|||
|
||||
typedef struct {
|
||||
ExaOffscreenArea *area;
|
||||
int score;
|
||||
int devKind;
|
||||
DevUnion devPrivate;
|
||||
int score; /**< score for the move-in vs move-out heuristic */
|
||||
|
||||
/* If area is NULL, then dirty == TRUE means that the pixmap has been
|
||||
CARD8 *sys_ptr; /**< pointer to pixmap data in system memory */
|
||||
int sys_pitch; /**< pitch of pixmap in system memory */
|
||||
|
||||
CARD8 *fb_ptr; /**< pointer to pixmap data in framebuffer memory */
|
||||
int fb_pitch; /**< pitch of pixmap in framebuffer memory */
|
||||
unsigned int fb_size; /**< size of pixmap in framebuffer memory */
|
||||
|
||||
/**
|
||||
* If area is NULL, then dirty == TRUE means that the pixmap has been
|
||||
* modified, so the contents are defined. Used to avoid uploads of
|
||||
* undefined data.
|
||||
* If area is non-NULL, then dirty == TRUE means that the in-framebuffer
|
||||
* copy has been changed from the system-memory copy. Used to avoid
|
||||
* downloads of unmodified data.
|
||||
*
|
||||
* If area is non-NULL, then dirty == TRUE means that the pixmap data at
|
||||
* pPixmap->devPrivate.ptr (either fb_ptr or sys_ptr) has been changed
|
||||
* compared to the copy in the other location. This is used to avoid
|
||||
* uploads/downloads of unmodified data.
|
||||
*/
|
||||
Bool dirty;
|
||||
unsigned int size;
|
||||
} ExaPixmapPrivRec, *ExaPixmapPrivPtr;
|
||||
|
||||
typedef struct _ExaMigrationRec {
|
||||
|
|
Loading…
Reference in New Issue