| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/gl/gl_image_io_surface.h" | 5 #include "ui/gl/gl_image_io_surface.h" |
| 6 | 6 |
| 7 #include <map> | 7 #include <map> |
| 8 | 8 |
| 9 #include "base/callback_helpers.h" | 9 #include "base/callback_helpers.h" |
| 10 #include "base/mac/bind_objc_block.h" | 10 #include "base/mac/bind_objc_block.h" |
| (...skipping 24 matching lines...) Expand all Loading... |
| 35 case GL_RGB: | 35 case GL_RGB: |
| 36 case GL_RGB_YCBCR_420V_CHROMIUM: | 36 case GL_RGB_YCBCR_420V_CHROMIUM: |
| 37 case GL_RGB_YCBCR_422_CHROMIUM: | 37 case GL_RGB_YCBCR_422_CHROMIUM: |
| 38 case GL_RGBA: | 38 case GL_RGBA: |
| 39 return true; | 39 return true; |
| 40 default: | 40 default: |
| 41 return false; | 41 return false; |
| 42 } | 42 } |
| 43 } | 43 } |
| 44 | 44 |
| 45 bool ValidFormat(BufferFormat format) { | 45 bool ValidFormat(gfx::BufferFormat format) { |
| 46 switch (format) { | 46 switch (format) { |
| 47 case BufferFormat::R_8: | 47 case gfx::BufferFormat::R_8: |
| 48 case BufferFormat::BGRA_8888: | 48 case gfx::BufferFormat::BGRA_8888: |
| 49 case BufferFormat::BGRX_8888: | 49 case gfx::BufferFormat::BGRX_8888: |
| 50 case BufferFormat::RGBA_8888: | 50 case gfx::BufferFormat::RGBA_8888: |
| 51 case BufferFormat::UYVY_422: | 51 case gfx::BufferFormat::UYVY_422: |
| 52 case BufferFormat::YUV_420_BIPLANAR: | 52 case gfx::BufferFormat::YUV_420_BIPLANAR: |
| 53 return true; | 53 return true; |
| 54 case BufferFormat::ATC: | 54 case gfx::BufferFormat::ATC: |
| 55 case BufferFormat::ATCIA: | 55 case gfx::BufferFormat::ATCIA: |
| 56 case BufferFormat::DXT1: | 56 case gfx::BufferFormat::DXT1: |
| 57 case BufferFormat::DXT5: | 57 case gfx::BufferFormat::DXT5: |
| 58 case BufferFormat::ETC1: | 58 case gfx::BufferFormat::ETC1: |
| 59 case BufferFormat::BGR_565: | 59 case gfx::BufferFormat::BGR_565: |
| 60 case BufferFormat::RGBA_4444: | 60 case gfx::BufferFormat::RGBA_4444: |
| 61 case BufferFormat::RGBX_8888: | 61 case gfx::BufferFormat::RGBX_8888: |
| 62 case BufferFormat::YUV_420: | 62 case gfx::BufferFormat::YUV_420: |
| 63 return false; | 63 return false; |
| 64 } | 64 } |
| 65 | 65 |
| 66 NOTREACHED(); | 66 NOTREACHED(); |
| 67 return false; | 67 return false; |
| 68 } | 68 } |
| 69 | 69 |
| 70 GLenum TextureFormat(BufferFormat format) { | 70 GLenum TextureFormat(gfx::BufferFormat format) { |
| 71 switch (format) { | 71 switch (format) { |
| 72 case BufferFormat::R_8: | 72 case gfx::BufferFormat::R_8: |
| 73 return GL_RED; | 73 return GL_RED; |
| 74 case BufferFormat::BGRA_8888: | 74 case gfx::BufferFormat::BGRA_8888: |
| 75 case BufferFormat::BGRX_8888: | 75 case gfx::BufferFormat::BGRX_8888: |
| 76 case BufferFormat::RGBA_8888: | 76 case gfx::BufferFormat::RGBA_8888: |
| 77 return GL_RGBA; | 77 return GL_RGBA; |
| 78 case BufferFormat::UYVY_422: | 78 case gfx::BufferFormat::UYVY_422: |
| 79 return GL_RGB; | 79 return GL_RGB; |
| 80 case BufferFormat::YUV_420_BIPLANAR: | 80 case gfx::BufferFormat::YUV_420_BIPLANAR: |
| 81 return GL_RGB_YCBCR_420V_CHROMIUM; | 81 return GL_RGB_YCBCR_420V_CHROMIUM; |
| 82 case BufferFormat::ATC: | 82 case gfx::BufferFormat::ATC: |
| 83 case BufferFormat::ATCIA: | 83 case gfx::BufferFormat::ATCIA: |
| 84 case BufferFormat::DXT1: | 84 case gfx::BufferFormat::DXT1: |
| 85 case BufferFormat::DXT5: | 85 case gfx::BufferFormat::DXT5: |
| 86 case BufferFormat::ETC1: | 86 case gfx::BufferFormat::ETC1: |
| 87 case BufferFormat::BGR_565: | 87 case gfx::BufferFormat::BGR_565: |
| 88 case BufferFormat::RGBA_4444: | 88 case gfx::BufferFormat::RGBA_4444: |
| 89 case BufferFormat::RGBX_8888: | 89 case gfx::BufferFormat::RGBX_8888: |
| 90 case BufferFormat::YUV_420: | 90 case gfx::BufferFormat::YUV_420: |
| 91 NOTREACHED(); | 91 NOTREACHED(); |
| 92 return 0; | 92 return 0; |
| 93 } | 93 } |
| 94 | 94 |
| 95 NOTREACHED(); | 95 NOTREACHED(); |
| 96 return 0; | 96 return 0; |
| 97 } | 97 } |
| 98 | 98 |
| 99 GLenum DataFormat(BufferFormat format) { | 99 GLenum DataFormat(gfx::BufferFormat format) { |
| 100 switch (format) { | 100 switch (format) { |
| 101 case BufferFormat::R_8: | 101 case gfx::BufferFormat::R_8: |
| 102 return GL_RED; | 102 return GL_RED; |
| 103 case BufferFormat::BGRA_8888: | 103 case gfx::BufferFormat::BGRA_8888: |
| 104 case BufferFormat::BGRX_8888: | 104 case gfx::BufferFormat::BGRX_8888: |
| 105 case BufferFormat::RGBA_8888: | 105 case gfx::BufferFormat::RGBA_8888: |
| 106 return GL_BGRA; | 106 return GL_BGRA; |
| 107 case BufferFormat::UYVY_422: | 107 case gfx::BufferFormat::UYVY_422: |
| 108 return GL_YCBCR_422_APPLE; | 108 return GL_YCBCR_422_APPLE; |
| 109 case BufferFormat::ATC: | 109 case gfx::BufferFormat::ATC: |
| 110 case BufferFormat::ATCIA: | 110 case gfx::BufferFormat::ATCIA: |
| 111 case BufferFormat::DXT1: | 111 case gfx::BufferFormat::DXT1: |
| 112 case BufferFormat::DXT5: | 112 case gfx::BufferFormat::DXT5: |
| 113 case BufferFormat::ETC1: | 113 case gfx::BufferFormat::ETC1: |
| 114 case BufferFormat::BGR_565: | 114 case gfx::BufferFormat::BGR_565: |
| 115 case BufferFormat::RGBA_4444: | 115 case gfx::BufferFormat::RGBA_4444: |
| 116 case BufferFormat::RGBX_8888: | 116 case gfx::BufferFormat::RGBX_8888: |
| 117 case BufferFormat::YUV_420: | 117 case gfx::BufferFormat::YUV_420: |
| 118 case BufferFormat::YUV_420_BIPLANAR: | 118 case gfx::BufferFormat::YUV_420_BIPLANAR: |
| 119 NOTREACHED(); | 119 NOTREACHED(); |
| 120 return 0; | 120 return 0; |
| 121 } | 121 } |
| 122 | 122 |
| 123 NOTREACHED(); | 123 NOTREACHED(); |
| 124 return 0; | 124 return 0; |
| 125 } | 125 } |
| 126 | 126 |
| 127 GLenum DataType(BufferFormat format) { | 127 GLenum DataType(gfx::BufferFormat format) { |
| 128 switch (format) { | 128 switch (format) { |
| 129 case BufferFormat::R_8: | 129 case gfx::BufferFormat::R_8: |
| 130 return GL_UNSIGNED_BYTE; | 130 return GL_UNSIGNED_BYTE; |
| 131 case BufferFormat::BGRA_8888: | 131 case gfx::BufferFormat::BGRA_8888: |
| 132 case BufferFormat::BGRX_8888: | 132 case gfx::BufferFormat::BGRX_8888: |
| 133 case BufferFormat::RGBA_8888: | 133 case gfx::BufferFormat::RGBA_8888: |
| 134 return GL_UNSIGNED_INT_8_8_8_8_REV; | 134 return GL_UNSIGNED_INT_8_8_8_8_REV; |
| 135 case BufferFormat::UYVY_422: | 135 case gfx::BufferFormat::UYVY_422: |
| 136 return GL_UNSIGNED_SHORT_8_8_APPLE; | 136 return GL_UNSIGNED_SHORT_8_8_APPLE; |
| 137 break; | 137 break; |
| 138 case BufferFormat::ATC: | 138 case gfx::BufferFormat::ATC: |
| 139 case BufferFormat::ATCIA: | 139 case gfx::BufferFormat::ATCIA: |
| 140 case BufferFormat::DXT1: | 140 case gfx::BufferFormat::DXT1: |
| 141 case BufferFormat::DXT5: | 141 case gfx::BufferFormat::DXT5: |
| 142 case BufferFormat::ETC1: | 142 case gfx::BufferFormat::ETC1: |
| 143 case BufferFormat::BGR_565: | 143 case gfx::BufferFormat::BGR_565: |
| 144 case BufferFormat::RGBA_4444: | 144 case gfx::BufferFormat::RGBA_4444: |
| 145 case BufferFormat::RGBX_8888: | 145 case gfx::BufferFormat::RGBX_8888: |
| 146 case BufferFormat::YUV_420: | 146 case gfx::BufferFormat::YUV_420: |
| 147 case BufferFormat::YUV_420_BIPLANAR: | 147 case gfx::BufferFormat::YUV_420_BIPLANAR: |
| 148 NOTREACHED(); | 148 NOTREACHED(); |
| 149 return 0; | 149 return 0; |
| 150 } | 150 } |
| 151 | 151 |
| 152 NOTREACHED(); | 152 NOTREACHED(); |
| 153 return 0; | 153 return 0; |
| 154 } | 154 } |
| 155 | 155 |
| 156 // When an IOSurface is bound to a texture with internalformat "GL_RGB", many | 156 // When an IOSurface is bound to a texture with internalformat "GL_RGB", many |
| 157 // OpenGL operations are broken. Therefore, never allow an IOSurface to be bound | 157 // OpenGL operations are broken. Therefore, never allow an IOSurface to be bound |
| 158 // with GL_RGB. https://crbug.com/595948. | 158 // with GL_RGB. https://crbug.com/595948. |
| 159 GLenum ConvertRequestedInternalFormat(GLenum internalformat) { | 159 GLenum ConvertRequestedInternalFormat(GLenum internalformat) { |
| 160 if (internalformat == GL_RGB) | 160 if (internalformat == GL_RGB) |
| 161 return GL_RGBA; | 161 return GL_RGBA; |
| 162 return internalformat; | 162 return internalformat; |
| 163 } | 163 } |
| 164 | 164 |
| 165 } // namespace | 165 } // namespace |
| 166 | 166 |
| 167 GLImageIOSurface::GLImageIOSurface(const gfx::Size& size, | 167 GLImageIOSurface::GLImageIOSurface(const gfx::Size& size, |
| 168 unsigned internalformat) | 168 unsigned internalformat) |
| 169 : size_(size), | 169 : size_(size), |
| 170 internalformat_(ConvertRequestedInternalFormat(internalformat)), | 170 internalformat_(ConvertRequestedInternalFormat(internalformat)), |
| 171 client_internalformat_(internalformat), | 171 client_internalformat_(internalformat), |
| 172 format_(BufferFormat::RGBA_8888) {} | 172 format_(gfx::BufferFormat::RGBA_8888) {} |
| 173 | 173 |
| 174 GLImageIOSurface::~GLImageIOSurface() { | 174 GLImageIOSurface::~GLImageIOSurface() { |
| 175 DCHECK(thread_checker_.CalledOnValidThread()); | 175 DCHECK(thread_checker_.CalledOnValidThread()); |
| 176 DCHECK(!io_surface_); | 176 DCHECK(!io_surface_); |
| 177 } | 177 } |
| 178 | 178 |
| 179 bool GLImageIOSurface::Initialize(IOSurfaceRef io_surface, | 179 bool GLImageIOSurface::Initialize(IOSurfaceRef io_surface, |
| 180 gfx::GenericSharedMemoryId io_surface_id, | 180 gfx::GenericSharedMemoryId io_surface_id, |
| 181 BufferFormat format) { | 181 gfx::BufferFormat format) { |
| 182 DCHECK(thread_checker_.CalledOnValidThread()); | 182 DCHECK(thread_checker_.CalledOnValidThread()); |
| 183 DCHECK(!io_surface_); | 183 DCHECK(!io_surface_); |
| 184 | 184 |
| 185 if (!ValidInternalFormat(internalformat_)) { | 185 if (!ValidInternalFormat(internalformat_)) { |
| 186 LOG(ERROR) << "Invalid internalformat: " << internalformat_; | 186 LOG(ERROR) << "Invalid internalformat: " << internalformat_; |
| 187 return false; | 187 return false; |
| 188 } | 188 } |
| 189 | 189 |
| 190 if (!ValidFormat(format)) { | 190 if (!ValidFormat(format)) { |
| 191 LOG(ERROR) << "Invalid format: " << static_cast<int>(format); | 191 LOG(ERROR) << "Invalid format: " << static_cast<int>(format); |
| 192 return false; | 192 return false; |
| 193 } | 193 } |
| 194 | 194 |
| 195 format_ = format; | 195 format_ = format; |
| 196 io_surface_.reset(io_surface, base::scoped_policy::RETAIN); | 196 io_surface_.reset(io_surface, base::scoped_policy::RETAIN); |
| 197 io_surface_id_ = io_surface_id; | 197 io_surface_id_ = io_surface_id; |
| 198 return true; | 198 return true; |
| 199 } | 199 } |
| 200 | 200 |
| 201 bool GLImageIOSurface::InitializeWithCVPixelBuffer( | 201 bool GLImageIOSurface::InitializeWithCVPixelBuffer( |
| 202 CVPixelBufferRef cv_pixel_buffer, | 202 CVPixelBufferRef cv_pixel_buffer, |
| 203 gfx::GenericSharedMemoryId io_surface_id, | 203 gfx::GenericSharedMemoryId io_surface_id, |
| 204 BufferFormat format) { | 204 gfx::BufferFormat format) { |
| 205 IOSurfaceRef io_surface = CVPixelBufferGetIOSurface(cv_pixel_buffer); | 205 IOSurfaceRef io_surface = CVPixelBufferGetIOSurface(cv_pixel_buffer); |
| 206 if (!io_surface) { | 206 if (!io_surface) { |
| 207 LOG(ERROR) << "Can't init GLImage from CVPixelBuffer with no IOSurface"; | 207 LOG(ERROR) << "Can't init GLImage from CVPixelBuffer with no IOSurface"; |
| 208 return false; | 208 return false; |
| 209 } | 209 } |
| 210 | 210 |
| 211 if (!Initialize(io_surface, io_surface_id, format)) | 211 if (!Initialize(io_surface, io_surface_id, format)) |
| 212 return false; | 212 return false; |
| 213 | 213 |
| 214 cv_pixel_buffer_.reset(cv_pixel_buffer, base::scoped_policy::RETAIN); | 214 cv_pixel_buffer_.reset(cv_pixel_buffer, base::scoped_policy::RETAIN); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 228 unsigned GLImageIOSurface::GetInternalFormat() { | 228 unsigned GLImageIOSurface::GetInternalFormat() { |
| 229 return internalformat_; | 229 return internalformat_; |
| 230 } | 230 } |
| 231 | 231 |
| 232 bool GLImageIOSurface::BindTexImage(unsigned target) { | 232 bool GLImageIOSurface::BindTexImage(unsigned target) { |
| 233 DCHECK(thread_checker_.CalledOnValidThread()); | 233 DCHECK(thread_checker_.CalledOnValidThread()); |
| 234 | 234 |
| 235 // YUV_420_BIPLANAR is not supported by BindTexImage. | 235 // YUV_420_BIPLANAR is not supported by BindTexImage. |
| 236 // CopyTexImage is supported by this format as that performs conversion to RGB | 236 // CopyTexImage is supported by this format as that performs conversion to RGB |
| 237 // as part of the copy operation. | 237 // as part of the copy operation. |
| 238 if (format_ == BufferFormat::YUV_420_BIPLANAR) | 238 if (format_ == gfx::BufferFormat::YUV_420_BIPLANAR) |
| 239 return false; | 239 return false; |
| 240 | 240 |
| 241 if (target != GL_TEXTURE_RECTANGLE_ARB) { | 241 if (target != GL_TEXTURE_RECTANGLE_ARB) { |
| 242 // This might be supported in the future. For now, perform strict | 242 // This might be supported in the future. For now, perform strict |
| 243 // validation so we know what's going on. | 243 // validation so we know what's going on. |
| 244 LOG(ERROR) << "IOSurface requires TEXTURE_RECTANGLE_ARB target"; | 244 LOG(ERROR) << "IOSurface requires TEXTURE_RECTANGLE_ARB target"; |
| 245 return false; | 245 return false; |
| 246 } | 246 } |
| 247 | 247 |
| 248 CGLContextObj cgl_context = | 248 CGLContextObj cgl_context = |
| 249 static_cast<CGLContextObj>(gfx::GLContext::GetCurrent()->GetHandle()); | 249 static_cast<CGLContextObj>(gl::GLContext::GetCurrent()->GetHandle()); |
| 250 | 250 |
| 251 DCHECK(io_surface_); | 251 DCHECK(io_surface_); |
| 252 CGLError cgl_error = | 252 CGLError cgl_error = |
| 253 CGLTexImageIOSurface2D(cgl_context, target, TextureFormat(format_), | 253 CGLTexImageIOSurface2D(cgl_context, target, TextureFormat(format_), |
| 254 size_.width(), size_.height(), DataFormat(format_), | 254 size_.width(), size_.height(), DataFormat(format_), |
| 255 DataType(format_), io_surface_.get(), 0); | 255 DataType(format_), io_surface_.get(), 0); |
| 256 if (cgl_error != kCGLNoError) { | 256 if (cgl_error != kCGLNoError) { |
| 257 LOG(ERROR) << "Error in CGLTexImageIOSurface2D: " | 257 LOG(ERROR) << "Error in CGLTexImageIOSurface2D: " |
| 258 << CGLErrorString(cgl_error); | 258 << CGLErrorString(cgl_error); |
| 259 return false; | 259 return false; |
| 260 } | 260 } |
| 261 | 261 |
| 262 return true; | 262 return true; |
| 263 } | 263 } |
| 264 | 264 |
| 265 bool GLImageIOSurface::CopyTexImage(unsigned target) { | 265 bool GLImageIOSurface::CopyTexImage(unsigned target) { |
| 266 DCHECK(thread_checker_.CalledOnValidThread()); | 266 DCHECK(thread_checker_.CalledOnValidThread()); |
| 267 | 267 |
| 268 if (format_ != BufferFormat::YUV_420_BIPLANAR) | 268 if (format_ != gfx::BufferFormat::YUV_420_BIPLANAR) |
| 269 return false; | 269 return false; |
| 270 | 270 |
| 271 if (target != GL_TEXTURE_RECTANGLE_ARB) { | 271 if (target != GL_TEXTURE_RECTANGLE_ARB) { |
| 272 LOG(ERROR) << "YUV_420_BIPLANAR requires GL_TEXTURE_RECTANGLE_ARB target"; | 272 LOG(ERROR) << "YUV_420_BIPLANAR requires GL_TEXTURE_RECTANGLE_ARB target"; |
| 273 return false; | 273 return false; |
| 274 } | 274 } |
| 275 | 275 |
| 276 gfx::GLContext* gl_context = gfx::GLContext::GetCurrent(); | 276 gl::GLContext* gl_context = gl::GLContext::GetCurrent(); |
| 277 DCHECK(gl_context); | 277 DCHECK(gl_context); |
| 278 | 278 |
| 279 gl::YUVToRGBConverter* yuv_to_rgb_converter = | 279 gl::YUVToRGBConverter* yuv_to_rgb_converter = |
| 280 gl_context->GetYUVToRGBConverter(); | 280 gl_context->GetYUVToRGBConverter(); |
| 281 DCHECK(yuv_to_rgb_converter); | 281 DCHECK(yuv_to_rgb_converter); |
| 282 | 282 |
| 283 gfx::ScopedSetGLToRealGLApi scoped_set_gl_api; | 283 gl::ScopedSetGLToRealGLApi scoped_set_gl_api; |
| 284 | 284 |
| 285 // Note that state restoration is done explicitly instead of scoped binders to | 285 // Note that state restoration is done explicitly instead of scoped binders to |
| 286 // avoid https://crbug.com/601729. | 286 // avoid https://crbug.com/601729. |
| 287 GLint rgb_texture = 0; | 287 GLint rgb_texture = 0; |
| 288 glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &rgb_texture); | 288 glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &rgb_texture); |
| 289 base::ScopedClosureRunner destroy_resources_runner(base::BindBlock(^{ | 289 base::ScopedClosureRunner destroy_resources_runner(base::BindBlock(^{ |
| 290 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, rgb_texture); | 290 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, rgb_texture); |
| 291 })); | 291 })); |
| 292 | 292 |
| 293 CGLContextObj cgl_context = CGLGetCurrentContext(); | 293 CGLContextObj cgl_context = CGLGetCurrentContext(); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 367 return cv_pixel_buffer_; | 367 return cv_pixel_buffer_; |
| 368 } | 368 } |
| 369 | 369 |
| 370 // static | 370 // static |
| 371 unsigned GLImageIOSurface::GetInternalFormatForTesting( | 371 unsigned GLImageIOSurface::GetInternalFormatForTesting( |
| 372 gfx::BufferFormat format) { | 372 gfx::BufferFormat format) { |
| 373 DCHECK(ValidFormat(format)); | 373 DCHECK(ValidFormat(format)); |
| 374 return TextureFormat(format); | 374 return TextureFormat(format); |
| 375 } | 375 } |
| 376 } // namespace gl | 376 } // namespace gl |
| OLD | NEW |