bug 532344 - only issue one NS_PAINT event for each WM_PAINT on WinMo r=dougt

This commit is contained in:
Brad Lassey 2010-01-18 00:05:58 -05:00
parent e4668b2b4d
commit d3bc320ce8
2 changed files with 97 additions and 128 deletions

View File

@ -341,7 +341,6 @@ protected:
void OnWindowPosChanged(WINDOWPOS *wp, PRBool& aResult);
#if defined(CAIRO_HAS_DDRAW_SURFACE)
PRBool OnPaintImageDDraw16();
HRESULT PaintRectImageDDraw16(RECT aRect, nsPaintEvent* aEvent);
#endif // defined(CAIRO_HAS_DDRAW_SURFACE)
PRBool OnMouseWheel(UINT msg, WPARAM wParam, LPARAM lParam,
PRBool& result, PRBool& getWheelInfo,

View File

@ -878,147 +878,31 @@ HBITMAP nsWindowGfx::DataToBitmap(PRUint8* aImageData,
// Windows Mobile Special image/direct draw painting fun
#if defined(CAIRO_HAS_DDRAW_SURFACE)
HRESULT nsWindow::PaintRectImageDDraw16(RECT rcPaint, nsPaintEvent* event){
HRESULT hr;
PRBool nsWindow::OnPaintImageDDraw16()
{
PRBool result = PR_FALSE;
PAINTSTRUCT ps;
nsPaintEvent event(PR_TRUE, NS_PAINT, this);
gfxIntSize surfaceSize;
nsRefPtr<gfxImageSurface> targetSurfaceImage;
nsRefPtr<gfxContext> thebesContext;
nsCOMPtr<nsIRenderingContext> rc;
nsEventStatus eventStatus = nsEventStatus_eIgnore;
RECT renderArea;
surfaceSize = gfxIntSize(rcPaint.right - rcPaint.left,
rcPaint.bottom - rcPaint.top);
if (!EnsureSharedSurfaceSize(surfaceSize)) {
NS_ERROR("Couldn't allocate shared surface!");
return E_FAIL;
}
targetSurfaceImage = new gfxImageSurface(sSharedSurfaceData.get(),
surfaceSize,
surfaceSize.width * 4,
gfxASurface::ImageFormatRGB24);
if (!targetSurfaceImage || targetSurfaceImage->CairoStatus()) {
NS_ERROR("Invalid targetSurfaceImage!");
return E_FAIL;
}
targetSurfaceImage->SetDeviceOffset(gfxPoint(-rcPaint.left, -rcPaint.top));
thebesContext = new gfxContext(targetSurfaceImage);
thebesContext->SetFlag(gfxContext::FLAG_DESTINED_FOR_SCREEN);
thebesContext->SetFlag(gfxContext::FLAG_SIMPLIFY_OPERATORS);
nsresult rv = mContext->CreateRenderingContextInstance (*getter_AddRefs(rc));
if (NS_FAILED(rv)) {
NS_WARNING("CreateRenderingContextInstance failed");
return E_FAIL;
}
rv = rc->Init(mContext, thebesContext);
if (NS_FAILED(rv)) {
NS_WARNING("RC::Init failed");
return E_FAIL;
}
event->renderingContext = rc;
nsresult result = DispatchWindowEvent(event, eventStatus);
event->renderingContext = nsnull;
if (!result) {
printf("result is null from dispatch\n");
return E_FAIL;
}
hr = glpDDSecondary->Lock(0, &gDDSDSecondary, DDLOCK_WAITNOTBUSY | DDLOCK_DISCARD, 0); /* should we wait here? */
if (FAILED(hr)) {
#ifdef DEBUG
DDError("Failed to lock renderer", hr);
#endif
return E_FAIL;
}
// Convert RGB24 -> RGB565
pixman_image_t *srcPixmanImage = pixman_image_create_bits(PIXMAN_x8r8g8b8,
surfaceSize.width,
surfaceSize.height,
(uint32_t*) sSharedSurfaceData.get(),
surfaceSize.width * 4);
pixman_image_t *dstPixmanImage = pixman_image_create_bits(PIXMAN_r5g6b5,
gDDSDSecondary.dwWidth,
gDDSDSecondary.dwHeight,
(uint32_t*) gDDSDSecondary.lpSurface,
gDDSDSecondary.dwWidth * 2);
pixman_image_composite(PIXMAN_OP_SRC,
srcPixmanImage,
NULL,
dstPixmanImage,
0, 0,
0, 0,
0, 0,
surfaceSize.width,
surfaceSize.height);
pixman_image_unref(dstPixmanImage);
pixman_image_unref(srcPixmanImage);
hr = glpDDSecondary->Unlock(0);
if (FAILED(hr)) {
#ifdef DEBUG
DDError("Failed to unlock renderer", hr);
#endif
return E_FAIL;
}
hr = glpDDClipper->SetHWnd(0, mWnd);
if (FAILED(hr)) {
#ifdef DEBUG
DDError("SetHWnd", hr);
#endif
return E_FAIL;
}
// translate the paint region to screen coordinates
renderArea = rcPaint;
MapWindowPoints(mWnd, 0, (LPPOINT)&renderArea, 2);
// set the rect to be 0,0 based
rcPaint.right = surfaceSize.width;
rcPaint.bottom = surfaceSize.height;
rcPaint.left = rcPaint.top = 0;
return glpDDPrimary->Blt(&renderArea,
glpDDSecondary,
&rcPaint,
DDBLT_WAITNOTBUSY, /* should we really wait here? */
NULL);
}
PRBool nsWindow::OnPaintImageDDraw16()
{
PRBool result = PR_TRUE;
PAINTSTRUCT ps;
nsPaintEvent event(PR_TRUE, NS_PAINT, this);
mPainting = PR_TRUE;
PRInt32 brx, bry, brw, brh;
gfxIntSize newSize;
newSize.height = GetSystemMetrics(SM_CYSCREEN);
newSize.width = GetSystemMetrics(SM_CXSCREEN);
mPainting = PR_TRUE;
HDC hDC = ::BeginPaint(mWnd, &ps);
mPaintDC = hDC;
nsCOMPtr<nsIRegion> paintRgnWin = GetRegionToPaint(PR_FALSE, ps, hDC);
if (!paintRgnWin || paintRgnWin->IsEmpty() || !mEventCallback) {
printf("nothing to paint\n");
result = PR_TRUE;
goto cleanup;
}
InitEvent(event);
event.region = paintRgnWin;
@ -1058,22 +942,108 @@ PRBool nsWindow::OnPaintImageDDraw16()
goto cleanup;
}
}
paintRgnWin->GetBoundingBox(&brx, &bry, &brw, &brh);
surfaceSize = gfxIntSize(brw, brh);
if (!EnsureSharedSurfaceSize(surfaceSize))
goto cleanup;
targetSurfaceImage = new gfxImageSurface(sSharedSurfaceData.get(),
surfaceSize,
surfaceSize.width * 4,
gfxASurface::ImageFormatRGB24);
if (!targetSurfaceImage || targetSurfaceImage->CairoStatus())
goto cleanup;
targetSurfaceImage->SetDeviceOffset(gfxPoint(-brx, -bry));
thebesContext = new gfxContext(targetSurfaceImage);
thebesContext->SetFlag(gfxContext::FLAG_DESTINED_FOR_SCREEN);
thebesContext->SetFlag(gfxContext::FLAG_SIMPLIFY_OPERATORS);
nsresult rv = mContext->CreateRenderingContextInstance (*getter_AddRefs(rc));
if (NS_FAILED(rv))
goto cleanup;
rv = rc->Init(mContext, thebesContext);
if (NS_FAILED(rv))
goto cleanup;
event.renderingContext = rc;
PRBool res = DispatchWindowEvent(&event, eventStatus);
event.renderingContext = nsnull;
if (!res && eventStatus == nsEventStatus_eConsumeNoDefault)
goto cleanup;
nsRegionRectSet *rects = nsnull;
RECT r;
paintRgnWin->GetRects(&rects);
HRESULT hr = glpDDSecondary->Lock(0, &gDDSDSecondary, DDLOCK_WAITNOTBUSY | DDLOCK_DISCARD, 0);
if (FAILED(hr))
goto cleanup;
pixman_image_t *srcPixmanImage =
pixman_image_create_bits(PIXMAN_x8r8g8b8, surfaceSize.width,
surfaceSize.height,
(uint32_t*) sSharedSurfaceData.get(),
surfaceSize.width * 4);
pixman_image_t *dstPixmanImage =
pixman_image_create_bits(PIXMAN_r5g6b5, gDDSDSecondary.dwWidth,
gDDSDSecondary.dwHeight,
(uint32_t*) gDDSDSecondary.lpSurface,
gDDSDSecondary.dwWidth * 2);
for (unsigned int i = 0; i < rects->mNumRects; i++) {
pixman_image_composite(PIXMAN_OP_SRC, srcPixmanImage, NULL, dstPixmanImage,
rects->mRects[i].x - brx, rects->mRects[i].y - bry,
0, 0,
rects->mRects[i].x, rects->mRects[i].y,
rects->mRects[i].width, rects->mRects[i].height);
}
pixman_image_unref(dstPixmanImage);
pixman_image_unref(srcPixmanImage);
hr = glpDDSecondary->Unlock(0);
if (FAILED(hr))
goto cleanup;
hr = glpDDClipper->SetHWnd(0, mWnd);
if (FAILED(hr))
goto cleanup;
for (unsigned int i = 0; i < rects->mNumRects; i++) {
r.left = rects->mRects[i].x;
r.top = rects->mRects[i].y;
r.right = rects->mRects[i].width + rects->mRects[i].x;
r.bottom = rects->mRects[i].height + rects->mRects[i].y;
PaintRectImageDDraw16(r, &event);
RECT renderRect = r;
SetLastError(0); // See http://msdn.microsoft.com/en-us/library/dd145046%28VS.85%29.aspx
if (MapWindowPoints(mWnd, 0, (LPPOINT)&renderRect, 2) || 0 == (hr = GetLastError()))
hr = glpDDPrimary->Blt(&renderRect, glpDDSecondary, &r, 0, NULL);
if (FAILED(hr))
// add this rect back to the invalidated region so we'll attempt paint it next time around
mInvalidatedRegion->Union(rects->mRects[i].x, rects->mRects[i].y,
rects->mRects[i].width, rects->mRects[i].height);
}
result = PR_TRUE;
cleanup:
// re-invalidate the region if we failed.
if (!result)
mInvalidatedRegion->Union(*paintRgnWin.get());
::EndPaint(mWnd, &ps);
mPaintDC = nsnull;
mPainting = PR_FALSE;
return result;
}
#endif // defined(CAIRO_HAS_DDRAW_SURFACE)