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 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 166 : context_provider_(context_provider), | 166 : context_provider_(context_provider), |
| 167 resource_provider_(resource_provider) { | 167 resource_provider_(resource_provider) { |
| 168 } | 168 } |
| 169 | 169 |
| 170 VideoResourceUpdater::~VideoResourceUpdater() { | 170 VideoResourceUpdater::~VideoResourceUpdater() { |
| 171 for (const PlaneResource& plane_resource : all_resources_) | 171 for (const PlaneResource& plane_resource : all_resources_) |
| 172 resource_provider_->DeleteResource(plane_resource.resource_id()); | 172 resource_provider_->DeleteResource(plane_resource.resource_id()); |
| 173 } | 173 } |
| 174 | 174 |
| 175 VideoResourceUpdater::ResourceList::iterator | 175 VideoResourceUpdater::ResourceList::iterator |
| 176 VideoResourceUpdater::RecycleOrAllocateResource( | |
| 177 const gfx::Size& resource_size, | |
| 178 ResourceFormat resource_format, | |
| 179 const gfx::ColorSpace& color_space, | |
| 180 bool software_resource, | |
| 181 bool immutable_hint, | |
| 182 int unique_id, | |
| 183 int plane_index) { | |
| 184 if (unique_id >= 0 && plane_index >= 0) { | |
|
danakj
2016/09/02 22:58:15
i dont think we should bake in assumptions about t
Tobias Sargeant
2016/09/12 14:25:25
Done. Went with checking only the plane index for
| |
| 185 for (auto it = all_resources_.begin(); it != all_resources_.end(); ++it) { | |
| 186 if (it->Matches(unique_id, plane_index)) { | |
| 187 DCHECK(it->resource_size() == resource_size); | |
| 188 DCHECK(it->resource_format() == resource_format); | |
| 189 DCHECK(it->mailbox().IsZero() == software_resource); | |
| 190 return it; | |
| 191 } | |
| 192 } | |
| 193 } | |
| 194 for (auto it = all_resources_.begin(); it != all_resources_.end(); ++it) { | |
|
danakj
2016/09/02 22:58:15
I kinda feel like it was a bit more clear when thi
Tobias Sargeant
2016/09/12 14:25:25
The original loop was subtle, in that it returned
| |
| 195 if (it->resource_size() == resource_size && | |
| 196 it->resource_format() == resource_format && | |
| 197 it->mailbox().IsZero() == software_resource && !it->has_refs()) { | |
| 198 if (software_resource) { | |
| 199 // This extra check is needed because resources backed by SharedMemory | |
| 200 // are not ref-counted, unlike mailboxes. Full discussion in | |
| 201 // codereview.chromium.org/145273021. | |
| 202 if (!resource_provider_->InUseByConsumer(it->resource_id())) | |
| 203 return it; | |
| 204 } else { | |
| 205 if (immutable_hint == | |
|
danakj
2016/09/02 22:58:15
Can you make this an else if () { instead of else
Tobias Sargeant
2016/09/12 14:25:25
Done.
| |
| 206 (resource_provider_->GetTextureHint(it->resource_id()) == | |
| 207 ResourceProvider::TEXTURE_HINT_IMMUTABLE)) | |
| 208 return it; | |
| 209 } | |
| 210 } | |
| 211 } | |
| 212 | |
| 213 // Otherwise allocate a new resource. | |
| 214 return AllocateResource(resource_size, resource_format, color_space, | |
| 215 !software_resource, immutable_hint); | |
| 216 } | |
| 217 | |
| 218 VideoResourceUpdater::ResourceList::iterator | |
| 176 VideoResourceUpdater::AllocateResource(const gfx::Size& plane_size, | 219 VideoResourceUpdater::AllocateResource(const gfx::Size& plane_size, |
| 177 ResourceFormat format, | 220 ResourceFormat format, |
| 178 const gfx::ColorSpace& color_space, | 221 const gfx::ColorSpace& color_space, |
| 179 bool has_mailbox, | 222 bool has_mailbox, |
| 180 bool immutable_hint) { | 223 bool immutable_hint) { |
| 181 // TODO(danakj): Abstract out hw/sw resource create/delete from | 224 // TODO(danakj): Abstract out hw/sw resource create/delete from |
| 182 // ResourceProvider and stop using ResourceProvider in this class. | 225 // ResourceProvider and stop using ResourceProvider in this class. |
| 183 const ResourceId resource_id = resource_provider_->CreateResource( | 226 const ResourceId resource_id = resource_provider_->CreateResource( |
| 184 plane_size, immutable_hint ? ResourceProvider::TEXTURE_HINT_IMMUTABLE | 227 plane_size, immutable_hint ? ResourceProvider::TEXTURE_HINT_IMMUTABLE |
| 185 : ResourceProvider::TEXTURE_HINT_DEFAULT, | 228 : ResourceProvider::TEXTURE_HINT_DEFAULT, |
| 186 format, color_space); | 229 format, color_space); |
| 187 if (resource_id == 0) | 230 if (resource_id == 0) |
|
danakj
2016/09/02 22:58:15
Maybe it used to? But CreateResource() can't retur
Tobias Sargeant
2016/09/12 14:25:25
Cleaned this up.
| |
| 188 return all_resources_.end(); | 231 return all_resources_.end(); |
| 189 | 232 |
| 190 gpu::Mailbox mailbox; | 233 gpu::Mailbox mailbox; |
| 191 if (has_mailbox) { | 234 if (has_mailbox) { |
| 192 DCHECK(context_provider_); | 235 DCHECK(context_provider_); |
| 193 | 236 |
| 194 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); | 237 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); |
| 195 | 238 |
| 196 gl->GenMailboxCHROMIUM(mailbox.name); | 239 gl->GenMailboxCHROMIUM(mailbox.name); |
| 197 ResourceProvider::ScopedWriteLockGL lock(resource_provider_, resource_id, | 240 ResourceProvider::ScopedWriteLockGL lock(resource_provider_, resource_id, |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 291 if (!media::IsYuvPlanar(input_frame_format)) { | 334 if (!media::IsYuvPlanar(input_frame_format)) { |
| 292 NOTREACHED() << media::VideoPixelFormatToString(input_frame_format); | 335 NOTREACHED() << media::VideoPixelFormatToString(input_frame_format); |
| 293 return VideoFrameExternalResources(); | 336 return VideoFrameExternalResources(); |
| 294 } | 337 } |
| 295 | 338 |
| 296 const bool software_compositor = context_provider_ == NULL; | 339 const bool software_compositor = context_provider_ == NULL; |
| 297 | 340 |
| 298 ResourceFormat output_resource_format = | 341 ResourceFormat output_resource_format = |
| 299 resource_provider_->YuvResourceFormat(bits_per_channel); | 342 resource_provider_->YuvResourceFormat(bits_per_channel); |
| 300 | 343 |
| 344 // If GPU compositing is enabled, but the output resource format | |
| 345 // returned by the resource provider is RGBA_8888, then a GPU driver | |
| 346 // bug workaround requires that YUV frames must be converted to RGB | |
| 347 // before texture upload. | |
| 348 bool texture_needs_rgb_conversion = | |
| 349 !software_compositor && | |
| 350 output_resource_format == ResourceFormat::RGBA_8888; | |
| 301 size_t output_plane_count = media::VideoFrame::NumPlanes(input_frame_format); | 351 size_t output_plane_count = media::VideoFrame::NumPlanes(input_frame_format); |
| 302 | 352 |
| 303 // TODO(skaslev): If we're in software compositing mode, we do the YUV -> RGB | 353 // TODO(skaslev): If we're in software compositing mode, we do the YUV -> RGB |
| 304 // conversion here. That involves an extra copy of each frame to a bitmap. | 354 // conversion here. That involves an extra copy of each frame to a bitmap. |
| 305 // Obviously, this is suboptimal and should be addressed once ubercompositor | 355 // Obviously, this is suboptimal and should be addressed once ubercompositor |
| 306 // starts shaping up. | 356 // starts shaping up. |
| 307 if (software_compositor) { | 357 if (software_compositor || texture_needs_rgb_conversion) { |
| 308 output_resource_format = kRGBResourceFormat; | 358 output_resource_format = kRGBResourceFormat; |
| 309 output_plane_count = 1; | 359 output_plane_count = 1; |
| 360 bits_per_channel = 8; | |
| 310 } | 361 } |
| 311 | 362 |
| 312 // Drop recycled resources that are the wrong format. | 363 // Drop recycled resources that are the wrong format. |
| 313 for (auto it = all_resources_.begin(); it != all_resources_.end();) { | 364 for (auto it = all_resources_.begin(); it != all_resources_.end();) { |
| 314 if (!it->has_refs() && it->resource_format() != output_resource_format) | 365 if (!it->has_refs() && it->resource_format() != output_resource_format) |
| 315 DeleteResource(it++); | 366 DeleteResource(it++); |
| 316 else | 367 else |
| 317 ++it; | 368 ++it; |
| 318 } | 369 } |
| 319 | 370 |
| 320 const int max_resource_size = resource_provider_->max_texture_size(); | 371 const int max_resource_size = resource_provider_->max_texture_size(); |
| 321 std::vector<ResourceList::iterator> plane_resources; | 372 std::vector<ResourceList::iterator> plane_resources; |
| 322 for (size_t i = 0; i < output_plane_count; ++i) { | 373 for (size_t i = 0; i < output_plane_count; ++i) { |
| 323 gfx::Size output_plane_resource_size = | 374 gfx::Size output_plane_resource_size = |
| 324 SoftwarePlaneDimension(video_frame.get(), software_compositor, i); | 375 SoftwarePlaneDimension(video_frame.get(), software_compositor, i); |
| 325 if (output_plane_resource_size.IsEmpty() || | 376 if (output_plane_resource_size.IsEmpty() || |
| 326 output_plane_resource_size.width() > max_resource_size || | 377 output_plane_resource_size.width() > max_resource_size || |
| 327 output_plane_resource_size.height() > max_resource_size) { | 378 output_plane_resource_size.height() > max_resource_size) { |
| 328 break; | 379 break; |
| 329 } | 380 } |
| 330 | 381 |
| 331 // Try recycle a previously-allocated resource. | 382 const bool is_immutable = true; |
| 332 ResourceList::iterator resource_it = all_resources_.end(); | 383 ResourceList::iterator resource_it = RecycleOrAllocateResource( |
| 333 for (auto it = all_resources_.begin(); it != all_resources_.end(); ++it) { | 384 output_plane_resource_size, output_resource_format, |
| 334 if (it->resource_size() == output_plane_resource_size && | 385 video_frame->ColorSpace(), software_compositor, is_immutable, |
| 335 it->resource_format() == output_resource_format) { | 386 video_frame->unique_id(), i); |
| 336 if (it->Matches(video_frame->unique_id(), i)) { | |
| 337 // Bingo, we found a resource that already contains the data we are | |
| 338 // planning to put in it. It's safe to reuse it even if | |
| 339 // resource_provider_ holds some references to it, because those | |
| 340 // references are read-only. | |
| 341 resource_it = it; | |
| 342 break; | |
| 343 } | |
| 344 | 387 |
| 345 // This extra check is needed because resources backed by SharedMemory | |
| 346 // are not ref-counted, unlike mailboxes. Full discussion in | |
| 347 // codereview.chromium.org/145273021. | |
| 348 const bool in_use = | |
| 349 software_compositor && | |
| 350 resource_provider_->InUseByConsumer(it->resource_id()); | |
| 351 if (!it->has_refs() && !in_use) { | |
| 352 // We found a resource with the correct size that we can overwrite. | |
| 353 resource_it = it; | |
| 354 } | |
| 355 } | |
| 356 } | |
| 357 | |
| 358 // Check if we need to allocate a new resource. | |
| 359 if (resource_it == all_resources_.end()) { | |
| 360 const bool is_immutable = true; | |
| 361 resource_it = AllocateResource( | |
| 362 output_plane_resource_size, output_resource_format, | |
| 363 video_frame->ColorSpace(), !software_compositor, is_immutable); | |
| 364 } | |
| 365 if (resource_it == all_resources_.end()) | 388 if (resource_it == all_resources_.end()) |
| 366 break; | 389 break; |
| 367 | 390 |
| 368 resource_it->add_ref(); | 391 resource_it->add_ref(); |
| 369 plane_resources.push_back(resource_it); | 392 plane_resources.push_back(resource_it); |
| 370 } | 393 } |
| 371 | 394 |
| 372 if (plane_resources.size() != output_plane_count) { | 395 if (plane_resources.size() != output_plane_count) { |
| 373 // Allocation failed, nothing will be returned so restore reference counts. | 396 // Allocation failed, nothing will be returned so restore reference counts. |
| 374 for (ResourceList::iterator resource_it : plane_resources) | 397 for (ResourceList::iterator resource_it : plane_resources) |
| 375 resource_it->remove_ref(); | 398 resource_it->remove_ref(); |
| 376 return VideoFrameExternalResources(); | 399 return VideoFrameExternalResources(); |
| 377 } | 400 } |
| 378 | 401 |
| 379 VideoFrameExternalResources external_resources; | 402 VideoFrameExternalResources external_resources; |
| 380 | 403 |
| 381 external_resources.bits_per_channel = bits_per_channel; | 404 external_resources.bits_per_channel = bits_per_channel; |
| 382 | 405 |
| 383 if (software_compositor) { | 406 if (software_compositor || texture_needs_rgb_conversion) { |
| 384 DCHECK_EQ(plane_resources.size(), 1u); | 407 DCHECK_EQ(plane_resources.size(), 1u); |
| 385 PlaneResource& plane_resource = *plane_resources[0]; | 408 PlaneResource& plane_resource = *plane_resources[0]; |
| 386 DCHECK_EQ(plane_resource.resource_format(), kRGBResourceFormat); | 409 DCHECK_EQ(plane_resource.resource_format(), kRGBResourceFormat); |
| 387 DCHECK(plane_resource.mailbox().IsZero()); | 410 DCHECK_EQ(software_compositor, plane_resource.mailbox().IsZero()); |
| 388 | 411 |
| 389 if (!plane_resource.Matches(video_frame->unique_id(), 0)) { | 412 if (!plane_resource.Matches(video_frame->unique_id(), 0)) { |
| 390 // We need to transfer data from |video_frame| to the plane resource. | 413 // We need to transfer data from |video_frame| to the plane resource. |
| 391 if (!video_renderer_) | 414 if (software_compositor) { |
| 392 video_renderer_.reset(new media::SkCanvasVideoRenderer); | 415 if (!video_renderer_) |
| 416 video_renderer_.reset(new media::SkCanvasVideoRenderer); | |
| 393 | 417 |
| 394 ResourceProvider::ScopedWriteLockSoftware lock( | 418 ResourceProvider::ScopedWriteLockSoftware lock( |
| 395 resource_provider_, plane_resource.resource_id()); | 419 resource_provider_, plane_resource.resource_id()); |
| 396 SkCanvas canvas(lock.sk_bitmap()); | 420 SkCanvas canvas(lock.sk_bitmap()); |
| 397 // This is software path, so canvas and video_frame are always backed | 421 // This is software path, so canvas and video_frame are always backed |
| 398 // by software. | 422 // by software. |
| 399 video_renderer_->Copy(video_frame, &canvas, media::Context3D()); | 423 video_renderer_->Copy(video_frame, &canvas, media::Context3D()); |
| 424 } else { | |
| 425 size_t bytes_per_row = ResourceUtil::CheckedWidthInBytes<size_t>( | |
| 426 video_frame->coded_size().width(), ResourceFormat::RGBA_8888); | |
| 427 size_t needed_size = bytes_per_row * video_frame->coded_size().height(); | |
| 428 if (upload_pixels_.size() < needed_size) | |
| 429 upload_pixels_.resize(needed_size); | |
| 430 | |
| 431 media::SkCanvasVideoRenderer::ConvertVideoFrameToRGBPixels( | |
| 432 video_frame.get(), &upload_pixels_[0], bytes_per_row); | |
| 433 | |
| 434 resource_provider_->CopyToResource(plane_resource.resource_id(), | |
| 435 &upload_pixels_[0], | |
| 436 plane_resource.resource_size()); | |
| 437 } | |
| 400 plane_resource.SetUniqueId(video_frame->unique_id(), 0); | 438 plane_resource.SetUniqueId(video_frame->unique_id(), 0); |
| 401 } | 439 } |
| 402 | 440 |
| 403 external_resources.software_resources.push_back( | 441 if (software_compositor) { |
| 404 plane_resource.resource_id()); | 442 external_resources.software_resources.push_back( |
| 405 external_resources.software_release_callback = | 443 plane_resource.resource_id()); |
| 406 base::Bind(&RecycleResource, AsWeakPtr(), plane_resource.resource_id()); | 444 external_resources.software_release_callback = base::Bind( |
| 407 external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE; | 445 &RecycleResource, AsWeakPtr(), plane_resource.resource_id()); |
| 446 external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE; | |
| 447 } else { | |
| 448 TextureMailbox mailbox(plane_resource.mailbox(), gpu::SyncToken(), | |
| 449 resource_provider_->GetResourceTextureTarget( | |
| 450 plane_resource.resource_id())); | |
| 451 mailbox.set_color_space(video_frame->ColorSpace()); | |
| 452 external_resources.mailboxes.push_back(mailbox); | |
| 453 external_resources.release_callbacks.push_back(base::Bind( | |
| 454 &RecycleResource, AsWeakPtr(), plane_resource.resource_id())); | |
| 455 external_resources.type = VideoFrameExternalResources::RGBA_RESOURCE; | |
| 456 } | |
| 408 return external_resources; | 457 return external_resources; |
| 409 } | 458 } |
| 410 | 459 |
| 411 for (size_t i = 0; i < plane_resources.size(); ++i) { | 460 for (size_t i = 0; i < plane_resources.size(); ++i) { |
| 412 PlaneResource& plane_resource = *plane_resources[i]; | 461 PlaneResource& plane_resource = *plane_resources[i]; |
| 413 // Update each plane's resource id with its content. | 462 // Update each plane's resource id with its content. |
| 414 DCHECK_EQ(plane_resource.resource_format(), | 463 DCHECK_EQ(plane_resource.resource_format(), |
| 415 resource_provider_->YuvResourceFormat(bits_per_channel)); | 464 resource_provider_->YuvResourceFormat(bits_per_channel)); |
| 416 | 465 |
| 417 if (!plane_resource.Matches(video_frame->unique_id(), i)) { | 466 if (!plane_resource.Matches(video_frame->unique_id(), i)) { |
| 418 // We need to transfer data from |video_frame| to the plane resource. | 467 // We need to transfer data from |video_frame| to the plane resource. |
| 419 // TODO(reveman): Can use GpuMemoryBuffers here to improve performance. | 468 // TODO(reveman): Can use GpuMemoryBuffers here to improve performance. |
| 420 | 469 |
| 421 // The |resource_size_pixels| is the size of the resource we want to | 470 // The |resource_size_pixels| is the size of the resource we want to |
| 422 // upload to. | 471 // upload to. |
| 423 gfx::Size resource_size_pixels = plane_resource.resource_size(); | 472 gfx::Size resource_size_pixels = plane_resource.resource_size(); |
| 424 // The |video_stride_bytes| is the width of the video frame we are | 473 // The |video_stride_bytes| is the width of the video frame we are |
| 425 // uploading (including non-frame data to fill in the stride). | 474 // uploading (including non-frame data to fill in the stride). |
| 426 int video_stride_bytes = video_frame->stride(i); | 475 int video_stride_bytes = video_frame->stride(i); |
| 427 | 476 |
| 428 size_t bytes_per_row = ResourceUtil::UncheckedWidthInBytes<size_t>( | 477 size_t bytes_per_row = ResourceUtil::CheckedWidthInBytes<size_t>( |
| 429 resource_size_pixels.width(), plane_resource.resource_format()); | 478 resource_size_pixels.width(), plane_resource.resource_format()); |
| 430 // Use 4-byte row alignment (OpenGL default) for upload performance. | 479 // Use 4-byte row alignment (OpenGL default) for upload performance. |
| 431 // Assuming that GL_UNPACK_ALIGNMENT has not changed from default. | 480 // Assuming that GL_UNPACK_ALIGNMENT has not changed from default. |
| 432 size_t upload_image_stride = | 481 size_t upload_image_stride = |
| 433 MathUtil::UncheckedRoundUp<size_t>(bytes_per_row, 4u); | 482 MathUtil::CheckedRoundUp<size_t>(bytes_per_row, 4u); |
| 434 | 483 |
| 435 bool needs_conversion = false; | 484 bool needs_conversion = false; |
| 436 int shift = 0; | 485 int shift = 0; |
| 437 | 486 |
| 438 // LUMINANCE_F16 uses half-floats, so we always need a conversion step. | 487 // LUMINANCE_F16 uses half-floats, so we always need a conversion step. |
| 439 if (plane_resource.resource_format() == LUMINANCE_F16) { | 488 if (plane_resource.resource_format() == LUMINANCE_F16) { |
| 440 needs_conversion = true; | 489 needs_conversion = true; |
| 441 // Note that the current method of converting integers to half-floats | 490 // Note that the current method of converting integers to half-floats |
| 442 // stops working if you have more than 10 bits of data. | 491 // stops working if you have more than 10 bits of data. |
| 443 DCHECK_LE(bits_per_channel, 10); | 492 DCHECK_LE(bits_per_channel, 10); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 546 // Update the release sync point in |video_frame| with |sync_token| | 595 // Update the release sync point in |video_frame| with |sync_token| |
| 547 // returned by the compositor and emit a WaitSyncTokenCHROMIUM on | 596 // returned by the compositor and emit a WaitSyncTokenCHROMIUM on |
| 548 // |video_frame|'s previous sync point using the current GL context. | 597 // |video_frame|'s previous sync point using the current GL context. |
| 549 SyncTokenClientImpl client(updater->context_provider_->ContextGL(), | 598 SyncTokenClientImpl client(updater->context_provider_->ContextGL(), |
| 550 sync_token); | 599 sync_token); |
| 551 video_frame->UpdateReleaseSyncToken(&client); | 600 video_frame->UpdateReleaseSyncToken(&client); |
| 552 } | 601 } |
| 553 | 602 |
| 554 // Create a copy of a texture-backed source video frame in a new GL_TEXTURE_2D | 603 // Create a copy of a texture-backed source video frame in a new GL_TEXTURE_2D |
| 555 // texture. | 604 // texture. |
| 556 void VideoResourceUpdater::CopyPlaneTexture( | 605 bool VideoResourceUpdater::CopyPlaneTexture( |
| 557 media::VideoFrame* video_frame, | 606 media::VideoFrame* video_frame, |
| 558 const gpu::MailboxHolder& mailbox_holder, | 607 const gpu::MailboxHolder& mailbox_holder, |
| 559 VideoFrameExternalResources* external_resources) { | 608 VideoFrameExternalResources* external_resources) { |
| 560 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); | 609 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); |
| 561 SyncTokenClientImpl client(gl, mailbox_holder.sync_token); | 610 SyncTokenClientImpl client(gl, mailbox_holder.sync_token); |
| 562 | 611 |
| 563 const gfx::Size output_plane_resource_size = video_frame->coded_size(); | 612 const gfx::Size output_plane_resource_size = video_frame->coded_size(); |
| 564 // The copy needs to be a direct transfer of pixel data, so we use an RGBA8 | 613 // The copy needs to be a direct transfer of pixel data, so we use an RGBA8 |
| 565 // target to avoid loss of precision or dropping any alpha component. | 614 // target to avoid loss of precision or dropping any alpha component. |
| 566 const ResourceFormat copy_target_format = ResourceFormat::RGBA_8888; | 615 const ResourceFormat copy_target_format = ResourceFormat::RGBA_8888; |
| 567 | 616 |
| 568 // Search for an existing resource to reuse. | 617 const bool is_immutable = false; |
| 569 VideoResourceUpdater::ResourceList::iterator resource = all_resources_.end(); | 618 VideoResourceUpdater::ResourceList::iterator resource = |
| 570 | 619 RecycleOrAllocateResource(output_plane_resource_size, copy_target_format, |
| 571 for (auto it = all_resources_.begin(); it != all_resources_.end(); ++it) { | 620 video_frame->ColorSpace(), false, is_immutable, |
| 572 // Reuse resource if attributes match and the resource is a currently | 621 -1, |
|
danakj
2016/09/02 22:58:15
can you use temp vars to give these litarals names
Tobias Sargeant
2016/09/12 14:25:25
Done.
| |
| 573 // unreferenced texture. | 622 -1 /* do not recycle referenced textures */); |
| 574 if (it->resource_size() == output_plane_resource_size && | |
| 575 it->resource_format() == copy_target_format && | |
| 576 !it->mailbox().IsZero() && !it->has_refs() && | |
| 577 resource_provider_->GetTextureHint(it->resource_id()) != | |
| 578 ResourceProvider::TEXTURE_HINT_IMMUTABLE) { | |
| 579 resource = it; | |
| 580 break; | |
| 581 } | |
| 582 } | |
| 583 | |
| 584 // Otherwise allocate a new resource. | |
| 585 if (resource == all_resources_.end()) { | 623 if (resource == all_resources_.end()) { |
| 586 const bool is_immutable = false; | 624 return false; |
| 587 resource = AllocateResource(output_plane_resource_size, copy_target_format, | |
| 588 video_frame->ColorSpace(), true, is_immutable); | |
| 589 } | 625 } |
| 590 | 626 |
| 591 resource->add_ref(); | 627 resource->add_ref(); |
| 592 | 628 |
| 593 ResourceProvider::ScopedWriteLockGL lock(resource_provider_, | 629 ResourceProvider::ScopedWriteLockGL lock(resource_provider_, |
| 594 resource->resource_id(), false); | 630 resource->resource_id(), false); |
| 595 DCHECK_EQ( | 631 DCHECK_EQ( |
| 596 resource_provider_->GetResourceTextureTarget(resource->resource_id()), | 632 resource_provider_->GetResourceTextureTarget(resource->resource_id()), |
| 597 (GLenum)GL_TEXTURE_2D); | 633 (GLenum)GL_TEXTURE_2D); |
| 598 | 634 |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 614 // Done with the source video frame texture at this point. | 650 // Done with the source video frame texture at this point. |
| 615 video_frame->UpdateReleaseSyncToken(&client); | 651 video_frame->UpdateReleaseSyncToken(&client); |
| 616 | 652 |
| 617 TextureMailbox mailbox(resource->mailbox(), sync_token, GL_TEXTURE_2D, | 653 TextureMailbox mailbox(resource->mailbox(), sync_token, GL_TEXTURE_2D, |
| 618 video_frame->coded_size(), false, false); | 654 video_frame->coded_size(), false, false); |
| 619 mailbox.set_color_space(video_frame->ColorSpace()); | 655 mailbox.set_color_space(video_frame->ColorSpace()); |
| 620 external_resources->mailboxes.push_back(mailbox); | 656 external_resources->mailboxes.push_back(mailbox); |
| 621 | 657 |
| 622 external_resources->release_callbacks.push_back( | 658 external_resources->release_callbacks.push_back( |
| 623 base::Bind(&RecycleResource, AsWeakPtr(), resource->resource_id())); | 659 base::Bind(&RecycleResource, AsWeakPtr(), resource->resource_id())); |
| 660 | |
| 661 return true; | |
| 624 } | 662 } |
| 625 | 663 |
| 626 VideoFrameExternalResources VideoResourceUpdater::CreateForHardwarePlanes( | 664 VideoFrameExternalResources VideoResourceUpdater::CreateForHardwarePlanes( |
| 627 scoped_refptr<media::VideoFrame> video_frame) { | 665 scoped_refptr<media::VideoFrame> video_frame) { |
| 628 TRACE_EVENT0("cc", "VideoResourceUpdater::CreateForHardwarePlanes"); | 666 TRACE_EVENT0("cc", "VideoResourceUpdater::CreateForHardwarePlanes"); |
| 629 DCHECK(video_frame->HasTextures()); | 667 DCHECK(video_frame->HasTextures()); |
| 630 if (!context_provider_) | 668 if (!context_provider_) |
| 631 return VideoFrameExternalResources(); | 669 return VideoFrameExternalResources(); |
| 632 | 670 |
| 633 VideoFrameExternalResources external_resources; | 671 VideoFrameExternalResources external_resources; |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 644 } | 682 } |
| 645 | 683 |
| 646 const size_t num_planes = media::VideoFrame::NumPlanes(video_frame->format()); | 684 const size_t num_planes = media::VideoFrame::NumPlanes(video_frame->format()); |
| 647 for (size_t i = 0; i < num_planes; ++i) { | 685 for (size_t i = 0; i < num_planes; ++i) { |
| 648 const gpu::MailboxHolder& mailbox_holder = video_frame->mailbox_holder(i); | 686 const gpu::MailboxHolder& mailbox_holder = video_frame->mailbox_holder(i); |
| 649 if (mailbox_holder.mailbox.IsZero()) | 687 if (mailbox_holder.mailbox.IsZero()) |
| 650 break; | 688 break; |
| 651 | 689 |
| 652 if (video_frame->metadata()->IsTrue( | 690 if (video_frame->metadata()->IsTrue( |
| 653 media::VideoFrameMetadata::COPY_REQUIRED)) { | 691 media::VideoFrameMetadata::COPY_REQUIRED)) { |
| 654 CopyPlaneTexture(video_frame.get(), mailbox_holder, &external_resources); | 692 if (!CopyPlaneTexture(video_frame.get(), mailbox_holder, |
| 693 &external_resources)) { | |
| 694 return VideoFrameExternalResources(); | |
| 695 } | |
| 655 } else { | 696 } else { |
| 656 TextureMailbox mailbox(mailbox_holder.mailbox, mailbox_holder.sync_token, | 697 TextureMailbox mailbox(mailbox_holder.mailbox, mailbox_holder.sync_token, |
| 657 mailbox_holder.texture_target, | 698 mailbox_holder.texture_target, |
| 658 video_frame->coded_size(), | 699 video_frame->coded_size(), |
| 659 video_frame->metadata()->IsTrue( | 700 video_frame->metadata()->IsTrue( |
| 660 media::VideoFrameMetadata::ALLOW_OVERLAY), | 701 media::VideoFrameMetadata::ALLOW_OVERLAY), |
| 661 false); | 702 false); |
| 662 mailbox.set_color_space(video_frame->ColorSpace()); | 703 mailbox.set_color_space(video_frame->ColorSpace()); |
| 663 external_resources.mailboxes.push_back(mailbox); | 704 external_resources.mailboxes.push_back(mailbox); |
| 664 external_resources.release_callbacks.push_back( | 705 external_resources.release_callbacks.push_back( |
| 665 base::Bind(&ReturnTexture, AsWeakPtr(), video_frame)); | 706 base::Bind(&ReturnTexture, AsWeakPtr(), video_frame)); |
| 666 } | 707 } |
| 667 } | 708 } |
| 668 return external_resources; | 709 return external_resources; |
| 669 } | 710 } |
| 670 | 711 |
| 671 // static | 712 // static |
| 672 void VideoResourceUpdater::RecycleResource( | 713 void VideoResourceUpdater::RecycleResource( |
| 673 base::WeakPtr<VideoResourceUpdater> updater, | 714 base::WeakPtr<VideoResourceUpdater> updater, |
| 674 ResourceId resource_id, | 715 ResourceId resource_id, |
| 675 const gpu::SyncToken& sync_token, | 716 const gpu::SyncToken& sync_token, |
| 676 bool lost_resource, | 717 bool lost_resource, |
| 677 BlockingTaskRunner* main_thread_task_runner) { | 718 BlockingTaskRunner* main_thread_task_runner) { |
| 678 if (!updater.get()) { | 719 if (!updater.get()) { |
| 679 // Resource was already deleted. | 720 // Resource was already deleted. |
| 680 return; | 721 return; |
| 681 } | 722 } |
| 682 | |
| 683 const ResourceList::iterator resource_it = std::find_if( | 723 const ResourceList::iterator resource_it = std::find_if( |
| 684 updater->all_resources_.begin(), updater->all_resources_.end(), | 724 updater->all_resources_.begin(), updater->all_resources_.end(), |
| 685 [resource_id](const PlaneResource& plane_resource) { | 725 [resource_id](const PlaneResource& plane_resource) { |
| 686 return plane_resource.resource_id() == resource_id; | 726 return plane_resource.resource_id() == resource_id; |
| 687 }); | 727 }); |
| 688 if (resource_it == updater->all_resources_.end()) | 728 if (resource_it == updater->all_resources_.end()) |
| 689 return; | 729 return; |
| 690 | 730 |
| 691 ContextProvider* context_provider = updater->context_provider_; | 731 ContextProvider* context_provider = updater->context_provider_; |
| 692 if (context_provider && sync_token.HasData()) { | 732 if (context_provider && sync_token.HasData()) { |
| 693 context_provider->ContextGL()->WaitSyncTokenCHROMIUM( | 733 context_provider->ContextGL()->WaitSyncTokenCHROMIUM( |
| 694 sync_token.GetConstData()); | 734 sync_token.GetConstData()); |
| 695 } | 735 } |
| 696 | 736 |
| 697 if (lost_resource) { | 737 if (lost_resource) { |
| 698 resource_it->clear_refs(); | 738 resource_it->clear_refs(); |
| 699 updater->DeleteResource(resource_it); | 739 updater->DeleteResource(resource_it); |
| 700 return; | 740 return; |
| 701 } | 741 } |
| 702 | 742 |
| 703 resource_it->remove_ref(); | 743 resource_it->remove_ref(); |
| 704 } | 744 } |
| 705 | 745 |
| 706 } // namespace cc | 746 } // namespace cc |
| OLD | NEW |