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) {
35 bool ValidFormat(BufferFormat format) {
37 case BufferFormat::R_8:
38 case BufferFormat::BGRA_8888:
39 case BufferFormat::UYVY_422:
41 case BufferFormat::ATC:
42 case BufferFormat::ATCIA:
43 case BufferFormat::DXT1:
44 case BufferFormat::DXT5:
45 case BufferFormat::ETC1:
46 case BufferFormat::RGBA_4444:
47 case BufferFormat::RGBA_8888:
48 case BufferFormat::BGRX_8888:
49 case BufferFormat::YUV_420:
57 GLenum TextureFormat(BufferFormat format) {
59 case BufferFormat::R_8:
61 case BufferFormat::BGRA_8888:
63 case BufferFormat::UYVY_422:
65 case BufferFormat::ATC:
66 case BufferFormat::ATCIA:
67 case BufferFormat::DXT1:
68 case BufferFormat::DXT5:
69 case BufferFormat::ETC1:
70 case BufferFormat::RGBA_4444:
71 case BufferFormat::RGBA_8888:
72 case BufferFormat::BGRX_8888:
73 case BufferFormat::YUV_420:
82 GLenum DataFormat(BufferFormat format) {
84 case BufferFormat::R_8:
86 case BufferFormat::BGRA_8888:
88 case BufferFormat::UYVY_422:
89 return GL_YCBCR_422_APPLE;
91 case BufferFormat::ATC:
92 case BufferFormat::ATCIA:
93 case BufferFormat::DXT1:
94 case BufferFormat::DXT5:
95 case BufferFormat::ETC1:
96 case BufferFormat::RGBA_4444:
97 case BufferFormat::RGBA_8888:
98 case BufferFormat::BGRX_8888:
99 case BufferFormat::YUV_420:
108 GLenum DataType(BufferFormat format) {
110 case BufferFormat::R_8:
111 return GL_UNSIGNED_BYTE;
112 case BufferFormat::BGRA_8888:
113 return GL_UNSIGNED_INT_8_8_8_8_REV;
114 case BufferFormat::UYVY_422:
115 return GL_UNSIGNED_SHORT_8_8_APPLE;
117 case BufferFormat::ATC:
118 case BufferFormat::ATCIA:
119 case BufferFormat::DXT1:
120 case BufferFormat::DXT5:
121 case BufferFormat::ETC1:
122 case BufferFormat::RGBA_4444:
123 case BufferFormat::RGBA_8888:
124 case BufferFormat::BGRX_8888:
125 case BufferFormat::YUV_420:
136 GLImageIOSurface::GLImageIOSurface(gfx::GenericSharedMemoryId io_surface_id,
137 const gfx::Size& size,
138 unsigned internalformat)
139 : io_surface_id_(io_surface_id),
141 internalformat_(internalformat),
142 format_(BufferFormat::RGBA_8888) {}
144 GLImageIOSurface::~GLImageIOSurface() {
145 DCHECK(thread_checker_.CalledOnValidThread());
146 DCHECK(!io_surface_);
149 bool GLImageIOSurface::Initialize(IOSurfaceRef io_surface,
150 BufferFormat format) {
151 DCHECK(thread_checker_.CalledOnValidThread());
152 DCHECK(!io_surface_);
154 if (!ValidInternalFormat(internalformat_)) {
155 LOG(ERROR) << "Invalid internalformat: " << internalformat_;
159 if (!ValidFormat(format)) {
160 LOG(ERROR) << "Invalid format: " << static_cast<int>(format);
165 io_surface_.reset(io_surface, base::scoped_policy::RETAIN);
169 void GLImageIOSurface::Destroy(bool have_context) {
170 DCHECK(thread_checker_.CalledOnValidThread());
174 gfx::Size GLImageIOSurface::GetSize() { return size_; }
176 unsigned GLImageIOSurface::GetInternalFormat() { return internalformat_; }
178 bool GLImageIOSurface::BindTexImage(unsigned target) {
179 DCHECK(thread_checker_.CalledOnValidThread());
180 if (target != GL_TEXTURE_RECTANGLE_ARB) {
181 // This might be supported in the future. For now, perform strict
182 // validation so we know what's going on.
183 LOG(ERROR) << "IOSurface requires TEXTURE_RECTANGLE_ARB target";
187 CGLContextObj cgl_context =
188 static_cast<CGLContextObj>(GLContext::GetCurrent()->GetHandle());
192 CGLTexImageIOSurface2D(cgl_context, target, TextureFormat(format_),
193 size_.width(), size_.height(), DataFormat(format_),
194 DataType(format_), io_surface_.get(), 0);
195 if (cgl_error != kCGLNoError) {
196 LOG(ERROR) << "Error in CGLTexImageIOSurface2D";
203 bool GLImageIOSurface::CopyTexSubImage(unsigned target,
209 bool GLImageIOSurface::ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
211 OverlayTransform transform,
212 const Rect& bounds_rect,
213 const RectF& crop_rect) {
218 void GLImageIOSurface::OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd,
219 uint64_t process_tracing_id,
220 const std::string& dump_name) {
221 // IOSurfaceGetAllocSize will return 0 if io_surface_ is invalid. In this case
222 // we log 0 for consistency with other GLImage memory dump functions.
223 size_t size_bytes = IOSurfaceGetAllocSize(io_surface_);
225 base::trace_event::MemoryAllocatorDump* dump =
226 pmd->CreateAllocatorDump(dump_name);
227 dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
228 base::trace_event::MemoryAllocatorDump::kUnitsBytes,
229 static_cast<uint64_t>(size_bytes));
231 auto guid = gfx::GetGenericSharedMemoryGUIDForTracing(process_tracing_id,
233 pmd->CreateSharedGlobalAllocatorDump(guid);
234 pmd->AddOwnershipEdge(dump->guid(), guid);
237 base::ScopedCFTypeRef<IOSurfaceRef> GLImageIOSurface::io_surface() {
242 void GLImageIOSurface::SetLayerForWidget(
243 gfx::AcceleratedWidget widget, CALayer* layer) {
245 g_widget_to_layer_map.Pointer()->insert(std::make_pair(widget, layer));
247 g_widget_to_layer_map.Pointer()->erase(widget);