15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// found in the LICENSE file.
4a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h"
6a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/bind.h"
8010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/numerics/safe_math.h"
9010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "ui/gl/gl_bindings.h"
10a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace content {
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace {
131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid Noop() {
151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}  // namespace
18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)GpuMemoryBufferImplSharedMemory::GpuMemoryBufferImplSharedMemory(
205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const gfx::Size& size,
211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    unsigned internalformat,
221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const DestructionCallback& callback,
231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_ptr<base::SharedMemory> shared_memory)
241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    : GpuMemoryBufferImpl(size, internalformat, callback),
251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      shared_memory_(shared_memory.Pass()) {
265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)GpuMemoryBufferImplSharedMemory::~GpuMemoryBufferImplSharedMemory() {
295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
31010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// static
321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid GpuMemoryBufferImplSharedMemory::Create(const gfx::Size& size,
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                             unsigned internalformat,
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                             unsigned usage,
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                             const CreationCallback& callback) {
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(GpuMemoryBufferImplSharedMemory::IsConfigurationSupported(
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      size, internalformat, usage));
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!shared_memory->CreateAnonymous(size.GetArea() *
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                      BytesPerPixel(internalformat))) {
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    callback.Run(scoped_ptr<GpuMemoryBufferImpl>());
431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  callback.Run(
471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      make_scoped_ptr<GpuMemoryBufferImpl>(new GpuMemoryBufferImplSharedMemory(
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          size, internalformat, base::Bind(&Noop), shared_memory.Pass())));
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// static
521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid GpuMemoryBufferImplSharedMemory::AllocateForChildProcess(
53010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const gfx::Size& size,
54010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    unsigned internalformat,
55010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    base::ProcessHandle child_process,
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const AllocationCallback& callback) {
57010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(IsLayoutSupported(size, internalformat));
58010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  base::SharedMemory shared_memory;
59010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!shared_memory.CreateAnonymous(size.GetArea() *
60010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                     BytesPerPixel(internalformat))) {
611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    callback.Run(gfx::GpuMemoryBufferHandle());
62010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
63010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::GpuMemoryBufferHandle handle;
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  handle.type = gfx::SHARED_MEMORY_BUFFER;
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  shared_memory.GiveToProcess(child_process, &handle.handle);
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  callback.Run(handle);
68010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
69010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
70010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// static
711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciscoped_ptr<GpuMemoryBufferImpl>
721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciGpuMemoryBufferImplSharedMemory::CreateFromHandle(
731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const gfx::GpuMemoryBufferHandle& handle,
741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const gfx::Size& size,
751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    unsigned internalformat,
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const DestructionCallback& callback) {
771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(IsLayoutSupported(size, internalformat));
781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!base::SharedMemory::IsHandleValid(handle.handle))
801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return scoped_ptr<GpuMemoryBufferImpl>();
811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return make_scoped_ptr<GpuMemoryBufferImpl>(
831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new GpuMemoryBufferImplSharedMemory(
841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          size,
851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          internalformat,
861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          callback,
871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          make_scoped_ptr(new base::SharedMemory(handle.handle, false))));
881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// static
915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool GpuMemoryBufferImplSharedMemory::IsLayoutSupported(
925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const gfx::Size& size,
935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    unsigned internalformat) {
94010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  base::CheckedNumeric<int> buffer_size = size.width();
95010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  buffer_size *= size.height();
96010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  buffer_size *= BytesPerPixel(internalformat);
97010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return buffer_size.IsValid();
98010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
99010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
100010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// static
1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool GpuMemoryBufferImplSharedMemory::IsUsageSupported(unsigned usage) {
102010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  switch (usage) {
103010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    case GL_IMAGE_MAP_CHROMIUM:
104010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return true;
105010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    default:
106010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return false;
107010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
108010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
109010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
110010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// static
1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool GpuMemoryBufferImplSharedMemory::IsConfigurationSupported(
1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const gfx::Size& size,
1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    unsigned internalformat,
1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    unsigned usage) {
115010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return IsLayoutSupported(size, internalformat) && IsUsageSupported(usage);
116010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
117010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void* GpuMemoryBufferImplSharedMemory::Map() {
119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(!mapped_);
120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!shared_memory_->Map(size_.GetArea() * BytesPerPixel(internalformat_)))
121e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    return NULL;
122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  mapped_ = true;
123e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return shared_memory_->memory();
124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void GpuMemoryBufferImplSharedMemory::Unmap() {
127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(mapped_);
128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  shared_memory_->Unmap();
129a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  mapped_ = false;
130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
131a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)uint32 GpuMemoryBufferImplSharedMemory::GetStride() const {
133010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return size_.width() * BytesPerPixel(internalformat_);
134010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
135010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)gfx::GpuMemoryBufferHandle GpuMemoryBufferImplSharedMemory::GetHandle() const {
137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  gfx::GpuMemoryBufferHandle handle;
138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  handle.type = gfx::SHARED_MEMORY_BUFFER;
139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  handle.handle = shared_memory_->handle();
140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return handle;
141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}  // namespace content
144