GPU workaround to simulate Out of Memory errors with large textures
[chromium-blink-merge.git] / content / common / gpu / gpu_memory_buffer_factory_io_surface.cc
blob604c1b4927388f956c415939b023ce24b242932c
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 "base/logging.h"
10 #include "ui/gl/gl_image_io_surface.h"
12 namespace content {
13 namespace {
15 void AddBooleanValue(CFMutableDictionaryRef dictionary,
16 const CFStringRef key,
17 bool value) {
18 CFDictionaryAddValue(
19 dictionary, key, value ? kCFBooleanTrue : kCFBooleanFalse);
22 void AddIntegerValue(CFMutableDictionaryRef dictionary,
23 const CFStringRef key,
24 int32 value) {
25 base::ScopedCFTypeRef<CFNumberRef> number(
26 CFNumberCreate(NULL, kCFNumberSInt32Type, &value));
27 CFDictionaryAddValue(dictionary, key, number.get());
30 int32 BytesPerPixel(gfx::GpuMemoryBuffer::Format format) {
31 switch (format) {
32 case gfx::GpuMemoryBuffer::BGRA_8888:
33 return 4;
34 case gfx::GpuMemoryBuffer::ATC:
35 case gfx::GpuMemoryBuffer::ATCIA:
36 case gfx::GpuMemoryBuffer::DXT1:
37 case gfx::GpuMemoryBuffer::DXT5:
38 case gfx::GpuMemoryBuffer::ETC1:
39 case gfx::GpuMemoryBuffer::RGBA_8888:
40 case gfx::GpuMemoryBuffer::RGBX_8888:
41 NOTREACHED();
42 return 0;
45 NOTREACHED();
46 return 0;
49 int32 PixelFormat(gfx::GpuMemoryBuffer::Format format) {
50 switch (format) {
51 case gfx::GpuMemoryBuffer::BGRA_8888:
52 return 'BGRA';
53 case gfx::GpuMemoryBuffer::ATC:
54 case gfx::GpuMemoryBuffer::ATCIA:
55 case gfx::GpuMemoryBuffer::DXT1:
56 case gfx::GpuMemoryBuffer::DXT5:
57 case gfx::GpuMemoryBuffer::ETC1:
58 case gfx::GpuMemoryBuffer::RGBA_8888:
59 case gfx::GpuMemoryBuffer::RGBX_8888:
60 NOTREACHED();
61 return 0;
64 NOTREACHED();
65 return 0;
68 const GpuMemoryBufferFactory::Configuration kSupportedConfigurations[] = {
69 { gfx::GpuMemoryBuffer::BGRA_8888, gfx::GpuMemoryBuffer::MAP }
72 } // namespace
74 GpuMemoryBufferFactoryIOSurface::GpuMemoryBufferFactoryIOSurface() {
77 GpuMemoryBufferFactoryIOSurface::~GpuMemoryBufferFactoryIOSurface() {
80 // static
81 bool GpuMemoryBufferFactoryIOSurface::IsGpuMemoryBufferConfigurationSupported(
82 gfx::GpuMemoryBuffer::Format format,
83 gfx::GpuMemoryBuffer::Usage usage) {
84 for (auto& configuration : kSupportedConfigurations) {
85 if (configuration.format == format && configuration.usage == usage)
86 return true;
89 return false;
92 void GpuMemoryBufferFactoryIOSurface::GetSupportedGpuMemoryBufferConfigurations(
93 std::vector<Configuration>* configurations) {
94 configurations->assign(
95 kSupportedConfigurations,
96 kSupportedConfigurations + arraysize(kSupportedConfigurations));
99 gfx::GpuMemoryBufferHandle
100 GpuMemoryBufferFactoryIOSurface::CreateGpuMemoryBuffer(
101 gfx::GpuMemoryBufferId id,
102 const gfx::Size& size,
103 gfx::GpuMemoryBuffer::Format format,
104 gfx::GpuMemoryBuffer::Usage usage,
105 int client_id,
106 gfx::PluginWindowHandle surface_handle) {
107 base::ScopedCFTypeRef<CFMutableDictionaryRef> properties;
108 properties.reset(CFDictionaryCreateMutable(kCFAllocatorDefault,
110 &kCFTypeDictionaryKeyCallBacks,
111 &kCFTypeDictionaryValueCallBacks));
112 AddIntegerValue(properties, kIOSurfaceWidth, size.width());
113 AddIntegerValue(properties, kIOSurfaceHeight, size.height());
114 AddIntegerValue(properties, kIOSurfaceBytesPerElement, BytesPerPixel(format));
115 AddIntegerValue(properties, kIOSurfacePixelFormat, PixelFormat(format));
116 // TODO(reveman): Remove this when using a mach_port_t to transfer
117 // IOSurface to browser and renderer process. crbug.com/323304
118 AddBooleanValue(properties, kIOSurfaceIsGlobal, true);
120 base::ScopedCFTypeRef<IOSurfaceRef> io_surface(IOSurfaceCreate(properties));
121 if (!io_surface)
122 return gfx::GpuMemoryBufferHandle();
125 base::AutoLock lock(io_surfaces_lock_);
127 IOSurfaceMapKey key(id, client_id);
128 DCHECK(io_surfaces_.find(key) == io_surfaces_.end());
129 io_surfaces_[key] = io_surface;
132 gfx::GpuMemoryBufferHandle handle;
133 handle.type = gfx::IO_SURFACE_BUFFER;
134 handle.id = id;
135 handle.io_surface_id = IOSurfaceGetID(io_surface);
136 return handle;
139 void GpuMemoryBufferFactoryIOSurface::DestroyGpuMemoryBuffer(
140 gfx::GpuMemoryBufferId id,
141 int client_id) {
142 base::AutoLock lock(io_surfaces_lock_);
144 IOSurfaceMapKey key(id, client_id);
145 IOSurfaceMap::iterator it = io_surfaces_.find(key);
146 if (it != io_surfaces_.end())
147 io_surfaces_.erase(it);
150 gpu::ImageFactory* GpuMemoryBufferFactoryIOSurface::AsImageFactory() {
151 return this;
154 scoped_refptr<gfx::GLImage>
155 GpuMemoryBufferFactoryIOSurface::CreateImageForGpuMemoryBuffer(
156 const gfx::GpuMemoryBufferHandle& handle,
157 const gfx::Size& size,
158 gfx::GpuMemoryBuffer::Format format,
159 unsigned internalformat,
160 int client_id) {
161 base::AutoLock lock(io_surfaces_lock_);
163 DCHECK_EQ(handle.type, gfx::IO_SURFACE_BUFFER);
164 IOSurfaceMapKey key(handle.id, client_id);
165 IOSurfaceMap::iterator it = io_surfaces_.find(key);
166 if (it == io_surfaces_.end())
167 return scoped_refptr<gfx::GLImage>();
169 scoped_refptr<gfx::GLImageIOSurface> image(new gfx::GLImageIOSurface(size));
170 if (!image->Initialize(it->second.get()))
171 return scoped_refptr<gfx::GLImage>();
173 return image;
176 } // namespace content