Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / ui / gl / gl_image_io_surface.mm
blobb1f95f47beb229fa9e3cf15b0edfefaac5cbf86c
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       return true;
29     default:
30       return false;
31   }
34 bool ValidFormat(GpuMemoryBuffer::Format format) {
35   switch (format) {
36     case GpuMemoryBuffer::R_8:
37     case GpuMemoryBuffer::BGRA_8888:
38       return true;
39     case GpuMemoryBuffer::ATC:
40     case GpuMemoryBuffer::ATCIA:
41     case GpuMemoryBuffer::DXT1:
42     case GpuMemoryBuffer::DXT5:
43     case GpuMemoryBuffer::ETC1:
44     case GpuMemoryBuffer::RGBA_4444:
45     case GpuMemoryBuffer::RGBA_8888:
46     case GpuMemoryBuffer::RGBX_8888:
47     case GpuMemoryBuffer::YUV_420:
48       return false;
49   }
51   NOTREACHED();
52   return false;
55 GLenum TextureFormat(GpuMemoryBuffer::Format format) {
56   switch (format) {
57     case GpuMemoryBuffer::R_8:
58       return GL_RED;
59     case GpuMemoryBuffer::BGRA_8888:
60       return GL_RGBA;
61     case GpuMemoryBuffer::ATC:
62     case GpuMemoryBuffer::ATCIA:
63     case GpuMemoryBuffer::DXT1:
64     case GpuMemoryBuffer::DXT5:
65     case GpuMemoryBuffer::ETC1:
66     case GpuMemoryBuffer::RGBA_4444:
67     case GpuMemoryBuffer::RGBA_8888:
68     case GpuMemoryBuffer::RGBX_8888:
69     case GpuMemoryBuffer::YUV_420:
70       NOTREACHED();
71       return 0;
72   }
74   NOTREACHED();
75   return 0;
78 GLenum DataFormat(GpuMemoryBuffer::Format format) {
79   switch (format) {
80     case GpuMemoryBuffer::R_8:
81       return GL_RED;
82     case GpuMemoryBuffer::BGRA_8888:
83       return GL_BGRA;
84     case GpuMemoryBuffer::ATC:
85     case GpuMemoryBuffer::ATCIA:
86     case GpuMemoryBuffer::DXT1:
87     case GpuMemoryBuffer::DXT5:
88     case GpuMemoryBuffer::ETC1:
89     case GpuMemoryBuffer::RGBA_4444:
90     case GpuMemoryBuffer::RGBA_8888:
91     case GpuMemoryBuffer::RGBX_8888:
92     case GpuMemoryBuffer::YUV_420:
93       NOTREACHED();
94       return 0;
95   }
97   NOTREACHED();
98   return 0;
101 GLenum DataType(GpuMemoryBuffer::Format format) {
102   switch (format) {
103     case GpuMemoryBuffer::R_8:
104       return GL_UNSIGNED_BYTE;
105     case GpuMemoryBuffer::BGRA_8888:
106       return GL_UNSIGNED_INT_8_8_8_8_REV;
107     case GpuMemoryBuffer::ATC:
108     case GpuMemoryBuffer::ATCIA:
109     case GpuMemoryBuffer::DXT1:
110     case GpuMemoryBuffer::DXT5:
111     case GpuMemoryBuffer::ETC1:
112     case GpuMemoryBuffer::RGBA_4444:
113     case GpuMemoryBuffer::RGBA_8888:
114     case GpuMemoryBuffer::RGBX_8888:
115     case GpuMemoryBuffer::YUV_420:
116       NOTREACHED();
117       return 0;
118   }
120   NOTREACHED();
121   return 0;
124 }  // namespace
126 GLImageIOSurface::GLImageIOSurface(const gfx::Size& size,
127                                    unsigned internalformat)
128     : size_(size),
129       internalformat_(internalformat),
130       format_(GpuMemoryBuffer::RGBA_8888) {
133 GLImageIOSurface::~GLImageIOSurface() {
134   DCHECK(thread_checker_.CalledOnValidThread());
135   DCHECK(!io_surface_);
138 bool GLImageIOSurface::Initialize(IOSurfaceRef io_surface,
139                                   GpuMemoryBuffer::Format format) {
140   DCHECK(thread_checker_.CalledOnValidThread());
141   DCHECK(!io_surface_);
143   if (!ValidInternalFormat(internalformat_)) {
144     LOG(ERROR) << "Invalid internalformat: " << internalformat_;
145     return false;
146   }
148   if (!ValidFormat(format)) {
149     LOG(ERROR) << "Invalid format: " << format;
150     return false;
151   }
153   format_ = format;
154   io_surface_.reset(io_surface, base::scoped_policy::RETAIN);
155   return true;
158 void GLImageIOSurface::Destroy(bool have_context) {
159   DCHECK(thread_checker_.CalledOnValidThread());
160   io_surface_.reset();
163 gfx::Size GLImageIOSurface::GetSize() { return size_; }
165 unsigned GLImageIOSurface::GetInternalFormat() { return internalformat_; }
167 bool GLImageIOSurface::BindTexImage(unsigned target) {
168   DCHECK(thread_checker_.CalledOnValidThread());
169   if (target != GL_TEXTURE_RECTANGLE_ARB) {
170     // This might be supported in the future. For now, perform strict
171     // validation so we know what's going on.
172     LOG(ERROR) << "IOSurface requires TEXTURE_RECTANGLE_ARB target";
173     return false;
174   }
176   CGLContextObj cgl_context =
177       static_cast<CGLContextObj>(GLContext::GetCurrent()->GetHandle());
179   DCHECK(io_surface_);
180   CGLError cgl_error =
181       CGLTexImageIOSurface2D(cgl_context, target, TextureFormat(format_),
182                              size_.width(), size_.height(), DataFormat(format_),
183                              DataType(format_), io_surface_.get(), 0);
184   if (cgl_error != kCGLNoError) {
185     LOG(ERROR) << "Error in CGLTexImageIOSurface2D";
186     return false;
187   }
189   return true;
192 bool GLImageIOSurface::CopyTexSubImage(unsigned target,
193                                        const Point& offset,
194                                        const Rect& rect) {
195   return false;
198 bool GLImageIOSurface::ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
199                                             int z_order,
200                                             OverlayTransform transform,
201                                             const Rect& bounds_rect,
202                                             const RectF& crop_rect) {
203   // Only simple overlay planes are currently supported.
204   DCHECK_EQ(0, z_order);
205   DCHECK_EQ(gfx::RectF(0, 0, 1, 1).ToString(), crop_rect.ToString());
206   DCHECK_EQ(gfx::OVERLAY_TRANSFORM_NONE, transform);
208   // Convert the phony widget to the appropriate CALayer.
209   auto found = g_widget_to_layer_map.Pointer()->find(widget);
210   if (found == g_widget_to_layer_map.Pointer()->end())
211     return false;
212   CALayer* layer = found->second;
214   // Also note that transactions are not disabled. The caller must ensure that
215   // all changes to the CALayer tree happen atomically.
216   [layer setContents:static_cast<id>(io_surface_.get())];
217   [layer setFrame:bounds_rect.ToCGRect()];
218   return true;
221 // static
222 void GLImageIOSurface::SetLayerForWidget(
223     gfx::AcceleratedWidget widget, CALayer* layer) {
224   if (layer)
225     g_widget_to_layer_map.Pointer()->insert(std::make_pair(widget, layer));
226   else
227     g_widget_to_layer_map.Pointer()->erase(widget);
230 }  // namespace gfx