From 3d511ad85744b88158d6dbcaa51eb8860cde8dd4 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 6 Jun 2011 05:36:07 +0000 Subject: [PATCH 2/4] Remove the cacheing of the last scratch PixmapRec In order for the driver to be notified of when the resource backing the scratch pixmap becomes no longer accessible, it needs to be called on every FreeScratchPixmapHeader(). As we instead maybe cached the PixmapRec (to avoid the free and malloc overhead), this notification went astray, and the driver would fail to insert the correct barriers on the backing resource. That resource would then be reused by the Xserver, leading to rampant memory corruption as the GPU flushed it write caches at some point in the future and overwriting random structures. In addition we introduce a new hint, CREATE_PIXMAP_USAGE_SCRATCH_HEADER, so that the driver can be warned during pixmap creation (and lifetime) if the pixmap points to other data. A side-effect of removing the cache is that several members of the ScreenInfo structure and associated routines become redundant and deleted as well. So we bump the ABI version as well. Signed-off-by: Chris Wilson --- dix/dispatch.c | 1 - dix/main.c | 4 +-- dix/pixmap.c | 58 ++++++++++++++++------------------------ fb/fbpixmap.c | 2 +- hw/xfree86/common/xf86Module.h | 2 +- include/pixmap.h | 7 +--- include/scrnintstr.h | 8 +++--- 7 files changed, 32 insertions(+), 50 deletions(-) diff --git a/dix/dispatch.c b/dix/dispatch.c index 192c8c3..3f73175 100644 --- a/dix/dispatch.c +++ b/dix/dispatch.c @@ -3855,7 +3855,6 @@ AddScreen( return -1; } pScreen->myNum = i; - pScreen->totalPixmapSize = 0; /* computed in CreateScratchPixmapForScreen */ pScreen->ClipNotify = 0; /* for R4 ddx compatibility */ pScreen->CreateScreenResources = 0; diff --git a/dix/main.c b/dix/main.c index 955b7ea..7eadf36 100644 --- a/dix/main.c +++ b/dix/main.c @@ -206,12 +206,11 @@ int main(int argc, char *argv[], char *envp[]) if (screenInfo.numScreens < 1) FatalError("no screens found"); InitExtensions(argc, argv); + InitPixmaps(); for (i = 0; i < screenInfo.numScreens; i++) { ScreenPtr pScreen = screenInfo.screens[i]; - if (!CreateScratchPixmapsForScreen(i)) - FatalError("failed to create scratch pixmaps"); if (pScreen->CreateScreenResources && !(*pScreen->CreateScreenResources)(pScreen)) FatalError("failed to create screen resources"); @@ -321,7 +320,6 @@ int main(int argc, char *argv[], char *envp[]) for (i = screenInfo.numScreens - 1; i >= 0; i--) { - FreeScratchPixmapsForScreen(i); FreeGCperDepth(i); FreeDefaultStipple(i); (* screenInfo.screens[i]->CloseScreen)(i, screenInfo.screens[i]); diff --git a/dix/pixmap.c b/dix/pixmap.c index cbb5e7f..0b43592 100644 --- a/dix/pixmap.c +++ b/dix/pixmap.c @@ -53,20 +53,19 @@ PixmapPtr GetScratchPixmapHeader(ScreenPtr pScreen, int width, int height, int depth, int bitsPerPixel, int devKind, pointer pPixData) { - PixmapPtr pPixmap = pScreen->pScratchPixmap; + PixmapPtr pPixmap; - if (pPixmap) - pScreen->pScratchPixmap = NULL; - else - /* width and height of 0 means don't allocate any pixmap data */ - pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, depth, 0); - - if (pPixmap) { - if ((*pScreen->ModifyPixmapHeader)(pPixmap, width, height, depth, - bitsPerPixel, devKind, pPixData)) - return pPixmap; - (*pScreen->DestroyPixmap)(pPixmap); - } + /* width and height of 0 means don't allocate any pixmap data */ + pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, depth, + CREATE_PIXMAP_USAGE_SCRATCH_HEADER); + if (pPixmap == NullPixmap) + return NullPixmap; + + if ((*pScreen->ModifyPixmapHeader)(pPixmap, width, height, depth, + bitsPerPixel, devKind, pPixData)) + return pPixmap; + + (*pScreen->DestroyPixmap)(pPixmap); return NullPixmap; } @@ -79,33 +78,22 @@ FreeScratchPixmapHeader(PixmapPtr pPixmap) { ScreenPtr pScreen = pPixmap->drawable.pScreen; - pPixmap->devPrivate.ptr = NULL; /* lest ddx chases bad ptr */ - if (pScreen->pScratchPixmap) - (*pScreen->DestroyPixmap)(pPixmap); - else - pScreen->pScratchPixmap = pPixmap; + if (pPixmap->refcnt != 1) + FatalError("Scratch pixmap still in use when finalized, refcnt=%d\n", + pPixmap->refcnt); + + (*pScreen->DestroyPixmap)(pPixmap); } } -Bool -CreateScratchPixmapsForScreen(int scrnum) +void +InitPixmaps(void) { unsigned int pixmap_size; pixmap_size = sizeof(PixmapRec) + dixPrivatesSize(PRIVATE_PIXMAP); - screenInfo.screens[scrnum]->totalPixmapSize = BitmapBytePad(pixmap_size * 8); - - /* let it be created on first use */ - screenInfo.screens[scrnum]->pScratchPixmap = NULL; - return TRUE; -} - - -void -FreeScratchPixmapsForScreen(int scrnum) -{ - FreeScratchPixmapHeader(screenInfo.screens[scrnum]->pScratchPixmap); + screenInfo.totalPixmapSize = BitmapBytePad(pixmap_size * 8); } @@ -115,12 +103,12 @@ AllocatePixmap(ScreenPtr pScreen, int pixDataSize) { PixmapPtr pPixmap; - assert(pScreen->totalPixmapSize > 0); + assert(screenInfo.totalPixmapSize > 0); - if (pScreen->totalPixmapSize > ((size_t)-1) - pixDataSize) + if (screenInfo.totalPixmapSize > ((size_t)-1) - pixDataSize) return NullPixmap; - pPixmap = malloc(pScreen->totalPixmapSize + pixDataSize); + pPixmap = malloc(screenInfo.totalPixmapSize + pixDataSize); if (!pPixmap) return NullPixmap; diff --git a/fb/fbpixmap.c b/fb/fbpixmap.c index a356c67..aebdff0 100644 --- a/fb/fbpixmap.c +++ b/fb/fbpixmap.c @@ -42,7 +42,7 @@ fbCreatePixmapBpp (ScreenPtr pScreen, int width, int height, int depth, int bpp, if (paddedWidth / 4 > 32767 || height > 32767) return NullPixmap; datasize = height * paddedWidth; - base = pScreen->totalPixmapSize; + base = screenInfo.totalPixmapSize; adjust = 0; if (base & 7) adjust = 8 - (base & 7); diff --git a/hw/xfree86/common/xf86Module.h b/hw/xfree86/common/xf86Module.h index 2a5c805..cf7557e 100644 --- a/hw/xfree86/common/xf86Module.h +++ b/hw/xfree86/common/xf86Module.h @@ -82,7 +82,7 @@ typedef enum { * mask is 0xFFFF0000. */ #define ABI_ANSIC_VERSION SET_ABI_VERSION(0, 4) -#define ABI_VIDEODRV_VERSION SET_ABI_VERSION(11, 0) +#define ABI_VIDEODRV_VERSION SET_ABI_VERSION(12, 0) #define ABI_XINPUT_VERSION SET_ABI_VERSION(13, 0) #define ABI_EXTENSION_VERSION SET_ABI_VERSION(5, 0) #define ABI_FONT_VERSION SET_ABI_VERSION(0, 6) diff --git a/include/pixmap.h b/include/pixmap.h index 014a111..daab76c 100644 --- a/include/pixmap.h +++ b/include/pixmap.h @@ -103,11 +103,8 @@ extern _X_EXPORT PixmapPtr GetScratchPixmapHeader( extern _X_EXPORT void FreeScratchPixmapHeader( PixmapPtr /*pPixmap*/); -extern _X_EXPORT Bool CreateScratchPixmapsForScreen( - int /*scrnum*/); - -extern _X_EXPORT void FreeScratchPixmapsForScreen( - int /*scrnum*/); +extern _X_EXPORT void InitPixmaps( + void); extern _X_EXPORT PixmapPtr AllocatePixmap( ScreenPtr /*pScreen*/, diff --git a/include/scrnintstr.h b/include/scrnintstr.h index a9357e8..617eadb 100644 --- a/include/scrnintstr.h +++ b/include/scrnintstr.h @@ -202,6 +202,8 @@ typedef void (* ClipNotifyProcPtr)( #define CREATE_PIXMAP_USAGE_BACKING_PIXMAP 2 /* pixmap will contain a glyph */ #define CREATE_PIXMAP_USAGE_GLYPH_PICTURE 3 +/* pixmap will only be as a header for transient (e.g. on-stack) pixels */ +#define CREATE_PIXMAP_USAGE_SCRATCH_HEADER 4 typedef PixmapPtr (* CreatePixmapProcPtr)( ScreenPtr /*pScreen*/, @@ -518,10 +520,6 @@ typedef struct _Screen { GetScreenPixmapProcPtr GetScreenPixmap; SetScreenPixmapProcPtr SetScreenPixmap; - PixmapPtr pScratchPixmap; /* scratch pixmap "pool" */ - - unsigned int totalPixmapSize; - MarkWindowProcPtr MarkWindow; MarkOverlappedWindowsProcPtr MarkOverlappedWindows; ConfigNotifyProcPtr ConfigNotify; @@ -556,6 +554,8 @@ typedef struct _ScreenInfo { int bitmapScanlineUnit; int bitmapScanlinePad; int bitmapBitOrder; + unsigned int totalPixmapSize; + int numPixmapFormats; PixmapFormatRec formats[MAXFORMATS]; -- 1.7.3.4