OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/common/gpu/client/gl_helper.h" | 5 #include "content/common/gpu/client/gl_helper.h" |
6 | 6 |
7 #include <queue> | 7 #include <queue> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/debug/trace_event.h" | |
10 #include "base/lazy_instance.h" | 11 #include "base/lazy_instance.h" |
11 #include "base/logging.h" | 12 #include "base/logging.h" |
12 #include "base/memory/ref_counted.h" | 13 #include "base/memory/ref_counted.h" |
13 #include "base/message_loop.h" | 14 #include "base/message_loop.h" |
14 #include "base/synchronization/lock.h" | 15 #include "base/synchronization/lock.h" |
15 #include "base/synchronization/waitable_event.h" | 16 #include "base/synchronization/waitable_event.h" |
apatrick_chromium
2013/03/20 18:39:09
I think some of these includes are not needed now,
hubbe
2013/03/20 22:03:48
Done
(Is there something like iwyu for chrome sour
| |
16 #include "base/threading/thread.h" | 17 #include "base/threading/thread.h" |
17 #include "base/threading/thread_restrictions.h" | 18 #include "base/threading/thread_restrictions.h" |
19 #include "base/time.h" | |
18 #include "third_party/WebKit/Source/Platform/chromium/public/WebCString.h" | 20 #include "third_party/WebKit/Source/Platform/chromium/public/WebCString.h" |
19 #include "third_party/WebKit/Source/Platform/chromium/public/WebString.h" | 21 #include "third_party/WebKit/Source/Platform/chromium/public/WebString.h" |
20 #include "third_party/skia/include/core/SkRegion.h" | 22 #include "third_party/skia/include/core/SkRegion.h" |
21 #include "ui/gfx/rect.h" | 23 #include "ui/gfx/rect.h" |
22 #include "ui/gfx/size.h" | 24 #include "ui/gfx/size.h" |
23 #include "ui/gl/gl_bindings.h" | 25 #include "ui/gl/gl_bindings.h" |
24 | 26 |
25 using WebKit::WebGLId; | 27 using WebKit::WebGLId; |
26 using WebKit::WebGraphicsContext3D; | 28 using WebKit::WebGraphicsContext3D; |
27 | 29 |
28 namespace { | 30 namespace { |
29 | 31 |
30 const char kGLHelperThreadName[] = "GLHelperThread"; | |
31 | |
32 class GLHelperThread : public base::Thread { | |
33 public: | |
34 GLHelperThread() : base::Thread(kGLHelperThreadName) { | |
35 Start(); | |
36 } | |
37 virtual ~GLHelperThread() { | |
38 Stop(); | |
39 } | |
40 | |
41 private: | |
42 DISALLOW_COPY_AND_ASSIGN(GLHelperThread); | |
43 }; | |
44 | |
45 base::LazyInstance<GLHelperThread> g_gl_helper_thread = | |
46 LAZY_INSTANCE_INITIALIZER; | |
47 | |
48 class ScopedWebGLId { | 32 class ScopedWebGLId { |
49 public: | 33 public: |
50 typedef void (WebGraphicsContext3D::*DeleteFunc)(WebGLId); | 34 typedef void (WebGraphicsContext3D::*DeleteFunc)(WebGLId); |
51 ScopedWebGLId(WebGraphicsContext3D* context, | 35 ScopedWebGLId(WebGraphicsContext3D* context, |
52 WebGLId id, | 36 WebGLId id, |
53 DeleteFunc delete_func) | 37 DeleteFunc delete_func) |
54 : context_(context), | 38 : context_(context), |
55 id_(id), | 39 id_(id), |
56 delete_func_(delete_func) { | 40 delete_func_(delete_func) { |
57 } | 41 } |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
92 | 76 |
93 class ScopedFramebuffer : public ScopedWebGLId { | 77 class ScopedFramebuffer : public ScopedWebGLId { |
94 public: | 78 public: |
95 ScopedFramebuffer(WebGraphicsContext3D* context, | 79 ScopedFramebuffer(WebGraphicsContext3D* context, |
96 WebGLId id) | 80 WebGLId id) |
97 : ScopedWebGLId(context, | 81 : ScopedWebGLId(context, |
98 id, | 82 id, |
99 &WebGraphicsContext3D::deleteFramebuffer) {} | 83 &WebGraphicsContext3D::deleteFramebuffer) {} |
100 }; | 84 }; |
101 | 85 |
102 class ScopedRenderbuffer : public ScopedWebGLId { | |
103 public: | |
104 ScopedRenderbuffer(WebGraphicsContext3D* context, | |
105 WebGLId id) | |
106 : ScopedWebGLId(context, | |
107 id, | |
108 &WebGraphicsContext3D::deleteRenderbuffer) {} | |
109 }; | |
110 | |
111 class ScopedProgram : public ScopedWebGLId { | 86 class ScopedProgram : public ScopedWebGLId { |
112 public: | 87 public: |
113 ScopedProgram(WebGraphicsContext3D* context, | 88 ScopedProgram(WebGraphicsContext3D* context, |
114 WebGLId id) | 89 WebGLId id) |
115 : ScopedWebGLId(context, | 90 : ScopedWebGLId(context, |
116 id, | 91 id, |
117 &WebGraphicsContext3D::deleteProgram) {} | 92 &WebGraphicsContext3D::deleteProgram) {} |
118 }; | 93 }; |
119 | 94 |
120 class ScopedShader : public ScopedWebGLId { | 95 class ScopedShader : public ScopedWebGLId { |
(...skipping 16 matching lines...) Expand all Loading... | |
137 | 112 |
138 template <WebKit::WGC3Denum target> | 113 template <WebKit::WGC3Denum target> |
139 class ScopedBinder { | 114 class ScopedBinder { |
140 public: | 115 public: |
141 typedef void (WebGraphicsContext3D::*BindFunc)(WebKit::WGC3Denum, | 116 typedef void (WebGraphicsContext3D::*BindFunc)(WebKit::WGC3Denum, |
142 WebGLId); | 117 WebGLId); |
143 ScopedBinder(WebGraphicsContext3D* context, | 118 ScopedBinder(WebGraphicsContext3D* context, |
144 WebGLId id, | 119 WebGLId id, |
145 BindFunc bind_func) | 120 BindFunc bind_func) |
146 : context_(context), | 121 : context_(context), |
147 id_(id), | |
148 bind_func_(bind_func) { | 122 bind_func_(bind_func) { |
149 (context_->*bind_func_)(target, id_); | 123 (context_->*bind_func_)(target, id); |
150 } | 124 } |
151 | 125 |
152 virtual ~ScopedBinder() { | 126 virtual ~ScopedBinder() { |
153 if (id_ != 0) | 127 (context_->*bind_func_)(target, 0); |
154 (context_->*bind_func_)(target, 0); | |
155 } | 128 } |
156 | 129 |
157 private: | 130 private: |
158 WebGraphicsContext3D* context_; | 131 WebGraphicsContext3D* context_; |
159 WebGLId id_; | |
160 BindFunc bind_func_; | 132 BindFunc bind_func_; |
161 | 133 |
162 DISALLOW_COPY_AND_ASSIGN(ScopedBinder); | 134 DISALLOW_COPY_AND_ASSIGN(ScopedBinder); |
163 }; | 135 }; |
164 | 136 |
165 template <WebKit::WGC3Denum target> | 137 template <WebKit::WGC3Denum target> |
166 class ScopedBufferBinder : ScopedBinder<target> { | 138 class ScopedBufferBinder : ScopedBinder<target> { |
167 public: | 139 public: |
168 ScopedBufferBinder(WebGraphicsContext3D* context, | 140 ScopedBufferBinder(WebGraphicsContext3D* context, |
169 WebGLId id) | 141 WebGLId id) |
170 : ScopedBinder<target>( | 142 : ScopedBinder<target>( |
171 context, | 143 context, |
172 id, | 144 id, |
173 &WebGraphicsContext3D::bindBuffer) {} | 145 &WebGraphicsContext3D::bindBuffer) {} |
174 }; | 146 }; |
175 | 147 |
176 template <WebKit::WGC3Denum target> | 148 template <WebKit::WGC3Denum target> |
177 class ScopedFramebufferBinder : ScopedBinder<target> { | 149 class ScopedFramebufferBinder : ScopedBinder<target> { |
178 public: | 150 public: |
179 ScopedFramebufferBinder(WebGraphicsContext3D* context, | 151 ScopedFramebufferBinder(WebGraphicsContext3D* context, |
180 WebGLId id) | 152 WebGLId id) |
181 : ScopedBinder<target>( | 153 : ScopedBinder<target>( |
182 context, | 154 context, |
183 id, | 155 id, |
184 &WebGraphicsContext3D::bindFramebuffer) {} | 156 &WebGraphicsContext3D::bindFramebuffer) {} |
185 }; | 157 }; |
186 | 158 |
187 template <WebKit::WGC3Denum target> | 159 template <WebKit::WGC3Denum target> |
188 class ScopedRenderbufferBinder : ScopedBinder<target> { | |
189 public: | |
190 ScopedRenderbufferBinder(WebGraphicsContext3D* context, | |
191 WebGLId id) | |
192 : ScopedBinder<target>( | |
193 context, | |
194 id, | |
195 &WebGraphicsContext3D::bindRenderbuffer) {} | |
196 }; | |
197 | |
198 template <WebKit::WGC3Denum target> | |
199 class ScopedTextureBinder : ScopedBinder<target> { | 160 class ScopedTextureBinder : ScopedBinder<target> { |
200 public: | 161 public: |
201 ScopedTextureBinder(WebGraphicsContext3D* context, | 162 ScopedTextureBinder(WebGraphicsContext3D* context, |
202 WebGLId id) | 163 WebGLId id) |
203 : ScopedBinder<target>( | 164 : ScopedBinder<target>( |
204 context, | 165 context, |
205 id, | 166 id, |
206 &WebGraphicsContext3D::bindTexture) {} | 167 &WebGraphicsContext3D::bindTexture) {} |
207 }; | 168 }; |
208 | 169 |
(...skipping 20 matching lines...) Expand all Loading... | |
229 void SignalWaitableEvent(base::WaitableEvent* event) { | 190 void SignalWaitableEvent(base::WaitableEvent* event) { |
230 event->Signal(); | 191 event->Signal(); |
231 } | 192 } |
232 | 193 |
233 } // namespace | 194 } // namespace |
234 | 195 |
235 namespace content { | 196 namespace content { |
236 | 197 |
237 // Implements GLHelper::CropScaleReadbackAndCleanTexture and encapsulates the | 198 // Implements GLHelper::CropScaleReadbackAndCleanTexture and encapsulates the |
238 // data needed for it. | 199 // data needed for it. |
239 class GLHelper::CopyTextureToImpl { | 200 class GLHelper::CopyTextureToImpl : |
201 public base::SupportsWeakPtr<GLHelper::CopyTextureToImpl> { | |
240 public: | 202 public: |
241 CopyTextureToImpl(WebGraphicsContext3D* context, | 203 CopyTextureToImpl(WebGraphicsContext3D* context, |
242 WebGraphicsContext3D* context_for_thread, | |
243 GLHelper* helper) | 204 GLHelper* helper) |
244 : context_(context), | 205 : context_(context), |
245 context_for_thread_(context_for_thread), | |
246 helper_(helper), | 206 helper_(helper), |
247 flush_(context), | 207 flush_(context), |
248 program_(context, context->createProgram()), | 208 program_(context, context->createProgram()), |
249 vertex_attributes_buffer_(context_, context_->createBuffer()), | 209 vertex_attributes_buffer_(context_, context_->createBuffer()), |
250 flipped_vertex_attributes_buffer_(context_, context_->createBuffer()) { | 210 flipped_vertex_attributes_buffer_(context_, context_->createBuffer()) { |
251 InitBuffer(); | 211 InitBuffer(); |
252 InitProgram(); | 212 InitProgram(); |
253 } | 213 } |
254 ~CopyTextureToImpl() { | 214 ~CopyTextureToImpl() { |
255 CancelRequests(); | 215 CancelRequests(); |
256 DeleteContextForThread(); | |
257 } | 216 } |
258 | 217 |
259 void InitBuffer(); | 218 void InitBuffer(); |
260 void InitProgram(); | 219 void InitProgram(); |
261 | 220 |
262 void CropScaleReadbackAndCleanTexture( | 221 void CropScaleReadbackAndCleanTexture( |
263 WebGLId src_texture, | 222 WebGLId src_texture, |
264 const gfx::Size& src_size, | 223 const gfx::Size& src_size, |
265 const gfx::Rect& src_subrect, | 224 const gfx::Rect& src_subrect, |
266 const gfx::Size& dst_size, | 225 const gfx::Size& dst_size, |
267 unsigned char* out, | 226 unsigned char* out, |
268 const base::Callback<void(bool)>& callback); | 227 const base::Callback<void(bool)>& callback); |
269 | 228 |
270 void ReadbackTextureSync(WebGLId texture, | 229 void ReadbackTextureSync(WebGLId texture, |
271 const gfx::Rect& src_rect, | 230 const gfx::Rect& src_rect, |
272 unsigned char* out); | 231 unsigned char* out); |
273 | 232 |
274 WebKit::WebGLId CopyAndScaleTexture(WebGLId texture, | 233 WebKit::WebGLId CopyAndScaleTexture(WebGLId texture, |
275 const gfx::Size& src_size, | 234 const gfx::Size& src_size, |
276 const gfx::Size& dst_size, | 235 const gfx::Size& dst_size, |
277 bool vertically_flip_texture); | 236 bool vertically_flip_texture); |
278 | 237 |
279 private: | 238 private: |
280 // A single request to CropScaleReadbackAndCleanTexture. | 239 // A single request to CropScaleReadbackAndCleanTexture. |
281 // Thread-safety notes: the main thread creates instances of this class. The | 240 // The main thread can cancel the request, before it's handled by the helper |
282 // main thread can cancel the request, before it's handled by the helper | |
283 // thread, by resetting the texture and pixels fields. Alternatively, the | 241 // thread, by resetting the texture and pixels fields. Alternatively, the |
284 // thread marks that it handles the request by resetting the pixels field | 242 // thread marks that it handles the request by resetting the pixels field |
285 // (meaning it guarantees that the callback with be called). | 243 // (meaning it guarantees that the callback with be called). |
286 // In either case, the callback must be called exactly once, and the texture | 244 // In either case, the callback must be called exactly once, and the texture |
287 // must be deleted by the main thread context. | 245 // must be deleted by the main thread context. |
288 struct Request : public base::RefCountedThreadSafe<Request> { | 246 struct Request { |
289 Request(CopyTextureToImpl* impl, | 247 Request(WebGLId texture_, |
290 WebGLId texture_, | |
291 const gfx::Size& size_, | 248 const gfx::Size& size_, |
292 unsigned char* pixels_, | 249 unsigned char* pixels_, |
293 const base::Callback<void(bool)>& callback_) | 250 const base::Callback<void(bool)>& callback_) |
294 : copy_texture_impl(impl), | 251 : size(size_), |
295 size(size_), | 252 callback(callback_), |
296 callback(callback_), | 253 texture(texture_), |
297 lock(), | 254 pixels(pixels_), |
298 texture(texture_), | 255 buffer(0), |
299 pixels(pixels_) { | 256 query(0) { |
300 } | 257 } |
301 | 258 |
302 // These members are only accessed on the main thread. | |
303 GLHelper::CopyTextureToImpl* copy_texture_impl; | |
304 gfx::Size size; | 259 gfx::Size size; |
305 base::Callback<void(bool)> callback; | 260 base::Callback<void(bool)> callback; |
306 | 261 |
307 // Locks access to below members, which can be accessed on any thread. | |
308 base::Lock lock; | |
309 WebGLId texture; | 262 WebGLId texture; |
310 unsigned char* pixels; | 263 unsigned char* pixels; |
311 | 264 GLuint buffer; |
312 private: | 265 GLuint query; |
313 friend class base::RefCountedThreadSafe<Request>; | |
314 ~Request() {} | |
315 }; | 266 }; |
316 | 267 |
317 // Copies the block of pixels specified with |src_subrect| from |src_texture|, | 268 // Copies the block of pixels specified with |src_subrect| from |src_texture|, |
318 // scales it to |dst_size|, writes it into a texture, and returns its ID. | 269 // scales it to |dst_size|, writes it into a texture, and returns its ID. |
319 // |src_size| is the size of |src_texture|. | 270 // |src_size| is the size of |src_texture|. |
320 WebGLId ScaleTexture(WebGLId src_texture, | 271 WebGLId ScaleTexture(WebGLId src_texture, |
321 const gfx::Size& src_size, | 272 const gfx::Size& src_size, |
322 const gfx::Rect& src_subrect, | 273 const gfx::Rect& src_subrect, |
323 const gfx::Size& dst_size, | 274 const gfx::Size& dst_size, |
324 bool vertically_flip_texture); | 275 bool vertically_flip_texture); |
325 | 276 |
326 // Deletes the context for GLHelperThread. | 277 void ScheduleCheckReadbackDone(); |
327 void DeleteContextForThread(); | 278 void CheckReadbackDone(); |
328 static void ReadBackFramebuffer(scoped_refptr<Request> request, | 279 void FinishRequest(Request* request, bool result); |
329 WebGraphicsContext3D* context, | |
330 scoped_refptr<base::TaskRunner> reply_loop); | |
331 static void ReadBackFramebufferComplete(scoped_refptr<Request> request, | |
332 bool result); | |
333 void FinishRequest(scoped_refptr<Request> request); | |
334 void CancelRequests(); | 280 void CancelRequests(); |
335 | 281 |
336 // Interleaved array of 2-dimentional vertex positions (x, y) and | 282 // Interleaved array of 2-dimentional vertex positions (x, y) and |
337 // 2-dimentional texture coordinates (s, t). | 283 // 2-dimentional texture coordinates (s, t). |
338 static const WebKit::WGC3Dfloat kVertexAttributes[]; | 284 static const WebKit::WGC3Dfloat kVertexAttributes[]; |
339 // Interleaved array of 2-dimensional vertex positions (x, y) and | 285 // Interleaved array of 2-dimensional vertex positions (x, y) and |
340 // 2 dimensional texture coordinates (s, t). | 286 // 2 dimensional texture coordinates (s, t). |
341 static const WebKit::WGC3Dfloat kFlippedVertexAttributes[]; | 287 static const WebKit::WGC3Dfloat kFlippedVertexAttributes[]; |
342 // Shader sources used for GLHelper::CropScaleReadbackAndCleanTexture and | 288 // Shader sources used for GLHelper::CropScaleReadbackAndCleanTexture and |
343 // GLHelper::ReadbackTextureSync | 289 // GLHelper::ReadbackTextureSync |
344 static const WebKit::WGC3Dchar kCopyVertexShader[]; | 290 static const WebKit::WGC3Dchar kCopyVertexShader[]; |
345 static const WebKit::WGC3Dchar kCopyFragmentShader[]; | 291 static const WebKit::WGC3Dchar kCopyFragmentShader[]; |
346 | 292 |
347 WebGraphicsContext3D* context_; | 293 WebGraphicsContext3D* context_; |
348 WebGraphicsContext3D* context_for_thread_; | |
349 GLHelper* helper_; | 294 GLHelper* helper_; |
350 | 295 |
351 // A scoped flush that will ensure all resource deletions are flushed when | 296 // A scoped flush that will ensure all resource deletions are flushed when |
352 // this object is destroyed. Must be declared before other Scoped* fields. | 297 // this object is destroyed. Must be declared before other Scoped* fields. |
353 ScopedFlush flush_; | 298 ScopedFlush flush_; |
354 // A program for copying a source texture into a destination texture. | 299 // A program for copying a source texture into a destination texture. |
355 ScopedProgram program_; | 300 ScopedProgram program_; |
356 // The buffer that holds the vertices and the texture coordinates data for | 301 // The buffer that holds the vertices and the texture coordinates data for |
357 // drawing a quad. | 302 // drawing a quad. |
358 ScopedBuffer vertex_attributes_buffer_; | 303 ScopedBuffer vertex_attributes_buffer_; |
359 ScopedBuffer flipped_vertex_attributes_buffer_; | 304 ScopedBuffer flipped_vertex_attributes_buffer_; |
360 | 305 |
361 // The location of the position in the program. | 306 // The location of the position in the program. |
362 WebKit::WGC3Dint position_location_; | 307 WebKit::WGC3Dint position_location_; |
363 // The location of the texture coordinate in the program. | 308 // The location of the texture coordinate in the program. |
364 WebKit::WGC3Dint texcoord_location_; | 309 WebKit::WGC3Dint texcoord_location_; |
365 // The location of the source texture in the program. | 310 // The location of the source texture in the program. |
366 WebKit::WGC3Dint texture_location_; | 311 WebKit::WGC3Dint texture_location_; |
367 // The location of the texture coordinate of the sub-rectangle in the program. | 312 // The location of the texture coordinate of the sub-rectangle in the program. |
368 WebKit::WGC3Dint src_subrect_location_; | 313 WebKit::WGC3Dint src_subrect_location_; |
369 std::queue<scoped_refptr<Request> > request_queue_; | 314 std::queue<Request*> request_queue_; |
370 }; | 315 }; |
371 | 316 |
372 const WebKit::WGC3Dfloat GLHelper::CopyTextureToImpl::kVertexAttributes[] = { | 317 const WebKit::WGC3Dfloat GLHelper::CopyTextureToImpl::kVertexAttributes[] = { |
373 -1.0f, -1.0f, 0.0f, 0.0f, | 318 -1.0f, -1.0f, 0.0f, 0.0f, |
374 1.0f, -1.0f, 1.0f, 0.0f, | 319 1.0f, -1.0f, 1.0f, 0.0f, |
375 -1.0f, 1.0f, 0.0f, 1.0f, | 320 -1.0f, 1.0f, 0.0f, 1.0f, |
376 1.0f, 1.0f, 1.0f, 1.0f, | 321 1.0f, 1.0f, 1.0f, 1.0f, |
377 }; | 322 }; |
378 | 323 |
379 const WebKit::WGC3Dfloat | 324 const WebKit::WGC3Dfloat |
380 GLHelper::CopyTextureToImpl::kFlippedVertexAttributes[] = { | 325 GLHelper::CopyTextureToImpl::kFlippedVertexAttributes[] = { |
381 -1.0f, -1.0f, 0.0f, 1.0f, | 326 -1.0f, -1.0f, 0.0f, 1.0f, |
382 1.0f, -1.0f, 1.0f, 1.0f, | 327 1.0f, -1.0f, 1.0f, 1.0f, |
383 -1.0f, 1.0f, 0.0f, 0.0f, | 328 -1.0f, 1.0f, 0.0f, 0.0f, |
384 1.0f, 1.0f, 1.0f, 0.0f, | 329 1.0f, 1.0f, 1.0f, 0.0f, |
385 }; | 330 }; |
386 | 331 |
387 const WebKit::WGC3Dchar GLHelper::CopyTextureToImpl::kCopyVertexShader[] = | 332 const WebKit::WGC3Dchar GLHelper::CopyTextureToImpl::kCopyVertexShader[] = |
388 "attribute vec2 a_position;" | 333 "attribute vec2 a_position;" |
389 "attribute vec2 a_texcoord;" | 334 "attribute vec2 a_texcoord;" |
390 "varying vec2 v_texcoord;" | 335 "varying vec2 v_texcoord;" |
391 "uniform vec4 src_subrect;" | 336 "uniform vec4 src_subrect;" |
392 "void main() {" | 337 "void main() {" |
393 " gl_Position = vec4(a_position, 0.0, 1.0);" | 338 " gl_Position = vec4(a_position, 0.0, 1.0);" |
394 " v_texcoord = src_subrect.xy + a_texcoord * src_subrect.zw;" | 339 " v_texcoord = src_subrect.xy + a_texcoord * src_subrect.zw;" |
395 "}"; | 340 "}"; |
396 | 341 |
342 | |
343 #if (SK_R32_SHIFT == 16) && !SK_B32_SHIFT | |
397 const WebKit::WGC3Dchar GLHelper::CopyTextureToImpl::kCopyFragmentShader[] = | 344 const WebKit::WGC3Dchar GLHelper::CopyTextureToImpl::kCopyFragmentShader[] = |
398 "precision mediump float;" | 345 "precision mediump float;" |
399 "varying vec2 v_texcoord;" | 346 "varying vec2 v_texcoord;" |
347 "uniform sampler2D s_texture;" | |
348 "void main() {" | |
349 " gl_FragColor = texture2D(s_texture, v_texcoord).bgra;" | |
350 "}"; | |
351 #else | |
352 const WebKit::WGC3Dchar GLHelper::CopyTextureToImpl::kCopyFragmentShader[] = | |
353 "precision mediump float;" | |
354 "varying vec2 v_texcoord;" | |
400 "uniform sampler2D s_texture;" | 355 "uniform sampler2D s_texture;" |
401 "void main() {" | 356 "void main() {" |
402 " gl_FragColor = texture2D(s_texture, v_texcoord);" | 357 " gl_FragColor = texture2D(s_texture, v_texcoord);" |
403 "}"; | 358 "}"; |
359 #endif | |
360 | |
404 | 361 |
405 void GLHelper::CopyTextureToImpl::InitBuffer() { | 362 void GLHelper::CopyTextureToImpl::InitBuffer() { |
406 ScopedBufferBinder<GL_ARRAY_BUFFER> buffer_binder( | 363 ScopedBufferBinder<GL_ARRAY_BUFFER> buffer_binder( |
407 context_, vertex_attributes_buffer_); | 364 context_, vertex_attributes_buffer_); |
408 context_->bufferData(GL_ARRAY_BUFFER, | 365 context_->bufferData(GL_ARRAY_BUFFER, |
409 sizeof(kVertexAttributes), | 366 sizeof(kVertexAttributes), |
410 kVertexAttributes, | 367 kVertexAttributes, |
411 GL_STATIC_DRAW); | 368 GL_STATIC_DRAW); |
412 ScopedBufferBinder<GL_ARRAY_BUFFER> flipped_buffer_binder( | 369 ScopedBufferBinder<GL_ARRAY_BUFFER> flipped_buffer_binder( |
413 context_, flipped_vertex_attributes_buffer_); | 370 context_, flipped_vertex_attributes_buffer_); |
(...skipping 30 matching lines...) Expand all Loading... | |
444 | 401 |
445 WebGLId GLHelper::CopyTextureToImpl::ScaleTexture( | 402 WebGLId GLHelper::CopyTextureToImpl::ScaleTexture( |
446 WebGLId src_texture, | 403 WebGLId src_texture, |
447 const gfx::Size& src_size, | 404 const gfx::Size& src_size, |
448 const gfx::Rect& src_subrect, | 405 const gfx::Rect& src_subrect, |
449 const gfx::Size& dst_size, | 406 const gfx::Size& dst_size, |
450 bool vertically_flip_texture) { | 407 bool vertically_flip_texture) { |
451 WebGLId dst_texture = context_->createTexture(); | 408 WebGLId dst_texture = context_->createTexture(); |
452 { | 409 { |
453 ScopedFramebuffer dst_framebuffer(context_, context_->createFramebuffer()); | 410 ScopedFramebuffer dst_framebuffer(context_, context_->createFramebuffer()); |
454 ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder( | 411 ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(context_, |
455 context_, dst_framebuffer); | 412 dst_framebuffer); |
456 { | 413 { |
457 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder( | 414 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, dst_texture); |
458 context_, dst_texture); | |
459 context_->texImage2D(GL_TEXTURE_2D, | 415 context_->texImage2D(GL_TEXTURE_2D, |
460 0, | 416 0, |
461 GL_RGBA, | 417 GL_RGBA, |
462 dst_size.width(), | 418 dst_size.width(), |
463 dst_size.height(), | 419 dst_size.height(), |
464 0, | 420 0, |
465 GL_RGBA, | 421 GL_RGBA, |
466 GL_UNSIGNED_BYTE, | 422 GL_UNSIGNED_BYTE, |
467 NULL); | 423 NULL); |
468 context_->framebufferTexture2D(GL_FRAMEBUFFER, | 424 context_->framebufferTexture2D(GL_FRAMEBUFFER, |
469 GL_COLOR_ATTACHMENT0, | 425 GL_COLOR_ATTACHMENT0, |
470 GL_TEXTURE_2D, | 426 GL_TEXTURE_2D, |
471 dst_texture, | 427 dst_texture, |
472 0); | 428 0); |
473 } | 429 } |
474 | 430 |
475 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, src_texture); | 431 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, src_texture); |
476 WebKit::WebGLId vertex_attributes_buffer = vertically_flip_texture ? | 432 WebKit::WebGLId vertex_attributes_buffer = vertically_flip_texture ? |
477 flipped_vertex_attributes_buffer_ : vertex_attributes_buffer_; | 433 flipped_vertex_attributes_buffer_ : vertex_attributes_buffer_; |
478 ScopedBufferBinder<GL_ARRAY_BUFFER> buffer_binder( | 434 ScopedBufferBinder<GL_ARRAY_BUFFER> buffer_binder(context_, |
479 context_, vertex_attributes_buffer); | 435 vertex_attributes_buffer); |
480 | 436 |
481 context_->viewport(0, 0, dst_size.width(), dst_size.height()); | 437 context_->viewport(0, 0, dst_size.width(), dst_size.height()); |
482 context_->useProgram(program_); | 438 context_->useProgram(program_); |
483 | 439 |
484 WebKit::WGC3Dintptr offset = 0; | 440 WebKit::WGC3Dintptr offset = 0; |
485 context_->vertexAttribPointer(position_location_, | 441 context_->vertexAttribPointer(position_location_, |
486 2, | 442 2, |
487 GL_FLOAT, | 443 GL_FLOAT, |
488 GL_FALSE, | 444 GL_FALSE, |
489 4 * sizeof(WebKit::WGC3Dfloat), | 445 4 * sizeof(WebKit::WGC3Dfloat), |
(...skipping 20 matching lines...) Expand all Loading... | |
510 }; | 466 }; |
511 | 467 |
512 context_->uniform4fv(src_subrect_location_, 1, src_subrect_texcoord); | 468 context_->uniform4fv(src_subrect_location_, 1, src_subrect_texcoord); |
513 | 469 |
514 // Conduct texture mapping by drawing a quad composed of two triangles. | 470 // Conduct texture mapping by drawing a quad composed of two triangles. |
515 context_->drawArrays(GL_TRIANGLE_STRIP, 0, 4); | 471 context_->drawArrays(GL_TRIANGLE_STRIP, 0, 4); |
516 } | 472 } |
517 return dst_texture; | 473 return dst_texture; |
518 } | 474 } |
519 | 475 |
520 void GLHelper::CopyTextureToImpl::DeleteContextForThread() { | |
521 if (!context_for_thread_) | |
522 return; | |
523 | |
524 g_gl_helper_thread.Pointer()->message_loop_proxy()->PostTask( | |
525 FROM_HERE, | |
526 base::Bind(&DeleteContext, | |
527 context_for_thread_)); | |
528 context_for_thread_ = NULL; | |
529 } | |
530 | |
531 void GLHelper::CopyTextureToImpl::CropScaleReadbackAndCleanTexture( | 476 void GLHelper::CopyTextureToImpl::CropScaleReadbackAndCleanTexture( |
532 WebGLId src_texture, | 477 WebGLId src_texture, |
533 const gfx::Size& src_size, | 478 const gfx::Size& src_size, |
534 const gfx::Rect& src_subrect, | 479 const gfx::Rect& src_subrect, |
535 const gfx::Size& dst_size, | 480 const gfx::Size& dst_size, |
536 unsigned char* out, | 481 unsigned char* out, |
537 const base::Callback<void(bool)>& callback) { | 482 const base::Callback<void(bool)>& callback) { |
538 if (!context_for_thread_) { | |
539 callback.Run(false); | |
540 return; | |
541 } | |
542 | |
543 WebGLId texture = ScaleTexture(src_texture, | 483 WebGLId texture = ScaleTexture(src_texture, |
544 src_size, | 484 src_size, |
545 src_subrect, | 485 src_subrect, |
546 dst_size, | 486 dst_size, |
547 false); | 487 #ifdef USE_SKIA |
488 true | |
489 #else | |
490 false | |
491 #endif | |
492 ); | |
548 context_->flush(); | 493 context_->flush(); |
549 scoped_refptr<Request> request = | 494 Request *request = new Request(texture, dst_size, out, callback); |
550 new Request(this, texture, dst_size, out, callback); | |
551 request_queue_.push(request); | 495 request_queue_.push(request); |
496 if (request_queue_.size() == 1) { | |
497 ScheduleCheckReadbackDone(); | |
498 } | |
552 | 499 |
553 g_gl_helper_thread.Pointer()->message_loop_proxy()->PostTask(FROM_HERE, | 500 ScopedFlush flush(context_); |
554 base::Bind(&ReadBackFramebuffer, | 501 ScopedFramebuffer dst_framebuffer(context_, context_->createFramebuffer()); |
555 request, | 502 gfx::Size size; |
556 context_for_thread_, | 503 size = request->size; |
557 base::MessageLoopProxy::current())); | 504 |
505 ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(context_, | |
506 dst_framebuffer); | |
507 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, request->texture); | |
508 context_->framebufferTexture2D(GL_FRAMEBUFFER, | |
509 GL_COLOR_ATTACHMENT0, | |
510 GL_TEXTURE_2D, | |
511 request->texture, | |
512 0); | |
513 request->buffer = context_->createBuffer(); | |
514 context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, | |
515 request->buffer); | |
516 context_->bufferData(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, | |
517 4 * size.GetArea(), | |
518 NULL, | |
519 GL_STREAM_READ); | |
520 | |
521 request->query = context_->createQueryEXT(); | |
522 context_->beginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM, request->query); | |
523 context_->readPixels(0, 0, size.width(), size.height(), | |
524 GL_RGBA, GL_UNSIGNED_BYTE, 0); | |
525 context_->endQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM); | |
526 context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0); | |
527 | |
558 } | 528 } |
559 | 529 |
560 void GLHelper::CopyTextureToImpl::ReadbackTextureSync(WebGLId texture, | 530 void GLHelper::CopyTextureToImpl::ReadbackTextureSync(WebGLId texture, |
561 const gfx::Rect& src_rect, | 531 const gfx::Rect& src_rect, |
562 unsigned char* out) { | 532 unsigned char* out) { |
563 ScopedFramebuffer dst_framebuffer(context_, context_->createFramebuffer()); | 533 ScopedFramebuffer dst_framebuffer(context_, context_->createFramebuffer()); |
564 ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder( | 534 ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(context_, |
565 context_, dst_framebuffer); | 535 dst_framebuffer); |
566 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, texture); | 536 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, texture); |
567 context_->framebufferTexture2D(GL_FRAMEBUFFER, | 537 context_->framebufferTexture2D(GL_FRAMEBUFFER, |
568 GL_COLOR_ATTACHMENT0, | 538 GL_COLOR_ATTACHMENT0, |
569 GL_TEXTURE_2D, | 539 GL_TEXTURE_2D, |
570 texture, | 540 texture, |
571 0); | 541 0); |
572 context_->readPixels(src_rect.x(), | 542 context_->readPixels(src_rect.x(), |
573 src_rect.y(), | 543 src_rect.y(), |
574 src_rect.width(), | 544 src_rect.width(), |
575 src_rect.height(), | 545 src_rect.height(), |
576 GL_RGBA, | 546 GL_RGBA, |
577 GL_UNSIGNED_BYTE, | 547 GL_UNSIGNED_BYTE, |
578 out); | 548 out); |
579 } | 549 } |
580 | 550 |
581 WebKit::WebGLId GLHelper::CopyTextureToImpl::CopyAndScaleTexture( | 551 WebKit::WebGLId GLHelper::CopyTextureToImpl::CopyAndScaleTexture( |
582 WebGLId src_texture, | 552 WebGLId src_texture, |
583 const gfx::Size& src_size, | 553 const gfx::Size& src_size, |
584 const gfx::Size& dst_size, | 554 const gfx::Size& dst_size, |
585 bool vertically_flip_texture) { | 555 bool vertically_flip_texture) { |
586 return ScaleTexture(src_texture, | 556 return ScaleTexture(src_texture, |
587 src_size, | 557 src_size, |
588 gfx::Rect(src_size), | 558 gfx::Rect(src_size), |
589 dst_size, | 559 dst_size, |
590 vertically_flip_texture); | 560 vertically_flip_texture); |
591 } | 561 } |
592 | 562 |
593 void GLHelper::CopyTextureToImpl::ReadBackFramebuffer( | 563 |
594 scoped_refptr<Request> request, | 564 void GLHelper::CopyTextureToImpl::ScheduleCheckReadbackDone() { |
595 WebGraphicsContext3D* context, | 565 DCHECK(!request_queue_.empty()); |
596 scoped_refptr<base::TaskRunner> reply_loop) { | 566 base::MessageLoopProxy::current()->PostDelayedTask( |
597 DCHECK(context); | 567 FROM_HERE, |
598 if (!context->makeContextCurrent() || context->isContextLost()) { | 568 base::Bind(&CopyTextureToImpl::CheckReadbackDone, AsWeakPtr()), |
599 base::AutoLock auto_lock(request->lock); | 569 base::TimeDelta::FromMilliseconds(2)); |
600 if (request->pixels) { | |
601 // Only report failure if the request wasn't canceled (otherwise the | |
602 // failure has already been reported). | |
603 request->pixels = NULL; | |
604 reply_loop->PostTask( | |
605 FROM_HERE, base::Bind(ReadBackFramebufferComplete, request, false)); | |
606 } | |
607 return; | |
608 } | |
609 ScopedFlush flush(context); | |
610 ScopedFramebuffer dst_framebuffer(context, context->createFramebuffer()); | |
611 unsigned char* pixels = NULL; | |
612 gfx::Size size; | |
613 { | |
614 // Note: We don't want to keep the lock while doing the readBack (since we | |
615 // don't want to block the UI thread). We rely on the fact that once the | |
616 // texture is bound to a FBO (that isn't current), deleting the texture is | |
617 // delayed until the FBO is deleted. We ensure ordering by flushing while | |
618 // the lock is held. Either the main thread cancelled before we get the | |
619 // lock, and we'll exit early, or we ensure that the texture is bound to the | |
620 // framebuffer before the main thread has a chance to delete it. | |
621 base::AutoLock auto_lock(request->lock); | |
622 if (!request->texture || !request->pixels) | |
623 return; | |
624 pixels = request->pixels; | |
625 request->pixels = NULL; | |
626 size = request->size; | |
627 { | |
628 ScopedFlush flush(context); | |
629 ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder( | |
630 context, dst_framebuffer); | |
631 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder( | |
632 context, request->texture); | |
633 context->framebufferTexture2D(GL_FRAMEBUFFER, | |
634 GL_COLOR_ATTACHMENT0, | |
635 GL_TEXTURE_2D, | |
636 request->texture, | |
637 0); | |
638 } | |
639 } | |
640 bool result = context->readBackFramebuffer( | |
641 pixels, | |
642 4 * size.GetArea(), | |
643 dst_framebuffer.id(), | |
644 size.width(), | |
645 size.height()); | |
646 reply_loop->PostTask( | |
647 FROM_HERE, base::Bind(ReadBackFramebufferComplete, request, result)); | |
648 } | 570 } |
649 | 571 |
650 void GLHelper::CopyTextureToImpl::ReadBackFramebufferComplete( | 572 void GLHelper::CopyTextureToImpl::CheckReadbackDone() { |
651 scoped_refptr<Request> request, | 573 TRACE_EVENT0("mirror", |
652 bool result) { | 574 "GLHelper::CopyTextureToImpl::CheckReadBackFramebufferComplete"); |
653 request->callback.Run(result); | 575 while (!request_queue_.empty()) { |
654 if (request->copy_texture_impl) | 576 Request* request = request_queue_.front(); |
655 request->copy_texture_impl->FinishRequest(request); | 577 |
578 bool result = false; | |
579 if (request->buffer != 0) { | |
580 unsigned int done = 1; | |
581 context_->getQueryObjectuivEXT(request->query, | |
582 GL_QUERY_RESULT_AVAILABLE_EXT, &done); | |
583 if (!done) { | |
584 ScheduleCheckReadbackDone(); | |
585 return; | |
586 } | |
587 context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, | |
588 request->buffer); | |
589 void* data = context_->mapBufferCHROMIUM( | |
590 GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, GL_READ_ONLY); | |
591 | |
592 if (data) { | |
593 result = true; | |
594 memcpy(request->pixels, data, request->size.GetArea() * 4); | |
595 context_->unmapBufferCHROMIUM(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM); | |
596 } | |
597 context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0); | |
598 } | |
599 | |
600 FinishRequest(request, result); | |
601 } | |
656 } | 602 } |
657 | 603 |
658 void GLHelper::CopyTextureToImpl::FinishRequest( | 604 void GLHelper::CopyTextureToImpl::FinishRequest(Request* request, bool result) { |
659 scoped_refptr<Request> request) { | 605 DCHECK(request_queue_.front() == request); |
660 CHECK(request_queue_.front() == request); | |
661 request_queue_.pop(); | 606 request_queue_.pop(); |
662 base::AutoLock auto_lock(request->lock); | 607 request->callback.Run(result); |
663 if (request->texture != 0) { | 608 if (request->texture != 0) { |
664 context_->deleteTexture(request->texture); | 609 context_->deleteTexture(request->texture); |
665 request->texture = 0; | 610 request->texture = 0; |
666 context_->flush(); | 611 context_->flush(); |
667 } | 612 } |
613 if (request->buffer != 0) { | |
614 context_->deleteBuffer(request->buffer); | |
615 request->buffer = 0; | |
616 context_->flush(); | |
apatrick_chromium
2013/03/20 18:39:09
You could just flush once at the end of this funct
hubbe
2013/03/20 22:03:48
Done.
| |
617 } | |
618 if (request->query != 0) { | |
619 context_->deleteQueryEXT(request->query); | |
620 request->query = 0; | |
621 context_->flush(); | |
622 } | |
623 delete request; | |
668 } | 624 } |
669 | 625 |
670 void GLHelper::CopyTextureToImpl::CancelRequests() { | 626 void GLHelper::CopyTextureToImpl::CancelRequests() { |
671 while (!request_queue_.empty()) { | 627 while (!request_queue_.empty()) { |
672 scoped_refptr<Request> request = request_queue_.front(); | 628 Request* request = request_queue_.front(); |
673 request_queue_.pop(); | 629 FinishRequest(request, false); |
674 request->copy_texture_impl = NULL; | |
675 bool cancelled = false; | |
676 { | |
677 base::AutoLock auto_lock(request->lock); | |
678 if (request->texture != 0) { | |
679 context_->deleteTexture(request->texture); | |
680 request->texture = 0; | |
681 } | |
682 if (request->pixels != NULL) { | |
683 request->pixels = NULL; | |
684 cancelled = true; | |
685 } | |
686 } | |
687 if (cancelled) | |
688 request->callback.Run(false); | |
689 } | 630 } |
690 } | 631 } |
691 | 632 |
692 base::subtle::Atomic32 GLHelper::count_ = 0; | 633 GLHelper::GLHelper(WebGraphicsContext3D* context) |
693 | 634 : context_(context) { |
694 GLHelper::GLHelper(WebGraphicsContext3D* context, | |
695 WebGraphicsContext3D* context_for_thread) | |
696 : context_(context), | |
697 context_for_thread_(context_for_thread) { | |
698 base::subtle::NoBarrier_AtomicIncrement(&count_, 1); | |
699 } | 635 } |
700 | 636 |
701 GLHelper::~GLHelper() { | 637 GLHelper::~GLHelper() { |
702 DCHECK_NE(MessageLoop::current(), | |
703 g_gl_helper_thread.Pointer()->message_loop()); | |
704 base::subtle::Atomic32 decremented_count = | |
705 base::subtle::NoBarrier_AtomicIncrement(&count_, -1); | |
706 if (decremented_count == 0) { | |
707 // When this is the last instance, we synchronize with the pending | |
708 // operations on GLHelperThread. Otherwise on shutdown we may kill the GPU | |
709 // process infrastructure (BrowserGpuChannelHostFactory) before they have | |
710 // a chance to complete, likely leading to a crash. | |
711 base::WaitableEvent event(false, false); | |
712 g_gl_helper_thread.Pointer()->message_loop_proxy()->PostTask( | |
713 FROM_HERE, | |
714 base::Bind(&SignalWaitableEvent, | |
715 &event)); | |
716 // http://crbug.com/125415 | |
717 base::ThreadRestrictions::ScopedAllowWait allow_wait; | |
718 event.Wait(); | |
719 } | |
720 } | 638 } |
721 | 639 |
722 WebGraphicsContext3D* GLHelper::context() const { | 640 WebGraphicsContext3D* GLHelper::context() const { |
723 return context_; | 641 return context_; |
724 } | 642 } |
725 | 643 |
726 void GLHelper::CropScaleReadbackAndCleanTexture( | 644 void GLHelper::CropScaleReadbackAndCleanTexture( |
727 WebGLId src_texture, | 645 WebGLId src_texture, |
728 const gfx::Size& src_size, | 646 const gfx::Size& src_size, |
729 const gfx::Rect& src_subrect, | 647 const gfx::Rect& src_subrect, |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
779 if (!compile_status) { | 697 if (!compile_status) { |
780 LOG(ERROR) << std::string(context_->getShaderInfoLog(shader).utf8()); | 698 LOG(ERROR) << std::string(context_->getShaderInfoLog(shader).utf8()); |
781 return 0; | 699 return 0; |
782 } | 700 } |
783 return shader.Detach(); | 701 return shader.Detach(); |
784 } | 702 } |
785 | 703 |
786 void GLHelper::InitCopyTextToImpl() { | 704 void GLHelper::InitCopyTextToImpl() { |
787 // Lazily initialize |copy_texture_to_impl_| | 705 // Lazily initialize |copy_texture_to_impl_| |
788 if (!copy_texture_to_impl_.get()) | 706 if (!copy_texture_to_impl_.get()) |
789 copy_texture_to_impl_.reset(new CopyTextureToImpl(context_, | 707 copy_texture_to_impl_.reset(new CopyTextureToImpl(context_, this)); |
790 context_for_thread_, | |
791 this)); | |
792 } | 708 } |
793 | 709 |
794 void GLHelper::CopySubBufferDamage(WebKit::WebGLId texture, | 710 void GLHelper::CopySubBufferDamage(WebKit::WebGLId texture, |
795 WebKit::WebGLId previous_texture, | 711 WebKit::WebGLId previous_texture, |
796 const SkRegion& new_damage, | 712 const SkRegion& new_damage, |
797 const SkRegion& old_damage) { | 713 const SkRegion& old_damage) { |
798 SkRegion region(old_damage); | 714 SkRegion region(old_damage); |
799 if (region.op(new_damage, SkRegion::kDifference_Op)) { | 715 if (region.op(new_damage, SkRegion::kDifference_Op)) { |
800 ScopedFramebuffer dst_framebuffer(context_, context_->createFramebuffer()); | 716 ScopedFramebuffer dst_framebuffer(context_, context_->createFramebuffer()); |
801 ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder( | 717 ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(context_, |
802 context_, dst_framebuffer); | 718 dst_framebuffer); |
803 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, texture); | 719 ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(context_, texture); |
804 context_->framebufferTexture2D(GL_FRAMEBUFFER, | 720 context_->framebufferTexture2D(GL_FRAMEBUFFER, |
805 GL_COLOR_ATTACHMENT0, | 721 GL_COLOR_ATTACHMENT0, |
806 GL_TEXTURE_2D, | 722 GL_TEXTURE_2D, |
807 previous_texture, | 723 previous_texture, |
808 0); | 724 0); |
809 for (SkRegion::Iterator it(region); !it.done(); it.next()) { | 725 for (SkRegion::Iterator it(region); !it.done(); it.next()) { |
810 const SkIRect& rect = it.rect(); | 726 const SkIRect& rect = it.rect(); |
811 context_->copyTexSubImage2D(GL_TEXTURE_2D, 0, | 727 context_->copyTexSubImage2D(GL_TEXTURE_2D, 0, |
812 rect.x(), rect.y(), | 728 rect.x(), rect.y(), |
813 rect.x(), rect.y(), | 729 rect.x(), rect.y(), |
814 rect.width(), rect.height()); | 730 rect.width(), rect.height()); |
815 } | 731 } |
816 context_->flush(); | 732 context_->flush(); |
817 } | 733 } |
818 } | 734 } |
819 | 735 |
820 } // namespace content | 736 } // namespace content |
OLD | NEW |