Bug 1249813 - part 1 - revise nsShmImage to allow draw targets anywhere inside its bounds. r=jrmuizel
authorLee Salzman <lsalzman@mozilla.com>
Thu, 25 Feb 2016 14:38:05 -0500
changeset 285607 a90066c54f7cf0755a8c2982ddf4279ebba4b1c4
parent 285606 d78875efa55acb8f8849336e264bee955ce6a460
child 285608 1c4e6d47312a5418d39435635c2ab06ef381f9e3
push id72438
push userlsalzman@mozilla.com
push dateThu, 25 Feb 2016 19:38:18 +0000
treeherdermozilla-inbound@bd59893f50b8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1249813
milestone47.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1249813 - part 1 - revise nsShmImage to allow draw targets anywhere inside its bounds. r=jrmuizel
gfx/layers/basic/BasicCompositor.cpp
widget/gtk/nsWindow.cpp
widget/nsShmImage.cpp
widget/nsShmImage.h
--- a/gfx/layers/basic/BasicCompositor.cpp
+++ b/gfx/layers/basic/BasicCompositor.cpp
@@ -181,21 +181,24 @@ BasicCompositor::CreateRenderTargetForWi
 
   if (aRect.width * aRect.height == 0) {
     return nullptr;
   }
 
   MOZ_ASSERT(mDrawTarget);
 
   // Adjust bounds rect to account for new origin at (0, 0).
-  IntRect rect(0, 0, aRect.XMost(), aRect.YMost());
-  RefPtr<BasicCompositingRenderTarget> rt = new BasicCompositingRenderTarget(mDrawTarget, rect);
+  IntRect windowRect = aRect;
+  if (aRect.Size() != mDrawTarget->GetSize()) {
+    windowRect.ExpandToEnclose(IntPoint(0, 0));
+  }
+  RefPtr<BasicCompositingRenderTarget> rt = new BasicCompositingRenderTarget(mDrawTarget, windowRect);
 
   if (aInit == INIT_MODE_CLEAR) {
-    mDrawTarget->ClearRect(gfx::Rect(aRect));
+    mDrawTarget->ClearRect(Rect(aRect - rt->GetOrigin()));
   }
 
   return rt.forget();
 }
 
 already_AddRefed<DataTextureSource>
 BasicCompositor::CreateDataTextureSource(TextureFlags aFlags)
 {
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -2231,40 +2231,41 @@ nsWindow::OnExposeEvent(cairo_t *cr)
     }
 
     BufferMode layerBuffering = BufferMode::BUFFERED;
     RefPtr<DrawTarget> dt = GetDrawTarget(region, &layerBuffering);
     if (!dt) {
         return FALSE;
     }
     RefPtr<gfxContext> ctx;
+    IntRect boundsRect = region.GetBounds().ToUnknownRect();
+    IntPoint offset(0, 0);
+    if (dt->GetSize() == boundsRect.Size()) {
+      offset = boundsRect.TopLeft();
+      dt->SetTransform(Matrix::Translation(-offset));
+    }
 
 #ifdef MOZ_X11
-    nsIntRect boundsRect; // for shaped only
-
     if (shaped) {
         // Collapse update area to the bounding box. This is so we only have to
         // call UpdateTranslucentWindowAlpha once. After we have dropped
         // support for non-Thebes graphics, UpdateTranslucentWindowAlpha will be
         // our private interface so we can rework things to avoid this.
-        boundsRect = region.GetBounds().ToUnknownRect();
         dt->PushClipRect(Rect(boundsRect));
-    } else {
-        gfxUtils::ClipToRegion(dt, region.ToUnknownRegion());
-    }
-
-    if (shaped) {
+
         // The double buffering is done here to extract the shape mask.
         // (The shape mask won't be necessary when a visual with an alpha
         // channel is used on compositing window managers.)
         layerBuffering = BufferMode::BUFFER_NONE;
         RefPtr<DrawTarget> destDT = dt->CreateSimilarDrawTarget(boundsRect.Size(), SurfaceFormat::B8G8R8A8);
         ctx = new gfxContext(destDT, boundsRect.TopLeft());
     } else {
-        ctx = new gfxContext(dt);
+        gfxUtils::ClipToRegion(dt, region.ToUnknownRegion());
+
+        ctx = new gfxContext(dt, offset);
     }
 
 #if 0
     // NOTE: Paint flashing region would be wrong for cairo, since
     // cairo inflates the update region, etc.  So don't paint flash
     // for cairo.
 #ifdef DEBUG
     // XXX aEvent->region may refer to a newly-invalid area.  FIXME
