summaryrefslogtreecommitdiffstats
path: root/chrome/common/transport_dib.h
diff options
context:
space:
mode:
authoragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-02-20 02:00:04 +0000
committeragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-02-20 02:00:04 +0000
commite68e62fa169c45bd779bfe890aa4fcdaa24d267d (patch)
treeefdb18adec880e7f780d8cde4e12893d3a20234f /chrome/common/transport_dib.h
parent7fe07d0726bad485fa40150aa9f7cecb1318217e (diff)
downloadchromium_src-e68e62fa169c45bd779bfe890aa4fcdaa24d267d.zip
chromium_src-e68e62fa169c45bd779bfe890aa4fcdaa24d267d.tar.gz
chromium_src-e68e62fa169c45bd779bfe890aa4fcdaa24d267d.tar.bz2
Bitmap transport
This patch reworks bitmap transport on all platforms. Linux and Mac are switched from serialising bitmaps over the IPC channel to using shared memory. All platforms gain a shared memory mapping cache on the host side. The concept of a TransportDIB (device independent bitmap) is added to encapsulate most of the platform specifics. On Linux, we use SysV shared memory. This is because X shared pixmaps, which predate POSIX SHM, can only use SysV. By using SysV between renderer and browser, we open up the possibility to map the shared memory directly from the renderer to the X server. On Mac, we use POSIX shared memory. However, since this needs filesystem access and the Mac renderer is sandboxed from the filesystem, we add two new messages from renderer -> browser: The first, AllocTransportDIB, synchronously creates a transport DIB in the browser and passes a handle back to the renderer. The second, FreeTransportDIB, asynchronously, notifies the browser that it may close its handle to the shared memory region. On Mac, the shared memory regions are identified by their inode numbers on the wire. This means that the browser must keep handles open to all the allocated shared memory regions (since an inode number is insufficient to map the region). The alternative design is that the renderer passes the file descriptor with each paint operation. Since passing file descriptors is special case in the code, I felt that it would be best to minimise their use. Creating and freeing transport DIBs are relatively rare operations relative to paints and scrolls. On Windows, most of the code remains the same, except that Windows now uses the mapping cache added in this patch. This allows the browser to maintain a shared memory mapping for a transport DIB over several paints. Previously it mapped and unmapped for every operation, causing lots of TLB and VM churn. Review URL: http://codereview.chromium.org/21485 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@10071 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/common/transport_dib.h')
-rw-r--r--chrome/common/transport_dib.h112
1 files changed, 112 insertions, 0 deletions
diff --git a/chrome/common/transport_dib.h b/chrome/common/transport_dib.h
new file mode 100644
index 0000000..e5fc009
--- /dev/null
+++ b/chrome/common/transport_dib.h
@@ -0,0 +1,112 @@
+// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_COMMON_TRANSPORT_DIB_H_
+#define CHROME_COMMON_TRANSPORT_DIB_H_
+
+#include "base/basictypes.h"
+
+#if defined(OS_WIN) || defined(OS_MACOSX)
+#include "base/shared_memory.h"
+#endif
+
+#if defined(OS_WIN)
+#include <windows.h>
+#endif
+
+// -----------------------------------------------------------------------------
+// A TransportDIB is a block of memory that is used to transport pixels
+// from the renderer process to the browser.
+// -----------------------------------------------------------------------------
+class TransportDIB {
+ public:
+ ~TransportDIB();
+
+ // Two typedefs are defined. A Handle is the type which can be sent over
+ // the wire so that the remote side can map the transport DIB. The Id typedef
+ // is sufficient to identify the transport DIB when you know that the remote
+ // side already may have it mapped.
+#if defined(OS_WIN)
+ typedef HANDLE Handle;
+ // On Windows, the Id type includes a sequence number (epoch) to solve an ABA
+ // issue:
+ // 1) Process A creates a transport DIB with HANDLE=1 and sends to B.
+ // 2) Process B maps the transport DIB and caches 1 -> DIB.
+ // 3) Process A closes the transport DIB and creates a new one. The new DIB
+ // is also assigned HANDLE=1.
+ // 4) Process A sends the Handle to B, but B incorrectly believes that it
+ // already has it cached.
+ struct HandleAndSequenceNum {
+ HandleAndSequenceNum()
+ : handle(NULL),
+ sequence_num(0) {
+ }
+
+ HandleAndSequenceNum(HANDLE h, uint32 seq_num)
+ : handle(h),
+ sequence_num(seq_num) {
+ }
+
+ bool operator< (const HandleAndSequenceNum& other) const {
+ if (other.handle < handle)
+ return true;
+ if (other.sequence_num < sequence_num)
+ return true;
+ return false;
+ }
+
+ HANDLE handle;
+ uint32 sequence_num;
+ };
+ typedef HandleAndSequenceNum Id;
+#elif defined(OS_MACOSX)
+ typedef base::SharedMemoryHandle Handle;
+ // On Mac, the inode number of the backing file is used as an id.
+ typedef base::SharedMemoryId Id;
+#elif defined(OS_LINUX)
+ typedef int Handle; // These two ints are SysV IPC shared memory keys
+ typedef int Id;
+#endif
+
+ // Create a new TransportDIB
+ // size: the minimum size, in bytes
+ // epoch: Windows only: a global counter. See comment above.
+ // returns: NULL on failure
+ static TransportDIB* Create(size_t size, uint32 sequence_num);
+
+ // Map the referenced transport DIB. Returns NULL on failure.
+ static TransportDIB* Map(Handle transport_dib);
+
+ // Return a pointer to the shared memory
+ void* memory() const;
+
+ // Return the maximum size of the shared memory. This is not the amount of
+ // data which is valid, you have to know that via other means, this is simply
+ // the maximum amount that /could/ be valid.
+ size_t size() const { return size_; }
+
+ // Return the identifier which can be used to refer to this shared memory
+ // on the wire.
+ Id id() const;
+
+ // Return a handle to the underlying shared memory. This can be sent over the
+ // wire to give this transport DIB to another process.
+ Handle handle() const;
+
+ private:
+ TransportDIB();
+#if defined(OS_WIN) || defined(OS_MACOSX)
+ explicit TransportDIB(base::SharedMemoryHandle dib);
+ base::SharedMemory shared_memory_;
+ uint32 sequence_num_;
+#elif defined(OS_LINUX)
+ int key_; // SysV shared memory id
+ void* address_; // mapped address
+#endif
+ size_t size_; // length, in bytes
+};
+
+class MessageLoop;
+
+#endif // CHROME_COMMON_TRANSPORT_DIB_H_