|  | // Copyright 2014 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/gl/gl_image_shared_memory.h" | 
|  |  | 
|  | #include "base/logging.h" | 
|  | #include "base/numerics/safe_math.h" | 
|  | #include "base/process/process_handle.h" | 
|  |  | 
|  | namespace gfx { | 
|  | namespace { | 
|  |  | 
|  | // Returns true if the size is valid and false otherwise. | 
|  | bool SizeInBytes(const gfx::Size& size, | 
|  | gfx::GpuMemoryBuffer::Format format, | 
|  | size_t* size_in_bytes) { | 
|  | if (size.IsEmpty()) | 
|  | return false; | 
|  |  | 
|  | size_t stride_in_bytes = 0; | 
|  | if (!GLImageMemory::StrideInBytes(size.width(), format, &stride_in_bytes)) | 
|  | return false; | 
|  | base::CheckedNumeric<size_t> s = stride_in_bytes; | 
|  | s *= size.height(); | 
|  | if (!s.IsValid()) | 
|  | return false; | 
|  | *size_in_bytes = s.ValueOrDie(); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | GLImageSharedMemory::GLImageSharedMemory(const gfx::Size& size, | 
|  | unsigned internalformat) | 
|  | : GLImageMemory(size, internalformat) { | 
|  | } | 
|  |  | 
|  | GLImageSharedMemory::~GLImageSharedMemory() { | 
|  | DCHECK(!shared_memory_); | 
|  | } | 
|  |  | 
|  | bool GLImageSharedMemory::Initialize(const gfx::GpuMemoryBufferHandle& handle, | 
|  | gfx::GpuMemoryBuffer::Format format) { | 
|  | size_t size_in_bytes; | 
|  | if (!SizeInBytes(GetSize(), format, &size_in_bytes)) | 
|  | return false; | 
|  |  | 
|  | if (!base::SharedMemory::IsHandleValid(handle.handle)) | 
|  | return false; | 
|  |  | 
|  | base::SharedMemory shared_memory(handle.handle, true); | 
|  |  | 
|  | // Duplicate the handle. | 
|  | base::SharedMemoryHandle duped_shared_memory_handle; | 
|  | if (!shared_memory.ShareToProcess(base::GetCurrentProcessHandle(), | 
|  | &duped_shared_memory_handle)) { | 
|  | DVLOG(0) << "Failed to duplicate shared memory handle."; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | scoped_ptr<base::SharedMemory> duped_shared_memory( | 
|  | new base::SharedMemory(duped_shared_memory_handle, true)); | 
|  | if (!duped_shared_memory->Map(size_in_bytes)) { | 
|  | DVLOG(0) << "Failed to map shared memory."; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | if (!GLImageMemory::Initialize( | 
|  | static_cast<unsigned char*>(duped_shared_memory->memory()), format)) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | DCHECK(!shared_memory_); | 
|  | shared_memory_ = duped_shared_memory.Pass(); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | void GLImageSharedMemory::Destroy(bool have_context) { | 
|  | GLImageMemory::Destroy(have_context); | 
|  | shared_memory_.reset(); | 
|  | } | 
|  |  | 
|  | }  // namespace gfx |