Chromium Code Reviews| 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/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
| 10 #include "base/mac/foundation_util.h" | 11 #include "base/mac/foundation_util.h" |
| 12 #include "base/strings/stringize_macros.h" | |
| 11 #include "base/trace_event/memory_allocator_dump.h" | 13 #include "base/trace_event/memory_allocator_dump.h" |
| 12 #include "base/trace_event/memory_dump_manager.h" | 14 #include "base/trace_event/memory_dump_manager.h" |
| 13 #include "base/trace_event/process_memory_dump.h" | 15 #include "base/trace_event/process_memory_dump.h" |
| 14 #include "ui/gl/gl_bindings.h" | 16 #include "ui/gl/gl_bindings.h" |
| 15 #include "ui/gl/gl_context.h" | 17 #include "ui/gl/gl_context.h" |
| 18 #include "ui/gl/gl_helper.h" | |
| 19 #include "ui/gl/scoped_binders.h" | |
| 16 | 20 |
| 17 // Note that this must be included after gl_bindings.h to avoid conflicts. | 21 // Note that this must be included after gl_bindings.h to avoid conflicts. |
| 18 #include <OpenGL/CGLIOSurface.h> | 22 #include <OpenGL/CGLIOSurface.h> |
| 19 #include <Quartz/Quartz.h> | 23 #include <Quartz/Quartz.h> |
| 20 | 24 |
| 21 using gfx::BufferFormat; | 25 using gfx::BufferFormat; |
| 22 | 26 |
| 23 namespace gl { | 27 namespace gl { |
| 24 namespace { | 28 namespace { |
| 25 | 29 |
| 26 using WidgetToLayerMap = std::map<gfx::AcceleratedWidget, CALayer*>; | 30 using WidgetToLayerMap = std::map<gfx::AcceleratedWidget, CALayer*>; |
| 27 base::LazyInstance<WidgetToLayerMap> g_widget_to_layer_map; | 31 base::LazyInstance<WidgetToLayerMap> g_widget_to_layer_map; |
| 28 | 32 |
| 29 bool ValidInternalFormat(unsigned internalformat) { | 33 bool ValidInternalFormat(unsigned internalformat) { |
| 30 switch (internalformat) { | 34 switch (internalformat) { |
| 31 case GL_R8: | 35 case GL_R8: |
| 32 case GL_BGRA_EXT: | 36 case GL_BGRA_EXT: |
| 33 case GL_RGB: | 37 case GL_RGB: |
| 38 case GL_RGB_YCBCR_420V_CHROMIUM: | |
| 34 case GL_RGB_YCBCR_422_CHROMIUM: | 39 case GL_RGB_YCBCR_422_CHROMIUM: |
| 35 case GL_RGBA: | 40 case GL_RGBA: |
| 36 return true; | 41 return true; |
| 37 default: | 42 default: |
| 38 return false; | 43 return false; |
| 39 } | 44 } |
| 40 } | 45 } |
| 41 | 46 |
| 42 bool ValidFormat(BufferFormat format) { | 47 bool ValidFormat(BufferFormat format) { |
| 43 switch (format) { | 48 switch (format) { |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 59 return false; | 64 return false; |
| 60 } | 65 } |
| 61 | 66 |
| 62 NOTREACHED(); | 67 NOTREACHED(); |
| 63 return false; | 68 return false; |
| 64 } | 69 } |
| 65 | 70 |
| 66 GLenum TextureFormat(BufferFormat format) { | 71 GLenum TextureFormat(BufferFormat format) { |
| 67 switch (format) { | 72 switch (format) { |
| 68 case BufferFormat::R_8: | 73 case BufferFormat::R_8: |
| 69 case BufferFormat::YUV_420_BIPLANAR: | |
| 70 return GL_RED; | 74 return GL_RED; |
| 71 case BufferFormat::BGRA_8888: | 75 case BufferFormat::BGRA_8888: |
| 72 case BufferFormat::RGBA_8888: | 76 case BufferFormat::RGBA_8888: |
| 73 return GL_RGBA; | 77 return GL_RGBA; |
| 74 case BufferFormat::UYVY_422: | 78 case BufferFormat::UYVY_422: |
| 75 return GL_RGB; | |
| 76 case BufferFormat::ATC: | 79 case BufferFormat::ATC: |
| 77 case BufferFormat::ATCIA: | 80 case BufferFormat::ATCIA: |
| 78 case BufferFormat::DXT1: | 81 case BufferFormat::DXT1: |
| 79 case BufferFormat::DXT5: | 82 case BufferFormat::DXT5: |
| 80 case BufferFormat::ETC1: | 83 case BufferFormat::ETC1: |
| 81 case BufferFormat::RGBA_4444: | 84 case BufferFormat::RGBA_4444: |
| 82 case BufferFormat::RGBX_8888: | 85 case BufferFormat::RGBX_8888: |
| 83 case BufferFormat::BGRX_8888: | 86 case BufferFormat::BGRX_8888: |
| 84 case BufferFormat::YUV_420: | 87 case BufferFormat::YUV_420: |
| 88 case BufferFormat::YUV_420_BIPLANAR: | |
| 85 NOTREACHED(); | 89 NOTREACHED(); |
| 86 return 0; | 90 return 0; |
| 87 } | 91 } |
| 88 | 92 |
| 89 NOTREACHED(); | 93 NOTREACHED(); |
| 90 return 0; | 94 return 0; |
| 91 } | 95 } |
| 92 | 96 |
| 93 GLenum DataFormat(BufferFormat format) { | 97 GLenum DataFormat(BufferFormat format) { |
| 94 switch (format) { | 98 switch (format) { |
| 95 case BufferFormat::R_8: | 99 case BufferFormat::R_8: |
| 96 case BufferFormat::YUV_420_BIPLANAR: | |
| 97 return GL_RED; | 100 return GL_RED; |
| 98 case BufferFormat::BGRA_8888: | 101 case BufferFormat::BGRA_8888: |
| 99 case BufferFormat::RGBA_8888: | 102 case BufferFormat::RGBA_8888: |
| 100 return GL_BGRA; | 103 return GL_BGRA; |
| 101 case BufferFormat::UYVY_422: | 104 case BufferFormat::UYVY_422: |
| 102 return GL_YCBCR_422_APPLE; | 105 return GL_YCBCR_422_APPLE; |
| 103 break; | |
| 104 case BufferFormat::ATC: | 106 case BufferFormat::ATC: |
| 105 case BufferFormat::ATCIA: | 107 case BufferFormat::ATCIA: |
| 106 case BufferFormat::DXT1: | 108 case BufferFormat::DXT1: |
| 107 case BufferFormat::DXT5: | 109 case BufferFormat::DXT5: |
| 108 case BufferFormat::ETC1: | 110 case BufferFormat::ETC1: |
| 109 case BufferFormat::RGBA_4444: | 111 case BufferFormat::RGBA_4444: |
| 110 case BufferFormat::RGBX_8888: | 112 case BufferFormat::RGBX_8888: |
| 111 case BufferFormat::BGRX_8888: | 113 case BufferFormat::BGRX_8888: |
| 112 case BufferFormat::YUV_420: | 114 case BufferFormat::YUV_420: |
| 115 case BufferFormat::YUV_420_BIPLANAR: | |
| 113 NOTREACHED(); | 116 NOTREACHED(); |
| 114 return 0; | 117 return 0; |
| 115 } | 118 } |
| 116 | 119 |
| 117 NOTREACHED(); | 120 NOTREACHED(); |
| 118 return 0; | 121 return 0; |
| 119 } | 122 } |
| 120 | 123 |
| 121 GLenum DataType(BufferFormat format) { | 124 GLenum DataType(BufferFormat format) { |
| 122 switch (format) { | 125 switch (format) { |
| 123 case BufferFormat::R_8: | 126 case BufferFormat::R_8: |
| 124 case BufferFormat::YUV_420_BIPLANAR: | |
| 125 return GL_UNSIGNED_BYTE; | 127 return GL_UNSIGNED_BYTE; |
| 126 case BufferFormat::BGRA_8888: | 128 case BufferFormat::BGRA_8888: |
| 127 case BufferFormat::RGBA_8888: | 129 case BufferFormat::RGBA_8888: |
| 128 return GL_UNSIGNED_INT_8_8_8_8_REV; | 130 return GL_UNSIGNED_INT_8_8_8_8_REV; |
| 129 case BufferFormat::UYVY_422: | 131 case BufferFormat::UYVY_422: |
| 130 return GL_UNSIGNED_SHORT_8_8_APPLE; | 132 return GL_UNSIGNED_SHORT_8_8_APPLE; |
| 131 break; | 133 break; |
| 132 case BufferFormat::ATC: | 134 case BufferFormat::ATC: |
| 133 case BufferFormat::ATCIA: | 135 case BufferFormat::ATCIA: |
| 134 case BufferFormat::DXT1: | 136 case BufferFormat::DXT1: |
| 135 case BufferFormat::DXT5: | 137 case BufferFormat::DXT5: |
| 136 case BufferFormat::ETC1: | 138 case BufferFormat::ETC1: |
| 137 case BufferFormat::RGBA_4444: | 139 case BufferFormat::RGBA_4444: |
| 138 case BufferFormat::RGBX_8888: | 140 case BufferFormat::RGBX_8888: |
| 139 case BufferFormat::BGRX_8888: | 141 case BufferFormat::BGRX_8888: |
| 140 case BufferFormat::YUV_420: | 142 case BufferFormat::YUV_420: |
| 143 case BufferFormat::YUV_420_BIPLANAR: | |
| 141 NOTREACHED(); | 144 NOTREACHED(); |
| 142 return 0; | 145 return 0; |
| 143 } | 146 } |
| 144 | 147 |
| 145 NOTREACHED(); | 148 NOTREACHED(); |
| 146 return 0; | 149 return 0; |
| 147 } | 150 } |
| 148 | 151 |
| 152 GLuint SetupVertexBuffer() { | |
| 153 GLuint vertex_buffer = 0; | |
| 154 glGenBuffersARB(1, &vertex_buffer); | |
| 155 gfx::ScopedBufferBinder sbb(GL_ARRAY_BUFFER, vertex_buffer); | |
|
reveman
2015/10/29 22:08:04
nit: s/sbb/scoped_buffer_binder/ or buffer_binder,
Daniele Castagna
2015/10/30 23:51:57
Renamed just buffer_binder, also changed the name
| |
| 156 | |
| 157 GLfloat data[] = {-1.f, -1.f, 1.f, -1.f, -1.f, 1.f, 1.f, 1.f}; | |
| 158 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW); | |
| 159 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 2, 0); | |
| 160 | |
| 161 return vertex_buffer; | |
| 162 } | |
| 163 | |
| 149 } // namespace | 164 } // namespace |
| 150 | 165 |
| 166 // clang-format off | |
| 167 const char GLImageIOSurface::kVertexShader[] = | |
| 168 STRINGIZE( | |
| 169 attribute vec2 a_position; | |
| 170 uniform vec2 a_size; | |
| 171 varying vec2 v_texCoord; | |
| 172 void main() { | |
| 173 gl_Position = vec4(a_position.x, a_position.y, 0.0, 1.0); | |
| 174 v_texCoord = (a_position + vec2(1,1)) * 0.5 * a_size; | |
| 175 } | |
| 176 ); | |
| 177 | |
| 178 const char GLImageIOSurface::kFragmentShader[] = | |
| 179 STRINGIZE( | |
| 180 uniform sampler2DRect a_y_texture; | |
| 181 uniform sampler2DRect a_uv_texture; | |
| 182 varying vec2 v_texCoord; | |
| 183 void main() { | |
| 184 vec3 yuv_adj = vec3(-0.0625, -0.5, -0.5); | |
| 185 mat3 yuv_matrix = mat3(vec3(1.164, 1.164, 1.164), | |
| 186 vec3(0.0, -.391, 2.018), | |
| 187 vec3(1.596, -.813, 0.0)); | |
| 188 vec3 yuv = vec3(texture2DRect(a_y_texture, v_texCoord).r, | |
| 189 texture2DRect(a_uv_texture, v_texCoord * 0.5).rg); | |
| 190 gl_FragColor = vec4( yuv_matrix * (yuv + yuv_adj), 1.0); | |
| 191 } | |
| 192 ); | |
| 193 // clang-format on | |
| 194 | |
| 151 GLImageIOSurface::GLImageIOSurface(const gfx::Size& size, | 195 GLImageIOSurface::GLImageIOSurface(const gfx::Size& size, |
| 152 unsigned internalformat) | 196 unsigned internalformat) |
| 153 : size_(size), | 197 : size_(size), |
| 154 internalformat_(internalformat), | 198 internalformat_(internalformat), |
| 155 format_(BufferFormat::RGBA_8888) {} | 199 format_(BufferFormat::RGBA_8888) {} |
| 156 | 200 |
| 157 GLImageIOSurface::~GLImageIOSurface() { | 201 GLImageIOSurface::~GLImageIOSurface() { |
| 158 DCHECK(thread_checker_.CalledOnValidThread()); | 202 DCHECK(thread_checker_.CalledOnValidThread()); |
| 159 DCHECK(!io_surface_); | 203 DCHECK(!io_surface_); |
| 160 } | 204 } |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 176 } | 220 } |
| 177 | 221 |
| 178 format_ = format; | 222 format_ = format; |
| 179 io_surface_.reset(io_surface, base::scoped_policy::RETAIN); | 223 io_surface_.reset(io_surface, base::scoped_policy::RETAIN); |
| 180 io_surface_id_ = io_surface_id; | 224 io_surface_id_ = io_surface_id; |
| 181 return true; | 225 return true; |
| 182 } | 226 } |
| 183 | 227 |
| 184 void GLImageIOSurface::Destroy(bool have_context) { | 228 void GLImageIOSurface::Destroy(bool have_context) { |
| 185 DCHECK(thread_checker_.CalledOnValidThread()); | 229 DCHECK(thread_checker_.CalledOnValidThread()); |
| 230 if (have_context) { | |
| 231 glDeleteProgram(program_); | |
|
reveman
2015/10/29 22:08:04
what if you haven't created a program?
Daniele Castagna
2015/10/30 23:51:57
In that case program_ would be 0.
The documentatio
| |
| 232 glDeleteShader(vertex_shader_); | |
| 233 glDeleteShader(fragment_shader_); | |
| 234 glDeleteBuffersARB(1, &vertex_buffer_); | |
| 235 glDeleteFramebuffersEXT(1, &framebuffer_); | |
| 236 } | |
| 186 io_surface_.reset(); | 237 io_surface_.reset(); |
| 187 } | 238 } |
| 188 | 239 |
| 189 gfx::Size GLImageIOSurface::GetSize() { | 240 gfx::Size GLImageIOSurface::GetSize() { |
| 190 return size_; | 241 return size_; |
| 191 } | 242 } |
| 192 | 243 |
| 193 unsigned GLImageIOSurface::GetInternalFormat() { return internalformat_; } | 244 unsigned GLImageIOSurface::GetInternalFormat() { return internalformat_; } |
| 194 | 245 |
| 195 bool GLImageIOSurface::BindTexImage(unsigned target) { | 246 bool GLImageIOSurface::BindTexImage(unsigned target) { |
| 196 DCHECK(thread_checker_.CalledOnValidThread()); | 247 DCHECK(thread_checker_.CalledOnValidThread()); |
| 248 | |
| 249 if (format_ == BufferFormat::YUV_420_BIPLANAR) | |
|
reveman
2015/10/29 22:08:04
Can you add a comment here to explain that this fo
Daniele Castagna
2015/10/30 23:51:57
Done.
| |
| 250 return false; | |
| 251 | |
| 197 if (target != GL_TEXTURE_RECTANGLE_ARB) { | 252 if (target != GL_TEXTURE_RECTANGLE_ARB) { |
| 198 // This might be supported in the future. For now, perform strict | 253 // This might be supported in the future. For now, perform strict |
| 199 // validation so we know what's going on. | 254 // validation so we know what's going on. |
| 200 LOG(ERROR) << "IOSurface requires TEXTURE_RECTANGLE_ARB target"; | 255 LOG(ERROR) << "IOSurface requires TEXTURE_RECTANGLE_ARB target"; |
| 201 return false; | 256 return false; |
| 202 } | 257 } |
| 203 | 258 |
| 204 CGLContextObj cgl_context = | 259 CGLContextObj cgl_context = |
| 205 static_cast<CGLContextObj>(gfx::GLContext::GetCurrent()->GetHandle()); | 260 static_cast<CGLContextObj>(gfx::GLContext::GetCurrent()->GetHandle()); |
| 206 | 261 |
| 207 DCHECK(io_surface_); | 262 DCHECK(io_surface_); |
| 208 CGLError cgl_error = | 263 CGLError cgl_error = |
| 209 CGLTexImageIOSurface2D(cgl_context, target, TextureFormat(format_), | 264 CGLTexImageIOSurface2D(cgl_context, target, TextureFormat(format_), |
| 210 size_.width(), size_.height(), DataFormat(format_), | 265 size_.width(), size_.height(), DataFormat(format_), |
| 211 DataType(format_), io_surface_.get(), 0); | 266 DataType(format_), io_surface_.get(), 0); |
| 212 if (cgl_error != kCGLNoError) { | 267 if (cgl_error != kCGLNoError) { |
| 213 LOG(ERROR) << "Error in CGLTexImageIOSurface2D"; | 268 LOG(ERROR) << "Error in CGLTexImageIOSurface2D"; |
| 214 return false; | 269 return false; |
| 215 } | 270 } |
| 216 | 271 |
| 217 return true; | 272 return true; |
| 218 } | 273 } |
| 219 | 274 |
| 220 bool GLImageIOSurface::CopyTexImage(unsigned target) { | 275 bool GLImageIOSurface::CopyTexImage(unsigned target) { |
| 221 return false; | 276 DCHECK(thread_checker_.CalledOnValidThread()); |
| 277 DCHECK(io_surface_); | |
| 278 if (format_ != BufferFormat::YUV_420_BIPLANAR) | |
| 279 return false; | |
| 280 | |
| 281 if (target != GL_TEXTURE_2D) { | |
| 282 LOG(ERROR) << "YUV_420_BIPLANAR requires TEXTURE_2D target"; | |
| 283 return false; | |
| 284 } | |
| 285 | |
| 286 if (!framebuffer_) { | |
| 287 glGenFramebuffersEXT(1, &framebuffer_); | |
| 288 vertex_buffer_ = SetupVertexBuffer(); | |
| 289 vertex_shader_ = gfx::GLHelper::LoadShader(GL_VERTEX_SHADER, kVertexShader); | |
| 290 fragment_shader_ = | |
| 291 gfx::GLHelper::LoadShader(GL_FRAGMENT_SHADER, kFragmentShader); | |
| 292 program_ = gfx::GLHelper::SetupProgram(vertex_shader_, fragment_shader_); | |
| 293 gfx::ScopedUseProgram pr(program_); | |
| 294 | |
| 295 size_location_ = glGetUniformLocation(program_, "a_size"); | |
| 296 DCHECK_NE(-1, size_location_); | |
| 297 int y_sampler_location = glGetUniformLocation(program_, "a_y_texture"); | |
| 298 DCHECK_NE(-1, y_sampler_location); | |
| 299 int uv_sampler_location = glGetUniformLocation(program_, "a_uv_texture"); | |
| 300 DCHECK_NE(-1, uv_sampler_location); | |
| 301 | |
| 302 glUniform1i(y_sampler_location, 0); | |
| 303 glUniform1i(uv_sampler_location, 1); | |
| 304 } | |
| 305 | |
| 306 CGLContextObj cgl_context = | |
| 307 static_cast<CGLContextObj>(gfx::GLContext::GetCurrent()->GetHandle()); | |
| 308 | |
| 309 GLuint yuv_textures[2]; | |
| 310 glGenTextures(2, yuv_textures); | |
| 311 DCHECK(yuv_textures[0] && yuv_textures[1]); | |
| 312 | |
| 313 GLint service_texture = 0; | |
|
reveman
2015/10/29 22:08:04
nit: service_texture -> target_texture as there's
Daniele Castagna
2015/10/30 23:51:57
Done.
| |
| 314 glGetIntegerv(GL_TEXTURE_BINDING_2D, &service_texture); | |
| 315 DCHECK(service_texture); | |
| 316 | |
| 317 GLint previous_active_texture = 0; | |
| 318 glGetIntegerv(GL_ACTIVE_TEXTURE, &previous_active_texture); | |
| 319 | |
| 320 CGLError cgl_error = kCGLNoError; | |
| 321 { | |
| 322 glActiveTexture(GL_TEXTURE0); | |
| 323 gfx::ScopedTextureBinder b(GL_TEXTURE_RECTANGLE_ARB, yuv_textures[0]); | |
| 324 cgl_error = CGLTexImageIOSurface2D( | |
| 325 cgl_context, GL_TEXTURE_RECTANGLE_ARB, GL_RED, size_.width(), | |
| 326 size_.height(), GL_RED, GL_UNSIGNED_BYTE, io_surface_.get(), 0); | |
| 327 if (cgl_error != kCGLNoError) { | |
| 328 LOG(ERROR) << "Error in CGLTexImageIOSurface2D for the Y plane. " | |
| 329 << cgl_error; | |
| 330 glDeleteTextures(2, yuv_textures); | |
|
reveman
2015/10/29 22:08:04
Do we need to restore the active texture here? May
Daniele Castagna
2015/10/30 23:51:57
Done.
| |
| 331 return false; | |
| 332 } | |
| 333 { | |
| 334 glActiveTexture(GL_TEXTURE1); | |
| 335 gfx::ScopedTextureBinder b(GL_TEXTURE_RECTANGLE_ARB, yuv_textures[1]); | |
| 336 cgl_error = CGLTexImageIOSurface2D( | |
| 337 cgl_context, GL_TEXTURE_RECTANGLE_ARB, GL_RG, size_.width() / 2, | |
| 338 size_.height() / 2, GL_RG, GL_UNSIGNED_BYTE, io_surface_.get(), 1); | |
| 339 if (cgl_error != kCGLNoError) { | |
| 340 LOG(ERROR) << "Error in CGLTexImageIOSurface2D for the UV plane. " | |
| 341 << cgl_error; | |
| 342 glDeleteTextures(2, yuv_textures); | |
| 343 return false; | |
| 344 } | |
| 345 | |
| 346 gfx::ScopedFrameBufferBinder fb(framebuffer_); | |
|
reveman
2015/10/29 22:08:04
nit: s/fb/scoped_framebuffer/
Daniele Castagna
2015/10/30 23:51:57
Changed all of them!
| |
| 347 glViewport(0, 0, size_.width(), size_.height()); | |
|
reveman
2015/10/29 22:08:04
do we need to restore the viewport before we exit?
Daniele Castagna
2015/10/30 23:51:57
Added another Scoped* class...
| |
| 348 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, | |
| 349 GL_TEXTURE_2D, service_texture, 0); | |
| 350 DCHECK_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), | |
| 351 glCheckFramebufferStatusEXT(GL_FRAMEBUFFER)); | |
| 352 | |
| 353 gfx::ScopedUseProgram pr(program_); | |
|
reveman
2015/10/29 22:08:04
nit: please remove "pr" abbreviation here and simi
Daniele Castagna
2015/10/30 23:51:57
Done.
| |
| 354 glUniform2f(size_location_, size_.width(), size_.height()); | |
| 355 | |
| 356 gfx::ScopedEnableVertexAttribArray vaa(0); | |
| 357 gfx::ScopedBufferBinder bb(GL_ARRAY_BUFFER, vertex_buffer_); | |
| 358 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | |
| 359 | |
| 360 // Detach the service texture from the fbo. | |
|
reveman
2015/10/29 22:08:04
target texture
Daniele Castagna
2015/10/30 23:51:57
Done.
| |
| 361 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, | |
| 362 GL_TEXTURE_2D, 0, 0); | |
| 363 | |
| 364 } // GL_TEXTURE1 | |
| 365 glActiveTexture(GL_TEXTURE0); | |
|
reveman
2015/10/29 22:08:04
previous_active_texture?
Daniele Castagna
2015/10/30 23:51:57
ack.
| |
| 366 } // GL_TEXTURE0 | |
| 367 return true; | |
| 222 } | 368 } |
| 223 | 369 |
| 224 bool GLImageIOSurface::CopyTexSubImage(unsigned target, | 370 bool GLImageIOSurface::CopyTexSubImage(unsigned target, |
| 225 const gfx::Point& offset, | 371 const gfx::Point& offset, |
| 226 const gfx::Rect& rect) { | 372 const gfx::Rect& rect) { |
| 227 return false; | 373 return false; |
| 228 } | 374 } |
| 229 | 375 |
| 230 bool GLImageIOSurface::ScheduleOverlayPlane(gfx::AcceleratedWidget widget, | 376 bool GLImageIOSurface::ScheduleOverlayPlane(gfx::AcceleratedWidget widget, |
| 231 int z_order, | 377 int z_order, |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 262 // static | 408 // static |
| 263 void GLImageIOSurface::SetLayerForWidget(gfx::AcceleratedWidget widget, | 409 void GLImageIOSurface::SetLayerForWidget(gfx::AcceleratedWidget widget, |
| 264 CALayer* layer) { | 410 CALayer* layer) { |
| 265 if (layer) | 411 if (layer) |
| 266 g_widget_to_layer_map.Pointer()->insert(std::make_pair(widget, layer)); | 412 g_widget_to_layer_map.Pointer()->insert(std::make_pair(widget, layer)); |
| 267 else | 413 else |
| 268 g_widget_to_layer_map.Pointer()->erase(widget); | 414 g_widget_to_layer_map.Pointer()->erase(widget); |
| 269 } | 415 } |
| 270 | 416 |
| 271 } // namespace gfx | 417 } // namespace gfx |
| OLD | NEW |