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 |