Roll src/third_party/WebKit eac3800:0237a66 (svn 202606:202607)
[chromium-blink-merge.git] / content / common / gpu / gpu_memory_buffer_factory_io_surface.cc
bloba6ce59fdd627b57c58a0eee83af99206a8e8712c
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/common/gpu/gpu_memory_buffer_factory_io_surface.h"
7 #include <CoreFoundation/CoreFoundation.h>
9 #include <vector>
11 #include "base/logging.h"
12 #include "content/common/gpu/client/gpu_memory_buffer_impl.h"
13 #include "ui/gfx/buffer_format_util.h"
14 #include "ui/gl/gl_image_io_surface.h"
16 namespace content {
17 namespace {
19 void AddIntegerValue(CFMutableDictionaryRef dictionary,
20 const CFStringRef key,
21 int32 value) {
22 base::ScopedCFTypeRef<CFNumberRef> number(
23 CFNumberCreate(NULL, kCFNumberSInt32Type, &value));
24 CFDictionaryAddValue(dictionary, key, number.get());
27 int32 BytesPerElement(gfx::BufferFormat format, int plane) {
28 switch (format) {
29 case gfx::BufferFormat::R_8:
30 DCHECK_EQ(plane, 0);
31 return 1;
32 case gfx::BufferFormat::BGRA_8888:
33 DCHECK_EQ(plane, 0);
34 return 4;
35 case gfx::BufferFormat::YUV_420_BIPLANAR:
36 static int32 bytes_per_element[] = {1, 2};
37 DCHECK_LT(static_cast<size_t>(plane), arraysize(bytes_per_element));
38 return bytes_per_element[plane];
39 case gfx::BufferFormat::UYVY_422:
40 DCHECK_EQ(plane, 0);
41 return 2;
42 case gfx::BufferFormat::ATC:
43 case gfx::BufferFormat::ATCIA:
44 case gfx::BufferFormat::DXT1:
45 case gfx::BufferFormat::DXT5:
46 case gfx::BufferFormat::ETC1:
47 case gfx::BufferFormat::RGBA_4444:
48 case gfx::BufferFormat::RGBA_8888:
49 case gfx::BufferFormat::BGRX_8888:
50 case gfx::BufferFormat::YUV_420:
51 NOTREACHED();
52 return 0;
55 NOTREACHED();
56 return 0;
59 int32 PixelFormat(gfx::BufferFormat format) {
60 switch (format) {
61 case gfx::BufferFormat::R_8:
62 return 'L008';
63 case gfx::BufferFormat::BGRA_8888:
64 return 'BGRA';
65 case gfx::BufferFormat::YUV_420_BIPLANAR:
66 return '420v';
67 case gfx::BufferFormat::UYVY_422:
68 return '2vuy';
69 case gfx::BufferFormat::ATC:
70 case gfx::BufferFormat::ATCIA:
71 case gfx::BufferFormat::DXT1:
72 case gfx::BufferFormat::DXT5:
73 case gfx::BufferFormat::ETC1:
74 case gfx::BufferFormat::RGBA_4444:
75 case gfx::BufferFormat::RGBA_8888:
76 case gfx::BufferFormat::BGRX_8888:
77 case gfx::BufferFormat::YUV_420:
78 NOTREACHED();
79 return 0;
82 NOTREACHED();
83 return 0;
86 const GpuMemoryBufferFactory::Configuration kSupportedConfigurations[] = {
87 {gfx::BufferFormat::BGRA_8888, gfx::BufferUsage::SCANOUT},
88 {gfx::BufferFormat::R_8, gfx::BufferUsage::PERSISTENT_MAP},
89 {gfx::BufferFormat::R_8, gfx::BufferUsage::MAP},
90 {gfx::BufferFormat::BGRA_8888, gfx::BufferUsage::PERSISTENT_MAP},
91 {gfx::BufferFormat::BGRA_8888, gfx::BufferUsage::MAP},
92 {gfx::BufferFormat::UYVY_422, gfx::BufferUsage::MAP},
93 {gfx::BufferFormat::UYVY_422, gfx::BufferUsage::PERSISTENT_MAP},
94 {gfx::BufferFormat::YUV_420_BIPLANAR, gfx::BufferUsage::MAP},
95 {gfx::BufferFormat::YUV_420_BIPLANAR, gfx::BufferUsage::PERSISTENT_MAP},
98 } // namespace
100 GpuMemoryBufferFactoryIOSurface::GpuMemoryBufferFactoryIOSurface() {
103 GpuMemoryBufferFactoryIOSurface::~GpuMemoryBufferFactoryIOSurface() {
106 // static
107 bool GpuMemoryBufferFactoryIOSurface::IsGpuMemoryBufferConfigurationSupported(
108 gfx::BufferFormat format,
109 gfx::BufferUsage usage) {
110 for (auto& configuration : kSupportedConfigurations) {
111 if (configuration.format == format && configuration.usage == usage)
112 return true;
115 return false;
118 void GpuMemoryBufferFactoryIOSurface::GetSupportedGpuMemoryBufferConfigurations(
119 std::vector<Configuration>* configurations) {
120 configurations->assign(
121 kSupportedConfigurations,
122 kSupportedConfigurations + arraysize(kSupportedConfigurations));
125 gfx::GpuMemoryBufferHandle
126 GpuMemoryBufferFactoryIOSurface::CreateGpuMemoryBuffer(
127 gfx::GpuMemoryBufferId id,
128 const gfx::Size& size,
129 gfx::BufferFormat format,
130 gfx::BufferUsage usage,
131 int client_id,
132 gfx::PluginWindowHandle surface_handle) {
133 size_t num_planes = gfx::NumberOfPlanesForBufferFormat(format);
134 base::ScopedCFTypeRef<CFMutableArrayRef> planes(CFArrayCreateMutable(
135 kCFAllocatorDefault, num_planes, &kCFTypeArrayCallBacks));
137 for (size_t plane = 0; plane < num_planes; ++plane) {
138 size_t factor = gfx::SubsamplingFactorForBufferFormat(format, plane);
140 base::ScopedCFTypeRef<CFMutableDictionaryRef> plane_info(
141 CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
142 &kCFTypeDictionaryKeyCallBacks,
143 &kCFTypeDictionaryValueCallBacks));
144 AddIntegerValue(plane_info, kIOSurfacePlaneWidth, size.width() / factor);
145 AddIntegerValue(plane_info, kIOSurfacePlaneHeight, size.height() / factor);
146 AddIntegerValue(plane_info, kIOSurfacePlaneBytesPerElement,
147 BytesPerElement(format, plane));
149 CFArrayAppendValue(planes, plane_info);
152 base::ScopedCFTypeRef<CFMutableDictionaryRef> properties(
153 CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
154 &kCFTypeDictionaryKeyCallBacks,
155 &kCFTypeDictionaryValueCallBacks));
156 AddIntegerValue(properties, kIOSurfaceWidth, size.width());
157 AddIntegerValue(properties, kIOSurfaceHeight, size.height());
158 AddIntegerValue(properties, kIOSurfacePixelFormat, PixelFormat(format));
159 CFDictionaryAddValue(properties, kIOSurfacePlaneInfo, planes);
161 base::ScopedCFTypeRef<IOSurfaceRef> io_surface(IOSurfaceCreate(properties));
162 if (!io_surface)
163 return gfx::GpuMemoryBufferHandle();
165 if (!IOSurfaceManager::GetInstance()->RegisterIOSurface(id, client_id,
166 io_surface)) {
167 return gfx::GpuMemoryBufferHandle();
171 base::AutoLock lock(io_surfaces_lock_);
173 IOSurfaceMapKey key(id, client_id);
174 DCHECK(io_surfaces_.find(key) == io_surfaces_.end());
175 io_surfaces_[key] = io_surface;
178 gfx::GpuMemoryBufferHandle handle;
179 handle.type = gfx::IO_SURFACE_BUFFER;
180 handle.id = id;
181 return handle;
184 void GpuMemoryBufferFactoryIOSurface::DestroyGpuMemoryBuffer(
185 gfx::GpuMemoryBufferId id,
186 int client_id) {
188 base::AutoLock lock(io_surfaces_lock_);
190 IOSurfaceMapKey key(id, client_id);
191 DCHECK(io_surfaces_.find(key) != io_surfaces_.end());
192 io_surfaces_.erase(key);
195 IOSurfaceManager::GetInstance()->UnregisterIOSurface(id, client_id);
198 gpu::ImageFactory* GpuMemoryBufferFactoryIOSurface::AsImageFactory() {
199 return this;
202 scoped_refptr<gfx::GLImage>
203 GpuMemoryBufferFactoryIOSurface::CreateImageForGpuMemoryBuffer(
204 const gfx::GpuMemoryBufferHandle& handle,
205 const gfx::Size& size,
206 gfx::BufferFormat format,
207 unsigned internalformat,
208 int client_id) {
209 base::AutoLock lock(io_surfaces_lock_);
211 DCHECK_EQ(handle.type, gfx::IO_SURFACE_BUFFER);
212 IOSurfaceMapKey key(handle.id, client_id);
213 IOSurfaceMap::iterator it = io_surfaces_.find(key);
214 if (it == io_surfaces_.end())
215 return scoped_refptr<gfx::GLImage>();
217 scoped_refptr<gfx::GLImageIOSurface> image(
218 new gfx::GLImageIOSurface(handle.id, size, internalformat));
219 if (!image->Initialize(it->second.get(), format))
220 return scoped_refptr<gfx::GLImage>();
222 return image;
225 } // namespace content