vaapi_picture_native_pixmap_ozone.cc 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "media/gpu/vaapi/vaapi_picture_native_pixmap_ozone.h"
  5. #include "media/base/format_utils.h"
  6. #include "media/gpu/buffer_validation.h"
  7. #include "media/gpu/chromeos/platform_video_frame_utils.h"
  8. #include "media/gpu/macros.h"
  9. #include "media/gpu/vaapi/va_surface.h"
  10. #include "media/gpu/vaapi/vaapi_status.h"
  11. #include "media/gpu/vaapi/vaapi_wrapper.h"
  12. #include "ui/gfx/gpu_memory_buffer.h"
  13. #include "ui/gfx/linux/native_pixmap_dmabuf.h"
  14. #include "ui/gfx/native_pixmap.h"
  15. #include "ui/gl/gl_bindings.h"
  16. #include "ui/gl/gl_image_native_pixmap.h"
  17. #include "ui/gl/scoped_binders.h"
  18. #include "ui/ozone/public/ozone_platform.h"
  19. #include "ui/ozone/public/surface_factory_ozone.h"
  20. namespace media {
  21. VaapiPictureNativePixmapOzone::VaapiPictureNativePixmapOzone(
  22. scoped_refptr<VaapiWrapper> vaapi_wrapper,
  23. const MakeGLContextCurrentCallback& make_context_current_cb,
  24. const BindGLImageCallback& bind_image_cb,
  25. int32_t picture_buffer_id,
  26. const gfx::Size& size,
  27. const gfx::Size& visible_size,
  28. uint32_t texture_id,
  29. uint32_t client_texture_id,
  30. uint32_t texture_target)
  31. : VaapiPictureNativePixmap(std::move(vaapi_wrapper),
  32. make_context_current_cb,
  33. bind_image_cb,
  34. picture_buffer_id,
  35. size,
  36. visible_size,
  37. texture_id,
  38. client_texture_id,
  39. texture_target) {
  40. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  41. // Either |texture_id| and |client_texture_id| are both zero, or not.
  42. DCHECK((texture_id == 0 && client_texture_id == 0) ||
  43. (texture_id != 0 && client_texture_id != 0));
  44. }
  45. VaapiPictureNativePixmapOzone::~VaapiPictureNativePixmapOzone() {
  46. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  47. if (gl_image_ && make_context_current_cb_.Run()) {
  48. gl_image_->ReleaseTexImage(texture_target_);
  49. DCHECK_EQ(glGetError(), static_cast<GLenum>(GL_NO_ERROR));
  50. }
  51. }
  52. VaapiStatus VaapiPictureNativePixmapOzone::Initialize(
  53. scoped_refptr<gfx::NativePixmap> pixmap) {
  54. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  55. DCHECK(pixmap);
  56. DCHECK(pixmap->AreDmaBufFdsValid());
  57. // Create a |va_surface_| from dmabuf fds (pixmap->GetDmaBufFd)
  58. va_surface_ = vaapi_wrapper_->CreateVASurfaceForPixmap(pixmap);
  59. if (!va_surface_) {
  60. LOG(ERROR) << "Failed creating VASurface for NativePixmap";
  61. return VaapiStatus::Codes::kNoSurface;
  62. }
  63. // ARC++ has no texture ids.
  64. if (texture_id_ == 0 && client_texture_id_ == 0)
  65. return VaapiStatus::Codes::kOk;
  66. // Import dmabuf fds into the output gl texture through EGLImage.
  67. if (make_context_current_cb_ && !make_context_current_cb_.Run())
  68. return VaapiStatus::Codes::kBadContext;
  69. gl::ScopedTextureBinder texture_binder(texture_target_, texture_id_);
  70. const gfx::BufferFormat format = pixmap->GetBufferFormat();
  71. // TODO(b/220336463): plumb the right color space.
  72. auto image =
  73. base::MakeRefCounted<gl::GLImageNativePixmap>(visible_size_, format);
  74. if (!image->Initialize(std::move(pixmap))) {
  75. LOG(ERROR) << "Failed to create GLImage";
  76. return VaapiStatus::Codes::kFailedToInitializeImage;
  77. }
  78. gl_image_ = image;
  79. if (!gl_image_->BindTexImage(texture_target_)) {
  80. LOG(ERROR) << "Failed to bind texture to GLImage";
  81. return VaapiStatus::Codes::kFailedToBindTexture;
  82. }
  83. if (bind_image_cb_ &&
  84. !bind_image_cb_.Run(client_texture_id_, texture_target_, gl_image_,
  85. true /* can_bind_to_sampler */)) {
  86. LOG(ERROR) << "Failed to bind client_texture_id";
  87. return VaapiStatus::Codes::kFailedToBindImage;
  88. }
  89. return VaapiStatus::Codes::kOk;
  90. }
  91. VaapiStatus VaapiPictureNativePixmapOzone::Allocate(gfx::BufferFormat format) {
  92. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  93. ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance();
  94. ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone();
  95. auto pixmap = factory->CreateNativePixmap(
  96. gfx::kNullAcceleratedWidget, VK_NULL_HANDLE, size_, format,
  97. gfx::BufferUsage::SCANOUT_VDA_WRITE, /*framebuffer_size=*/visible_size_);
  98. if (!pixmap) {
  99. return VaapiStatus::Codes::kNoPixmap;
  100. }
  101. return Initialize(std::move(pixmap));
  102. }
  103. bool VaapiPictureNativePixmapOzone::ImportGpuMemoryBufferHandle(
  104. gfx::BufferFormat format,
  105. gfx::GpuMemoryBufferHandle gpu_memory_buffer_handle) {
  106. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  107. if (!CanImportGpuMemoryBufferHandle(size_, format,
  108. gpu_memory_buffer_handle)) {
  109. VLOGF(1) << "Can't import the given GpuMemoryBufferHandle";
  110. return false;
  111. }
  112. const auto& plane = gpu_memory_buffer_handle.native_pixmap_handle.planes[0];
  113. if (size_.width() > static_cast<int>(plane.stride) ||
  114. size_.GetArea() > static_cast<int>(plane.size)) {
  115. DLOG(ERROR) << "GpuMemoryBufferHandle (stride=" << plane.stride
  116. << ", size=" << plane.size
  117. << "is smaller than size_=" << size_.ToString();
  118. return false;
  119. }
  120. // gfx::NativePixmapDmaBuf() will take ownership of the handle.
  121. return Initialize(
  122. base::MakeRefCounted<gfx::NativePixmapDmaBuf>(
  123. size_, format,
  124. std::move(gpu_memory_buffer_handle.native_pixmap_handle)))
  125. .is_ok();
  126. }
  127. } // namespace media