On Mon, Apr 18, 2005 at 01:06:23PM +0200, Alexandre Julliard wrote:
Sure, the general idea is fine. You actually don't need a mem_area structure at all, you can store that directly in the phys bitmap. Also it would be nice to only set the handler when a DIB is allocated, not at startup.
Right, I realized that after sending the email about making the data field a pointer to physBitmap. Compiles, but not tested, as I don't have a DIB using app.
ChangeLog Remove the VIRTUAL_SetFaultHandler(), use vectored exceptions instead.
Index: dlls/ntdll/ntdll.spec =================================================================== RCS file: /var/cvs/wine/dlls/ntdll/ntdll.spec,v retrieving revision 1.177 diff -u -p -r1.177 ntdll.spec --- dlls/ntdll/ntdll.spec 16 Apr 2005 11:19:27 -0000 1.177 +++ dlls/ntdll/ntdll.spec 18 Apr 2005 11:42:07 -0000 @@ -1036,4 +1036,3 @@ @ cdecl MODULE_DllThreadAttach(ptr) @ cdecl MODULE_GetLoadOrderW(ptr wstr wstr) @ cdecl VERSION_Init(wstr) -@ cdecl VIRTUAL_SetFaultHandler(ptr ptr ptr) Index: dlls/ntdll/virtual.c =================================================================== RCS file: /var/cvs/wine/dlls/ntdll/virtual.c,v retrieving revision 1.46 diff -u -p -r1.46 virtual.c --- dlls/ntdll/virtual.c 22 Feb 2005 19:33:50 -0000 1.46 +++ dlls/ntdll/virtual.c 17 Apr 2005 04:20:14 -0000 @@ -1098,25 +1104,6 @@ void virtual_init(void)
/*********************************************************************** - * VIRTUAL_SetFaultHandler - */ -BOOL VIRTUAL_SetFaultHandler( LPCVOID addr, HANDLERPROC proc, LPVOID arg ) -{ - FILE_VIEW *view; - BOOL ret = FALSE; - - RtlEnterCriticalSection( &csVirtual ); - if ((view = VIRTUAL_FindView( addr ))) - { - view->handlerProc = proc; - view->handlerArg = arg; - ret = TRUE; - } - RtlLeaveCriticalSection( &csVirtual ); - return ret; -} - -/*********************************************************************** * VIRTUAL_HandleFault */ DWORD VIRTUAL_HandleFault( LPCVOID addr ) Index: dlls/x11drv/dib.c =================================================================== RCS file: /var/cvs/wine/dlls/x11drv/dib.c,v retrieving revision 1.35 diff -u -p -r1.35 dib.c --- dlls/x11drv/dib.c 14 Apr 2005 12:48:31 -0000 1.35 +++ dlls/x11drv/dib.c 18 Apr 2005 12:14:34 -0000 @@ -38,11 +38,25 @@ #include "winbase.h" #include "wingdi.h" #include "x11drv.h" +#include "excpt.h" #include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(bitmap); WINE_DECLARE_DEBUG_CHANNEL(x11drv);
+static struct list dibs_list = LIST_INIT(dibs_list); + +static CRITICAL_SECTION dibs_cs; +static CRITICAL_SECTION_DEBUG dibs_cs_debug = +{ + 0, 0, &dibs_cs, + { &dibs_cs_debug.ProcessLocksList, &dibs_cs_debug.ProcessLocksList }, + 0, 0, { 0, (DWORD)(__FILE__ ": dibs_cs") } +}; +static CRITICAL_SECTION dibs_cs = { &dibs_cs_debug, -1, 0, 0, 0, 0 }; + +PVOID dibs_handler = 0; + static int ximageDepthTable[32];
/* This structure holds the arguments for DIB_SetImageBits() */ @@ -4268,22 +4282,43 @@ static void X11DRV_DIB_DoUpdateDIBSectio /*********************************************************************** * X11DRV_DIB_FaultHandler */ -static BOOL X11DRV_DIB_FaultHandler( LPVOID res, LPCVOID addr ) +static LONG CALLBACK X11DRV_DIB_FaultHandler( PEXCEPTION_POINTERS ep ) { - X_PHYSBITMAP *physBitmap = res; - INT state = X11DRV_DIB_Lock( physBitmap, DIB_Status_None, FALSE ); + X_PHYSBITMAP *physBitmap = NULL; + BOOL found = FALSE; + struct list *ptr; + INT state; + + if (ep->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION) + return EXCEPTION_CONTINUE_SEARCH; + + EnterCriticalSection(&dibs_cs); + LIST_FOR_EACH( ptr, &dibs_list ) + { + physBitmap = LIST_ENTRY( ptr, X_PHYSBITMAP, entry ); + if (physBitmap->base > ep->ExceptionRecord->ExceptionAddress) break; + if ((const char*)ep->ExceptionRecord->ExceptionAddress < + (const char*)physBitmap->base + physBitmap->size) + { + found = TRUE; + break; + } + } + LeaveCriticalSection(&dibs_cs);
- if (state != DIB_Status_InSync) { - /* no way to tell whether app needs read or write yet, - * try read first */ - X11DRV_DIB_Coerce( physBitmap, DIB_Status_InSync, FALSE ); - } else { - /* hm, apparently the app must have write access */ - X11DRV_DIB_Coerce( physBitmap, DIB_Status_AppMod, FALSE ); - } - X11DRV_DIB_Unlock( physBitmap, TRUE ); + if (!found) return EXCEPTION_CONTINUE_SEARCH;
- return TRUE; + state = X11DRV_DIB_Lock( physBitmap, DIB_Status_None, FALSE ); + if (state != DIB_Status_InSync) { + /* no way to tell whether app needs read or write yet, try read first */ + X11DRV_DIB_Coerce( physBitmap, DIB_Status_InSync, FALSE ); + } else { + /* hm, apparently the app must have write access */ + X11DRV_DIB_Coerce( physBitmap, DIB_Status_AppMod, FALSE ); + } + X11DRV_DIB_Unlock( physBitmap, TRUE ); + + return EXCEPTION_CONTINUE_EXECUTION; }
/*********************************************************************** @@ -4566,7 +4601,6 @@ static XImage *X11DRV_XShmCreateImage( i HBITMAP X11DRV_CreateDIBSection( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, const BITMAPINFO *bmi, UINT usage ) { - extern BOOL VIRTUAL_SetFaultHandler(LPCVOID addr, BOOL (*proc)(LPVOID, LPCVOID), LPVOID arg); X_PHYSBITMAP *physBitmap; DIBSECTION dib;
@@ -4602,11 +4636,18 @@ HBITMAP X11DRV_CreateDIBSection( X11DRV_
/* install fault handler */ InitializeCriticalSection( &physBitmap->lock ); - if (VIRTUAL_SetFaultHandler(dib.dsBm.bmBits, X11DRV_DIB_FaultHandler, physBitmap)) - { - X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READWRITE ); - physBitmap->status = DIB_Status_AppMod; - } + + physBitmap->base = dib.dsBm.bmBits; + physBitmap->size = dib.dsBmih.biSize; + physBitmap->status = DIB_Status_AppMod; + + EnterCriticalSection( &dibs_cs ); + list_add_head( &dibs_list, &physBitmap->entry ); + if (!dibs_handler) + dibs_handler = AddVectoredExceptionHandler( TRUE, X11DRV_DIB_FaultHandler ); + LeaveCriticalSection( &dibs_cs ); + + X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READWRITE );
return hbitmap; } @@ -4616,6 +4657,10 @@ HBITMAP X11DRV_CreateDIBSection( X11DRV_ */ void X11DRV_DIB_DeleteDIBSection(X_PHYSBITMAP *physBitmap, DIBSECTION *dib) { + EnterCriticalSection( &dibs_cs ); + list_remove( &physBitmap->entry ); + LeaveCriticalSection( &dibs_cs ); + if (dib->dshSection) X11DRV_DIB_Coerce(physBitmap, DIB_Status_InSync, FALSE);
Index: dlls/x11drv/x11drv.h =================================================================== RCS file: /var/cvs/wine/dlls/x11drv/x11drv.h,v retrieving revision 1.69 diff -u -p -r1.69 x11drv.h --- dlls/x11drv/x11drv.h 14 Apr 2005 12:48:11 -0000 1.69 +++ dlls/x11drv/x11drv.h 18 Apr 2005 12:13:43 -0000 @@ -64,6 +64,7 @@ typedef int Status; #include "winuser.h" #include "ddrawi.h" #include "thread.h" +#include "wine/list.h"
#define MAX_PIXELFORMATS 8
@@ -111,6 +112,9 @@ typedef struct #ifdef HAVE_LIBXXSHM XShmSegmentInfo shminfo; /* shared memory segment info */ #endif + struct list entry; /* Entry in global DIB list */ + const void *base; /* Base address */ + SIZE_T size; /* Size in bytes */ } X_PHYSBITMAP;
/* X physical font */ @@ -147,6 +151,7 @@ typedef struct /* GCs used for B&W and color bitmap operations */ extern GC BITMAP_monoGC, BITMAP_colorGC; extern X_PHYSBITMAP BITMAP_stock_phys_bitmap; /* phys bitmap for the default stock bitmap */ +extern PVOID dibs_handler;
#define BITMAP_GC(physBitmap) (((physBitmap)->pixmap_depth == 1) ? BITMAP_monoGC : BITMAP_colorGC)
Index: dlls/x11drv/x11drv_main.c =================================================================== RCS file: /var/cvs/wine/dlls/x11drv/x11drv_main.c,v retrieving revision 1.102 diff -u -p -r1.102 x11drv_main.c --- dlls/x11drv/x11drv_main.c 14 Apr 2005 12:48:11 -0000 1.102 +++ dlls/x11drv/x11drv_main.c 18 Apr 2005 12:06:15 -0000 @@ -422,6 +422,9 @@ static void process_detach(void) /* cleanup GDI */ X11DRV_GDI_Finalize();
+ /* cleanup DIB handling */ + if (dibs_handler) RemoveVectoredExceptionHandler( dibs_handler ); + DeleteCriticalSection( &X11DRV_CritSection ); }