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 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
181 // thread marks that it handles the request by resetting the pixels field | 181 // thread marks that it handles the request by resetting the pixels field |
182 // (meaning it guarantees that the callback with be called). | 182 // (meaning it guarantees that the callback with be called). |
183 // In either case, the callback must be called exactly once, and the texture | 183 // In either case, the callback must be called exactly once, and the texture |
184 // must be deleted by the main thread context. | 184 // must be deleted by the main thread context. |
185 struct Request { | 185 struct Request { |
186 Request(const gfx::Size& size_, | 186 Request(const gfx::Size& size_, |
187 int32 bytes_per_row_, | 187 int32 bytes_per_row_, |
188 int32 row_stride_bytes_, | 188 int32 row_stride_bytes_, |
189 unsigned char* pixels_, | 189 unsigned char* pixels_, |
190 const base::Callback<void(bool)>& callback_) | 190 const base::Callback<void(bool)>& callback_) |
191 : size(size_), | 191 : done(false), |
192 size(size_), | |
192 bytes_per_row(bytes_per_row_), | 193 bytes_per_row(bytes_per_row_), |
193 row_stride_bytes(row_stride_bytes_), | 194 row_stride_bytes(row_stride_bytes_), |
194 pixels(pixels_), | 195 pixels(pixels_), |
195 callback(callback_), | 196 callback(callback_), |
196 buffer(0) { | 197 buffer(0), |
198 query(0) { | |
197 } | 199 } |
198 | 200 |
201 bool done; | |
199 gfx::Size size; | 202 gfx::Size size; |
200 int bytes_per_row; | 203 int bytes_per_row; |
201 int row_stride_bytes; | 204 int row_stride_bytes; |
202 unsigned char* pixels; | 205 unsigned char* pixels; |
203 base::Callback<void(bool)> callback; | 206 base::Callback<void(bool)> callback; |
204 GLuint buffer; | 207 GLuint buffer; |
208 WebKit::WebGLId query; | |
205 }; | 209 }; |
206 | 210 |
207 // A readback pipeline that also converts the data to YUV before | 211 // A readback pipeline that also converts the data to YUV before |
208 // reading it back. | 212 // reading it back. |
209 class ReadbackYUVImpl : public ReadbackYUVInterface { | 213 class ReadbackYUVImpl : public ReadbackYUVInterface { |
210 public: | 214 public: |
211 ReadbackYUVImpl(WebGraphicsContext3D* context, | 215 ReadbackYUVImpl(WebGraphicsContext3D* context, |
212 CopyTextureToImpl* copy_impl, | 216 CopyTextureToImpl* copy_impl, |
213 GLHelperScaling* scaler_impl, | 217 GLHelperScaling* scaler_impl, |
214 GLHelper::ScalerQuality quality, | 218 GLHelper::ScalerQuality quality, |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
285 // |src_size| is the size of |src_texture|. | 289 // |src_size| is the size of |src_texture|. |
286 WebGLId ScaleTexture(WebGLId src_texture, | 290 WebGLId ScaleTexture(WebGLId src_texture, |
287 const gfx::Size& src_size, | 291 const gfx::Size& src_size, |
288 const gfx::Rect& src_subrect, | 292 const gfx::Rect& src_subrect, |
289 const gfx::Size& dst_size, | 293 const gfx::Size& dst_size, |
290 bool vertically_flip_texture, | 294 bool vertically_flip_texture, |
291 bool swizzle, | 295 bool swizzle, |
292 GLHelper::ScalerQuality quality); | 296 GLHelper::ScalerQuality quality); |
293 | 297 |
294 static void nullcallback(bool success) {} | 298 static void nullcallback(bool success) {} |
295 void ReadbackDone(Request* request); | 299 void ReadbackDone(Request *request); |
296 void FinishRequest(Request* request, bool result); | 300 void FinishRequest(Request* request, bool result); |
297 void CancelRequests(); | 301 void CancelRequests(); |
298 | 302 |
299 static const float kRGBtoYColorWeights[]; | 303 static const float kRGBtoYColorWeights[]; |
300 static const float kRGBtoUColorWeights[]; | 304 static const float kRGBtoUColorWeights[]; |
301 static const float kRGBtoVColorWeights[]; | 305 static const float kRGBtoVColorWeights[]; |
302 | 306 |
303 WebGraphicsContext3D* context_; | 307 WebGraphicsContext3D* context_; |
304 GLHelper* helper_; | 308 GLHelper* helper_; |
305 | 309 |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
373 callback); | 377 callback); |
374 request_queue_.push(request); | 378 request_queue_.push(request); |
375 request->buffer = context_->createBuffer(); | 379 request->buffer = context_->createBuffer(); |
376 context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, | 380 context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, |
377 request->buffer); | 381 request->buffer); |
378 context_->bufferData(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, | 382 context_->bufferData(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, |
379 4 * dst_size.GetArea(), | 383 4 * dst_size.GetArea(), |
380 NULL, | 384 NULL, |
381 GL_STREAM_READ); | 385 GL_STREAM_READ); |
382 | 386 |
387 request->query = context_->createQueryEXT(); | |
388 context_->beginQueryEXT(GL_ASYNC_READ_PIXELS_COMPLETED_CHROMIUM, | |
389 request->query); | |
383 context_->readPixels(0, 0, dst_size.width(), dst_size.height(), | 390 context_->readPixels(0, 0, dst_size.width(), dst_size.height(), |
384 GL_RGBA, GL_UNSIGNED_BYTE, NULL); | 391 GL_RGBA, GL_UNSIGNED_BYTE, NULL); |
392 context_->endQueryEXT(GL_ASYNC_READ_PIXELS_COMPLETED_CHROMIUM); | |
385 context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0); | 393 context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0); |
386 cc::SyncPointHelper::SignalSyncPoint( | 394 cc::SyncPointHelper::SignalQuery( |
387 context_, | 395 context_, |
388 context_->insertSyncPoint(), | 396 request->query, |
389 base::Bind(&CopyTextureToImpl::ReadbackDone, AsWeakPtr(), request)); | 397 base::Bind(&CopyTextureToImpl::ReadbackDone, AsWeakPtr(), request)); |
390 } | 398 } |
391 | 399 |
392 | 400 |
393 void GLHelper::CopyTextureToImpl::CropScaleReadbackAndCleanTexture( | 401 void GLHelper::CopyTextureToImpl::CropScaleReadbackAndCleanTexture( |
394 WebGLId src_texture, | 402 WebGLId src_texture, |
395 const gfx::Size& src_size, | 403 const gfx::Size& src_size, |
396 const gfx::Rect& src_subrect, | 404 const gfx::Rect& src_subrect, |
397 const gfx::Size& dst_size, | 405 const gfx::Size& dst_size, |
398 unsigned char* out, | 406 unsigned char* out, |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
459 gfx::Rect(src_size), | 467 gfx::Rect(src_size), |
460 dst_size, | 468 dst_size, |
461 vertically_flip_texture, | 469 vertically_flip_texture, |
462 false, | 470 false, |
463 quality); | 471 quality); |
464 } | 472 } |
465 | 473 |
466 void GLHelper::CopyTextureToImpl::ReadbackDone(Request* request) { | 474 void GLHelper::CopyTextureToImpl::ReadbackDone(Request* request) { |
467 TRACE_EVENT0("mirror", | 475 TRACE_EVENT0("mirror", |
468 "GLHelper::CopyTextureToImpl::CheckReadbackFramebufferComplete"); | 476 "GLHelper::CopyTextureToImpl::CheckReadbackFramebufferComplete"); |
469 DCHECK(request == request_queue_.front()); | 477 request->done = true; |
470 | 478 |
471 bool result = false; | 479 // We process transfer requests in the order they were received, regardless |
472 if (request->buffer != 0) { | 480 // of the order we get the callbacks in. |
473 context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, | 481 while (!request_queue_.empty()) { |
474 request->buffer); | 482 request = request_queue_.front(); |
piman
2013/07/01 22:24:08
nit: can we avoid hiding the method parameter? It
hubbe
2013/07/01 22:34:41
Done.
| |
475 unsigned char* data = static_cast<unsigned char *>( | 483 if (!request->done) break; |
piman
2013/07/01 22:24:08
nit: break on next line
hubbe
2013/07/01 22:34:41
Done.
| |
476 context_->mapBufferCHROMIUM( | 484 |
477 GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, GL_READ_ONLY)); | 485 bool result = false; |
478 if (data) { | 486 if (request->buffer != 0) { |
479 result = true; | 487 context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, |
480 if (request->bytes_per_row == request->size.width() * 4 && | 488 request->buffer); |
481 request->bytes_per_row == request->row_stride_bytes) { | 489 unsigned char* data = static_cast<unsigned char *>( |
482 memcpy(request->pixels, data, request->size.GetArea() * 4); | 490 context_->mapBufferCHROMIUM( |
483 } else { | 491 GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, GL_READ_ONLY)); |
484 unsigned char* out = request->pixels; | 492 if (data) { |
485 for (int y = 0; y < request->size.height(); y++) { | 493 result = true; |
486 memcpy(out, data, request->bytes_per_row); | 494 if (request->bytes_per_row == request->size.width() * 4 && |
487 out += request->row_stride_bytes; | 495 request->bytes_per_row == request->row_stride_bytes) { |
488 data += request->size.width() * 4; | 496 memcpy(request->pixels, data, request->size.GetArea() * 4); |
497 } else { | |
498 unsigned char* out = request->pixels; | |
499 for (int y = 0; y < request->size.height(); y++) { | |
500 memcpy(out, data, request->bytes_per_row); | |
501 out += request->row_stride_bytes; | |
502 data += request->size.width() * 4; | |
503 } | |
489 } | 504 } |
505 context_->unmapBufferCHROMIUM(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM); | |
490 } | 506 } |
491 context_->unmapBufferCHROMIUM(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM); | 507 context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0); |
492 } | 508 } |
493 context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0); | 509 |
510 FinishRequest(request, result); | |
494 } | 511 } |
495 | |
496 FinishRequest(request, result); | |
497 } | 512 } |
498 | 513 |
499 void GLHelper::CopyTextureToImpl::FinishRequest(Request* request, | 514 void GLHelper::CopyTextureToImpl::FinishRequest(Request* request, |
500 bool result) { | 515 bool result) { |
516 TRACE_EVENT0("mirror", "GLHelper::CopyTextureToImpl::FinishRequest"); | |
501 DCHECK(request_queue_.front() == request); | 517 DCHECK(request_queue_.front() == request); |
502 request_queue_.pop(); | 518 request_queue_.pop(); |
503 request->callback.Run(result); | 519 request->callback.Run(result); |
504 ScopedFlush flush(context_); | 520 ScopedFlush flush(context_); |
521 if (request->query != 0) { | |
522 context_->deleteQueryEXT(request->query); | |
523 request->query = 0; | |
524 } | |
505 if (request->buffer != 0) { | 525 if (request->buffer != 0) { |
506 context_->deleteBuffer(request->buffer); | 526 context_->deleteBuffer(request->buffer); |
507 request->buffer = 0; | 527 request->buffer = 0; |
508 } | 528 } |
509 delete request; | 529 delete request; |
510 } | 530 } |
511 | 531 |
512 void GLHelper::CopyTextureToImpl::CancelRequests() { | 532 void GLHelper::CopyTextureToImpl::CancelRequests() { |
513 while (!request_queue_.empty()) { | 533 while (!request_queue_.empty()) { |
514 Request* request = request_queue_.front(); | 534 Request* request = request_queue_.front(); |
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
960 quality, | 980 quality, |
961 src_size, | 981 src_size, |
962 src_subrect, | 982 src_subrect, |
963 dst_size, | 983 dst_size, |
964 dst_subrect, | 984 dst_subrect, |
965 flip_vertically, | 985 flip_vertically, |
966 use_mrt); | 986 use_mrt); |
967 } | 987 } |
968 | 988 |
969 } // namespace content | 989 } // namespace content |
OLD | NEW |