Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(266)

Side by Side Diff: content/common/gpu/client/gl_helper.cc

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

Powered by Google App Engine
This is Rietveld 408576698