bug 510979 - OnPaintImageDDraw16 repaints the entire screen on every call r=dougt a192=stuart
authorBrad Lassey <blassey@mozilla.com>
Thu, 20 Aug 2009 18:15:01 -0400
changeset 31518 94d90ddad6e22acef79a31066a11c6014d3f618b
parent 31517 8fca26f09b161ae8c0b05a8df31e45373fcf7a92
child 31519 fffff571cfb05b63bd0f83948daa70c2fbaf7009
push id65
push userblassey@mozilla.com
push dateThu, 03 Sep 2009 00:33:01 +0000
reviewersdougt
bugs510979
milestone1.9.2a2pre
bug 510979 - OnPaintImageDDraw16 repaints the entire screen on every call r=dougt a192=stuart
widget/src/windows/nsWindow.cpp
widget/src/windows/nsWindow.h
widget/src/windows/nsWindowGfx.cpp
--- a/widget/src/windows/nsWindow.cpp
+++ b/widget/src/windows/nsWindow.cpp
@@ -190,16 +190,19 @@
 
 // Windowless plugin support
 #include "nsplugindefs.h"
 
 #include "nsWindowDefs.h"
 
 // For scroll wheel calculations
 #include "nsITimer.h"
+#ifdef WINCE_WINDOWS_MOBILE
+#include "nsGfxCIID.h"
+#endif
 
 /**************************************************************
  *
  * nsScrollPrefObserver Class for scroll acceleration prefs
  *
  **************************************************************/
 
 class nsScrollPrefObserver : public nsIObserver
@@ -400,16 +403,19 @@ PRUint32        gLastInputEventTime     
 // Global user preference for disabling native theme. Used
 // in NativeWindowTheme.
 PRBool          gDisableNativeTheme               = PR_FALSE;
 
 // Global used in Show window enumerations.
 static PRBool   gWindowsVisible                   = PR_FALSE;
 
 static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
