| 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_scaling.h" | 5 #include "content/common/gpu/client/gl_helper_scaling.h" |
| 6 | 6 |
| 7 #include <deque> | 7 #include <deque> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/debug/trace_event.h" | 12 #include "base/debug/trace_event.h" |
| 13 #include "base/lazy_instance.h" | 13 #include "base/lazy_instance.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/memory/ref_counted.h" | 15 #include "base/memory/ref_counted.h" |
| 16 #include "base/message_loop/message_loop.h" | 16 #include "base/message_loop/message_loop.h" |
| 17 #include "base/time/time.h" | 17 #include "base/time/time.h" |
| 18 #include "third_party/WebKit/public/platform/WebCString.h" | 18 #include "gpu/command_buffer/client/gles2_interface.h" |
| 19 #include "third_party/skia/include/core/SkRegion.h" | 19 #include "third_party/skia/include/core/SkRegion.h" |
| 20 #include "ui/gfx/rect.h" | 20 #include "ui/gfx/rect.h" |
| 21 #include "ui/gfx/size.h" | 21 #include "ui/gfx/size.h" |
| 22 #include "ui/gl/gl_bindings.h" | |
| 23 | 22 |
| 24 using blink::WebGLId; | 23 using gpu::gles2::GLES2Interface; |
| 25 using blink::WebGraphicsContext3D; | |
| 26 | 24 |
| 27 namespace content { | 25 namespace content { |
| 28 | 26 |
| 29 GLHelperScaling::GLHelperScaling(blink::WebGraphicsContext3D* context, | 27 GLHelperScaling::GLHelperScaling(GLES2Interface* gl, GLHelper* helper) |
| 30 GLHelper* helper) | 28 : gl_(gl), helper_(helper), vertex_attributes_buffer_(gl_) { |
| 31 : context_(context), | |
| 32 helper_(helper), | |
| 33 vertex_attributes_buffer_(context_, context_->createBuffer()) { | |
| 34 InitBuffer(); | 29 InitBuffer(); |
| 35 } | 30 } |
| 36 | 31 |
| 37 GLHelperScaling::~GLHelperScaling() { | 32 GLHelperScaling::~GLHelperScaling() {} |
| 38 } | |
| 39 | 33 |
| 40 // Used to keep track of a generated shader program. The program | 34 // Used to keep track of a generated shader program. The program |
| 41 // is passed in as text through Setup and is used by calling | 35 // is passed in as text through Setup and is used by calling |
| 42 // UseProgram() with the right parameters. Note that |context_| | 36 // UseProgram() with the right parameters. Note that |gl_| |
| 43 // and |helper_| are assumed to live longer than this program. | 37 // and |helper_| are assumed to live longer than this program. |
| 44 class ShaderProgram : public base::RefCounted<ShaderProgram> { | 38 class ShaderProgram : public base::RefCounted<ShaderProgram> { |
| 45 public: | 39 public: |
| 46 ShaderProgram(WebGraphicsContext3D* context, | 40 ShaderProgram(GLES2Interface* gl, GLHelper* helper) |
| 47 GLHelper* helper) | 41 : gl_(gl), |
| 48 : context_(context), | |
| 49 helper_(helper), | 42 helper_(helper), |
| 50 program_(context, context->createProgram()) { | 43 program_(gl_->CreateProgram()), |
| 51 } | 44 position_location_(-1), |
| 45 texcoord_location_(-1), |
| 46 src_subrect_location_(-1), |
| 47 src_pixelsize_location_(-1), |
| 48 dst_pixelsize_location_(-1), |
| 49 scaling_vector_location_(-1), |
| 50 color_weights_location_(-1) {} |
| 52 | 51 |
| 53 // Compile shader program, return true if successful. | 52 // Compile shader program. |
| 54 bool Setup(const blink::WGC3Dchar* vertex_shader_text, | 53 void Setup(const GLchar* vertex_shader_text, |
| 55 const blink::WGC3Dchar* fragment_shader_text); | 54 const GLchar* fragment_shader_text); |
| 56 | 55 |
| 57 // UseProgram must be called with GL_TEXTURE_2D bound to the | 56 // UseProgram must be called with GL_TEXTURE_2D bound to the |
| 58 // source texture and GL_ARRAY_BUFFER bound to a vertex | 57 // source texture and GL_ARRAY_BUFFER bound to a vertex |
| 59 // attribute buffer. | 58 // attribute buffer. |
| 60 void UseProgram(const gfx::Size& src_size, | 59 void UseProgram(const gfx::Size& src_size, |
| 61 const gfx::Rect& src_subrect, | 60 const gfx::Rect& src_subrect, |
| 62 const gfx::Size& dst_size, | 61 const gfx::Size& dst_size, |
| 63 bool scale_x, | 62 bool scale_x, |
| 64 bool flip_y, | 63 bool flip_y, |
| 65 GLfloat color_weights[4]); | 64 GLfloat color_weights[4]); |
| 66 | 65 |
| 66 bool Initialized() const { return position_location_ != -1; } |
| 67 |
| 67 private: | 68 private: |
| 68 friend class base::RefCounted<ShaderProgram>; | 69 friend class base::RefCounted<ShaderProgram>; |
| 69 ~ShaderProgram() {} | 70 ~ShaderProgram() { gl_->DeleteProgram(program_); } |
| 70 | 71 |
| 71 WebGraphicsContext3D* context_; | 72 GLES2Interface* gl_; |
| 72 GLHelper* helper_; | 73 GLHelper* helper_; |
| 73 | 74 |
| 74 // A program for copying a source texture into a destination texture. | 75 // A program for copying a source texture into a destination texture. |
| 75 ScopedProgram program_; | 76 GLuint program_; |
| 76 | 77 |
| 77 // The location of the position in the program. | 78 // The location of the position in the program. |
| 78 blink::WGC3Dint position_location_; | 79 GLint position_location_; |
| 79 // The location of the texture coordinate in the program. | 80 // The location of the texture coordinate in the program. |
| 80 blink::WGC3Dint texcoord_location_; | 81 GLint texcoord_location_; |
| 81 // The location of the source texture in the program. | 82 // The location of the source texture in the program. |
| 82 blink::WGC3Dint texture_location_; | 83 GLint texture_location_; |
| 83 // The location of the texture coordinate of | 84 // The location of the texture coordinate of |
| 84 // the sub-rectangle in the program. | 85 // the sub-rectangle in the program. |
| 85 blink::WGC3Dint src_subrect_location_; | 86 GLint src_subrect_location_; |
| 86 // Location of size of source image in pixels. | 87 // Location of size of source image in pixels. |
| 87 blink::WGC3Dint src_pixelsize_location_; | 88 GLint src_pixelsize_location_; |
| 88 // Location of size of destination image in pixels. | 89 // Location of size of destination image in pixels. |
| 89 blink::WGC3Dint dst_pixelsize_location_; | 90 GLint dst_pixelsize_location_; |
| 90 // Location of vector for scaling direction. | 91 // Location of vector for scaling direction. |
| 91 blink::WGC3Dint scaling_vector_location_; | 92 GLint scaling_vector_location_; |
| 92 // Location of color weights. | 93 // Location of color weights. |
| 93 blink::WGC3Dint color_weights_location_; | 94 GLint color_weights_location_; |
| 94 | 95 |
| 95 DISALLOW_COPY_AND_ASSIGN(ShaderProgram); | 96 DISALLOW_COPY_AND_ASSIGN(ShaderProgram); |
| 96 }; | 97 }; |
| 97 | 98 |
| 98 | |
| 99 // Implementation of a single stage in a scaler pipeline. If the pipeline has | 99 // Implementation of a single stage in a scaler pipeline. If the pipeline has |
| 100 // multiple stages, it calls Scale() on the subscaler, then further scales the | 100 // multiple stages, it calls Scale() on the subscaler, then further scales the |
| 101 // output. Caches textures and framebuffers to avoid allocating/deleting | 101 // output. Caches textures and framebuffers to avoid allocating/deleting |
| 102 // them once per frame, which can be expensive on some drivers. | 102 // them once per frame, which can be expensive on some drivers. |
| 103 class ScalerImpl : | 103 class ScalerImpl : public GLHelper::ScalerInterface, |
| 104 public GLHelper::ScalerInterface, | 104 public GLHelperScaling::ShaderInterface { |
| 105 public GLHelperScaling::ShaderInterface { | |
| 106 public: | 105 public: |
| 107 // |context| and |copy_impl| are expected to live longer than this object. | 106 // |gl| and |copy_impl| are expected to live longer than this object. |
| 108 // |src_size| is the size of the input texture in pixels. | 107 // |src_size| is the size of the input texture in pixels. |
| 109 // |dst_size| is the size of the output texutre in pixels. | 108 // |dst_size| is the size of the output texutre in pixels. |
| 110 // |src_subrect| is the portion of the src to copy to the output texture. | 109 // |src_subrect| is the portion of the src to copy to the output texture. |
| 111 // If |scale_x| is true, we are scaling along the X axis, otherwise Y. | 110 // If |scale_x| is true, we are scaling along the X axis, otherwise Y. |
| 112 // If we are scaling in both X and Y, |scale_x| is ignored. | 111 // If we are scaling in both X and Y, |scale_x| is ignored. |
| 113 // If |vertically_flip_texture| is true, output will be upside-down. | 112 // If |vertically_flip_texture| is true, output will be upside-down. |
| 114 // If |swizzle| is true, RGBA will be transformed into BGRA. | 113 // If |swizzle| is true, RGBA will be transformed into BGRA. |
| 115 // |color_weights| are only used together with SHADER_PLANAR to specify | 114 // |color_weights| are only used together with SHADER_PLANAR to specify |
| 116 // how to convert RGB colors into a single value. | 115 // how to convert RGB colors into a single value. |
| 117 ScalerImpl(WebGraphicsContext3D* context, | 116 ScalerImpl(GLES2Interface* gl, |
| 118 GLHelperScaling* scaler_helper, | 117 GLHelperScaling* scaler_helper, |
| 119 const GLHelperScaling::ScalerStage &scaler_stage, | 118 const GLHelperScaling::ScalerStage& scaler_stage, |
| 120 ScalerImpl* subscaler, | 119 ScalerImpl* subscaler, |
| 121 const float* color_weights) : | 120 const float* color_weights) |
| 122 context_(context), | 121 : gl_(gl), |
| 123 scaler_helper_(scaler_helper), | 122 scaler_helper_(scaler_helper), |
| 124 spec_(scaler_stage), | 123 spec_(scaler_stage), |
| 125 intermediate_texture_(0), | 124 intermediate_texture_(0), |
| 126 dst_framebuffer_(context, context_->createFramebuffer()), | 125 dst_framebuffer_(gl), |
| 127 subscaler_(subscaler) { | 126 subscaler_(subscaler) { |
| 128 if (color_weights) { | 127 if (color_weights) { |
| 129 color_weights_[0] = color_weights[0]; | 128 color_weights_[0] = color_weights[0]; |
| 130 color_weights_[1] = color_weights[1]; | 129 color_weights_[1] = color_weights[1]; |
| 131 color_weights_[2] = color_weights[2]; | 130 color_weights_[2] = color_weights[2]; |
| 132 color_weights_[3] = color_weights[3]; | 131 color_weights_[3] = color_weights[3]; |
| 133 } else { | 132 } else { |
| 134 color_weights_[0] = 0.0; | 133 color_weights_[0] = 0.0; |
| 135 color_weights_[1] = 0.0; | 134 color_weights_[1] = 0.0; |
| 136 color_weights_[2] = 0.0; | 135 color_weights_[2] = 0.0; |
| 137 color_weights_[3] = 0.0; | 136 color_weights_[3] = 0.0; |
| 138 } | 137 } |
| 139 shader_program_ = scaler_helper_->GetShaderProgram(spec_.shader, | 138 shader_program_ = |
| 140 spec_.swizzle); | 139 scaler_helper_->GetShaderProgram(spec_.shader, spec_.swizzle); |
| 141 | 140 |
| 142 if (subscaler_) { | 141 if (subscaler_) { |
| 143 intermediate_texture_ = context_->createTexture(); | 142 intermediate_texture_ = 0u; |
| 144 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder( | 143 gl_->GenTextures(1, &intermediate_texture_); |
| 145 context_, | 144 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, |
| 146 intermediate_texture_); | 145 intermediate_texture_); |
| 147 context_->texImage2D(GL_TEXTURE_2D, | 146 gl_->TexImage2D(GL_TEXTURE_2D, |
| 148 0, | 147 0, |
| 149 GL_RGBA, | 148 GL_RGBA, |
| 150 spec_.src_size.width(), | 149 spec_.src_size.width(), |
| 151 spec_.src_size.height(), | 150 spec_.src_size.height(), |
| 152 0, | 151 0, |
| 153 GL_RGBA, | 152 GL_RGBA, |
| 154 GL_UNSIGNED_BYTE, | 153 GL_UNSIGNED_BYTE, |
| 155 NULL); | 154 NULL); |
| 156 } | 155 } |
| 157 } | 156 } |
| 158 | 157 |
| 159 virtual ~ScalerImpl() { | 158 virtual ~ScalerImpl() { |
| 160 if (intermediate_texture_) { | 159 if (intermediate_texture_) { |
| 161 context_->deleteTexture(intermediate_texture_); | 160 gl_->DeleteTextures(1, &intermediate_texture_); |
| 162 } | 161 } |
| 163 } | 162 } |
| 164 | 163 |
| 165 // GLHelperShader::ShaderInterface implementation. | 164 // GLHelperShader::ShaderInterface implementation. |
| 166 virtual void Execute( | 165 virtual void Execute(GLuint source_texture, |
| 167 blink::WebGLId source_texture, | 166 const std::vector<GLuint>& dest_textures) OVERRIDE { |
| 168 const std::vector<blink::WebGLId>& dest_textures) OVERRIDE { | |
| 169 if (subscaler_) { | 167 if (subscaler_) { |
| 170 subscaler_->Scale(source_texture, intermediate_texture_); | 168 subscaler_->Scale(source_texture, intermediate_texture_); |
| 171 source_texture = intermediate_texture_; | 169 source_texture = intermediate_texture_; |
| 172 } | 170 } |
| 173 | 171 |
| 174 ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder( | 172 ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder( |
| 175 context_, | 173 gl_, dst_framebuffer_); |
| 176 dst_framebuffer_); | |
| 177 DCHECK_GT(dest_textures.size(), 0U); | 174 DCHECK_GT(dest_textures.size(), 0U); |
| 178 scoped_ptr<blink::WGC3Denum[]> buffers( | 175 scoped_ptr<GLenum[]> buffers(new GLenum[dest_textures.size()]); |
| 179 new blink::WGC3Denum[dest_textures.size()]); | |
| 180 for (size_t t = 0; t < dest_textures.size(); t++) { | 176 for (size_t t = 0; t < dest_textures.size(); t++) { |
| 181 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, | 177 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, dest_textures[t]); |
| 182 dest_textures[t]); | 178 gl_->FramebufferTexture2D(GL_FRAMEBUFFER, |
| 183 context_->framebufferTexture2D(GL_FRAMEBUFFER, | 179 GL_COLOR_ATTACHMENT0 + t, |
| 184 GL_COLOR_ATTACHMENT0 + t, | 180 GL_TEXTURE_2D, |
| 185 GL_TEXTURE_2D, | 181 dest_textures[t], |
| 186 dest_textures[t], | 182 0); |
| 187 0); | |
| 188 buffers[t] = GL_COLOR_ATTACHMENT0 + t; | 183 buffers[t] = GL_COLOR_ATTACHMENT0 + t; |
| 189 } | 184 } |
| 190 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, | 185 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, source_texture); |
| 191 source_texture); | |
| 192 | 186 |
| 193 context_->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, | 187 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
| 194 GL_LINEAR); | 188 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| 195 context_->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, | 189 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| 196 GL_LINEAR); | 190 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| 197 context_->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, | |
| 198 GL_CLAMP_TO_EDGE); | |
| 199 context_->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, | |
| 200 GL_CLAMP_TO_EDGE); | |
| 201 | 191 |
| 202 ScopedBufferBinder<GL_ARRAY_BUFFER> buffer_binder( | 192 ScopedBufferBinder<GL_ARRAY_BUFFER> buffer_binder( |
| 203 context_, | 193 gl_, scaler_helper_->vertex_attributes_buffer_); |
| 204 scaler_helper_->vertex_attributes_buffer_); | 194 DCHECK(shader_program_->Initialized()); |
| 205 shader_program_->UseProgram(spec_.src_size, | 195 shader_program_->UseProgram(spec_.src_size, |
| 206 spec_.src_subrect, | 196 spec_.src_subrect, |
| 207 spec_.dst_size, | 197 spec_.dst_size, |
| 208 spec_.scale_x, | 198 spec_.scale_x, |
| 209 spec_.vertically_flip_texture, | 199 spec_.vertically_flip_texture, |
| 210 color_weights_); | 200 color_weights_); |
| 211 context_->viewport(0, 0, spec_.dst_size.width(), spec_.dst_size.height()); | 201 gl_->Viewport(0, 0, spec_.dst_size.width(), spec_.dst_size.height()); |
| 212 | 202 |
| 213 if (dest_textures.size() > 1) { | 203 if (dest_textures.size() > 1) { |
| 214 DCHECK_LE(static_cast<int>(dest_textures.size()), | 204 DCHECK_LE(static_cast<int>(dest_textures.size()), |
| 215 scaler_helper_->helper_->MaxDrawBuffers()); | 205 scaler_helper_->helper_->MaxDrawBuffers()); |
| 216 context_->drawBuffersEXT(dest_textures.size(), buffers.get()); | 206 gl_->DrawBuffersEXT(dest_textures.size(), buffers.get()); |
| 217 } | 207 } |
| 218 // Conduct texture mapping by drawing a quad composed of two triangles. | 208 // Conduct texture mapping by drawing a quad composed of two triangles. |
| 219 context_->drawArrays(GL_TRIANGLE_STRIP, 0, 4); | 209 gl_->DrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| 220 if (dest_textures.size() > 1) { | 210 if (dest_textures.size() > 1) { |
| 221 // Set the draw buffers back to not confuse others. | 211 // Set the draw buffers back to not confuse others. |
| 222 context_->drawBuffersEXT(1, &buffers[0]); | 212 gl_->DrawBuffersEXT(1, &buffers[0]); |
| 223 } | 213 } |
| 224 } | 214 } |
| 225 | 215 |
| 226 // GLHelper::ScalerInterface implementation. | 216 // GLHelper::ScalerInterface implementation. |
| 227 virtual void Scale(blink::WebGLId source_texture, | 217 virtual void Scale(GLuint source_texture, GLuint dest_texture) OVERRIDE { |
| 228 blink::WebGLId dest_texture) OVERRIDE { | 218 std::vector<GLuint> tmp(1); |
| 229 std::vector<blink::WebGLId> tmp(1); | |
| 230 tmp[0] = dest_texture; | 219 tmp[0] = dest_texture; |
| 231 Execute(source_texture, tmp); | 220 Execute(source_texture, tmp); |
| 232 } | 221 } |
| 233 | 222 |
| 234 virtual const gfx::Size& SrcSize() OVERRIDE { | 223 virtual const gfx::Size& SrcSize() OVERRIDE { |
| 235 if (subscaler_) { | 224 if (subscaler_) { |
| 236 return subscaler_->SrcSize(); | 225 return subscaler_->SrcSize(); |
| 237 } | 226 } |
| 238 return spec_.src_size; | 227 return spec_.src_size; |
| 239 } | 228 } |
| 240 virtual const gfx::Rect& SrcSubrect() OVERRIDE { | 229 virtual const gfx::Rect& SrcSubrect() OVERRIDE { |
| 241 if (subscaler_) { | 230 if (subscaler_) { |
| 242 return subscaler_->SrcSubrect(); | 231 return subscaler_->SrcSubrect(); |
| 243 } | 232 } |
| 244 return spec_.src_subrect; | 233 return spec_.src_subrect; |
| 245 } | 234 } |
| 246 virtual const gfx::Size& DstSize() OVERRIDE { | 235 virtual const gfx::Size& DstSize() OVERRIDE { return spec_.dst_size; } |
| 247 return spec_.dst_size; | |
| 248 } | |
| 249 | 236 |
| 250 private: | 237 private: |
| 251 WebGraphicsContext3D* context_; | 238 GLES2Interface* gl_; |
| 252 GLHelperScaling* scaler_helper_; | 239 GLHelperScaling* scaler_helper_; |
| 253 GLHelperScaling::ScalerStage spec_; | 240 GLHelperScaling::ScalerStage spec_; |
| 254 GLfloat color_weights_[4]; | 241 GLfloat color_weights_[4]; |
| 255 blink::WebGLId intermediate_texture_; | 242 GLuint intermediate_texture_; |
| 256 scoped_refptr<ShaderProgram> shader_program_; | 243 scoped_refptr<ShaderProgram> shader_program_; |
| 257 ScopedFramebuffer dst_framebuffer_; | 244 ScopedFramebuffer dst_framebuffer_; |
| 258 scoped_ptr<ScalerImpl> subscaler_; | 245 scoped_ptr<ScalerImpl> subscaler_; |
| 259 }; | 246 }; |
| 260 | 247 |
| 261 GLHelperScaling::ScalerStage::ScalerStage( | 248 GLHelperScaling::ScalerStage::ScalerStage(ShaderType shader_, |
| 262 ShaderType shader_, | 249 gfx::Size src_size_, |
| 263 gfx::Size src_size_, | 250 gfx::Rect src_subrect_, |
| 264 gfx::Rect src_subrect_, | 251 gfx::Size dst_size_, |
| 265 gfx::Size dst_size_, | 252 bool scale_x_, |
| 266 bool scale_x_, | 253 bool vertically_flip_texture_, |
| 267 bool vertically_flip_texture_, | 254 bool swizzle_) |
| 268 bool swizzle_) | |
| 269 : shader(shader_), | 255 : shader(shader_), |
| 270 src_size(src_size_), | 256 src_size(src_size_), |
| 271 src_subrect(src_subrect_), | 257 src_subrect(src_subrect_), |
| 272 dst_size(dst_size_), | 258 dst_size(dst_size_), |
| 273 scale_x(scale_x_), | 259 scale_x(scale_x_), |
| 274 vertically_flip_texture(vertically_flip_texture_), | 260 vertically_flip_texture(vertically_flip_texture_), |
| 275 swizzle(swizzle_) { | 261 swizzle(swizzle_) {} |
| 276 } | |
| 277 | 262 |
| 278 // The important inputs for this function is |x_ops| and | 263 // The important inputs for this function is |x_ops| and |
| 279 // |y_ops|. They represent scaling operations to be done | 264 // |y_ops|. They represent scaling operations to be done |
| 280 // on an imag of size |src_size|. If |quality| is SCALER_QUALITY_BEST, | 265 // on an imag of size |src_size|. If |quality| is SCALER_QUALITY_BEST, |
| 281 // then we will interpret these scale operations literally and we'll | 266 // then we will interpret these scale operations literally and we'll |
| 282 // create one scaler stage for each ScaleOp. However, if |quality| | 267 // create one scaler stage for each ScaleOp. However, if |quality| |
| 283 // is SCALER_QUALITY_GOOD, then we can do a whole bunch of optimizations | 268 // is SCALER_QUALITY_GOOD, then we can do a whole bunch of optimizations |
| 284 // by combining two or more ScaleOps in to a single scaler stage. | 269 // by combining two or more ScaleOps in to a single scaler stage. |
| 285 // Normally we process ScaleOps from |y_ops| first and |x_ops| after | 270 // Normally we process ScaleOps from |y_ops| first and |x_ops| after |
| 286 // all |y_ops| are processed, but sometimes we can combine one or more | 271 // all |y_ops| are processed, but sometimes we can combine one or more |
| 287 // operation from both queues essentially for free. This is the reason | 272 // operation from both queues essentially for free. This is the reason |
| 288 // why |x_ops| and |y_ops| aren't just one single queue. | 273 // why |x_ops| and |y_ops| aren't just one single queue. |
| 289 void GLHelperScaling::ConvertScalerOpsToScalerStages( | 274 void GLHelperScaling::ConvertScalerOpsToScalerStages( |
| 290 GLHelper::ScalerQuality quality, | 275 GLHelper::ScalerQuality quality, |
| 291 gfx::Size src_size, | 276 gfx::Size src_size, |
| 292 gfx::Rect src_subrect, | 277 gfx::Rect src_subrect, |
| 293 const gfx::Size& dst_size, | 278 const gfx::Size& dst_size, |
| 294 bool vertically_flip_texture, | 279 bool vertically_flip_texture, |
| 295 bool swizzle, | 280 bool swizzle, |
| 296 std::deque<GLHelperScaling::ScaleOp>* x_ops, | 281 std::deque<GLHelperScaling::ScaleOp>* x_ops, |
| 297 std::deque<GLHelperScaling::ScaleOp>* y_ops, | 282 std::deque<GLHelperScaling::ScaleOp>* y_ops, |
| 298 std::vector<ScalerStage> *scaler_stages) { | 283 std::vector<ScalerStage>* scaler_stages) { |
| 299 while (!x_ops->empty() || !y_ops->empty()) { | 284 while (!x_ops->empty() || !y_ops->empty()) { |
| 300 gfx::Size intermediate_size = src_subrect.size(); | 285 gfx::Size intermediate_size = src_subrect.size(); |
| 301 std::deque<ScaleOp>* current_queue = NULL; | 286 std::deque<ScaleOp>* current_queue = NULL; |
| 302 | 287 |
| 303 if (!y_ops->empty()) { | 288 if (!y_ops->empty()) { |
| 304 current_queue = y_ops; | 289 current_queue = y_ops; |
| 305 } else { | 290 } else { |
| 306 current_queue = x_ops; | 291 current_queue = x_ops; |
| 307 } | 292 } |
| 308 | 293 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 // Check if we can combine some steps in the other dimension as well. | 332 // Check if we can combine some steps in the other dimension as well. |
| 348 // Since all shaders currently use GL_LINEAR, we can easily scale up | 333 // Since all shaders currently use GL_LINEAR, we can easily scale up |
| 349 // or scale down by exactly 2x at the same time as we do another | 334 // or scale down by exactly 2x at the same time as we do another |
| 350 // operation. Currently, the following mergers are supported: | 335 // operation. Currently, the following mergers are supported: |
| 351 // * 1 bilinear Y-pass with 1 bilinear X-pass (up or down) | 336 // * 1 bilinear Y-pass with 1 bilinear X-pass (up or down) |
| 352 // * 2 bilinear Y-passes with 2 bilinear X-passes | 337 // * 2 bilinear Y-passes with 2 bilinear X-passes |
| 353 // * 1 bilinear Y-pass with N bilinear X-pass | 338 // * 1 bilinear Y-pass with N bilinear X-pass |
| 354 // * N bilinear Y-passes with 1 bilinear X-pass (down only) | 339 // * N bilinear Y-passes with 1 bilinear X-pass (down only) |
| 355 // Measurements indicate that generalizing this for 3x3 and 4x4 | 340 // Measurements indicate that generalizing this for 3x3 and 4x4 |
| 356 // makes it slower on some platforms, such as the Pixel. | 341 // makes it slower on some platforms, such as the Pixel. |
| 357 if (!scale_x && x_ops->size() > 0 && | 342 if (!scale_x && x_ops->size() > 0 && x_ops->front().scale_factor <= 2) { |
| 358 x_ops->front().scale_factor <= 2) { | |
| 359 int x_passes = 0; | 343 int x_passes = 0; |
| 360 if (current_shader == SHADER_BILINEAR2 && x_ops->size() >= 2) { | 344 if (current_shader == SHADER_BILINEAR2 && x_ops->size() >= 2) { |
| 361 // 2y + 2x passes | 345 // 2y + 2x passes |
| 362 x_passes = 2; | 346 x_passes = 2; |
| 363 current_shader = SHADER_BILINEAR2X2; | 347 current_shader = SHADER_BILINEAR2X2; |
| 364 } else if (current_shader == SHADER_BILINEAR) { | 348 } else if (current_shader == SHADER_BILINEAR) { |
| 365 // 1y + Nx passes | 349 // 1y + Nx passes |
| 366 scale_x = true; | 350 scale_x = true; |
| 367 switch (x_ops->size()) { | 351 switch (x_ops->size()) { |
| 368 case 0: | 352 case 0: |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 408 } | 392 } |
| 409 } | 393 } |
| 410 | 394 |
| 411 void GLHelperScaling::ComputeScalerStages( | 395 void GLHelperScaling::ComputeScalerStages( |
| 412 GLHelper::ScalerQuality quality, | 396 GLHelper::ScalerQuality quality, |
| 413 const gfx::Size& src_size, | 397 const gfx::Size& src_size, |
| 414 const gfx::Rect& src_subrect, | 398 const gfx::Rect& src_subrect, |
| 415 const gfx::Size& dst_size, | 399 const gfx::Size& dst_size, |
| 416 bool vertically_flip_texture, | 400 bool vertically_flip_texture, |
| 417 bool swizzle, | 401 bool swizzle, |
| 418 std::vector<ScalerStage> *scaler_stages) { | 402 std::vector<ScalerStage>* scaler_stages) { |
| 419 if (quality == GLHelper::SCALER_QUALITY_FAST || | 403 if (quality == GLHelper::SCALER_QUALITY_FAST || |
| 420 src_subrect.size() == dst_size) { | 404 src_subrect.size() == dst_size) { |
| 421 scaler_stages->push_back(ScalerStage(SHADER_BILINEAR, | 405 scaler_stages->push_back(ScalerStage(SHADER_BILINEAR, |
| 422 src_size, | 406 src_size, |
| 423 src_subrect, | 407 src_subrect, |
| 424 dst_size, | 408 dst_size, |
| 425 false, | 409 false, |
| 426 vertically_flip_texture, | 410 vertically_flip_texture, |
| 427 swizzle)); | 411 swizzle)); |
| 428 return; | 412 return; |
| 429 } | 413 } |
| 430 | 414 |
| 431 std::deque<GLHelperScaling::ScaleOp> x_ops, y_ops; | 415 std::deque<GLHelperScaling::ScaleOp> x_ops, y_ops; |
| 432 GLHelperScaling::ScaleOp::AddOps(src_subrect.width(), | 416 GLHelperScaling::ScaleOp::AddOps(src_subrect.width(), |
| 433 dst_size.width(), | 417 dst_size.width(), |
| 434 true, | 418 true, |
| 435 quality == GLHelper::SCALER_QUALITY_GOOD, | 419 quality == GLHelper::SCALER_QUALITY_GOOD, |
| 436 &x_ops); | 420 &x_ops); |
| 437 GLHelperScaling::ScaleOp::AddOps(src_subrect.height(), | 421 GLHelperScaling::ScaleOp::AddOps(src_subrect.height(), |
| 438 dst_size.height(), | 422 dst_size.height(), |
| 439 false, | 423 false, |
| 440 quality == GLHelper::SCALER_QUALITY_GOOD, | 424 quality == GLHelper::SCALER_QUALITY_GOOD, |
| 441 &y_ops); | 425 &y_ops); |
| 442 | 426 |
| 443 ConvertScalerOpsToScalerStages( | 427 ConvertScalerOpsToScalerStages(quality, |
| 444 quality, | 428 src_size, |
| 445 src_size, | 429 src_subrect, |
| 446 src_subrect, | 430 dst_size, |
| 447 dst_size, | 431 vertically_flip_texture, |
| 448 vertically_flip_texture, | 432 swizzle, |
| 449 swizzle, | 433 &x_ops, |
| 450 &x_ops, | 434 &y_ops, |
| 451 &y_ops, | 435 scaler_stages); |
| 452 scaler_stages); | |
| 453 } | 436 } |
| 454 | 437 |
| 455 GLHelper::ScalerInterface* | 438 GLHelper::ScalerInterface* GLHelperScaling::CreateScaler( |
| 456 GLHelperScaling::CreateScaler(GLHelper::ScalerQuality quality, | 439 GLHelper::ScalerQuality quality, |
| 457 gfx::Size src_size, | 440 gfx::Size src_size, |
| 458 gfx::Rect src_subrect, | 441 gfx::Rect src_subrect, |
| 459 const gfx::Size& dst_size, | 442 const gfx::Size& dst_size, |
| 460 bool vertically_flip_texture, | 443 bool vertically_flip_texture, |
| 461 bool swizzle) { | 444 bool swizzle) { |
| 462 std::vector<ScalerStage> scaler_stages; | 445 std::vector<ScalerStage> scaler_stages; |
| 463 ComputeScalerStages(quality, | 446 ComputeScalerStages(quality, |
| 464 src_size, | 447 src_size, |
| 465 src_subrect, | 448 src_subrect, |
| 466 dst_size, | 449 dst_size, |
| 467 vertically_flip_texture, | 450 vertically_flip_texture, |
| 468 swizzle, | 451 swizzle, |
| 469 &scaler_stages); | 452 &scaler_stages); |
| 470 | 453 |
| 471 ScalerImpl* ret = NULL; | 454 ScalerImpl* ret = NULL; |
| 472 for (unsigned int i = 0; i < scaler_stages.size(); i++) { | 455 for (unsigned int i = 0; i < scaler_stages.size(); i++) { |
| 473 ret = new ScalerImpl(context_, this, scaler_stages[i], ret, NULL); | 456 ret = new ScalerImpl(gl_, this, scaler_stages[i], ret, NULL); |
| 474 } | 457 } |
| 475 return ret; | 458 return ret; |
| 476 } | 459 } |
| 477 | 460 |
| 478 GLHelper::ScalerInterface* | 461 GLHelper::ScalerInterface* GLHelperScaling::CreatePlanarScaler( |
| 479 GLHelperScaling::CreatePlanarScaler( | |
| 480 const gfx::Size& src_size, | 462 const gfx::Size& src_size, |
| 481 const gfx::Rect& src_subrect, | 463 const gfx::Rect& src_subrect, |
| 482 const gfx::Size& dst_size, | 464 const gfx::Size& dst_size, |
| 483 bool vertically_flip_texture, | 465 bool vertically_flip_texture, |
| 484 const float color_weights[4]) { | 466 const float color_weights[4]) { |
| 485 ScalerStage stage(SHADER_PLANAR, | 467 ScalerStage stage(SHADER_PLANAR, |
| 486 src_size, | 468 src_size, |
| 487 src_subrect, | 469 src_subrect, |
| 488 dst_size, | 470 dst_size, |
| 489 true, | 471 true, |
| 490 vertically_flip_texture, | 472 vertically_flip_texture, |
| 491 false); | 473 false); |
| 492 return new ScalerImpl(context_, this, stage, NULL, color_weights); | 474 return new ScalerImpl(gl_, this, stage, NULL, color_weights); |
| 493 } | 475 } |
| 494 | 476 |
| 495 GLHelperScaling::ShaderInterface* | 477 GLHelperScaling::ShaderInterface* GLHelperScaling::CreateYuvMrtShader( |
| 496 GLHelperScaling::CreateYuvMrtShader( | |
| 497 const gfx::Size& src_size, | 478 const gfx::Size& src_size, |
| 498 const gfx::Rect& src_subrect, | 479 const gfx::Rect& src_subrect, |
| 499 const gfx::Size& dst_size, | 480 const gfx::Size& dst_size, |
| 500 bool vertically_flip_texture, | 481 bool vertically_flip_texture, |
| 501 ShaderType shader) { | 482 ShaderType shader) { |
| 502 DCHECK(shader == SHADER_YUV_MRT_PASS1 || shader == SHADER_YUV_MRT_PASS2); | 483 DCHECK(shader == SHADER_YUV_MRT_PASS1 || shader == SHADER_YUV_MRT_PASS2); |
| 503 ScalerStage stage(shader, | 484 ScalerStage stage(shader, |
| 504 src_size, | 485 src_size, |
| 505 src_subrect, | 486 src_subrect, |
| 506 dst_size, | 487 dst_size, |
| 507 true, | 488 true, |
| 508 vertically_flip_texture, | 489 vertically_flip_texture, |
| 509 false); | 490 false); |
| 510 return new ScalerImpl(context_, this, stage, NULL, NULL); | 491 return new ScalerImpl(gl_, this, stage, NULL, NULL); |
| 511 } | 492 } |
| 512 | 493 |
| 513 const blink::WGC3Dfloat GLHelperScaling::kVertexAttributes[] = { | 494 const GLfloat GLHelperScaling::kVertexAttributes[] = { |
| 514 -1.0f, -1.0f, 0.0f, 0.0f, | 495 -1.0f, -1.0f, 0.0f, 0.0f, // vertex 0 |
| 515 1.0f, -1.0f, 1.0f, 0.0f, | 496 1.0f, -1.0f, 1.0f, 0.0f, // vertex 1 |
| 516 -1.0f, 1.0f, 0.0f, 1.0f, | 497 -1.0f, 1.0f, 0.0f, 1.0f, // vertex 2 |
| 517 1.0f, 1.0f, 1.0f, 1.0f, | 498 1.0f, 1.0f, 1.0f, 1.0f, }; // vertex 3 |
| 518 }; | |
| 519 | 499 |
| 520 void GLHelperScaling::InitBuffer() { | 500 void GLHelperScaling::InitBuffer() { |
| 521 ScopedBufferBinder<GL_ARRAY_BUFFER> buffer_binder( | 501 ScopedBufferBinder<GL_ARRAY_BUFFER> buffer_binder(gl_, |
| 522 context_, vertex_attributes_buffer_); | 502 vertex_attributes_buffer_); |
| 523 context_->bufferData(GL_ARRAY_BUFFER, | 503 gl_->BufferData(GL_ARRAY_BUFFER, |
| 524 sizeof(kVertexAttributes), | 504 sizeof(kVertexAttributes), |
| 525 kVertexAttributes, | 505 kVertexAttributes, |
| 526 GL_STATIC_DRAW); | 506 GL_STATIC_DRAW); |
| 527 } | 507 } |
| 528 | 508 |
| 529 scoped_refptr<ShaderProgram> | 509 scoped_refptr<ShaderProgram> GLHelperScaling::GetShaderProgram(ShaderType type, |
| 530 GLHelperScaling::GetShaderProgram(ShaderType type, | 510 bool swizzle) { |
| 531 bool swizzle) { | |
| 532 ShaderProgramKeyType key(type, swizzle); | 511 ShaderProgramKeyType key(type, swizzle); |
| 533 scoped_refptr<ShaderProgram>& cache_entry(shader_programs_[key]); | 512 scoped_refptr<ShaderProgram>& cache_entry(shader_programs_[key]); |
| 534 if (!cache_entry.get()) { | 513 if (!cache_entry.get()) { |
| 535 cache_entry = new ShaderProgram(context_, helper_); | 514 cache_entry = new ShaderProgram(gl_, helper_); |
| 536 std::basic_string<blink::WGC3Dchar> vertex_program; | 515 std::basic_string<GLchar> vertex_program; |
| 537 std::basic_string<blink::WGC3Dchar> fragment_program; | 516 std::basic_string<GLchar> fragment_program; |
| 538 std::basic_string<blink::WGC3Dchar> vertex_header; | 517 std::basic_string<GLchar> vertex_header; |
| 539 std::basic_string<blink::WGC3Dchar> fragment_directives; | 518 std::basic_string<GLchar> fragment_directives; |
| 540 std::basic_string<blink::WGC3Dchar> fragment_header; | 519 std::basic_string<GLchar> fragment_header; |
| 541 std::basic_string<blink::WGC3Dchar> shared_variables; | 520 std::basic_string<GLchar> shared_variables; |
| 542 | 521 |
| 543 vertex_header.append( | 522 vertex_header.append( |
| 544 "precision highp float;\n" | 523 "precision highp float;\n" |
| 545 "attribute vec2 a_position;\n" | 524 "attribute vec2 a_position;\n" |
| 546 "attribute vec2 a_texcoord;\n" | 525 "attribute vec2 a_texcoord;\n" |
| 547 "uniform vec4 src_subrect;\n"); | 526 "uniform vec4 src_subrect;\n"); |
| 548 | 527 |
| 549 fragment_header.append( | 528 fragment_header.append( |
| 550 "precision mediump float;\n" | 529 "precision mediump float;\n" |
| 551 "uniform sampler2D s_texture;\n"); | 530 "uniform sampler2D s_texture;\n"); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 599 " v_texcoords2 = texcoord - step;\n"); | 578 " v_texcoords2 = texcoord - step;\n"); |
| 600 fragment_program.append( | 579 fragment_program.append( |
| 601 " gl_FragColor = (texture2D(s_texture, v_texcoords1.xy) +\n" | 580 " gl_FragColor = (texture2D(s_texture, v_texcoords1.xy) +\n" |
| 602 " texture2D(s_texture, v_texcoords1.zw) +\n" | 581 " texture2D(s_texture, v_texcoords1.zw) +\n" |
| 603 " texture2D(s_texture, v_texcoords2)) / 3.0;\n"); | 582 " texture2D(s_texture, v_texcoords2)) / 3.0;\n"); |
| 604 break; | 583 break; |
| 605 | 584 |
| 606 case SHADER_BILINEAR4: | 585 case SHADER_BILINEAR4: |
| 607 // This is equivialent to three passes of the BILINEAR shader above, | 586 // This is equivialent to three passes of the BILINEAR shader above, |
| 608 // It can be used to scale an image down 2.0x-4.0x or exactly 8x. | 587 // It can be used to scale an image down 2.0x-4.0x or exactly 8x. |
| 609 shared_variables.append( | 588 shared_variables.append("varying vec4 v_texcoords[2];\n"); |
| 610 "varying vec4 v_texcoords[2];\n"); | |
| 611 vertex_header.append( | 589 vertex_header.append( |
| 612 "uniform vec2 scaling_vector;\n" | 590 "uniform vec2 scaling_vector;\n" |
| 613 "uniform vec2 dst_pixelsize;\n"); | 591 "uniform vec2 dst_pixelsize;\n"); |
| 614 vertex_program.append( | 592 vertex_program.append( |
| 615 " vec2 step = scaling_vector * src_subrect.zw / dst_pixelsize;\n" | 593 " vec2 step = scaling_vector * src_subrect.zw / dst_pixelsize;\n" |
| 616 " step /= 8.0;\n" | 594 " step /= 8.0;\n" |
| 617 " v_texcoords[0].xy = texcoord - step * 3.0;\n" | 595 " v_texcoords[0].xy = texcoord - step * 3.0;\n" |
| 618 " v_texcoords[0].zw = texcoord - step;\n" | 596 " v_texcoords[0].zw = texcoord - step;\n" |
| 619 " v_texcoords[1].xy = texcoord + step;\n" | 597 " v_texcoords[1].xy = texcoord + step;\n" |
| 620 " v_texcoords[1].zw = texcoord + step * 3.0;\n"); | 598 " v_texcoords[1].zw = texcoord + step * 3.0;\n"); |
| 621 fragment_program.append( | 599 fragment_program.append( |
| 622 " gl_FragColor = (\n" | 600 " gl_FragColor = (\n" |
| 623 " texture2D(s_texture, v_texcoords[0].xy) +\n" | 601 " texture2D(s_texture, v_texcoords[0].xy) +\n" |
| 624 " texture2D(s_texture, v_texcoords[0].zw) +\n" | 602 " texture2D(s_texture, v_texcoords[0].zw) +\n" |
| 625 " texture2D(s_texture, v_texcoords[1].xy) +\n" | 603 " texture2D(s_texture, v_texcoords[1].xy) +\n" |
| 626 " texture2D(s_texture, v_texcoords[1].zw)) / 4.0;\n"); | 604 " texture2D(s_texture, v_texcoords[1].zw)) / 4.0;\n"); |
| 627 break; | 605 break; |
| 628 | 606 |
| 629 case SHADER_BILINEAR2X2: | 607 case SHADER_BILINEAR2X2: |
| 630 // This is equivialent to four passes of the BILINEAR shader above. | 608 // This is equivialent to four passes of the BILINEAR shader above. |
| 631 // Two in each dimension. It can be used to scale an image down | 609 // Two in each dimension. It can be used to scale an image down |
| 632 // 1.0x-2.0x in both X and Y directions. Or, it could be used to | 610 // 1.0x-2.0x in both X and Y directions. Or, it could be used to |
| 633 // scale an image down by exactly 4x in both dimensions. | 611 // scale an image down by exactly 4x in both dimensions. |
| 634 shared_variables.append( | 612 shared_variables.append("varying vec4 v_texcoords[2];\n"); |
| 635 "varying vec4 v_texcoords[2];\n"); | 613 vertex_header.append("uniform vec2 dst_pixelsize;\n"); |
| 636 vertex_header.append( | |
| 637 "uniform vec2 dst_pixelsize;\n"); | |
| 638 vertex_program.append( | 614 vertex_program.append( |
| 639 " vec2 step = src_subrect.zw / 4.0 / dst_pixelsize;\n" | 615 " vec2 step = src_subrect.zw / 4.0 / dst_pixelsize;\n" |
| 640 " v_texcoords[0].xy = texcoord + vec2(step.x, step.y);\n" | 616 " v_texcoords[0].xy = texcoord + vec2(step.x, step.y);\n" |
| 641 " v_texcoords[0].zw = texcoord + vec2(step.x, -step.y);\n" | 617 " v_texcoords[0].zw = texcoord + vec2(step.x, -step.y);\n" |
| 642 " v_texcoords[1].xy = texcoord + vec2(-step.x, step.y);\n" | 618 " v_texcoords[1].xy = texcoord + vec2(-step.x, step.y);\n" |
| 643 " v_texcoords[1].zw = texcoord + vec2(-step.x, -step.y);\n"); | 619 " v_texcoords[1].zw = texcoord + vec2(-step.x, -step.y);\n"); |
| 644 fragment_program.append( | 620 fragment_program.append( |
| 645 " gl_FragColor = (\n" | 621 " gl_FragColor = (\n" |
| 646 " texture2D(s_texture, v_texcoords[0].xy) +\n" | 622 " texture2D(s_texture, v_texcoords[0].xy) +\n" |
| 647 " texture2D(s_texture, v_texcoords[0].zw) +\n" | 623 " texture2D(s_texture, v_texcoords[0].zw) +\n" |
| (...skipping 23 matching lines...) Expand all Loading... |
| 671 fragment_program.append( | 647 fragment_program.append( |
| 672 " gl_FragColor = \n" | 648 " gl_FragColor = \n" |
| 673 // Lobe pixels | 649 // Lobe pixels |
| 674 " (texture2D(s_texture, v_texcoords[0].xy) +\n" | 650 " (texture2D(s_texture, v_texcoords[0].xy) +\n" |
| 675 " texture2D(s_texture, v_texcoords[1].zw)) *\n" | 651 " texture2D(s_texture, v_texcoords[1].zw)) *\n" |
| 676 " LobeWeight +\n" | 652 " LobeWeight +\n" |
| 677 // Center pixels | 653 // Center pixels |
| 678 " (texture2D(s_texture, v_texcoords[0].zw) +\n" | 654 " (texture2D(s_texture, v_texcoords[0].zw) +\n" |
| 679 " texture2D(s_texture, v_texcoords[1].xy)) *\n" | 655 " texture2D(s_texture, v_texcoords[1].xy)) *\n" |
| 680 " CenterWeight;\n"); | 656 " CenterWeight;\n"); |
| 681 break; | 657 break; |
| 682 | 658 |
| 683 case SHADER_BICUBIC_UPSCALE: | 659 case SHADER_BICUBIC_UPSCALE: |
| 684 // When scaling up, we need 4 texture reads, but we can | 660 // When scaling up, we need 4 texture reads, but we can |
| 685 // save some instructions because will know in which range of | 661 // save some instructions because will know in which range of |
| 686 // the bicubic function each call call to the bicubic function | 662 // the bicubic function each call call to the bicubic function |
| 687 // will be in. | 663 // will be in. |
| 688 // Also, when sampling the bicubic function like this, the sum | 664 // Also, when sampling the bicubic function like this, the sum |
| 689 // is always exactly one, so we can skip normalization as well. | 665 // is always exactly one, so we can skip normalization as well. |
| 690 shared_variables.append( | 666 shared_variables.append("varying vec2 v_texcoord;\n"); |
| 691 "varying vec2 v_texcoord;\n"); | 667 vertex_program.append(" v_texcoord = texcoord;\n"); |
| 692 vertex_program.append( | |
| 693 " v_texcoord = texcoord;\n"); | |
| 694 fragment_header.append( | 668 fragment_header.append( |
| 695 "uniform vec2 src_pixelsize;\n" | 669 "uniform vec2 src_pixelsize;\n" |
| 696 "uniform vec2 scaling_vector;\n" | 670 "uniform vec2 scaling_vector;\n" |
| 697 "const float a = -0.5;\n" | 671 "const float a = -0.5;\n" |
| 698 // This function is equivialent to calling the bicubic | 672 // This function is equivialent to calling the bicubic |
| 699 // function with x-1, x, 1-x and 2-x | 673 // function with x-1, x, 1-x and 2-x |
| 700 // (assuming 0 <= x < 1) | 674 // (assuming 0 <= x < 1) |
| 701 "vec4 filt4(float x) {\n" | 675 "vec4 filt4(float x) {\n" |
| 702 " return vec4(x * x * x, x * x, x, 1) *\n" | 676 " return vec4(x * x * x, x * x, x, 1) *\n" |
| 703 " mat4( a, -2.0 * a, a, 0.0,\n" | 677 " mat4( a, -2.0 * a, a, 0.0,\n" |
| (...skipping 17 matching lines...) Expand all Loading... |
| 721 " gl_FragColor = pixels_x(base, step) * filt4(frac);\n"); | 695 " gl_FragColor = pixels_x(base, step) * filt4(frac);\n"); |
| 722 break; | 696 break; |
| 723 | 697 |
| 724 case SHADER_PLANAR: | 698 case SHADER_PLANAR: |
| 725 // Converts four RGBA pixels into one pixel. Each RGBA | 699 // Converts four RGBA pixels into one pixel. Each RGBA |
| 726 // pixel will be dot-multiplied with the color weights and | 700 // pixel will be dot-multiplied with the color weights and |
| 727 // then placed into a component of the output. This is used to | 701 // then placed into a component of the output. This is used to |
| 728 // convert RGBA textures into Y, U and V textures. We do this | 702 // convert RGBA textures into Y, U and V textures. We do this |
| 729 // because single-component textures are not renderable on all | 703 // because single-component textures are not renderable on all |
| 730 // architectures. | 704 // architectures. |
| 731 shared_variables.append( | 705 shared_variables.append("varying vec4 v_texcoords[2];\n"); |
| 732 "varying vec4 v_texcoords[2];\n"); | |
| 733 vertex_header.append( | 706 vertex_header.append( |
| 734 "uniform vec2 scaling_vector;\n" | 707 "uniform vec2 scaling_vector;\n" |
| 735 "uniform vec2 dst_pixelsize;\n"); | 708 "uniform vec2 dst_pixelsize;\n"); |
| 736 vertex_program.append( | 709 vertex_program.append( |
| 737 " vec2 step = scaling_vector * src_subrect.zw / dst_pixelsize;\n" | 710 " vec2 step = scaling_vector * src_subrect.zw / dst_pixelsize;\n" |
| 738 " step /= 4.0;\n" | 711 " step /= 4.0;\n" |
| 739 " v_texcoords[0].xy = texcoord - step * 1.5;\n" | 712 " v_texcoords[0].xy = texcoord - step * 1.5;\n" |
| 740 " v_texcoords[0].zw = texcoord - step * 0.5;\n" | 713 " v_texcoords[0].zw = texcoord - step * 0.5;\n" |
| 741 " v_texcoords[1].xy = texcoord + step * 0.5;\n" | 714 " v_texcoords[1].xy = texcoord + step * 0.5;\n" |
| 742 " v_texcoords[1].zw = texcoord + step * 1.5;\n"); | 715 " v_texcoords[1].zw = texcoord + step * 1.5;\n"); |
| 743 fragment_header.append( | 716 fragment_header.append("uniform vec4 color_weights;\n"); |
| 744 "uniform vec4 color_weights;\n"); | |
| 745 fragment_program.append( | 717 fragment_program.append( |
| 746 " gl_FragColor = color_weights * mat4(\n" | 718 " gl_FragColor = color_weights * mat4(\n" |
| 747 " vec4(texture2D(s_texture, v_texcoords[0].xy).rgb, 1.0),\n" | 719 " vec4(texture2D(s_texture, v_texcoords[0].xy).rgb, 1.0),\n" |
| 748 " vec4(texture2D(s_texture, v_texcoords[0].zw).rgb, 1.0),\n" | 720 " vec4(texture2D(s_texture, v_texcoords[0].zw).rgb, 1.0),\n" |
| 749 " vec4(texture2D(s_texture, v_texcoords[1].xy).rgb, 1.0),\n" | 721 " vec4(texture2D(s_texture, v_texcoords[1].xy).rgb, 1.0),\n" |
| 750 " vec4(texture2D(s_texture, v_texcoords[1].zw).rgb, 1.0));\n"); | 722 " vec4(texture2D(s_texture, v_texcoords[1].zw).rgb, 1.0));\n"); |
| 751 // Swizzle makes no sense for this shader. | 723 // Swizzle makes no sense for this shader. |
| 752 DCHECK(!swizzle); | 724 DCHECK(!swizzle); |
| 753 break; | 725 break; |
| 754 | 726 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 771 // YYYY YYYY UUVV UUVV | 743 // YYYY YYYY UUVV UUVV |
| 772 // First YYYY YYYY UUVV UUVV | 744 // First YYYY YYYY UUVV UUVV |
| 773 // pass YYYY YYYY UUVV UUVV | 745 // pass YYYY YYYY UUVV UUVV |
| 774 // YYYY YYYY UUVV UUVV | 746 // YYYY YYYY UUVV UUVV |
| 775 // | | 747 // | |
| 776 // | (u plane) (v plane) | 748 // | (u plane) (v plane) |
| 777 // Second | UUUU VVVV | 749 // Second | UUUU VVVV |
| 778 // pass +--> { UUUU + VVVV } | 750 // pass +--> { UUUU + VVVV } |
| 779 // UUUU VVVV | 751 // UUUU VVVV |
| 780 // | 752 // |
| 781 shared_variables.append( | 753 shared_variables.append("varying vec4 v_texcoords[2];\n"); |
| 782 "varying vec4 v_texcoords[2];\n"); | |
| 783 vertex_header.append( | 754 vertex_header.append( |
| 784 "uniform vec2 scaling_vector;\n" | 755 "uniform vec2 scaling_vector;\n" |
| 785 "uniform vec2 dst_pixelsize;\n"); | 756 "uniform vec2 dst_pixelsize;\n"); |
| 786 vertex_program.append( | 757 vertex_program.append( |
| 787 " vec2 step = scaling_vector * src_subrect.zw / dst_pixelsize;\n" | 758 " vec2 step = scaling_vector * src_subrect.zw / dst_pixelsize;\n" |
| 788 " step /= 4.0;\n" | 759 " step /= 4.0;\n" |
| 789 " v_texcoords[0].xy = texcoord - step * 1.5;\n" | 760 " v_texcoords[0].xy = texcoord - step * 1.5;\n" |
| 790 " v_texcoords[0].zw = texcoord - step * 0.5;\n" | 761 " v_texcoords[0].zw = texcoord - step * 0.5;\n" |
| 791 " v_texcoords[1].xy = texcoord + step * 0.5;\n" | 762 " v_texcoords[1].xy = texcoord + step * 0.5;\n" |
| 792 " v_texcoords[1].zw = texcoord + step * 1.5;\n"); | 763 " v_texcoords[1].zw = texcoord + step * 1.5;\n"); |
| 793 fragment_directives.append( | 764 fragment_directives.append("#extension GL_EXT_draw_buffers : enable\n"); |
| 794 "#extension GL_EXT_draw_buffers : enable\n"); | |
| 795 fragment_header.append( | 765 fragment_header.append( |
| 796 "const vec3 kRGBtoY = vec3(0.257, 0.504, 0.098);\n" | 766 "const vec3 kRGBtoY = vec3(0.257, 0.504, 0.098);\n" |
| 797 "const float kYBias = 0.0625;\n" | 767 "const float kYBias = 0.0625;\n" |
| 798 // Divide U and V by two to compensate for averaging below. | 768 // Divide U and V by two to compensate for averaging below. |
| 799 "const vec3 kRGBtoU = vec3(-0.148, -0.291, 0.439) / 2.0;\n" | 769 "const vec3 kRGBtoU = vec3(-0.148, -0.291, 0.439) / 2.0;\n" |
| 800 "const vec3 kRGBtoV = vec3(0.439, -0.368, -0.071) / 2.0;\n" | 770 "const vec3 kRGBtoV = vec3(0.439, -0.368, -0.071) / 2.0;\n" |
| 801 "const float kUVBias = 0.5;\n"); | 771 "const float kUVBias = 0.5;\n"); |
| 802 fragment_program.append( | 772 fragment_program.append( |
| 803 " vec3 pixel1 = texture2D(s_texture, v_texcoords[0].xy).rgb;\n" | 773 " vec3 pixel1 = texture2D(s_texture, v_texcoords[0].xy).rgb;\n" |
| 804 " vec3 pixel2 = texture2D(s_texture, v_texcoords[0].zw).rgb;\n" | 774 " vec3 pixel2 = texture2D(s_texture, v_texcoords[0].zw).rgb;\n" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 815 " dot(pixel12, kRGBtoV),\n" | 785 " dot(pixel12, kRGBtoV),\n" |
| 816 " dot(pixel34, kRGBtoV)) + kUVBias;\n"); | 786 " dot(pixel34, kRGBtoV)) + kUVBias;\n"); |
| 817 // Swizzle makes no sense for this shader. | 787 // Swizzle makes no sense for this shader. |
| 818 DCHECK(!swizzle); | 788 DCHECK(!swizzle); |
| 819 break; | 789 break; |
| 820 | 790 |
| 821 case SHADER_YUV_MRT_PASS2: | 791 case SHADER_YUV_MRT_PASS2: |
| 822 // We're just sampling two pixels and unswizzling them. There's | 792 // We're just sampling two pixels and unswizzling them. There's |
| 823 // no need to do vertical scaling with math, since bilinear | 793 // no need to do vertical scaling with math, since bilinear |
| 824 // interpolation in the sampler takes care of that. | 794 // interpolation in the sampler takes care of that. |
| 825 shared_variables.append( | 795 shared_variables.append("varying vec4 v_texcoords;\n"); |
| 826 "varying vec4 v_texcoords;\n"); | |
| 827 vertex_header.append( | 796 vertex_header.append( |
| 828 "uniform vec2 scaling_vector;\n" | 797 "uniform vec2 scaling_vector;\n" |
| 829 "uniform vec2 dst_pixelsize;\n"); | 798 "uniform vec2 dst_pixelsize;\n"); |
| 830 vertex_program.append( | 799 vertex_program.append( |
| 831 " vec2 step = scaling_vector * src_subrect.zw / dst_pixelsize;\n" | 800 " vec2 step = scaling_vector * src_subrect.zw / dst_pixelsize;\n" |
| 832 " step /= 2.0;\n" | 801 " step /= 2.0;\n" |
| 833 " v_texcoords.xy = texcoord - step * 0.5;\n" | 802 " v_texcoords.xy = texcoord - step * 0.5;\n" |
| 834 " v_texcoords.zw = texcoord + step * 0.5;\n"); | 803 " v_texcoords.zw = texcoord + step * 0.5;\n"); |
| 835 fragment_directives.append( | 804 fragment_directives.append("#extension GL_EXT_draw_buffers : enable\n"); |
| 836 "#extension GL_EXT_draw_buffers : enable\n"); | |
| 837 fragment_program.append( | 805 fragment_program.append( |
| 838 " vec4 lo_uuvv = texture2D(s_texture, v_texcoords.xy);\n" | 806 " vec4 lo_uuvv = texture2D(s_texture, v_texcoords.xy);\n" |
| 839 " vec4 hi_uuvv = texture2D(s_texture, v_texcoords.zw);\n" | 807 " vec4 hi_uuvv = texture2D(s_texture, v_texcoords.zw);\n" |
| 840 " gl_FragData[0] = vec4(lo_uuvv.rg, hi_uuvv.rg);\n" | 808 " gl_FragData[0] = vec4(lo_uuvv.rg, hi_uuvv.rg);\n" |
| 841 " gl_FragData[1] = vec4(lo_uuvv.ba, hi_uuvv.ba);\n"); | 809 " gl_FragData[1] = vec4(lo_uuvv.ba, hi_uuvv.ba);\n"); |
| 842 // Swizzle makes no sense for this shader. | 810 // Swizzle makes no sense for this shader. |
| 843 DCHECK(!swizzle); | 811 DCHECK(!swizzle); |
| 844 break; | 812 break; |
| 845 } | 813 } |
| 846 if (swizzle) { | 814 if (swizzle) { |
| 847 fragment_program.append(" gl_FragColor = gl_FragColor.bgra;\n"); | 815 fragment_program.append(" gl_FragColor = gl_FragColor.bgra;\n"); |
| 848 } | 816 } |
| 849 | 817 |
| 850 vertex_program = | 818 vertex_program = vertex_header + shared_variables + "void main() {\n" + |
| 851 vertex_header + | 819 vertex_program + "}\n"; |
| 852 shared_variables + | |
| 853 "void main() {\n" + | |
| 854 vertex_program + | |
| 855 "}\n"; | |
| 856 | 820 |
| 857 fragment_program = | 821 fragment_program = fragment_directives + fragment_header + |
| 858 fragment_directives + | 822 shared_variables + "void main() {\n" + fragment_program + |
| 859 fragment_header + | 823 "}\n"; |
| 860 shared_variables + | |
| 861 "void main() {\n" + | |
| 862 fragment_program + | |
| 863 "}\n"; | |
| 864 | 824 |
| 865 bool result = cache_entry->Setup(vertex_program.c_str(), | 825 cache_entry->Setup(vertex_program.c_str(), fragment_program.c_str()); |
| 866 fragment_program.c_str()); | |
| 867 DCHECK(result || context_->isContextLost()) | |
| 868 << "vertex_program =\n" << vertex_program | |
| 869 << "fragment_program =\n" << fragment_program; | |
| 870 } | 826 } |
| 871 return cache_entry; | 827 return cache_entry; |
| 872 } | 828 } |
| 873 | 829 |
| 874 bool ShaderProgram::Setup(const blink::WGC3Dchar* vertex_shader_text, | 830 void ShaderProgram::Setup(const GLchar* vertex_shader_text, |
| 875 const blink::WGC3Dchar* fragment_shader_text) { | 831 const GLchar* fragment_shader_text) { |
| 876 // Shaders to map the source texture to |dst_texture_|. | 832 // Shaders to map the source texture to |dst_texture_|. |
| 877 ScopedShader vertex_shader(context_, helper_->CompileShaderFromSource( | 833 GLuint vertex_shader = |
| 878 vertex_shader_text, GL_VERTEX_SHADER)); | 834 helper_->CompileShaderFromSource(vertex_shader_text, GL_VERTEX_SHADER); |
| 879 if (vertex_shader.id() == 0) { | 835 if (vertex_shader == 0) |
| 880 return false; | 836 return; |
| 881 } | |
| 882 context_->attachShader(program_, vertex_shader); | |
| 883 ScopedShader fragment_shader(context_, helper_->CompileShaderFromSource( | |
| 884 fragment_shader_text, GL_FRAGMENT_SHADER)); | |
| 885 if (fragment_shader.id() == 0) { | |
| 886 return false; | |
| 887 } | |
| 888 context_->attachShader(program_, fragment_shader); | |
| 889 context_->linkProgram(program_); | |
| 890 | 837 |
| 891 blink::WGC3Dint link_status = 0; | 838 gl_->AttachShader(program_, vertex_shader); |
| 892 context_->getProgramiv(program_, GL_LINK_STATUS, &link_status); | 839 gl_->DeleteShader(vertex_shader); |
| 893 if (!link_status) { | 840 |
| 894 LOG(ERROR) << std::string(context_->getProgramInfoLog(program_).utf8()); | 841 GLuint fragment_shader = helper_->CompileShaderFromSource( |
| 895 return false; | 842 fragment_shader_text, GL_FRAGMENT_SHADER); |
| 896 } | 843 if (fragment_shader == 0) |
| 897 position_location_ = context_->getAttribLocation(program_, "a_position"); | 844 return; |
| 898 texcoord_location_ = context_->getAttribLocation(program_, "a_texcoord"); | 845 gl_->AttachShader(program_, fragment_shader); |
| 899 texture_location_ = context_->getUniformLocation(program_, "s_texture"); | 846 gl_->DeleteShader(fragment_shader); |
| 900 src_subrect_location_ = context_->getUniformLocation(program_, "src_subrect"); | 847 |
| 901 src_pixelsize_location_ = context_->getUniformLocation(program_, | 848 gl_->LinkProgram(program_); |
| 902 "src_pixelsize"); | 849 |
| 903 dst_pixelsize_location_ = context_->getUniformLocation(program_, | 850 GLint link_status = 0; |
| 904 "dst_pixelsize"); | 851 gl_->GetProgramiv(program_, GL_LINK_STATUS, &link_status); |
| 905 scaling_vector_location_ = context_->getUniformLocation(program_, | 852 if (!link_status) |
| 906 "scaling_vector"); | 853 return; |
| 907 color_weights_location_ = context_->getUniformLocation(program_, | 854 |
| 908 "color_weights"); | 855 position_location_ = gl_->GetAttribLocation(program_, "a_position"); |
| 909 return true; | 856 texcoord_location_ = gl_->GetAttribLocation(program_, "a_texcoord"); |
| 857 texture_location_ = gl_->GetUniformLocation(program_, "s_texture"); |
| 858 src_subrect_location_ = gl_->GetUniformLocation(program_, "src_subrect"); |
| 859 src_pixelsize_location_ = gl_->GetUniformLocation(program_, "src_pixelsize"); |
| 860 dst_pixelsize_location_ = gl_->GetUniformLocation(program_, "dst_pixelsize"); |
| 861 scaling_vector_location_ = |
| 862 gl_->GetUniformLocation(program_, "scaling_vector"); |
| 863 color_weights_location_ = gl_->GetUniformLocation(program_, "color_weights"); |
| 864 return; |
| 910 } | 865 } |
| 911 | 866 |
| 912 void ShaderProgram::UseProgram( | 867 void ShaderProgram::UseProgram(const gfx::Size& src_size, |
| 913 const gfx::Size& src_size, | 868 const gfx::Rect& src_subrect, |
| 914 const gfx::Rect& src_subrect, | 869 const gfx::Size& dst_size, |
| 915 const gfx::Size& dst_size, | 870 bool scale_x, |
| 916 bool scale_x, | 871 bool flip_y, |
| 917 bool flip_y, | 872 GLfloat color_weights[4]) { |
| 918 GLfloat color_weights[4]) { | 873 gl_->UseProgram(program_); |
| 919 context_->useProgram(program_); | |
| 920 | 874 |
| 921 blink::WGC3Dintptr offset = 0; | 875 // OpenGL defines the last parameter to VertexAttribPointer as type |
| 922 context_->vertexAttribPointer(position_location_, | 876 // "const GLvoid*" even though it is actually an offset into the buffer |
| 923 2, | 877 // object's data store and not a pointer to the client's address space. |
| 924 GL_FLOAT, | 878 const void* offsets[2] = { |
| 925 GL_FALSE, | 879 0, reinterpret_cast<const void*>(2 * sizeof(GLfloat)) |
| 926 4 * sizeof(blink::WGC3Dfloat), | 880 }; |
| 927 offset); | |
| 928 context_->enableVertexAttribArray(position_location_); | |
| 929 | 881 |
| 930 offset += 2 * sizeof(blink::WGC3Dfloat); | 882 gl_->VertexAttribPointer(position_location_, |
| 931 context_->vertexAttribPointer(texcoord_location_, | 883 2, |
| 932 2, | 884 GL_FLOAT, |
| 933 GL_FLOAT, | 885 GL_FALSE, |
| 934 GL_FALSE, | 886 4 * sizeof(GLfloat), |
| 935 4 * sizeof(blink::WGC3Dfloat), | 887 offsets[0]); |
| 936 offset); | 888 gl_->EnableVertexAttribArray(position_location_); |
| 937 context_->enableVertexAttribArray(texcoord_location_); | |
| 938 | 889 |
| 939 context_->uniform1i(texture_location_, 0); | 890 gl_->VertexAttribPointer(texcoord_location_, |
| 891 2, |
| 892 GL_FLOAT, |
| 893 GL_FALSE, |
| 894 4 * sizeof(GLfloat), |
| 895 offsets[1]); |
| 896 gl_->EnableVertexAttribArray(texcoord_location_); |
| 897 |
| 898 gl_->Uniform1i(texture_location_, 0); |
| 940 | 899 |
| 941 // Convert |src_subrect| to texture coordinates. | 900 // Convert |src_subrect| to texture coordinates. |
| 942 GLfloat src_subrect_texcoord[] = { | 901 GLfloat src_subrect_texcoord[] = { |
| 943 static_cast<float>(src_subrect.x()) / src_size.width(), | 902 static_cast<float>(src_subrect.x()) / src_size.width(), |
| 944 static_cast<float>(src_subrect.y()) / src_size.height(), | 903 static_cast<float>(src_subrect.y()) / src_size.height(), |
| 945 static_cast<float>(src_subrect.width()) / src_size.width(), | 904 static_cast<float>(src_subrect.width()) / src_size.width(), |
| 946 static_cast<float>(src_subrect.height()) / src_size.height(), | 905 static_cast<float>(src_subrect.height()) / src_size.height(), }; |
| 947 }; | |
| 948 if (flip_y) { | 906 if (flip_y) { |
| 949 src_subrect_texcoord[1] += src_subrect_texcoord[3]; | 907 src_subrect_texcoord[1] += src_subrect_texcoord[3]; |
| 950 src_subrect_texcoord[3] *= -1.0; | 908 src_subrect_texcoord[3] *= -1.0; |
| 951 } | 909 } |
| 952 context_->uniform4fv(src_subrect_location_, 1, src_subrect_texcoord); | 910 gl_->Uniform4fv(src_subrect_location_, 1, src_subrect_texcoord); |
| 953 | 911 |
| 954 context_->uniform2f(src_pixelsize_location_, | 912 gl_->Uniform2f(src_pixelsize_location_, src_size.width(), src_size.height()); |
| 955 src_size.width(), | 913 gl_->Uniform2f(dst_pixelsize_location_, |
| 956 src_size.height()); | 914 static_cast<float>(dst_size.width()), |
| 957 context_->uniform2f(dst_pixelsize_location_, | 915 static_cast<float>(dst_size.height())); |
| 958 static_cast<float>(dst_size.width()), | |
| 959 static_cast<float>(dst_size.height())); | |
| 960 | 916 |
| 961 context_->uniform2f(scaling_vector_location_, | 917 gl_->Uniform2f( |
| 962 scale_x ? 1.0 : 0.0, | 918 scaling_vector_location_, scale_x ? 1.0 : 0.0, scale_x ? 0.0 : 1.0); |
| 963 scale_x ? 0.0 : 1.0); | 919 gl_->Uniform4fv(color_weights_location_, 1, color_weights); |
| 964 context_->uniform4fv(color_weights_location_, 1, color_weights); | |
| 965 } | 920 } |
| 966 | 921 |
| 967 } // namespace content | 922 } // namespace content |
| OLD | NEW |