| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "content/common/gpu/client/gl_helper.h" | 5 #include "content/common/gpu/client/gl_helper.h" |
| 6 | 6 |
| 7 #include <queue> | 7 #include <queue> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/debug/trace_event.h" | 11 #include "base/debug/trace_event.h" |
| 12 #include "base/lazy_instance.h" | 12 #include "base/lazy_instance.h" |
| 13 #include "base/logging.h" | 13 #include "base/logging.h" |
| 14 #include "base/memory/ref_counted.h" | 14 #include "base/memory/ref_counted.h" |
| 15 #include "base/message_loop/message_loop.h" | 15 #include "base/message_loop/message_loop.h" |
| 16 #include "base/strings/string_util.h" | 16 #include "base/strings/string_util.h" |
| 17 #include "base/time/time.h" | 17 #include "base/time/time.h" |
| 18 #include "content/common/gpu/client/gl_helper_scaling.h" | 18 #include "content/common/gpu/client/gl_helper_scaling.h" |
| 19 #include "gpu/GLES2/gl2extchromium.h" |
| 19 #include "gpu/command_buffer/client/context_support.h" | 20 #include "gpu/command_buffer/client/context_support.h" |
| 20 #include "gpu/command_buffer/common/mailbox.h" | 21 #include "gpu/command_buffer/common/mailbox.h" |
| 21 #include "media/base/video_frame.h" | 22 #include "media/base/video_frame.h" |
| 22 #include "media/base/video_util.h" | 23 #include "media/base/video_util.h" |
| 23 #include "third_party/WebKit/public/platform/WebCString.h" | |
| 24 #include "third_party/skia/include/core/SkRegion.h" | 24 #include "third_party/skia/include/core/SkRegion.h" |
| 25 #include "ui/gfx/rect.h" | 25 #include "ui/gfx/rect.h" |
| 26 #include "ui/gfx/size.h" | 26 #include "ui/gfx/size.h" |
| 27 #include "ui/gl/gl_bindings.h" | |
| 28 | 27 |
| 29 using blink::WebGLId; | 28 using gpu::gles2::GLES2Interface; |
| 30 using blink::WebGraphicsContext3D; | |
| 31 | 29 |
| 32 namespace { | 30 namespace { |
| 33 | 31 |
| 34 // Helper class for allocating and holding an RGBA texture of a given | 32 // Helper class for allocating and holding an RGBA texture of a given |
| 35 // size and an associated framebuffer. | 33 // size and an associated framebuffer. |
| 36 class TextureFrameBufferPair { | 34 class TextureFrameBufferPair { |
| 37 public: | 35 public: |
| 38 TextureFrameBufferPair(WebGraphicsContext3D* context, | 36 TextureFrameBufferPair(GLES2Interface* gl, gfx::Size size) |
| 39 gfx::Size size) | 37 : texture_(gl), framebuffer_(gl), size_(size) { |
| 40 : texture_(context, context->createTexture()), | 38 content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl, texture_); |
| 41 framebuffer_(context, context->createFramebuffer()), | 39 gl->TexImage2D(GL_TEXTURE_2D, |
| 42 size_(size) { | 40 0, |
| 43 content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context, | 41 GL_RGBA, |
| 44 texture_); | 42 size.width(), |
| 45 context->texImage2D(GL_TEXTURE_2D, | 43 size.height(), |
| 46 0, | 44 0, |
| 47 GL_RGBA, | 45 GL_RGBA, |
| 48 size.width(), | 46 GL_UNSIGNED_BYTE, |
| 49 size.height(), | 47 NULL); |
| 50 0, | |
| 51 GL_RGBA, | |
| 52 GL_UNSIGNED_BYTE, | |
| 53 NULL); | |
| 54 content::ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder( | 48 content::ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder( |
| 55 context, | 49 gl, framebuffer_); |
| 56 framebuffer_); | 50 gl->FramebufferTexture2D( |
| 57 context->framebufferTexture2D(GL_FRAMEBUFFER, | 51 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_, 0); |
| 58 GL_COLOR_ATTACHMENT0, | |
| 59 GL_TEXTURE_2D, | |
| 60 texture_, | |
| 61 0); | |
| 62 } | 52 } |
| 63 | 53 |
| 64 WebGLId texture() const { return texture_.id(); } | 54 GLuint texture() const { return texture_.id(); } |
| 65 WebGLId framebuffer() const { return framebuffer_.id(); } | 55 GLuint framebuffer() const { return framebuffer_.id(); } |
| 66 gfx::Size size() const { return size_; } | 56 gfx::Size size() const { return size_; } |
| 67 | 57 |
| 68 private: | 58 private: |
| 69 content::ScopedTexture texture_; | 59 content::ScopedTexture texture_; |
| 70 content::ScopedFramebuffer framebuffer_; | 60 content::ScopedFramebuffer framebuffer_; |
| 71 gfx::Size size_; | 61 gfx::Size size_; |
| 72 | 62 |
| 73 DISALLOW_COPY_AND_ASSIGN(TextureFrameBufferPair); | 63 DISALLOW_COPY_AND_ASSIGN(TextureFrameBufferPair); |
| 74 }; | 64 }; |
| 75 | 65 |
| 76 // Helper class for holding a scaler, a texture for the output of that | 66 // Helper class for holding a scaler, a texture for the output of that |
| 77 // scaler and an associated frame buffer. This is inteded to be used | 67 // scaler and an associated frame buffer. This is inteded to be used |
| 78 // when the output of a scaler is to be sent to a readback. | 68 // when the output of a scaler is to be sent to a readback. |
| 79 class ScalerHolder { | 69 class ScalerHolder { |
| 80 public: | 70 public: |
| 81 ScalerHolder(WebGraphicsContext3D* context, | 71 ScalerHolder(GLES2Interface* gl, content::GLHelper::ScalerInterface* scaler) |
| 82 content::GLHelper::ScalerInterface *scaler) | 72 : texture_and_framebuffer_(gl, scaler->DstSize()), scaler_(scaler) {} |
| 83 : texture_and_framebuffer_(context, scaler->DstSize()), | |
| 84 scaler_(scaler) { | |
| 85 } | |
| 86 | 73 |
| 87 void Scale(blink::WebGLId src_texture) { | 74 void Scale(GLuint src_texture) { |
| 88 scaler_->Scale(src_texture, texture_and_framebuffer_.texture()); | 75 scaler_->Scale(src_texture, texture_and_framebuffer_.texture()); |
| 89 } | 76 } |
| 90 | 77 |
| 91 content::GLHelper::ScalerInterface* scaler() const { return scaler_.get(); } | 78 content::GLHelper::ScalerInterface* scaler() const { return scaler_.get(); } |
| 92 TextureFrameBufferPair *texture_and_framebuffer() { | 79 TextureFrameBufferPair* texture_and_framebuffer() { |
| 93 return &texture_and_framebuffer_; | 80 return &texture_and_framebuffer_; |
| 94 } | 81 } |
| 95 WebGLId texture() const { return texture_and_framebuffer_.texture(); } | 82 GLuint texture() const { return texture_and_framebuffer_.texture(); } |
| 96 | 83 |
| 97 private: | 84 private: |
| 98 TextureFrameBufferPair texture_and_framebuffer_; | 85 TextureFrameBufferPair texture_and_framebuffer_; |
| 99 scoped_ptr<content::GLHelper::ScalerInterface> scaler_; | 86 scoped_ptr<content::GLHelper::ScalerInterface> scaler_; |
| 100 | 87 |
| 101 DISALLOW_COPY_AND_ASSIGN(ScalerHolder); | 88 DISALLOW_COPY_AND_ASSIGN(ScalerHolder); |
| 102 }; | 89 }; |
| 103 | 90 |
| 104 } // namespace | 91 } // namespace |
| 105 | 92 |
| 106 namespace content { | 93 namespace content { |
| 107 | 94 |
| 108 // Implements GLHelper::CropScaleReadbackAndCleanTexture and encapsulates | 95 // Implements GLHelper::CropScaleReadbackAndCleanTexture and encapsulates |
| 109 // the data needed for it. | 96 // the data needed for it. |
| 110 class GLHelper::CopyTextureToImpl : | 97 class GLHelper::CopyTextureToImpl |
| 111 public base::SupportsWeakPtr<GLHelper::CopyTextureToImpl> { | 98 : public base::SupportsWeakPtr<GLHelper::CopyTextureToImpl> { |
| 112 public: | 99 public: |
| 113 CopyTextureToImpl(WebGraphicsContext3D* context, | 100 CopyTextureToImpl(GLES2Interface* gl, |
| 114 gpu::ContextSupport* context_support, | 101 gpu::ContextSupport* context_support, |
| 115 GLHelper* helper) | 102 GLHelper* helper) |
| 116 : context_(context), | 103 : gl_(gl), |
| 117 context_support_(context_support), | 104 context_support_(context_support), |
| 118 helper_(helper), | 105 helper_(helper), |
| 119 flush_(context), | 106 flush_(gl), |
| 120 max_draw_buffers_(0) { | 107 max_draw_buffers_(0) { |
| 121 std::string extensions_string = " " + | 108 const GLubyte* extensions = gl_->GetString(GL_EXTENSIONS); |
| 122 UTF16ToASCII(context_->getString(GL_EXTENSIONS)) + " "; | 109 if (!extensions) |
| 110 return; |
| 111 std::string extensions_string = |
| 112 " " + std::string(reinterpret_cast<const char*>(extensions)) + " "; |
| 123 if (extensions_string.find(" GL_EXT_draw_buffers ") != std::string::npos) { | 113 if (extensions_string.find(" GL_EXT_draw_buffers ") != std::string::npos) { |
| 124 context_->getIntegerv(GL_MAX_DRAW_BUFFERS, &max_draw_buffers_); | 114 gl_->GetIntegerv(GL_MAX_DRAW_BUFFERS_EXT, &max_draw_buffers_); |
| 125 } | 115 } |
| 126 } | 116 } |
| 127 ~CopyTextureToImpl() { | 117 ~CopyTextureToImpl() { CancelRequests(); } |
| 128 CancelRequests(); | |
| 129 } | |
| 130 | 118 |
| 131 WebGLId ConsumeMailboxToTexture(const gpu::Mailbox& mailbox, | 119 GLuint ConsumeMailboxToTexture(const gpu::Mailbox& mailbox, |
| 132 uint32 sync_point) { | 120 uint32 sync_point) { |
| 133 return helper_->ConsumeMailboxToTexture(mailbox, sync_point); | 121 return helper_->ConsumeMailboxToTexture(mailbox, sync_point); |
| 134 } | 122 } |
| 135 | 123 |
| 136 void CropScaleReadbackAndCleanTexture( | 124 void CropScaleReadbackAndCleanTexture( |
| 137 WebGLId src_texture, | 125 GLuint src_texture, |
| 138 const gfx::Size& src_size, | 126 const gfx::Size& src_size, |
| 139 const gfx::Rect& src_subrect, | 127 const gfx::Rect& src_subrect, |
| 140 const gfx::Size& dst_size, | 128 const gfx::Size& dst_size, |
| 141 unsigned char* out, | 129 unsigned char* out, |
| 142 const base::Callback<void(bool)>& callback, | 130 const base::Callback<void(bool)>& callback, |
| 143 GLHelper::ScalerQuality quality); | 131 GLHelper::ScalerQuality quality); |
| 144 | 132 |
| 145 void ReadbackTextureSync(WebGLId texture, | 133 void ReadbackTextureSync(GLuint texture, |
| 146 const gfx::Rect& src_rect, | 134 const gfx::Rect& src_rect, |
| 147 unsigned char* out); | 135 unsigned char* out); |
| 148 | 136 |
| 149 // Reads back bytes from the currently bound frame buffer. | 137 // Reads back bytes from the currently bound frame buffer. |
| 150 // Note that dst_size is specified in bytes, not pixels. | 138 // Note that dst_size is specified in bytes, not pixels. |
| 151 void ReadbackAsync( | 139 void ReadbackAsync(const gfx::Size& dst_size, |
| 152 const gfx::Size& dst_size, | 140 int32 bytes_per_row, // generally dst_size.width() * 4 |
| 153 int32 bytes_per_row, // generally dst_size.width() * 4 | 141 int32 row_stride_bytes, // generally dst_size.width() * 4 |
| 154 int32 row_stride_bytes, // generally dst_size.width() * 4 | 142 unsigned char* out, |
| 155 unsigned char* out, | 143 const base::Callback<void(bool)>& callback); |
| 156 const base::Callback<void(bool)>& callback); | |
| 157 | 144 |
| 158 void ReadbackPlane(TextureFrameBufferPair* source, | 145 void ReadbackPlane(TextureFrameBufferPair* source, |
| 159 const scoped_refptr<media::VideoFrame>& target, | 146 const scoped_refptr<media::VideoFrame>& target, |
| 160 int plane, | 147 int plane, |
| 161 int size_shift, | 148 int size_shift, |
| 162 const gfx::Rect& dst_subrect, | 149 const gfx::Rect& dst_subrect, |
| 163 const base::Callback<void(bool)>& callback); | 150 const base::Callback<void(bool)>& callback); |
| 164 | 151 |
| 165 blink::WebGLId CopyAndScaleTexture(WebGLId texture, | 152 GLuint CopyAndScaleTexture(GLuint texture, |
| 166 const gfx::Size& src_size, | 153 const gfx::Size& src_size, |
| 167 const gfx::Size& dst_size, | 154 const gfx::Size& dst_size, |
| 168 bool vertically_flip_texture, | 155 bool vertically_flip_texture, |
| 169 GLHelper::ScalerQuality quality); | 156 GLHelper::ScalerQuality quality); |
| 170 | 157 |
| 171 ReadbackYUVInterface* CreateReadbackPipelineYUV( | 158 ReadbackYUVInterface* CreateReadbackPipelineYUV( |
| 172 GLHelper::ScalerQuality quality, | 159 GLHelper::ScalerQuality quality, |
| 173 const gfx::Size& src_size, | 160 const gfx::Size& src_size, |
| 174 const gfx::Rect& src_subrect, | 161 const gfx::Rect& src_subrect, |
| 175 const gfx::Size& dst_size, | 162 const gfx::Size& dst_size, |
| 176 const gfx::Rect& dst_subrect, | 163 const gfx::Rect& dst_subrect, |
| 177 bool flip_vertically, | 164 bool flip_vertically, |
| 178 bool use_mrt); | 165 bool use_mrt); |
| 179 | 166 |
| 180 // Returns the maximum number of draw buffers available, | 167 // Returns the maximum number of draw buffers available, |
| 181 // 0 if GL_EXT_draw_buffers is not available. | 168 // 0 if GL_EXT_draw_buffers is not available. |
| 182 blink::WGC3Dint MaxDrawBuffers() const { | 169 GLint MaxDrawBuffers() const { return max_draw_buffers_; } |
| 183 return max_draw_buffers_; | |
| 184 } | |
| 185 | 170 |
| 186 private: | 171 private: |
| 187 // A single request to CropScaleReadbackAndCleanTexture. | 172 // A single request to CropScaleReadbackAndCleanTexture. |
| 188 // The main thread can cancel the request, before it's handled by the helper | 173 // The main thread can cancel the request, before it's handled by the helper |
| 189 // thread, by resetting the texture and pixels fields. Alternatively, the | 174 // thread, by resetting the texture and pixels fields. Alternatively, the |
| 190 // thread marks that it handles the request by resetting the pixels field | 175 // thread marks that it handles the request by resetting the pixels field |
| 191 // (meaning it guarantees that the callback with be called). | 176 // (meaning it guarantees that the callback with be called). |
| 192 // In either case, the callback must be called exactly once, and the texture | 177 // In either case, the callback must be called exactly once, and the texture |
| 193 // must be deleted by the main thread context. | 178 // must be deleted by the main thread gl. |
| 194 struct Request { | 179 struct Request { |
| 195 Request(const gfx::Size& size_, | 180 Request(const gfx::Size& size_, |
| 196 int32 bytes_per_row_, | 181 int32 bytes_per_row_, |
| 197 int32 row_stride_bytes_, | 182 int32 row_stride_bytes_, |
| 198 unsigned char* pixels_, | 183 unsigned char* pixels_, |
| 199 const base::Callback<void(bool)>& callback_) | 184 const base::Callback<void(bool)>& callback_) |
| 200 : done(false), | 185 : done(false), |
| 201 size(size_), | 186 size(size_), |
| 202 bytes_per_row(bytes_per_row_), | 187 bytes_per_row(bytes_per_row_), |
| 203 row_stride_bytes(row_stride_bytes_), | 188 row_stride_bytes(row_stride_bytes_), |
| 204 pixels(pixels_), | 189 pixels(pixels_), |
| 205 callback(callback_), | 190 callback(callback_), |
| 206 buffer(0), | 191 buffer(0), |
| 207 query(0) { | 192 query(0) {} |
| 208 } | |
| 209 | 193 |
| 210 bool done; | 194 bool done; |
| 211 gfx::Size size; | 195 gfx::Size size; |
| 212 int bytes_per_row; | 196 int bytes_per_row; |
| 213 int row_stride_bytes; | 197 int row_stride_bytes; |
| 214 unsigned char* pixels; | 198 unsigned char* pixels; |
| 215 base::Callback<void(bool)> callback; | 199 base::Callback<void(bool)> callback; |
| 216 GLuint buffer; | 200 GLuint buffer; |
| 217 blink::WebGLId query; | 201 GLuint query; |
| 218 }; | 202 }; |
| 219 | 203 |
| 220 // A readback pipeline that also converts the data to YUV before | 204 // A readback pipeline that also converts the data to YUV before |
| 221 // reading it back. | 205 // reading it back. |
| 222 class ReadbackYUVImpl : public ReadbackYUVInterface { | 206 class ReadbackYUVImpl : public ReadbackYUVInterface { |
| 223 public: | 207 public: |
| 224 ReadbackYUVImpl(WebGraphicsContext3D* context, | 208 ReadbackYUVImpl(GLES2Interface* gl, |
| 225 CopyTextureToImpl* copy_impl, | 209 CopyTextureToImpl* copy_impl, |
| 226 GLHelperScaling* scaler_impl, | 210 GLHelperScaling* scaler_impl, |
| 227 GLHelper::ScalerQuality quality, | 211 GLHelper::ScalerQuality quality, |
| 228 const gfx::Size& src_size, | 212 const gfx::Size& src_size, |
| 229 const gfx::Rect& src_subrect, | 213 const gfx::Rect& src_subrect, |
| 230 const gfx::Size& dst_size, | 214 const gfx::Size& dst_size, |
| 231 const gfx::Rect& dst_subrect, | 215 const gfx::Rect& dst_subrect, |
| 232 bool flip_vertically); | 216 bool flip_vertically); |
| 233 | 217 |
| 234 virtual void ReadbackYUV( | 218 virtual void ReadbackYUV(const gpu::Mailbox& mailbox, |
| 235 const gpu::Mailbox& mailbox, | 219 uint32 sync_point, |
| 236 uint32 sync_point, | 220 const scoped_refptr<media::VideoFrame>& target, |
| 237 const scoped_refptr<media::VideoFrame>& target, | 221 const base::Callback<void(bool)>& callback) |
| 238 const base::Callback<void(bool)>& callback) OVERRIDE; | 222 OVERRIDE; |
| 239 | 223 |
| 240 virtual ScalerInterface* scaler() OVERRIDE { | 224 virtual ScalerInterface* scaler() OVERRIDE { return scaler_.scaler(); } |
| 241 return scaler_.scaler(); | |
| 242 } | |
| 243 | 225 |
| 244 private: | 226 private: |
| 245 WebGraphicsContext3D* context_; | 227 GLES2Interface* gl_; |
| 246 CopyTextureToImpl* copy_impl_; | 228 CopyTextureToImpl* copy_impl_; |
| 247 gfx::Size dst_size_; | 229 gfx::Size dst_size_; |
| 248 gfx::Rect dst_subrect_; | 230 gfx::Rect dst_subrect_; |
| 249 ScalerHolder scaler_; | 231 ScalerHolder scaler_; |
| 250 ScalerHolder y_; | 232 ScalerHolder y_; |
| 251 ScalerHolder u_; | 233 ScalerHolder u_; |
| 252 ScalerHolder v_; | 234 ScalerHolder v_; |
| 253 | 235 |
| 254 DISALLOW_COPY_AND_ASSIGN(ReadbackYUVImpl); | 236 DISALLOW_COPY_AND_ASSIGN(ReadbackYUVImpl); |
| 255 }; | 237 }; |
| 256 | 238 |
| 257 // A readback pipeline that also converts the data to YUV before | 239 // A readback pipeline that also converts the data to YUV before |
| 258 // reading it back. This one uses Multiple Render Targets, which | 240 // reading it back. This one uses Multiple Render Targets, which |
| 259 // may not be supported on all platforms. | 241 // may not be supported on all platforms. |
| 260 class ReadbackYUV_MRT : public ReadbackYUVInterface { | 242 class ReadbackYUV_MRT : public ReadbackYUVInterface { |
| 261 public: | 243 public: |
| 262 ReadbackYUV_MRT(WebGraphicsContext3D* context, | 244 ReadbackYUV_MRT(GLES2Interface* gl, |
| 263 CopyTextureToImpl* copy_impl, | 245 CopyTextureToImpl* copy_impl, |
| 264 GLHelperScaling* scaler_impl, | 246 GLHelperScaling* scaler_impl, |
| 265 GLHelper::ScalerQuality quality, | 247 GLHelper::ScalerQuality quality, |
| 266 const gfx::Size& src_size, | 248 const gfx::Size& src_size, |
| 267 const gfx::Rect& src_subrect, | 249 const gfx::Rect& src_subrect, |
| 268 const gfx::Size& dst_size, | 250 const gfx::Size& dst_size, |
| 269 const gfx::Rect& dst_subrect, | 251 const gfx::Rect& dst_subrect, |
| 270 bool flip_vertically); | 252 bool flip_vertically); |
| 271 | 253 |
| 272 virtual void ReadbackYUV( | 254 virtual void ReadbackYUV(const gpu::Mailbox& mailbox, |
| 273 const gpu::Mailbox& mailbox, | 255 uint32 sync_point, |
| 274 uint32 sync_point, | 256 const scoped_refptr<media::VideoFrame>& target, |
| 275 const scoped_refptr<media::VideoFrame>& target, | 257 const base::Callback<void(bool)>& callback) |
| 276 const base::Callback<void(bool)>& callback) OVERRIDE; | 258 OVERRIDE; |
| 277 | 259 |
| 278 virtual ScalerInterface* scaler() OVERRIDE { | 260 virtual ScalerInterface* scaler() OVERRIDE { return scaler_.scaler(); } |
| 279 return scaler_.scaler(); | |
| 280 } | |
| 281 | 261 |
| 282 private: | 262 private: |
| 283 WebGraphicsContext3D* context_; | 263 GLES2Interface* gl_; |
| 284 CopyTextureToImpl* copy_impl_; | 264 CopyTextureToImpl* copy_impl_; |
| 285 gfx::Size dst_size_; | 265 gfx::Size dst_size_; |
| 286 gfx::Rect dst_subrect_; | 266 gfx::Rect dst_subrect_; |
| 287 GLHelper::ScalerQuality quality_; | 267 GLHelper::ScalerQuality quality_; |
| 288 ScalerHolder scaler_; | 268 ScalerHolder scaler_; |
| 289 scoped_ptr<content::GLHelperScaling::ShaderInterface> pass1_shader_; | 269 scoped_ptr<content::GLHelperScaling::ShaderInterface> pass1_shader_; |
| 290 scoped_ptr<content::GLHelperScaling::ShaderInterface> pass2_shader_; | 270 scoped_ptr<content::GLHelperScaling::ShaderInterface> pass2_shader_; |
| 291 TextureFrameBufferPair y_; | 271 TextureFrameBufferPair y_; |
| 292 ScopedTexture uv_; | 272 ScopedTexture uv_; |
| 293 TextureFrameBufferPair u_; | 273 TextureFrameBufferPair u_; |
| 294 TextureFrameBufferPair v_; | 274 TextureFrameBufferPair v_; |
| 295 | 275 |
| 296 DISALLOW_COPY_AND_ASSIGN(ReadbackYUV_MRT); | 276 DISALLOW_COPY_AND_ASSIGN(ReadbackYUV_MRT); |
| 297 }; | 277 }; |
| 298 | 278 |
| 299 // Copies the block of pixels specified with |src_subrect| from |src_texture|, | 279 // Copies the block of pixels specified with |src_subrect| from |src_texture|, |
| 300 // scales it to |dst_size|, writes it into a texture, and returns its ID. | 280 // scales it to |dst_size|, writes it into a texture, and returns its ID. |
| 301 // |src_size| is the size of |src_texture|. | 281 // |src_size| is the size of |src_texture|. |
| 302 WebGLId ScaleTexture(WebGLId src_texture, | 282 GLuint ScaleTexture(GLuint src_texture, |
| 303 const gfx::Size& src_size, | 283 const gfx::Size& src_size, |
| 304 const gfx::Rect& src_subrect, | 284 const gfx::Rect& src_subrect, |
| 305 const gfx::Size& dst_size, | 285 const gfx::Size& dst_size, |
| 306 bool vertically_flip_texture, | 286 bool vertically_flip_texture, |
| 307 bool swizzle, | 287 bool swizzle, |
| 308 GLHelper::ScalerQuality quality); | 288 GLHelper::ScalerQuality quality); |
| 309 | 289 |
| 310 static void nullcallback(bool success) {} | 290 static void nullcallback(bool success) {} |
| 311 void ReadbackDone(Request *request); | 291 void ReadbackDone(Request* request); |
| 312 void FinishRequest(Request* request, bool result); | 292 void FinishRequest(Request* request, bool result); |
| 313 void CancelRequests(); | 293 void CancelRequests(); |
| 314 | 294 |
| 315 static const float kRGBtoYColorWeights[]; | 295 static const float kRGBtoYColorWeights[]; |
| 316 static const float kRGBtoUColorWeights[]; | 296 static const float kRGBtoUColorWeights[]; |
| 317 static const float kRGBtoVColorWeights[]; | 297 static const float kRGBtoVColorWeights[]; |
| 318 | 298 |
| 319 WebGraphicsContext3D* context_; | 299 GLES2Interface* gl_; |
| 320 gpu::ContextSupport* context_support_; | 300 gpu::ContextSupport* context_support_; |
| 321 GLHelper* helper_; | 301 GLHelper* helper_; |
| 322 | 302 |
| 323 // A scoped flush that will ensure all resource deletions are flushed when | 303 // A scoped flush that will ensure all resource deletions are flushed when |
| 324 // this object is destroyed. Must be declared before other Scoped* fields. | 304 // this object is destroyed. Must be declared before other Scoped* fields. |
| 325 ScopedFlush flush_; | 305 ScopedFlush flush_; |
| 326 | 306 |
| 327 std::queue<Request*> request_queue_; | 307 std::queue<Request*> request_queue_; |
| 328 blink::WGC3Dint max_draw_buffers_; | 308 GLint max_draw_buffers_; |
| 329 }; | 309 }; |
| 330 | 310 |
| 331 GLHelper::ScalerInterface* GLHelper::CreateScaler( | 311 GLHelper::ScalerInterface* GLHelper::CreateScaler(ScalerQuality quality, |
| 332 ScalerQuality quality, | 312 const gfx::Size& src_size, |
| 333 const gfx::Size& src_size, | 313 const gfx::Rect& src_subrect, |
| 334 const gfx::Rect& src_subrect, | 314 const gfx::Size& dst_size, |
| 335 const gfx::Size& dst_size, | 315 bool vertically_flip_texture, |
| 336 bool vertically_flip_texture, | 316 bool swizzle) { |
| 337 bool swizzle) { | |
| 338 InitScalerImpl(); | 317 InitScalerImpl(); |
| 339 return scaler_impl_->CreateScaler(quality, | 318 return scaler_impl_->CreateScaler(quality, |
| 340 src_size, | 319 src_size, |
| 341 src_subrect, | 320 src_subrect, |
| 342 dst_size, | 321 dst_size, |
| 343 vertically_flip_texture, | 322 vertically_flip_texture, |
| 344 swizzle); | 323 swizzle); |
| 345 } | 324 } |
| 346 | 325 |
| 347 WebGLId GLHelper::CopyTextureToImpl::ScaleTexture( | 326 GLuint GLHelper::CopyTextureToImpl::ScaleTexture( |
| 348 WebGLId src_texture, | 327 GLuint src_texture, |
| 349 const gfx::Size& src_size, | 328 const gfx::Size& src_size, |
| 350 const gfx::Rect& src_subrect, | 329 const gfx::Rect& src_subrect, |
| 351 const gfx::Size& dst_size, | 330 const gfx::Size& dst_size, |
| 352 bool vertically_flip_texture, | 331 bool vertically_flip_texture, |
| 353 bool swizzle, | 332 bool swizzle, |
| 354 GLHelper::ScalerQuality quality) { | 333 GLHelper::ScalerQuality quality) { |
| 355 scoped_ptr<ScalerInterface> scaler( | 334 scoped_ptr<ScalerInterface> scaler( |
| 356 helper_->CreateScaler(quality, | 335 helper_->CreateScaler(quality, |
| 357 src_size, | 336 src_size, |
| 358 src_subrect, | 337 src_subrect, |
| 359 dst_size, | 338 dst_size, |
| 360 vertically_flip_texture, | 339 vertically_flip_texture, |
| 361 swizzle)); | 340 swizzle)); |
| 362 | 341 |
| 363 WebGLId dst_texture = context_->createTexture(); | 342 GLuint dst_texture = 0u; |
| 343 gl_->GenTextures(1, &dst_texture); |
| 364 { | 344 { |
| 365 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, dst_texture); | 345 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, dst_texture); |
| 366 context_->texImage2D(GL_TEXTURE_2D, | 346 gl_->TexImage2D(GL_TEXTURE_2D, |
| 367 0, | 347 0, |
| 368 GL_RGBA, | 348 GL_RGBA, |
| 369 dst_size.width(), | 349 dst_size.width(), |
| 370 dst_size.height(), | 350 dst_size.height(), |
| 371 0, | 351 0, |
| 372 GL_RGBA, | 352 GL_RGBA, |
| 373 GL_UNSIGNED_BYTE, | 353 GL_UNSIGNED_BYTE, |
| 374 NULL); | 354 NULL); |
| 375 } | 355 } |
| 376 scaler->Scale(src_texture, dst_texture); | 356 scaler->Scale(src_texture, dst_texture); |
| 377 return dst_texture; | 357 return dst_texture; |
| 378 } | 358 } |
| 379 | 359 |
| 380 void GLHelper::CopyTextureToImpl::ReadbackAsync( | 360 void GLHelper::CopyTextureToImpl::ReadbackAsync( |
| 381 const gfx::Size& dst_size, | 361 const gfx::Size& dst_size, |
| 382 int32 bytes_per_row, | 362 int32 bytes_per_row, |
| 383 int32 row_stride_bytes, | 363 int32 row_stride_bytes, |
| 384 unsigned char* out, | 364 unsigned char* out, |
| 385 const base::Callback<void(bool)>& callback) { | 365 const base::Callback<void(bool)>& callback) { |
| 386 Request* request = new Request(dst_size, | 366 Request* request = |
| 387 bytes_per_row, | 367 new Request(dst_size, bytes_per_row, row_stride_bytes, out, callback); |
| 388 row_stride_bytes, | |
| 389 out, | |
| 390 callback); | |
| 391 request_queue_.push(request); | 368 request_queue_.push(request); |
| 392 request->buffer = context_->createBuffer(); | 369 request->buffer = 0u; |
| 393 context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, | 370 gl_->GenBuffers(1, &request->buffer); |
| 394 request->buffer); | 371 gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, request->buffer); |
| 395 context_->bufferData(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, | 372 gl_->BufferData(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, |
| 396 4 * dst_size.GetArea(), | 373 4 * dst_size.GetArea(), |
| 397 NULL, | 374 NULL, |
| 398 GL_STREAM_READ); | 375 GL_STREAM_READ); |
| 399 | 376 |
| 400 request->query = context_->createQueryEXT(); | 377 request->query = 0u; |
| 401 context_->beginQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM, | 378 gl_->GenQueriesEXT(1, &request->query); |
| 402 request->query); | 379 gl_->BeginQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM, request->query); |
| 403 context_->readPixels(0, 0, dst_size.width(), dst_size.height(), | 380 gl_->ReadPixels(0, |
| 404 GL_RGBA, GL_UNSIGNED_BYTE, NULL); | 381 0, |
| 405 context_->endQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM); | 382 dst_size.width(), |
| 406 context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0); | 383 dst_size.height(), |
| 384 GL_RGBA, |
| 385 GL_UNSIGNED_BYTE, |
| 386 NULL); |
| 387 gl_->EndQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM); |
| 388 gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0); |
| 407 context_support_->SignalQuery( | 389 context_support_->SignalQuery( |
| 408 request->query, | 390 request->query, |
| 409 base::Bind(&CopyTextureToImpl::ReadbackDone, AsWeakPtr(), request)); | 391 base::Bind(&CopyTextureToImpl::ReadbackDone, AsWeakPtr(), request)); |
| 410 } | 392 } |
| 411 | 393 |
| 412 | |
| 413 void GLHelper::CopyTextureToImpl::CropScaleReadbackAndCleanTexture( | 394 void GLHelper::CopyTextureToImpl::CropScaleReadbackAndCleanTexture( |
| 414 WebGLId src_texture, | 395 GLuint src_texture, |
| 415 const gfx::Size& src_size, | 396 const gfx::Size& src_size, |
| 416 const gfx::Rect& src_subrect, | 397 const gfx::Rect& src_subrect, |
| 417 const gfx::Size& dst_size, | 398 const gfx::Size& dst_size, |
| 418 unsigned char* out, | 399 unsigned char* out, |
| 419 const base::Callback<void(bool)>& callback, | 400 const base::Callback<void(bool)>& callback, |
| 420 GLHelper::ScalerQuality quality) { | 401 GLHelper::ScalerQuality quality) { |
| 421 WebGLId texture = ScaleTexture(src_texture, | 402 GLuint texture = ScaleTexture(src_texture, |
| 422 src_size, | 403 src_size, |
| 423 src_subrect, | 404 src_subrect, |
| 424 dst_size, | 405 dst_size, |
| 425 true, | 406 true, |
| 426 #if (SK_R32_SHIFT == 16) && !SK_B32_SHIFT | 407 #if (SK_R32_SHIFT == 16) && !SK_B32_SHIFT |
| 427 true, | 408 true, |
| 428 #else | 409 #else |
| 429 false, | 410 false, |
| 430 #endif | 411 #endif |
| 431 quality); | 412 quality); |
| 432 ScopedFramebuffer dst_framebuffer(context_, context_->createFramebuffer()); | 413 ScopedFramebuffer dst_framebuffer(gl_); |
| 433 ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(context_, | 414 ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(gl_, |
| 434 dst_framebuffer); | 415 dst_framebuffer); |
| 435 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, texture); | 416 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture); |
| 436 context_->framebufferTexture2D(GL_FRAMEBUFFER, | 417 gl_->FramebufferTexture2D( |
| 437 GL_COLOR_ATTACHMENT0, | 418 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); |
| 438 GL_TEXTURE_2D, | 419 ReadbackAsync( |
| 439 texture, | 420 dst_size, dst_size.width() * 4, dst_size.width() * 4, out, callback); |
| 440 0); | 421 gl_->DeleteTextures(1, &texture); |
| 441 ReadbackAsync(dst_size, | |
| 442 dst_size.width() * 4, | |
| 443 dst_size.width() * 4, | |
| 444 out, | |
| 445 callback); | |
| 446 context_->deleteTexture(texture); | |
| 447 } | 422 } |
| 448 | 423 |
| 449 void GLHelper::CopyTextureToImpl::ReadbackTextureSync( | 424 void GLHelper::CopyTextureToImpl::ReadbackTextureSync(GLuint texture, |
| 450 WebGLId texture, | 425 const gfx::Rect& src_rect, |
| 451 const gfx::Rect& src_rect, | 426 unsigned char* out) { |
| 452 unsigned char* out) { | 427 ScopedFramebuffer dst_framebuffer(gl_); |
| 453 ScopedFramebuffer dst_framebuffer(context_, context_->createFramebuffer()); | 428 ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(gl_, |
| 454 ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(context_, | |
| 455 dst_framebuffer); | 429 dst_framebuffer); |
| 456 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, texture); | 430 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture); |
| 457 context_->framebufferTexture2D(GL_FRAMEBUFFER, | 431 gl_->FramebufferTexture2D( |
| 458 GL_COLOR_ATTACHMENT0, | 432 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); |
| 459 GL_TEXTURE_2D, | 433 gl_->ReadPixels(src_rect.x(), |
| 460 texture, | 434 src_rect.y(), |
| 461 0); | 435 src_rect.width(), |
| 462 context_->readPixels(src_rect.x(), | 436 src_rect.height(), |
| 463 src_rect.y(), | 437 GL_RGBA, |
| 464 src_rect.width(), | 438 GL_UNSIGNED_BYTE, |
| 465 src_rect.height(), | 439 out); |
| 466 GL_RGBA, | |
| 467 GL_UNSIGNED_BYTE, | |
| 468 out); | |
| 469 } | 440 } |
| 470 | 441 |
| 471 blink::WebGLId GLHelper::CopyTextureToImpl::CopyAndScaleTexture( | 442 GLuint GLHelper::CopyTextureToImpl::CopyAndScaleTexture( |
| 472 WebGLId src_texture, | 443 GLuint src_texture, |
| 473 const gfx::Size& src_size, | 444 const gfx::Size& src_size, |
| 474 const gfx::Size& dst_size, | 445 const gfx::Size& dst_size, |
| 475 bool vertically_flip_texture, | 446 bool vertically_flip_texture, |
| 476 GLHelper::ScalerQuality quality) { | 447 GLHelper::ScalerQuality quality) { |
| 477 return ScaleTexture(src_texture, | 448 return ScaleTexture(src_texture, |
| 478 src_size, | 449 src_size, |
| 479 gfx::Rect(src_size), | 450 gfx::Rect(src_size), |
| 480 dst_size, | 451 dst_size, |
| 481 vertically_flip_texture, | 452 vertically_flip_texture, |
| 482 false, | 453 false, |
| 483 quality); | 454 quality); |
| 484 } | 455 } |
| 485 | 456 |
| 486 void GLHelper::CopyTextureToImpl::ReadbackDone(Request* finished_request) { | 457 void GLHelper::CopyTextureToImpl::ReadbackDone(Request* finished_request) { |
| 487 TRACE_EVENT0("mirror", | 458 TRACE_EVENT0("mirror", |
| 488 "GLHelper::CopyTextureToImpl::CheckReadbackFramebufferComplete"); | 459 "GLHelper::CopyTextureToImpl::CheckReadbackFramebufferComplete"); |
| 489 finished_request->done = true; | 460 finished_request->done = true; |
| 490 | 461 |
| 491 // We process transfer requests in the order they were received, regardless | 462 // We process transfer requests in the order they were received, regardless |
| 492 // of the order we get the callbacks in. | 463 // of the order we get the callbacks in. |
| 493 while (!request_queue_.empty()) { | 464 while (!request_queue_.empty()) { |
| 494 Request* request = request_queue_.front(); | 465 Request* request = request_queue_.front(); |
| 495 if (!request->done) { | 466 if (!request->done) { |
| 496 break; | 467 break; |
| 497 } | 468 } |
| 498 | 469 |
| 499 bool result = false; | 470 bool result = false; |
| 500 if (request->buffer != 0) { | 471 if (request->buffer != 0) { |
| 501 context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, | 472 gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, request->buffer); |
| 502 request->buffer); | 473 unsigned char* data = static_cast<unsigned char*>(gl_->MapBufferCHROMIUM( |
| 503 unsigned char* data = static_cast<unsigned char *>( | 474 GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, GL_READ_ONLY)); |
| 504 context_->mapBufferCHROMIUM( | |
| 505 GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, GL_READ_ONLY)); | |
| 506 if (data) { | 475 if (data) { |
| 507 result = true; | 476 result = true; |
| 508 if (request->bytes_per_row == request->size.width() * 4 && | 477 if (request->bytes_per_row == request->size.width() * 4 && |
| 509 request->bytes_per_row == request->row_stride_bytes) { | 478 request->bytes_per_row == request->row_stride_bytes) { |
| 510 memcpy(request->pixels, data, request->size.GetArea() * 4); | 479 memcpy(request->pixels, data, request->size.GetArea() * 4); |
| 511 } else { | 480 } else { |
| 512 unsigned char* out = request->pixels; | 481 unsigned char* out = request->pixels; |
| 513 for (int y = 0; y < request->size.height(); y++) { | 482 for (int y = 0; y < request->size.height(); y++) { |
| 514 memcpy(out, data, request->bytes_per_row); | 483 memcpy(out, data, request->bytes_per_row); |
| 515 out += request->row_stride_bytes; | 484 out += request->row_stride_bytes; |
| 516 data += request->size.width() * 4; | 485 data += request->size.width() * 4; |
| 517 } | 486 } |
| 518 } | 487 } |
| 519 context_->unmapBufferCHROMIUM(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM); | 488 gl_->UnmapBufferCHROMIUM(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM); |
| 520 } | 489 } |
| 521 context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0); | 490 gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0); |
| 522 } | 491 } |
| 523 | 492 |
| 524 FinishRequest(request, result); | 493 FinishRequest(request, result); |
| 525 } | 494 } |
| 526 } | 495 } |
| 527 | 496 |
| 528 void GLHelper::CopyTextureToImpl::FinishRequest(Request* request, | 497 void GLHelper::CopyTextureToImpl::FinishRequest(Request* request, bool result) { |
| 529 bool result) { | |
| 530 TRACE_EVENT0("mirror", "GLHelper::CopyTextureToImpl::FinishRequest"); | 498 TRACE_EVENT0("mirror", "GLHelper::CopyTextureToImpl::FinishRequest"); |
| 531 DCHECK(request_queue_.front() == request); | 499 DCHECK(request_queue_.front() == request); |
| 532 request_queue_.pop(); | 500 request_queue_.pop(); |
| 533 request->callback.Run(result); | 501 request->callback.Run(result); |
| 534 ScopedFlush flush(context_); | 502 ScopedFlush flush(gl_); |
| 535 if (request->query != 0) { | 503 if (request->query != 0) { |
| 536 context_->deleteQueryEXT(request->query); | 504 gl_->DeleteQueriesEXT(1, &request->query); |
| 537 request->query = 0; | 505 request->query = 0; |
| 538 } | 506 } |
| 539 if (request->buffer != 0) { | 507 if (request->buffer != 0) { |
| 540 context_->deleteBuffer(request->buffer); | 508 gl_->DeleteBuffers(1, &request->buffer); |
| 541 request->buffer = 0; | 509 request->buffer = 0; |
| 542 } | 510 } |
| 543 delete request; | 511 delete request; |
| 544 } | 512 } |
| 545 | 513 |
| 546 void GLHelper::CopyTextureToImpl::CancelRequests() { | 514 void GLHelper::CopyTextureToImpl::CancelRequests() { |
| 547 while (!request_queue_.empty()) { | 515 while (!request_queue_.empty()) { |
| 548 Request* request = request_queue_.front(); | 516 Request* request = request_queue_.front(); |
| 549 FinishRequest(request, false); | 517 FinishRequest(request, false); |
| 550 } | 518 } |
| 551 } | 519 } |
| 552 | 520 |
| 553 GLHelper::GLHelper(blink::WebGraphicsContext3D* context, | 521 GLHelper::GLHelper(GLES2Interface* gl, gpu::ContextSupport* context_support) |
| 554 gpu::ContextSupport* context_support) | 522 : gl_(gl), context_support_(context_support) {} |
| 555 : context_(context), | |
| 556 context_support_(context_support) { | |
| 557 } | |
| 558 | 523 |
| 559 GLHelper::~GLHelper() { | 524 GLHelper::~GLHelper() {} |
| 560 } | |
| 561 | 525 |
| 562 void GLHelper::CropScaleReadbackAndCleanTexture( | 526 void GLHelper::CropScaleReadbackAndCleanTexture( |
| 563 WebGLId src_texture, | 527 GLuint src_texture, |
| 564 const gfx::Size& src_size, | 528 const gfx::Size& src_size, |
| 565 const gfx::Rect& src_subrect, | 529 const gfx::Rect& src_subrect, |
| 566 const gfx::Size& dst_size, | 530 const gfx::Size& dst_size, |
| 567 unsigned char* out, | 531 unsigned char* out, |
| 568 const base::Callback<void(bool)>& callback) { | 532 const base::Callback<void(bool)>& callback) { |
| 569 InitCopyTextToImpl(); | 533 InitCopyTextToImpl(); |
| 570 copy_texture_to_impl_->CropScaleReadbackAndCleanTexture( | 534 copy_texture_to_impl_->CropScaleReadbackAndCleanTexture( |
| 571 src_texture, | 535 src_texture, |
| 572 src_size, | 536 src_size, |
| 573 src_subrect, | 537 src_subrect, |
| 574 dst_size, | 538 dst_size, |
| 575 out, | 539 out, |
| 576 callback, | 540 callback, |
| 577 GLHelper::SCALER_QUALITY_FAST); | 541 GLHelper::SCALER_QUALITY_FAST); |
| 578 } | 542 } |
| 579 | 543 |
| 580 void GLHelper::CropScaleReadbackAndCleanMailbox( | 544 void GLHelper::CropScaleReadbackAndCleanMailbox( |
| 581 const gpu::Mailbox& src_mailbox, | 545 const gpu::Mailbox& src_mailbox, |
| 582 uint32 sync_point, | 546 uint32 sync_point, |
| 583 const gfx::Size& src_size, | 547 const gfx::Size& src_size, |
| 584 const gfx::Rect& src_subrect, | 548 const gfx::Rect& src_subrect, |
| 585 const gfx::Size& dst_size, | 549 const gfx::Size& dst_size, |
| 586 unsigned char* out, | 550 unsigned char* out, |
| 587 const base::Callback<void(bool)>& callback) { | 551 const base::Callback<void(bool)>& callback) { |
| 588 WebGLId mailbox_texture = ConsumeMailboxToTexture(src_mailbox, sync_point); | 552 GLuint mailbox_texture = ConsumeMailboxToTexture(src_mailbox, sync_point); |
| 589 CropScaleReadbackAndCleanTexture( | 553 CropScaleReadbackAndCleanTexture( |
| 590 mailbox_texture, src_size, src_subrect, dst_size, out, callback); | 554 mailbox_texture, src_size, src_subrect, dst_size, out, callback); |
| 591 context_->deleteTexture(mailbox_texture); | 555 gl_->DeleteTextures(1, &mailbox_texture); |
| 592 } | 556 } |
| 593 | 557 |
| 594 void GLHelper::ReadbackTextureSync(blink::WebGLId texture, | 558 void GLHelper::ReadbackTextureSync(GLuint texture, |
| 595 const gfx::Rect& src_rect, | 559 const gfx::Rect& src_rect, |
| 596 unsigned char* out) { | 560 unsigned char* out) { |
| 597 InitCopyTextToImpl(); | 561 InitCopyTextToImpl(); |
| 598 copy_texture_to_impl_->ReadbackTextureSync(texture, | 562 copy_texture_to_impl_->ReadbackTextureSync(texture, src_rect, out); |
| 599 src_rect, | |
| 600 out); | |
| 601 } | 563 } |
| 602 | 564 |
| 603 blink::WebGLId GLHelper::CopyTexture(blink::WebGLId texture, | 565 GLuint GLHelper::CopyTexture(GLuint texture, const gfx::Size& size) { |
| 604 const gfx::Size& size) { | |
| 605 InitCopyTextToImpl(); | 566 InitCopyTextToImpl(); |
| 606 return copy_texture_to_impl_->CopyAndScaleTexture( | 567 return copy_texture_to_impl_->CopyAndScaleTexture( |
| 607 texture, | 568 texture, size, size, false, GLHelper::SCALER_QUALITY_FAST); |
| 608 size, | |
| 609 size, | |
| 610 false, | |
| 611 GLHelper::SCALER_QUALITY_FAST); | |
| 612 } | 569 } |
| 613 | 570 |
| 614 blink::WebGLId GLHelper::CopyAndScaleTexture( | 571 GLuint GLHelper::CopyAndScaleTexture(GLuint texture, |
| 615 blink::WebGLId texture, | 572 const gfx::Size& src_size, |
| 616 const gfx::Size& src_size, | 573 const gfx::Size& dst_size, |
| 617 const gfx::Size& dst_size, | 574 bool vertically_flip_texture, |
| 618 bool vertically_flip_texture, | 575 ScalerQuality quality) { |
| 619 ScalerQuality quality) { | |
| 620 InitCopyTextToImpl(); | 576 InitCopyTextToImpl(); |
| 621 return copy_texture_to_impl_->CopyAndScaleTexture(texture, | 577 return copy_texture_to_impl_->CopyAndScaleTexture( |
| 622 src_size, | 578 texture, src_size, dst_size, vertically_flip_texture, quality); |
| 623 dst_size, | |
| 624 vertically_flip_texture, | |
| 625 quality); | |
| 626 } | 579 } |
| 627 | 580 |
| 628 WebGLId GLHelper::CompileShaderFromSource( | 581 GLuint GLHelper::CompileShaderFromSource(const GLchar* source, GLenum type) { |
| 629 const blink::WGC3Dchar* source, | 582 GLuint shader = gl_->CreateShader(type); |
| 630 blink::WGC3Denum type) { | 583 GLint length = strlen(source); |
| 631 ScopedShader shader(context_, context_->createShader(type)); | 584 gl_->ShaderSource(shader, 1, &source, &length); |
| 632 context_->shaderSource(shader, source); | 585 gl_->CompileShader(shader); |
| 633 context_->compileShader(shader); | 586 GLint compile_status = 0; |
| 634 blink::WGC3Dint compile_status = 0; | 587 gl_->GetShaderiv(shader, GL_COMPILE_STATUS, &compile_status); |
| 635 context_->getShaderiv(shader, GL_COMPILE_STATUS, &compile_status); | |
| 636 if (!compile_status) { | 588 if (!compile_status) { |
| 637 LOG(ERROR) << std::string(context_->getShaderInfoLog(shader).utf8()); | 589 GLint log_length = 0; |
| 590 gl_->GetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length); |
| 591 if (log_length) { |
| 592 scoped_ptr<GLchar[]> log(new GLchar[log_length]); |
| 593 GLsizei returned_log_length = 0; |
| 594 gl_->GetShaderInfoLog( |
| 595 shader, log_length, &returned_log_length, log.get()); |
| 596 LOG(ERROR) << std::string(log.get(), returned_log_length); |
| 597 } |
| 598 gl_->DeleteShader(shader); |
| 638 return 0; | 599 return 0; |
| 639 } | 600 } |
| 640 return shader.Detach(); | 601 return shader; |
| 641 } | 602 } |
| 642 | 603 |
| 643 void GLHelper::InitCopyTextToImpl() { | 604 void GLHelper::InitCopyTextToImpl() { |
| 644 // Lazily initialize |copy_texture_to_impl_| | 605 // Lazily initialize |copy_texture_to_impl_| |
| 645 if (!copy_texture_to_impl_) | 606 if (!copy_texture_to_impl_) |
| 646 copy_texture_to_impl_.reset( | 607 copy_texture_to_impl_.reset( |
| 647 new CopyTextureToImpl(context_, context_support_, this)); | 608 new CopyTextureToImpl(gl_, context_support_, this)); |
| 648 } | 609 } |
| 649 | 610 |
| 650 void GLHelper::InitScalerImpl() { | 611 void GLHelper::InitScalerImpl() { |
| 651 // Lazily initialize |scaler_impl_| | 612 // Lazily initialize |scaler_impl_| |
| 652 if (!scaler_impl_) | 613 if (!scaler_impl_) |
| 653 scaler_impl_.reset(new GLHelperScaling(context_, this)); | 614 scaler_impl_.reset(new GLHelperScaling(gl_, this)); |
| 654 } | 615 } |
| 655 | 616 |
| 656 blink::WGC3Dint GLHelper::MaxDrawBuffers() { | 617 GLint GLHelper::MaxDrawBuffers() { |
| 657 InitCopyTextToImpl(); | 618 InitCopyTextToImpl(); |
| 658 return copy_texture_to_impl_->MaxDrawBuffers(); | 619 return copy_texture_to_impl_->MaxDrawBuffers(); |
| 659 } | 620 } |
| 660 | 621 |
| 661 void GLHelper::CopySubBufferDamage(blink::WebGLId texture, | 622 void GLHelper::CopySubBufferDamage(GLuint texture, |
| 662 blink::WebGLId previous_texture, | 623 GLuint previous_texture, |
| 663 const SkRegion& new_damage, | 624 const SkRegion& new_damage, |
| 664 const SkRegion& old_damage) { | 625 const SkRegion& old_damage) { |
| 665 SkRegion region(old_damage); | 626 SkRegion region(old_damage); |
| 666 if (region.op(new_damage, SkRegion::kDifference_Op)) { | 627 if (region.op(new_damage, SkRegion::kDifference_Op)) { |
| 667 ScopedFramebuffer dst_framebuffer(context_, | 628 ScopedFramebuffer dst_framebuffer(gl_); |
| 668 context_->createFramebuffer()); | 629 ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(gl_, |
| 669 ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(context_, | |
| 670 dst_framebuffer); | 630 dst_framebuffer); |
| 671 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, texture); | 631 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture); |
| 672 context_->framebufferTexture2D(GL_FRAMEBUFFER, | 632 gl_->FramebufferTexture2D(GL_FRAMEBUFFER, |
| 673 GL_COLOR_ATTACHMENT0, | 633 GL_COLOR_ATTACHMENT0, |
| 674 GL_TEXTURE_2D, | 634 GL_TEXTURE_2D, |
| 675 previous_texture, | 635 previous_texture, |
| 676 0); | 636 0); |
| 677 for (SkRegion::Iterator it(region); !it.done(); it.next()) { | 637 for (SkRegion::Iterator it(region); !it.done(); it.next()) { |
| 678 const SkIRect& rect = it.rect(); | 638 const SkIRect& rect = it.rect(); |
| 679 context_->copyTexSubImage2D(GL_TEXTURE_2D, 0, | 639 gl_->CopyTexSubImage2D(GL_TEXTURE_2D, |
| 680 rect.x(), rect.y(), | 640 0, |
| 681 rect.x(), rect.y(), | 641 rect.x(), |
| 682 rect.width(), rect.height()); | 642 rect.y(), |
| 643 rect.x(), |
| 644 rect.y(), |
| 645 rect.width(), |
| 646 rect.height()); |
| 683 } | 647 } |
| 684 context_->flush(); | 648 gl_->Flush(); |
| 685 } | 649 } |
| 686 } | 650 } |
| 687 | 651 |
| 688 blink::WebGLId GLHelper::CreateTexture() { | 652 GLuint GLHelper::CreateTexture() { |
| 689 blink::WebGLId texture = context_->createTexture(); | 653 GLuint texture = 0u; |
| 690 content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, | 654 gl_->GenTextures(1, &texture); |
| 691 texture); | 655 content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture); |
| 692 context_->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 656 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| 693 context_->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 657 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
| 694 context_->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 658 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| 695 context_->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 659 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| 696 return texture; | 660 return texture; |
| 697 } | 661 } |
| 698 | 662 |
| 699 void GLHelper::DeleteTexture(blink::WebGLId texture_id) { | 663 void GLHelper::DeleteTexture(GLuint texture_id) { |
| 700 context_->deleteTexture(texture_id); | 664 gl_->DeleteTextures(1, &texture_id); |
| 701 } | 665 } |
| 702 | 666 |
| 703 uint32 GLHelper::InsertSyncPoint() { return context_->insertSyncPoint(); } | 667 uint32 GLHelper::InsertSyncPoint() { return gl_->InsertSyncPointCHROMIUM(); } |
| 704 | 668 |
| 705 void GLHelper::WaitSyncPoint(uint32 sync_point) { | 669 void GLHelper::WaitSyncPoint(uint32 sync_point) { |
| 706 context_->waitSyncPoint(sync_point); | 670 gl_->WaitSyncPointCHROMIUM(sync_point); |
| 707 } | 671 } |
| 708 | 672 |
| 709 gpu::Mailbox GLHelper::ProduceMailboxFromTexture(blink::WebGLId texture_id, | 673 gpu::Mailbox GLHelper::ProduceMailboxFromTexture(GLuint texture_id, |
| 710 uint32* sync_point) { | 674 uint32* sync_point) { |
| 711 gpu::Mailbox mailbox; | 675 gpu::Mailbox mailbox; |
| 712 context_->genMailboxCHROMIUM(mailbox.name); | 676 gl_->GenMailboxCHROMIUM(mailbox.name); |
| 713 if (mailbox.IsZero()) { | 677 if (mailbox.IsZero()) { |
| 714 *sync_point = 0; | 678 *sync_point = 0; |
| 715 return mailbox; | 679 return mailbox; |
| 716 } | 680 } |
| 717 content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, | 681 content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture_id); |
| 718 texture_id); | 682 gl_->ProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); |
| 719 context_->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); | 683 *sync_point = InsertSyncPoint(); |
| 720 *sync_point = context_->insertSyncPoint(); | |
| 721 return mailbox; | 684 return mailbox; |
| 722 } | 685 } |
| 723 | 686 |
| 724 blink::WebGLId GLHelper::ConsumeMailboxToTexture(const gpu::Mailbox& mailbox, | 687 GLuint GLHelper::ConsumeMailboxToTexture(const gpu::Mailbox& mailbox, |
| 725 uint32 sync_point) { | 688 uint32 sync_point) { |
| 726 if (mailbox.IsZero()) | 689 if (mailbox.IsZero()) |
| 727 return 0; | 690 return 0; |
| 728 if (sync_point) | 691 if (sync_point) |
| 729 context_->waitSyncPoint(sync_point); | 692 WaitSyncPoint(sync_point); |
| 730 blink::WebGLId texture = CreateTexture(); | 693 GLuint texture = CreateTexture(); |
| 731 content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, | 694 content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture); |
| 732 texture); | 695 gl_->ConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); |
| 733 context_->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name); | |
| 734 return texture; | 696 return texture; |
| 735 } | 697 } |
| 736 | 698 |
| 737 void GLHelper::ResizeTexture(blink::WebGLId texture, const gfx::Size& size) { | 699 void GLHelper::ResizeTexture(GLuint texture, const gfx::Size& size) { |
| 738 content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, texture); | 700 content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture); |
| 739 context_->texImage2D(GL_TEXTURE_2D, 0, GL_RGB, | 701 gl_->TexImage2D(GL_TEXTURE_2D, |
| 740 size.width(), size.height(), 0, | 702 0, |
| 741 GL_RGB, GL_UNSIGNED_BYTE, NULL); | 703 GL_RGB, |
| 704 size.width(), |
| 705 size.height(), |
| 706 0, |
| 707 GL_RGB, |
| 708 GL_UNSIGNED_BYTE, |
| 709 NULL); |
| 742 } | 710 } |
| 743 | 711 |
| 744 void GLHelper::CopyTextureSubImage(blink::WebGLId texture, | 712 void GLHelper::CopyTextureSubImage(GLuint texture, const gfx::Rect& rect) { |
| 745 const gfx::Rect& rect) { | 713 content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture); |
| 746 content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, texture); | 714 gl_->CopyTexSubImage2D(GL_TEXTURE_2D, |
| 747 context_->copyTexSubImage2D(GL_TEXTURE_2D, 0, | 715 0, |
| 748 rect.x(), rect.y(), | 716 rect.x(), |
| 749 rect.x(), rect.y(), rect.width(), rect.height()); | 717 rect.y(), |
| 718 rect.x(), |
| 719 rect.y(), |
| 720 rect.width(), |
| 721 rect.height()); |
| 750 } | 722 } |
| 751 | 723 |
| 752 void GLHelper::CopyTextureFullImage(blink::WebGLId texture, | 724 void GLHelper::CopyTextureFullImage(GLuint texture, const gfx::Size& size) { |
| 753 const gfx::Size& size) { | 725 content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture); |
| 754 content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, texture); | 726 gl_->CopyTexImage2D( |
| 755 context_->copyTexImage2D(GL_TEXTURE_2D, 0, | 727 GL_TEXTURE_2D, 0, GL_RGB, 0, 0, size.width(), size.height(), 0); |
| 756 GL_RGB, | |
| 757 0, 0, | |
| 758 size.width(), size.height(), 0); | |
| 759 } | 728 } |
| 760 | 729 |
| 761 void GLHelper::CopyTextureToImpl::ReadbackPlane( | 730 void GLHelper::CopyTextureToImpl::ReadbackPlane( |
| 762 TextureFrameBufferPair* source, | 731 TextureFrameBufferPair* source, |
| 763 const scoped_refptr<media::VideoFrame>& target, | 732 const scoped_refptr<media::VideoFrame>& target, |
| 764 int plane, | 733 int plane, |
| 765 int size_shift, | 734 int size_shift, |
| 766 const gfx::Rect& dst_subrect, | 735 const gfx::Rect& dst_subrect, |
| 767 const base::Callback<void(bool)>& callback) { | 736 const base::Callback<void(bool)>& callback) { |
| 768 context_->bindFramebuffer(GL_FRAMEBUFFER, source->framebuffer()); | 737 gl_->BindFramebuffer(GL_FRAMEBUFFER, source->framebuffer()); |
| 769 size_t offset = target->stride(plane) * (dst_subrect.y() >> size_shift) + | 738 size_t offset = target->stride(plane) * (dst_subrect.y() >> size_shift) + |
| 770 (dst_subrect.x() >> size_shift); | 739 (dst_subrect.x() >> size_shift); |
| 771 ReadbackAsync( | 740 ReadbackAsync(source->size(), |
| 772 source->size(), | 741 dst_subrect.width() >> size_shift, |
| 773 dst_subrect.width() >> size_shift, | 742 target->stride(plane), |
| 774 target->stride(plane), | 743 target->data(plane) + offset, |
| 775 target->data(plane) + offset, | 744 callback); |
| 776 callback); | |
| 777 } | 745 } |
| 778 | 746 |
| 779 const float GLHelper::CopyTextureToImpl::kRGBtoYColorWeights[] = { | 747 const float GLHelper::CopyTextureToImpl::kRGBtoYColorWeights[] = { |
| 780 0.257f, 0.504f, 0.098f, 0.0625f | 748 0.257f, 0.504f, 0.098f, 0.0625f}; |
| 781 }; | |
| 782 const float GLHelper::CopyTextureToImpl::kRGBtoUColorWeights[] = { | 749 const float GLHelper::CopyTextureToImpl::kRGBtoUColorWeights[] = { |
| 783 -0.148f, -0.291f, 0.439f, 0.5f | 750 -0.148f, -0.291f, 0.439f, 0.5f}; |
| 784 }; | |
| 785 const float GLHelper::CopyTextureToImpl::kRGBtoVColorWeights[] = { | 751 const float GLHelper::CopyTextureToImpl::kRGBtoVColorWeights[] = { |
| 786 0.439f, -0.368f, -0.071f, 0.5f | 752 0.439f, -0.368f, -0.071f, 0.5f}; |
| 787 }; | |
| 788 | 753 |
| 789 // YUV readback constructors. Initiates the main scaler pipeline and | 754 // YUV readback constructors. Initiates the main scaler pipeline and |
| 790 // one planar scaler for each of the Y, U and V planes. | 755 // one planar scaler for each of the Y, U and V planes. |
| 791 GLHelper::CopyTextureToImpl::ReadbackYUVImpl::ReadbackYUVImpl( | 756 GLHelper::CopyTextureToImpl::ReadbackYUVImpl::ReadbackYUVImpl( |
| 792 WebGraphicsContext3D* context, | 757 GLES2Interface* gl, |
| 793 CopyTextureToImpl* copy_impl, | 758 CopyTextureToImpl* copy_impl, |
| 794 GLHelperScaling* scaler_impl, | 759 GLHelperScaling* scaler_impl, |
| 795 GLHelper::ScalerQuality quality, | 760 GLHelper::ScalerQuality quality, |
| 796 const gfx::Size& src_size, | 761 const gfx::Size& src_size, |
| 797 const gfx::Rect& src_subrect, | 762 const gfx::Rect& src_subrect, |
| 798 const gfx::Size& dst_size, | 763 const gfx::Size& dst_size, |
| 799 const gfx::Rect& dst_subrect, | 764 const gfx::Rect& dst_subrect, |
| 800 bool flip_vertically) | 765 bool flip_vertically) |
| 801 : context_(context), | 766 : gl_(gl), |
| 802 copy_impl_(copy_impl), | 767 copy_impl_(copy_impl), |
| 803 dst_size_(dst_size), | 768 dst_size_(dst_size), |
| 804 dst_subrect_(dst_subrect), | 769 dst_subrect_(dst_subrect), |
| 805 scaler_(context, scaler_impl->CreateScaler( | 770 scaler_(gl, |
| 806 quality, | 771 scaler_impl->CreateScaler(quality, |
| 807 src_size, | 772 src_size, |
| 808 src_subrect, | 773 src_subrect, |
| 809 dst_subrect.size(), | 774 dst_subrect.size(), |
| 810 flip_vertically, | 775 flip_vertically, |
| 811 false)), | 776 false)), |
| 812 y_(context, scaler_impl->CreatePlanarScaler( | 777 y_(gl, |
| 813 dst_subrect.size(), | 778 scaler_impl->CreatePlanarScaler( |
| 814 gfx::Rect(0, 0, | 779 dst_subrect.size(), |
| 815 (dst_subrect.width() + 3) & ~3, | 780 gfx::Rect(0, |
| 816 dst_subrect.height()), | 781 0, |
| 817 gfx::Size((dst_subrect.width() + 3) / 4, | 782 (dst_subrect.width() + 3) & ~3, |
| 818 dst_subrect.height()), | 783 dst_subrect.height()), |
| 819 false, | 784 gfx::Size((dst_subrect.width() + 3) / 4, dst_subrect.height()), |
| 820 kRGBtoYColorWeights)), | 785 false, |
| 821 u_(context, scaler_impl->CreatePlanarScaler( | 786 kRGBtoYColorWeights)), |
| 822 dst_subrect.size(), | 787 u_(gl, |
| 823 gfx::Rect(0, 0, | 788 scaler_impl->CreatePlanarScaler( |
| 824 (dst_subrect.width() + 7) & ~7, | 789 dst_subrect.size(), |
| 825 (dst_subrect.height() + 1) & ~1), | 790 gfx::Rect(0, |
| 826 gfx::Size((dst_subrect.width() + 7) / 8, | 791 0, |
| 827 (dst_subrect.height() + 1) / 2), | 792 (dst_subrect.width() + 7) & ~7, |
| 828 false, | 793 (dst_subrect.height() + 1) & ~1), |
| 829 kRGBtoUColorWeights)), | 794 gfx::Size((dst_subrect.width() + 7) / 8, |
| 830 v_(context, scaler_impl->CreatePlanarScaler( | 795 (dst_subrect.height() + 1) / 2), |
| 831 dst_subrect.size(), | 796 false, |
| 832 gfx::Rect(0, 0, | 797 kRGBtoUColorWeights)), |
| 833 (dst_subrect.width() + 7) & ~7, | 798 v_(gl, |
| 834 (dst_subrect.height() + 1) & ~1), | 799 scaler_impl->CreatePlanarScaler( |
| 835 gfx::Size((dst_subrect.width() + 7) / 8, | 800 dst_subrect.size(), |
| 836 (dst_subrect.height() + 1) / 2), | 801 gfx::Rect(0, |
| 837 false, | 802 0, |
| 838 kRGBtoVColorWeights)) { | 803 (dst_subrect.width() + 7) & ~7, |
| 804 (dst_subrect.height() + 1) & ~1), |
| 805 gfx::Size((dst_subrect.width() + 7) / 8, |
| 806 (dst_subrect.height() + 1) / 2), |
| 807 false, |
| 808 kRGBtoVColorWeights)) { |
| 839 DCHECK(!(dst_size.width() & 1)); | 809 DCHECK(!(dst_size.width() & 1)); |
| 840 DCHECK(!(dst_size.height() & 1)); | 810 DCHECK(!(dst_size.height() & 1)); |
| 841 DCHECK(!(dst_subrect.width() & 1)); | 811 DCHECK(!(dst_subrect.width() & 1)); |
| 842 DCHECK(!(dst_subrect.height() & 1)); | 812 DCHECK(!(dst_subrect.height() & 1)); |
| 843 DCHECK(!(dst_subrect.x() & 1)); | 813 DCHECK(!(dst_subrect.x() & 1)); |
| 844 DCHECK(!(dst_subrect.y() & 1)); | 814 DCHECK(!(dst_subrect.y() & 1)); |
| 845 } | 815 } |
| 846 | 816 |
| 847 static void CallbackKeepingVideoFrameAlive( | 817 static void CallbackKeepingVideoFrameAlive( |
| 848 scoped_refptr<media::VideoFrame> video_frame, | 818 scoped_refptr<media::VideoFrame> video_frame, |
| 849 const base::Callback<void(bool)>& callback, | 819 const base::Callback<void(bool)>& callback, |
| 850 bool success) { | 820 bool success) { |
| 851 callback.Run(success); | 821 callback.Run(success); |
| 852 } | 822 } |
| 853 | 823 |
| 854 void GLHelper::CopyTextureToImpl::ReadbackYUVImpl::ReadbackYUV( | 824 void GLHelper::CopyTextureToImpl::ReadbackYUVImpl::ReadbackYUV( |
| 855 const gpu::Mailbox& mailbox, | 825 const gpu::Mailbox& mailbox, |
| 856 uint32 sync_point, | 826 uint32 sync_point, |
| 857 const scoped_refptr<media::VideoFrame>& target, | 827 const scoped_refptr<media::VideoFrame>& target, |
| 858 const base::Callback<void(bool)>& callback) { | 828 const base::Callback<void(bool)>& callback) { |
| 859 WebGLId mailbox_texture = | 829 GLuint mailbox_texture = |
| 860 copy_impl_->ConsumeMailboxToTexture(mailbox, sync_point); | 830 copy_impl_->ConsumeMailboxToTexture(mailbox, sync_point); |
| 861 | 831 |
| 862 // Scale texture to right size. | 832 // Scale texture to right size. |
| 863 scaler_.Scale(mailbox_texture); | 833 scaler_.Scale(mailbox_texture); |
| 864 context_->deleteTexture(mailbox_texture); | 834 gl_->DeleteTextures(1, &mailbox_texture); |
| 865 | 835 |
| 866 // Convert the scaled texture in to Y, U and V planes. | 836 // Convert the scaled texture in to Y, U and V planes. |
| 867 y_.Scale(scaler_.texture()); | 837 y_.Scale(scaler_.texture()); |
| 868 u_.Scale(scaler_.texture()); | 838 u_.Scale(scaler_.texture()); |
| 869 v_.Scale(scaler_.texture()); | 839 v_.Scale(scaler_.texture()); |
| 870 | 840 |
| 871 if (target->coded_size() != dst_size_) { | 841 if (target->coded_size() != dst_size_) { |
| 872 DCHECK(target->coded_size() == dst_size_); | 842 DCHECK(target->coded_size() == dst_size_); |
| 873 LOG(ERROR) << "ReadbackYUV size error!"; | 843 LOG(ERROR) << "ReadbackYUV size error!"; |
| 874 callback.Run(false); | 844 callback.Run(false); |
| 875 return; | 845 return; |
| 876 } | 846 } |
| 877 | 847 |
| 878 // Read back planes, one at a time. Keep the video frame alive while doing the | 848 // Read back planes, one at a time. Keep the video frame alive while doing the |
| 879 // readback. | 849 // readback. |
| 880 copy_impl_->ReadbackPlane(y_.texture_and_framebuffer(), | 850 copy_impl_->ReadbackPlane(y_.texture_and_framebuffer(), |
| 881 target, | 851 target, |
| 882 media::VideoFrame::kYPlane, | 852 media::VideoFrame::kYPlane, |
| 883 0, | 853 0, |
| 884 dst_subrect_, | 854 dst_subrect_, |
| 885 base::Bind(&nullcallback)); | 855 base::Bind(&nullcallback)); |
| 886 copy_impl_->ReadbackPlane(u_.texture_and_framebuffer(), | 856 copy_impl_->ReadbackPlane(u_.texture_and_framebuffer(), |
| 887 target, | 857 target, |
| 888 media::VideoFrame::kUPlane, | 858 media::VideoFrame::kUPlane, |
| 889 1, | 859 1, |
| 890 dst_subrect_, | 860 dst_subrect_, |
| 891 base::Bind(&nullcallback)); | 861 base::Bind(&nullcallback)); |
| 892 copy_impl_->ReadbackPlane(v_.texture_and_framebuffer(), | 862 copy_impl_->ReadbackPlane( |
| 893 target, | 863 v_.texture_and_framebuffer(), |
| 894 media::VideoFrame::kVPlane, | 864 target, |
| 895 1, | 865 media::VideoFrame::kVPlane, |
| 896 dst_subrect_, | 866 1, |
| 897 base::Bind(&CallbackKeepingVideoFrameAlive, | 867 dst_subrect_, |
| 898 target, | 868 base::Bind(&CallbackKeepingVideoFrameAlive, target, callback)); |
| 899 callback)); | 869 gl_->BindFramebuffer(GL_FRAMEBUFFER, 0); |
| 900 context_->bindFramebuffer(GL_FRAMEBUFFER, 0); | |
| 901 media::LetterboxYUV(target, dst_subrect_); | 870 media::LetterboxYUV(target, dst_subrect_); |
| 902 } | 871 } |
| 903 | 872 |
| 904 // YUV readback constructors. Initiates the main scaler pipeline and | 873 // YUV readback constructors. Initiates the main scaler pipeline and |
| 905 // one planar scaler for each of the Y, U and V planes. | 874 // one planar scaler for each of the Y, U and V planes. |
| 906 GLHelper::CopyTextureToImpl::ReadbackYUV_MRT::ReadbackYUV_MRT( | 875 GLHelper::CopyTextureToImpl::ReadbackYUV_MRT::ReadbackYUV_MRT( |
| 907 WebGraphicsContext3D* context, | 876 GLES2Interface* gl, |
| 908 CopyTextureToImpl* copy_impl, | 877 CopyTextureToImpl* copy_impl, |
| 909 GLHelperScaling* scaler_impl, | 878 GLHelperScaling* scaler_impl, |
| 910 GLHelper::ScalerQuality quality, | 879 GLHelper::ScalerQuality quality, |
| 911 const gfx::Size& src_size, | 880 const gfx::Size& src_size, |
| 912 const gfx::Rect& src_subrect, | 881 const gfx::Rect& src_subrect, |
| 913 const gfx::Size& dst_size, | 882 const gfx::Size& dst_size, |
| 914 const gfx::Rect& dst_subrect, | 883 const gfx::Rect& dst_subrect, |
| 915 bool flip_vertically) | 884 bool flip_vertically) |
| 916 : context_(context), | 885 : gl_(gl), |
| 917 copy_impl_(copy_impl), | 886 copy_impl_(copy_impl), |
| 918 dst_size_(dst_size), | 887 dst_size_(dst_size), |
| 919 dst_subrect_(dst_subrect), | 888 dst_subrect_(dst_subrect), |
| 920 quality_(quality), | 889 quality_(quality), |
| 921 scaler_(context, scaler_impl->CreateScaler( | 890 scaler_(gl, |
| 922 quality, | 891 scaler_impl->CreateScaler(quality, |
| 923 src_size, | 892 src_size, |
| 924 src_subrect, | 893 src_subrect, |
| 925 dst_subrect.size(), | 894 dst_subrect.size(), |
| 926 false, | 895 false, |
| 927 false)), | 896 false)), |
| 928 pass1_shader_(scaler_impl->CreateYuvMrtShader( | 897 pass1_shader_(scaler_impl->CreateYuvMrtShader( |
| 929 dst_subrect.size(), | 898 dst_subrect.size(), |
| 930 gfx::Rect(0, 0, | 899 gfx::Rect(0, 0, (dst_subrect.width() + 3) & ~3, dst_subrect.height()), |
| 931 (dst_subrect.width() + 3) & ~3, | 900 gfx::Size((dst_subrect.width() + 3) / 4, dst_subrect.height()), |
| 932 dst_subrect.height()), | |
| 933 gfx::Size((dst_subrect.width() + 3) / 4, | |
| 934 dst_subrect.height()), | |
| 935 flip_vertically, | 901 flip_vertically, |
| 936 GLHelperScaling::SHADER_YUV_MRT_PASS1)), | 902 GLHelperScaling::SHADER_YUV_MRT_PASS1)), |
| 937 pass2_shader_(scaler_impl->CreateYuvMrtShader( | 903 pass2_shader_(scaler_impl->CreateYuvMrtShader( |
| 938 gfx::Size((dst_subrect.width() + 3) / 4, | 904 gfx::Size((dst_subrect.width() + 3) / 4, dst_subrect.height()), |
| 939 dst_subrect.height()), | 905 gfx::Rect(0, |
| 940 gfx::Rect(0, 0, | 906 0, |
| 941 (dst_subrect.width() + 7) / 8 * 2, | 907 (dst_subrect.width() + 7) / 8 * 2, |
| 942 dst_subrect.height()), | 908 dst_subrect.height()), |
| 943 gfx::Size((dst_subrect.width() + 7) / 8, | 909 gfx::Size((dst_subrect.width() + 7) / 8, |
| 944 (dst_subrect.height() + 1) / 2), | 910 (dst_subrect.height() + 1) / 2), |
| 945 false, | 911 false, |
| 946 GLHelperScaling::SHADER_YUV_MRT_PASS2)), | 912 GLHelperScaling::SHADER_YUV_MRT_PASS2)), |
| 947 y_(context, gfx::Size((dst_subrect.width() + 3) / 4, | 913 y_(gl, gfx::Size((dst_subrect.width() + 3) / 4, dst_subrect.height())), |
| 948 dst_subrect.height())), | 914 uv_(gl), |
| 949 uv_(context, context->createTexture()), | 915 u_(gl, |
| 950 u_(context, gfx::Size((dst_subrect.width() + 7) / 8, | 916 gfx::Size((dst_subrect.width() + 7) / 8, |
| 951 (dst_subrect.height() + 1) / 2)), | 917 (dst_subrect.height() + 1) / 2)), |
| 952 v_(context, gfx::Size((dst_subrect.width() + 7) / 8, | 918 v_(gl, |
| 953 (dst_subrect.height() + 1) / 2)) { | 919 gfx::Size((dst_subrect.width() + 7) / 8, |
| 920 (dst_subrect.height() + 1) / 2)) { |
| 954 | 921 |
| 955 content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context, uv_); | 922 content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl, uv_); |
| 956 context->texImage2D(GL_TEXTURE_2D, | 923 gl->TexImage2D(GL_TEXTURE_2D, |
| 957 0, | 924 0, |
| 958 GL_RGBA, | 925 GL_RGBA, |
| 959 (dst_subrect.width() + 3) / 4, | 926 (dst_subrect.width() + 3) / 4, |
| 960 dst_subrect.height(), | 927 dst_subrect.height(), |
| 961 0, | 928 0, |
| 962 GL_RGBA, | 929 GL_RGBA, |
| 963 GL_UNSIGNED_BYTE, | 930 GL_UNSIGNED_BYTE, |
| 964 NULL); | 931 NULL); |
| 965 | 932 |
| 966 DCHECK(!(dst_size.width() & 1)); | 933 DCHECK(!(dst_size.width() & 1)); |
| 967 DCHECK(!(dst_size.height() & 1)); | 934 DCHECK(!(dst_size.height() & 1)); |
| 968 DCHECK(!(dst_subrect.width() & 1)); | 935 DCHECK(!(dst_subrect.width() & 1)); |
| 969 DCHECK(!(dst_subrect.height() & 1)); | 936 DCHECK(!(dst_subrect.height() & 1)); |
| 970 DCHECK(!(dst_subrect.x() & 1)); | 937 DCHECK(!(dst_subrect.x() & 1)); |
| 971 DCHECK(!(dst_subrect.y() & 1)); | 938 DCHECK(!(dst_subrect.y() & 1)); |
| 972 } | 939 } |
| 973 | 940 |
| 974 void GLHelper::CopyTextureToImpl::ReadbackYUV_MRT::ReadbackYUV( | 941 void GLHelper::CopyTextureToImpl::ReadbackYUV_MRT::ReadbackYUV( |
| 975 const gpu::Mailbox& mailbox, | 942 const gpu::Mailbox& mailbox, |
| 976 uint32 sync_point, | 943 uint32 sync_point, |
| 977 const scoped_refptr<media::VideoFrame>& target, | 944 const scoped_refptr<media::VideoFrame>& target, |
| 978 const base::Callback<void(bool)>& callback) { | 945 const base::Callback<void(bool)>& callback) { |
| 979 WebGLId mailbox_texture = | 946 GLuint mailbox_texture = |
| 980 copy_impl_->ConsumeMailboxToTexture(mailbox, sync_point); | 947 copy_impl_->ConsumeMailboxToTexture(mailbox, sync_point); |
| 981 | 948 |
| 982 WebGLId texture; | 949 GLuint texture; |
| 983 if (quality_ == GLHelper::SCALER_QUALITY_FAST) { | 950 if (quality_ == GLHelper::SCALER_QUALITY_FAST) { |
| 984 // Optimization: SCALER_QUALITY_FAST is just a single bilinear | 951 // Optimization: SCALER_QUALITY_FAST is just a single bilinear |
| 985 // pass, which pass1_shader_ can do just as well, so let's skip | 952 // pass, which pass1_shader_ can do just as well, so let's skip |
| 986 // the actual scaling in that case. | 953 // the actual scaling in that case. |
| 987 texture = mailbox_texture; | 954 texture = mailbox_texture; |
| 988 } else { | 955 } else { |
| 989 // Scale texture to right size. | 956 // Scale texture to right size. |
| 990 scaler_.Scale(mailbox_texture); | 957 scaler_.Scale(mailbox_texture); |
| 991 texture = scaler_.texture(); | 958 texture = scaler_.texture(); |
| 992 } | 959 } |
| 993 | 960 |
| 994 | 961 std::vector<GLuint> outputs(2); |
| 995 std::vector<blink::WebGLId> outputs(2); | |
| 996 // Convert the scaled texture in to Y, U and V planes. | 962 // Convert the scaled texture in to Y, U and V planes. |
| 997 outputs[0] = y_.texture(); | 963 outputs[0] = y_.texture(); |
| 998 outputs[1] = uv_; | 964 outputs[1] = uv_; |
| 999 pass1_shader_->Execute(texture, outputs); | 965 pass1_shader_->Execute(texture, outputs); |
| 1000 | 966 |
| 1001 context_->deleteTexture(mailbox_texture); | 967 gl_->DeleteTextures(1, &mailbox_texture); |
| 1002 | 968 |
| 1003 outputs[0] = u_.texture(); | 969 outputs[0] = u_.texture(); |
| 1004 outputs[1] = v_.texture(); | 970 outputs[1] = v_.texture(); |
| 1005 pass2_shader_->Execute(uv_, outputs); | 971 pass2_shader_->Execute(uv_, outputs); |
| 1006 | 972 |
| 1007 if (target->coded_size() != dst_size_) { | 973 if (target->coded_size() != dst_size_) { |
| 1008 DCHECK(target->coded_size() == dst_size_); | 974 DCHECK(target->coded_size() == dst_size_); |
| 1009 LOG(ERROR) << "ReadbackYUV size error!"; | 975 LOG(ERROR) << "ReadbackYUV size error!"; |
| 1010 callback.Run(false); | 976 callback.Run(false); |
| 1011 return; | 977 return; |
| 1012 } | 978 } |
| 1013 | 979 |
| 1014 // Read back planes, one at a time. | 980 // Read back planes, one at a time. |
| 1015 copy_impl_->ReadbackPlane(&y_, | 981 copy_impl_->ReadbackPlane(&y_, |
| 1016 target, | 982 target, |
| 1017 media::VideoFrame::kYPlane, | 983 media::VideoFrame::kYPlane, |
| 1018 0, | 984 0, |
| 1019 dst_subrect_, | 985 dst_subrect_, |
| 1020 base::Bind(&nullcallback)); | 986 base::Bind(&nullcallback)); |
| 1021 copy_impl_->ReadbackPlane(&u_, | 987 copy_impl_->ReadbackPlane(&u_, |
| 1022 target, | 988 target, |
| 1023 media::VideoFrame::kUPlane, | 989 media::VideoFrame::kUPlane, |
| 1024 1, | 990 1, |
| 1025 dst_subrect_, | 991 dst_subrect_, |
| 1026 base::Bind(&nullcallback)); | 992 base::Bind(&nullcallback)); |
| 1027 copy_impl_->ReadbackPlane(&v_, | 993 copy_impl_->ReadbackPlane( |
| 1028 target, | 994 &v_, |
| 1029 media::VideoFrame::kVPlane, | 995 target, |
| 1030 1, | 996 media::VideoFrame::kVPlane, |
| 1031 dst_subrect_, | 997 1, |
| 1032 base::Bind(&CallbackKeepingVideoFrameAlive, | 998 dst_subrect_, |
| 1033 target, | 999 base::Bind(&CallbackKeepingVideoFrameAlive, target, callback)); |
| 1034 callback)); | 1000 gl_->BindFramebuffer(GL_FRAMEBUFFER, 0); |
| 1035 context_->bindFramebuffer(GL_FRAMEBUFFER, 0); | |
| 1036 media::LetterboxYUV(target, dst_subrect_); | 1001 media::LetterboxYUV(target, dst_subrect_); |
| 1037 } | 1002 } |
| 1038 | 1003 |
| 1039 ReadbackYUVInterface* | 1004 ReadbackYUVInterface* GLHelper::CopyTextureToImpl::CreateReadbackPipelineYUV( |
| 1040 GLHelper::CopyTextureToImpl::CreateReadbackPipelineYUV( | |
| 1041 GLHelper::ScalerQuality quality, | 1005 GLHelper::ScalerQuality quality, |
| 1042 const gfx::Size& src_size, | 1006 const gfx::Size& src_size, |
| 1043 const gfx::Rect& src_subrect, | 1007 const gfx::Rect& src_subrect, |
| 1044 const gfx::Size& dst_size, | 1008 const gfx::Size& dst_size, |
| 1045 const gfx::Rect& dst_subrect, | 1009 const gfx::Rect& dst_subrect, |
| 1046 bool flip_vertically, | 1010 bool flip_vertically, |
| 1047 bool use_mrt) { | 1011 bool use_mrt) { |
| 1048 helper_->InitScalerImpl(); | 1012 helper_->InitScalerImpl(); |
| 1049 if (max_draw_buffers_ >= 2 && use_mrt) { | 1013 if (max_draw_buffers_ >= 2 && use_mrt) { |
| 1050 return new ReadbackYUV_MRT( | 1014 return new ReadbackYUV_MRT(gl_, |
| 1051 context_, | 1015 this, |
| 1052 this, | 1016 helper_->scaler_impl_.get(), |
| 1053 helper_->scaler_impl_.get(), | 1017 quality, |
| 1054 quality, | 1018 src_size, |
| 1055 src_size, | 1019 src_subrect, |
| 1056 src_subrect, | 1020 dst_size, |
| 1057 dst_size, | 1021 dst_subrect, |
| 1058 dst_subrect, | 1022 flip_vertically); |
| 1059 flip_vertically); | |
| 1060 } | 1023 } |
| 1061 return new ReadbackYUVImpl( | 1024 return new ReadbackYUVImpl(gl_, |
| 1062 context_, | 1025 this, |
| 1063 this, | 1026 helper_->scaler_impl_.get(), |
| 1064 helper_->scaler_impl_.get(), | 1027 quality, |
| 1065 quality, | 1028 src_size, |
| 1066 src_size, | 1029 src_subrect, |
| 1067 src_subrect, | 1030 dst_size, |
| 1068 dst_size, | 1031 dst_subrect, |
| 1069 dst_subrect, | 1032 flip_vertically); |
| 1070 flip_vertically); | |
| 1071 } | 1033 } |
| 1072 | 1034 |
| 1073 ReadbackYUVInterface* | 1035 ReadbackYUVInterface* GLHelper::CreateReadbackPipelineYUV( |
| 1074 GLHelper::CreateReadbackPipelineYUV( | |
| 1075 ScalerQuality quality, | 1036 ScalerQuality quality, |
| 1076 const gfx::Size& src_size, | 1037 const gfx::Size& src_size, |
| 1077 const gfx::Rect& src_subrect, | 1038 const gfx::Rect& src_subrect, |
| 1078 const gfx::Size& dst_size, | 1039 const gfx::Size& dst_size, |
| 1079 const gfx::Rect& dst_subrect, | 1040 const gfx::Rect& dst_subrect, |
| 1080 bool flip_vertically, | 1041 bool flip_vertically, |
| 1081 bool use_mrt) { | 1042 bool use_mrt) { |
| 1082 InitCopyTextToImpl(); | 1043 InitCopyTextToImpl(); |
| 1083 return copy_texture_to_impl_->CreateReadbackPipelineYUV( | 1044 return copy_texture_to_impl_->CreateReadbackPipelineYUV(quality, |
| 1084 quality, | 1045 src_size, |
| 1085 src_size, | 1046 src_subrect, |
| 1086 src_subrect, | 1047 dst_size, |
| 1087 dst_size, | 1048 dst_subrect, |
| 1088 dst_subrect, | 1049 flip_vertically, |
| 1089 flip_vertically, | 1050 use_mrt); |
| 1090 use_mrt); | |
| 1091 } | 1051 } |
| 1092 | 1052 |
| 1093 } // namespace content | 1053 } // namespace content |
| OLD | NEW |