From cb75116ab624dd0df65508653119afdc081e7800 Mon Sep 17 00:00:00 2001 From: "cevans@chromium.org" Date: Fri, 5 Apr 2013 20:50:42 +0000 Subject: Simplify the transport dib situation across our various platforms, as a pre-cursor to moving Chrome OS + Aura away from legacy GTK+X11 dibs. Now, we have just: - Windows style dibs - POSIX style dibs - Legacy GTK+X11 style dibs. There's some ifdef hoops that will be removed in a follow-up CL when Chrome OS + Aura will be moved away from legacy GTK+X11 dibs and on to POSIX dibs. BUG=147622 Review URL: https://codereview.chromium.org/13582008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@192629 0039d316-1c4b-4281-b951-d872f2087c98 --- ui/surface/surface.gyp | 5 +- ui/surface/transport_dib.h | 40 ++++----- ui/surface/transport_dib_android.cc | 92 -------------------- ui/surface/transport_dib_linux.cc | 155 ---------------------------------- ui/surface/transport_dib_mac.cc | 97 --------------------- ui/surface/transport_dib_posix.cc | 118 ++++++++++++++++++++++++++ ui/surface/transport_dib_sysvipc.cc | 162 ++++++++++++++++++++++++++++++++++++ 7 files changed, 297 insertions(+), 372 deletions(-) delete mode 100644 ui/surface/transport_dib_android.cc delete mode 100644 ui/surface/transport_dib_linux.cc delete mode 100644 ui/surface/transport_dib_mac.cc create mode 100644 ui/surface/transport_dib_posix.cc create mode 100644 ui/surface/transport_dib_sysvipc.cc (limited to 'ui/surface') diff --git a/ui/surface/surface.gyp b/ui/surface/surface.gyp index cc4aa6b..d64972d 100644 --- a/ui/surface/surface.gyp +++ b/ui/surface/surface.gyp @@ -81,9 +81,8 @@ 'surface_switches.cc', 'transport_dib.h', 'transport_dib.cc', - 'transport_dib_android.cc', - 'transport_dib_linux.cc', - 'transport_dib_mac.cc', + 'transport_dib_posix.cc', + 'transport_dib_sysvipc.cc', 'transport_dib_win.cc', ], 'defines': [ diff --git a/ui/surface/transport_dib.h b/ui/surface/transport_dib.h index a9d17d4..9057bb6 100644 --- a/ui/surface/transport_dib.h +++ b/ui/surface/transport_dib.h @@ -8,13 +8,13 @@ #include "base/basictypes.h" #include "ui/surface/surface_export.h" -#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_ANDROID) +#if !defined(TOOLKIT_GTK) #include "base/memory/shared_memory.h" #endif #if defined(OS_WIN) #include -#elif defined(USE_X11) +#elif defined(TOOLKIT_GTK) || (defined(OS_LINUX) && defined(USE_AURA)) #include "ui/base/x/x11_util.h" #endif @@ -80,22 +80,7 @@ class SURFACE_EXPORT TransportDIB { static int fake_handle = 10; return reinterpret_cast(fake_handle++); } -#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; - - // Returns a default, invalid handle, that is meant to indicate a missing - // Transport DIB. - static Handle DefaultHandleValue() { return Handle(); } - - // Returns a value that is ONLY USEFUL FOR TESTS WHERE IT WON'T BE - // ACTUALLY USED AS A REAL HANDLE. - static Handle GetFakeHandleForTest() { - static int fake_handle = 10; - return Handle(fake_handle++, false); - } -#elif defined(USE_X11) +#elif defined(TOOLKIT_GTK) || (defined(OS_LINUX) && defined(USE_AURA)) typedef int Handle; // These two ints are SysV IPC shared memory keys struct Id { // Ensure that default initialized Ids are invalid. @@ -123,9 +108,14 @@ class SURFACE_EXPORT TransportDIB { static int fake_handle = 10; return fake_handle++; } -#elif defined(OS_ANDROID) +#else // OS_POSIX typedef base::SharedMemoryHandle Handle; + // On POSIX, the inode number of the backing file is used as an id. +#if defined(OS_ANDROID) typedef base::SharedMemoryHandle Id; +#else + typedef base::SharedMemoryId Id; +#endif // Returns a default, invalid handle, that is meant to indicate a missing // Transport DIB. @@ -196,7 +186,7 @@ class SURFACE_EXPORT TransportDIB { // wire to give this transport DIB to another process. Handle handle() const; -#if defined(USE_X11) +#if defined(TOOLKIT_GTK) || (defined(OS_LINUX) && defined(USE_AURA)) // Map the shared memory into the X server and return an id for the shared // segment. XID MapToX(Display* connection); @@ -217,17 +207,17 @@ class SURFACE_EXPORT TransportDIB { // Verifies that the dib can hold a canvas of the requested dimensions. bool VerifyCanvasSize(int w, int h); -#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_ANDROID) - explicit TransportDIB(base::SharedMemoryHandle dib); - base::SharedMemory shared_memory_; - uint32 sequence_num_; -#elif defined(USE_X11) +#if defined(TOOLKIT_GTK) || (defined(OS_LINUX) && defined(USE_AURA)) Id key_; // SysV shared memory id void* address_; // mapped address XSharedMemoryId x_shm_; // X id for the shared segment Display* display_; // connection to the X server size_t inflight_counter_; // How many requests to the X server are in flight bool detached_; // If true, delete the transport DIB when it is idle +#else + explicit TransportDIB(base::SharedMemoryHandle dib); + base::SharedMemory shared_memory_; + uint32 sequence_num_; #endif size_t size_; // length, in bytes diff --git a/ui/surface/transport_dib_android.cc b/ui/surface/transport_dib_android.cc deleted file mode 100644 index 310f3f3..0000000 --- a/ui/surface/transport_dib_android.cc +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) 2012 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. - -#include "ui/surface/transport_dib.h" - -#include -#include - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/shared_memory.h" -#include "base/posix/eintr_wrapper.h" -#include "skia/ext/platform_canvas.h" - -TransportDIB::TransportDIB() - : size_(0) { -} - -TransportDIB::TransportDIB(TransportDIB::Handle dib) - : shared_memory_(dib, false /* read write */), - size_(0) { -} - -TransportDIB::~TransportDIB() { -} - -// static -TransportDIB* TransportDIB::Create(size_t size, uint32 sequence_num) { - TransportDIB* dib = new TransportDIB; - // We will use ashmem_get_size_region() to figure out the size in Map(size). - if (!dib->shared_memory_.CreateAndMapAnonymous(size)) { - delete dib; - return NULL; - } - - dib->size_ = size; - return dib; -} - -// static -TransportDIB* TransportDIB::Map(Handle handle) { - scoped_ptr dib(CreateWithHandle(handle)); - if (!dib->Map()) - return NULL; - return dib.release(); -} - -// static -TransportDIB* TransportDIB::CreateWithHandle(Handle handle) { - return new TransportDIB(handle); -} - -// static -bool TransportDIB::is_valid_handle(Handle dib) { - return dib.fd >= 0; -} - -// static -bool TransportDIB::is_valid_id(Id id) { - // Same as is_valid_handle(). - return id.fd >= 0; -} - -skia::PlatformCanvas* TransportDIB::GetPlatformCanvas(int w, int h) { - if ((!memory() && !Map()) || !VerifyCanvasSize(w, h)) - return NULL; - return skia::CreatePlatformCanvas(w, h, true, - reinterpret_cast(memory()), - skia::RETURN_NULL_ON_FAILURE); -} - -bool TransportDIB::Map() { - if (!is_valid_handle(handle()) || !shared_memory_.Map(0)) - return false; - - size_ = shared_memory_.mapped_size(); - return true; -} - -void* TransportDIB::memory() const { - return shared_memory_.memory(); -} - -TransportDIB::Id TransportDIB::id() const { - // Use FileDescriptor as id. - return shared_memory_.handle(); -} - -TransportDIB::Handle TransportDIB::handle() const { - return shared_memory_.handle(); -} diff --git a/ui/surface/transport_dib_linux.cc b/ui/surface/transport_dib_linux.cc deleted file mode 100644 index 1e8d8fa..0000000 --- a/ui/surface/transport_dib_linux.cc +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright (c) 2012 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. - -#include "ui/surface/transport_dib.h" - -#include -#include -#include -#include - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "skia/ext/platform_canvas.h" -#include "ui/base/x/x11_util.h" -#include "ui/gfx/size.h" - -// The shmat system call uses this as it's invalid return address -static void *const kInvalidAddress = (void*) -1; - -TransportDIB::TransportDIB() - : address_(kInvalidAddress), - x_shm_(0), - display_(NULL), - inflight_counter_(0), - detached_(false), - size_(0) { -} - -TransportDIB::~TransportDIB() { - if (address_ != kInvalidAddress) { - shmdt(address_); - address_ = kInvalidAddress; - } - - if (x_shm_) { - DCHECK(display_); - ui::DetachSharedMemory(display_, x_shm_); - } -} - -// static -TransportDIB* TransportDIB::Create(size_t size, uint32 sequence_num) { - const int shmkey = shmget(IPC_PRIVATE, size, 0600); - if (shmkey == -1) { - DLOG(ERROR) << "Failed to create SysV shared memory region" - << " errno:" << errno; - return NULL; - } else { - VLOG(1) << "Created SysV shared memory region " << shmkey; - } - - void* address = shmat(shmkey, NULL /* desired address */, 0 /* flags */); - // Here we mark the shared memory for deletion. Since we attached it in the - // line above, it doesn't actually get deleted but, if we crash, this means - // that the kernel will automatically clean it up for us. - shmctl(shmkey, IPC_RMID, 0); - if (address == kInvalidAddress) - return NULL; - - TransportDIB* dib = new TransportDIB; - - dib->key_.shmkey = shmkey; - dib->address_ = address; - dib->size_ = size; - return dib; -} - -// static -TransportDIB* TransportDIB::Map(Handle handle) { - scoped_ptr dib(CreateWithHandle(handle)); - if (!dib->Map()) - return NULL; - return dib.release(); -} - -// static -TransportDIB* TransportDIB::CreateWithHandle(Handle shmkey) { - TransportDIB* dib = new TransportDIB; - dib->key_.shmkey = shmkey; - return dib; -} - -// static -bool TransportDIB::is_valid_handle(Handle dib) { - return dib >= 0; -} - -// static -bool TransportDIB::is_valid_id(Id id) { - return id.shmkey != -1; -} - -skia::PlatformCanvas* TransportDIB::GetPlatformCanvas(int w, int h) { - if ((address_ == kInvalidAddress && !Map()) || !VerifyCanvasSize(w, h)) - return NULL; - return skia::CreatePlatformCanvas(w, h, true, - reinterpret_cast(memory()), - skia::RETURN_NULL_ON_FAILURE); -} - -bool TransportDIB::Map() { - if (!is_valid_id(key_)) - return false; - if (address_ != kInvalidAddress) - return true; - - struct shmid_ds shmst; - if (shmctl(key_.shmkey, IPC_STAT, &shmst) == -1) - return false; - - void* address = shmat(key_.shmkey, NULL /* desired address */, 0 /* flags */); - if (address == kInvalidAddress) - return false; - - address_ = address; - size_ = shmst.shm_segsz; - return true; -} - -void* TransportDIB::memory() const { - DCHECK_NE(address_, kInvalidAddress); - return address_; -} - -TransportDIB::Id TransportDIB::id() const { - return key_; -} - -TransportDIB::Handle TransportDIB::handle() const { - return key_.shmkey; -} - -XID TransportDIB::MapToX(Display* display) { - if (!x_shm_) { - x_shm_ = ui::AttachSharedMemory(display, key_.shmkey); - display_ = display; - } - - return x_shm_; -} - -void TransportDIB::DecreaseInFlightCounter() { - CHECK(inflight_counter_); - inflight_counter_--; - if (!inflight_counter_ && detached_) - delete this; -} - -void TransportDIB::Detach() { - CHECK(!detached_); - detached_ = true; - if (!inflight_counter_) - delete this; -} diff --git a/ui/surface/transport_dib_mac.cc b/ui/surface/transport_dib_mac.cc deleted file mode 100644 index 5e30f2b..0000000 --- a/ui/surface/transport_dib_mac.cc +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) 2012 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. - -#include "ui/surface/transport_dib.h" - -#include -#include - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/shared_memory.h" -#include "base/posix/eintr_wrapper.h" -#include "skia/ext/platform_canvas.h" - -TransportDIB::TransportDIB() - : size_(0) { -} - -TransportDIB::TransportDIB(TransportDIB::Handle dib) - : shared_memory_(dib, false /* read write */), - size_(0) { -} - -TransportDIB::~TransportDIB() { -} - -// static -TransportDIB* TransportDIB::Create(size_t size, uint32 sequence_num) { - TransportDIB* dib = new TransportDIB; - if (!dib->shared_memory_.CreateAndMapAnonymous(size)) { - delete dib; - return NULL; - } - - dib->size_ = size; - return dib; -} - -// static -TransportDIB* TransportDIB::Map(Handle handle) { - scoped_ptr dib(CreateWithHandle(handle)); - if (!dib->Map()) - return NULL; - return dib.release(); -} - -// static -TransportDIB* TransportDIB::CreateWithHandle(Handle handle) { - return new TransportDIB(handle); -} - -// static -bool TransportDIB::is_valid_handle(Handle dib) { - return dib.fd >= 0; -} - -// static -bool TransportDIB::is_valid_id(Id id) { - return id != 0; -} - -skia::PlatformCanvas* TransportDIB::GetPlatformCanvas(int w, int h) { - if ((!memory() && !Map()) || !VerifyCanvasSize(w, h)) - return NULL; - return skia::CreatePlatformCanvas(w, h, true, - reinterpret_cast(memory()), - skia::RETURN_NULL_ON_FAILURE); -} - -bool TransportDIB::Map() { - if (!is_valid_handle(handle())) - return false; - if (memory()) - return true; - - struct stat st; - if ((fstat(shared_memory_.handle().fd, &st) != 0) || - (!shared_memory_.Map(st.st_size))) { - return false; - } - - size_ = st.st_size; - return true; -} - -void* TransportDIB::memory() const { - return shared_memory_.memory(); -} - -TransportDIB::Id TransportDIB::id() const { - return shared_memory_.id(); -} - -TransportDIB::Handle TransportDIB::handle() const { - return shared_memory_.handle(); -} diff --git a/ui/surface/transport_dib_posix.cc b/ui/surface/transport_dib_posix.cc new file mode 100644 index 0000000..fcb935d --- /dev/null +++ b/ui/surface/transport_dib_posix.cc @@ -0,0 +1,118 @@ +// Copyright (c) 2012 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. + +#include "ui/surface/transport_dib.h" + +// Desktop GTK Linux builds use the old-style SYSV SHM based DIBs. +// Linux Aura and Chrome OS do too. This will change very soon. +#if !defined(TOOLKIT_GTK) && !(defined(OS_LINUX) && defined(USE_AURA)) + +#include +#include + +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/shared_memory.h" +#include "base/posix/eintr_wrapper.h" +#include "skia/ext/platform_canvas.h" + +TransportDIB::TransportDIB() + : size_(0) { +} + +TransportDIB::TransportDIB(TransportDIB::Handle dib) + : shared_memory_(dib, false /* read write */), + size_(0) { +} + +TransportDIB::~TransportDIB() { +} + +// static +TransportDIB* TransportDIB::Create(size_t size, uint32 sequence_num) { + TransportDIB* dib = new TransportDIB; + if (!dib->shared_memory_.CreateAndMapAnonymous(size)) { + delete dib; + return NULL; + } + + dib->size_ = size; + return dib; +} + +// static +TransportDIB* TransportDIB::Map(Handle handle) { + scoped_ptr dib(CreateWithHandle(handle)); + if (!dib->Map()) + return NULL; + return dib.release(); +} + +// static +TransportDIB* TransportDIB::CreateWithHandle(Handle handle) { + return new TransportDIB(handle); +} + +// static +bool TransportDIB::is_valid_handle(Handle dib) { + return dib.fd >= 0; +} + +// static +bool TransportDIB::is_valid_id(Id id) { +#if defined(OS_ANDROID) + return is_valid_handle(id); +#else + return id != 0; +#endif +} + +skia::PlatformCanvas* TransportDIB::GetPlatformCanvas(int w, int h) { + if ((!memory() && !Map()) || !VerifyCanvasSize(w, h)) + return NULL; + return skia::CreatePlatformCanvas(w, h, true, + reinterpret_cast(memory()), + skia::RETURN_NULL_ON_FAILURE); +} + +bool TransportDIB::Map() { + if (!is_valid_handle(handle())) + return false; +#if defined(OS_ANDROID) + if (!shared_memory_.Map(0)) + return false; + size_ = shared_memory_.mapped_size(); +#else + if (memory()) + return true; + + struct stat st; + if ((fstat(shared_memory_.handle().fd, &st) != 0) || + (!shared_memory_.Map(st.st_size))) { + return false; + } + + size_ = st.st_size; +#endif + return true; +} + +void* TransportDIB::memory() const { + return shared_memory_.memory(); +} + +TransportDIB::Id TransportDIB::id() const { +#if defined(OS_ANDROID) + return handle(); +#else + return shared_memory_.id(); +#endif +} + +TransportDIB::Handle TransportDIB::handle() const { + return shared_memory_.handle(); +} + +#endif // !defined(TOOLKIT_GTK) && !(defined(OS_LINUX) && defined(USE_AURA)) + diff --git a/ui/surface/transport_dib_sysvipc.cc b/ui/surface/transport_dib_sysvipc.cc new file mode 100644 index 0000000..a15ca41 --- /dev/null +++ b/ui/surface/transport_dib_sysvipc.cc @@ -0,0 +1,162 @@ +// Copyright (c) 2012 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. + +#include "ui/surface/transport_dib.h" + +// Desktop GTK Linux builds use the old-style SYSV SHM based DIBs. +// Linux Aura and Chrome OS do too. This will change very soon. +#if defined(TOOLKIT_GTK) || (defined(OS_LINUX) && defined(USE_AURA)) + +#include +#include +#include +#include + +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "skia/ext/platform_canvas.h" +#include "ui/base/x/x11_util.h" +#include "ui/gfx/size.h" + +// The shmat system call uses this as it's invalid return address +static void *const kInvalidAddress = (void*) -1; + +TransportDIB::TransportDIB() + : address_(kInvalidAddress), + x_shm_(0), + display_(NULL), + inflight_counter_(0), + detached_(false), + size_(0) { +} + +TransportDIB::~TransportDIB() { + if (address_ != kInvalidAddress) { + shmdt(address_); + address_ = kInvalidAddress; + } + + if (x_shm_) { + DCHECK(display_); + ui::DetachSharedMemory(display_, x_shm_); + } +} + +// static +TransportDIB* TransportDIB::Create(size_t size, uint32 sequence_num) { + const int shmkey = shmget(IPC_PRIVATE, size, 0600); + if (shmkey == -1) { + DLOG(ERROR) << "Failed to create SysV shared memory region" + << " errno:" << errno; + return NULL; + } else { + VLOG(1) << "Created SysV shared memory region " << shmkey; + } + + void* address = shmat(shmkey, NULL /* desired address */, 0 /* flags */); + // Here we mark the shared memory for deletion. Since we attached it in the + // line above, it doesn't actually get deleted but, if we crash, this means + // that the kernel will automatically clean it up for us. + shmctl(shmkey, IPC_RMID, 0); + if (address == kInvalidAddress) + return NULL; + + TransportDIB* dib = new TransportDIB; + + dib->key_.shmkey = shmkey; + dib->address_ = address; + dib->size_ = size; + return dib; +} + +// static +TransportDIB* TransportDIB::Map(Handle handle) { + scoped_ptr dib(CreateWithHandle(handle)); + if (!dib->Map()) + return NULL; + return dib.release(); +} + +// static +TransportDIB* TransportDIB::CreateWithHandle(Handle shmkey) { + TransportDIB* dib = new TransportDIB; + dib->key_.shmkey = shmkey; + return dib; +} + +// static +bool TransportDIB::is_valid_handle(Handle dib) { + return dib >= 0; +} + +// static +bool TransportDIB::is_valid_id(Id id) { + return id.shmkey != -1; +} + +skia::PlatformCanvas* TransportDIB::GetPlatformCanvas(int w, int h) { + if ((address_ == kInvalidAddress && !Map()) || !VerifyCanvasSize(w, h)) + return NULL; + return skia::CreatePlatformCanvas(w, h, true, + reinterpret_cast(memory()), + skia::RETURN_NULL_ON_FAILURE); +} + +bool TransportDIB::Map() { + if (!is_valid_id(key_)) + return false; + if (address_ != kInvalidAddress) + return true; + + struct shmid_ds shmst; + if (shmctl(key_.shmkey, IPC_STAT, &shmst) == -1) + return false; + + void* address = shmat(key_.shmkey, NULL /* desired address */, 0 /* flags */); + if (address == kInvalidAddress) + return false; + + address_ = address; + size_ = shmst.shm_segsz; + return true; +} + +void* TransportDIB::memory() const { + DCHECK_NE(address_, kInvalidAddress); + return address_; +} + +TransportDIB::Id TransportDIB::id() const { + return key_; +} + +TransportDIB::Handle TransportDIB::handle() const { + return key_.shmkey; +} + +XID TransportDIB::MapToX(Display* display) { + if (!x_shm_) { + x_shm_ = ui::AttachSharedMemory(display, key_.shmkey); + display_ = display; + } + + return x_shm_; +} + +void TransportDIB::DecreaseInFlightCounter() { + CHECK(inflight_counter_); + inflight_counter_--; + if (!inflight_counter_ && detached_) + delete this; +} + +void TransportDIB::Detach() { + CHECK(!detached_); + detached_ = true; + if (!inflight_counter_) + delete this; +} + +#endif + -- cgit v1.1