author | Lee Salzman <lsalzman@mozilla.com> |
Thu, 18 Feb 2016 10:56:15 -0500 (2016-02-18) | |
changeset 284721 | 94f9bb9e325342ef86c534a14a651060d76bd8b4 |
parent 284720 | 48fa8a92f9364a82985021ae1dfe940de09dd898 |
child 284722 | 1fff1b2ac665d640e0f2e669647aca6d2ec31dc9 |
push id | 72076 |
push user | lsalzman@mozilla.com |
push date | Thu, 18 Feb 2016 15:56:31 +0000 (2016-02-18) |
treeherder | mozilla-inbound@94f9bb9e3253 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | nical |
bugs | 1245241 |
milestone | 47.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
|
ipc/glue/SharedMemory.h | file | annotate | diff | comparison | revisions | |
ipc/glue/SharedMemorySysV.h | file | annotate | diff | comparison | revisions | |
ipc/glue/moz.build | file | annotate | diff | comparison | revisions | |
widget/gtk/nsWindow.h | file | annotate | diff | comparison | revisions | |
widget/nsShmImage.cpp | file | annotate | diff | comparison | revisions | |
widget/nsShmImage.h | file | annotate | diff | comparison | revisions |
--- a/ipc/glue/SharedMemory.h +++ b/ipc/glue/SharedMemory.h @@ -42,17 +42,16 @@ protected: { Unmapped(); Destroyed(); } public: enum SharedMemoryType { TYPE_BASIC, - TYPE_SYSV, TYPE_UNKNOWN }; size_t Size() const { return mMappedSize; } virtual void* memory() const = 0; virtual bool Create(size_t size) = 0;
deleted file mode 100644 --- a/ipc/glue/SharedMemorySysV.h +++ /dev/null @@ -1,162 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: sw=2 ts=8 et : - */ -/* 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/. */ - -#ifndef mozilla_ipc_SharedMemorySysV_h -#define mozilla_ipc_SharedMemorySysV_h - -#if (defined(OS_LINUX) && !defined(ANDROID)) || defined(OS_BSD) - -// SysV shared memory isn't available on Windows, but we define the -// following macro so that #ifdefs are clearer (compared to #ifdef -// OS_LINUX). -#define MOZ_HAVE_SHAREDMEMORYSYSV - -#include "SharedMemory.h" - -#include "nsDebug.h" - -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <string.h> -#include <sys/ipc.h> -#include <sys/shm.h> - -// -// This is a low-level wrapper around platform shared memory. Don't -// use it directly; use Shmem allocated through IPDL interfaces. -// - -namespace mozilla { -namespace ipc { - - -class SharedMemorySysV : public SharedMemoryCommon<int> -{ -public: - SharedMemorySysV() : - mHandle(-1), - mData(nullptr) - { - } - - virtual ~SharedMemorySysV() - { - shmdt(mData); - mHandle = -1; - mData = nullptr; - } - - virtual bool SetHandle(const Handle& aHandle) override - { - MOZ_ASSERT(mHandle == -1, "already initialized"); - - mHandle = aHandle; - return true; - } - - virtual bool Create(size_t aNbytes) override - { - int id = shmget(IPC_PRIVATE, aNbytes, IPC_CREAT | 0600); - if (id == -1) - return false; - - mHandle = id; - mAllocSize = aNbytes; - Created(aNbytes); - - return Map(aNbytes); - } - - virtual bool Map(size_t nBytes) override - { - // already mapped - if (mData) - return true; - - if (!IsHandleValid(mHandle)) - return false; - - void* mem = shmat(mHandle, nullptr, 0); - if (mem == (void*) -1) { - char warning[256]; - ::snprintf(warning, sizeof(warning)-1, - "shmat(): %s (%d)\n", strerror(errno), errno); - - NS_WARNING(warning); - - return false; - } - - // Mark the handle as deleted so that, should this process go away, the - // segment is cleaned up. - shmctl(mHandle, IPC_RMID, 0); - - mData = mem; - -#ifdef DEBUG - struct shmid_ds info; - if (shmctl(mHandle, IPC_STAT, &info) < 0) - return false; - - MOZ_ASSERT(nBytes <= info.shm_segsz, - "Segment doesn't have enough space!"); -#endif - - Mapped(nBytes); - return true; - } - - virtual void* memory() const override - { - return mData; - } - - virtual SharedMemoryType Type() const override - { - return TYPE_SYSV; - } - - Handle GetHandle() const - { - MOZ_ASSERT(IsHandleValid(mHandle), "invalid handle"); - return mHandle; - } - - static Handle NULLHandle() - { - return -1; - } - - virtual bool IsHandleValid(const Handle& aHandle) const override - { - return aHandle != -1; - } - - virtual void CloseHandle() override - { - } - - virtual bool ShareToProcess(base::ProcessId aProcessId, Handle* aHandle) override { - if (mHandle == -1) { - return false; - } - *aHandle = mHandle; - return true; - } - -private: - Handle mHandle; - void* mData; -}; - -} // namespace ipc -} // namespace mozilla - -#endif // OS_LINUX - -#endif // ifndef mozilla_ipc_SharedMemorySysV_h
--- a/ipc/glue/moz.build +++ b/ipc/glue/moz.build @@ -26,17 +26,16 @@ EXPORTS.mozilla.ipc += [ 'MessageChannel.h', 'MessageLink.h', 'Neutering.h', 'ProcessChild.h', 'ProtocolUtils.h', 'ScopedXREEmbed.h', 'SharedMemory.h', 'SharedMemoryBasic.h', - 'SharedMemorySysV.h', 'Shmem.h', 'Transport.h', 'URIUtils.h', 'WindowsMessageLoop.h', ] if CONFIG['OS_ARCH'] == 'WINNT': DEFINES['WEBRTC_WIN'] = True
--- a/widget/gtk/nsWindow.h +++ b/widget/gtk/nsWindow.h @@ -3,18 +3,16 @@ */ /* 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/. */ #ifndef __nsWindow_h__ #define __nsWindow_h__ -#include "mozilla/ipc/SharedMemorySysV.h" - #include "nsAutoPtr.h" #include "mozcontainer.h" #include "nsIDragService.h" #include "nsITimer.h" #include "nsGkAtoms.h" #include "nsRefPtrHashtable.h" @@ -22,16 +20,18 @@ #include "nsBaseWidget.h" #include <gdk/gdk.h> #include <gtk/gtk.h> #ifdef MOZ_X11 #include <gdk/gdkx.h> #endif /* MOZ_X11 */ +#include "nsShmImage.h" + #ifdef ACCESSIBILITY #include "mozilla/a11y/Accessible.h" #endif #include "mozilla/EventForwards.h" #include "mozilla/TouchEvents.h" #include "IMContextWrapper.h" @@ -59,20 +59,16 @@ extern PRLogModuleInfo *gWidgetDrawLog; #define LOGDRAG(args) #define LOGDRAW(args) #endif /* MOZ_LOGGING */ class gfxASurface; class gfxPattern; class nsPluginNativeWindowGtk; -#if defined(MOZ_X11) && defined(MOZ_HAVE_SHAREDMEMORYSYSV) -# define MOZ_HAVE_SHMIMAGE -class nsShmImage; -#endif namespace mozilla { class TimeStamp; class CurrentX11TimeGetter; } class nsWindow : public nsBaseWidget {
--- a/widget/nsShmImage.cpp +++ b/widget/nsShmImage.cpp @@ -12,16 +12,24 @@ #endif #include "nsShmImage.h" #ifdef MOZ_WIDGET_GTK #include "gfxPlatformGtk.h" #endif #ifdef MOZ_HAVE_SHMIMAGE +#include "mozilla/X11Util.h" + +#include "mozilla/ipc/SharedMemory.h" + +#include <errno.h> +#include <string.h> +#include <sys/ipc.h> +#include <sys/shm.h> 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() @@ -40,102 +48,153 @@ static int TrapShmError(Display* aDisplay, XErrorEvent* aEvent) { // store the error code and ignore the error gShmError = aEvent->error_code; return 0; } #endif -already_AddRefed<nsShmImage> -nsShmImage::Create(const LayoutDeviceIntSize& aSize, - Display* aDisplay, Visual* aVisual, unsigned int aDepth) +bool +nsShmImage::CreateShmSegment() { - RefPtr<nsShmImage> shm = new nsShmImage(); - shm->mDisplay = aDisplay; - shm->mImage = XShmCreateImage(aDisplay, aVisual, aDepth, - ZPixmap, nullptr, - &(shm->mInfo), - aSize.width, aSize.height); - if (!shm->mImage) { - return nullptr; - } + if (!mImage) { + return false; + } + + 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; + } - size_t size = SharedMemory::PageAlignedSize( - shm->mImage->bytes_per_line * shm->mImage->height); - shm->mSegment = new SharedMemorySysV(); - if (!shm->mSegment->Create(size) || !shm->mSegment->Map(size)) { - return nullptr; - } - - shm->mInfo.shmid = shm->mSegment->GetHandle(); - shm->mInfo.shmaddr = - shm->mImage->data = static_cast<char*>(shm->mSegment->memory()); - shm->mInfo.readOnly = False; + mInfo.shmaddr = (char *)shmat(mInfo.shmid, nullptr, 0); + if (mInfo.shmaddr == (void *)-1) { + nsPrintfCString warning("shmat(): %s (%d)\n", strerror(errno), errno); + NS_WARNING(warning.get()); + return false; + } -#if defined(MOZ_WIDGET_GTK) - gShmError = 0; - XErrorHandler previousHandler = XSetErrorHandler(TrapShmError); - Status attachOk = XShmAttach(aDisplay, &shm->mInfo); - XSync(aDisplay, False); - XSetErrorHandler(previousHandler); - if (gShmError) { - attachOk = 0; - } -#elif defined(MOZ_WIDGET_QT) - Status attachOk = XShmAttach(aDisplay, &shm->mInfo); + // 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!"); #endif - if (!attachOk) { - // Assume XShm isn't available, and don't attempt to use it - // again. - gShmAvailable = false; - return nullptr; - } + mInfo.readOnly = False; + + mImage->data = mInfo.shmaddr; + + return true; +} + +void +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) +{ + mDisplay = aDisplay; + mImage = XShmCreateImage(aDisplay, aVisual, aDepth, + ZPixmap, nullptr, + &mInfo, + aSize.width, aSize.height); + if (!mImage || !CreateShmSegment()) { + return false; + } + +#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 - shm->mXAttached = true; - shm->mSize = aSize; - switch (shm->mImage->depth) { - case 32: - if ((shm->mImage->red_mask == 0xff0000) && - (shm->mImage->green_mask == 0xff00) && - (shm->mImage->blue_mask == 0xff)) { - shm->mFormat = SurfaceFormat::B8G8R8A8; - memset(shm->mSegment->memory(), 0, size); - break; - } - goto unsupported; - case 24: - // Only xRGB is supported. - if ((shm->mImage->red_mask == 0xff0000) && - (shm->mImage->green_mask == 0xff00) && - (shm->mImage->blue_mask == 0xff)) { - shm->mFormat = SurfaceFormat::B8G8R8X8; - memset(shm->mSegment->memory(), 0xFF, size); - break; - } - goto unsupported; - case 16: - shm->mFormat = SurfaceFormat::R5G6B5_UINT16; - memset(shm->mSegment->memory(), 0, size); - break; - unsupported: - default: - NS_WARNING("Unsupported XShm Image format!"); - gShmAvailable = false; - return nullptr; + 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) { + case 32: + if ((mImage->red_mask == 0xff0000) && + (mImage->green_mask == 0xff00) && + (mImage->blue_mask == 0xff)) { + mFormat = SurfaceFormat::B8G8R8A8; + memset(mImage->data, 0, mImage->bytes_per_line * mImage->height); + } + break; + case 24: + // Only xRGB is supported. + if ((mImage->red_mask == 0xff0000) && + (mImage->green_mask == 0xff00) && + (mImage->blue_mask == 0xff)) { + mFormat = SurfaceFormat::B8G8R8X8; + memset(mImage->data, 0xFF, mImage->bytes_per_line * mImage->height); } - return shm.forget(); + break; + case 16: + mFormat = SurfaceFormat::R5G6B5_UINT16; + memset(mImage->data, 0, mImage->bytes_per_line * mImage->height); + break; + } + + if (mFormat == SurfaceFormat::UNKNOWN) { + NS_WARNING("Unsupported XShm Image format!"); + gShmAvailable = false; + return false; + } + + return true; +} + +nsShmImage::~nsShmImage() +{ + if (mImage) { + mozilla::FinishX(mDisplay); + if (mXAttached) { + XShmDetach(mDisplay, &mInfo); + } + XDestroyImage(mImage); + } + DestroyShmSegment(); } already_AddRefed<DrawTarget> nsShmImage::CreateDrawTarget() { return gfxPlatform::GetPlatform()->CreateDrawTargetForData( - static_cast<unsigned char*>(mSegment->memory()), + reinterpret_cast<unsigned char*>(mImage->data), mSize.ToUnknownSize(), mImage->bytes_per_line, mFormat); } #ifdef MOZ_WIDGET_GTK void nsShmImage::Put(Display* aDisplay, Drawable aWindow, @@ -184,20 +243,23 @@ nsShmImage::Put(QWindow* aWindow, QRect& } #endif 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 = nsShmImage::Create(aSize, aDisplay, aVisual, aDepth); + 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; } - return !aImage ? nullptr : aImage->CreateDrawTarget(); + } + return !aImage ? nullptr : aImage->CreateDrawTarget(); } -#endif // defined(MOZ_X11) && defined(MOZ_HAVE_SHAREDMEMORYSYSV) +#endif // MOZ_HAVE_SHMIMAGE
--- a/widget/nsShmImage.h +++ b/widget/nsShmImage.h @@ -2,66 +2,45 @@ * * 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/. */ #ifndef __mozilla_widget_nsShmImage_h__ #define __mozilla_widget_nsShmImage_h__ -#include "mozilla/ipc/SharedMemorySysV.h" - -#if defined(MOZ_X11) && defined(MOZ_HAVE_SHAREDMEMORYSYSV) +#if defined(MOZ_X11) # define MOZ_HAVE_SHMIMAGE #endif #ifdef MOZ_HAVE_SHMIMAGE #include "mozilla/gfx/2D.h" #include "nsIWidget.h" #include "nsAutoPtr.h" -#include "mozilla/X11Util.h" #include <X11/Xlib.h> -#include <X11/Xutil.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) - typedef mozilla::ipc::SharedMemorySysV SharedMemorySysV; - public: static bool UseShm(); - static already_AddRefed<nsShmImage> - Create(const mozilla::LayoutDeviceIntSize& aSize, - Display* aDisplay, Visual* aVisual, unsigned int aDepth); static already_AddRefed<mozilla::gfx::DrawTarget> EnsureShmImage(const mozilla::LayoutDeviceIntSize& aSize, Display* aDisplay, Visual* aVisual, unsigned int aDepth, RefPtr<nsShmImage>& aImage); -private: - ~nsShmImage() { - if (mImage) { - mozilla::FinishX(mDisplay); - if (mXAttached) { - XShmDetach(mDisplay, &mInfo); - } - XDestroyImage(mImage); - } - } - -public: already_AddRefed<mozilla::gfx::DrawTarget> CreateDrawTarget(); #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 @@ -69,19 +48,26 @@ public: mozilla::LayoutDeviceIntSize Size() const { return mSize; } private: nsShmImage() : mImage(nullptr) , mDisplay(nullptr) , mFormat(mozilla::gfx::SurfaceFormat::UNKNOWN) , mXAttached(false) - { mInfo.shmid = SharedMemorySysV::NULLHandle(); } + { mInfo.shmid = -1; } + + ~nsShmImage(); - RefPtr<SharedMemorySysV> mSegment; + bool CreateShmSegment(); + void DestroyShmSegment(); + + bool CreateImage(const mozilla::LayoutDeviceIntSize& aSize, + Display* aDisplay, Visual* aVisual, unsigned int aDepth); + XImage* mImage; Display* mDisplay; XShmSegmentInfo mInfo; mozilla::LayoutDeviceIntSize mSize; mozilla::gfx::SurfaceFormat mFormat; bool mXAttached; };