OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/common/gpu/client/gl_helper.h" | 5 #include "content/common/gpu/client/gl_helper.h" |
6 | 6 |
7 #include <queue> | 7 #include <queue> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 // thread marks that it handles the request by resetting the pixels field | 188 // thread marks that it handles the request by resetting the pixels field |
189 // (meaning it guarantees that the callback with be called). | 189 // (meaning it guarantees that the callback with be called). |
190 // In either case, the callback must be called exactly once, and the texture | 190 // In either case, the callback must be called exactly once, and the texture |
191 // must be deleted by the main thread context. | 191 // must be deleted by the main thread context. |
192 struct Request { | 192 struct Request { |
193 Request(const gfx::Size& size_, | 193 Request(const gfx::Size& size_, |
194 int32 bytes_per_row_, | 194 int32 bytes_per_row_, |
195 int32 row_stride_bytes_, | 195 int32 row_stride_bytes_, |
196 unsigned char* pixels_, | 196 unsigned char* pixels_, |
197 const base::Callback<void(bool)>& callback_) | 197 const base::Callback<void(bool)>& callback_) |
198 : size(size_), | 198 : done(false), |
| 199 size(size_), |
199 bytes_per_row(bytes_per_row_), | 200 bytes_per_row(bytes_per_row_), |
200 row_stride_bytes(row_stride_bytes_), | 201 row_stride_bytes(row_stride_bytes_), |
201 pixels(pixels_), | 202 pixels(pixels_), |
202 callback(callback_), | 203 callback(callback_), |
203 buffer(0) { | 204 buffer(0), |
| 205 query(0) { |
204 } | 206 } |
205 | 207 |
| 208 bool done; |
206 gfx::Size size; | 209 gfx::Size size; |
207 int bytes_per_row; | 210 int bytes_per_row; |
208 int row_stride_bytes; | 211 int row_stride_bytes; |
209 unsigned char* pixels; | 212 unsigned char* pixels; |
210 base::Callback<void(bool)> callback; | 213 base::Callback<void(bool)> callback; |
211 GLuint buffer; | 214 GLuint buffer; |
| 215 WebKit::WebGLId query; |
212 }; | 216 }; |
213 | 217 |
214 // A readback pipeline that also converts the data to YUV before | 218 // A readback pipeline that also converts the data to YUV before |
215 // reading it back. | 219 // reading it back. |
216 class ReadbackYUVImpl : public ReadbackYUVInterface { | 220 class ReadbackYUVImpl : public ReadbackYUVInterface { |
217 public: | 221 public: |
218 ReadbackYUVImpl(WebGraphicsContext3D* context, | 222 ReadbackYUVImpl(WebGraphicsContext3D* context, |
219 CopyTextureToImpl* copy_impl, | 223 CopyTextureToImpl* copy_impl, |
220 GLHelperScaling* scaler_impl, | 224 GLHelperScaling* scaler_impl, |
221 GLHelper::ScalerQuality quality, | 225 GLHelper::ScalerQuality quality, |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
294 // |src_size| is the size of |src_texture|. | 298 // |src_size| is the size of |src_texture|. |
295 WebGLId ScaleTexture(WebGLId src_texture, | 299 WebGLId ScaleTexture(WebGLId src_texture, |
296 const gfx::Size& src_size, | 300 const gfx::Size& src_size, |
297 const gfx::Rect& src_subrect, | 301 const gfx::Rect& src_subrect, |
298 const gfx::Size& dst_size, | 302 const gfx::Size& dst_size, |
299 bool vertically_flip_texture, | 303 bool vertically_flip_texture, |
300 bool swizzle, | 304 bool swizzle, |
301 GLHelper::ScalerQuality quality); | 305 GLHelper::ScalerQuality quality); |
302 | 306 |
303 static void nullcallback(bool success) {} | 307 static void nullcallback(bool success) {} |
304 void ReadbackDone(Request* request); | 308 void ReadbackDone(Request *request); |
305 void FinishRequest(Request* request, bool result); | 309 void FinishRequest(Request* request, bool result); |
306 void CancelRequests(); | 310 void CancelRequests(); |
307 | 311 |
308 static const float kRGBtoYColorWeights[]; | 312 static const float kRGBtoYColorWeights[]; |
309 static const float kRGBtoUColorWeights[]; | 313 static const float kRGBtoUColorWeights[]; |
310 static const float kRGBtoVColorWeights[]; | 314 static const float kRGBtoVColorWeights[]; |
311 | 315 |
312 WebGraphicsContext3D* context_; | 316 WebGraphicsContext3D* context_; |
313 GLHelper* helper_; | 317 GLHelper* helper_; |
314 | 318 |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
382 callback); | 386 callback); |
383 request_queue_.push(request); | 387 request_queue_.push(request); |
384 request->buffer = context_->createBuffer(); | 388 request->buffer = context_->createBuffer(); |
385 context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, | 389 context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, |
386 request->buffer); | 390 request->buffer); |
387 context_->bufferData(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, | 391 context_->bufferData(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, |
388 4 * dst_size.GetArea(), | 392 4 * dst_size.GetArea(), |
389 NULL, | 393 NULL, |
390 GL_STREAM_READ); | 394 GL_STREAM_READ); |
391 | 395 |
| 396 request->query = context_->createQueryEXT(); |
| 397 context_->beginQueryEXT(GL_ASYNC_READ_PIXELS_COMPLETED_CHROMIUM, |
| 398 request->query); |
392 context_->readPixels(0, 0, dst_size.width(), dst_size.height(), | 399 context_->readPixels(0, 0, dst_size.width(), dst_size.height(), |
393 GL_RGBA, GL_UNSIGNED_BYTE, NULL); | 400 GL_RGBA, GL_UNSIGNED_BYTE, NULL); |
| 401 context_->endQueryEXT(GL_ASYNC_READ_PIXELS_COMPLETED_CHROMIUM); |
394 context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0); | 402 context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0); |
395 cc::SyncPointHelper::SignalSyncPoint( | 403 cc::SyncPointHelper::SignalQuery( |
396 context_, | 404 context_, |
397 context_->insertSyncPoint(), | 405 request->query, |
398 base::Bind(&CopyTextureToImpl::ReadbackDone, AsWeakPtr(), request)); | 406 base::Bind(&CopyTextureToImpl::ReadbackDone, AsWeakPtr(), request)); |
399 } | 407 } |
400 | 408 |
401 | 409 |
402 void GLHelper::CopyTextureToImpl::CropScaleReadbackAndCleanTexture( | 410 void GLHelper::CopyTextureToImpl::CropScaleReadbackAndCleanTexture( |
403 WebGLId src_texture, | 411 WebGLId src_texture, |
404 const gfx::Size& src_size, | 412 const gfx::Size& src_size, |
405 const gfx::Rect& src_subrect, | 413 const gfx::Rect& src_subrect, |
406 const gfx::Size& dst_size, | 414 const gfx::Size& dst_size, |
407 unsigned char* out, | 415 unsigned char* out, |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
465 GLHelper::ScalerQuality quality) { | 473 GLHelper::ScalerQuality quality) { |
466 return ScaleTexture(src_texture, | 474 return ScaleTexture(src_texture, |
467 src_size, | 475 src_size, |
468 gfx::Rect(src_size), | 476 gfx::Rect(src_size), |
469 dst_size, | 477 dst_size, |
470 vertically_flip_texture, | 478 vertically_flip_texture, |
471 false, | 479 false, |
472 quality); | 480 quality); |
473 } | 481 } |
474 | 482 |
475 void GLHelper::CopyTextureToImpl::ReadbackDone(Request* request) { | 483 void GLHelper::CopyTextureToImpl::ReadbackDone(Request* finished_request) { |
476 TRACE_EVENT0("mirror", | 484 TRACE_EVENT0("mirror", |
477 "GLHelper::CopyTextureToImpl::CheckReadbackFramebufferComplete"); | 485 "GLHelper::CopyTextureToImpl::CheckReadbackFramebufferComplete"); |
478 DCHECK(request == request_queue_.front()); | 486 finished_request->done = true; |
479 | 487 |
480 bool result = false; | 488 // We process transfer requests in the order they were received, regardless |
481 if (request->buffer != 0) { | 489 // of the order we get the callbacks in. |
482 context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, | 490 while (!request_queue_.empty()) { |
483 request->buffer); | 491 Request* request = request_queue_.front(); |
484 unsigned char* data = static_cast<unsigned char *>( | 492 if (!request->done) { |
485 context_->mapBufferCHROMIUM( | 493 break; |
486 GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, GL_READ_ONLY)); | 494 } |
487 if (data) { | 495 |
488 result = true; | 496 bool result = false; |
489 if (request->bytes_per_row == request->size.width() * 4 && | 497 if (request->buffer != 0) { |
490 request->bytes_per_row == request->row_stride_bytes) { | 498 context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, |
491 memcpy(request->pixels, data, request->size.GetArea() * 4); | 499 request->buffer); |
492 } else { | 500 unsigned char* data = static_cast<unsigned char *>( |
493 unsigned char* out = request->pixels; | 501 context_->mapBufferCHROMIUM( |
494 for (int y = 0; y < request->size.height(); y++) { | 502 GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, GL_READ_ONLY)); |
495 memcpy(out, data, request->bytes_per_row); | 503 if (data) { |
496 out += request->row_stride_bytes; | 504 result = true; |
497 data += request->size.width() * 4; | 505 if (request->bytes_per_row == request->size.width() * 4 && |
| 506 request->bytes_per_row == request->row_stride_bytes) { |
| 507 memcpy(request->pixels, data, request->size.GetArea() * 4); |
| 508 } else { |
| 509 unsigned char* out = request->pixels; |
| 510 for (int y = 0; y < request->size.height(); y++) { |
| 511 memcpy(out, data, request->bytes_per_row); |
| 512 out += request->row_stride_bytes; |
| 513 data += request->size.width() * 4; |
| 514 } |
498 } | 515 } |
| 516 context_->unmapBufferCHROMIUM(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM); |
499 } | 517 } |
500 context_->unmapBufferCHROMIUM(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM); | 518 context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0); |
501 } | 519 } |
502 context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0); | 520 |
| 521 FinishRequest(request, result); |
503 } | 522 } |
504 | |
505 FinishRequest(request, result); | |
506 } | 523 } |
507 | 524 |
508 void GLHelper::CopyTextureToImpl::FinishRequest(Request* request, | 525 void GLHelper::CopyTextureToImpl::FinishRequest(Request* request, |
509 bool result) { | 526 bool result) { |
| 527 TRACE_EVENT0("mirror", "GLHelper::CopyTextureToImpl::FinishRequest"); |
510 DCHECK(request_queue_.front() == request); | 528 DCHECK(request_queue_.front() == request); |
511 request_queue_.pop(); | 529 request_queue_.pop(); |
512 request->callback.Run(result); | 530 request->callback.Run(result); |
513 ScopedFlush flush(context_); | 531 ScopedFlush flush(context_); |
| 532 if (request->query != 0) { |
| 533 context_->deleteQueryEXT(request->query); |
| 534 request->query = 0; |
| 535 } |
514 if (request->buffer != 0) { | 536 if (request->buffer != 0) { |
515 context_->deleteBuffer(request->buffer); | 537 context_->deleteBuffer(request->buffer); |
516 request->buffer = 0; | 538 request->buffer = 0; |
517 } | 539 } |
518 delete request; | 540 delete request; |
519 } | 541 } |
520 | 542 |
521 void GLHelper::CopyTextureToImpl::CancelRequests() { | 543 void GLHelper::CopyTextureToImpl::CancelRequests() { |
522 while (!request_queue_.empty()) { | 544 while (!request_queue_.empty()) { |
523 Request* request = request_queue_.front(); | 545 Request* request = request_queue_.front(); |
(...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1007 quality, | 1029 quality, |
1008 src_size, | 1030 src_size, |
1009 src_subrect, | 1031 src_subrect, |
1010 dst_size, | 1032 dst_size, |
1011 dst_subrect, | 1033 dst_subrect, |
1012 flip_vertically, | 1034 flip_vertically, |
1013 use_mrt); | 1035 use_mrt); |
1014 } | 1036 } |
1015 | 1037 |
1016 } // namespace content | 1038 } // namespace content |
OLD | NEW |