gdiplus: Make GpBitmap->bitmapbits access thread safe.
Signed-off-by: Piotr Caban <piotr@codeweavers.com> Signed-off-by: Vincent Povirk <vincent@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
d00f7315e0
commit
0eaaa15144
|
@ -348,6 +348,7 @@ struct GpImage{
|
|||
UINT frame_count, current_frame;
|
||||
ColorPalette *palette;
|
||||
REAL xres, yres;
|
||||
LONG busy;
|
||||
};
|
||||
|
||||
struct GpMetafile{
|
||||
|
@ -515,4 +516,17 @@ GpStatus gdip_format_string(HDC hdc,
|
|||
|
||||
void get_log_fontW(const GpFont *, GpGraphics *, LOGFONTW *) DECLSPEC_HIDDEN;
|
||||
|
||||
static inline BOOL image_lock(GpImage *image, BOOL *unlock)
|
||||
{
|
||||
LONG tid = GetCurrentThreadId(), owner_tid;
|
||||
owner_tid = InterlockedCompareExchange(&image->busy, tid, 0);
|
||||
*unlock = !owner_tid;
|
||||
return !owner_tid || owner_tid==tid;
|
||||
}
|
||||
|
||||
static inline void image_unlock(GpImage *image, BOOL unlock)
|
||||
{
|
||||
if (unlock) image->busy = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1027,16 +1027,22 @@ GpStatus WINGDIPAPI GdipBitmapLockBits(GpBitmap* bitmap, GDIPCONST GpRect* rect,
|
|||
INT bitspp = PIXELFORMATBPP(format);
|
||||
GpRect act_rect; /* actual rect to be used */
|
||||
GpStatus stat;
|
||||
BOOL unlock;
|
||||
|
||||
TRACE("%p %p %d 0x%x %p\n", bitmap, rect, flags, format, lockeddata);
|
||||
|
||||
if(!lockeddata || !bitmap)
|
||||
return InvalidParameter;
|
||||
if(!image_lock(&bitmap->image, &unlock))
|
||||
return ObjectBusy;
|
||||
|
||||
if(rect){
|
||||
if(rect->X < 0 || rect->Y < 0 || (rect->X + rect->Width > bitmap->width) ||
|
||||
(rect->Y + rect->Height > bitmap->height) || !flags)
|
||||
{
|
||||
image_unlock(&bitmap->image, unlock);
|
||||
return InvalidParameter;
|
||||
}
|
||||
|
||||
act_rect = *rect;
|
||||
}
|
||||
|
@ -1049,6 +1055,7 @@ GpStatus WINGDIPAPI GdipBitmapLockBits(GpBitmap* bitmap, GDIPCONST GpRect* rect,
|
|||
if(bitmap->lockmode)
|
||||
{
|
||||
WARN("bitmap is already locked and cannot be locked again\n");
|
||||
image_unlock(&bitmap->image, unlock);
|
||||
return WrongState;
|
||||
}
|
||||
|
||||
|
@ -1066,6 +1073,7 @@ GpStatus WINGDIPAPI GdipBitmapLockBits(GpBitmap* bitmap, GDIPCONST GpRect* rect,
|
|||
bitmap->lockmode = flags | ImageLockModeRead;
|
||||
bitmap->numlocks++;
|
||||
|
||||
image_unlock(&bitmap->image, unlock);
|
||||
return Ok;
|
||||
}
|
||||
|
||||
|
@ -1076,6 +1084,7 @@ GpStatus WINGDIPAPI GdipBitmapLockBits(GpBitmap* bitmap, GDIPCONST GpRect* rect,
|
|||
if (stat == NotImplemented)
|
||||
{
|
||||
FIXME("cannot read bitmap from %x to %x\n", bitmap->format, format);
|
||||
image_unlock(&bitmap->image, unlock);
|
||||
return NotImplemented;
|
||||
}
|
||||
}
|
||||
|
@ -1088,6 +1097,7 @@ GpStatus WINGDIPAPI GdipBitmapLockBits(GpBitmap* bitmap, GDIPCONST GpRect* rect,
|
|||
if (stat == NotImplemented)
|
||||
{
|
||||
FIXME("cannot write bitmap from %x to %x\n", format, bitmap->format);
|
||||
image_unlock(&bitmap->image, unlock);
|
||||
return NotImplemented;
|
||||
}
|
||||
}
|
||||
|
@ -1103,7 +1113,11 @@ GpStatus WINGDIPAPI GdipBitmapLockBits(GpBitmap* bitmap, GDIPCONST GpRect* rect,
|
|||
|
||||
bitmap->bitmapbits = heap_alloc_zero(lockeddata->Stride * act_rect.Height);
|
||||
|
||||
if (!bitmap->bitmapbits) return OutOfMemory;
|
||||
if (!bitmap->bitmapbits)
|
||||
{
|
||||
image_unlock(&bitmap->image, unlock);
|
||||
return OutOfMemory;
|
||||
}
|
||||
|
||||
lockeddata->Scan0 = bitmap->bitmapbits;
|
||||
}
|
||||
|
@ -1128,6 +1142,7 @@ GpStatus WINGDIPAPI GdipBitmapLockBits(GpBitmap* bitmap, GDIPCONST GpRect* rect,
|
|||
{
|
||||
heap_free(bitmap->bitmapbits);
|
||||
bitmap->bitmapbits = NULL;
|
||||
image_unlock(&bitmap->image, unlock);
|
||||
return stat;
|
||||
}
|
||||
}
|
||||
|
@ -1137,6 +1152,7 @@ GpStatus WINGDIPAPI GdipBitmapLockBits(GpBitmap* bitmap, GDIPCONST GpRect* rect,
|
|||
bitmap->lockx = act_rect.X;
|
||||
bitmap->locky = act_rect.Y;
|
||||
|
||||
image_unlock(&bitmap->image, unlock);
|
||||
return Ok;
|
||||
}
|
||||
|
||||
|
@ -1158,14 +1174,20 @@ GpStatus WINGDIPAPI GdipBitmapUnlockBits(GpBitmap* bitmap,
|
|||
{
|
||||
GpStatus stat;
|
||||
static BOOL fixme = FALSE;
|
||||
BOOL unlock;
|
||||
|
||||
TRACE("(%p,%p)\n", bitmap, lockeddata);
|
||||
|
||||
if(!bitmap || !lockeddata)
|
||||
return InvalidParameter;
|
||||
if(!image_lock(&bitmap->image, &unlock))
|
||||
return ObjectBusy;
|
||||
|
||||
if(!bitmap->lockmode)
|
||||
{
|
||||
image_unlock(&bitmap->image, unlock);
|
||||
return WrongState;
|
||||
}
|
||||
|
||||
if(!(lockeddata->Reserved & ImageLockModeWrite)){
|
||||
if(!(--bitmap->numlocks))
|
||||
|
@ -1173,6 +1195,7 @@ GpStatus WINGDIPAPI GdipBitmapUnlockBits(GpBitmap* bitmap,
|
|||
|
||||
heap_free(bitmap->bitmapbits);
|
||||
bitmap->bitmapbits = NULL;
|
||||
image_unlock(&bitmap->image, unlock);
|
||||
return Ok;
|
||||
}
|
||||
|
||||
|
@ -1181,6 +1204,7 @@ GpStatus WINGDIPAPI GdipBitmapUnlockBits(GpBitmap* bitmap,
|
|||
/* we passed a direct reference; no need to do anything */
|
||||
bitmap->lockmode = 0;
|
||||
bitmap->numlocks = 0;
|
||||
image_unlock(&bitmap->image, unlock);
|
||||
return Ok;
|
||||
}
|
||||
|
||||
|
@ -1206,6 +1230,7 @@ GpStatus WINGDIPAPI GdipBitmapUnlockBits(GpBitmap* bitmap,
|
|||
bitmap->lockmode = 0;
|
||||
bitmap->numlocks = 0;
|
||||
|
||||
image_unlock(&bitmap->image, unlock);
|
||||
return stat;
|
||||
}
|
||||
|
||||
|
@ -3746,6 +3771,7 @@ static GpStatus select_frame_wic(GpImage *image, UINT active_frame)
|
|||
if(status != Ok)
|
||||
return status;
|
||||
|
||||
new_image->busy = image->busy;
|
||||
memcpy(&new_image->format, &image->format, sizeof(GUID));
|
||||
free_image_data(image);
|
||||
if (image->type == ImageTypeBitmap)
|
||||
|
@ -4219,30 +4245,39 @@ GpStatus WINGDIPAPI GdipImageSelectActiveFrame(GpImage *image, GDIPCONST GUID *d
|
|||
{
|
||||
GpStatus stat;
|
||||
const struct image_codec *codec = NULL;
|
||||
BOOL unlock;
|
||||
|
||||
TRACE("(%p,%s,%u)\n", image, debugstr_guid(dimensionID), frame);
|
||||
|
||||
if (!image || !dimensionID)
|
||||
return InvalidParameter;
|
||||
if(!image_lock(image, &unlock))
|
||||
return ObjectBusy;
|
||||
|
||||
if (frame >= image->frame_count)
|
||||
{
|
||||
WARN("requested frame %u, but image has only %u\n", frame, image->frame_count);
|
||||
image_unlock(image, unlock);
|
||||
return InvalidParameter;
|
||||
}
|
||||
|
||||
if (image->type != ImageTypeBitmap && image->type != ImageTypeMetafile)
|
||||
{
|
||||
WARN("invalid image type %d\n", image->type);
|
||||
image_unlock(image, unlock);
|
||||
return InvalidParameter;
|
||||
}
|
||||
|
||||
if (image->current_frame == frame)
|
||||
{
|
||||
image_unlock(image, unlock);
|
||||
return Ok;
|
||||
}
|
||||
|
||||
if (!image->decoder)
|
||||
{
|
||||
TRACE("image doesn't have an associated decoder\n");
|
||||
image_unlock(image, unlock);
|
||||
return Ok;
|
||||
}
|
||||
|
||||
|
@ -4251,10 +4286,13 @@ GpStatus WINGDIPAPI GdipImageSelectActiveFrame(GpImage *image, GDIPCONST GUID *d
|
|||
if (stat != Ok)
|
||||
{
|
||||
WARN("can't find decoder info\n");
|
||||
image_unlock(image, unlock);
|
||||
return stat;
|
||||
}
|
||||
|
||||
return codec->select_func(image, frame);
|
||||
stat = codec->select_func(image, frame);
|
||||
image_unlock(image, unlock);
|
||||
return stat;
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipLoadImageFromStream(IStream *stream, GpImage **image)
|
||||
|
@ -5264,11 +5302,14 @@ GpStatus WINGDIPAPI GdipImageRotateFlip(GpImage *image, RotateFlipType type)
|
|||
UINT x, y, width, height;
|
||||
BitmapData src_lock, dst_lock;
|
||||
GpStatus stat;
|
||||
BOOL unlock;
|
||||
|
||||
TRACE("(%p, %u)\n", image, type);
|
||||
|
||||
if (!image)
|
||||
return InvalidParameter;
|
||||
if (!image_lock(image, &unlock))
|
||||
return ObjectBusy;
|
||||
|
||||
rotate_90 = type&1;
|
||||
flip_x = (type&6) == 2 || (type&6) == 4;
|
||||
|
@ -5277,6 +5318,7 @@ GpStatus WINGDIPAPI GdipImageRotateFlip(GpImage *image, RotateFlipType type)
|
|||
if (image->type != ImageTypeBitmap)
|
||||
{
|
||||
FIXME("Not implemented for type %i\n", image->type);
|
||||
image_unlock(image, unlock);
|
||||
return NotImplemented;
|
||||
}
|
||||
|
||||
|
@ -5286,6 +5328,7 @@ GpStatus WINGDIPAPI GdipImageRotateFlip(GpImage *image, RotateFlipType type)
|
|||
if (bpp < 8)
|
||||
{
|
||||
FIXME("Not implemented for %i bit images\n", bpp);
|
||||
image_unlock(image, unlock);
|
||||
return NotImplemented;
|
||||
}
|
||||
|
||||
|
@ -5305,7 +5348,10 @@ GpStatus WINGDIPAPI GdipImageRotateFlip(GpImage *image, RotateFlipType type)
|
|||
stat = GdipCreateBitmapFromScan0(width, height, 0, bitmap->format, NULL, &new_bitmap);
|
||||
|
||||
if (stat != Ok)
|
||||
{
|
||||
image_unlock(image, unlock);
|
||||
return stat;
|
||||
}
|
||||
|
||||
stat = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, bitmap->format, &src_lock);
|
||||
|
||||
|
@ -5365,6 +5411,7 @@ GpStatus WINGDIPAPI GdipImageRotateFlip(GpImage *image, RotateFlipType type)
|
|||
else
|
||||
GdipDisposeImage(&new_bitmap->image);
|
||||
|
||||
image_unlock(image, unlock);
|
||||
return stat;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue