diff --git a/dlls/ttydrv/bitmap.c b/dlls/ttydrv/bitmap.c index 888eff0c887..23821e6d128 100644 --- a/dlls/ttydrv/bitmap.c +++ b/dlls/ttydrv/bitmap.c @@ -222,6 +222,23 @@ UINT TTYDRV_BITMAP_GetDIBColorTable(BITMAPOBJ *bmp, DC *dc, UINT start, UINT cou return 0; } +/*********************************************************************** + * TTYDRV_BITMAP_Lock + */ +INT TTYDRV_BITMAP_Lock(BITMAPOBJ *bmp, INT req, BOOL lossy) +{ + FIXME("(%p): stub\n", bmp); + return DIB_Status_None; +} + +/*********************************************************************** + * TTYDRV_BITMAP_Unlock + */ +void TTYDRV_BITMAP_Unlock(BITMAPOBJ *bmp, BOOL commit) +{ + FIXME("(%p): stub\n", bmp); +} + /*********************************************************************** * TTYDRV_BITMAP_GetDIBits */ diff --git a/dlls/ttydrv/dc.c b/dlls/ttydrv/dc.c index 44dc9d1eeda..2bc7163b9e2 100644 --- a/dlls/ttydrv/dc.c +++ b/dlls/ttydrv/dc.c @@ -124,7 +124,9 @@ BITMAP_DRIVER TTYDRV_BITMAP_Driver = TTYDRV_BITMAP_GetDIBits, TTYDRV_BITMAP_DeleteDIBSection, TTYDRV_BITMAP_SetDIBColorTable, - TTYDRV_BITMAP_GetDIBColorTable + TTYDRV_BITMAP_GetDIBColorTable, + TTYDRV_BITMAP_Lock, + TTYDRV_BITMAP_Unlock }; PALETTE_DRIVER TTYDRV_PALETTE_Driver = diff --git a/dlls/ttydrv/ttydrv.h b/dlls/ttydrv/ttydrv.h index 828fd8c9a12..e44f8ec8b6d 100644 --- a/dlls/ttydrv/ttydrv.h +++ b/dlls/ttydrv/ttydrv.h @@ -53,6 +53,8 @@ extern INT TTYDRV_BITMAP_GetDIBits(struct tagBITMAPOBJ *bmp, struct tagDC *dc, U extern void TTYDRV_BITMAP_DeleteDIBSection(struct tagBITMAPOBJ *bmp); extern UINT TTYDRV_BITMAP_SetDIBColorTable(struct tagBITMAPOBJ *,struct tagDC *,UINT,UINT,const RGBQUAD *); extern UINT TTYDRV_BITMAP_GetDIBColorTable(struct tagBITMAPOBJ *,struct tagDC *,UINT,UINT,RGBQUAD *); +extern INT TTYDRV_BITMAP_Lock(struct tagBITMAPOBJ *,INT,BOOL); +extern void TTYDRV_BITMAP_Unlock(struct tagBITMAPOBJ *,BOOL); #ifndef WINE_CURSES typedef struct { int dummy; } WINDOW; diff --git a/graphics/x11drv/bitblt.c b/graphics/x11drv/bitblt.c index 1d2e7af0501..68f87263c20 100644 --- a/graphics/x11drv/bitblt.c +++ b/graphics/x11drv/bitblt.c @@ -1471,11 +1471,11 @@ BOOL X11DRV_PatBlt( DC *dc, INT left, INT top, params.heightSrc = 0; params.rop = rop; - X11DRV_DIB_UpdateDIBSection( dc, FALSE ); + X11DRV_LockDIBSection( dc, DIB_Status_GdiMod, FALSE ); EnterCriticalSection( &X11DRV_CritSection ); result = (BOOL)CALL_LARGE_STACK( BITBLT_DoStretchBlt, ¶ms ); LeaveCriticalSection( &X11DRV_CritSection ); - X11DRV_DIB_UpdateDIBSection( dc, TRUE ); + X11DRV_UnlockDIBSection( dc, TRUE ); return result; } @@ -1488,7 +1488,41 @@ BOOL X11DRV_BitBlt( DC *dcDst, INT xDst, INT yDst, INT xSrc, INT ySrc, DWORD rop ) { struct StretchBlt_params params; - BOOL result; + BOOL result = FALSE; + INT sSrc, sDst; + + if (((rop >> 16) & 0x55) == ((rop >> 17) & 0x55)) { + /* FIXME: seems the ROP doesn't include destination; + * now if the destination area include the entire dcDst, + * we can pass TRUE instead of FALSE to CoerceDIBSection(dcDst...), + * which may avoid a copy in some situations */ + } + sDst = X11DRV_LockDIBSection( dcDst, DIB_Status_None, FALSE ); + sSrc = X11DRV_LockDIBSection( dcSrc, DIB_Status_None, FALSE ); + if ((sSrc == DIB_Status_AppMod) && (rop == SRCCOPY)) { + BITMAPOBJ *bmp; + BOOL done = FALSE; + + if (sDst == DIB_Status_AppMod) { + FIXME("potential optimization - client-side DIB copy\n"); + } + + X11DRV_CoerceDIBSection( dcDst, DIB_Status_GdiMod, FALSE ); + + bmp = (BITMAPOBJ *)GDI_GetObjPtr( dcSrc->hBitmap, BITMAP_MAGIC ); + if (bmp->dib) { + if (bmp->dib->dsBmih.biBitCount > 8) { + if (X11DRV_SetDIBitsToDevice( dcDst, xDst, yDst, width, height, xSrc, ySrc, + 0, bmp->dib->dsBm.bmHeight, bmp->dib->dsBm.bmBits, + (BITMAPINFO*)&(bmp->dib->dsBmih), 0)) + result = TRUE; + done = TRUE; + } + else FIXME("potential optimization - 8 bpp SetDIBitsToDevice\n"); + } + GDI_ReleaseObj( dcSrc->hBitmap ); + if (done) goto END; + } params.dcDst = dcDst; params.xDst = xDst; @@ -1502,13 +1536,17 @@ BOOL X11DRV_BitBlt( DC *dcDst, INT xDst, INT yDst, params.heightSrc = height; params.rop = rop; - X11DRV_DIB_UpdateDIBSection( dcDst, FALSE ); - X11DRV_DIB_UpdateDIBSection( dcSrc, FALSE ); + X11DRV_CoerceDIBSection( dcDst, DIB_Status_GdiMod, FALSE ); + X11DRV_CoerceDIBSection( dcSrc, DIB_Status_GdiMod, FALSE ); EnterCriticalSection( &X11DRV_CritSection ); result = (BOOL)CALL_LARGE_STACK( BITBLT_DoStretchBlt, ¶ms ); LeaveCriticalSection( &X11DRV_CritSection ); - X11DRV_DIB_UpdateDIBSection( dcDst, TRUE ); + +END: + X11DRV_UnlockDIBSection( dcSrc, FALSE ); + X11DRV_UnlockDIBSection( dcDst, TRUE ); + return result; } @@ -1536,13 +1574,15 @@ BOOL X11DRV_StretchBlt( DC *dcDst, INT xDst, INT yDst, params.heightSrc = heightSrc; params.rop = rop; - X11DRV_DIB_UpdateDIBSection( dcDst, FALSE ); - X11DRV_DIB_UpdateDIBSection( dcSrc, FALSE ); + X11DRV_LockDIBSection( dcDst, DIB_Status_GdiMod, FALSE ); + X11DRV_LockDIBSection( dcSrc, DIB_Status_GdiMod, FALSE ); EnterCriticalSection( &X11DRV_CritSection ); result = (BOOL)CALL_LARGE_STACK( BITBLT_DoStretchBlt, ¶ms ); LeaveCriticalSection( &X11DRV_CritSection ); - X11DRV_DIB_UpdateDIBSection( dcDst, TRUE ); + + X11DRV_UnlockDIBSection( dcSrc, FALSE ); + X11DRV_UnlockDIBSection( dcDst, TRUE ); return result; } diff --git a/graphics/x11drv/dib.c b/graphics/x11drv/dib.c index cfa06b1071c..9a6ba92daba 100644 --- a/graphics/x11drv/dib.c +++ b/graphics/x11drv/dib.c @@ -269,13 +269,10 @@ static void X11DRV_DIB_SetImageBits_1_Line(DWORD dstwidth, int left, int *colors */ static void X11DRV_DIB_SetImageBits_1( int lines, const BYTE *srcbits, DWORD srcwidth, DWORD dstwidth, int left, - int *colors, XImage *bmpImage ) + int *colors, XImage *bmpImage, DWORD linebytes) { int h; - /* 32 bit aligned */ - DWORD linebytes = ((srcwidth + 31) & ~31) / 8; - if (lines > 0) { for (h = lines-1; h >=0; h--) { X11DRV_DIB_SetImageBits_1_Line(dstwidth, left, colors, bmpImage, h, @@ -300,15 +297,12 @@ static void X11DRV_DIB_SetImageBits_1( int lines, const BYTE *srcbits, static void X11DRV_DIB_GetImageBits_1( int lines, BYTE *dstbits, DWORD dstwidth, DWORD srcwidth, RGBQUAD *colors, PALETTEENTRY *srccolors, - XImage *bmpImage ) + XImage *bmpImage, DWORD linebytes ) { DWORD x; int h; BYTE *bits; - /* 32 bit aligned */ - DWORD linebytes = ((dstwidth + 31) & ~31) / 8; - if (lines < 0 ) { lines = -lines; dstbits = dstbits + linebytes * (lines - 1); @@ -537,15 +531,12 @@ static void X11DRV_DIB_GetImageBits_1( int lines, BYTE *dstbits, */ static void X11DRV_DIB_SetImageBits_4( int lines, const BYTE *srcbits, DWORD srcwidth, DWORD dstwidth, int left, - int *colors, XImage *bmpImage ) + int *colors, XImage *bmpImage, DWORD linebytes) { DWORD i, x; int h; const BYTE *bits = srcbits + (left >> 1); - /* 32 bit aligned */ - DWORD linebytes = ((srcwidth+7)&~7)/2; - if(left & 1) { left--; dstwidth++; @@ -587,16 +578,13 @@ static void X11DRV_DIB_SetImageBits_4( int lines, const BYTE *srcbits, static void X11DRV_DIB_GetImageBits_4( int lines, BYTE *dstbits, DWORD srcwidth, DWORD dstwidth, RGBQUAD *colors, PALETTEENTRY *srccolors, - XImage *bmpImage ) + XImage *bmpImage, DWORD linebytes ) { DWORD x; int h; BYTE *bits; LPBYTE srcpixel; - /* 32 bit aligned */ - DWORD linebytes = ((srcwidth+7)&~7)/2; - if (lines < 0 ) { lines = -lines; @@ -903,15 +891,13 @@ static void X11DRV_DIB_SetImageBits_RLE4( int lines, const BYTE *bits, */ static void X11DRV_DIB_SetImageBits_8( int lines, const BYTE *srcbits, DWORD srcwidth, DWORD dstwidth, int left, - const int *colors, XImage *bmpImage ) + const int *colors, XImage *bmpImage, + DWORD linebytes ) { DWORD x; int h, color; const BYTE *bits; - /* align to 32 bit */ - DWORD linebytes = (srcwidth + 3) & ~3; - dstwidth += left; if (lines < 0 ) @@ -976,15 +962,12 @@ static void X11DRV_DIB_SetImageBits_8( int lines, const BYTE *srcbits, static void X11DRV_DIB_GetImageBits_8( int lines, BYTE *dstbits, DWORD srcwidth, DWORD dstwidth, RGBQUAD *colors, PALETTEENTRY *srccolors, - XImage *bmpImage ) + XImage *bmpImage, DWORD linebytes ) { DWORD x; int h; BYTE *bits; - /* align to 32 bit */ - DWORD linebytes = (srcwidth + 3) & ~3; - if (lines < 0 ) { lines = -lines; @@ -1391,14 +1374,11 @@ static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits, static void X11DRV_DIB_SetImageBits_16( int lines, const BYTE *srcbits, DWORD srcwidth, DWORD dstwidth, int left, DC *dc, DWORD rSrc, DWORD gSrc, DWORD bSrc, - XImage *bmpImage ) + XImage *bmpImage, DWORD linebytes ) { DWORD x; int h; - /* align to 32 bit */ - DWORD linebytes = (srcwidth * 2 + 3) & ~3; - if (lines < 0 ) { lines = -lines; @@ -1541,13 +1521,12 @@ static void X11DRV_DIB_GetImageBits_16( int lines, BYTE *dstbits, DWORD dstwidth, DWORD srcwidth, PALETTEENTRY *srccolors, DWORD rDst, DWORD gDst, DWORD bDst, - XImage *bmpImage ) + XImage *bmpImage, DWORD dibpitch ) { DWORD x; int h, rsc, gsc; - /* align to 32 bit */ - DWORD linebytes = (dstwidth * 2 + 3) & ~3; + DWORD linebytes = dibpitch; if (lines < 0 ) { @@ -1760,14 +1739,11 @@ static void X11DRV_DIB_GetImageBits_16( int lines, BYTE *dstbits, */ static void X11DRV_DIB_SetImageBits_24( int lines, const BYTE *srcbits, DWORD srcwidth, DWORD dstwidth, int left, - DC *dc, XImage *bmpImage ) + DC *dc, XImage *bmpImage, DWORD linebytes ) { DWORD x; int h; - /* align to 32 bit */ - DWORD linebytes = (srcwidth * 3 + 3) & ~3; - if (lines < 0 ) { lines = -lines; @@ -1994,14 +1970,12 @@ static void X11DRV_DIB_SetImageBits_24( int lines, const BYTE *srcbits, */ static void X11DRV_DIB_GetImageBits_24( int lines, BYTE *dstbits, DWORD dstwidth, DWORD srcwidth, - PALETTEENTRY *srccolors, XImage *bmpImage ) + PALETTEENTRY *srccolors, + XImage *bmpImage, DWORD linebytes ) { DWORD x, val; int h; - /* align to 32 bit */ - DWORD linebytes = (dstwidth * 3 + 3) & ~3; - if (lines < 0 ) { lines = -lines; @@ -2248,13 +2222,12 @@ static void X11DRV_DIB_GetImageBits_24( int lines, BYTE *dstbits, */ static void X11DRV_DIB_SetImageBits_32( int lines, const BYTE *srcbits, DWORD srcwidth, DWORD dstwidth, int left, - DC *dc, XImage *bmpImage ) + DC *dc, XImage *bmpImage, + DWORD linebytes ) { DWORD x, *ptr; int h; - DWORD linebytes = (srcwidth * 4); - if (lines < 0 ) { lines = -lines; @@ -2294,6 +2267,13 @@ static void X11DRV_DIB_SetImageBits_32( int lines, const BYTE *srcbits, case 24: /* ==== 32 BGR dib to 24 (888) BGR bitmap ==== */ /* we need to check that source mask matches destination */ + if (bmpImage->bits_per_pixel == 32) + { + for (h = lines - 1; h >= 0; h--, srcbits+=linebytes) { + memcpy( bmpImage->data + h * bmpImage->bytes_per_line, srcbits + left*4, dstwidth*4 ); + } + } + else { BYTE *bptr; @@ -2405,15 +2385,14 @@ static void X11DRV_DIB_SetImageBits_32( int lines, const BYTE *srcbits, */ static void X11DRV_DIB_GetImageBits_32( int lines, BYTE *dstbits, DWORD dstwidth, DWORD srcwidth, - PALETTEENTRY *srccolors, XImage *bmpImage ) + PALETTEENTRY *srccolors, + XImage *bmpImage, DWORD linebytes ) { DWORD x; int h; BYTE *bits; - /* align to 32 bit */ - DWORD linebytes = (srcwidth * 4); - DWORD copybytes = linebytes; + DWORD copybytes = srcwidth * 4; if (lines < 0 ) { @@ -2647,7 +2626,7 @@ int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr ) case 1: X11DRV_DIB_SetImageBits_1( descr->lines, descr->bits, descr->infoWidth, descr->width, descr->xSrc, (int *)(descr->colorMap), - bmpImage ); + bmpImage, descr->dibpitch ); break; case 4: if (descr->compression) { @@ -2663,7 +2642,7 @@ int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr ) X11DRV_DIB_SetImageBits_4( descr->lines, descr->bits, descr->infoWidth, descr->width, descr->xSrc, (int*)(descr->colorMap), - bmpImage ); + bmpImage, descr->dibpitch ); break; case 8: if (descr->compression) { @@ -2678,7 +2657,7 @@ int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr ) X11DRV_DIB_SetImageBits_8( descr->lines, descr->bits, descr->infoWidth, descr->width, descr->xSrc, (int *)(descr->colorMap), - bmpImage ); + bmpImage, descr->dibpitch ); break; case 15: case 16: @@ -2686,18 +2665,19 @@ int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr ) descr->infoWidth, descr->width, descr->xSrc, descr->dc, descr->rMask, descr->gMask, descr->bMask, - bmpImage); + bmpImage, descr->dibpitch); break; case 24: X11DRV_DIB_SetImageBits_24( descr->lines, descr->bits, descr->infoWidth, descr->width, - descr->xSrc, descr->dc, bmpImage ); + descr->xSrc, descr->dc, bmpImage, + descr->dibpitch); break; case 32: X11DRV_DIB_SetImageBits_32( descr->lines, descr->bits, descr->infoWidth, descr->width, descr->xSrc, descr->dc, - bmpImage); + bmpImage, descr->dibpitch); break; default: WARN("(%d): Invalid depth\n", descr->infoBpp ); @@ -2743,6 +2723,9 @@ int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr ) return lines; } } + TRACE("XGetSubImage(%p,%ld,%d,%d,%d,%d,%ld,%d,%p,%d,%d)\n", + display, descr->drawable, descr->xSrc, descr->ySrc, descr->width, + lines, AllPlanes, ZPixmap, bmpImage, descr->xDest, descr->yDest); XGetSubImage( display, descr->drawable, descr->xSrc, descr->ySrc, descr->width, lines, AllPlanes, ZPixmap, bmpImage, descr->xDest, descr->yDest ); @@ -2754,7 +2737,7 @@ int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr ) X11DRV_DIB_GetImageBits_1( descr->lines,(LPVOID)descr->bits, descr->infoWidth, descr->width, descr->colorMap, descr->palentry, - bmpImage ); + bmpImage, descr->dibpitch ); break; case 4: @@ -2764,7 +2747,7 @@ int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr ) X11DRV_DIB_GetImageBits_4( descr->lines,(LPVOID)descr->bits, descr->infoWidth, descr->width, descr->colorMap, descr->palentry, - bmpImage ); + bmpImage, descr->dibpitch ); break; case 8: @@ -2774,7 +2757,7 @@ int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr ) X11DRV_DIB_GetImageBits_8( descr->lines, (LPVOID)descr->bits, descr->infoWidth, descr->width, descr->colorMap, descr->palentry, - bmpImage ); + bmpImage, descr->dibpitch ); break; case 15: case 16: @@ -2782,19 +2765,19 @@ int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr ) descr->infoWidth,descr->width, descr->palentry, descr->rMask, descr->gMask, descr->bMask, - bmpImage ); + bmpImage, descr->dibpitch ); break; case 24: X11DRV_DIB_GetImageBits_24( descr->lines, (LPVOID)descr->bits, descr->infoWidth,descr->width, - descr->palentry, bmpImage ); + descr->palentry, bmpImage, descr->dibpitch); break; case 32: X11DRV_DIB_GetImageBits_32( descr->lines, (LPVOID)descr->bits, descr->infoWidth, descr->width, - descr->palentry, bmpImage ); + descr->palentry, bmpImage, descr->dibpitch); break; default: @@ -2889,6 +2872,7 @@ INT X11DRV_SetDIBitsToDevice( DC *dc, INT xDest, INT yDest, DWORD cx, descr.width = cx; descr.height = cy; descr.useShm = FALSE; + descr.dibpitch = ((width * descr.infoBpp + 31) &~31) / 8; EnterCriticalSection( &X11DRV_CritSection ); result = CALL_LARGE_STACK( X11DRV_DIB_SetImageBits, &descr ); @@ -2977,6 +2961,7 @@ INT X11DRV_DIB_SetDIBits( descr.width = bmp->bitmap.bmWidth; descr.height = lines; descr.useShm = FALSE; + descr.dibpitch = ((descr.infoWidth * descr.infoBpp + 31) &~31) / 8; EnterCriticalSection( &X11DRV_CritSection ); result = CALL_LARGE_STACK( X11DRV_DIB_SetImageBits, &descr ); @@ -2998,6 +2983,7 @@ INT X11DRV_DIB_GetDIBits( X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib; X11DRV_DIB_IMAGEBITS_DESCR descr; PALETTEOBJ * palette; + int height; TRACE("%u scanlines of (%i,%i) -> (%i,%i) starting from %u\n", lines, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight, @@ -3007,7 +2993,11 @@ INT X11DRV_DIB_GetDIBits( if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->hPalette, PALETTE_MAGIC ))) return 0; - if( lines > info->bmiHeader.biHeight ) lines = info->bmiHeader.biHeight; + if( lines > bmp->bitmap.bmHeight ) lines = bmp->bitmap.bmHeight; + + height = info->bmiHeader.biHeight; + if (height < 0) height = -height; + if( lines > height ) lines = height; /* Top-down images have a negative biHeight, the scanlines of theses images * were inverted in X11DRV_DIB_GetImageBits_xx * To prevent this we simply change the sign of lines @@ -3080,11 +3070,12 @@ INT X11DRV_DIB_GetDIBits( descr.ySrc = startscan; } #ifdef HAVE_LIBXXSHM - if (dib) - descr.useShm = (dib->shminfo.shmid != -1); - else + descr.useShm = dib ? (dib->shminfo.shmid != -1) : FALSE; +#else + descr.useShm = FALSE; #endif - descr.useShm = FALSE; + descr.dibpitch = dib ? (dib->dibSection.dsBm.bmWidthBytes) + : (((descr.infoWidth * descr.infoBpp + 31) &~31) / 8); EnterCriticalSection( &X11DRV_CritSection ); @@ -3182,6 +3173,7 @@ static void X11DRV_DIB_DoUpdateDIBSection(BITMAPOBJ *bmp, BOOL toDIB) #else descr.useShm = FALSE; #endif + descr.dibpitch = dib->dibSection.dsBm.bmWidthBytes; if (toDIB) { @@ -3204,137 +3196,355 @@ static void X11DRV_DIB_DoUpdateDIBSection(BITMAPOBJ *bmp, BOOL toDIB) */ static BOOL X11DRV_DIB_FaultHandler( LPVOID res, LPCVOID addr ) { - BOOL handled = FALSE; BITMAPOBJ *bmp; + INT state; bmp = (BITMAPOBJ *)GDI_GetObjPtr( (HBITMAP)res, BITMAP_MAGIC ); if (!bmp) return FALSE; - - if (bmp->dib) - switch (((X11DRV_DIBSECTION *) bmp->dib)->status) - { - case X11DRV_DIB_GdiMod: - TRACE("called in status DIB_GdiMod\n" ); - X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE ); - X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE ); - X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY ); - ((X11DRV_DIBSECTION *) bmp->dib)->status = X11DRV_DIB_InSync; - handled = TRUE; - break; - - case X11DRV_DIB_InSync: - TRACE("called in status X11DRV_DIB_InSync\n" ); - X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE ); - ((X11DRV_DIBSECTION *) bmp->dib)->status = X11DRV_DIB_AppMod; - handled = TRUE; - break; - - case X11DRV_DIB_AppMod: - FIXME("called in status X11DRV_DIB_AppMod: this can't happen!\n" ); - break; - - case X11DRV_DIB_NoHandler: - FIXME("called in status DIB_NoHandler: this can't happen!\n" ); - break; - } - + + state = X11DRV_DIB_Lock(bmp, 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(bmp, DIB_Status_InSync, FALSE); + } else { + /* hm, apparently the app must have write access */ + X11DRV_DIB_Coerce(bmp, DIB_Status_AppMod, FALSE); + } + X11DRV_DIB_Unlock(bmp, TRUE); + GDI_ReleaseObj( (HBITMAP)res ); - return handled; + return TRUE; } /*********************************************************************** - * X11DRV_DIB_CmnUpdateDIBSection + * X11DRV_DIB_Coerce */ -static void X11DRV_DIB_CmnUpdateDIBSection(BITMAPOBJ *bmp, BOOL toDIB) +INT X11DRV_DIB_Coerce(BITMAPOBJ *bmp, INT req, BOOL lossy) { - if (!bmp) return; - if (!bmp->dib) return; - - if (!toDIB) - { - /* Prepare for access to the DIB by GDI functions */ - - switch (((X11DRV_DIBSECTION *) bmp->dib)->status) - { + X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib; + INT ret = DIB_Status_None; + + if (dib) { + EnterCriticalSection(&(dib->lock)); + ret = dib->status; + switch (req) { + case DIB_Status_GdiMod: + /* GDI access - request to draw on pixmap */ + switch (dib->status) + { default: - case X11DRV_DIB_NoHandler: + case DIB_Status_None: + dib->p_status = DIB_Status_GdiMod; X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE ); break; - - case X11DRV_DIB_GdiMod: - TRACE("fromDIB called in status X11DRV_DIB_GdiMod\n" ); - /* nothing to do */ + + case DIB_Status_GdiMod: + TRACE("GdiMod requested in status GdiMod\n" ); break; - - case X11DRV_DIB_InSync: - TRACE("fromDIB called in status X11DRV_DIB_InSync\n" ); - /* nothing to do */ - break; - - case X11DRV_DIB_AppMod: - TRACE("fromDIB called in status X11DRV_DIB_AppMod\n" ); - X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE ); - X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY ); - ((X11DRV_DIBSECTION *) bmp->dib)->status = X11DRV_DIB_InSync; - break; - } - } - else - { - /* Acknowledge write access to the DIB by GDI functions */ - - switch (((X11DRV_DIBSECTION *) bmp->dib)->status) - { - default: - case X11DRV_DIB_NoHandler: - X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE ); - break; - - case X11DRV_DIB_GdiMod: - TRACE(" toDIB called in status X11DRV_DIB_GdiMod\n" ); - /* nothing to do */ - break; - - case X11DRV_DIB_InSync: - TRACE(" toDIB called in status X11DRV_DIB_InSync\n" ); + + case DIB_Status_InSync: + TRACE("GdiMod requested in status InSync\n" ); X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS ); - ((X11DRV_DIBSECTION *) bmp->dib)->status = X11DRV_DIB_GdiMod; + dib->status = DIB_Status_GdiMod; + dib->p_status = DIB_Status_InSync; break; - - case X11DRV_DIB_AppMod: - FIXME(" toDIB called in status X11DRV_DIB_AppMod: " - "this can't happen!\n" ); + + case DIB_Status_AuxMod: + TRACE("GdiMod requested in status AuxMod\n" ); + if (lossy) dib->status = DIB_Status_GdiMod; + else (*dib->copy_aux)(dib->aux_ctx, DIB_Status_GdiMod); + dib->p_status = DIB_Status_AuxMod; + if (dib->status != DIB_Status_AppMod) { + X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS ); + break; + } + /* fall through if copy_aux() had to change to AppMod state */ + + case DIB_Status_AppMod: + TRACE("GdiMod requested in status AppMod\n" ); + if (!lossy) { + /* make it readonly to avoid app changing data while we copy */ + X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY ); + X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE ); + } + X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS ); + dib->p_status = DIB_Status_AppMod; + dib->status = DIB_Status_GdiMod; break; - } + } + break; + + case DIB_Status_InSync: + /* App access - request access to read DIB surface */ + /* (typically called from signal handler) */ + switch (dib->status) + { + default: + case DIB_Status_None: + /* shouldn't happen from signal handler */ + break; + + case DIB_Status_AuxMod: + TRACE("InSync requested in status AuxMod\n" ); + if (lossy) dib->status = DIB_Status_InSync; + else { + X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE ); + (*dib->copy_aux)(dib->aux_ctx, DIB_Status_InSync); + } + if (dib->status != DIB_Status_GdiMod) { + X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY ); + break; + } + /* fall through if copy_aux() had to change to GdiMod state */ + + case DIB_Status_GdiMod: + TRACE("InSync requested in status GdiMod\n" ); + if (!lossy) { + X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE ); + X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE ); + } + X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY ); + dib->status = DIB_Status_InSync; + break; + + case DIB_Status_InSync: + TRACE("InSync requested in status InSync\n" ); + /* shouldn't happen from signal handler */ + break; + + case DIB_Status_AppMod: + TRACE("InSync requested in status AppMod\n" ); + /* no reason to do anything here, and this + * shouldn't happen from signal handler */ + break; + } + break; + + case DIB_Status_AppMod: + /* App access - request access to write DIB surface */ + /* (typically called from signal handler) */ + switch (dib->status) + { + default: + case DIB_Status_None: + /* shouldn't happen from signal handler */ + break; + + case DIB_Status_AuxMod: + TRACE("AppMod requested in status AuxMod\n" ); + if (lossy) dib->status = DIB_Status_AppMod; + else { + X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE ); + (*dib->copy_aux)(dib->aux_ctx, DIB_Status_AppMod); + } + if (dib->status != DIB_Status_GdiMod) + break; + /* fall through if copy_aux() had to change to GdiMod state */ + + case DIB_Status_GdiMod: + TRACE("AppMod requested in status GdiMod\n" ); + X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE ); + if (!lossy) X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE ); + /* fall through */ + + case DIB_Status_InSync: + TRACE("AppMod requested in status InSync\n" ); + X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE ); + dib->status = DIB_Status_AppMod; + break; + + case DIB_Status_AppMod: + TRACE("AppMod requested in status AppMod\n" ); + /* shouldn't happen from signal handler */ + break; + } + break; + + case DIB_Status_AuxMod: + if (dib->status == DIB_Status_None) { + dib->p_status = req; + } else { + if (dib->status != DIB_Status_AuxMod) + dib->p_status = dib->status; + dib->status = DIB_Status_AuxMod; + } + break; + /* it is up to the caller to do the copy/conversion, probably + * using the return value to decide where to copy from */ } + LeaveCriticalSection(&(dib->lock)); + } + return ret; } /*********************************************************************** - * X11DRV_DIB_UpdateDIBSection2 + * X11DRV_DIB_Lock */ -void X11DRV_DIB_UpdateDIBSection2(HBITMAP hbmp, BOOL toDIB) +INT X11DRV_DIB_Lock(BITMAPOBJ *bmp, INT req, BOOL lossy) +{ + X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib; + INT ret = DIB_Status_None; + + if (dib) { + EnterCriticalSection(&(dib->lock)); + ret = dib->status; + if (req != DIB_Status_None) + X11DRV_DIB_Coerce(bmp, req, lossy); + } + return ret; +} + +/*********************************************************************** + * X11DRV_DIB_Unlock + */ +void X11DRV_DIB_Unlock(BITMAPOBJ *bmp, BOOL commit) +{ + X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib; + + if (dib) { + switch (dib->status) + { + default: + case DIB_Status_None: + /* in case anyone is wondering, this is the "signal handler doesn't + * work" case, where we always have to be ready for app access */ + if (commit) { + switch (dib->p_status) + { + case DIB_Status_AuxMod: + TRACE("Unlocking and syncing from AuxMod\n" ); + (*dib->copy_aux)(dib->aux_ctx, DIB_Status_AppMod); + if (dib->status != DIB_Status_None) { + dib->p_status = dib->status; + dib->status = DIB_Status_None; + } + if (dib->p_status != DIB_Status_GdiMod) + break; + /* fall through if copy_aux() had to change to GdiMod state */ + + case DIB_Status_GdiMod: + TRACE("Unlocking and syncing from GdiMod\n" ); + X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE ); + break; + + default: + TRACE("Unlocking without needing to sync\n" ); + break; + } + } + else TRACE("Unlocking with no changes\n"); + dib->p_status = DIB_Status_None; + break; + + case DIB_Status_GdiMod: + TRACE("Unlocking in status GdiMod\n" ); + /* DIB was protected in Coerce */ + if (!commit) { + /* no commit, revert to InSync if applicable */ + if ((dib->p_status == DIB_Status_InSync) || + (dib->p_status == DIB_Status_AppMod)) { + X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY ); + dib->status = DIB_Status_InSync; + } + } + break; + + case DIB_Status_InSync: + TRACE("Unlocking in status InSync\n" ); + /* DIB was already protected in Coerce */ + break; + + case DIB_Status_AppMod: + TRACE("Unlocking in status AppMod\n" ); + /* DIB was already protected in Coerce */ + /* this case is ordinary only called from the signal handler, + * so we don't bother to check for !commit */ + break; + + case DIB_Status_AuxMod: + TRACE("Unlocking in status AuxMod\n" ); + if (commit) { + /* DIB may need protection now */ + if ((dib->p_status == DIB_Status_InSync) || + (dib->p_status == DIB_Status_AppMod)) + X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS ); + } else { + /* no commit, revert to previous state */ + if (dib->p_status != DIB_Status_None) + dib->status = dib->p_status; + /* no protections changed */ + } + dib->p_status = DIB_Status_None; + break; + } + LeaveCriticalSection(&(dib->lock)); + } +} + +/*********************************************************************** + * X11DRV_CoerceDIBSection + */ +INT X11DRV_CoerceDIBSection(DC *dc, INT req, BOOL lossy) { BITMAPOBJ *bmp; - - bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbmp, BITMAP_MAGIC ); - if (!bmp) return; + INT ret; - X11DRV_DIB_CmnUpdateDIBSection(bmp, toDIB); + if (!dc) return DIB_Status_None; + if (!(dc->flags & DC_MEMORY)) return DIB_Status_None; - GDI_ReleaseObj(hbmp); + bmp = (BITMAPOBJ *)GDI_GetObjPtr( dc->hBitmap, BITMAP_MAGIC ); + ret = X11DRV_DIB_Coerce(bmp, req, lossy); + GDI_ReleaseObj( dc->hBitmap ); + return ret; } /*********************************************************************** - * X11DRV_DIB_UpdateDIBSection + * X11DRV_LockDIBSection2 */ -void X11DRV_DIB_UpdateDIBSection(DC *dc, BOOL toDIB) +INT X11DRV_LockDIBSection2(HBITMAP hBmp, INT req, BOOL lossy) +{ + BITMAPOBJ *bmp; + INT ret; + + bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC ); + ret = X11DRV_DIB_Lock(bmp, req, lossy); + GDI_ReleaseObj( hBmp ); + return ret; +} + +/*********************************************************************** + * X11DRV_UnlockDIBSection2 + */ +void X11DRV_UnlockDIBSection2(HBITMAP hBmp, BOOL commit) +{ + BITMAPOBJ *bmp; + + bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC ); + X11DRV_DIB_Unlock(bmp, commit); + GDI_ReleaseObj( hBmp ); +} + +/*********************************************************************** + * X11DRV_LockDIBSection + */ +INT X11DRV_LockDIBSection(DC *dc, INT req, BOOL lossy) +{ + if (!dc) return DIB_Status_None; + if (!(dc->flags & DC_MEMORY)) return DIB_Status_None; + + return X11DRV_LockDIBSection2( dc->hBitmap, req, lossy ); +} + +/*********************************************************************** + * X11DRV_UnlockDIBSection + */ +void X11DRV_UnlockDIBSection(DC *dc, BOOL commit) { - /* Ensure this is a Compatible DC that has a DIB section selected */ - if (!dc) return; if (!(dc->flags & DC_MEMORY)) return; - - X11DRV_DIB_UpdateDIBSection2(dc->hBitmap, toDIB); + + X11DRV_UnlockDIBSection2( dc->hBitmap, commit ); } /*********************************************************************** @@ -3536,7 +3746,7 @@ HBITMAP X11DRV_DIB_CreateDIBSection( dib->dibSection.dshSection = section; dib->dibSection.dsOffset = offset; - dib->status = X11DRV_DIB_NoHandler; + dib->status = DIB_Status_None; dib->selector = 0; dib->nColorMap = nColorMap; @@ -3597,21 +3807,21 @@ HBITMAP X11DRV_DIB_CreateDIBSection( if (bmp) { GDI_ReleaseObj(res); bmp = NULL; } if (res) { DeleteObject(res); res = 0; } } - - /* Install fault handler, if possible */ - if (bm.bmBits) + else if (bm.bmBits) { + /* Install fault handler, if possible */ + InitializeCriticalSection(&(dib->lock)); if (VIRTUAL_SetFaultHandler(bm.bmBits, X11DRV_DIB_FaultHandler, (LPVOID)res)) { if (section || offset) { X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE ); - if (dib) dib->status = X11DRV_DIB_AppMod; + if (dib) dib->status = DIB_Status_AppMod; } else { X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY ); - if (dib) dib->status = X11DRV_DIB_InSync; + if (dib) dib->status = DIB_Status_InSync; } } } @@ -3648,6 +3858,7 @@ void X11DRV_DIB_DeleteDIBSection(BITMAPOBJ *bmp) HeapFree(GetProcessHeap(), 0, dib->colorMap); if (dib->selector) SELECTOR_FreeBlock( dib->selector ); + DeleteCriticalSection(&(dib->lock)); } /*********************************************************************** diff --git a/graphics/x11drv/graphics.c b/graphics/x11drv/graphics.c index 57726b0fd95..f2b57eecf34 100644 --- a/graphics/x11drv/graphics.c +++ b/graphics/x11drv/graphics.c @@ -295,14 +295,14 @@ X11DRV_LineTo( DC *dc, INT x, INT y ) if (X11DRV_SetupGCForPen( dc )) { /* Update the pixmap from the DIB section */ - X11DRV_DIB_UpdateDIBSection(dc, FALSE); + X11DRV_LockDIBSection(dc, DIB_Status_GdiMod, FALSE); TSXDrawLine(display, physDev->drawable, physDev->gc, dc->DCOrgX + XLPTODP( dc, dc->CursPosX ), dc->DCOrgY + YLPTODP( dc, dc->CursPosY ), dc->DCOrgX + XLPTODP( dc, x ), dc->DCOrgY + YLPTODP( dc, y ) ); /* Update the DIBSection from the pixmap */ - X11DRV_DIB_UpdateDIBSection(dc, TRUE); + X11DRV_UnlockDIBSection(dc, TRUE); } return TRUE; } @@ -386,7 +386,7 @@ X11DRV_DrawArc( DC *dc, INT left, INT top, INT right, if (idiff_angle <= 0) idiff_angle += 360 * 64; /* Update the pixmap from the DIB section */ - X11DRV_DIB_UpdateDIBSection(dc, FALSE); + X11DRV_LockDIBSection(dc, DIB_Status_GdiMod, FALSE); /* Fill arc with brush if Chord() or Pie() */ @@ -465,7 +465,7 @@ X11DRV_DrawArc( DC *dc, INT left, INT top, INT right, } /* Update the DIBSection of the pixmap */ - if (update) X11DRV_DIB_UpdateDIBSection(dc, TRUE); + X11DRV_UnlockDIBSection(dc, update); physDev->pen.width = oldwidth; physDev->pen.endcap = oldendcap; @@ -544,7 +544,7 @@ X11DRV_Ellipse( DC *dc, INT left, INT top, INT right, INT bottom ) physDev->pen.width = width; /* Update the pixmap from the DIB section */ - X11DRV_DIB_UpdateDIBSection(dc, FALSE); + X11DRV_LockDIBSection(dc, DIB_Status_GdiMod, FALSE); if (X11DRV_SetupGCForBrush( dc )) { @@ -562,7 +562,7 @@ X11DRV_Ellipse( DC *dc, INT left, INT top, INT right, INT bottom ) } /* Update the DIBSection from the pixmap */ - if (update) X11DRV_DIB_UpdateDIBSection(dc, TRUE); + X11DRV_UnlockDIBSection(dc, update); physDev->pen.width = oldwidth; return TRUE; @@ -612,7 +612,7 @@ X11DRV_Rectangle(DC *dc, INT left, INT top, INT right, INT bottom) physDev->pen.linejoin = PS_JOIN_MITER; /* Update the pixmap from the DIB section */ - X11DRV_DIB_UpdateDIBSection(dc, FALSE); + X11DRV_LockDIBSection(dc, DIB_Status_GdiMod, FALSE); if ((right > left + width) && (bottom > top + width)) if (X11DRV_SetupGCForBrush( dc )) @@ -632,7 +632,7 @@ X11DRV_Rectangle(DC *dc, INT left, INT top, INT right, INT bottom) } /* Update the DIBSection from the pixmap */ - if (update) X11DRV_DIB_UpdateDIBSection(dc, TRUE); + X11DRV_UnlockDIBSection(dc, update); physDev->pen.width = oldwidth; physDev->pen.linejoin = oldjoinstyle; @@ -690,7 +690,7 @@ X11DRV_RoundRect( DC *dc, INT left, INT top, INT right, physDev->pen.endcap = PS_ENDCAP_SQUARE; /* Update the pixmap from the DIB section */ - X11DRV_DIB_UpdateDIBSection(dc, FALSE); + X11DRV_LockDIBSection(dc, DIB_Status_GdiMod, FALSE); if (X11DRV_SetupGCForBrush( dc )) { @@ -834,7 +834,7 @@ X11DRV_RoundRect( DC *dc, INT left, INT top, INT right, } /* Update the DIBSection from the pixmap */ - if (update) X11DRV_DIB_UpdateDIBSection(dc, TRUE); + X11DRV_UnlockDIBSection(dc, update); physDev->pen.width = oldwidth; physDev->pen.endcap = oldendcap; @@ -939,14 +939,14 @@ X11DRV_PaintRgn( DC *dc, HRGN hrgn ) if (X11DRV_SetupGCForBrush( dc )) { /* Update the pixmap from the DIB section */ - X11DRV_DIB_UpdateDIBSection(dc, FALSE); + X11DRV_LockDIBSection(dc, DIB_Status_GdiMod, FALSE); TSXFillRectangle( display, physDev->drawable, physDev->gc, box.left, box.top, box.right-box.left, box.bottom-box.top ); /* Update the DIBSection from the pixmap */ - X11DRV_DIB_UpdateDIBSection(dc, TRUE); + X11DRV_UnlockDIBSection(dc, TRUE); } /* Restore the visible region */ @@ -982,13 +982,13 @@ X11DRV_Polyline( DC *dc, const POINT* pt, INT count ) if (X11DRV_SetupGCForPen ( dc )) { /* Update the pixmap from the DIB section */ - X11DRV_DIB_UpdateDIBSection(dc, FALSE); + X11DRV_LockDIBSection(dc, DIB_Status_GdiMod, FALSE); TSXDrawLines( display, physDev->drawable, physDev->gc, points, count, CoordModeOrigin ); /* Update the DIBSection from the pixmap */ - X11DRV_DIB_UpdateDIBSection(dc, TRUE); + X11DRV_UnlockDIBSection(dc, TRUE); } HeapFree( GetProcessHeap(), 0, points ); @@ -1021,7 +1021,7 @@ X11DRV_Polygon( DC *dc, const POINT* pt, INT count ) points[count] = points[0]; /* Update the pixmap from the DIB section */ - X11DRV_DIB_UpdateDIBSection(dc, FALSE); + X11DRV_LockDIBSection(dc, DIB_Status_GdiMod, FALSE); if (X11DRV_SetupGCForBrush( dc )) { @@ -1037,7 +1037,7 @@ X11DRV_Polygon( DC *dc, const POINT* pt, INT count ) } /* Update the DIBSection from the pixmap */ - if (update) X11DRV_DIB_UpdateDIBSection(dc, TRUE); + X11DRV_UnlockDIBSection(dc, update); HeapFree( GetProcessHeap(), 0, points ); return TRUE; @@ -1068,7 +1068,7 @@ X11DRV_PolyPolygon( DC *dc, const POINT* pt, const INT* counts, UINT polygons) XPoint *points; /* Update the pixmap from the DIB section */ - X11DRV_DIB_UpdateDIBSection(dc, FALSE); + X11DRV_LockDIBSection(dc, DIB_Status_GdiMod, FALSE); for (i = 0; i < polygons; i++) if (counts[i] > max) max = counts[i]; if (!(points = HeapAlloc( GetProcessHeap(), 0, sizeof(XPoint) * (max+1) ))) @@ -1090,7 +1090,7 @@ X11DRV_PolyPolygon( DC *dc, const POINT* pt, const INT* counts, UINT polygons) } /* Update the DIBSection of the dc's bitmap */ - X11DRV_DIB_UpdateDIBSection(dc, TRUE); + X11DRV_UnlockDIBSection(dc, TRUE); HeapFree( GetProcessHeap(), 0, points ); } @@ -1112,7 +1112,7 @@ X11DRV_PolyPolyline( DC *dc, const POINT* pt, const DWORD* counts, DWORD polylin XPoint *points; /* Update the pixmap from the DIB section */ - X11DRV_DIB_UpdateDIBSection(dc, FALSE); + X11DRV_LockDIBSection(dc, DIB_Status_GdiMod, FALSE); for (i = 0; i < polylines; i++) if (counts[i] > max) max = counts[i]; if (!(points = HeapAlloc( GetProcessHeap(), 0, sizeof(XPoint) * max ))) @@ -1133,7 +1133,7 @@ X11DRV_PolyPolyline( DC *dc, const POINT* pt, const DWORD* counts, DWORD polylin } /* Update the DIBSection of the dc's bitmap */ - X11DRV_DIB_UpdateDIBSection(dc, TRUE); + X11DRV_UnlockDIBSection(dc, TRUE); HeapFree( GetProcessHeap(), 0, points ); } @@ -1247,7 +1247,7 @@ static BOOL X11DRV_DoFloodFill( const struct FloodFill_params *params ) if (X11DRV_SetupGCForBrush( dc )) { /* Update the pixmap from the DIB section */ - X11DRV_DIB_UpdateDIBSection(dc, FALSE); + X11DRV_LockDIBSection(dc, DIB_Status_GdiMod, FALSE); /* ROP mode is always GXcopy for flood-fill */ XSetFunction( display, physDev->gc, GXcopy ); @@ -1260,7 +1260,7 @@ static BOOL X11DRV_DoFloodFill( const struct FloodFill_params *params ) params->fillType ); /* Update the DIBSection of the dc's bitmap */ - X11DRV_DIB_UpdateDIBSection(dc, TRUE); + X11DRV_UnlockDIBSection(dc, TRUE); } XDestroyImage( image ); diff --git a/graphics/x11drv/init.c b/graphics/x11drv/init.c index d1f32b2ddb6..f966af3bb5e 100644 --- a/graphics/x11drv/init.c +++ b/graphics/x11drv/init.c @@ -133,7 +133,9 @@ BITMAP_DRIVER X11DRV_BITMAP_Driver = X11DRV_DIB_GetDIBits, X11DRV_DIB_DeleteDIBSection, X11DRV_DIB_SetDIBColorTable, - X11DRV_DIB_GetDIBColorTable + X11DRV_DIB_GetDIBColorTable, + X11DRV_DIB_Lock, + X11DRV_DIB_Unlock }; PALETTE_DRIVER X11DRV_PALETTE_Driver = diff --git a/graphics/x11drv/text.c b/graphics/x11drv/text.c index 52356351e33..98b01155d2a 100644 --- a/graphics/x11drv/text.c +++ b/graphics/x11drv/text.c @@ -18,6 +18,7 @@ #include "gdi.h" #include "heap.h" #include "x11font.h" +#include "bitmap.h" #include "debugtools.h" DEFAULT_DEBUG_CHANNEL(text); @@ -112,7 +113,7 @@ X11DRV_ExtTextOut( DC *dc, INT x, INT y, UINT flags, if (flags & ETO_OPAQUE) { - X11DRV_DIB_UpdateDIBSection( dc, FALSE ); + X11DRV_LockDIBSection( dc, DIB_Status_GdiMod, FALSE ); dibUpdateFlag = TRUE; TSXSetForeground( display, physDev->gc, physDev->backgroundPixel ); TSXFillRectangle( display, physDev->drawable, physDev->gc, @@ -196,7 +197,7 @@ X11DRV_ExtTextOut( DC *dc, INT x, INT y, UINT flags, if (!dibUpdateFlag) { - X11DRV_DIB_UpdateDIBSection( dc, FALSE ); + X11DRV_LockDIBSection( dc, DIB_Status_GdiMod, FALSE ); dibUpdateFlag = TRUE; } @@ -384,7 +385,7 @@ FAIL: result = FALSE; END: - if (dibUpdateFlag) X11DRV_DIB_UpdateDIBSection( dc, TRUE ); + if (dibUpdateFlag) X11DRV_UnlockDIBSection( dc, TRUE ); return result; } diff --git a/include/bitmap.h b/include/bitmap.h index b028bbd0699..6aa311bfff1 100644 --- a/include/bitmap.h +++ b/include/bitmap.h @@ -18,6 +18,9 @@ struct tagGDI_BITMAP_DRIVER; #define DDB_COPY 4 #define DDB_SETWITHFILLER 8 +/* DIB Section sync state */ +enum { DIB_Status_None, DIB_Status_InSync, DIB_Status_GdiMod, DIB_Status_AppMod, DIB_Status_AuxMod }; + /* GDI logical bitmap object */ typedef struct tagBITMAPOBJ { @@ -37,6 +40,8 @@ typedef struct tagBITMAP_DRIVER VOID (*pDeleteDIBSection)(struct tagBITMAPOBJ *); UINT (*pSetDIBColorTable)(struct tagBITMAPOBJ *,struct tagDC *,UINT,UINT,const RGBQUAD *); UINT (*pGetDIBColorTable)(struct tagBITMAPOBJ *,struct tagDC *,UINT,UINT,RGBQUAD *); + INT (*pLockDIB)(struct tagBITMAPOBJ *,INT,BOOL); + VOID (*pUnlockDIB)(struct tagBITMAPOBJ *,BOOL); } BITMAP_DRIVER; extern BITMAP_DRIVER *BITMAP_Driver; diff --git a/include/x11drv.h b/include/x11drv.h index fd0c5eef6f3..bb8421decfd 100644 --- a/include/x11drv.h +++ b/include/x11drv.h @@ -214,7 +214,7 @@ typedef struct DIBSECTION dibSection; /* Mapping status */ - enum { X11DRV_DIB_NoHandler, X11DRV_DIB_InSync, X11DRV_DIB_AppMod, X11DRV_DIB_GdiMod } status; + int status, p_status; /* Color map info */ int nColorMap; @@ -231,6 +231,13 @@ typedef struct XShmSegmentInfo shminfo; #endif + /* Aux buffer access function */ + void (*copy_aux)(void*ctx, int req); + void *aux_ctx; + + /* GDI access lock */ + CRITICAL_SECTION lock; + } X11DRV_DIBSECTION; /* This structure holds the arguments for DIB_SetImageBits() */ @@ -259,14 +266,18 @@ typedef struct DWORD gMask; DWORD bMask; BOOL useShm; + int dibpitch; } X11DRV_DIB_IMAGEBITS_DESCR; extern int *X11DRV_DIB_BuildColorMap( struct tagDC *dc, WORD coloruse, WORD depth, const BITMAPINFO *info, int *nColors ); -extern void X11DRV_DIB_UpdateDIBSection(struct tagDC *dc, BOOL toDIB); -extern void X11DRV_DIB_UpdateDIBSection2(HBITMAP hbmp, BOOL toDIB); +extern INT X11DRV_CoerceDIBSection(struct tagDC *dc,INT,BOOL); +extern INT X11DRV_LockDIBSection(struct tagDC *dc,INT,BOOL); +extern void X11DRV_UnlockDIBSection(struct tagDC *dc,BOOL); +extern INT X11DRV_LockDIBSection2(HBITMAP bmp,INT,BOOL); +extern void X11DRV_UnlockDIBSection2(HBITMAP bmp,BOOL); extern HBITMAP X11DRV_DIB_CreateDIBSection(struct tagDC *dc, BITMAPINFO *bmi, UINT usage, LPVOID *bits, HANDLE section, DWORD offset, DWORD ovr_pitch); @@ -284,6 +295,9 @@ extern INT X11DRV_DIB_GetDIBits(struct tagBITMAPOBJ *bmp, struct tagDC *dc, UINT extern void X11DRV_DIB_DeleteDIBSection(struct tagBITMAPOBJ *bmp); extern UINT X11DRV_DIB_SetDIBColorTable(struct tagBITMAPOBJ *,struct tagDC*,UINT,UINT,const RGBQUAD *); extern UINT X11DRV_DIB_GetDIBColorTable(struct tagBITMAPOBJ *,struct tagDC*,UINT,UINT,RGBQUAD *); +extern INT X11DRV_DIB_Coerce(struct tagBITMAPOBJ *,INT,BOOL); +extern INT X11DRV_DIB_Lock(struct tagBITMAPOBJ *,INT,BOOL); +extern void X11DRV_DIB_Unlock(struct tagBITMAPOBJ *,BOOL); /************************************************************************** * X11 GDI driver