@@ -2299,17 +2300,17 @@ nsWindow::OnExposeEvent(cairo_t *cr)
         }
     }
 
     ctx = nullptr;
     dt->PopClip();
 
 #  ifdef MOZ_HAVE_SHMIMAGE
     if (mShmImage && MOZ_LIKELY(!mIsDestroyed)) {
-      mShmImage->Put(mXDisplay, mXWindow, region);
+      mShmImage->Put(region);
     }
 #  endif  // MOZ_HAVE_SHMIMAGE
 #endif // MOZ_X11
 
     listener->DidPaintWindow();
 
     // Synchronously flush any new dirty areas
 #if (MOZ_WIDGET_GTK == 2)
@@ -6482,37 +6483,38 @@ nsWindow::GetSurfaceForGdkDrawable(GdkDr
 
     return result.forget();
 }
 #endif
 
 already_AddRefed<DrawTarget>
 nsWindow::GetDrawTarget(const LayoutDeviceIntRegion& aRegion, BufferMode* aBufferMode)
 {
-  if (!mGdkWindow) {
-    return nullptr;
-  }
-
-  LayoutDeviceIntRect bounds = aRegion.GetBounds();
-  LayoutDeviceIntSize size(bounds.XMost(), bounds.YMost());
-  if (size.width <= 0 || size.height <= 0) {
+  if (!mGdkWindow || aRegion.IsEmpty()) {
     return nullptr;
   }
 
   RefPtr<DrawTarget> dt;
 
 #ifdef MOZ_X11
 #  ifdef MOZ_HAVE_SHMIMAGE
   if (nsShmImage::UseShm()) {
-    dt = nsShmImage::EnsureShmImage(size,
-                                    mXDisplay, mXVisual, mXDepth, mShmImage);
+    if (!mShmImage) {
+      mShmImage = new nsShmImage(mXDisplay, mXWindow, mXVisual, mXDepth);
+    }
+    dt = mShmImage->CreateDrawTarget(aRegion);
     *aBufferMode = BufferMode::BUFFER_NONE;
+    if (!dt) {
+      mShmImage = nullptr;
+    }
   }
 #  endif  // MOZ_HAVE_SHMIMAGE
   if (!dt) {
+    LayoutDeviceIntRect bounds = aRegion.GetBounds();
+    LayoutDeviceIntSize size(bounds.XMost(), bounds.YMost());
     RefPtr<gfxXlibSurface> surf = new gfxXlibSurface(mXDisplay, mXWindow, mXVisual, size.ToUnknownSize());
     if (!surf->CairoStatus()) {
       dt = gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(surf.get(), surf->GetSize());
       *aBufferMode = BufferMode::BUFFERED;
     }
   }
 #endif // MOZ_X11
 
@@ -6530,17 +6532,17 @@ nsWindow::EndRemoteDrawingInRegion(DrawT
                                    LayoutDeviceIntRegion& aInvalidRegion)
 {
 #ifdef MOZ_X11
 #  ifdef MOZ_HAVE_SHMIMAGE
   if (!mGdkWindow || !mShmImage) {
     return;
   }
 
-  mShmImage->Put(mXDisplay, mXWindow, aInvalidRegion);
+  mShmImage->Put(aInvalidRegion);
 #  endif // MOZ_HAVE_SHMIMAGE
 #endif // MOZ_X11
 }
 
 // Code shared begin BeginMoveDrag and BeginResizeDrag
 bool
 nsWindow::GetDragInfo(WidgetMouseEvent* aMouseEvent,
                       GdkWindow** aWindow, gint* aButton,
--- a/widget/nsShmImage.cpp
+++ b/widget/nsShmImage.cpp
@@ -1,21 +1,14 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  *
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#if defined(MOZ_WIDGET_GTK)
-#include <gtk/gtk.h>
-#include <gdk/gdkx.h>
-#elif defined(MOZ_WIDGET_QT)
-#include <QWindow>
-#endif
-
 #include "nsShmImage.h"
 #ifdef MOZ_WIDGET_GTK
 #include "gfxPlatformGtk.h"
 #endif
 
 #ifdef MOZ_HAVE_SHMIMAGE
 #include "mozilla/X11Util.h"
 
@@ -30,31 +23,31 @@ using namespace mozilla::ipc;
 using namespace mozilla::gfx;
 
 // If XShm isn't available to our client, we'll try XShm once, fail,
 // set this to false and then never try again.
 static bool gShmAvailable = true;
 bool nsShmImage::UseShm()
 {
 #ifdef MOZ_WIDGET_GTK
-    return (gShmAvailable && !gfxPlatformGtk::GetPlatform()->UseXRender());
+  return (gShmAvailable && !gfxPlatformGtk::GetPlatform()->UseXRender());
 #else
-    return gShmAvailable;
+  return gShmAvailable;
 #endif
 }
 
 #ifdef MOZ_WIDGET_GTK
 static int gShmError = 0;
 
 static int
 TrapShmError(Display* aDisplay, XErrorEvent* aEvent)
 {
-    // store the error code and ignore the error
-    gShmError = aEvent->error_code;
-    return 0;
+  // store the error code and ignore the error
+  gShmError = aEvent->error_code;
+  return 0;
 }
 #endif
 
 bool
 nsShmImage::CreateShmSegment()
 {
   if (!mImage) {
     return false;
@@ -63,26 +56,29 @@ nsShmImage::CreateShmSegment()
   size_t size = SharedMemory::PageAlignedSize(mImage->bytes_per_line * mImage->height);
 
   mInfo.shmid = shmget(IPC_PRIVATE, size, IPC_CREAT | 0600);
   if (mInfo.shmid == -1) {
     return false;
   }
 
   mInfo.shmaddr = (char *)shmat(mInfo.shmid, nullptr, 0);
+
+  // Mark the handle removed so that it will destroy the segment when unmapped.
+  shmctl(mInfo.shmid, IPC_RMID, nullptr);
+
   if (mInfo.shmaddr == (void *)-1) {
+    // Since mapping failed, the segment is already destroyed.
+    mInfo.shmid = -1;
+
     nsPrintfCString warning("shmat(): %s (%d)\n", strerror(errno), errno);
     NS_WARNING(warning.get());
     return false;
   }
 
-  // Mark the handle as deleted so that, should this process go away, the
-  // segment is cleaned up.
-  shmctl(mInfo.shmid, IPC_RMID, 0);
-
 #ifdef DEBUG
   struct shmid_ds info;
   if (shmctl(mInfo.shmid, IPC_STAT, &info) < 0) {
     return false;
   }
 
   MOZ_ASSERT(size <= info.shm_segsz,
              "Segment doesn't have enough space!");
@@ -100,164 +96,146 @@ nsShmImage::DestroyShmSegment()
 {
   if (mInfo.shmid != -1) {
     shmdt(mInfo.shmaddr);
     mInfo.shmid = -1;
   }
 }
 
 bool
-nsShmImage::CreateImage(const LayoutDeviceIntSize& aSize,
-                        Display* aDisplay, Visual* aVisual, unsigned int aDepth)
+nsShmImage::CreateImage(const IntSize& aSize)
 {
-  mDisplay = aDisplay;
-  mImage = XShmCreateImage(aDisplay, aVisual, aDepth,
-                           ZPixmap, nullptr,
-                           &mInfo,
-                           aSize.width, aSize.height);
-  if (!mImage || !CreateShmSegment()) {
-    return false;
-  }
+  MOZ_ASSERT(mDisplay && mVisual);
 
-#if defined(MOZ_WIDGET_GTK)
-  gShmError = 0;
-  XErrorHandler previousHandler = XSetErrorHandler(TrapShmError);
-  Status attachOk = XShmAttach(aDisplay, &mInfo);
-  XSync(aDisplay, False);
-  XSetErrorHandler(previousHandler);
-  if (gShmError) {
-    attachOk = 0;
-  }
-#elif defined(MOZ_WIDGET_QT)
-  Status attachOk = XShmAttach(aDisplay, &mInfo);
-#endif
-
-  if (!attachOk) {
-    // Assume XShm isn't available, and don't attempt to use it
-    // again.
-    gShmAvailable = false;
-    return false;
-  }
-
-  mXAttached = true;
-  mSize = aSize;
   mFormat = SurfaceFormat::UNKNOWN;
-  switch (mImage->depth) {
+  switch (mDepth) {
   case 32:
-    if ((mImage->red_mask == 0xff0000) &&
-        (mImage->green_mask == 0xff00) &&
-        (mImage->blue_mask == 0xff)) {
+    if (mVisual->red_mask == 0xff0000 &&
+        mVisual->green_mask == 0xff00 &&
+        mVisual->blue_mask == 0xff) {
       mFormat = SurfaceFormat::B8G8R8A8;
     }
     break;
   case 24:
     // Only support the BGRX layout, and report it as BGRA to the compositor.
     // The alpha channel will be discarded when we put the image.
-    if ((mImage->red_mask == 0xff0000) &&
-        (mImage->green_mask == 0xff00) &&
-        (mImage->blue_mask == 0xff)) {
+    if (mVisual->red_mask == 0xff0000 &&
+        mVisual->green_mask == 0xff00 &&
+        mVisual->blue_mask == 0xff) {
       mFormat = SurfaceFormat::B8G8R8A8;
     }
     break;
   case 16:
     mFormat = SurfaceFormat::R5G6B5_UINT16;
     break;
   }
 
   if (mFormat == SurfaceFormat::UNKNOWN) {
     NS_WARNING("Unsupported XShm Image format!");
     gShmAvailable = false;
     return false;
   }
 
+  mImage = XShmCreateImage(mDisplay, mVisual, mDepth,
+                           ZPixmap, nullptr,
+                           &mInfo,
+                           aSize.width, aSize.height);
+  if (!mImage || !CreateShmSegment()) {
+    DestroyImage();
+    return false;
+  }
+
+#ifdef MOZ_WIDGET_GTK
+  gShmError = 0;
+  XErrorHandler previousHandler = XSetErrorHandler(TrapShmError);
+  Status attachOk = XShmAttach(mDisplay, &mInfo);
+  XSync(mDisplay, False);
+  XSetErrorHandler(previousHandler);
+  if (gShmError) {
+    attachOk = 0;
+  }
+#else
+  Status attachOk = XShmAttach(mDisplay, &mInfo);
+#endif
+
+  if (!attachOk) {
+    DestroyShmSegment();
+    DestroyImage();
+
+    // Assume XShm isn't available, and don't attempt to use it
+    // again.
+    gShmAvailable = false;
+    return false;
+  }
+
   return true;
 }
 
-nsShmImage::~nsShmImage()
+void
+nsShmImage::DestroyImage()
 {
   if (mImage) {
     mozilla::FinishX(mDisplay);
-    if (mXAttached) {
+    if (mInfo.shmid != -1) {
       XShmDetach(mDisplay, &mInfo);
     }
     XDestroyImage(mImage);
+    mImage = nullptr;
   }
   DestroyShmSegment();
 }
 
 already_AddRefed<DrawTarget>
-nsShmImage::CreateDrawTarget()
+nsShmImage::CreateDrawTarget(const LayoutDeviceIntRegion& aRegion)
 {
+  // Due to bug 1205045, we must avoid making GTK calls off the main thread to query window size.
+  // Instead we just track the largest offset within the image we are drawing to and grow the image
+  // to accomodate it. Since usually the entire window is invalidated on the first paint to it,
+  // this should grow the image to the necessary size quickly without many intermediate reallocations.
+  IntRect bounds = aRegion.GetBounds().ToUnknownRect();
+  IntSize size(bounds.XMost(), bounds.YMost());
+  if (!mImage || size.width > mImage->width || size.height > mImage->height) {
+    DestroyImage();
+    if (!CreateImage(size)) {
+      return nullptr;
+    }
+  }
+
   return gfxPlatform::GetPlatform()->CreateDrawTargetForData(
-    reinterpret_cast<unsigned char*>(mImage->data),
-    mSize.ToUnknownSize(),
+    reinterpret_cast<unsigned char*>(mImage->data)
+      + bounds.y * mImage->bytes_per_line + bounds.x * BytesPerPixel(mFormat),
+    bounds.Size(),
     mImage->bytes_per_line,
     mFormat);
 }
 
-#ifdef MOZ_WIDGET_GTK
 void
-nsShmImage::Put(Display* aDisplay, Drawable aWindow,
-                const LayoutDeviceIntRegion& aRegion)
-{
-    GC gc = XCreateGC(aDisplay, aWindow, 0, nullptr);
-    LayoutDeviceIntRegion bounded;
-    bounded.And(aRegion,
-                LayoutDeviceIntRect(0, 0, mImage->width, mImage->height));
-    for (auto iter = bounded.RectIter(); !iter.Done(); iter.Next()) {
-        const LayoutDeviceIntRect& r = iter.Get();
-        XShmPutImage(aDisplay, aWindow, gc, mImage,
-                     r.x, r.y,
-                     r.x, r.y,
-                     r.width, r.height,
-                     False);
-    }
-
-    XFreeGC(aDisplay, gc);
-
-    // FIXME/bug 597336: we need to ensure that the shm image isn't
-    // scribbled over before all its pending XShmPutImage()s complete.
-    // However, XSync() is an unnecessarily heavyweight
-    // synchronization mechanism; other options are possible.  If this
-    // XSync is shown to hurt responsiveness, we need to explore the
-    // other options.
-    XSync(aDisplay, False);
-}
-
-#elif defined(MOZ_WIDGET_QT)
-void
-nsShmImage::Put(QWindow* aWindow, QRect& aRect)
+nsShmImage::Put(const LayoutDeviceIntRegion& aRegion)
 {
-    Display* dpy = gfxQtPlatform::GetXDisplay(aWindow);
-    Drawable d = aWindow->winId();
-
-    GC gc = XCreateGC(dpy, d, 0, nullptr);
-    // Avoid out of bounds painting
-    QRect inter = aRect.intersected(aWindow->geometry());
-    XShmPutImage(dpy, d, gc, mImage,
-                 inter.x(), inter.y(),
-                 inter.x(), inter.y(),
-                 inter.width(), inter.height(),
-                 False);
-    XFreeGC(dpy, gc);
-}
-#endif
+  if (!mImage) {
+    return;
+  }
 
-already_AddRefed<DrawTarget>
-nsShmImage::EnsureShmImage(const LayoutDeviceIntSize& aSize,
-                           Display* aDisplay, Visual* aVisual, unsigned int aDepth,
-                           RefPtr<nsShmImage>& aImage)
-{
-  if (!aImage || aImage->Size() != aSize) {
-    // Because we XSync() after XShmAttach() to trap errors, we
-    // know that the X server has the old image's memory mapped
-    // into its address space, so it's OK to destroy the old image
-    // here even if there are outstanding Puts.  The Detach is
-    // ordered after the Puts.
-    aImage = new nsShmImage;
-    if (!aImage->CreateImage(aSize, aDisplay, aVisual, aDepth)) {
-      aImage = nullptr;
-    }
+  GC gc = XCreateGC(mDisplay, mWindow, 0, nullptr);
+  LayoutDeviceIntRegion bounded;
+  bounded.And(aRegion,
+              LayoutDeviceIntRect(0, 0, mImage->width, mImage->height));
+  for (auto iter = bounded.RectIter(); !iter.Done(); iter.Next()) {
+    const LayoutDeviceIntRect& r = iter.Get();
+    XShmPutImage(mDisplay, mWindow, gc, mImage,
+                 r.x, r.y,
+                 r.x, r.y,
+                 r.width, r.height,
+                 False);
   }
-  return !aImage ? nullptr : aImage->CreateDrawTarget();
+
+  XFreeGC(mDisplay, gc);
+
+  // FIXME/bug 597336: we need to ensure that the shm image isn't
+  // scribbled over before all its pending XShmPutImage()s complete.
+  // However, XSync() is an unnecessarily heavyweight
+  // synchronization mechanism; other options are possible.  If this
+  // XSync is shown to hurt responsiveness, we need to explore the
+  // other options.
+  XSync(mDisplay, False);
 }
 
 #endif  // MOZ_HAVE_SHMIMAGE
--- a/widget/nsShmImage.h
+++ b/widget/nsShmImage.h
@@ -15,62 +15,58 @@
 
 #include "mozilla/gfx/2D.h"
 #include "nsIWidget.h"
 #include "nsAutoPtr.h"
 
 #include <X11/Xlib.h>
 #include <X11/extensions/XShm.h>
 
-#ifdef MOZ_WIDGET_QT
-class QRect;
-class QWindow;
-#endif
-
 class nsShmImage {
-    // bug 1168843, compositor thread may create shared memory instances that are destroyed by main thread on shutdown, so this must use thread-safe RC to avoid hitting assertion
-    NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsShmImage)
+  // bug 1168843, compositor thread may create shared memory instances that are destroyed by main thread on shutdown, so this must use thread-safe RC to avoid hitting assertion
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsShmImage)
 
 public:
-    static bool UseShm();
-    static already_AddRefed<mozilla::gfx::DrawTarget>
-        EnsureShmImage(const mozilla::LayoutDeviceIntSize& aSize,
-                       Display* aDisplay, Visual* aVisual, unsigned int aDepth,
-                       RefPtr<nsShmImage>& aImage);
+  static bool UseShm();
 
-    already_AddRefed<mozilla::gfx::DrawTarget> CreateDrawTarget();
+  already_AddRefed<mozilla::gfx::DrawTarget>
+    CreateDrawTarget(const mozilla::LayoutDeviceIntRegion& aRegion);
+
+  void Put(const mozilla::LayoutDeviceIntRegion& aRegion);
 
-#ifdef MOZ_WIDGET_GTK
-    void Put(Display* aDisplay, Drawable aWindow,
-             const mozilla::LayoutDeviceIntRegion& aRegion);
-#elif defined(MOZ_WIDGET_QT)
-    void Put(QWindow* aWindow, QRect& aRect);
-#endif
-
-    mozilla::LayoutDeviceIntSize Size() const { return mSize; }
+  nsShmImage(Display* aDisplay,
+             Drawable aWindow,
+             Visual* aVisual,
+             unsigned int aDepth)
+    : mImage(nullptr)
+    , mDisplay(aDisplay)
+    , mWindow(aWindow)
+    , mVisual(aVisual)
+    , mDepth(aDepth)
+    , mFormat(mozilla::gfx::SurfaceFormat::UNKNOWN)
+  {
+    mInfo.shmid = -1;
+  }
 
 private:
-    nsShmImage()
-        : mImage(nullptr)
-        , mDisplay(nullptr)
-        , mFormat(mozilla::gfx::SurfaceFormat::UNKNOWN)
-        , mXAttached(false)
-    { mInfo.shmid = -1; }
+  ~nsShmImage()
+  {
+    DestroyImage();
+  }
 
-    ~nsShmImage();
+  bool CreateShmSegment();
+  void DestroyShmSegment();
 
-    bool CreateShmSegment();
-    void DestroyShmSegment();
-
-    bool CreateImage(const mozilla::LayoutDeviceIntSize& aSize,
-                     Display* aDisplay, Visual* aVisual, unsigned int aDepth);
+  bool CreateImage(const mozilla::gfx::IntSize& aSize);
+  void DestroyImage();
 
-    XImage*                      mImage;
-    Display*                     mDisplay;
-    XShmSegmentInfo              mInfo;
-    mozilla::LayoutDeviceIntSize mSize;
-    mozilla::gfx::SurfaceFormat  mFormat;
-    bool                         mXAttached;
+  XImage*                      mImage;
+  Display*                     mDisplay;
+  Drawable                     mWindow;
+  Visual*                      mVisual;
+  unsigned int                 mDepth;
+  XShmSegmentInfo              mInfo;
+  mozilla::gfx::SurfaceFormat  mFormat;
 };
 
 #endif // MOZ_HAVE_SHMIMAGE
 
 #endif