Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / ui / gl / gl_image_io_surface.mm
blob211226a27b373701bda3b7375637823e1c741f66
1 // Copyright 2013 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 "ui/gl/gl_image_io_surface.h"
7 #include <map>
9 #include "base/lazy_instance.h"
10 #include "base/mac/foundation_util.h"
11 #include "ui/gl/gl_bindings.h"
12 #include "ui/gl/gl_context.h"
14 // Note that this must be included after gl_bindings.h to avoid conflicts.
15 #include <OpenGL/CGLIOSurface.h>
16 #include <Quartz/Quartz.h>
18 namespace gfx {
19 namespace {
21 typedef std::map<gfx::AcceleratedWidget,CALayer*> WidgetToLayerMap;
22 base::LazyInstance<WidgetToLayerMap> g_widget_to_layer_map;
24 bool ValidInternalFormat(unsigned internalformat) {
25   switch (internalformat) {
26     case GL_R8:
27     case GL_BGRA_EXT:
28     case GL_RGB:
29     case GL_RGB_YCBCR_422_CHROMIUM:
30       return true;
31     default:
32       return false;
33   }
36 bool ValidFormat(BufferFormat format) {
37   switch (format) {
38     case BufferFormat::R_8:
39     case BufferFormat::BGRA_8888:
40     case BufferFormat::UYVY_422:
41     case BufferFormat::YUV_420_BIPLANAR:
42       return true;
43     case BufferFormat::ATC:
44     case BufferFormat::ATCIA:
45     case BufferFormat::DXT1:
46     case BufferFormat::DXT5:
47     case BufferFormat::ETC1:
48     case BufferFormat::RGBA_4444:
49     case BufferFormat::RGBA_8888:
50     case BufferFormat::BGRX_8888:
51     case BufferFormat::YUV_420:
52       return false;
53   }
55   NOTREACHED();
56   return false;
59 GLenum TextureFormat(BufferFormat format) {
60   switch (format) {
61     case BufferFormat::R_8:
62     case BufferFormat::YUV_420_BIPLANAR:
63       return GL_RED;
64     case BufferFormat::BGRA_8888:
65       return GL_RGBA;
66     case BufferFormat::UYVY_422:
67       return GL_RGB;
68     case BufferFormat::ATC:
69     case BufferFormat::ATCIA:
70     case BufferFormat::DXT1:
71     case BufferFormat::DXT5:
72     case BufferFormat::ETC1:
73     case BufferFormat::RGBA_4444:
74     case BufferFormat::RGBA_8888:
75     case BufferFormat::BGRX_8888:
76     case BufferFormat::YUV_420:
77       NOTREACHED();
78       return 0;
79   }
81   NOTREACHED();
82   return 0;
85 GLenum DataFormat(BufferFormat format) {
86   switch (format) {
87     case BufferFormat::R_8:
88     case BufferFormat::YUV_420_BIPLANAR:
89       return GL_RED;
90     case BufferFormat::BGRA_8888:
91       return GL_BGRA;
92     case BufferFormat::UYVY_422:
93       return GL_YCBCR_422_APPLE;
94       break;
95     case BufferFormat::ATC:
96     case BufferFormat::ATCIA:
97     case BufferFormat::DXT1:
98     case BufferFormat::DXT5:
99     case BufferFormat::ETC1:
100     case BufferFormat::RGBA_4444:
101     case BufferFormat::RGBA_8888:
102     case BufferFormat::BGRX_8888:
103     case BufferFormat::YUV_420:
104       NOTREACHED();
105       return 0;
106   }
108   NOTREACHED();
109   return 0;
112 GLenum DataType(BufferFormat format) {
113   switch (format) {
114     case BufferFormat::R_8:
115     case BufferFormat::YUV_420_BIPLANAR:
116       return GL_UNSIGNED_BYTE;
117     case BufferFormat::BGRA_8888:
118       return GL_UNSIGNED_INT_8_8_8_8_REV;
119     case BufferFormat::UYVY_422:
120       return GL_UNSIGNED_SHORT_8_8_APPLE;
121       break;
122     case BufferFormat::ATC:
123     case BufferFormat::ATCIA:
124     case BufferFormat::DXT1:
125     case BufferFormat::DXT5:
126     case BufferFormat::ETC1:
127     case BufferFormat::RGBA_4444:
128     case BufferFormat::RGBA_8888:
129     case BufferFormat::BGRX_8888:
130     case BufferFormat::YUV_420:
131       NOTREACHED();
132       return 0;
133   }
135   NOTREACHED();
136   return 0;
139 }  // namespace
141 GLImageIOSurface::GLImageIOSurface(gfx::GenericSharedMemoryId io_surface_id,
142                                    const gfx::Size& size,
143                                    unsigned internalformat)
144     : io_surface_id_(io_surface_id),
145       size_(size),
146       internalformat_(internalformat),
147       format_(BufferFormat::RGBA_8888) {}
149 GLImageIOSurface::~GLImageIOSurface() {
150   DCHECK(thread_checker_.CalledOnValidThread());
151   DCHECK(!io_surface_);
154 bool GLImageIOSurface::Initialize(IOSurfaceRef io_surface,
155                                   BufferFormat format) {
156   DCHECK(thread_checker_.CalledOnValidThread());
157   DCHECK(!io_surface_);
159   if (!ValidInternalFormat(internalformat_)) {
160     LOG(ERROR) << "Invalid internalformat: " << internalformat_;
161     return false;
162   }
164   if (!ValidFormat(format)) {
165     LOG(ERROR) << "Invalid format: " << static_cast<int>(format);
166     return false;
167   }
169   format_ = format;
170   io_surface_.reset(io_surface, base::scoped_policy::RETAIN);
171   return true;
174 void GLImageIOSurface::Destroy(bool have_context) {
175   DCHECK(thread_checker_.CalledOnValidThread());
176   io_surface_.reset();
179 gfx::Size GLImageIOSurface::GetSize() { return size_; }
181 unsigned GLImageIOSurface::GetInternalFormat() { return internalformat_; }
183 bool GLImageIOSurface::BindTexImage(unsigned target) {
184   DCHECK(thread_checker_.CalledOnValidThread());
185   if (target != GL_TEXTURE_RECTANGLE_ARB) {
186     // This might be supported in the future. For now, perform strict
187     // validation so we know what's going on.
188     LOG(ERROR) << "IOSurface requires TEXTURE_RECTANGLE_ARB target";
189     return false;
190   }
192   CGLContextObj cgl_context =
193       static_cast<CGLContextObj>(GLContext::GetCurrent()->GetHandle());
195   DCHECK(io_surface_);
196   CGLError cgl_error =
197       CGLTexImageIOSurface2D(cgl_context, target, TextureFormat(format_),
198                              size_.width(), size_.height(), DataFormat(format_),
199                              DataType(format_), io_surface_.get(), 0);
200   if (cgl_error != kCGLNoError) {
201     LOG(ERROR) << "Error in CGLTexImageIOSurface2D";
202     return false;
203   }
205   return true;
208 bool GLImageIOSurface::CopyTexSubImage(unsigned target,
209                                        const Point& offset,
210                                        const Rect& rect) {
211   return false;
214 bool GLImageIOSurface::ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
215                                             int z_order,
216                                             OverlayTransform transform,
217                                             const Rect& bounds_rect,
218                                             const RectF& crop_rect) {
219   NOTREACHED();
220   return false;
223 void GLImageIOSurface::OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd,
224                                     uint64_t process_tracing_id,
225                                     const std::string& dump_name) {
226   // IOSurfaceGetAllocSize will return 0 if io_surface_ is invalid. In this case
227   // we log 0 for consistency with other GLImage memory dump functions.
228   size_t size_bytes = IOSurfaceGetAllocSize(io_surface_);
230   base::trace_event::MemoryAllocatorDump* dump =
231       pmd->CreateAllocatorDump(dump_name);
232   dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
233                   base::trace_event::MemoryAllocatorDump::kUnitsBytes,
234                   static_cast<uint64_t>(size_bytes));
236   auto guid = gfx::GetGenericSharedMemoryGUIDForTracing(process_tracing_id,
237                                                         io_surface_id_);
238   pmd->CreateSharedGlobalAllocatorDump(guid);
239   pmd->AddOwnershipEdge(dump->guid(), guid);
242 base::ScopedCFTypeRef<IOSurfaceRef> GLImageIOSurface::io_surface() {
243   return io_surface_;
246 // static
247 void GLImageIOSurface::SetLayerForWidget(
248     gfx::AcceleratedWidget widget, CALayer* layer) {
249   if (layer)
250     g_widget_to_layer_map.Pointer()->insert(std::make_pair(widget, layer));
251   else
252     g_widget_to_layer_map.Pointer()->erase(widget);
255 }  // namespace gfx