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"
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>
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) {
34 bool ValidFormat(BufferFormat format) {
36 case BufferFormat::R_8:
37 case BufferFormat::BGRA_8888:
39 case BufferFormat::ATC:
40 case BufferFormat::ATCIA:
41 case BufferFormat::DXT1:
42 case BufferFormat::DXT5:
43 case BufferFormat::ETC1:
44 case BufferFormat::RGBA_4444:
45 case BufferFormat::RGBA_8888:
46 case BufferFormat::RGBX_8888:
47 case BufferFormat::YUV_420:
55 GLenum TextureFormat(BufferFormat format) {
57 case BufferFormat::R_8:
59 case BufferFormat::BGRA_8888:
61 case BufferFormat::ATC:
62 case BufferFormat::ATCIA:
63 case BufferFormat::DXT1:
64 case BufferFormat::DXT5:
65 case BufferFormat::ETC1:
66 case BufferFormat::RGBA_4444:
67 case BufferFormat::RGBA_8888:
68 case BufferFormat::RGBX_8888:
69 case BufferFormat::YUV_420:
78 GLenum DataFormat(BufferFormat format) {
80 case BufferFormat::R_8:
82 case BufferFormat::BGRA_8888:
84 case BufferFormat::ATC:
85 case BufferFormat::ATCIA:
86 case BufferFormat::DXT1:
87 case BufferFormat::DXT5:
88 case BufferFormat::ETC1:
89 case BufferFormat::RGBA_4444:
90 case BufferFormat::RGBA_8888:
91 case BufferFormat::RGBX_8888:
92 case BufferFormat::YUV_420:
101 GLenum DataType(BufferFormat format) {
103 case BufferFormat::R_8:
104 return GL_UNSIGNED_BYTE;
105 case BufferFormat::BGRA_8888:
106 return GL_UNSIGNED_INT_8_8_8_8_REV;
107 case BufferFormat::ATC:
108 case BufferFormat::ATCIA:
109 case BufferFormat::DXT1:
110 case BufferFormat::DXT5:
111 case BufferFormat::ETC1:
112 case BufferFormat::RGBA_4444:
113 case BufferFormat::RGBA_8888:
114 case BufferFormat::RGBX_8888:
115 case BufferFormat::YUV_420:
126 GLImageIOSurface::GLImageIOSurface(const gfx::Size& size,
127 unsigned internalformat)
129 internalformat_(internalformat),
130 format_(BufferFormat::RGBA_8888) {}
132 GLImageIOSurface::~GLImageIOSurface() {
133 DCHECK(thread_checker_.CalledOnValidThread());
134 DCHECK(!io_surface_);
137 bool GLImageIOSurface::Initialize(IOSurfaceRef io_surface,
138 BufferFormat format) {
139 DCHECK(thread_checker_.CalledOnValidThread());
140 DCHECK(!io_surface_);
142 if (!ValidInternalFormat(internalformat_)) {
143 LOG(ERROR) << "Invalid internalformat: " << internalformat_;
147 if (!ValidFormat(format)) {
148 LOG(ERROR) << "Invalid format: " << static_cast<int>(format);
153 io_surface_.reset(io_surface, base::scoped_policy::RETAIN);
157 void GLImageIOSurface::Destroy(bool have_context) {
158 DCHECK(thread_checker_.CalledOnValidThread());
162 gfx::Size GLImageIOSurface::GetSize() { return size_; }
164 unsigned GLImageIOSurface::GetInternalFormat() { return internalformat_; }
166 bool GLImageIOSurface::BindTexImage(unsigned target) {
167 DCHECK(thread_checker_.CalledOnValidThread());
168 if (target != GL_TEXTURE_RECTANGLE_ARB) {
169 // This might be supported in the future. For now, perform strict
170 // validation so we know what's going on.
171 LOG(ERROR) << "IOSurface requires TEXTURE_RECTANGLE_ARB target";
175 CGLContextObj cgl_context =
176 static_cast<CGLContextObj>(GLContext::GetCurrent()->GetHandle());
180 CGLTexImageIOSurface2D(cgl_context, target, TextureFormat(format_),
181 size_.width(), size_.height(), DataFormat(format_),
182 DataType(format_), io_surface_.get(), 0);
183 if (cgl_error != kCGLNoError) {
184 LOG(ERROR) << "Error in CGLTexImageIOSurface2D";
191 bool GLImageIOSurface::CopyTexSubImage(unsigned target,
197 bool GLImageIOSurface::ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
199 OverlayTransform transform,
200 const Rect& bounds_rect,
201 const RectF& crop_rect) {
202 // Only simple overlay planes are currently supported.
203 DCHECK_EQ(0, z_order);
204 DCHECK_EQ(gfx::RectF(0, 0, 1, 1).ToString(), crop_rect.ToString());
205 DCHECK_EQ(gfx::OVERLAY_TRANSFORM_NONE, transform);
207 // Convert the phony widget to the appropriate CALayer.
208 auto found = g_widget_to_layer_map.Pointer()->find(widget);
209 if (found == g_widget_to_layer_map.Pointer()->end())
211 CALayer* layer = found->second;
213 // Also note that transactions are not disabled. The caller must ensure that
214 // all changes to the CALayer tree happen atomically.
215 [layer setContents:static_cast<id>(io_surface_.get())];
216 [layer setFrame:bounds_rect.ToCGRect()];
221 void GLImageIOSurface::SetLayerForWidget(
222 gfx::AcceleratedWidget widget, CALayer* layer) {
224 g_widget_to_layer_map.Pointer()->insert(std::make_pair(widget, layer));
226 g_widget_to_layer_map.Pointer()->erase(widget);