From 607ed17ba5d0d1c67901ecc7160db660f08bd831 Mon Sep 17 00:00:00 2001 From: emircan Date: Tue, 7 Apr 2015 23:25:00 -0700 Subject: 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} --- gpu/command_buffer/service/image_factory.cc | 2 + .../tests/gl_gpu_memory_buffer_unittest.cc | 3 + gpu/command_buffer/tests/gl_manager.cc | 75 ++++++++++++++++++++-- 3 files changed, 75 insertions(+), 5 deletions(-) (limited to 'gpu') 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 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(); } @@ -123,6 +124,7 @@ std::vector GetFramebufferPixel( case gfx::GpuMemoryBuffer::DXT5: case gfx::GpuMemoryBuffer::ETC1: case gfx::GpuMemoryBuffer::RGBX_8888: + case gfx::GpuMemoryBuffer::YUV_420: NOTREACHED(); return std::vector(); } @@ -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(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(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 GLManager::CreateGpuMemoryBuffer( const gfx::Size& size, gfx::GpuMemoryBuffer::Format format) { - std::vector data( - StrideInBytes(size.width(), format) * size.height(), 0); + std::vector data(BufferSizeInBytes(size, format), 0); scoped_refptr bytes(new base::RefCountedBytes(data)); return make_scoped_ptr( new GpuMemoryBufferImpl(bytes.get(), size, format)); -- cgit v1.1