summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjschuh@chromium.org <jschuh@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-28 02:02:18 +0000
committerjschuh@chromium.org <jschuh@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-28 02:02:18 +0000
commit67ea507fbee5b2d1647f3b86a60c36e8ba40c797 (patch)
tree26384c8a65a9c333da260e433055bead8b0ef88d
parent66eda3ee6b93c063f79ae9fc89e472e353b89585 (diff)
downloadchromium_src-67ea507fbee5b2d1647f3b86a60c36e8ba40c797.zip
chromium_src-67ea507fbee5b2d1647f3b86a60c36e8ba40c797.tar.gz
chromium_src-67ea507fbee5b2d1647f3b86a60c36e8ba40c797.tar.bz2
Make SharedMemory track the size that was actually mapped
In the process I also had to fix several dependencies, and some major issues in transport DIBs. BUG=60819 Review URL: https://chromiumcodereview.appspot.com/12537014 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@191098 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--base/shared_memory.h18
-rw-r--r--base/shared_memory_android.cc2
-rw-r--r--base/shared_memory_nacl.cc12
-rw-r--r--base/shared_memory_posix.cc18
-rw-r--r--base/shared_memory_unittest.cc22
-rw-r--r--base/shared_memory_win.cc48
-rw-r--r--content/browser/renderer_host/media/audio_input_renderer_host.cc2
-rw-r--r--content/browser/renderer_host/media/audio_input_sync_writer.cc4
-rw-r--r--content/browser/renderer_host/media/audio_renderer_host.cc2
-rw-r--r--content/browser/renderer_host/media/audio_sync_reader.cc2
-rw-r--r--content/browser/renderer_host/media/video_capture_buffer_pool.cc2
-rw-r--r--ui/surface/surface.gyp1
-rw-r--r--ui/surface/transport_dib.cc21
-rw-r--r--ui/surface/transport_dib.h4
-rw-r--r--ui/surface/transport_dib_android.cc11
-rw-r--r--ui/surface/transport_dib_linux.cc2
-rw-r--r--ui/surface/transport_dib_mac.cc2
-rw-r--r--ui/surface/transport_dib_win.cc30
18 files changed, 128 insertions, 75 deletions
diff --git a/base/shared_memory.h b/base/shared_memory.h
index da6f5b7b..4600194 100644
--- a/base/shared_memory.h
+++ b/base/shared_memory.h
@@ -159,15 +159,11 @@ class BASE_EXPORT SharedMemory {
// memory is not mapped.
bool Unmap();
- // Get the size of the shared memory backing file.
- // Note: This size is only available to the creator of the
- // shared memory, and not to those that opened shared memory
- // created externally.
- // Returns 0 if not created or unknown.
- // Deprecated method, please keep track of the size yourself if you created
- // it.
- // http://crbug.com/60821
- size_t created_size() const { return created_size_; }
+ // The size requested when the map is first created.
+ size_t requested_size() const { return requested_size_; }
+
+ // The actual size of the mapped memory (may be larger than requested).
+ size_t mapped_size() const { return mapped_size_; }
// Gets a pointer to the opened memory space if it has been
// Mapped via Map(). Returns NULL if it is not mapped.
@@ -246,12 +242,12 @@ class BASE_EXPORT SharedMemory {
HANDLE mapped_file_;
#elif defined(OS_POSIX)
int mapped_file_;
- size_t mapped_size_;
ino_t inode_;
#endif
+ size_t mapped_size_;
void* memory_;
bool read_only_;
- size_t created_size_;
+ size_t requested_size_;
#if !defined(OS_POSIX)
SharedMemoryLock lock_;
#endif
diff --git a/base/shared_memory_android.cc b/base/shared_memory_android.cc
index e2c683c..084904a 100644
--- a/base/shared_memory_android.cc
+++ b/base/shared_memory_android.cc
@@ -37,7 +37,7 @@ bool SharedMemory::Create(const SharedMemoryCreateOptions& options) {
DLOG(ERROR) << "Error " << err << " when setting protection of ashmem";
return false;
}
- created_size_ = options.size;
+ requested_size_ = options.size;
return true;
}
diff --git a/base/shared_memory_nacl.cc b/base/shared_memory_nacl.cc
index 291527e..5522b8f 100644
--- a/base/shared_memory_nacl.cc
+++ b/base/shared_memory_nacl.cc
@@ -18,30 +18,30 @@ namespace base {
SharedMemory::SharedMemory()
: mapped_file_(-1),
- mapped_size_(0),
inode_(0),
+ mapped_size_(0),
memory_(NULL),
read_only_(false),
- created_size_(0) {
+ requested_size_(0) {
}
SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only)
: mapped_file_(handle.fd),
- mapped_size_(0),
inode_(0),
+ mapped_size_(0),
memory_(NULL),
read_only_(read_only),
- created_size_(0) {
+ requested_size_(0) {
}
SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only,
ProcessHandle process)
: mapped_file_(handle.fd),
- mapped_size_(0),
inode_(0),
+ mapped_size_(0),
memory_(NULL),
read_only_(read_only),
- created_size_(0) {
+ requested_size_(0) {
NOTREACHED();
}
diff --git a/base/shared_memory_posix.cc b/base/shared_memory_posix.cc
index 25d141f..607d665 100644
--- a/base/shared_memory_posix.cc
+++ b/base/shared_memory_posix.cc
@@ -42,20 +42,20 @@ LazyInstance<Lock>::Leaky g_thread_lock_ = LAZY_INSTANCE_INITIALIZER;
SharedMemory::SharedMemory()
: mapped_file_(-1),
- mapped_size_(0),
inode_(0),
+ mapped_size_(0),
memory_(NULL),
read_only_(false),
- created_size_(0) {
+ requested_size_(0) {
}
SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only)
: mapped_file_(handle.fd),
- mapped_size_(0),
inode_(0),
+ mapped_size_(0),
memory_(NULL),
read_only_(read_only),
- created_size_(0) {
+ requested_size_(0) {
struct stat st;
if (fstat(handle.fd, &st) == 0) {
// If fstat fails, then the file descriptor is invalid and we'll learn this
@@ -67,11 +67,11 @@ SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only)
SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only,
ProcessHandle process)
: mapped_file_(handle.fd),
- mapped_size_(0),
inode_(0),
+ mapped_size_(0),
memory_(NULL),
read_only_(read_only),
- created_size_(0) {
+ requested_size_(0) {
// We don't handle this case yet (note the ignored parameter); let's die if
// someone comes calling.
NOTREACHED();
@@ -164,7 +164,7 @@ bool SharedMemory::Create(const SharedMemoryCreateOptions& options) {
return false;
}
}
- created_size_ = options.size;
+ requested_size_ = options.size;
}
if (fp == NULL) {
#if !defined(OS_MACOSX)
@@ -235,7 +235,7 @@ bool SharedMemory::MapAt(off_t offset, size_t bytes) {
// TODO(port): we set the created size here so that it is available in
// transport_dib_android.cc. We should use ashmem_get_size_region()
// in transport_dib_android.cc.
- created_size_ = ashmem_bytes;
+ mapped_size_ = ashmem_bytes;
}
#endif
@@ -244,7 +244,9 @@ bool SharedMemory::MapAt(off_t offset, size_t bytes) {
bool mmap_succeeded = memory_ != (void*)-1 && memory_ != NULL;
if (mmap_succeeded) {
+#if !defined(OS_ANDROID)
mapped_size_ = bytes;
+#endif
DCHECK_EQ(0U, reinterpret_cast<uintptr_t>(memory_) &
(SharedMemory::MAP_MINIMUM_ALIGNMENT - 1));
} else {
diff --git a/base/shared_memory_unittest.cc b/base/shared_memory_unittest.cc
index 3f83248..a9318ad 100644
--- a/base/shared_memory_unittest.cc
+++ b/base/shared_memory_unittest.cc
@@ -197,11 +197,18 @@ TEST(SharedMemoryTest, OpenExclusive) {
EXPECT_TRUE(rv);
// Memory1 knows it's size because it created it.
- EXPECT_EQ(memory1.created_size(), kDataSize);
+ EXPECT_EQ(memory1.requested_size(), kDataSize);
rv = memory1.Map(kDataSize);
EXPECT_TRUE(rv);
+ // The mapped memory1 must be at least the size we asked for.
+ EXPECT_GE(memory1.mapped_size(), kDataSize);
+
+ // The mapped memory1 shouldn't exceed rounding for allocation granularity.
+ EXPECT_LT(memory1.mapped_size(),
+ kDataSize + base::SysInfo::VMAllocationGranularity());
+
memset(memory1.memory(), 'G', kDataSize);
SharedMemory memory2;
@@ -214,12 +221,19 @@ TEST(SharedMemoryTest, OpenExclusive) {
EXPECT_TRUE(rv);
// Memory2 shouldn't know the size because we didn't create it.
- EXPECT_EQ(memory2.created_size(), 0U);
+ EXPECT_EQ(memory2.requested_size(), 0U);
// We should be able to map the original size.
rv = memory2.Map(kDataSize);
EXPECT_TRUE(rv);
+ // The mapped memory2 must be at least the size of the original.
+ EXPECT_GE(memory2.mapped_size(), kDataSize);
+
+ // The mapped memory2 shouldn't exceed rounding for allocation granularity.
+ EXPECT_LT(memory2.mapped_size(),
+ kDataSize2 + base::SysInfo::VMAllocationGranularity());
+
// Verify that opening memory2 didn't truncate or delete memory 1.
char *start_ptr = static_cast<char *>(memory2.memory());
char *end_ptr = start_ptr + kDataSize;
@@ -382,9 +396,9 @@ TEST(SharedMemoryTest, AnonymousExecutable) {
options.executable = true;
EXPECT_TRUE(shared_memory.Create(options));
- EXPECT_TRUE(shared_memory.Map(shared_memory.created_size()));
+ EXPECT_TRUE(shared_memory.Map(shared_memory.requested_size()));
- EXPECT_EQ(0, mprotect(shared_memory.memory(), shared_memory.created_size(),
+ EXPECT_EQ(0, mprotect(shared_memory.memory(), shared_memory.requested_size(),
PROT_READ | PROT_EXEC));
}
#endif
diff --git a/base/shared_memory_win.cc b/base/shared_memory_win.cc
index f64e3c8..defad6e 100644
--- a/base/shared_memory_win.cc
+++ b/base/shared_memory_win.cc
@@ -7,13 +7,27 @@
#include "base/logging.h"
#include "base/utf_string_conversions.h"
+namespace {
+
+// Returns the length of the memory section starting at the supplied address.
+size_t GetMemorySectionSize(void* address) {
+ MEMORY_BASIC_INFORMATION memory_info;
+ if (!::VirtualQuery(address, &memory_info, sizeof(memory_info)))
+ return 0;
+ return memory_info.RegionSize - (static_cast<char*>(address) -
+ static_cast<char*>(memory_info.AllocationBase));
+}
+
+} // namespace.
+
namespace base {
SharedMemory::SharedMemory()
: mapped_file_(NULL),
memory_(NULL),
read_only_(false),
- created_size_(0),
+ mapped_size_(0),
+ requested_size_(0),
lock_(NULL) {
}
@@ -21,7 +35,8 @@ SharedMemory::SharedMemory(const std::wstring& name)
: mapped_file_(NULL),
memory_(NULL),
read_only_(false),
- created_size_(0),
+ requested_size_(0),
+ mapped_size_(0),
lock_(NULL),
name_(name) {
}
@@ -30,7 +45,8 @@ SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only)
: mapped_file_(handle),
memory_(NULL),
read_only_(read_only),
- created_size_(0),
+ requested_size_(0),
+ mapped_size_(0),
lock_(NULL) {
}
@@ -39,7 +55,8 @@ SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only,
: mapped_file_(NULL),
memory_(NULL),
read_only_(read_only),
- created_size_(0),
+ requested_size_(0),
+ mapped_size_(0),
lock_(NULL) {
::DuplicateHandle(process, handle,
GetCurrentProcess(), &mapped_file_,
@@ -75,22 +92,20 @@ bool SharedMemory::CreateAndMapAnonymous(size_t size) {
}
bool SharedMemory::Create(const SharedMemoryCreateOptions& options) {
+ // TODO(bsy,sehr): crbug.com/210609 NaCl forces us to round up 64k here,
+ // wasting 32k per mapping on average.
+ static const size_t kSectionMask = 65536 - 1;
DCHECK(!options.executable);
DCHECK(!mapped_file_);
if (options.size == 0)
return false;
- if (options.size > static_cast<size_t>(std::numeric_limits<int>::max()))
+ // Check maximum accounting for overflow.
+ if (options.size >
+ static_cast<size_t>(std::numeric_limits<int>::max()) - kSectionMask)
return false;
- // NaCl's memory allocator requires 0mod64K alignment and size for
- // shared memory objects. To allow passing shared memory to NaCl,
- // therefore we round the size actually created to the nearest 64K unit.
- // To avoid client impact, we continue to retain the size as the
- // actual requested size.
- uint32 rounded_size = (options.size + 0xffff) & ~0xffff;
- if (rounded_size < options.size)
- return false;
+ size_t rounded_size = (options.size + kSectionMask) & ~kSectionMask;
name_ = ASCIIToWide(options.name == NULL ? "" : *options.name);
mapped_file_ = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,
PAGE_READWRITE, 0, static_cast<DWORD>(rounded_size),
@@ -98,13 +113,13 @@ bool SharedMemory::Create(const SharedMemoryCreateOptions& options) {
if (!mapped_file_)
return false;
- created_size_ = options.size;
+ requested_size_ = options.size;
// Check if the shared memory pre-exists.
if (GetLastError() == ERROR_ALREADY_EXISTS) {
- // If the file already existed, set created_size_ to 0 to show that
+ // If the file already existed, set requested_size_ to 0 to show that
// we don't know the size.
- created_size_ = 0;
+ requested_size_ = 0;
if (!options.open_existing) {
Close();
return false;
@@ -149,6 +164,7 @@ bool SharedMemory::MapAt(off_t offset, size_t bytes) {
if (memory_ != NULL) {
DCHECK_EQ(0U, reinterpret_cast<uintptr_t>(memory_) &
(SharedMemory::MAP_MINIMUM_ALIGNMENT - 1));
+ mapped_size_ = GetMemorySectionSize(memory_);
return true;
}
return false;
diff --git a/content/browser/renderer_host/media/audio_input_renderer_host.cc b/content/browser/renderer_host/media/audio_input_renderer_host.cc
index 750661c..65f9e62 100644
--- a/content/browser/renderer_host/media/audio_input_renderer_host.cc
+++ b/content/browser/renderer_host/media/audio_input_renderer_host.cc
@@ -159,7 +159,7 @@ void AudioInputRendererHost::DoCompleteCreation(
Send(new AudioInputMsg_NotifyStreamCreated(entry->stream_id,
foreign_memory_handle, foreign_socket_handle,
- entry->shared_memory.created_size(),
+ entry->shared_memory.requested_size(),
entry->shared_memory_segment_count));
}
diff --git a/content/browser/renderer_host/media/audio_input_sync_writer.cc b/content/browser/renderer_host/media/audio_input_sync_writer.cc
index 2af937d..18a85ab 100644
--- a/content/browser/renderer_host/media/audio_input_sync_writer.cc
+++ b/content/browser/renderer_host/media/audio_input_sync_writer.cc
@@ -18,9 +18,9 @@ AudioInputSyncWriter::AudioInputSyncWriter(
shared_memory_segment_count_(shared_memory_segment_count),
current_segment_id_(0) {
DCHECK_GT(shared_memory_segment_count, 0);
- DCHECK_EQ(shared_memory->created_size() % shared_memory_segment_count, 0u);
+ DCHECK_EQ(shared_memory->requested_size() % shared_memory_segment_count, 0u);
shared_memory_segment_size_ =
- shared_memory->created_size() / shared_memory_segment_count;
+ shared_memory->requested_size() / shared_memory_segment_count;
}
AudioInputSyncWriter::~AudioInputSyncWriter() {}
diff --git a/content/browser/renderer_host/media/audio_renderer_host.cc b/content/browser/renderer_host/media/audio_renderer_host.cc
index ceda190..9e7a92a 100644
--- a/content/browser/renderer_host/media/audio_renderer_host.cc
+++ b/content/browser/renderer_host/media/audio_renderer_host.cc
@@ -183,7 +183,7 @@ void AudioRendererHost::DoCompleteCreation(
entry->stream_id,
foreign_memory_handle,
foreign_socket_handle,
- media::PacketSizeInBytes(entry->shared_memory.created_size())));
+ media::PacketSizeInBytes(entry->shared_memory.requested_size())));
}
void AudioRendererHost::DoSendPlayingMessage(
diff --git a/content/browser/renderer_host/media/audio_sync_reader.cc b/content/browser/renderer_host/media/audio_sync_reader.cc
index 620ba54..7b3ea02 100644
--- a/content/browser/renderer_host/media/audio_sync_reader.cc
+++ b/content/browser/renderer_host/media/audio_sync_reader.cc
@@ -24,7 +24,7 @@ AudioSyncReader::AudioSyncReader(base::SharedMemory* shared_memory,
input_channels_(input_channels),
renderer_callback_count_(0),
renderer_missed_callback_count_(0) {
- packet_size_ = media::PacketSizeInBytes(shared_memory_->created_size());
+ packet_size_ = media::PacketSizeInBytes(shared_memory_->requested_size());
int input_memory_size = 0;
int output_memory_size = AudioBus::CalculateMemorySize(params);
if (input_channels_ > 0) {
diff --git a/content/browser/renderer_host/media/video_capture_buffer_pool.cc b/content/browser/renderer_host/media/video_capture_buffer_pool.cc
index d702201..8a6a0f86b 100644
--- a/content/browser/renderer_host/media/video_capture_buffer_pool.cc
+++ b/content/browser/renderer_host/media/video_capture_buffer_pool.cc
@@ -65,7 +65,7 @@ scoped_refptr<media::VideoFrame> VideoCaptureBufferPool::ReserveForProducer(
Buffer* buffer = buffers_[buffer_id];
- CHECK_GE(buffer->shared_memory.created_size(), GetMemorySize());
+ CHECK_GE(buffer->shared_memory.requested_size(), GetMemorySize());
// Complete the reservation.
buffer->held_by_producer = true;
diff --git a/ui/surface/surface.gyp b/ui/surface/surface.gyp
index 903ea49..cc4aa6b 100644
--- a/ui/surface/surface.gyp
+++ b/ui/surface/surface.gyp
@@ -80,6 +80,7 @@
'surface_switches.h',
'surface_switches.cc',
'transport_dib.h',
+ 'transport_dib.cc',
'transport_dib_android.cc',
'transport_dib_linux.cc',
'transport_dib_mac.cc',
diff --git a/ui/surface/transport_dib.cc b/ui/surface/transport_dib.cc
new file mode 100644
index 0000000..ba72f91
--- /dev/null
+++ b/ui/surface/transport_dib.cc
@@ -0,0 +1,21 @@
+// Copyright (c) 2013 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 "skia/ext/platform_canvas.h"
+
+// static
+bool TransportDIB::VerifyCanvasSize(int w, int h) {
+ static const size_t kMaxSize = static_cast<size_t>(INT_MAX);
+ const size_t one_stride = skia::PlatformCanvasStrideForWidth(1);
+ const size_t stride = skia::PlatformCanvasStrideForWidth(w);
+ if (w <= 0 || h <= 0 || static_cast<size_t>(w) > (kMaxSize / one_stride) ||
+ static_cast<size_t>(h) > (kMaxSize / stride)) {
+ return false;
+ }
+
+ return (stride * h) <= size_;
+}
+
diff --git a/ui/surface/transport_dib.h b/ui/surface/transport_dib.h
index 5050a6a..233cd2e 100644
--- a/ui/surface/transport_dib.h
+++ b/ui/surface/transport_dib.h
@@ -205,6 +205,10 @@ class SURFACE_EXPORT TransportDIB {
private:
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_;
diff --git a/ui/surface/transport_dib_android.cc b/ui/surface/transport_dib_android.cc
index 25a7875..f734155 100644
--- a/ui/surface/transport_dib_android.cc
+++ b/ui/surface/transport_dib_android.cc
@@ -63,7 +63,7 @@ bool TransportDIB::is_valid_id(Id id) {
}
skia::PlatformCanvas* TransportDIB::GetPlatformCanvas(int w, int h) {
- if (!memory() && !Map())
+ if ((!memory() && !Map()) || !VerifyCanvasSize(w, h))
return NULL;
return skia::CreatePlatformCanvas(w, h, true,
reinterpret_cast<uint8_t*>(memory()),
@@ -71,15 +71,10 @@ skia::PlatformCanvas* TransportDIB::GetPlatformCanvas(int w, int h) {
}
bool TransportDIB::Map() {
- if (!is_valid_handle(handle()))
- return false;
- // We will use ashmem_get_size_region() to figure out the size in Map(size).
- if (!shared_memory_.Map(0))
+ if (!is_valid_handle(handle()) || !shared_memory_.Map(0))
return false;
- // TODO: Note that using created_size() below is a hack. See the comment in
- // SharedMemory::Map().
- size_ = shared_memory_.created_size();
+ size_ = shared_memory_.mapped_size();
return true;
}
diff --git a/ui/surface/transport_dib_linux.cc b/ui/surface/transport_dib_linux.cc
index 3aaa798..1e8d8fa 100644
--- a/ui/surface/transport_dib_linux.cc
+++ b/ui/surface/transport_dib_linux.cc
@@ -92,7 +92,7 @@ bool TransportDIB::is_valid_id(Id id) {
}
skia::PlatformCanvas* TransportDIB::GetPlatformCanvas(int w, int h) {
- if (address_ == kInvalidAddress && !Map())
+ if ((address_ == kInvalidAddress && !Map()) || !VerifyCanvasSize(w, h))
return NULL;
return skia::CreatePlatformCanvas(w, h, true,
reinterpret_cast<uint8_t*>(memory()),
diff --git a/ui/surface/transport_dib_mac.cc b/ui/surface/transport_dib_mac.cc
index 7abfbce..8481656 100644
--- a/ui/surface/transport_dib_mac.cc
+++ b/ui/surface/transport_dib_mac.cc
@@ -61,7 +61,7 @@ bool TransportDIB::is_valid_id(Id id) {
}
skia::PlatformCanvas* TransportDIB::GetPlatformCanvas(int w, int h) {
- if (!memory() && !Map())
+ if ((!memory() && !Map()) || !VerifyCanvasSize(w, h))
return NULL;
return skia::CreatePlatformCanvas(w, h, true,
reinterpret_cast<uint8_t*>(memory()),
diff --git a/ui/surface/transport_dib_win.cc b/ui/surface/transport_dib_win.cc
index 55dd6a3..a664266 100644
--- a/ui/surface/transport_dib_win.cc
+++ b/ui/surface/transport_dib_win.cc
@@ -13,22 +13,20 @@
#include "base/sys_info.h"
#include "skia/ext/platform_canvas.h"
-TransportDIB::TransportDIB() {
+TransportDIB::TransportDIB()
+ : size_(0) {
}
TransportDIB::~TransportDIB() {
}
TransportDIB::TransportDIB(HANDLE handle)
- : shared_memory_(handle, false /* read write */) {
+ : shared_memory_(handle, false /* read write */),
+ size_(0) {
}
// static
TransportDIB* TransportDIB::Create(size_t size, uint32 sequence_num) {
- size_t allocation_granularity = base::SysInfo::VMAllocationGranularity();
- size = size / allocation_granularity + 1;
- size = size * allocation_granularity;
-
TransportDIB* dib = new TransportDIB;
if (!dib->shared_memory_.CreateAnonymous(size)) {
@@ -70,8 +68,18 @@ skia::PlatformCanvas* TransportDIB::GetPlatformCanvas(int w, int h) {
// will map it again.
DCHECK(!memory()) << "Mapped file twice in the same process.";
- return skia::CreatePlatformCanvas(w, h, true, handle(),
- skia::RETURN_NULL_ON_FAILURE);
+ // We can't check the canvas size before mapping, but it's safe because
+ // Windows will fail to map the section if the dimensions of the canvas
+ // are too large.
+ skia::PlatformCanvas* canvas =
+ skia::CreatePlatformCanvas(w, h, true, handle(),
+ skia::RETURN_NULL_ON_FAILURE);
+
+ // Calculate the size for the memory region backing the canvas.
+ if (canvas)
+ size_ = skia::PlatformCanvasStrideForWidth(w) * h;
+
+ return canvas;
}
bool TransportDIB::Map() {
@@ -87,11 +95,7 @@ bool TransportDIB::Map() {
return false;
}
- // There doesn't seem to be any way to find the size of the shared memory
- // region! GetFileSize indicates that the handle is invalid. Thus, we
- // conservatively set the size to the maximum and hope that the renderer
- // isn't about to ask us to read off the end of the array.
- size_ = std::numeric_limits<size_t>::max();
+ size_ = shared_memory_.mapped_size();
return true;
}