Bug 1321129 - make nsShmImage stride compatible with XShm. r=karlt
authorLee Salzman <lsalzman@mozilla.com>
Tue, 21 Feb 2017 10:00:52 -0500
changeset 343985 6c29f41213feb59ffce360a679a90688526c0233
parent 343984 a40af83f562acd1fdb6a6025cbe89290812f614a
child 343986 d749349957b3987cf1b7af83c7249f1ead7e845f
push id87244
push userlsalzman@mozilla.com
push dateTue, 21 Feb 2017 15:01:02 +0000
treeherdermozilla-inbound@6c29f41213fe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskarlt
bugs1321129
milestone54.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 1321129 - make nsShmImage stride compatible with XShm. r=karlt MozReview-Commit-ID: GuiVTPKvAZM
config/system-headers
widget/nsShmImage.cpp
widget/nsShmImage.h
--- a/config/system-headers
+++ b/config/system-headers
@@ -1226,16 +1226,17 @@ X11/cursorfont.h
 X11/extensions/Print.h
 X11/extensions/shape.h
 X11/extensions/scrnsaver.h
 X11/extensions/XShm.h
 X11/extensions/Xrender.h
 X11/extensions/Xfixes.h
 X11/extensions/Xdamage.h
 X11/extensions/Xcomposite.h
+X11/ImUtil.h
 X11/Intrinsic.h
 X11/keysymdef.h
 X11/keysym.h
 X11/Shell.h
 X11/StringDefs.h
 X11/Xatom.h
 X11/Xft/Xft.h
 X11/Xfuncproto.h
--- a/widget/nsShmImage.cpp
+++ b/widget/nsShmImage.cpp
@@ -14,36 +14,42 @@
 #include "nsPrintfCString.h"
 #include "nsTArray.h"
 
 #include <errno.h>
 #include <string.h>
 #include <sys/ipc.h>
 #include <sys/shm.h>
 
+extern "C" {
+#include <X11/ImUtil.h>
+}
+
 using namespace mozilla::ipc;
 using namespace mozilla::gfx;
 
 nsShmImage::nsShmImage(Display* aDisplay,
                        Drawable aWindow,
                        Visual* aVisual,
                        unsigned int aDepth)
-  : mWindow(aWindow)
+  : mDisplay(aDisplay)
+  , mConnection(XGetXCBConnection(aDisplay))
+  , mWindow(aWindow)
   , mVisual(aVisual)
   , mDepth(aDepth)
   , mFormat(mozilla::gfx::SurfaceFormat::UNKNOWN)
   , mSize(0, 0)
+  , mStride(0)
   , mPixmap(XCB_NONE)
   , mGC(XCB_NONE)
   , mRequestPending(false)
   , mShmSeg(XCB_NONE)
   , mShmId(-1)
   , mShmAddr(nullptr)
 {
-  mConnection = XGetXCBConnection(aDisplay);
   mozilla::PodZero(&mSyncRequest);
 }
 
 nsShmImage::~nsShmImage()
 {
   DestroyImage();
 }
 
@@ -53,18 +59,17 @@ static bool gShmAvailable = true;
 bool nsShmImage::UseShm()
 {
   return gShmAvailable;
 }
 
 bool
 nsShmImage::CreateShmSegment()
 {
-  size_t size = SharedMemory::PageAlignedSize(BytesPerPixel(mFormat) *
-                                              mSize.width * mSize.height);
+  size_t size = SharedMemory::PageAlignedSize(mStride * mSize.height);
 
   mShmId = shmget(IPC_PRIVATE, size, IPC_CREAT | 0600);
   if (mShmId == -1) {
     return false;
   }
   mShmAddr = (uint8_t*) shmat(mShmId, nullptr, 0);
   mShmSeg = xcb_generate_id(mConnection);
 
@@ -182,16 +187,23 @@ nsShmImage::CreateImage(const IntSize& a
   }
 
   if (mFormat == SurfaceFormat::UNKNOWN) {
     NS_WARNING("Unsupported XShm Image format!");
     gShmAvailable = false;
     return false;
   }
 
+  // Round up stride to the display's scanline pad (in bits) as XShm expects.
+  int scanlinePad = _XGetScanlinePad(mDisplay, mDepth);
+  int bitsPerPixel = _XGetBitsPerPixel(mDisplay, mDepth);
+  int bitsPerLine = ((bitsPerPixel * aSize.width + scanlinePad - 1)
+                     / scanlinePad) * scanlinePad;
+  mStride = bitsPerLine / 8;
+
   if (!CreateShmSegment()) {
     DestroyImage();
     return false;
   }
 
   xcb_generic_error_t* error;
   xcb_void_cookie_t cookie;
 
@@ -272,19 +284,19 @@ nsShmImage::CreateDrawTarget(const mozil
     DestroyImage();
     if (!CreateImage(size)) {
       return nullptr;
     }
   }
 
   return gfxPlatform::CreateDrawTargetForData(
     reinterpret_cast<unsigned char*>(mShmAddr)
-      + BytesPerPixel(mFormat) * (bounds.y * mSize.width + bounds.x),
+      + bounds.y * mStride + bounds.x * BytesPerPixel(mFormat),
     bounds.Size(),
-    BytesPerPixel(mFormat) * mSize.width,
+    mStride,
     mFormat);
 }
 
 void
 nsShmImage::Put(const mozilla::LayoutDeviceIntRegion& aRegion)
 {
   AutoTArray<xcb_rectangle_t, 32> xrects;
   xrects.SetCapacity(aRegion.GetNumRects());
--- a/widget/nsShmImage.h
+++ b/widget/nsShmImage.h
@@ -45,23 +45,25 @@ private:
   bool CreateShmSegment();
   void DestroyShmSegment();
 
   bool CreateImage(const mozilla::gfx::IntSize& aSize);
   void DestroyImage();
 
   void WaitIfPendingReply();
 
+  Display*                     mDisplay;
   xcb_connection_t*            mConnection;
   Window                       mWindow;
   Visual*                      mVisual;
   unsigned int                 mDepth;
 
   mozilla::gfx::SurfaceFormat  mFormat;
   mozilla::gfx::IntSize        mSize;
+  int                          mStride;
 
   xcb_pixmap_t                 mPixmap;
   xcb_gcontext_t               mGC;
   xcb_get_input_focus_cookie_t mSyncRequest;
   bool                         mRequestPending;
 
   xcb_shm_seg_t                mShmSeg;
   int                          mShmId;