Bug 1321129 - make nsShmImage stride compatible with XShm. r=karlt
authorLee Salzman <lsalzman@mozilla.com>
Tue, 21 Feb 2017 10:00:52 -0500
changeset 373102 6c29f41213feb59ffce360a679a90688526c0233
parent 373101 a40af83f562acd1fdb6a6025cbe89290812f614a
child 373103 d749349957b3987cf1b7af83c7249f1ead7e845f
push id10863
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 23:02:23 +0000
treeherdermozilla-aurora@0931190cd725 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskarlt
bugs1321129
milestone54.0a1
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;