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 idunknown
push userunknown
push dateunknown
reviewersjones.chris.g, vladimir
bugs562285
milestone1.9.3a5pre
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