From 809af590a191459c232bd00e0f0238747fc13f58 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Thu, 27 Sep 2007 18:02:26 +0200 Subject: [PATCH] winex11.drv: Don't call GDI functions while holding the X11 lock. --- dlls/winex11.drv/bitblt.c | 48 +++++++++++++++++++++++++++++-------- dlls/winex11.drv/dib.c | 15 +++++++++--- dlls/winex11.drv/graphics.c | 24 ++++++++++--------- dlls/winex11.drv/init.c | 4 +++- dlls/winex11.drv/opengl.c | 10 +++++--- dlls/winex11.drv/xrender.c | 4 +++- 6 files changed, 76 insertions(+), 29 deletions(-) diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c index 996319e75a7..93011bc2748 100644 --- a/dlls/winex11.drv/bitblt.c +++ b/dlls/winex11.drv/bitblt.c @@ -717,6 +717,7 @@ static void BITBLT_StretchImage( XImage *srcImage, XImage *dstImage, xoff = ((widthDst << 16) - (xinc * widthSrc)) / 2; } + wine_tsx11_lock(); if (vstretch) { yinc = ((int)heightSrc << 16) / heightDst; @@ -836,6 +837,7 @@ static void BITBLT_StretchImage( XImage *srcImage, XImage *dstImage, widthDst*sizeof(int) ); } } + wine_tsx11_unlock(); HeapFree( GetProcessHeap(), 0, rowSrc ); } @@ -873,6 +875,7 @@ static int BITBLT_GetSrcAreaStretch( X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE rectDst.bottom -= yDst; get_colors(physDevDst, physDevSrc, &fg, &bg); + wine_tsx11_lock(); /* FIXME: avoid BadMatch errors */ imageSrc = XGetImage( gdi_display, physDevSrc->drawable, physDevSrc->dc_rect.left + visRectSrc->left, @@ -880,6 +883,8 @@ static int BITBLT_GetSrcAreaStretch( X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE visRectSrc->right - visRectSrc->left, visRectSrc->bottom - visRectSrc->top, AllPlanes, ZPixmap ); + wine_tsx11_unlock(); + imageDst = X11DRV_DIB_CreateXImage( rectDst.right - rectDst.left, rectDst.bottom - rectDst.top, physDevDst->depth ); BITBLT_StretchImage( imageSrc, imageDst, widthSrc, heightSrc, @@ -887,10 +892,12 @@ static int BITBLT_GetSrcAreaStretch( X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE fg, physDevDst->depth != 1 ? bg : physDevSrc->backgroundPixel, GetStretchBltMode(physDevDst->hdc) ); + wine_tsx11_lock(); XPutImage( gdi_display, pixmap, gc, imageDst, 0, 0, 0, 0, rectDst.right - rectDst.left, rectDst.bottom - rectDst.top ); XDestroyImage( imageSrc ); XDestroyImage( imageDst ); + wine_tsx11_unlock(); return 0; /* no exposure events generated */ } @@ -910,9 +917,11 @@ static int BITBLT_GetSrcArea( X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDe INT width = visRectSrc->right - visRectSrc->left; INT height = visRectSrc->bottom - visRectSrc->top; int fg, bg; + BOOL memdc = (GetObjectType(physDevSrc->hdc) == OBJ_MEMDC); if (physDevSrc->depth == physDevDst->depth) { + wine_tsx11_lock(); if (!X11DRV_PALETTE_XPixelToPalette || (physDevDst->depth == 1)) /* monochrome -> monochrome */ { @@ -938,7 +947,7 @@ static int BITBLT_GetSrcArea( X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDe } else /* color -> color */ { - if (GetObjectType(physDevSrc->hdc) == OBJ_MEMDC) + if (memdc) imageSrc = XGetImage( gdi_display, physDevSrc->drawable, physDevSrc->dc_rect.left + visRectSrc->left, physDevSrc->dc_rect.top + visRectSrc->top, @@ -962,6 +971,7 @@ static int BITBLT_GetSrcArea( X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDe 0, 0, 0, 0, width, height ); XDestroyImage( imageSrc ); } + wine_tsx11_unlock(); } else { @@ -969,6 +979,7 @@ static int BITBLT_GetSrcArea( X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDe { get_colors(physDevDst, physDevSrc, &fg, &bg); + wine_tsx11_lock(); if (X11DRV_PALETTE_XPixelToPalette) { XSetBackground( gdi_display, gc, @@ -986,9 +997,11 @@ static int BITBLT_GetSrcArea( X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDe physDevSrc->dc_rect.top + visRectSrc->top, width, height, 0, 0, 1 ); exposures++; + wine_tsx11_unlock(); } else /* color -> monochrome */ { + wine_tsx11_lock(); /* FIXME: avoid BadMatch error */ imageSrc = XGetImage( gdi_display, physDevSrc->drawable, physDevSrc->dc_rect.left + visRectSrc->left, @@ -996,12 +1009,14 @@ static int BITBLT_GetSrcArea( X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDe width, height, AllPlanes, ZPixmap ); if (!imageSrc) { + wine_tsx11_unlock(); return exposures; } imageDst = X11DRV_DIB_CreateXImage( width, height, physDevDst->depth ); - if (!imageDst) + if (!imageDst) { XDestroyImage(imageSrc); + wine_tsx11_unlock(); return exposures; } for (y = 0; y < height; y++) @@ -1012,6 +1027,7 @@ static int BITBLT_GetSrcArea( X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDe 0, 0, 0, 0, width, height ); XDestroyImage( imageSrc ); XDestroyImage( imageDst ); + wine_tsx11_unlock(); } } return exposures; @@ -1029,6 +1045,9 @@ static int BITBLT_GetDstArea(X11DRV_PDEVICE *physDev, Pixmap pixmap, GC gc, RECT int exposures = 0; INT width = visRectDst->right - visRectDst->left; INT height = visRectDst->bottom - visRectDst->top; + BOOL memdc = (GetObjectType( physDev->hdc ) == OBJ_MEMDC); + + wine_tsx11_lock(); if (!X11DRV_PALETTE_XPixelToPalette || (physDev->depth == 1) || (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL) ) @@ -1043,7 +1062,7 @@ static int BITBLT_GetDstArea(X11DRV_PDEVICE *physDev, Pixmap pixmap, GC gc, RECT register INT x, y; XImage *image; - if (GetObjectType( physDev->hdc ) == OBJ_MEMDC) + if (memdc) image = XGetImage( gdi_display, physDev->drawable, physDev->dc_rect.left + visRectDst->left, physDev->dc_rect.top + visRectDst->top, @@ -1059,13 +1078,18 @@ static int BITBLT_GetDstArea(X11DRV_PDEVICE *physDev, Pixmap pixmap, GC gc, RECT image = XGetImage( gdi_display, pixmap, 0, 0, width, height, AllPlanes, ZPixmap ); } - for (y = 0; y < height; y++) - for (x = 0; x < width; x++) - XPutPixel( image, x, y, - X11DRV_PALETTE_XPixelToPalette[XGetPixel( image, x, y )]); - XPutImage( gdi_display, pixmap, gc, image, 0, 0, 0, 0, width, height ); - XDestroyImage( image ); + if (image) + { + for (y = 0; y < height; y++) + for (x = 0; x < width; x++) + XPutPixel( image, x, y, + X11DRV_PALETTE_XPixelToPalette[XGetPixel( image, x, y )]); + XPutImage( gdi_display, pixmap, gc, image, 0, 0, 0, 0, width, height ); + XDestroyImage( image ); + } } + + wine_tsx11_unlock(); return exposures; } @@ -1435,16 +1459,19 @@ static BOOL BITBLT_InternalStretchBlt( X11DRV_PDEVICE *physDevDst, INT xDst, INT } wine_tsx11_lock(); - tmpGC = XCreateGC( gdi_display, physDevDst->drawable, 0, NULL ); XSetSubwindowMode( gdi_display, tmpGC, IncludeInferiors ); XSetGraphicsExposures( gdi_display, tmpGC, False ); pixmaps[DST] = XCreatePixmap( gdi_display, root_window, width, height, physDevDst->depth ); + wine_tsx11_unlock(); + if (useSrc) { + wine_tsx11_lock(); pixmaps[SRC] = XCreatePixmap( gdi_display, root_window, width, height, physDevDst->depth ); + wine_tsx11_unlock(); if (fStretch) BITBLT_GetSrcAreaStretch( physDevSrc, physDevDst, pixmaps[SRC], tmpGC, xSrc, ySrc, widthSrc, heightSrc, @@ -1460,6 +1487,7 @@ static BOOL BITBLT_InternalStretchBlt( X11DRV_PDEVICE *physDevDst, INT xDst, INT else fNullBrush = FALSE; destUsed = FALSE; + wine_tsx11_lock(); for (opcode = BITBLT_Opcodes[(rop >> 16) & 0xff]; *opcode; opcode++) { if (OP_DST(*opcode) == DST) destUsed = TRUE; diff --git a/dlls/winex11.drv/dib.c b/dlls/winex11.drv/dib.c index 00b1f231030..9f402efc28e 100644 --- a/dlls/winex11.drv/dib.c +++ b/dlls/winex11.drv/dib.c @@ -3501,6 +3501,7 @@ static int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr ) return lines; } } + wine_tsx11_unlock(); TRACE("Dib: depth=%d r=%x g=%x b=%x\n", descr->infoBpp,descr->rMask,descr->gMask,descr->bMask); @@ -3573,6 +3574,8 @@ static int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr ) descr->drawable, descr->gc, bmpImage, descr->xSrc, descr->ySrc, descr->xDest, descr->yDest, descr->width, descr->height); + + wine_tsx11_lock(); #ifdef HAVE_LIBXXSHM if (descr->image && descr->useShm) { @@ -3656,6 +3659,7 @@ static int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr ) descr->width, lines, AllPlanes, ZPixmap, bmpImage, descr->xDest, descr->yDest ); } + wine_tsx11_unlock(); TRACE("Dib: depth=%2d r=%x g=%x b=%x\n", descr->infoBpp,descr->rMask,descr->gMask,descr->bMask); @@ -3724,8 +3728,12 @@ static int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr ) break; } - if (!descr->image) XDestroyImage( bmpImage ); - wine_tsx11_unlock(); + if (!descr->image) + { + wine_tsx11_lock(); + XDestroyImage( bmpImage ); + wine_tsx11_unlock(); + } return lines; } @@ -3743,6 +3751,7 @@ INT X11DRV_SetDIBitsToDevice( X11DRV_PDEVICE *physDev, INT xDest, INT yDest, DWO LONG width, height; BOOL top_down; POINT pt; + int rop = X11DRV_XROPfunction[GetROP2(physDev->hdc) - 1]; if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height, &descr.infoBpp, &descr.compression ) == -1) @@ -3795,7 +3804,7 @@ INT X11DRV_SetDIBitsToDevice( X11DRV_PDEVICE *physDev, INT xDest, INT yDest, DWO X11DRV_SetupGCForText( physDev ); /* To have the correct colors */ wine_tsx11_lock(); - XSetFunction(gdi_display, physDev->gc, X11DRV_XROPfunction[GetROP2(physDev->hdc) - 1]); + XSetFunction(gdi_display, physDev->gc, rop); wine_tsx11_unlock(); switch (descr.infoBpp) diff --git a/dlls/winex11.drv/graphics.c b/dlls/winex11.drv/graphics.c index b2e105fc398..79cd1131651 100644 --- a/dlls/winex11.drv/graphics.c +++ b/dlls/winex11.drv/graphics.c @@ -242,15 +242,16 @@ BOOL X11DRV_SetupGCForPen( X11DRV_PDEVICE *physDev ) default: val.join_style = JoinRound; } - wine_tsx11_lock(); + if (physDev->pen.dash_len) - { - XSetDashes( gdi_display, physDev->gc, 0, physDev->pen.dashes, physDev->pen.dash_len ); val.line_style = ((GetBkMode(physDev->hdc) == OPAQUE) && (!physDev->pen.ext)) ? LineDoubleDash : LineOnOffDash; - } - else val.line_style = LineSolid; + else + val.line_style = LineSolid; + wine_tsx11_lock(); + if (physDev->pen.dash_len) + XSetDashes( gdi_display, physDev->gc, 0, physDev->pen.dashes, physDev->pen.dash_len ); XChangeGC( gdi_display, physDev->gc, GCFunction | GCForeground | GCBackground | GCLineWidth | GCLineStyle | GCCapStyle | GCJoinStyle | GCFillStyle, &val ); @@ -748,9 +749,9 @@ X11DRV_RoundRect( X11DRV_PDEVICE *physDev, INT left, INT top, INT right, /* Update the pixmap from the DIB section */ X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod, FALSE); - wine_tsx11_lock(); if (X11DRV_SetupGCForBrush( physDev )) { + wine_tsx11_lock(); if (ell_width > (rc.right-rc.left) ) if (ell_height > (rc.bottom-rc.top) ) XFillArc( gdi_display, physDev->drawable, physDev->gc, @@ -812,6 +813,7 @@ X11DRV_RoundRect( X11DRV_PDEVICE *physDev, INT left, INT top, INT right, rc.right - rc.left - 2, rc.bottom - rc.top - ell_height - 1); } + wine_tsx11_unlock(); update = TRUE; } /* FIXME: this could be done with on X call @@ -825,6 +827,7 @@ X11DRV_RoundRect( X11DRV_PDEVICE *physDev, INT left, INT top, INT right, */ if (X11DRV_SetupGCForPen( physDev )) { + wine_tsx11_lock(); if (ell_width > (rc.right-rc.left) ) if (ell_height > (rc.bottom-rc.top) ) XDrawArc( gdi_display, physDev->drawable, physDev->gc, @@ -888,9 +891,9 @@ X11DRV_RoundRect( X11DRV_PDEVICE *physDev, INT left, INT top, INT right, physDev->dc_rect.left + rc.left, physDev->dc_rect.top + rc.bottom - (ell_height+1) / 2); } + wine_tsx11_unlock(); update = TRUE; } - wine_tsx11_unlock(); /* Update the DIBSection from the pixmap */ X11DRV_UnlockDIBSection(physDev, update); @@ -1294,18 +1297,18 @@ X11DRV_ExtFloodFill( X11DRV_PDEVICE *physDev, INT x, INT y, COLORREF color, if (!PtInRegion( physDev->region, pt.x, pt.y )) return FALSE; GetRgnBox( physDev->region, &rect ); - wine_tsx11_lock(); X11DRV_expect_error( gdi_display, ExtFloodFillXGetImageErrorHandler, NULL ); image = XGetImage( gdi_display, physDev->drawable, physDev->dc_rect.left + rect.left, physDev->dc_rect.top + rect.top, rect.right - rect.left, rect.bottom - rect.top, AllPlanes, ZPixmap ); if(X11DRV_check_error()) image = NULL; - wine_tsx11_unlock(); if (!image) return FALSE; if (X11DRV_SetupGCForBrush( physDev )) { + unsigned long pixel = X11DRV_PALETTE_ToPhysical( physDev, color ); + /* Update the pixmap from the DIB section */ X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod, FALSE); @@ -1317,8 +1320,7 @@ X11DRV_ExtFloodFill( X11DRV_PDEVICE *physDev, INT x, INT y, COLORREF color, pt.y - rect.top, physDev->dc_rect.left + rect.left, physDev->dc_rect.top + rect.top, - X11DRV_PALETTE_ToPhysical( physDev, color ), - fillType ); + pixel, fillType ); wine_tsx11_unlock(); /* Update the DIBSection of the dc's bitmap */ X11DRV_UnlockDIBSection(physDev, TRUE); diff --git a/dlls/winex11.drv/init.c b/dlls/winex11.drv/init.c index 0946257a84e..9000d0a1e60 100644 --- a/dlls/winex11.drv/init.c +++ b/dlls/winex11.drv/init.c @@ -360,13 +360,16 @@ INT X11DRV_ExtEscape( X11DRV_PDEVICE *physDev, INT escape, INT in_count, LPCVOID wine_tsx11_lock(); XSetGraphicsExposures( gdi_display, physDev->gc, False ); + wine_tsx11_unlock(); if (physDev->exposures) { for (;;) { XEvent event; + wine_tsx11_lock(); XWindowEvent( gdi_display, physDev->drawable, ~0, &event ); + wine_tsx11_unlock(); if (event.type == NoExpose) break; if (event.type == GraphicsExpose) { @@ -398,7 +401,6 @@ INT X11DRV_ExtEscape( X11DRV_PDEVICE *physDev, INT escape, INT in_count, LPCVOID } if (tmp) DeleteObject( tmp ); } - wine_tsx11_unlock(); *(HRGN *)out_data = hrgn; return TRUE; } diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c index b867abd5693..e3d32859629 100644 --- a/dlls/winex11.drv/opengl.c +++ b/dlls/winex11.drv/opengl.c @@ -1690,6 +1690,8 @@ BOOL X11DRV_wglMakeCurrent(X11DRV_PDEVICE *physDev, HGLRC hglrc) { BOOL X11DRV_wglMakeContextCurrentARB(X11DRV_PDEVICE* pDrawDev, X11DRV_PDEVICE* pReadDev, HGLRC hglrc) { BOOL ret; + int indirect = (GetObjectType(pDrawDev->hdc) == OBJ_MEMDC); + TRACE("(%p,%p,%p)\n", pDrawDev, pReadDev, hglrc); if (!has_opengl()) { @@ -1710,7 +1712,7 @@ BOOL X11DRV_wglMakeContextCurrentARB(X11DRV_PDEVICE* pDrawDev, X11DRV_PDEVICE* p Drawable d_read = get_glxdrawable(pReadDev); if (ctx->ctx == NULL) { - ctx->ctx = pglXCreateContext(gdi_display, ctx->vis, NULL, GetObjectType(pDrawDev->hdc) == OBJ_MEMDC ? False : True); + ctx->ctx = pglXCreateContext(gdi_display, ctx->vis, NULL, !indirect); TRACE(" created a delayed OpenGL context (%p)\n", ctx->ctx); } ctx->hdc = pDrawDev->hdc; @@ -1747,22 +1749,24 @@ BOOL X11DRV_wglShareLists(HGLRC hglrc1, HGLRC hglrc2) { return FALSE; } else { if (org->ctx == NULL) { + int indirect = (GetObjectType(org->hdc) == OBJ_MEMDC); wine_tsx11_lock(); describeContext(org); if(org->vis) - org->ctx = pglXCreateContext(gdi_display, org->vis, NULL, GetObjectType(org->hdc) == OBJ_MEMDC ? False : True); + org->ctx = pglXCreateContext(gdi_display, org->vis, NULL, !indirect); else /* Create a GLX Context for a pbuffer */ org->ctx = pglXCreateNewContext(gdi_display, org->fmt->fbconfig, org->fmt->render_type, NULL, True); wine_tsx11_unlock(); TRACE(" created a delayed OpenGL context (%p) for Wine context %p\n", org->ctx, org); } if (NULL != dest) { + int indirect = (GetObjectType(dest->hdc) == OBJ_MEMDC); wine_tsx11_lock(); describeContext(dest); /* Create the destination context with display lists shared */ if(dest->vis) - dest->ctx = pglXCreateContext(gdi_display, dest->vis, org->ctx, GetObjectType(org->hdc) == OBJ_MEMDC ? False : True); + dest->ctx = pglXCreateContext(gdi_display, dest->vis, org->ctx, !indirect); else /* Create a GLX Context for a pbuffer */ dest->ctx = pglXCreateNewContext(gdi_display, dest->fmt->fbconfig, dest->fmt->render_type, org->ctx, True); wine_tsx11_unlock(); diff --git a/dlls/winex11.drv/xrender.c b/dlls/winex11.drv/xrender.c index cbf83bc4dd0..c792eff4363 100644 --- a/dlls/winex11.drv/xrender.c +++ b/dlls/winex11.drv/xrender.c @@ -1630,6 +1630,8 @@ BOOL X11DRV_AlphaBlend(X11DRV_PDEVICE *devDst, INT xDst, INT yDst, INT widthDst, } + rgndata = X11DRV_GetRegionData( devDst->region, 0 ); + wine_tsx11_lock(); image = XCreateImage(gdi_display, visual, 32, ZPixmap, 0, (char*) data, widthSrc, heightSrc, 32, widthSrc * 4); @@ -1664,7 +1666,7 @@ BOOL X11DRV_AlphaBlend(X11DRV_PDEVICE *devDst, INT xDst, INT yDst, INT widthDst, CPSubwindowMode, &pa); TRACE("src_pict %08lx\n", src_pict); - if ((rgndata = X11DRV_GetRegionData( devDst->region, 0 ))) + if (rgndata) { pXRenderSetPictureClipRectangles( gdi_display, dst_pict, devDst->dc_rect.left, devDst->dc_rect.top,