Bug 557159 - [OS/2] Optimize Cairo/Thebes surfaces. Surface Part 2 - MozCairo and Thebes. r= Peter Weilbacher, a=NPOTB
authorRich Walsh <dragtext@e-vertise.com>
Sat, 21 Aug 2010 12:50:32 -0700
changeset 51173 8f1a1bad511eb6c1bb660e5bebf5bb1c189f87a2
parent 51172 b970fa3804ee0973bb5180d58f3e0280de64e09d
child 51174 77a52b34ea6c63d1c26de2f0479d8750f3bd218b
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersNPOTB
bugs557159
milestone2.0b5pre
Bug 557159 - [OS/2] Optimize Cairo/Thebes surfaces. Surface Part 2 - MozCairo and Thebes. r= Peter Weilbacher, a=NPOTB
gfx/cairo/cairo/src/cairo-rename.h
gfx/thebes/gfxOS2Surface.cpp
gfx/thebes/gfxOS2Surface.h
--- a/gfx/cairo/cairo/src/cairo-rename.h
+++ b/gfx/cairo/cairo/src/cairo-rename.h
@@ -109,21 +109,24 @@
 #define cairo_matrix_transform_point _moz_cairo_matrix_transform_point
 #define cairo_matrix_translate _moz_cairo_matrix_translate
 #define cairo_move_to _moz_cairo_move_to
 #define cairo_new_path _moz_cairo_new_path
 #define cairo_new_sub_path _moz_cairo_new_sub_path
 #define cairo_os2_fini _moz_cairo_os2_fini
 #define cairo_os2_init _moz_cairo_os2_init
 #define cairo_os2_surface_create _moz_cairo_os2_surface_create
+#define cairo_os2_surface_create_for_window _moz_cairo_os2_surface_create_for_window
 #define cairo_os2_surface_get_manual_window_refresh _moz_cairo_os2_surface_get_manual_window_refresh
 #define cairo_os2_surface_refresh_window _moz_cairo_os2_surface_refresh_window
 #define cairo_os2_surface_set_hwnd _moz_cairo_os2_surface_set_hwnd
 #define cairo_os2_surface_set_manual_window_refresh _moz_cairo_os2_surface_set_manual_window_refresh
 #define cairo_os2_surface_set_size _moz_cairo_os2_surface_set_size
+#define cairo_os2_surface_get_hps _moz_cairo_os2_surface_get_hps
+#define cairo_os2_surface_set_hps _moz_cairo_os2_surface_set_hps
 #define cairo_paint _moz_cairo_paint
 #define cairo_paint_with_alpha _moz_cairo_paint_with_alpha
 #define cairo_path_destroy _moz_cairo_path_destroy
 #define cairo_path_extents _moz_cairo_path_extents
 #define cairo_pattern_add_color_stop_rgb _moz_cairo_pattern_add_color_stop_rgb
 #define cairo_pattern_add_color_stop_rgba _moz_cairo_pattern_add_color_stop_rgba
 #define cairo_pattern_create_for_surface _moz_cairo_pattern_create_for_surface
 #define cairo_pattern_create_linear _moz_cairo_pattern_create_linear
--- a/gfx/thebes/gfxOS2Surface.cpp
+++ b/gfx/thebes/gfxOS2Surface.cpp
@@ -40,17 +40,17 @@
 #include <stdio.h>
 
 /**********************************************************************
  * class gfxOS2Surface
  **********************************************************************/
 
 gfxOS2Surface::gfxOS2Surface(const gfxIntSize& aSize,
                              gfxASurface::gfxImageFormat aImageFormat)
