vaapi_picture_native_pixmap_angle.cc 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. // Copyright 2020 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_angle.h"
  5. #include "media/gpu/vaapi/va_surface.h"
  6. #include "media/gpu/vaapi/vaapi_status.h"
  7. #include "media/gpu/vaapi/vaapi_wrapper.h"
  8. #include "ui/gfx/x/connection.h"
  9. #include "ui/gfx/x/future.h"
  10. #include "ui/gfx/x/xproto.h"
  11. #include "ui/gl/gl_bindings.h"
  12. #include "ui/gl/gl_image_egl_pixmap.h"
  13. #include "ui/gl/scoped_binders.h"
  14. namespace media {
  15. namespace {
  16. x11::Pixmap CreatePixmap(const gfx::Size& size) {
  17. auto* connection = x11::Connection::Get();
  18. if (!connection->Ready())
  19. return x11::Pixmap::None;
  20. auto root = connection->default_root();
  21. uint8_t depth = 0;
  22. if (auto reply = connection->GetGeometry(root).Sync())
  23. depth = reply->depth;
  24. else
  25. return x11::Pixmap::None;
  26. // TODO(tmathmeyer) should we use the depth from libva instead of root window?
  27. auto pixmap = connection->GenerateId<x11::Pixmap>();
  28. uint16_t pixmap_width, pixmap_height;
  29. if (!base::CheckedNumeric<int>(size.width()).AssignIfValid(&pixmap_width) ||
  30. !base::CheckedNumeric<int>(size.height()).AssignIfValid(&pixmap_height)) {
  31. return x11::Pixmap::None;
  32. }
  33. auto req = connection->CreatePixmap(
  34. {depth, pixmap, root, pixmap_width, pixmap_height});
  35. if (req.Sync().error)
  36. pixmap = x11::Pixmap::None;
  37. return pixmap;
  38. }
  39. } // namespace
  40. VaapiPictureNativePixmapAngle::VaapiPictureNativePixmapAngle(
  41. scoped_refptr<VaapiWrapper> vaapi_wrapper,
  42. const MakeGLContextCurrentCallback& make_context_current_cb,
  43. const BindGLImageCallback& bind_image_cb,
  44. int32_t picture_buffer_id,
  45. const gfx::Size& size,
  46. const gfx::Size& visible_size,
  47. uint32_t service_texture_id,
  48. uint32_t client_texture_id,
  49. uint32_t texture_target)
  50. : VaapiPictureNativePixmap(std::move(vaapi_wrapper),
  51. make_context_current_cb,
  52. bind_image_cb,
  53. picture_buffer_id,
  54. size,
  55. visible_size,
  56. service_texture_id,
  57. client_texture_id,
  58. texture_target) {
  59. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  60. // Check that they're both not 0
  61. DCHECK(service_texture_id);
  62. DCHECK(client_texture_id);
  63. }
  64. VaapiPictureNativePixmapAngle::~VaapiPictureNativePixmapAngle() {
  65. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  66. if (gl_image_ && make_context_current_cb_.Run()) {
  67. gl_image_->ReleaseTexImage(texture_target_);
  68. DCHECK_EQ(glGetError(), static_cast<GLenum>(GL_NO_ERROR));
  69. }
  70. if (x_pixmap_ != x11::Pixmap::None)
  71. x11::Connection::Get()->FreePixmap({x_pixmap_});
  72. }
  73. VaapiStatus VaapiPictureNativePixmapAngle::Allocate(gfx::BufferFormat format) {
  74. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  75. if (!(texture_id_ || client_texture_id_))
  76. return VaapiStatus::Codes::kNoTexture;
  77. if (!make_context_current_cb_ || !make_context_current_cb_.Run())
  78. return VaapiStatus::Codes::kBadContext;
  79. auto image =
  80. base::MakeRefCounted<gl::GLImageEGLPixmap>(visible_size_, format);
  81. if (!image)
  82. return VaapiStatus::Codes::kNoImage;
  83. x_pixmap_ = CreatePixmap(visible_size_);
  84. if (x_pixmap_ == x11::Pixmap::None)
  85. return VaapiStatus::Codes::kNoPixmap;
  86. if (!image->Initialize(x_pixmap_))
  87. return VaapiStatus::Codes::kFailedToInitializeImage;
  88. gl::ScopedTextureBinder texture_binder(texture_target_, texture_id_);
  89. if (!image->BindTexImage(texture_target_))
  90. return VaapiStatus::Codes::kFailedToBindTexture;
  91. gl_image_ = image;
  92. DCHECK(bind_image_cb_);
  93. if (!bind_image_cb_.Run(client_texture_id_, texture_target_, gl_image_,
  94. /*can_bind_to_sampler=*/true)) {
  95. return VaapiStatus::Codes::kFailedToBindImage;
  96. }
  97. return VaapiStatus::Codes::kOk;
  98. }
  99. bool VaapiPictureNativePixmapAngle::ImportGpuMemoryBufferHandle(
  100. gfx::BufferFormat format,
  101. gfx::GpuMemoryBufferHandle gpu_memory_buffer_handle) {
  102. NOTREACHED();
  103. return false;
  104. }
  105. bool VaapiPictureNativePixmapAngle::DownloadFromSurface(
  106. scoped_refptr<VASurface> va_surface) {
  107. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  108. if (!make_context_current_cb_ || !make_context_current_cb_.Run())
  109. return false;
  110. DCHECK(texture_id_);
  111. gl::ScopedTextureBinder texture_binder(texture_target_, texture_id_);
  112. // GL needs to re-bind the texture after the pixmap content is updated so that
  113. // the compositor sees the updated contents (we found this out experimentally)
  114. gl_image_->ReleaseTexImage(texture_target_);
  115. DCHECK(gfx::Rect(va_surface->size()).Contains(gfx::Rect(visible_size_)));
  116. if (!vaapi_wrapper_->PutSurfaceIntoPixmap(va_surface->id(), x_pixmap_,
  117. visible_size_)) {
  118. return false;
  119. }
  120. return gl_image_->BindTexImage(texture_target_);
  121. }
  122. VASurfaceID VaapiPictureNativePixmapAngle::va_surface_id() const {
  123. return VA_INVALID_ID;
  124. }
  125. } // namespace media