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

Side by Side Diff: cc/resources/video_resource_updater.cc

Issue 1852923002: Enable sampling from DXGI NV12 formats in GLRenderer. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 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
« no previous file with comments | « cc/output/shader.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "cc/resources/video_resource_updater.h" 5 #include "cc/resources/video_resource_updater.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 DeleteResource(it++); 339 DeleteResource(it++);
340 else 340 else
341 ++it; 341 ++it;
342 } 342 }
343 343
344 const int max_resource_size = resource_provider_->max_texture_size(); 344 const int max_resource_size = resource_provider_->max_texture_size();
345 std::vector<ResourceList::iterator> plane_resources; 345 std::vector<ResourceList::iterator> plane_resources;
346 for (size_t i = 0; i < output_plane_count; ++i) { 346 for (size_t i = 0; i < output_plane_count; ++i) {
347 gfx::Size output_plane_resource_size = 347 gfx::Size output_plane_resource_size =
348 SoftwarePlaneDimension(video_frame.get(), software_compositor, i); 348 SoftwarePlaneDimension(video_frame.get(), software_compositor, i);
349 ResourceFormat plane_resource_format = output_resource_format;
350 if ((input_frame_format == media::PIXEL_FORMAT_NV12) && (i == 1)) {
danakj 2016/04/13 00:24:18 If all of this is for tests I'd prefer to just not
351 // A two-byte-per-pixel format would avoid wasting space, but this is
352 // only used in testing.
353 plane_resource_format = RGBA_8888;
354 }
349 if (output_plane_resource_size.IsEmpty() || 355 if (output_plane_resource_size.IsEmpty() ||
350 output_plane_resource_size.width() > max_resource_size || 356 output_plane_resource_size.width() > max_resource_size ||
351 output_plane_resource_size.height() > max_resource_size) { 357 output_plane_resource_size.height() > max_resource_size) {
352 break; 358 break;
353 } 359 }
354 360
355 // Try recycle a previously-allocated resource. 361 // Try recycle a previously-allocated resource.
356 ResourceList::iterator resource_it = all_resources_.end(); 362 ResourceList::iterator resource_it = all_resources_.end();
357 for (auto it = all_resources_.begin(); it != all_resources_.end(); ++it) { 363 for (auto it = all_resources_.begin(); it != all_resources_.end(); ++it) {
358 if (it->resource_size == output_plane_resource_size && 364 if (it->resource_size == output_plane_resource_size &&
359 it->resource_format == output_resource_format) { 365 it->resource_format == plane_resource_format) {
360 if (PlaneResourceMatchesUniqueID(*it, video_frame.get(), i)) { 366 if (PlaneResourceMatchesUniqueID(*it, video_frame.get(), i)) {
361 // Bingo, we found a resource that already contains the data we are 367 // Bingo, we found a resource that already contains the data we are
362 // planning to put in it. It's safe to reuse it even if 368 // planning to put in it. It's safe to reuse it even if
363 // resource_provider_ holds some references to it, because those 369 // resource_provider_ holds some references to it, because those
364 // references are read-only. 370 // references are read-only.
365 resource_it = it; 371 resource_it = it;
366 break; 372 break;
367 } 373 }
368 374
369 // This extra check is needed because resources backed by SharedMemory 375 // This extra check is needed because resources backed by SharedMemory
370 // are not ref-counted, unlike mailboxes. Full discussion in 376 // are not ref-counted, unlike mailboxes. Full discussion in
371 // codereview.chromium.org/145273021. 377 // codereview.chromium.org/145273021.
372 const bool in_use = 378 const bool in_use =
373 software_compositor && 379 software_compositor &&
374 resource_provider_->InUseByConsumer(it->resource_id); 380 resource_provider_->InUseByConsumer(it->resource_id);
375 if (it->ref_count == 0 && !in_use) { 381 if (it->ref_count == 0 && !in_use) {
376 // We found a resource with the correct size that we can overwrite. 382 // We found a resource with the correct size that we can overwrite.
377 resource_it = it; 383 resource_it = it;
378 } 384 }
379 } 385 }
380 } 386 }
381 387
382 // Check if we need to allocate a new resource. 388 // Check if we need to allocate a new resource.
383 if (resource_it == all_resources_.end()) { 389 if (resource_it == all_resources_.end()) {
384 const bool is_immutable = true; 390 const bool is_immutable = true;
385 resource_it = 391 resource_it =
386 AllocateResource(output_plane_resource_size, output_resource_format, 392 AllocateResource(output_plane_resource_size, plane_resource_format,
387 !software_compositor, is_immutable); 393 !software_compositor, is_immutable);
388 } 394 }
389 if (resource_it == all_resources_.end()) 395 if (resource_it == all_resources_.end())
390 break; 396 break;
391 397
392 ++resource_it->ref_count; 398 ++resource_it->ref_count;
393 plane_resources.push_back(resource_it); 399 plane_resources.push_back(resource_it);
394 } 400 }
395 401
396 if (plane_resources.size() != output_plane_count) { 402 if (plane_resources.size() != output_plane_count) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
433 external_resources.software_resources.push_back(plane_resource.resource_id); 439 external_resources.software_resources.push_back(plane_resource.resource_id);
434 external_resources.software_release_callback = 440 external_resources.software_release_callback =
435 base::Bind(&RecycleResource, AsWeakPtr(), plane_resource.resource_id); 441 base::Bind(&RecycleResource, AsWeakPtr(), plane_resource.resource_id);
436 external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE; 442 external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE;
437 return external_resources; 443 return external_resources;
438 } 444 }
439 445
440 for (size_t i = 0; i < plane_resources.size(); ++i) { 446 for (size_t i = 0; i < plane_resources.size(); ++i) {
441 PlaneResource& plane_resource = *plane_resources[i]; 447 PlaneResource& plane_resource = *plane_resources[i];
442 // Update each plane's resource id with its content. 448 // Update each plane's resource id with its content.
443 DCHECK_EQ(plane_resource.resource_format,
444 resource_provider_->YuvResourceFormat(bits_per_channel));
445
446 if (!PlaneResourceMatchesUniqueID(plane_resource, video_frame.get(), i)) { 449 if (!PlaneResourceMatchesUniqueID(plane_resource, video_frame.get(), i)) {
447 // We need to transfer data from |video_frame| to the plane resource. 450 // We need to transfer data from |video_frame| to the plane resource.
448 // TODO(reveman): Can use GpuMemoryBuffers here to improve performance. 451 // TODO(reveman): Can use GpuMemoryBuffers here to improve performance.
449 452
450 // The |resource_size_pixels| is the size of the resource we want to 453 // The |resource_size_pixels| is the size of the resource we want to
451 // upload to. 454 // upload to.
452 gfx::Size resource_size_pixels = plane_resource.resource_size; 455 gfx::Size resource_size_pixels = plane_resource.resource_size;
453 // The |video_stride_bytes| is the width of the video frame we are 456 // The |video_stride_bytes| is the width of the video frame we are
454 // uploading (including non-frame data to fill in the stride). 457 // uploading (including non-frame data to fill in the stride).
455 int video_stride_bytes = video_frame->stride(i); 458 int video_stride_bytes = video_frame->stride(i);
456 459
457 size_t bytes_per_row = ResourceUtil::UncheckedWidthInBytes<size_t>( 460 size_t bytes_per_row = ResourceUtil::UncheckedWidthInBytes<size_t>(
458 resource_size_pixels.width(), plane_resource.resource_format); 461 resource_size_pixels.width(), plane_resource.resource_format);
459 // Use 4-byte row alignment (OpenGL default) for upload performance. 462 // Use 4-byte row alignment (OpenGL default) for upload performance.
460 // Assuming that GL_UNPACK_ALIGNMENT has not changed from default. 463 // Assuming that GL_UNPACK_ALIGNMENT has not changed from default.
461 size_t upload_image_stride = 464 size_t upload_image_stride =
462 MathUtil::UncheckedRoundUp<size_t>(bytes_per_row, 4u); 465 MathUtil::UncheckedRoundUp<size_t>(bytes_per_row, 4u);
463 466
464 bool needs_conversion = false; 467 bool needs_conversion = false;
465 int shift = 0; 468 int shift = 0;
469 bool needs_expansion = false;
466 470
467 // LUMINANCE_F16 uses half-floats, so we always need a conversion step. 471 // LUMINANCE_F16 uses half-floats, so we always need a conversion step.
468 if (plane_resource.resource_format == LUMINANCE_F16) { 472 if (plane_resource.resource_format == LUMINANCE_F16) {
469 needs_conversion = true; 473 needs_conversion = true;
470 // Note that the current method of converting integers to half-floats 474 // Note that the current method of converting integers to half-floats
471 // stops working if you have more than 10 bits of data. 475 // stops working if you have more than 10 bits of data.
472 DCHECK_LE(bits_per_channel, 10); 476 DCHECK_LE(bits_per_channel, 10);
473 } else if (bits_per_channel > 8) { 477 } else if (bits_per_channel > 8) {
474 // If bits_per_channel > 8 and we can't use LUMINANCE_F16, we need to 478 // If bits_per_channel > 8 and we can't use LUMINANCE_F16, we need to
475 // shift the data down and create an 8-bit texture. 479 // shift the data down and create an 8-bit texture.
476 needs_conversion = true; 480 needs_conversion = true;
477 shift = bits_per_channel - 8; 481 shift = bits_per_channel - 8;
482 } else if ((input_frame_format == media::PIXEL_FORMAT_NV12) && (i == 1)) {
483 DCHECK_EQ(RGBA_8888, plane_resource.resource_format);
484 needs_conversion = true;
485 // Expand each 2 byte pixel into 4 bytes.
486 needs_expansion = true;
478 } 487 }
479 const uint8_t* pixels; 488 const uint8_t* pixels;
480 if (static_cast<int>(upload_image_stride) == video_stride_bytes && 489 if (static_cast<int>(upload_image_stride) == video_stride_bytes &&
481 !needs_conversion) { 490 !needs_conversion) {
482 pixels = video_frame->data(i); 491 pixels = video_frame->data(i);
483 } else { 492 } else {
484 // Avoid malloc for each frame/plane if possible. 493 // Avoid malloc for each frame/plane if possible.
485 size_t needed_size = 494 size_t needed_size =
486 upload_image_stride * resource_size_pixels.height(); 495 upload_image_stride * resource_size_pixels.height();
487 if (upload_pixels_.size() < needed_size) 496 if (upload_pixels_.size() < needed_size)
(...skipping 13 matching lines...) Expand all
501 for (size_t i = 0; i < bytes_per_row / 2; i++) 510 for (size_t i = 0; i < bytes_per_row / 2; i++)
502 dst[i] = src[i] | 0x3800; 511 dst[i] = src[i] | 0x3800;
503 } else if (shift != 0) { 512 } else if (shift != 0) {
504 // We have more-than-8-bit input which we need to shift 513 // We have more-than-8-bit input which we need to shift
505 // down to fit it into an 8-bit texture. 514 // down to fit it into an 8-bit texture.
506 uint8_t* dst = &upload_pixels_[upload_image_stride * row]; 515 uint8_t* dst = &upload_pixels_[upload_image_stride * row];
507 const uint16_t* src = reinterpret_cast<uint16_t*>( 516 const uint16_t* src = reinterpret_cast<uint16_t*>(
508 video_frame->data(i) + (video_stride_bytes * row)); 517 video_frame->data(i) + (video_stride_bytes * row));
509 for (size_t i = 0; i < bytes_per_row; i++) 518 for (size_t i = 0; i < bytes_per_row; i++)
510 dst[i] = src[i] >> shift; 519 dst[i] = src[i] >> shift;
520 } else if (needs_expansion) {
521 uint32_t* dst = reinterpret_cast<uint32_t*>(
522 &upload_pixels_[upload_image_stride * row]);
523 const uint8_t* src =
524 video_frame->data(i) + (video_stride_bytes * row);
525 for (size_t i = 0; i < bytes_per_row / 4; i++) {
526 // The first channel (U) goes in the R component, and the second
527 // (V) goes in the G component. B and A are black.
528 dst[i] = ((src[i * 2] << 24) | (src[i * 2 + 1] << 16));
529 }
511 } else { 530 } else {
512 // Input and output are the same size and format, but 531 // Input and output are the same size and format, but
513 // differ in stride, copy one row at a time. 532 // differ in stride, copy one row at a time.
514 uint8_t* dst = &upload_pixels_[upload_image_stride * row]; 533 uint8_t* dst = &upload_pixels_[upload_image_stride * row];
515 const uint8_t* src = 534 const uint8_t* src =
516 video_frame->data(i) + (video_stride_bytes * row); 535 video_frame->data(i) + (video_stride_bytes * row);
517 memcpy(dst, src, bytes_per_row); 536 memcpy(dst, src, bytes_per_row);
518 } 537 }
519 } 538 }
520 pixels = &upload_pixels_[0]; 539 pixels = &upload_pixels_[0];
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
757 plane_resource.plane_index == 0; 776 plane_resource.plane_index == 0;
758 }); 777 });
759 if (resource_it == updater->all_resources_.end()) 778 if (resource_it == updater->all_resources_.end())
760 return; 779 return;
761 780
762 resource_it->destructed = true; 781 resource_it->destructed = true;
763 } 782 }
764 #endif 783 #endif
765 784
766 } // namespace cc 785 } // namespace cc
OLDNEW
« no previous file with comments | « cc/output/shader.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698