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>
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"
19 void AddIntegerValue(CFMutableDictionaryRef dictionary
,
20 const CFStringRef key
,
22 base::ScopedCFTypeRef
<CFNumberRef
> number(
23 CFNumberCreate(NULL
, kCFNumberSInt32Type
, &value
));
24 CFDictionaryAddValue(dictionary
, key
, number
.get());
27 int32
BytesPerElement(gfx::BufferFormat format
, int plane
) {
29 case gfx::BufferFormat::R_8
:
32 case gfx::BufferFormat::BGRA_8888
:
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
:
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
:
59 int32
PixelFormat(gfx::BufferFormat format
) {
61 case gfx::BufferFormat::R_8
:
63 case gfx::BufferFormat::BGRA_8888
:
65 case gfx::BufferFormat::YUV_420_BIPLANAR
:
67 case gfx::BufferFormat::UYVY_422
:
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
:
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
},
100 GpuMemoryBufferFactoryIOSurface::GpuMemoryBufferFactoryIOSurface() {
103 GpuMemoryBufferFactoryIOSurface::~GpuMemoryBufferFactoryIOSurface() {
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
)
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
,
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
));
163 return gfx::GpuMemoryBufferHandle();
165 if (!IOSurfaceManager::GetInstance()->RegisterIOSurface(id
, client_id
,
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
;
184 void GpuMemoryBufferFactoryIOSurface::DestroyGpuMemoryBuffer(
185 gfx::GpuMemoryBufferId 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() {
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
,
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
>();
225 } // namespace content