Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 238 if (software_compositor) | 238 if (software_compositor) |
| 239 return coded_size; | 239 return coded_size; |
| 240 | 240 |
| 241 int plane_width = media::VideoFrame::Columns( | 241 int plane_width = media::VideoFrame::Columns( |
| 242 plane_index, input_frame->format(), coded_size.width()); | 242 plane_index, input_frame->format(), coded_size.width()); |
| 243 int plane_height = media::VideoFrame::Rows(plane_index, input_frame->format(), | 243 int plane_height = media::VideoFrame::Rows(plane_index, input_frame->format(), |
| 244 coded_size.height()); | 244 coded_size.height()); |
| 245 return gfx::Size(plane_width, plane_height); | 245 return gfx::Size(plane_width, plane_height); |
| 246 } | 246 } |
| 247 | 247 |
| 248 VideoResourceUpdater::ResourceList::iterator | |
| 249 VideoResourceUpdater::RecycleOrAllocateTexture(const gfx::Size& resource_size, | |
| 250 ResourceFormat resource_format, | |
| 251 bool immutable_hint) { | |
| 252 for (auto it = all_resources_.begin(); it != all_resources_.end(); ++it) { | |
| 253 // Reuse resource if attributes match and the resource is a currently | |
| 254 // unreferenced texture. | |
| 255 if (it->ref_count == 0 && !it->mailbox.IsZero() && | |
| 256 it->resource_format == resource_format && | |
| 257 it->resource_size == resource_size && | |
| 258 immutable_hint == | |
| 259 (resource_provider_->GetTextureHint(it->resource_id) == | |
| 260 ResourceProvider::TEXTURE_HINT_IMMUTABLE)) { | |
| 261 return it; | |
| 262 } | |
| 263 } | |
| 264 | |
| 265 return AllocateResource(resource_size, resource_format, true, immutable_hint); | |
| 266 } | |
| 267 | |
| 268 // Create an RGB texture by software converting YUV planar data, for the case | |
| 269 // where YUV planar textures are not renderable by the GPU. | |
| 270 VideoFrameExternalResources | |
| 271 VideoResourceUpdater::CreateRGBTextureForSoftwarePlanes( | |
| 272 const scoped_refptr<media::VideoFrame>& video_frame) { | |
|
dcheng
2016/03/08 18:33:15
Nit: this function doesn't appear to take ownershi
Tobias Sargeant
2016/03/09 11:50:58
Done. Also changed the other private functions so
| |
| 273 DCHECK(media::IsYuvPlanar(video_frame->format())); | |
| 274 | |
| 275 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); | |
| 276 const ResourceFormat resource_format = ResourceFormat::RGBA_8888; | |
| 277 const gfx::Size output_plane_resource_size = video_frame->coded_size(); | |
| 278 const bool is_immutable = false; | |
| 279 | |
| 280 VideoResourceUpdater::ResourceList::iterator resource = | |
| 281 RecycleOrAllocateTexture(output_plane_resource_size, resource_format, | |
| 282 is_immutable); | |
| 283 | |
| 284 ++resource->ref_count; | |
| 285 | |
| 286 size_t bytes_per_row = ResourceUtil::UncheckedWidthInBytes<size_t>( | |
|
dcheng
2016/03/08 18:33:15
Not really related to this CL, but it's hard for m
Tobias Sargeant
2016/03/09 11:50:58
I agree that it is not obvious. This was copying t
| |
| 287 output_plane_resource_size.width(), ResourceFormat::RGBA_8888); | |
| 288 size_t upload_image_stride = | |
| 289 MathUtil::UncheckedRoundUp<size_t>(bytes_per_row, 4u); | |
| 290 size_t needed_size = | |
| 291 upload_image_stride * output_plane_resource_size.height(); | |
| 292 if (upload_pixels_.size() < needed_size) | |
| 293 upload_pixels_.resize(needed_size); | |
| 294 | |
| 295 ResourceProvider::ScopedWriteLockGL lock(resource_provider_, | |
| 296 resource->resource_id); | |
| 297 media::SkCanvasVideoRenderer::ConvertVideoFrameToRGBPixels( | |
| 298 video_frame.get(), &upload_pixels_[0], upload_image_stride); | |
| 299 | |
| 300 resource_provider_->CopyToResource(resource->resource_id, &upload_pixels_[0], | |
| 301 resource->resource_size); | |
| 302 | |
| 303 gpu::SyncToken sync_token; | |
| 304 const uint64_t fence_sync = gl->InsertFenceSyncCHROMIUM(); | |
| 305 gl->ShallowFlushCHROMIUM(); | |
| 306 gl->GenSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); | |
| 307 | |
| 308 VideoFrameExternalResources external_resources; | |
| 309 | |
| 310 external_resources.mailboxes.push_back( | |
| 311 TextureMailbox(resource->mailbox, sync_token, GL_TEXTURE_2D, | |
| 312 video_frame->coded_size(), false)); | |
| 313 external_resources.release_callbacks.push_back( | |
| 314 base::Bind(&RecycleResource, AsWeakPtr(), resource->resource_id)); | |
| 315 external_resources.type = VideoFrameExternalResources::RGBA_RESOURCE; | |
| 316 return external_resources; | |
| 317 } | |
| 318 | |
| 248 VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( | 319 VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( |
| 249 const scoped_refptr<media::VideoFrame>& video_frame) { | 320 const scoped_refptr<media::VideoFrame>& video_frame) { |
| 250 TRACE_EVENT0("cc", "VideoResourceUpdater::CreateForSoftwarePlanes"); | 321 TRACE_EVENT0("cc", "VideoResourceUpdater::CreateForSoftwarePlanes"); |
| 251 const media::VideoPixelFormat input_frame_format = video_frame->format(); | 322 const media::VideoPixelFormat input_frame_format = video_frame->format(); |
| 252 | 323 |
| 253 // TODO(hubbe): Make this a video frame method. | 324 // TODO(hubbe): Make this a video frame method. |
| 254 int bits_per_channel = 0; | 325 int bits_per_channel = 0; |
| 255 switch (input_frame_format) { | 326 switch (input_frame_format) { |
| 256 case media::PIXEL_FORMAT_UNKNOWN: | 327 case media::PIXEL_FORMAT_UNKNOWN: |
| 257 NOTREACHED(); | 328 NOTREACHED(); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 289 if (!media::IsYuvPlanar(input_frame_format)) { | 360 if (!media::IsYuvPlanar(input_frame_format)) { |
| 290 NOTREACHED() << media::VideoPixelFormatToString(input_frame_format); | 361 NOTREACHED() << media::VideoPixelFormatToString(input_frame_format); |
| 291 return VideoFrameExternalResources(); | 362 return VideoFrameExternalResources(); |
| 292 } | 363 } |
| 293 | 364 |
| 294 const bool software_compositor = context_provider_ == NULL; | 365 const bool software_compositor = context_provider_ == NULL; |
| 295 | 366 |
| 296 ResourceFormat output_resource_format = | 367 ResourceFormat output_resource_format = |
| 297 resource_provider_->YuvResourceFormat(bits_per_channel); | 368 resource_provider_->YuvResourceFormat(bits_per_channel); |
| 298 | 369 |
| 370 if (output_resource_format == ResourceFormat::RGBA_8888) { | |
| 371 // YUV frames must be converted to RGB before texture upload. | |
| 372 return CreateRGBTextureForSoftwarePlanes(video_frame); | |
| 373 } | |
| 374 | |
| 299 size_t output_plane_count = media::VideoFrame::NumPlanes(input_frame_format); | 375 size_t output_plane_count = media::VideoFrame::NumPlanes(input_frame_format); |
| 300 | 376 |
| 301 // TODO(skaslev): If we're in software compositing mode, we do the YUV -> RGB | 377 // TODO(skaslev): If we're in software compositing mode, we do the YUV -> RGB |
| 302 // conversion here. That involves an extra copy of each frame to a bitmap. | 378 // conversion here. That involves an extra copy of each frame to a bitmap. |
| 303 // Obviously, this is suboptimal and should be addressed once ubercompositor | 379 // Obviously, this is suboptimal and should be addressed once ubercompositor |
| 304 // starts shaping up. | 380 // starts shaping up. |
| 305 if (software_compositor) { | 381 if (software_compositor) { |
| 306 output_resource_format = kRGBResourceFormat; | 382 output_resource_format = kRGBResourceFormat; |
| 307 output_plane_count = 1; | 383 output_plane_count = 1; |
| 308 } | 384 } |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 551 const scoped_refptr<media::VideoFrame>& video_frame, | 627 const scoped_refptr<media::VideoFrame>& video_frame, |
| 552 const gpu::MailboxHolder& mailbox_holder, | 628 const gpu::MailboxHolder& mailbox_holder, |
| 553 VideoFrameExternalResources* external_resources) { | 629 VideoFrameExternalResources* external_resources) { |
| 554 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); | 630 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); |
| 555 SyncTokenClientImpl client(gl, mailbox_holder.sync_token); | 631 SyncTokenClientImpl client(gl, mailbox_holder.sync_token); |
| 556 | 632 |
| 557 const gfx::Size output_plane_resource_size = video_frame->coded_size(); | 633 const gfx::Size output_plane_resource_size = video_frame->coded_size(); |
| 558 // The copy needs to be a direct transfer of pixel data, so we use an RGBA8 | 634 // The copy needs to be a direct transfer of pixel data, so we use an RGBA8 |
| 559 // target to avoid loss of precision or dropping any alpha component. | 635 // target to avoid loss of precision or dropping any alpha component. |
| 560 const ResourceFormat copy_target_format = ResourceFormat::RGBA_8888; | 636 const ResourceFormat copy_target_format = ResourceFormat::RGBA_8888; |
| 637 const bool is_immutable = false; | |
| 561 | 638 |
| 562 // Search for an existing resource to reuse. | 639 // Search for an existing resource to reuse. |
| 563 VideoResourceUpdater::ResourceList::iterator resource = all_resources_.end(); | 640 ResourceList::iterator resource = RecycleOrAllocateTexture( |
| 564 | 641 output_plane_resource_size, copy_target_format, is_immutable); |
| 565 for (auto it = all_resources_.begin(); it != all_resources_.end(); ++it) { | |
| 566 // Reuse resource if attributes match and the resource is a currently | |
| 567 // unreferenced texture. | |
| 568 if (it->resource_size == output_plane_resource_size && | |
| 569 it->resource_format == copy_target_format && !it->mailbox.IsZero() && | |
| 570 it->ref_count == 0 && | |
| 571 resource_provider_->GetTextureHint(it->resource_id) != | |
| 572 ResourceProvider::TEXTURE_HINT_IMMUTABLE) { | |
| 573 resource = it; | |
| 574 break; | |
| 575 } | |
| 576 } | |
| 577 | |
| 578 // Otherwise allocate a new resource. | |
| 579 if (resource == all_resources_.end()) { | |
| 580 const bool is_immutable = false; | |
| 581 resource = AllocateResource(output_plane_resource_size, copy_target_format, | |
| 582 true, is_immutable); | |
| 583 } | |
| 584 | 642 |
| 585 ++resource->ref_count; | 643 ++resource->ref_count; |
| 586 | 644 |
| 587 ResourceProvider::ScopedWriteLockGL lock(resource_provider_, | 645 ResourceProvider::ScopedWriteLockGL lock(resource_provider_, |
| 588 resource->resource_id); | 646 resource->resource_id); |
| 589 uint32_t texture_id = lock.texture_id(); | 647 uint32_t texture_id = lock.texture_id(); |
| 590 | 648 |
| 591 DCHECK_EQ(resource_provider_->GetResourceTextureTarget(resource->resource_id), | 649 DCHECK_EQ(resource_provider_->GetResourceTextureTarget(resource->resource_id), |
| 592 (GLenum)GL_TEXTURE_2D); | 650 (GLenum)GL_TEXTURE_2D); |
| 593 | 651 |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 687 resource_it->ref_count = 0; | 745 resource_it->ref_count = 0; |
| 688 updater->DeleteResource(resource_it); | 746 updater->DeleteResource(resource_it); |
| 689 return; | 747 return; |
| 690 } | 748 } |
| 691 | 749 |
| 692 --resource_it->ref_count; | 750 --resource_it->ref_count; |
| 693 DCHECK_GE(resource_it->ref_count, 0); | 751 DCHECK_GE(resource_it->ref_count, 0); |
| 694 } | 752 } |
| 695 | 753 |
| 696 } // namespace cc | 754 } // namespace cc |
| OLD | NEW |