-    : mHasWnd(PR_FALSE), mSize(aSize)
+    : mWnd(0), mSize(aSize)
 {
 #ifdef DEBUG_thebes_2
     printf("gfxOS2Surface[%#x]::gfxOS2Surface(Size=%dx%d, %d)\n", (unsigned int)this,
            aSize.width, aSize.height, aImageFormat);
 #endif
     // in this case we don't have a window, so we create a memory presentation
     // space to construct the cairo surface on
 
@@ -92,50 +92,45 @@ gfxOS2Surface::gfxOS2Surface(const gfxIn
 
     // manual refresh is done from nsWindow::OnPaint
     cairo_os2_surface_set_manual_window_refresh(surf, 1);
 
     Init(surf);
 }
 
 gfxOS2Surface::gfxOS2Surface(HWND aWnd)
-    : mHasWnd(PR_TRUE), mDC(nsnull), mBitmap(nsnull)
+    : mWnd(aWnd), mDC(nsnull), mPS(nsnull), mBitmap(nsnull)
 {
 #ifdef DEBUG_thebes_2
     printf("gfxOS2Surface[%#x]::gfxOS2Surface(HWND=%#x)\n", (unsigned int)this,
            (unsigned int)aWnd);
 #endif
 
-    mPS = WinGetPS(aWnd);
-
     RECTL rectl;
     WinQueryWindowRect(aWnd, &rectl);
     mSize.width = rectl.xRight - rectl.xLeft;
     mSize.height = rectl.yTop - rectl.yBottom;
     if (mSize.width == 0) mSize.width = 1;   // fake a minimal surface area to let
     if (mSize.height == 0) mSize.height = 1; // cairo_os2_surface_create() return something
-    cairo_surface_t *surf = cairo_os2_surface_create(mPS, mSize.width, mSize.height);
+
+    // This variation on cairo_os2_surface_create() avoids creating a
+    // persistent HPS that may never be used.  It also enables manual
+    // refresh so nsWindow::OnPaint() controls when the screen is updated.
+    cairo_surface_t *surf =
+        cairo_os2_surface_create_for_window(mWnd, mSize.width, mSize.height);
 #ifdef DEBUG_thebes_2
     printf("  type(%#x)=%d (ID=%#x, h/w=%d/%d)\n", (unsigned int)surf,
            cairo_surface_get_type(surf), (unsigned int)mPS, mSize.width, mSize.height);
 #endif
-    // Normally, OS/2 cairo surfaces have to be forced to redraw completely
-    // by calling cairo_surface_mark_dirty(surf), but Mozilla paints them in
-    // full, so that is not necessary here.
-
-    // record the window handle in the cairo surface, so that refresh works
-    cairo_os2_surface_set_hwnd(surf, aWnd);
-    // manual refresh is done from nsWindow::OnPaint
-    cairo_os2_surface_set_manual_window_refresh(surf, 1);
 
     Init(surf);
 }
 
 gfxOS2Surface::gfxOS2Surface(HDC aDC, const gfxIntSize& aSize)
-    : mHasWnd(PR_FALSE), mDC(aDC), mBitmap(nsnull), mSize(aSize)
+    : mWnd(0), mDC(aDC), mBitmap(nsnull), mSize(aSize)
 {
 #ifdef DEBUG_thebes_2
     printf("gfxOS2Surface[%#x]::gfxOS2Surface(HDC=%#x, Size=%dx%d)\n", (unsigned int)this,
            (unsigned int)aDC, aSize.width, aSize.height);
 #endif
     SIZEL sizel = { 0, 0 }; // use same page size as device
     mPS = GpiCreatePS(0, mDC, &sizel, PU_PELS | GPIT_MICRO | GPIA_ASSOC);
     NS_ASSERTION(mPS != GPI_ERROR, "Could not create PS on print DC!");
@@ -175,17 +170,17 @@ gfxOS2Surface::~gfxOS2Surface()
 #ifdef DEBUG_thebes_2
     printf("gfxOS2Surface[%#x]::~gfxOS2Surface()\n", (unsigned int)this);
 #endif
 
     // Surfaces connected to a window were created using WinGetPS so we should
     // release it again with WinReleasePS. Memory or printer surfaces on the
     // other hand were created on device contexts with the GPI functions, so
     // use those to clean up stuff.
-    if (mHasWnd) {
+    if (mWnd) {
         if (mPS) {
             WinReleasePS(mPS);
         }
     } else {
         if (mBitmap) {
             GpiSetBitmap(mPS, NULL);
             GpiDeleteBitmap(mBitmap);
         }
@@ -201,21 +196,40 @@ gfxOS2Surface::~gfxOS2Surface()
 void gfxOS2Surface::Refresh(RECTL *aRect, HPS aPS)
 {
 #ifdef DEBUG_thebes_2
     printf("gfxOS2Surface[%#x]::Refresh(x=%ld,%ld/y=%ld,%ld, HPS=%#x), mPS=%#x\n",
            (unsigned int)this,
            aRect->xLeft, aRect->xRight, aRect->yBottom, aRect->yTop,
            (unsigned int)aPS, (unsigned int)mPS);
 #endif
-    cairo_os2_surface_refresh_window(CairoSurface(), aPS, aRect);
+    cairo_os2_surface_refresh_window(CairoSurface(), (aPS ? aPS : mPS), aRect);
 }
 
 int gfxOS2Surface::Resize(const gfxIntSize& aSize)
 {
 #ifdef DEBUG_thebes_2
     printf("gfxOS2Surface[%#x]::Resize(%dx%d)\n", (unsigned int)this,
            aSize.width, aSize.height);
 #endif
     mSize = aSize; // record the new size
     // hardcode mutex timeout to 50ms for now
     return cairo_os2_surface_set_size(CairoSurface(), mSize.width, mSize.height, 50);
 }
+
+HPS gfxOS2Surface::GetPS()
+{
+    // Creating an HPS on-the-fly should never be needed because GetPS()
+    // is only called for printing surfaces & mPS should only be null for
+    // window surfaces.  It would be a bug if Cairo had an HPS but Thebes
+    // didn't, but we'll check anyway to avoid leakage.  As a last resort,
+    // if this is a window surface we'll create one & hang on to it.
+    if (!mPS) {
+        cairo_os2_surface_get_hps(CairoSurface(), &mPS);
+        if (!mPS && mWnd) {
+            mPS = WinGetPS(mWnd);
+            cairo_os2_surface_set_hps(CairoSurface(), mPS);
+        }
+    }
+
+    return mPS;
+}
+
--- a/gfx/thebes/gfxOS2Surface.h
+++ b/gfx/thebes/gfxOS2Surface.h
@@ -61,20 +61,20 @@ public:
     // Update the cairo surface.
     // While gfxOS2Surface keeps track of the presentation handle itself,
     // use the one from WinBeginPaint() here.
     void Refresh(RECTL *aRect, HPS aPS);
 
     // Reset the cairo surface to the given size.
     int Resize(const gfxIntSize& aSize);
 
-    HPS GetPS() { return mPS; }
+    HPS GetPS();
     gfxIntSize GetSize() { return mSize; }
 
 private:
-    PRBool mHasWnd; // indicates if created through the HWND constructor
+    HWND mWnd; // non-null if created through the HWND constructor
     HDC mDC; // memory device context
     HPS mPS; // presentation space connected to window or memory device
     HBITMAP mBitmap; // bitmap for initialization of memory surface
     gfxIntSize mSize; // current size of the surface
 };
 
 #endif /* GFX_OS2_SURFACE_H */