+#ifdef WINCE_WINDOWS_MOBILE
+static NS_DEFINE_CID(kRegionCID, NS_REGION_CID);
+#endif
 
 // Global scroll pref observer for scroll acceleration prefs
 static nsScrollPrefObserver* gScrollPrefObserver  = nsnull;
 
 /**************************************************************
  **************************************************************
  **
  ** BLOCK: nsIWidget impl.
@@ -468,16 +474,21 @@ nsWindow::nsWindow() : nsBaseWidget()
 #endif
   mBackground           = ::GetSysColor(COLOR_BTNFACE);
   mBrush                = ::CreateSolidBrush(NSRGB_2_COLOREF(mBackground));
   mForeground           = ::GetSysColor(COLOR_WINDOWTEXT);
 
   // To be used for scroll acceleration
   mScrollSeriesCounter = 0;
 
+#ifdef WINCE_WINDOWS_MOBILE
+  mInvalidatedRegion = do_CreateInstance(kRegionCID);
+  mInvalidatedRegion->Init();
+#endif
+
   // Global initialization
   if (!sInstanceCount) {
 #if !defined(WINCE)
   gKbdLayout.LoadLayout(::GetKeyboardLayout(0));
 #endif
 
   // Init IME handler
   nsIMM32Handler::Initialize();
@@ -2061,30 +2072,42 @@ NS_IMETHODIMP nsWindow::HideWindowChrome
 // Validate a visible area of a widget.
 NS_METHOD nsWindow::Validate()
 {
   if (mWnd)
     VERIFY(::ValidateRect(mWnd, NULL));
   return NS_OK;
 }
 
+#ifdef WINCE_WINDOWS_MOBILE
+static inline void AddRECTToRegion(const RECT& aRect, nsIRegion* aRegion)
+{
+  aRegion->Union(aRect.left, aRect.top, aRect.right - aRect.left, aRect.bottom - aRect.top);
+}
+#endif
+
 // Invalidate this component visible area
 NS_METHOD nsWindow::Invalidate(PRBool aIsSynchronous)
 {
   if (mWnd)
   {
 #ifdef WIDGET_DEBUG_OUTPUT
     debug_DumpInvalidate(stdout,
                          this,
                          nsnull,
                          aIsSynchronous,
                          nsCAutoString("noname"),
                          (PRInt32) mWnd);
 #endif // WIDGET_DEBUG_OUTPUT
-
+#ifdef WINCE_WINDOWS_MOBILE
+    // We need to keep track of our own invalidated region for Windows CE
+    RECT r;
+    GetClientRect(mWnd, &r);
+    AddRECTToRegion(r, mInvalidatedRegion);
+#endif
     VERIFY(::InvalidateRect(mWnd, NULL, FALSE));
 
     if (aIsSynchronous) {
       VERIFY(::UpdateWindow(mWnd));
     }
   }
   return NS_OK;
 }
@@ -2105,16 +2128,20 @@ NS_METHOD nsWindow::Invalidate(const nsI
 
     RECT rect;
 
     rect.left   = aRect.x;
     rect.top    = aRect.y;
     rect.right  = aRect.x + aRect.width;
     rect.bottom = aRect.y + aRect.height;
 
+#ifdef WINCE_WINDOWS_MOBILE
+    // We need to keep track of our own invalidated region for Windows CE
+    AddRECTToRegion(rect, mInvalidatedRegion);
+#endif
     VERIFY(::InvalidateRect(mWnd, &rect, FALSE));
 
     if (aIsSynchronous) {
       VERIFY(::UpdateWindow(mWnd));
     }
   }
   return NS_OK;
 }
--- a/widget/src/windows/nsWindow.h
+++ b/widget/src/windows/nsWindow.h
@@ -310,16 +310,17 @@ protected:
   PRBool                  OnGesture(WPARAM wParam, LPARAM lParam);
   PRBool                  OnHotKey(WPARAM wParam, LPARAM lParam);
   BOOL                    OnInputLangChange(HKL aHKL);
   void                    OnSettingsChange(WPARAM wParam, LPARAM lParam);
   virtual PRBool          OnPaint(HDC aDC = nsnull);
   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,
                                        LRESULT *aRetValue);
   static void             OnMouseWheelTimeout(nsITimer* aTimer, void* aClosure);
   void                    UpdateMouseWheelSeriesCounter();
   int                     ComputeMouseWheelDelta(int currentVDelta,
                                                  int iDeltaPerLine,
@@ -376,16 +377,18 @@ protected:
    * Misc.
    */
   UINT                    MapFromNativeToDOM(UINT aNativeKeyCode);
   void                    StopFlashing();
   static PRBool           IsTopLevelMouseExit(HWND aWnd);
   static void             SetupKeyModifiersSequence(nsTArray<KeyPair>* aArray, PRUint32 aModifiers);
   nsresult                SetWindowClipRegion(const nsTArray<nsIntRect>& aRects,
                                               PRBool aIntersectWithExisting);
+  nsCOMPtr<nsIRegion>     GetRegionToPaint(PRBool aForceFullRepaint, 
+                                           PAINTSTRUCT ps, HDC aDC);
 
 #ifdef ACCESSIBILITY
   static STDMETHODIMP_(LRESULT) LresultFromObject(REFIID riid, WPARAM wParam, LPUNKNOWN pAcc);
 #endif // ACCESSIBILITY
 
 protected:
   nsIntSize             mLastSize;
   nsIntPoint            mLastPoint;
@@ -409,17 +412,19 @@ protected:
   DWORD_PTR             mOldExStyle;
   HIMC                  mOldIMC;
   PRUint32              mIMEEnabled;
   nsNativeDragTarget*   mNativeDragTarget;
   HKL                   mLastKeyboardLayout;
   nsPopupType           mPopupType;
   int                   mScrollSeriesCounter;
   PRPackedBool          mDisplayPanFeedback;
