Bug 562285 - Rewrite gfxSharedImageSurface class to be compatible with IPC Shmem.r=jones.chris.g, sr=vladimir
authorOleg Romashin <romaxa@gmail.com>
Thu, 13 May 2010 11:52:59 -0400
changeset 42262 8f2f03fb6a8ffd6fe4ccdd980ed910d1ff1d6e25
parent 42261 549f77777959e87a5f439902cd9787ceb8d57d2c
child 42263 7ef2a4732afe3ebc09763d3d0e2fa070328e5a5f
push id13249
push userromaxa@gmail.com
push dateThu, 13 May 2010 10:55:25 +0000
treeherdermozilla-central@8f2f03fb6a8f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjones.chris.g, vladimir
bugs562285
milestone1.9.3a5pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
Bug 562285 - Rewrite gfxSharedImageSurface class to be compatible with IPC Shmem.r=jones.chris.g, sr=vladimir
gfx/thebes/public/gfxImageSurface.h
gfx/thebes/public/gfxSharedImageSurface.h
gfx/thebes/src/Makefile.in
gfx/thebes/src/gfxImageSurface.cpp
gfx/thebes/src/gfxSharedImageSurface.cpp
ipc/chromium/Makefile.in
ipc/chromium/chromium-config.mk
--- a/gfx/thebes/public/gfxImageSurface.h
+++ b/gfx/thebes/public/gfxImageSurface.h
@@ -94,17 +94,19 @@ public:
     /**
      * Returns the total size of the image data.
      */
     PRInt32 GetDataSize() const { return mStride*mSize.height; }
 
     /* Fast copy from another image surface; returns TRUE if successful, FALSE otherwise */
     PRBool CopyFrom (gfxImageSurface *other);
 
-private:
+protected:
+    gfxImageSurface();
+    void InitFromSurface(cairo_surface_t *csurf);
     long ComputeStride() const;
 
     gfxIntSize mSize;
     PRBool mOwnsData;
     unsigned char *mData;
     gfxImageFormat mFormat;
     long mStride;
 };
--- a/gfx/thebes/public/gfxSharedImageSurface.h
+++ b/gfx/thebes/public/gfxSharedImageSurface.h
@@ -1,8 +1,9 @@
+// vim:set ts=4 sts=4 sw=4 et cin:
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
  * The contents of this file are subject to the Mozilla Public License Version
  * 1.1 (the "License"); you may not use this file except in compliance with
  * the License. You may obtain a copy of the License at
  * http://www.mozilla.org/MPL/
@@ -33,121 +34,66 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef GFX_SHARED_IMAGESURFACE_H
 #define GFX_SHARED_IMAGESURFACE_H
 
-#ifdef MOZ_X11
-#ifdef HAVE_XSHM
-
 #include "gfxASurface.h"
 #include "gfxImageSurface.h"
-#include "gfxPoint.h"
 
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef MOZ_WIDGET_QT
-#include <QX11Info>
-#endif
-
-#ifdef MOZ_WIDGET_GTK2
-#include <gtk/gtk.h>
-#include <gdk/gdk.h>
-#include <gdk/gdkx.h>
-#endif
-
-#ifdef MOZ_X11
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/extensions/XShm.h>
-#endif
+#include "mozilla/ipc/SharedMemory.h"
+#include "mozilla/ipc/Shmem.h"
 
