vaapi_picture_native_pixmap_egl.cc 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // Copyright 2018 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_egl.h"
  5. #include "base/file_descriptor_posix.h"
  6. #include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
  7. #include "media/gpu/vaapi/va_surface.h"
  8. #include "media/gpu/vaapi/vaapi_status.h"
  9. #include "media/gpu/vaapi/vaapi_wrapper.h"
  10. #include "ui/gfx/linux/native_pixmap_dmabuf.h"
  11. #include "ui/gfx/native_pixmap.h"
  12. #include "ui/gl/gl_bindings.h"
  13. #include "ui/gl/gl_image_native_pixmap.h"
  14. #include "ui/gl/scoped_binders.h"
  15. namespace media {
  16. VaapiPictureNativePixmapEgl::VaapiPictureNativePixmapEgl(
  17. scoped_refptr<VaapiWrapper> vaapi_wrapper,
  18. const MakeGLContextCurrentCallback& make_context_current_cb,
  19. const BindGLImageCallback& bind_image_cb,
  20. int32_t picture_buffer_id,
  21. const gfx::Size& visible_size,
  22. const gfx::Size& size,
  23. uint32_t texture_id,
  24. uint32_t client_texture_id,
  25. uint32_t texture_target)
  26. : VaapiPictureNativePixmap(std::move(vaapi_wrapper),
  27. make_context_current_cb,
  28. bind_image_cb,
  29. picture_buffer_id,
  30. size,
  31. visible_size,
  32. texture_id,
  33. client_texture_id,
  34. texture_target) {
  35. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  36. DCHECK(texture_id);
  37. DCHECK(client_texture_id);
  38. }
  39. VaapiPictureNativePixmapEgl::~VaapiPictureNativePixmapEgl() {
  40. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  41. if (gl_image_ && make_context_current_cb_.Run()) {
  42. gl_image_->ReleaseTexImage(texture_target_);
  43. DCHECK_EQ(glGetError(), static_cast<GLenum>(GL_NO_ERROR));
  44. }
  45. }
  46. VaapiStatus VaapiPictureNativePixmapEgl::Initialize(
  47. scoped_refptr<gfx::NativePixmap> pixmap) {
  48. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  49. DCHECK(pixmap);
  50. DCHECK(pixmap->AreDmaBufFdsValid());
  51. // Create a |va_surface_| from dmabuf fds (pixmap->GetDmaBufFd)
  52. va_surface_ = vaapi_wrapper_->CreateVASurfaceForPixmap(std::move(pixmap));
  53. if (!va_surface_) {
  54. LOG(ERROR) << "Failed creating VASurface for NativePixmap";
  55. return VaapiStatus::Codes::kNoSurface;
  56. }
  57. if (bind_image_cb_ &&
  58. !bind_image_cb_.Run(client_texture_id_, texture_target_, gl_image_,
  59. true /* can_bind_to_sampler */)) {
  60. LOG(ERROR) << "Failed to bind client_texture_id";
  61. return VaapiStatus::Codes::kFailedToBindImage;
  62. }
  63. return VaapiStatus::Codes::kOk;
  64. }
  65. VaapiStatus VaapiPictureNativePixmapEgl::Allocate(gfx::BufferFormat format) {
  66. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  67. // Export the gl texture as dmabuf.
  68. if (make_context_current_cb_ && !make_context_current_cb_.Run())
  69. return VaapiStatus::Codes::kBadContext;
  70. // TODO(b/220336463): plumb the right color space.
  71. auto image =
  72. base::MakeRefCounted<gl::GLImageNativePixmap>(visible_size_, format);
  73. // Create an EGLImage from a gl texture
  74. if (!image->InitializeFromTexture(texture_id_)) {
  75. DLOG(ERROR) << "Failed to initialize eglimage from texture id: "
  76. << texture_id_;
  77. return VaapiStatus::Codes::kFailedToInitializeImage;
  78. }
  79. // Export the EGLImage as dmabuf.
  80. gfx::NativePixmapHandle native_pixmap_handle = image->ExportHandle();
  81. if (!native_pixmap_handle.planes.size()) {
  82. DLOG(ERROR) << "Failed to export EGLImage as dmabuf fds";
  83. return VaapiStatus::Codes::kFailedToExportImage;
  84. }
  85. if (size_.width() > static_cast<int>(native_pixmap_handle.planes[0].stride) ||
  86. size_.GetArea() > static_cast<int>(native_pixmap_handle.planes[0].size)) {
  87. DLOG(ERROR) << "EGLImage (stride=" << native_pixmap_handle.planes[0].stride
  88. << ", size=" << native_pixmap_handle.planes[0].size
  89. << "is smaller than size_=" << size_.ToString();
  90. return VaapiStatus::Codes::kBadImageSize;
  91. }
  92. // Convert NativePixmapHandle to NativePixmapDmaBuf.
  93. scoped_refptr<gfx::NativePixmap> native_pixmap_dmabuf(
  94. new gfx::NativePixmapDmaBuf(size_, format,
  95. std::move(native_pixmap_handle)));
  96. if (!native_pixmap_dmabuf->AreDmaBufFdsValid()) {
  97. DLOG(ERROR) << "Invalid dmabuf fds";
  98. return VaapiStatus::Codes::kNoBufferHandle;
  99. }
  100. if (!image->BindTexImage(texture_target_)) {
  101. DLOG(ERROR) << "Failed to bind texture to GLImage";
  102. return VaapiStatus::Codes::kFailedToBindImage;
  103. }
  104. // The |va_surface_| created from |native_pixmap_dmabuf| shares the ownership
  105. // of the buffer. So the only reason to keep a reference on the image is
  106. // because the GPU service needs to track this image as it will be attached
  107. // to a client texture.
  108. gl_image_ = image;
  109. return Initialize(std::move(native_pixmap_dmabuf));
  110. }
  111. bool VaapiPictureNativePixmapEgl::ImportGpuMemoryBufferHandle(
  112. gfx::BufferFormat format,
  113. gfx::GpuMemoryBufferHandle gpu_memory_buffer_handle) {
  114. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  115. NOTIMPLEMENTED();
  116. return false;
  117. }
  118. } // namespace media