-
+#ifdef WINCE_WINDOWS_MOBILE
+  nsCOMPtr<nsIRegion>   mInvalidatedRegion; 
+#endif
   static PRUint32       sInstanceCount;
   static TriStateBool   sCanQuit;
   static nsWindow*      sCurrentWindow;
   static BOOL           sIsRegistered;
   static BOOL           sIsPopupClassRegistered;
   static BOOL           sIsOleInitialized;
   static HCURSOR        sHCursor;
   static imgIContainer* sCursorImgContainer;
--- a/widget/src/windows/nsWindowGfx.cpp
+++ b/widget/src/windows/nsWindowGfx.cpp
@@ -247,16 +247,69 @@ void nsWindowGfx::OnSettingsChangeGfx(WP
 
 void nsWindow::SetUpForPaint(HDC aHDC)
 {
   ::SetBkColor (aHDC, NSRGB_2_COLOREF(mBackground));
   ::SetTextColor(aHDC, NSRGB_2_COLOREF(mForeground));
   ::SetBkMode (aHDC, TRANSPARENT);
 }
 
+// GetRegionToPaint returns the invalidated region that needs to be painted
+// it's abstracted out because Windows XP/Vista/7 handles this for us, but
+// we need to keep track of it our selves for Windows CE and Windows Mobile
+
+nsCOMPtr<nsIRegion> nsWindow::GetRegionToPaint(PRBool aForceFullRepaint,
+                                               PAINTSTRUCT ps, HDC aDC)
+{ 
+  HRGN paintRgn = NULL;
+  nsCOMPtr<nsIRegion> paintRgnWin;
+  if (aForceFullRepaint) {
+    RECT paintRect;
+    ::GetClientRect(mWnd, &paintRect);
+    paintRgn = ::CreateRectRgn(paintRect.left, paintRect.top, 
+                               paintRect.right, paintRect.bottom);
+    if (paintRgn) {
+      paintRgnWin = nsWindowGfx::ConvertHRGNToRegion(paintRgn);
+      ::DeleteObject(paintRgn);
+      return paintRgnWin;
+    }
+  }
+#ifndef WINCE
+  paintRgn = ::CreateRectRgn(0, 0, 0, 0);
+  if (paintRgn != NULL) {
+    int result = GetRandomRgn(aDC, paintRgn, SYSRGN);
+    if (result == 1) {
+      POINT pt = {0,0};
+      ::MapWindowPoints(NULL, mWnd, &pt, 1);
+      ::OffsetRgn(paintRgn, pt.x, pt.y);
+    }
+    paintRgnWin = nsWindowGfx::ConvertHRGNToRegion(paintRgn);
+    ::DeleteObject(paintRgn);
+  }
+#else
+# ifdef WINCE_WINDOWS_MOBILE
+  if (!mInvalidatedRegion->IsEmpty()) {  
+    // XXX: we may not recieve invalidates when an OS dialog obsures out window 
+    // and dismisses, so mInvalidatedRegion may not be complete
+    paintRgnWin = mInvalidatedRegion.forget();
+    mInvalidatedRegion = do_CreateInstance(kRegionCID);
+    mInvalidatedRegion->Init(); 
+    return paintRgnWin;
+  }
+# endif
+  paintRgn = ::CreateRectRgn(ps.rcPaint.left, ps.rcPaint.top,
+                             ps.rcPaint.right, ps.rcPaint.bottom);
+  if (paintRgn) {
+    paintRgnWin = nsWindowGfx::ConvertHRGNToRegion(paintRgn);
+    ::DeleteObject(paintRgn);
+  }
+#endif
+  return paintRgnWin;
+}
+
 PRBool nsWindow::OnPaint(HDC aDC)
 {
 #ifdef CAIRO_HAS_DDRAW_SURFACE
   if (IsRenderMode(gfxWindowsPlatform::RENDER_IMAGE_DDRAW16)) {
     return OnPaintImageDDraw16();
   }
 #endif
 
@@ -291,50 +344,23 @@ PRBool nsWindow::OnPaint(HDC aDC)
     debugPaintFlashRegion = ::CreateRectRgn(0, 0, 0, 0);
     ::GetUpdateRgn(mWnd, debugPaintFlashRegion, TRUE);
     debugPaintFlashDC = ::GetDC(mWnd);
   }
 #endif // WIDGET_DEBUG_OUTPUT
 
   HDC hDC = aDC ? aDC : (::BeginPaint(mWnd, &ps));
   mPaintDC = hDC;
-  HRGN paintRgn = NULL;
 
 #ifdef MOZ_XUL
-  if (aDC || (eTransparencyTransparent == mTransparencyMode)) {
+  PRBool forceRepaint = aDC || (eTransparencyTransparent == mTransparencyMode);
 #else
-  if (aDC) {
+  PRBool forceRepaint = NULL != aDC;
 #endif
-
-    RECT paintRect;
-    ::GetClientRect(mWnd, &paintRect);
-    paintRgn = ::CreateRectRgn(paintRect.left, paintRect.top, paintRect.right, paintRect.bottom);
-  }
-  else {
-#ifndef WINCE
-    paintRgn = ::CreateRectRgn(0, 0, 0, 0);
-    if (paintRgn != NULL) {
-      int result = GetRandomRgn(hDC, paintRgn, SYSRGN);
-      if (result == 1) {
-        POINT pt = {0,0};
-        ::MapWindowPoints(NULL, mWnd, &pt, 1);
-        ::OffsetRgn(paintRgn, pt.x, pt.y);
-      }
-    }
-#else
-    paintRgn = ::CreateRectRgn(ps.rcPaint.left, ps.rcPaint.top, 
-                               ps.rcPaint.right, ps.rcPaint.bottom);
-#endif
-  }
-
-  nsCOMPtr<nsIRegion> paintRgnWin;
-  if (paintRgn) {
-    paintRgnWin = nsWindowGfx::ConvertHRGNToRegion(paintRgn);
-    ::DeleteObject(paintRgn);
-  }
+  nsCOMPtr<nsIRegion> paintRgnWin = GetRegionToPaint(forceRepaint, ps, hDC);
 
   if (paintRgnWin &&
       !paintRgnWin->IsEmpty() &&
       mEventCallback)
   {
     // generate the event and call the event callback
     nsPaintEvent event(PR_TRUE, NS_PAINT, this);
 
@@ -837,48 +863,150 @@ HBITMAP nsWindowGfx::DataToBitmap(PRUint
 #else
   return nsnull;
 #endif
 }
 
 
 // Windows Mobile Special image/direct draw painting fun
 #if defined(CAIRO_HAS_DDRAW_SURFACE)
+
+HRESULT nsWindow::PaintRectImageDDraw16(RECT rcPaint, nsPaintEvent* event){
+  HRESULT hr;
+  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);
+  
+  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,
+                                                            surfaceSize.width,
+                                                            surfaceSize.height,
+                                                            (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;
-  gfxIntSize surfaceSize;
   nsPaintEvent event(PR_TRUE, NS_PAINT, this);
-  RECT renderArea;
-
-  nsEventStatus eventStatus = nsEventStatus_eIgnore;
-  nsCOMPtr<nsIRenderingContext> rc;
-  nsRefPtr<gfxImageSurface> targetSurfaceImage;
-  nsRefPtr<gfxContext> thebesContext;
-
   mPainting = PR_TRUE;
 
   HDC hDC = ::BeginPaint(mWnd, &ps);
   mPaintDC = hDC;
-
-  HRGN paintRgn = ::CreateRectRgn(ps.rcPaint.left, ps.rcPaint.top, 
-                                  ps.rcPaint.right, ps.rcPaint.bottom);
-
-  nsCOMPtr<nsIRegion> paintRgnWin;
-  if (paintRgn) {
-    paintRgnWin = nsWindowGfx::ConvertHRGNToRegion(paintRgn);
-    ::DeleteObject(paintRgn);
-  }
+  nsCOMPtr<nsIRegion> paintRgnWin = GetRegionToPaint(PR_FALSE, ps, hDC);
 
   if (!paintRgnWin || paintRgnWin->IsEmpty() || !mEventCallback) {
     printf("nothing to paint\n");
     goto cleanup;
   }
-
   InitEvent(event);
   
   event.region = paintRgnWin;
   event.rect = nsnull;
   
   if (!glpDD) {
     if (!nsWindowGfx::InitDDraw()) {
       NS_WARNING("DirectDraw init failed.  Giving up.");
@@ -914,127 +1042,25 @@ PRBool nsWindow::OnPaintImageDDraw16()
     HRESULT hr = glpDD->CreateSurface(&gDDSDSecondary, &glpDDSecondary, 0);
     if (FAILED(hr)) {
 #ifdef DEBUG
       DDError("CreateSurface renderer", hr);
 #endif
       goto cleanup;
     }
   }
-
-  surfaceSize = gfxIntSize(ps.rcPaint.right - ps.rcPaint.left,
-                           ps.rcPaint.bottom - ps.rcPaint.top);
-
-  targetSurfaceImage = new gfxImageSurface(sSharedSurfaceData.get(),
-					   surfaceSize,
-					   surfaceSize.width * 4,
-					   gfxASurface::ImageFormatRGB24);
-
-  if (!targetSurfaceImage || targetSurfaceImage->CairoStatus()) {
-    NS_ERROR("Invalid targetSurfaceImage!");
-    goto cleanup;
-  }
-
-  targetSurfaceImage->SetDeviceOffset(gfxPoint(-ps.rcPaint.left, -ps.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");
-    goto cleanup;
-  }
-  
-  rv = rc->Init(mContext, thebesContext);
-  if (NS_FAILED(rv)) {
-    NS_WARNING("RC::Init failed");
-    goto cleanup;
-  }
-  
-  event.renderingContext = rc;
-  result = DispatchWindowEvent(&event, eventStatus);
-  event.renderingContext = nsnull;
-  
-  if (!result) {
-    printf("result is null from dispatch\n");
-    goto cleanup;
-  }
-    
-  HRESULT hr;  
-  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
-    goto cleanup;
-  }
-  
-  // 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,
-                                                            surfaceSize.width,
-                                                            surfaceSize.height,
-                                                            (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
-    goto cleanup;
-  }
-
-  hr = glpDDClipper->SetHWnd(0, mWnd);
-  if (FAILED(hr)) {
-#ifdef DEBUG
-    DDError("SetHWnd", hr);
-#endif
-    goto cleanup;
-  }
-
-  // translate the paint region to screen coordinates
-  renderArea = ps.rcPaint;
-  MapWindowPoints(mWnd, 0, (LPPOINT)&renderArea, 2);
-
-  // set the rect to be 0,0 based
-  ps.rcPaint.right = surfaceSize.width;
-  ps.rcPaint.bottom = surfaceSize.height;
-  ps.rcPaint.left = ps.rcPaint.top = 0;
-  
-  hr = glpDDPrimary->Blt(&renderArea,
-                         glpDDSecondary,
-                         &ps.rcPaint,
-                         DDBLT_WAITNOTBUSY, /* should we really wait here? */
-                         NULL);
-  if (FAILED(hr)) {
-#ifdef DEBUG
-    DDError("Blt", hr);
-#endif
-    goto cleanup;
+  nsRegionRectSet *rects = nsnull;
+  RECT r;
+  paintRgnWin->GetRects(&rects);
+  for (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);
   }
 
 cleanup:
  
   ::EndPaint(mWnd, &ps);
   mPaintDC = nsnull;
   mPainting = PR_FALSE;
   return result;