-#include <sys/ipc.h>
-#include <sys/shm.h>
-
-class THEBES_API gfxSharedImageSurface : public gfxASurface {
+class THEBES_API gfxSharedImageSurface : public gfxImageSurface {
 public:
-  gfxSharedImageSurface();
-  ~gfxSharedImageSurface();
+    /**
+     * Init must be called after ctor
+     */
+    gfxSharedImageSurface();
 
-  // ImageSurface methods
-  gfxImageFormat Format() const { return mFormat; }
+    /**
+     * Create shared image from external Shmem
+     * Shmem must be initialized by this class
+     */
+    gfxSharedImageSurface(const mozilla::ipc::Shmem &aShmem);
 
-  const gfxIntSize& GetSize() const { return mSize; }
-  int Width() const { return mSize.width; }
-  int Height() const { return mSize.height; }
-
-  /**
-   * Distance in bytes between the start of a line and the start of the
-   * next line.
-   */
-  int Stride() const { return mStride; }
+    ~gfxSharedImageSurface();
 
-  /**
-   * Returns a pointer for the image data. Users of this function can
-   * write to it, but must not attempt to free the buffer.
-   */
-  unsigned char* Data() const { return mData; } // delete this data under us and die.
-
-  /**
-   * Returns the total size of the image data.
-   */
-  int GetDataSize() const { return mStride*mSize.height; }
-
-  /**
-   * Returns a pointer for the X-image structure.
-   */
-  XImage *image() const { return mXShmImage; }
-
-  /**
-   * Returns a gfxImageSurface as gfxASurface.
-   */
-  already_AddRefed<gfxASurface> getASurface(void);
+    /**
+     * Initialize shared image surface
+     * @param aAllocator The pointer to protocol class which has AllocShmem method
+     * @param aSize The size of the buffer
+     * @param aFormat Format of the data
+     * @see gfxImageFormat
+     */
+    template<class ShmemAllocator>
+    bool Init(ShmemAllocator *aAllocator,
+              const gfxIntSize& aSize,
+              gfxImageFormat aFormat,
+              mozilla::ipc::SharedMemory::SharedMemoryType aShmType = mozilla::ipc::SharedMemory::TYPE_BASIC)
+    {
+        mSize = aSize;
+        mFormat = aFormat;
+        mStride = ComputeStride();
+        if (!aAllocator->AllocShmem(GetAlignedSize(),
+                                    aShmType, &mShmem))
+            return false;
 
-  /**
-   * Construct an shared image surface and XImage
-   * @param aSize The size of the buffer
-   * @param aFormat Format of the data
-   * @see gfxImageFormat
-   * @param aShmId Shared Memory ID of data created outside,
-   *                if not specified, then class will allocate own shared memory
-   * @display aDisplay display used for X-Image creation
-   *                if not specified, then used system default
-   *
-   */
-  bool Init(const gfxIntSize& aSize,
-            gfxImageFormat aFormat = ImageFormatUnknown,
-            int aDepth = 0,
-            int aShmId = -1);
+        return InitSurface(PR_TRUE);
+    }
 
-  /**
-   * Returns the depth of image surface 
-  */
-  int Depth() const { return mDepth; }
+    /* Gives Shmem data, which can be passed to IPDL interfaces */
+    mozilla::ipc::Shmem& GetShmem() { return mShmem; }
+
+    // This can be used for recognizing normal gfxImageSurface as SharedImage
+    static cairo_user_data_key_t SHM_KEY;
 
 private:
-  bool CreateInternal(int aShmid);
-  long ComputeStride() const;
-  inline bool ComputeDepth();
-  inline bool ComputeFormat();
-
-  unsigned int     mDepth;
-  int              mShmId;
+    size_t GetAlignedSize();
+    bool InitSurface(PRBool aUpdateShmemInfo);
 
-  gfxIntSize mSize;
-  bool mOwnsData;
-
-  unsigned char   *mData;
-  gfxImageFormat   mFormat;
-  long mStride;
-
-  Display *mDisp;
-  XShmSegmentInfo  mShmInfo;
-  XImage          *mXShmImage;
+    mozilla::ipc::Shmem mShmem;
 };
 
-#endif /* HAVE_XSHM */
-#endif /* MOZ_X11 */
 #endif /* GFX_SHARED_IMAGESURFACE_H */
--- a/gfx/thebes/src/Makefile.in
+++ b/gfx/thebes/src/Makefile.in
@@ -220,16 +220,19 @@ CMMSRCS += GLContextProviderCGL.mm
 else
 CPPSRCS += GLContextProviderNull.cpp
 endif
 endif
 
 DEFINES += -DIMPL_THEBES -DWOFF_MOZILLA_CLIENT
 
 include $(topsrcdir)/config/rules.mk
+include $(topsrcdir)/ipc/chromium/chromium-config.mk
+
+DEFINES := $(filter-out -DUNICODE,$(DEFINES))
 
 CXXFLAGS += $(MOZ_CAIRO_CFLAGS) $(TK_CFLAGS)
 CFLAGS += $(MOZ_CAIRO_CFLAGS) $(TK_CFLAGS)
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
 ifdef WINCE
 CXXFLAGS += $(CAIRO_FT_CFLAGS)
 endif
--- a/gfx/thebes/src/gfxImageSurface.cpp
+++ b/gfx/thebes/src/gfxImageSurface.cpp
@@ -36,16 +36,37 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "prmem.h"
 
 #include "gfxImageSurface.h"
 
 #include "cairo.h"
 
+gfxImageSurface::gfxImageSurface()
+  : mSize(0, 0),
+    mOwnsData(PR_FALSE),
+    mFormat(ImageFormatUnknown),
+    mStride(0)
+{
+}
+
+void
+gfxImageSurface::InitFromSurface(cairo_surface_t *csurf)
+{
+    mSize.width = cairo_image_surface_get_width(csurf);
+    mSize.height = cairo_image_surface_get_height(csurf);
+    mData = cairo_image_surface_get_data(csurf);
+    mFormat = (gfxImageFormat) cairo_image_surface_get_format(csurf);
+    mOwnsData = PR_FALSE;
+    mStride = cairo_image_surface_get_stride(csurf);
+
+    Init(csurf, PR_TRUE);
+}
+
 gfxImageSurface::gfxImageSurface(unsigned char *aData, const gfxIntSize& aSize,
                                  long aStride, gfxImageFormat aFormat)
   : mSize(aSize)
   , mOwnsData(PR_FALSE)
   , mData(aData)
   , mFormat(aFormat)
   , mStride(aStride)
 {
--- a/gfx/thebes/src/gfxSharedImageSurface.cpp
+++ b/gfx/thebes/src/gfxSharedImageSurface.cpp
@@ -1,8 +1,9 @@
+// vim:set ts=4 sts=4 sw=4 et cin:
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
  * The contents of this file are subject to the Mozilla Public License Version
  * 1.1 (the "License"); you may not use this file except in compliance with
  * the License. You may obtain a copy of the License at
  * http://www.mozilla.org/MPL/
@@ -30,217 +31,89 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
+#include "base/basictypes.h"
 #include "gfxSharedImageSurface.h"
-#include <stdio.h>
+#include "cairo.h"
+
+#define MOZ_ALIGN_WORD(x) (((x) + 3) & ~3)
+
+using mozilla::ipc::SharedMemory;
+
+cairo_user_data_key_t gfxSharedImageSurface::SHM_KEY;
 
-#ifdef MOZ_X11
-#ifdef HAVE_XSHM
+typedef struct _SharedImageInfo
+{
+    PRInt32 width;
+    PRInt32 height;
+    PRInt32 format;
+} SharedImageInfo;
+
+static SharedImageInfo*
+GetShmInfoPtr(const mozilla::ipc::Shmem &aShmem)
+{
+    return reinterpret_cast<SharedImageInfo*>
+        (aShmem.get<char>() + aShmem.Size<char>() - sizeof(SharedImageInfo));
+}
+
+size_t
+gfxSharedImageSurface::GetAlignedSize()
+{
+   return MOZ_ALIGN_WORD(sizeof(SharedImageInfo) + mSize.height * mStride);
+}
 
-gfxSharedImageSurface::gfxSharedImageSurface()
- : mDepth(0),
-   mShmId(0),
-   mOwnsData(true),
-   mData(NULL),
-   mStride(0),
-   mXShmImage(NULL)
+bool
+gfxSharedImageSurface::InitSurface(PRBool aUpdateShmemInfo)
 {
-    memset(&mShmInfo, 0, sizeof(XShmSegmentInfo));
+    if (!CheckSurfaceSize(mSize))
+        return false;
+
+    cairo_surface_t *surface =
+        cairo_image_surface_create_for_data(mShmem.get<unsigned char>(),
+                                            (cairo_format_t)mFormat,
+                                            mSize.width,
+                                            mSize.height,
+                                            mStride);
+
+    if (!surface)
+        return false;
+
+    cairo_surface_set_user_data(surface,
+                                &gfxSharedImageSurface::SHM_KEY,
+                                this, NULL);
+
+    if (aUpdateShmemInfo) {
+        SharedImageInfo *shmInfo = GetShmInfoPtr(mShmem);
+        shmInfo->width = mSize.width;
+        shmInfo->height = mSize.height;
+        shmInfo->format = mFormat;
+    }
+
+    InitFromSurface(surface);
+    return true;
 }
 
 gfxSharedImageSurface::~gfxSharedImageSurface()
 {
-    // Finish all pending XServer operations
-    if (mDisp) {
-        XSync(mDisp, False);
-        if (mShmInfo.shmaddr)
-            XShmDetach(mDisp, &mShmInfo);
-        mShmInfo.shmaddr = nsnull;
-    }
-
-    if (mData)
-        shmdt(mData);
-
-    if (mXShmImage)
-        XDestroyImage(mXShmImage);
 }
 
-already_AddRefed<gfxASurface>
-gfxSharedImageSurface::getASurface(void)
+gfxSharedImageSurface::gfxSharedImageSurface()
 {
-    NS_ENSURE_TRUE(mData, NULL);
-
-    gfxASurface::gfxImageFormat imageFormat = gfxASurface::ImageFormatRGB24;
-    if (mDepth == 32)
-        imageFormat = gfxASurface::ImageFormatARGB32;
-
-    gfxASurface* result = new gfxImageSurface(mData, mSize, mStride, imageFormat);
-    NS_IF_ADDREF(result);
-    return result;
-}
-
-#ifdef MOZ_WIDGET_QT
-static unsigned int
-getSystemDepth()
-{
-    return QX11Info::appDepth();
 }
 
-static Display*
-getSystemDisplay()
-{
-    return QX11Info::display();
-}
-#endif
-#ifdef MOZ_WIDGET_GTK2
-static unsigned int
-getSystemDepth()
-{
-    return gdk_visual_get_system()->depth;
-}
-
-static Display*
-getSystemDisplay()
-{
-    return GDK_DISPLAY();
-}
-#endif
-
-
-
-bool
-gfxSharedImageSurface::Init(const gfxIntSize& aSize,
-                            gfxImageFormat aFormat,
-                            int aDepth,
-                            int aShmId)
+gfxSharedImageSurface::gfxSharedImageSurface(const mozilla::ipc::Shmem &aShmem)
 {
-    mSize = aSize;
-
-    if (aFormat != ImageFormatUnknown) {
-        mFormat = aFormat;
-        if (!ComputeDepth())
-            return false;
-    } else if (aDepth) {
-        mDepth = aDepth;
-        if (!ComputeFormat())
-            NS_WARNING("Will work with system depth");
-    } else {
-        mDepth = getSystemDepth();
-        if (!ComputeFormat())
-            NS_WARNING("Will work with system depth");
-    }
-
-    mDisp = getSystemDisplay();
-    if (!mDisp)
-        return false;
-
-    return CreateInternal(aShmId);
-}
-
-bool
-gfxSharedImageSurface::CreateInternal(int aShmid)
-{
-    memset(&mShmInfo, 0, sizeof(mShmInfo));
-
+    mShmem = aShmem;
+    SharedImageInfo *shmInfo = GetShmInfoPtr(aShmem);
+    mSize.width = shmInfo->width;
+    mSize.height = shmInfo->height;
+    mFormat = (gfxImageFormat)shmInfo->format;
     mStride = ComputeStride();
 
-    if (aShmid != -1) {
-        mShmId = aShmid;
-        mOwnsData = false;
-    } else
-        mShmId = shmget(IPC_PRIVATE, GetDataSize(), IPC_CREAT | 0600);
-
-    if (mShmId == -1)
-        return false;
-
-    void *data = shmat(mShmId, 0, 0);
-    shmctl(mShmId, IPC_RMID, 0);
-    if (data == (void *)-1)
-        return false;
-    mData = (unsigned char *)data;
-
-    mXShmImage = XShmCreateImage(mDisp, NULL,
-                                 mDepth, ZPixmap,
-                                 NULL, &mShmInfo,
-                                 mSize.width,
-                                 mSize.height);
-    if (!mXShmImage)
-        return false;
-    mShmInfo.shmid = mShmId;
-
-    if (mStride != mXShmImage->bytes_per_line) {
-        NS_WARNING("XStride and gfxSharedImageSurface calculated stride does not match");
-        return false;
-    }
-
-    mShmInfo.shmaddr = mXShmImage->data = (char*)data;
-    mShmInfo.readOnly = False;
-    if (!XShmAttach(mDisp, &mShmInfo))
-        return false;
-
-    return true;
+    if (!InitSurface(PR_FALSE))
+        NS_RUNTIMEABORT("Shared memory is bad");
 }
-
-bool
-gfxSharedImageSurface::ComputeFormat()
-{
-    if (mDepth == 32)
-        mFormat = ImageFormatARGB32;
-    if (mDepth == 24)
-        mFormat = ImageFormatRGB24;
-    else {
-        NS_WARNING("Unknown depth specified to gfxSharedImageSurface!");
-        mFormat = ImageFormatUnknown;
-        return false;
-    }
-
-    return true;
-}
-
-bool
-gfxSharedImageSurface::ComputeDepth()
-{
-    mDepth = 0;
-    if (mFormat == ImageFormatARGB32)
-        mDepth = 32;
-    else if (mFormat == ImageFormatRGB24)
-        mDepth = 24;
-    else {
-        NS_WARNING("Unknown format specified to gfxSharedImageSurface!");
-        return false;
-    }
-
-    return true;
-}
-
-long
-gfxSharedImageSurface::ComputeStride() const
-{
-    long stride;
-
-    if (mDepth == 16)
-        stride = mSize.width * 2;
-    else if (mFormat == ImageFormatARGB32)
-        stride = mSize.width * 4;
-    else if (mFormat == ImageFormatRGB24)
-        stride = mSize.width * 4;
-    else if (mFormat == ImageFormatA8)
-        stride = mSize.width;
-    else if (mFormat == ImageFormatA1) {
-        stride = (mSize.width + 7) / 8;
-    } else {
-        NS_WARNING("Unknown format specified to gfxImageSurface!");
-        stride = mSize.width * 4;
-    }
-
-    stride = ((stride + 3) / 4) * 4;
-
-    return stride;
-}
-
-#endif /* HAVE_XSHM */
-#endif /* MOZ_X11 */
--- a/ipc/chromium/Makefile.in
+++ b/ipc/chromium/Makefile.in
@@ -319,15 +319,17 @@ endif # }
 
 ifneq (86,$(findstring 86,$(OS_TEST))) # {
 ifneq (arm,$(findstring arm,$(OS_TEST))) # {
 # Use mutex-backed atomics
 CPPSRCS += atomicops_internals_mutex.cc
 endif # }
 endif # }
 
+OS_CXXFLAGS += $(TK_CFLAGS)
+
 include $(topsrcdir)/config/rules.mk
 
 ifdef MOZ_NATIVE_LIBEVENT # {
 export::
 	mkdir -p $(DIST)/third_party/libevent
 	echo "#include <event.h>" > $(DIST)/third_party/libevent/event.h
 endif # }
--- a/ipc/chromium/chromium-config.mk
+++ b/ipc/chromium/chromium-config.mk
@@ -101,15 +101,12 @@ OS_POSIX = 1
 DEFINES += \
   -DOS_LINUX=1 \
   -DOS_POSIX=1 \
   $(NULL)
 
 # NB: to stop gcc warnings about exporting template instantiation
 OS_CXXFLAGS := $(filter-out -pedantic,$(OS_CXXFLAGS))
 
-OS_CXXFLAGS += $(TK_CFLAGS)
-OS_CFLAGS += $(TK_CFLAGS)
-
 endif # }
 endif # }
 
 endif # }
\ No newline at end of file