summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoremircan <emircan@chromium.org>2015-04-07 23:25:00 -0700
committerCommit bot <commit-bot@chromium.org>2015-04-08 06:25:48 +0000
commit607ed17ba5d0d1c67901ecc7160db660f08bd831 (patch)
tree8c8d692aaff4c1110998718c9cd587e0e76a47ee
parent7e576157bba19b8918f0ad2e3a43d0171a675155 (diff)
downloadchromium_src-607ed17ba5d0d1c67901ecc7160db660f08bd831.zip
chromium_src-607ed17ba5d0d1c67901ecc7160db660f08bd831.tar.gz
chromium_src-607ed17ba5d0d1c67901ecc7160db660f08bd831.tar.bz2
We started redesigning GpuMemoryBuffer interface to handle multiple buffers [0].
[0] https://codereview.chromium.org/1024113003/#ps200001 In this CL: - I added a new format gfx::GpuMemoryBuffer::YUV_420 - Implemented helper functions to use with it on GpuMemoryBufferImpl. - I added support in GpuMemoryBufferImplSharedMemory and GpuMemoryBufferFactorySharedMemory - I added { gfx::GpuMemoryBuffer::YUV_420, gfx::GpuMemoryBuffer::MAP } as a supported config for testing - I added support for multi plane in test implementations: test_gpu_memory_buffer_manager, gl_manager, gpu_memory_buffer_impl_unittest The future steps are: - Add a new GL_* internalformat corresponding to YUV_420 - Implement support for YUV_420 in GpuMemoryBufferFactoryOzoneNativeBuffer, GLImageLinuxDMABuffer and SurfaceFactoryOzone - Expose file descriptors for gfx::GpuMemoryBuffer::YUV_420 via Map() or GpuMemoryBufferHandle struct Check usage of gbm_bo_get_fd() at the lowest gbmbuffer level - Add support in GLImageSharedMemory and GLImageMemory through Bind functions - Look for possible use cases of multiple buffers on Android, Mac, and Win platforms BUG=439520 TEST=content_unittests --gtest_filter=GpuMemoryBufferImplTests.* content_unittests --gtest_filter=GpuMemoryBufferFactoryTest.* gl_tests --gtest_filter=GpuMemoryBufferTest* Review URL: https://codereview.chromium.org/1062853002 Cr-Commit-Position: refs/heads/master@{#324190}
-rw-r--r--cc/test/test_gpu_memory_buffer_manager.cc80
-rw-r--r--content/common/gpu/client/gpu_memory_buffer_impl.cc73
-rw-r--r--content/common/gpu/client/gpu_memory_buffer_impl.h10
-rw-r--r--content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.cc91
-rw-r--r--content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h6
-rw-r--r--content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.cc3
-rw-r--r--content/common/gpu/client/gpu_memory_buffer_impl_unittest.cc54
-rw-r--r--content/common/gpu/gpu_memory_buffer_factory_io_surface.cc2
-rw-r--r--content/common/gpu/gpu_memory_buffer_factory_shared_memory.cc21
-rw-r--r--content/common/gpu/gpu_memory_buffer_factory_unittest.cc2
-rw-r--r--gpu/command_buffer/service/image_factory.cc2
-rw-r--r--gpu/command_buffer/tests/gl_gpu_memory_buffer_unittest.cc3
-rw-r--r--gpu/command_buffer/tests/gl_manager.cc75
-rw-r--r--ui/gfx/gpu_memory_buffer.h3
-rw-r--r--ui/gl/gl_image_linux_dma_buffer.cc3
-rw-r--r--ui/gl/gl_image_memory.cc15
-rw-r--r--ui/ozone/gpu/gpu_memory_buffer_factory_ozone_native_buffer.cc1
17 files changed, 330 insertions, 114 deletions
diff --git a/cc/test/test_gpu_memory_buffer_manager.cc b/cc/test/test_gpu_memory_buffer_manager.cc
index b43cd76..8887feb 100644
--- a/cc/test/test_gpu_memory_buffer_manager.cc
+++ b/cc/test/test_gpu_memory_buffer_manager.cc
@@ -10,26 +10,82 @@
namespace cc {
namespace {
-size_t StrideInBytes(size_t width, gfx::GpuMemoryBuffer::Format format) {
+size_t NumberOfPlanesForGpuMemoryBufferFormat(
+ gfx::GpuMemoryBuffer::Format format) {
switch (format) {
+ case gfx::GpuMemoryBuffer::Format::ATC:
+ case gfx::GpuMemoryBuffer::Format::ATCIA:
+ case gfx::GpuMemoryBuffer::Format::DXT1:
+ case gfx::GpuMemoryBuffer::Format::DXT5:
+ case gfx::GpuMemoryBuffer::Format::ETC1:
+ case gfx::GpuMemoryBuffer::Format::RGBA_8888:
+ case gfx::GpuMemoryBuffer::Format::RGBX_8888:
+ case gfx::GpuMemoryBuffer::Format::BGRA_8888:
+ return 1;
+ case gfx::GpuMemoryBuffer::Format::YUV_420:
+ return 3;
+ }
+ NOTREACHED();
+ return 0;
+}
+
+size_t SubsamplingFactor(gfx::GpuMemoryBuffer::Format format, int plane) {
+ switch (format) {
+ case gfx::GpuMemoryBuffer::ATC:
case gfx::GpuMemoryBuffer::ATCIA:
+ case gfx::GpuMemoryBuffer::DXT1:
case gfx::GpuMemoryBuffer::DXT5:
+ case gfx::GpuMemoryBuffer::ETC1:
+ case gfx::GpuMemoryBuffer::RGBA_8888:
+ case gfx::GpuMemoryBuffer::RGBX_8888:
+ case gfx::GpuMemoryBuffer::BGRA_8888:
+ return 1;
+ case gfx::GpuMemoryBuffer::YUV_420: {
+ static size_t factor[] = {1, 2, 2};
+ DCHECK_LT(static_cast<size_t>(plane), arraysize(factor));
+ return factor[plane];
+ }
+ }
+ NOTREACHED();
+ return 0;
+}
+
+size_t StrideInBytes(size_t width,
+ gfx::GpuMemoryBuffer::Format format,
+ int plane) {
+ switch (format) {
+ case gfx::GpuMemoryBuffer::ATCIA:
+ case gfx::GpuMemoryBuffer::DXT5:
+ DCHECK_EQ(plane, 0);
return width;
case gfx::GpuMemoryBuffer::ATC:
case gfx::GpuMemoryBuffer::DXT1:
case gfx::GpuMemoryBuffer::ETC1:
+ DCHECK_EQ(plane, 0);
DCHECK_EQ(width % 2, 0U);
return width / 2;
case gfx::GpuMemoryBuffer::RGBA_8888:
case gfx::GpuMemoryBuffer::RGBX_8888:
case gfx::GpuMemoryBuffer::BGRA_8888:
+ DCHECK_EQ(plane, 0);
return width * 4;
+ case gfx::GpuMemoryBuffer::YUV_420:
+ return width / SubsamplingFactor(format, plane);
}
-
NOTREACHED();
return 0;
}
+size_t BufferSizeInBytes(const gfx::Size& size,
+ gfx::GpuMemoryBuffer::Format format) {
+ size_t size_in_bytes = 0u;
+ for (size_t i = 0; i < NumberOfPlanesForGpuMemoryBufferFormat(format); ++i) {
+ size_in_bytes += StrideInBytes(size.width(), format, i) *
+ (size.height() / SubsamplingFactor(format, i));
+ }
+ return size_in_bytes;
+}
+
class GpuMemoryBufferImpl : public gfx::GpuMemoryBuffer {
public:
GpuMemoryBufferImpl(const gfx::Size& size,
@@ -43,11 +99,17 @@ class GpuMemoryBufferImpl : public gfx::GpuMemoryBuffer {
// Overridden from gfx::GpuMemoryBuffer:
bool Map(void** data) override {
DCHECK(!mapped_);
- if (!shared_memory_->Map(StrideInBytes(size_.width(), format_) *
- size_.height()))
+ if (!shared_memory_->Map(BufferSizeInBytes(size_, format_)))
return false;
mapped_ = true;
- *data = shared_memory_->memory();
+ data[0] = shared_memory_->memory();
+ for (size_t i = 0; i < NumberOfPlanesForGpuMemoryBufferFormat(format_) - 1;
+ ++i) {
+ size_t offset = StrideInBytes(size_.width(), format_, i) *
+ (size_.height() / SubsamplingFactor(format_, i));
+ data[i + 1] = reinterpret_cast<uint8*>(data[i]) + offset;
+ }
+
return true;
}
void Unmap() override {
@@ -58,7 +120,10 @@ class GpuMemoryBufferImpl : public gfx::GpuMemoryBuffer {
bool IsMapped() const override { return mapped_; }
Format GetFormat() const override { return format_; }
void GetStride(uint32* stride) const override {
- *stride = StrideInBytes(size_.width(), format_);
+ for (size_t i = 0; i < NumberOfPlanesForGpuMemoryBufferFormat(format_);
+ ++i) {
+ stride[i] = StrideInBytes(size_.width(), format_, i);
+ }
}
gfx::GpuMemoryBufferHandle GetHandle() const override {
gfx::GpuMemoryBufferHandle handle;
@@ -91,8 +156,7 @@ TestGpuMemoryBufferManager::AllocateGpuMemoryBuffer(
gfx::GpuMemoryBuffer::Format format,
gfx::GpuMemoryBuffer::Usage usage) {
scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory);
- if (!shared_memory->CreateAnonymous(StrideInBytes(size.width(), format) *
- size.height()))
+ if (!shared_memory->CreateAnonymous(BufferSizeInBytes(size, format)))
return nullptr;
return make_scoped_ptr<gfx::GpuMemoryBuffer>(
new GpuMemoryBufferImpl(size, format, shared_memory.Pass()));
diff --git a/content/common/gpu/client/gpu_memory_buffer_impl.cc b/content/common/gpu/client/gpu_memory_buffer_impl.cc
index 208261d..b8284ec 100644
--- a/content/common/gpu/client/gpu_memory_buffer_impl.cc
+++ b/content/common/gpu/client/gpu_memory_buffer_impl.cc
@@ -77,57 +77,86 @@ GpuMemoryBufferImpl* GpuMemoryBufferImpl::FromClientBuffer(
}
// static
+size_t GpuMemoryBufferImpl::NumberOfPlanesForGpuMemoryBufferFormat(
+ Format format) {
+ switch (format) {
+ case ATC:
+ case ATCIA:
+ case DXT1:
+ case DXT5:
+ case ETC1:
+ case RGBA_8888:
+ case RGBX_8888:
+ case BGRA_8888:
+ return 1;
+ case YUV_420:
+ return 3;
+ }
+ NOTREACHED();
+ return 0;
+}
+
+// static
bool GpuMemoryBufferImpl::StrideInBytes(size_t width,
Format format,
+ int plane,
size_t* stride_in_bytes) {
- base::CheckedNumeric<size_t> s = width;
switch (format) {
case ATCIA:
case DXT5:
+ DCHECK_EQ(plane, 0);
*stride_in_bytes = width;
return true;
case ATC:
case DXT1:
case ETC1:
+ DCHECK_EQ(plane, 0);
DCHECK_EQ(width % 2, 0U);
- s /= 2;
- if (!s.IsValid())
- return false;
-
- *stride_in_bytes = s.ValueOrDie();
+ *stride_in_bytes = width / 2;
return true;
case RGBA_8888:
case RGBX_8888:
- case BGRA_8888:
+ case BGRA_8888: {
+ base::CheckedNumeric<size_t> s = width;
+ DCHECK_EQ(plane, 0);
s *= 4;
if (!s.IsValid())
return false;
-
*stride_in_bytes = s.ValueOrDie();
return true;
+ }
+ case YUV_420: {
+ DCHECK_EQ(width % 2, 0u);
+ *stride_in_bytes = width / SubsamplingFactor(format, plane);
+ return true;
+ }
}
-
NOTREACHED();
return false;
}
// static
-size_t GpuMemoryBufferImpl::NumberOfPlanesForGpuMemoryBufferFormat(
- gfx::GpuMemoryBuffer::Format format) {
+size_t GpuMemoryBufferImpl::SubsamplingFactor(
+ Format format,
+ int plane) {
switch (format) {
- case gfx::GpuMemoryBuffer::Format::ATC:
- case gfx::GpuMemoryBuffer::Format::ATCIA:
- case gfx::GpuMemoryBuffer::Format::DXT1:
- case gfx::GpuMemoryBuffer::Format::DXT5:
- case gfx::GpuMemoryBuffer::Format::ETC1:
- case gfx::GpuMemoryBuffer::Format::RGBA_8888:
- case gfx::GpuMemoryBuffer::Format::RGBX_8888:
- case gfx::GpuMemoryBuffer::Format::BGRA_8888:
+ case ATC:
+ case ATCIA:
+ case DXT1:
+ case DXT5:
+ case ETC1:
+ case RGBA_8888:
+ case RGBX_8888:
+ case BGRA_8888:
return 1;
- default:
- NOTREACHED();
- return 0;
+ case YUV_420: {
+ static size_t factor[] = {1, 2, 2};
+ DCHECK_LT(static_cast<size_t>(plane), arraysize(factor));
+ return factor[plane];
+ }
}
+ NOTREACHED();
+ return 0;
}
gfx::GpuMemoryBuffer::Format GpuMemoryBufferImpl::GetFormat() const {
diff --git a/content/common/gpu/client/gpu_memory_buffer_impl.h b/content/common/gpu/client/gpu_memory_buffer_impl.h
index cd8c108..31b28bc 100644
--- a/content/common/gpu/client/gpu_memory_buffer_impl.h
+++ b/content/common/gpu/client/gpu_memory_buffer_impl.h
@@ -33,15 +33,19 @@ class CONTENT_EXPORT GpuMemoryBufferImpl : public gfx::GpuMemoryBuffer {
// Type-checking upcast routine. Returns an NULL on failure.
static GpuMemoryBufferImpl* FromClientBuffer(ClientBuffer buffer);
+ // Returns the number of planes based on the format of the buffer.
+ static size_t NumberOfPlanesForGpuMemoryBufferFormat(Format format);
+
// Calculates the number of bytes that an implementation must use to store
// one row of pixel data.
static bool StrideInBytes(size_t width,
Format format,
+ int plane,
size_t* stride_in_bytes);
- // Returns the number of planes based on the format of the buffer.
- static size_t NumberOfPlanesForGpuMemoryBufferFormat(
- gfx::GpuMemoryBuffer::Format format);
+ // Returns the subsampling factor applied to the given zero-indexed |plane| of
+ // the |format| both horizontally and vertically.
+ static size_t SubsamplingFactor(Format format, int plane);
// Overridden from gfx::GpuMemoryBuffer:
bool IsMapped() const override;
diff --git a/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.cc b/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.cc
index 3d3aee9..9155205 100644
--- a/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.cc
+++ b/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.cc
@@ -36,18 +36,12 @@ scoped_ptr<GpuMemoryBufferImpl> GpuMemoryBufferImplSharedMemory::Create(
gfx::GpuMemoryBufferId id,
const gfx::Size& size,
Format format) {
- scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
-
- size_t stride_in_bytes = 0;
- if (!StrideInBytes(size.width(), format, &stride_in_bytes))
+ size_t buffer_size = 0u;
+ if (!BufferSizeInBytes(size, format, &buffer_size))
return scoped_ptr<GpuMemoryBufferImpl>();
- base::CheckedNumeric<size_t> size_in_bytes = stride_in_bytes;
- size_in_bytes *= size.height();
- if (!size_in_bytes.IsValid())
- return scoped_ptr<GpuMemoryBufferImpl>();
-
- if (!shared_memory->CreateAndMapAnonymous(size_in_bytes.ValueOrDie()))
+ scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
+ if (!shared_memory->CreateAndMapAnonymous(buffer_size))
return scoped_ptr<GpuMemoryBufferImpl>();
return make_scoped_ptr(new GpuMemoryBufferImplSharedMemory(
@@ -61,17 +55,12 @@ GpuMemoryBufferImplSharedMemory::AllocateForChildProcess(
const gfx::Size& size,
Format format,
base::ProcessHandle child_process) {
- size_t stride_in_bytes = 0;
- if (!StrideInBytes(size.width(), format, &stride_in_bytes))
- return gfx::GpuMemoryBufferHandle();
-
- base::CheckedNumeric<int> buffer_size = stride_in_bytes;
- buffer_size *= size.height();
- if (!buffer_size.IsValid())
+ size_t buffer_size = 0u;
+ if (!BufferSizeInBytes(size, format, &buffer_size))
return gfx::GpuMemoryBufferHandle();
base::SharedMemory shared_memory;
- if (!shared_memory.CreateAnonymous(buffer_size.ValueOrDie()))
+ if (!shared_memory.CreateAnonymous(buffer_size))
return gfx::GpuMemoryBufferHandle();
gfx::GpuMemoryBufferHandle handle;
@@ -82,6 +71,27 @@ GpuMemoryBufferImplSharedMemory::AllocateForChildProcess(
}
// static
+bool GpuMemoryBufferImplSharedMemory::BufferSizeInBytes(const gfx::Size& size,
+ Format format,
+ size_t* size_in_bytes) {
+ base::CheckedNumeric<size_t> checked_size_in_bytes = 0u;
+ for (size_t i = 0; i < NumberOfPlanesForGpuMemoryBufferFormat(format); ++i) {
+ size_t stride_in_bytes = 0;
+ if (!StrideInBytes(size.width(), format, i, &stride_in_bytes))
+ return false;
+ base::CheckedNumeric<size_t> checked_plane_size_in_bytes = stride_in_bytes;
+ checked_plane_size_in_bytes *= size.height() / SubsamplingFactor(format, i);
+ if (!checked_plane_size_in_bytes.IsValid())
+ return false;
+ checked_size_in_bytes += checked_plane_size_in_bytes.ValueOrDie();
+ if (!checked_size_in_bytes.IsValid())
+ return false;
+ }
+ *size_in_bytes = checked_size_in_bytes.ValueOrDie();
+ return true;
+}
+
+// static
scoped_ptr<GpuMemoryBufferImpl>
GpuMemoryBufferImplSharedMemory::CreateFromHandle(
const gfx::GpuMemoryBufferHandle& handle,
@@ -91,18 +101,13 @@ GpuMemoryBufferImplSharedMemory::CreateFromHandle(
if (!base::SharedMemory::IsHandleValid(handle.handle))
return scoped_ptr<GpuMemoryBufferImpl>();
- size_t stride_in_bytes = 0;
- if (!StrideInBytes(size.width(), format, &stride_in_bytes))
- return scoped_ptr<GpuMemoryBufferImpl>();
-
- base::CheckedNumeric<size_t> size_in_bytes = stride_in_bytes;
- size_in_bytes *= size.height();
- if (!size_in_bytes.IsValid())
+ size_t buffer_size = 0u;
+ if (!BufferSizeInBytes(size, format, &buffer_size))
return scoped_ptr<GpuMemoryBufferImpl>();
scoped_ptr<base::SharedMemory> shared_memory(
new base::SharedMemory(handle.handle, false));
- if (!shared_memory->Map(size_in_bytes.ValueOrDie()))
+ if (!shared_memory->Map(buffer_size))
return scoped_ptr<GpuMemoryBufferImpl>();
return make_scoped_ptr<GpuMemoryBufferImpl>(
@@ -124,6 +129,7 @@ bool GpuMemoryBufferImplSharedMemory::IsFormatSupported(Format format) {
case ETC1:
case RGBA_8888:
case BGRA_8888:
+ case YUV_420:
return true;
case RGBX_8888:
return false;
@@ -150,6 +156,15 @@ bool GpuMemoryBufferImplSharedMemory::IsSizeValidForFormat(
case BGRA_8888:
case RGBX_8888:
return true;
+ case YUV_420: {
+ for (size_t i = 0; i < NumberOfPlanesForGpuMemoryBufferFormat(format);
+ ++i) {
+ size_t factor = SubsamplingFactor(format, i);
+ if (size.width() % factor || size.height() % factor)
+ return false;
+ }
+ return true;
+ }
}
NOTREACHED();
@@ -158,8 +173,19 @@ bool GpuMemoryBufferImplSharedMemory::IsSizeValidForFormat(
bool GpuMemoryBufferImplSharedMemory::Map(void** data) {
DCHECK(!mapped_);
+ data[0] = shared_memory_->memory();
+ // Map the other planes if they exist.
+ for (size_t i = 0; i < NumberOfPlanesForGpuMemoryBufferFormat(format_) - 1;
+ ++i) {
+ size_t stride_in_bytes = 0;
+ bool valid_stride =
+ StrideInBytes(size_.width(), format_, i, &stride_in_bytes);
+ DCHECK(valid_stride);
+ data[i + 1] =
+ reinterpret_cast<uint8*>(data[i]) +
+ stride_in_bytes * (size_.height() / SubsamplingFactor(format_, i));
+ }
mapped_ = true;
- *data = shared_memory_->memory();
return true;
}
@@ -169,10 +195,13 @@ void GpuMemoryBufferImplSharedMemory::Unmap() {
}
void GpuMemoryBufferImplSharedMemory::GetStride(uint32* stride) const {
- size_t stride_in_bytes = 0;
- bool valid_stride = StrideInBytes(size_.width(), format_, &stride_in_bytes);
- DCHECK(valid_stride);
- *stride = stride_in_bytes;
+ for (size_t i = 0; i < NumberOfPlanesForGpuMemoryBufferFormat(format_); ++i) {
+ size_t stride_in_bytes = 0;
+ bool valid_stride =
+ StrideInBytes(size_.width(), format_, i, &stride_in_bytes);
+ DCHECK(valid_stride);
+ stride[i] = stride_in_bytes;
+ }
}
gfx::GpuMemoryBufferHandle GpuMemoryBufferImplSharedMemory::GetHandle() const {
diff --git a/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h b/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h
index c7eb80c..e93ab32 100644
--- a/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h
+++ b/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h
@@ -24,6 +24,12 @@ class GpuMemoryBufferImplSharedMemory : public GpuMemoryBufferImpl {
Format format,
base::ProcessHandle child_process);
+ // Calculates the number of bytes used to store all the planes of a given
+ // |format|.
+ static bool BufferSizeInBytes(const gfx::Size& size,
+ Format format,
+ size_t* size_in_bytes);
+
static scoped_ptr<GpuMemoryBufferImpl> CreateFromHandle(
const gfx::GpuMemoryBufferHandle& handle,
const gfx::Size& size,
diff --git a/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.cc b/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.cc
index a1d0e5c..8ed95a9 100644
--- a/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.cc
+++ b/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.cc
@@ -23,6 +23,7 @@ int WindowFormat(gfx::GpuMemoryBuffer::Format format) {
case gfx::GpuMemoryBuffer::ETC1:
case gfx::GpuMemoryBuffer::RGBX_8888:
case gfx::GpuMemoryBuffer::BGRA_8888:
+ case gfx::GpuMemoryBuffer::YUV_420:
NOTREACHED();
return 0;
}
@@ -81,7 +82,7 @@ bool GpuMemoryBufferImplSurfaceTexture::Map(void** data) {
}
size_t stride_in_bytes = 0;
- if (!StrideInBytes(buffer.stride, format_, &stride_in_bytes))
+ if (!StrideInBytes(buffer.stride, format_, 0, &stride_in_bytes))
return false;
DCHECK_LE(size_.width(), buffer.stride);
diff --git a/content/common/gpu/client/gpu_memory_buffer_impl_unittest.cc b/content/common/gpu/client/gpu_memory_buffer_impl_unittest.cc
index ba55d78..d73dae7 100644
--- a/content/common/gpu/client/gpu_memory_buffer_impl_unittest.cc
+++ b/content/common/gpu/client/gpu_memory_buffer_impl_unittest.cc
@@ -52,7 +52,7 @@ class GpuMemoryBufferImplTest
TEST_P(GpuMemoryBufferImplTest, CreateFromHandle) {
const int kBufferId = 1;
- gfx::Size buffer_size(1, 1);
+ gfx::Size buffer_size(8, 8);
for (auto configuration : supported_configurations_) {
scoped_ptr<GpuMemoryBufferImpl> buffer(
@@ -79,42 +79,50 @@ TEST_P(GpuMemoryBufferImplTest, CreateFromHandle) {
TEST_P(GpuMemoryBufferImplTest, Map) {
const int kBufferId = 1;
- gfx::Size buffer_size(1, 1);
+ gfx::Size buffer_size(2, 2);
for (auto configuration : supported_configurations_) {
if (configuration.usage != gfx::GpuMemoryBuffer::MAP)
continue;
- size_t width_in_bytes = 0;
- EXPECT_TRUE(GpuMemoryBufferImpl::StrideInBytes(
- buffer_size.width(), configuration.format, &width_in_bytes));
- EXPECT_GT(width_in_bytes, 0u);
- scoped_ptr<char[]> data(new char[width_in_bytes]);
- memset(data.get(), 0x2a, width_in_bytes);
-
scoped_ptr<GpuMemoryBufferImpl> buffer(
GpuMemoryBufferImpl::CreateFromHandle(
- CreateGpuMemoryBuffer(kBufferId,
- buffer_size,
- configuration.format,
+ CreateGpuMemoryBuffer(kBufferId, buffer_size, configuration.format,
configuration.usage),
- buffer_size,
- configuration.format,
+ buffer_size, configuration.format,
base::Bind(&GpuMemoryBufferImplTest::DestroyGpuMemoryBuffer,
- base::Unretained(this),
- kBufferId)));
+ base::Unretained(this), kBufferId)));
ASSERT_TRUE(buffer);
EXPECT_FALSE(buffer->IsMapped());
- void* memory;
- bool rv = buffer->Map(&memory);
+ size_t num_planes =
+ GpuMemoryBufferImpl::NumberOfPlanesForGpuMemoryBufferFormat(
+ configuration.format);
+
+ // Map buffer into user space.
+ scoped_ptr<void*[]> mapped_buffers(new void*[num_planes]);
+ bool rv = buffer->Map(mapped_buffers.get());
ASSERT_TRUE(rv);
EXPECT_TRUE(buffer->IsMapped());
- uint32 stride;
- buffer->GetStride(&stride);
- EXPECT_GE(stride, width_in_bytes);
- memcpy(memory, data.get(), width_in_bytes);
- EXPECT_EQ(memcmp(memory, data.get(), width_in_bytes), 0);
+
+ // Get strides.
+ scoped_ptr<uint32[]> strides(new uint32[num_planes]);
+ buffer->GetStride(strides.get());
+
+ // Copy and compare mapped buffers.
+ for (size_t i = 0; i < num_planes; ++i) {
+ size_t width_in_bytes = 0u;
+ EXPECT_TRUE(GpuMemoryBufferImpl::StrideInBytes(
+ buffer_size.width(), configuration.format, i, &width_in_bytes));
+ EXPECT_GT(width_in_bytes, 0u);
+ EXPECT_GE(strides[i], width_in_bytes);
+
+ scoped_ptr<char[]> data(new char[width_in_bytes]);
+ memset(data.get(), 0x2a + i, width_in_bytes);
+ memcpy(mapped_buffers[i], data.get(), width_in_bytes);
+ EXPECT_EQ(memcmp(mapped_buffers[i], data.get(), width_in_bytes), 0);
+ }
+
buffer->Unmap();
EXPECT_FALSE(buffer->IsMapped());
}
diff --git a/content/common/gpu/gpu_memory_buffer_factory_io_surface.cc b/content/common/gpu/gpu_memory_buffer_factory_io_surface.cc
index 604c1b4..2737a4d 100644
--- a/content/common/gpu/gpu_memory_buffer_factory_io_surface.cc
+++ b/content/common/gpu/gpu_memory_buffer_factory_io_surface.cc
@@ -38,6 +38,7 @@ int32 BytesPerPixel(gfx::GpuMemoryBuffer::Format format) {
case gfx::GpuMemoryBuffer::ETC1:
case gfx::GpuMemoryBuffer::RGBA_8888:
case gfx::GpuMemoryBuffer::RGBX_8888:
+ case gfx::GpuMemoryBuffer::YUV_420:
NOTREACHED();
return 0;
}
@@ -57,6 +58,7 @@ int32 PixelFormat(gfx::GpuMemoryBuffer::Format format) {
case gfx::GpuMemoryBuffer::ETC1:
case gfx::GpuMemoryBuffer::RGBA_8888:
case gfx::GpuMemoryBuffer::RGBX_8888:
+ case gfx::GpuMemoryBuffer::YUV_420:
NOTREACHED();
return 0;
}
diff --git a/content/common/gpu/gpu_memory_buffer_factory_shared_memory.cc b/content/common/gpu/gpu_memory_buffer_factory_shared_memory.cc
index 790fcab..992decd 100644
--- a/content/common/gpu/gpu_memory_buffer_factory_shared_memory.cc
+++ b/content/common/gpu/gpu_memory_buffer_factory_shared_memory.cc
@@ -7,7 +7,7 @@
#include <vector>
#include "base/logging.h"
-#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
+#include "content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h"
#include "ui/gl/gl_image.h"
#include "ui/gl/gl_image_shared_memory.h"
@@ -24,7 +24,8 @@ void GpuMemoryBufferFactorySharedMemory::
std::vector<Configuration>* configurations) {
const Configuration supported_configurations[] = {
{ gfx::GpuMemoryBuffer::RGBA_8888, gfx::GpuMemoryBuffer::MAP },
- { gfx::GpuMemoryBuffer::BGRA_8888, gfx::GpuMemoryBuffer::MAP }
+ { gfx::GpuMemoryBuffer::BGRA_8888, gfx::GpuMemoryBuffer::MAP },
+ { gfx::GpuMemoryBuffer::YUV_420, gfx::GpuMemoryBuffer::MAP }
};
configurations->assign(
supported_configurations,
@@ -39,19 +40,13 @@ GpuMemoryBufferFactorySharedMemory::CreateGpuMemoryBuffer(
gfx::GpuMemoryBuffer::Usage usage,
int client_id,
gfx::PluginWindowHandle surface_handle) {
- base::SharedMemory shared_memory;
-
- size_t stride_in_bytes = 0;
- if (!GpuMemoryBufferImpl::StrideInBytes(
- size.width(), format, &stride_in_bytes))
+ size_t buffer_size = 0u;
+ if (!GpuMemoryBufferImplSharedMemory::BufferSizeInBytes(size, format,
+ &buffer_size))
return gfx::GpuMemoryBufferHandle();
- base::CheckedNumeric<size_t> size_in_bytes = stride_in_bytes;
- size_in_bytes *= size.height();
- if (!size_in_bytes.IsValid())
- return gfx::GpuMemoryBufferHandle();
-
- if (!shared_memory.CreateAnonymous(size_in_bytes.ValueOrDie()))
+ base::SharedMemory shared_memory;
+ if (!shared_memory.CreateAnonymous(buffer_size))
return gfx::GpuMemoryBufferHandle();
gfx::GpuMemoryBufferHandle handle;
diff --git a/content/common/gpu/gpu_memory_buffer_factory_unittest.cc b/content/common/gpu/gpu_memory_buffer_factory_unittest.cc
index a191433..f9dc7e1 100644
--- a/content/common/gpu/gpu_memory_buffer_factory_unittest.cc
+++ b/content/common/gpu/gpu_memory_buffer_factory_unittest.cc
@@ -31,7 +31,7 @@ TEST_P(GpuMemoryBufferFactoryTest, CreateAndDestroy) {
const int kBufferId = 1;
const int kClientId = 1;
- gfx::Size buffer_size(1, 1);
+ gfx::Size buffer_size(2, 2);
for (auto configuration : supported_configurations_) {
gfx::GpuMemoryBufferHandle handle = factory_->CreateGpuMemoryBuffer(
diff --git a/gpu/command_buffer/service/image_factory.cc b/gpu/command_buffer/service/image_factory.cc
index a80d17c..f09cfb8 100644
--- a/gpu/command_buffer/service/image_factory.cc
+++ b/gpu/command_buffer/service/image_factory.cc
@@ -80,6 +80,7 @@ bool ImageFactory::IsGpuMemoryBufferFormatSupported(
return capabilities.texture_format_etc1;
case gfx::GpuMemoryBuffer::RGBA_8888:
case gfx::GpuMemoryBuffer::RGBX_8888:
+ case gfx::GpuMemoryBuffer::YUV_420:
return true;
}
@@ -103,6 +104,7 @@ bool ImageFactory::IsImageSizeValidForGpuMemoryBufferFormat(
case gfx::GpuMemoryBuffer::RGBA_8888:
case gfx::GpuMemoryBuffer::BGRA_8888:
case gfx::GpuMemoryBuffer::RGBX_8888:
+ case gfx::GpuMemoryBuffer::YUV_420:
return true;
}
diff --git a/gpu/command_buffer/tests/gl_gpu_memory_buffer_unittest.cc b/gpu/command_buffer/tests/gl_gpu_memory_buffer_unittest.cc
index 052bd3d..9368da5 100644
--- a/gpu/command_buffer/tests/gl_gpu_memory_buffer_unittest.cc
+++ b/gpu/command_buffer/tests/gl_gpu_memory_buffer_unittest.cc
@@ -98,6 +98,7 @@ std::vector<uint8> GetTexturePixel(const gfx::GpuMemoryBuffer::Format format) {
case gfx::GpuMemoryBuffer::DXT5:
case gfx::GpuMemoryBuffer::ETC1:
case gfx::GpuMemoryBuffer::RGBX_8888:
+ case gfx::GpuMemoryBuffer::YUV_420:
NOTREACHED();
return std::vector<uint8>();
}
@@ -123,6 +124,7 @@ std::vector<uint8> GetFramebufferPixel(
case gfx::GpuMemoryBuffer::DXT5:
case gfx::GpuMemoryBuffer::ETC1:
case gfx::GpuMemoryBuffer::RGBX_8888:
+ case gfx::GpuMemoryBuffer::YUV_420:
NOTREACHED();
return std::vector<uint8>();
}
@@ -143,6 +145,7 @@ GLenum InternalFormat(gfx::GpuMemoryBuffer::Format format) {
case gfx::GpuMemoryBuffer::DXT5:
case gfx::GpuMemoryBuffer::ETC1:
case gfx::GpuMemoryBuffer::RGBX_8888:
+ case gfx::GpuMemoryBuffer::YUV_420:
NOTREACHED();
return 0;
}
diff --git a/gpu/command_buffer/tests/gl_manager.cc b/gpu/command_buffer/tests/gl_manager.cc
index 67bdbb8..3a3d7e9 100644
--- a/gpu/command_buffer/tests/gl_manager.cc
+++ b/gpu/command_buffer/tests/gl_manager.cc
@@ -38,28 +38,85 @@
namespace gpu {
namespace {
-size_t StrideInBytes(size_t width, gfx::GpuMemoryBuffer::Format format) {
+size_t NumberOfPlanesForGpuMemoryBufferFormat(
+ gfx::GpuMemoryBuffer::Format format) {
+ switch (format) {
+ case gfx::GpuMemoryBuffer::Format::ATC:
+ case gfx::GpuMemoryBuffer::Format::ATCIA:
+ case gfx::GpuMemoryBuffer::Format::DXT1:
+ case gfx::GpuMemoryBuffer::Format::DXT5:
+ case gfx::GpuMemoryBuffer::Format::ETC1:
+ case gfx::GpuMemoryBuffer::Format::RGBA_8888:
+ case gfx::GpuMemoryBuffer::Format::RGBX_8888:
+ case gfx::GpuMemoryBuffer::Format::BGRA_8888:
+ return 1;
+ case gfx::GpuMemoryBuffer::Format::YUV_420:
+ return 3;
+ }
+ NOTREACHED();
+ return 0;
+}
+
+size_t SubsamplingFactor(gfx::GpuMemoryBuffer::Format format, int plane) {
switch (format) {
+ case gfx::GpuMemoryBuffer::ATC:
case gfx::GpuMemoryBuffer::ATCIA:
+ case gfx::GpuMemoryBuffer::DXT1:
case gfx::GpuMemoryBuffer::DXT5:
+ case gfx::GpuMemoryBuffer::ETC1:
+ case gfx::GpuMemoryBuffer::RGBA_8888:
+ case gfx::GpuMemoryBuffer::RGBX_8888:
+ case gfx::GpuMemoryBuffer::BGRA_8888:
+ return 1;
+ case gfx::GpuMemoryBuffer::YUV_420: {
+ static size_t factor[] = {1, 2, 2};
+ DCHECK_LT(static_cast<size_t>(plane), arraysize(factor));
+ return factor[plane];
+ }
+ }
+ NOTREACHED();
+ return 0;
+}
+
+size_t StrideInBytes(size_t width,
+ gfx::GpuMemoryBuffer::Format format,
+ int plane) {
+ switch (format) {
+ case gfx::GpuMemoryBuffer::ATCIA:
+ case gfx::GpuMemoryBuffer::DXT5:
+ DCHECK_EQ(plane, 0);
return width;
case gfx::GpuMemoryBuffer::ATC:
case gfx::GpuMemoryBuffer::DXT1:
case gfx::GpuMemoryBuffer::ETC1:
+ DCHECK_EQ(plane, 0);
DCHECK_EQ(width % 2, 0U);
return width / 2;
case gfx::GpuMemoryBuffer::RGBA_8888:
case gfx::GpuMemoryBuffer::BGRA_8888:
+ DCHECK_EQ(plane, 0);
return width * 4;
case gfx::GpuMemoryBuffer::RGBX_8888:
NOTREACHED();
return 0;
+ case gfx::GpuMemoryBuffer::YUV_420:
+ return width / SubsamplingFactor(format, plane);
}
NOTREACHED();
return 0;
}
+size_t BufferSizeInBytes(const gfx::Size& size,
+ gfx::GpuMemoryBuffer::Format format) {
+ size_t size_in_bytes = 0u;
+ for (size_t i = 0; i < NumberOfPlanesForGpuMemoryBufferFormat(format); ++i) {
+ size_in_bytes += StrideInBytes(size.width(), format, i) *
+ (size.height() / SubsamplingFactor(format, i));
+ }
+ return size_in_bytes;
+}
+
class GpuMemoryBufferImpl : public gfx::GpuMemoryBuffer {
public:
GpuMemoryBufferImpl(base::RefCountedBytes* bytes,
@@ -73,15 +130,24 @@ class GpuMemoryBufferImpl : public gfx::GpuMemoryBuffer {
// Overridden from gfx::GpuMemoryBuffer:
bool Map(void** data) override {
+ data[0] = &bytes_->data().front();
+ for (size_t i = 0; i < NumberOfPlanesForGpuMemoryBufferFormat(format_) - 1;
+ ++i) {
+ size_t offset = StrideInBytes(size_.width(), format_, i) *
+ (size_.height() / SubsamplingFactor(format_, i));
+ data[i + 1] = reinterpret_cast<uint8*>(data[i]) + offset;
+ }
mapped_ = true;
- *data = &bytes_->data().front();
return true;
}
void Unmap() override { mapped_ = false; }
bool IsMapped() const override { return mapped_; }
Format GetFormat() const override { return format_; }
void GetStride(uint32* stride) const override {
- *stride = StrideInBytes(size_.width(), format_);
+ for (size_t i = 0; i < NumberOfPlanesForGpuMemoryBufferFormat(format_);
+ ++i) {
+ stride[i] = StrideInBytes(size_.width(), format_, i);
+ }
}
gfx::GpuMemoryBufferHandle GetHandle() const override {
NOTREACHED();
@@ -143,8 +209,7 @@ GLManager::~GLManager() {
scoped_ptr<gfx::GpuMemoryBuffer> GLManager::CreateGpuMemoryBuffer(
const gfx::Size& size,
gfx::GpuMemoryBuffer::Format format) {
- std::vector<unsigned char> data(
- StrideInBytes(size.width(), format) * size.height(), 0);
+ std::vector<unsigned char> data(BufferSizeInBytes(size, format), 0);
scoped_refptr<base::RefCountedBytes> bytes(new base::RefCountedBytes(data));
return make_scoped_ptr<gfx::GpuMemoryBuffer>(
new GpuMemoryBufferImpl(bytes.get(), size, format));
diff --git a/ui/gfx/gpu_memory_buffer.h b/ui/gfx/gpu_memory_buffer.h
index e56009f..6383a13 100644
--- a/ui/gfx/gpu_memory_buffer.h
+++ b/ui/gfx/gpu_memory_buffer.h
@@ -51,8 +51,9 @@ class GFX_EXPORT GpuMemoryBuffer {
RGBA_8888,
RGBX_8888,
BGRA_8888,
+ YUV_420,
- FORMAT_LAST = BGRA_8888
+ FORMAT_LAST = YUV_420
};
// The usage mode affects how a buffer can be used. Only buffers created with
diff --git a/ui/gl/gl_image_linux_dma_buffer.cc b/ui/gl/gl_image_linux_dma_buffer.cc
index 04ad06b..080c9b5 100644
--- a/ui/gl/gl_image_linux_dma_buffer.cc
+++ b/ui/gl/gl_image_linux_dma_buffer.cc
@@ -39,6 +39,7 @@ bool ValidFormat(unsigned internalformat, gfx::GpuMemoryBuffer::Format format) {
case gfx::GpuMemoryBuffer::ETC1:
case gfx::GpuMemoryBuffer::RGBA_8888:
case gfx::GpuMemoryBuffer::BGRA_8888:
+ case gfx::GpuMemoryBuffer::YUV_420:
return false;
}
NOTREACHED();
@@ -54,6 +55,7 @@ bool ValidFormat(unsigned internalformat, gfx::GpuMemoryBuffer::Format format) {
case gfx::GpuMemoryBuffer::ETC1:
case gfx::GpuMemoryBuffer::RGBX_8888:
case gfx::GpuMemoryBuffer::RGBA_8888:
+ case gfx::GpuMemoryBuffer::YUV_420:
return false;
}
NOTREACHED();
@@ -75,6 +77,7 @@ EGLint FourCC(gfx::GpuMemoryBuffer::Format format) {
case gfx::GpuMemoryBuffer::DXT5:
case gfx::GpuMemoryBuffer::ETC1:
case gfx::GpuMemoryBuffer::RGBA_8888:
+ case gfx::GpuMemoryBuffer::YUV_420:
NOTREACHED();
return 0;
}
diff --git a/ui/gl/gl_image_memory.cc b/ui/gl/gl_image_memory.cc
index 9022917..ff9c97e 100644
--- a/ui/gl/gl_image_memory.cc
+++ b/ui/gl/gl_image_memory.cc
@@ -38,6 +38,7 @@ bool ValidFormat(gfx::GpuMemoryBuffer::Format format) {
case gfx::GpuMemoryBuffer::BGRA_8888:
return true;
case gfx::GpuMemoryBuffer::RGBX_8888:
+ case gfx::GpuMemoryBuffer::YUV_420:
return false;
}
@@ -52,6 +53,7 @@ bool IsCompressedFormat(gfx::GpuMemoryBuffer::Format format) {
case gfx::GpuMemoryBuffer::DXT1:
case gfx::GpuMemoryBuffer::DXT5:
case gfx::GpuMemoryBuffer::ETC1:
+ case gfx::GpuMemoryBuffer::YUV_420:
return true;
case gfx::GpuMemoryBuffer::RGBA_8888:
case gfx::GpuMemoryBuffer::BGRA_8888:
@@ -80,6 +82,7 @@ GLenum TextureFormat(gfx::GpuMemoryBuffer::Format format) {
case gfx::GpuMemoryBuffer::BGRA_8888:
return GL_BGRA_EXT;
case gfx::GpuMemoryBuffer::RGBX_8888:
+ case gfx::GpuMemoryBuffer::YUV_420:
NOTREACHED();
return 0;
}
@@ -103,6 +106,7 @@ GLenum DataType(gfx::GpuMemoryBuffer::Format format) {
case gfx::GpuMemoryBuffer::DXT5:
case gfx::GpuMemoryBuffer::ETC1:
case gfx::GpuMemoryBuffer::RGBX_8888:
+ case gfx::GpuMemoryBuffer::YUV_420:
NOTREACHED();
return 0;
}
@@ -153,10 +157,6 @@ bool GLImageMemory::StrideInBytes(size_t width,
size_t* stride_in_bytes) {
base::CheckedNumeric<size_t> s = width;
switch (format) {
- case gfx::GpuMemoryBuffer::ATCIA:
- case gfx::GpuMemoryBuffer::DXT5:
- *stride_in_bytes = width;
- return true;
case gfx::GpuMemoryBuffer::ATC:
case gfx::GpuMemoryBuffer::DXT1:
case gfx::GpuMemoryBuffer::ETC1:
@@ -164,18 +164,21 @@ bool GLImageMemory::StrideInBytes(size_t width,
s /= 2;
if (!s.IsValid())
return false;
-
*stride_in_bytes = s.ValueOrDie();
return true;
+ case gfx::GpuMemoryBuffer::ATCIA:
+ case gfx::GpuMemoryBuffer::DXT5:
+ *stride_in_bytes = width;
+ return true;
case gfx::GpuMemoryBuffer::RGBA_8888:
case gfx::GpuMemoryBuffer::BGRA_8888:
s *= 4;
if (!s.IsValid())
return false;
-
*stride_in_bytes = s.ValueOrDie();
return true;
case gfx::GpuMemoryBuffer::RGBX_8888:
+ case gfx::GpuMemoryBuffer::YUV_420:
NOTREACHED();
return false;
}
diff --git a/ui/ozone/gpu/gpu_memory_buffer_factory_ozone_native_buffer.cc b/ui/ozone/gpu/gpu_memory_buffer_factory_ozone_native_buffer.cc
index 38667e5..145b3e6 100644
--- a/ui/ozone/gpu/gpu_memory_buffer_factory_ozone_native_buffer.cc
+++ b/ui/ozone/gpu/gpu_memory_buffer_factory_ozone_native_buffer.cc
@@ -96,6 +96,7 @@ SurfaceFactoryOzone::BufferFormat GetOzoneFormatFor(
case gfx::GpuMemoryBuffer::DXT5:
case gfx::GpuMemoryBuffer::ETC1:
case gfx::GpuMemoryBuffer::BGRA_8888:
+ case gfx::GpuMemoryBuffer::YUV_420:
NOTREACHED();
return SurfaceFactoryOzone::RGBA_8888;
}