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) {
29 case GL_RGB_YCBCR_422_CHROMIUM:
36 bool ValidFormat(BufferFormat format) {
38 case BufferFormat::R_8:
39 case BufferFormat::BGRA_8888:
40 case BufferFormat::UYVY_422:
41 case BufferFormat::YUV_420_BIPLANAR:
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:
59 GLenum TextureFormat(BufferFormat format) {
61 case BufferFormat::R_8:
62 case BufferFormat::YUV_420_BIPLANAR:
64 case BufferFormat::BGRA_8888:
66 case BufferFormat::UYVY_422:
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:
85 GLenum DataFormat(BufferFormat format) {
87 case BufferFormat::R_8:
88 case BufferFormat::YUV_420_BIPLANAR:
90 case BufferFormat::BGRA_8888:
92 case BufferFormat::UYVY_422:
93 return GL_YCBCR_422_APPLE;
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:
112 GLenum DataType(BufferFormat 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;
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:
141 GLImageIOSurface::GLImageIOSurface(gfx::GenericSharedMemoryId io_surface_id,
142 const gfx::Size& size,
143 unsigned internalformat)
144 : io_surface_id_(io_surface_id),
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_;
164 if (!ValidFormat(format)) {
165 LOG(ERROR) << "Invalid format: " << static_cast<int>(format);
170 io_surface_.reset(io_surface, base::scoped_policy::RETAIN);
174 void GLImageIOSurface::Destroy(bool have_context) {
175 DCHECK(thread_checker_.CalledOnValidThread());
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";
192 CGLContextObj cgl_context =
193 static_cast<CGLContextObj>(GLContext::GetCurrent()->GetHandle());
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";
208 bool GLImageIOSurface::CopyTexSubImage(unsigned target,
214 bool GLImageIOSurface::ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
216 OverlayTransform transform,
217 const Rect& bounds_rect,
218 const RectF& crop_rect) {
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,
238 pmd->CreateSharedGlobalAllocatorDump(guid);
239 pmd->AddOwnershipEdge(dump->guid(), guid);
242 base::ScopedCFTypeRef<IOSurfaceRef> GLImageIOSurface::io_surface() {
247 void GLImageIOSurface::SetLayerForWidget(
248 gfx::AcceleratedWidget widget, CALayer* layer) {
250 g_widget_to_layer_map.Pointer()->insert(std::make_pair(widget, layer));
252 g_widget_to_layer_map.Pointer()->erase(widget);