vaapi_picture_tfp.cc 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  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_tfp.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/gl/gl_bindings.h"
  11. #include "ui/gl/gl_image_glx.h"
  12. #include "ui/gl/scoped_binders.h"
  13. namespace media {
  14. VaapiTFPPicture::VaapiTFPPicture(
  15. scoped_refptr<VaapiWrapper> vaapi_wrapper,
  16. const MakeGLContextCurrentCallback& make_context_current_cb,
  17. const BindGLImageCallback& bind_image_cb,
  18. int32_t picture_buffer_id,
  19. const gfx::Size& size,
  20. const gfx::Size& visible_size,
  21. uint32_t texture_id,
  22. uint32_t client_texture_id,
  23. uint32_t texture_target)
  24. : VaapiPicture(std::move(vaapi_wrapper),
  25. make_context_current_cb,
  26. bind_image_cb,
  27. picture_buffer_id,
  28. size,
  29. visible_size,
  30. texture_id,
  31. client_texture_id,
  32. texture_target),
  33. connection_(x11::Connection::Get()),
  34. x_pixmap_(x11::Pixmap::None) {
  35. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  36. DCHECK(texture_id);
  37. DCHECK(client_texture_id);
  38. }
  39. VaapiTFPPicture::~VaapiTFPPicture() {
  40. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  41. if (glx_image_.get() && make_context_current_cb_.Run()) {
  42. glx_image_->ReleaseTexImage(texture_target_);
  43. DCHECK_EQ(glGetError(), static_cast<GLenum>(GL_NO_ERROR));
  44. }
  45. if (x_pixmap_ != x11::Pixmap::None)
  46. connection_->FreePixmap({x_pixmap_});
  47. }
  48. VaapiStatus VaapiTFPPicture::Initialize() {
  49. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  50. DCHECK_NE(x_pixmap_, x11::Pixmap::None);
  51. if (make_context_current_cb_ && !make_context_current_cb_.Run())
  52. return VaapiStatus::Codes::kBadContext;
  53. glx_image_ = new gl::GLImageGLX(size_, gfx::BufferFormat::BGRX_8888);
  54. if (!glx_image_->Initialize(x_pixmap_)) {
  55. // x_pixmap_ will be freed in the destructor.
  56. DLOG(ERROR) << "Failed creating a GLX Pixmap for TFP";
  57. return VaapiStatus::Codes::kFailedToInitializeImage;
  58. }
  59. gl::ScopedTextureBinder texture_binder(texture_target_, texture_id_);
  60. if (!glx_image_->BindTexImage(texture_target_)) {
  61. DLOG(ERROR) << "Failed to bind texture to glx image";
  62. return VaapiStatus::Codes::kFailedToBindTexture;
  63. }
  64. return VaapiStatus::Codes::kOk;
  65. }
  66. VaapiStatus VaapiTFPPicture::Allocate(gfx::BufferFormat format) {
  67. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  68. if (format != gfx::BufferFormat::BGRX_8888 &&
  69. format != gfx::BufferFormat::BGRA_8888 &&
  70. format != gfx::BufferFormat::RGBX_8888) {
  71. DLOG(ERROR) << "Unsupported format";
  72. return VaapiStatus::Codes::kUnsupportedFormat;
  73. }
  74. if (!connection_->Ready())
  75. return VaapiStatus::Codes::kNoPixmap;
  76. auto root = connection_->default_root();
  77. uint8_t depth = 0;
  78. if (auto reply = connection_->GetGeometry(root).Sync())
  79. depth = reply->depth;
  80. else
  81. return VaapiStatus::Codes::kNoPixmap;
  82. // TODO(posciak): pass the depth required by libva, not the RootWindow's
  83. // depth
  84. auto pixmap = connection_->GenerateId<x11::Pixmap>();
  85. uint16_t pixmap_width, pixmap_height;
  86. if (!base::CheckedNumeric<int>(size_.width()).AssignIfValid(&pixmap_width) ||
  87. !base::CheckedNumeric<int>(size_.height())
  88. .AssignIfValid(&pixmap_height)) {
  89. return VaapiStatus::Codes::kNoPixmap;
  90. }
  91. auto req = connection_->CreatePixmap(
  92. {depth, pixmap, root, pixmap_width, pixmap_height});
  93. if (req.Sync().error) {
  94. DLOG(ERROR) << "Failed creating an X Pixmap for TFP";
  95. return VaapiStatus::Codes::kNoPixmap;
  96. } else {
  97. x_pixmap_ = pixmap;
  98. }
  99. return Initialize();
  100. }
  101. bool VaapiTFPPicture::ImportGpuMemoryBufferHandle(
  102. gfx::BufferFormat format,
  103. gfx::GpuMemoryBufferHandle gpu_memory_buffer_handle) {
  104. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  105. NOTIMPLEMENTED() << "GpuMemoryBufferHandle import not implemented";
  106. return false;
  107. }
  108. bool VaapiTFPPicture::DownloadFromSurface(scoped_refptr<VASurface> va_surface) {
  109. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  110. return vaapi_wrapper_->PutSurfaceIntoPixmap(va_surface->id(), x_pixmap_,
  111. va_surface->size());
  112. }
  113. } // namespace media