summaryrefslogtreecommitdiff
path: root/chromium/media/gpu/vaapi/vaapi_picture_native_pixmap_ozone.cc
blob: af93b47c6582ad6d4367bc84e1f5d694009025de (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/gpu/vaapi/vaapi_picture_native_pixmap_ozone.h"

#include "media/gpu/vaapi/va_surface.h"
#include "media/gpu/vaapi/vaapi_wrapper.h"
#include "ui/gfx/gpu_memory_buffer.h"
#include "ui/gfx/native_pixmap.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_image_native_pixmap.h"
#include "ui/gl/scoped_binders.h"
#include "ui/ozone/public/ozone_platform.h"
#include "ui/ozone/public/surface_factory_ozone.h"

namespace media {

VaapiPictureNativePixmapOzone::VaapiPictureNativePixmapOzone(
    scoped_refptr<VaapiWrapper> vaapi_wrapper,
    const MakeGLContextCurrentCallback& make_context_current_cb,
    const BindGLImageCallback& bind_image_cb,
    int32_t picture_buffer_id,
    const gfx::Size& size,
    const gfx::Size& visible_size,
    uint32_t texture_id,
    uint32_t client_texture_id,
    uint32_t texture_target)
    : VaapiPictureNativePixmap(std::move(vaapi_wrapper),
                               make_context_current_cb,
                               bind_image_cb,
                               picture_buffer_id,
                               size,
                               visible_size,
                               texture_id,
                               client_texture_id,
                               texture_target) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  // Either |texture_id| and |client_texture_id| are both zero, or not.
  DCHECK((texture_id == 0 && client_texture_id == 0) ||
         (texture_id != 0 && client_texture_id != 0));
}

VaapiPictureNativePixmapOzone::~VaapiPictureNativePixmapOzone() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  if (gl_image_ && make_context_current_cb_.Run()) {
    gl_image_->ReleaseTexImage(texture_target_);
    DCHECK_EQ(glGetError(), static_cast<GLenum>(GL_NO_ERROR));
  }
}

Status VaapiPictureNativePixmapOzone::Initialize(
    scoped_refptr<gfx::NativePixmap> pixmap) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(pixmap);
  DCHECK(pixmap->AreDmaBufFdsValid());
  // Create a |va_surface_| from dmabuf fds (pixmap->GetDmaBufFd)
  va_surface_ = vaapi_wrapper_->CreateVASurfaceForPixmap(pixmap);
  if (!va_surface_) {
    LOG(ERROR) << "Failed creating VASurface for NativePixmap";
    return StatusCode::kVaapiNoSurface;
  }

  // ARC++ has no texture ids.
  if (texture_id_ == 0 && client_texture_id_ == 0)
    return OkStatus();

  // Import dmabuf fds into the output gl texture through EGLImage.
  if (make_context_current_cb_ && !make_context_current_cb_.Run())
    return StatusCode::kVaapiBadContext;

  gl::ScopedTextureBinder texture_binder(texture_target_, texture_id_);

  const gfx::BufferFormat format = pixmap->GetBufferFormat();

  auto image =
      base::MakeRefCounted<gl::GLImageNativePixmap>(visible_size_, format);
  if (!image->Initialize(std::move(pixmap))) {
    LOG(ERROR) << "Failed to create GLImage";
    return StatusCode::kVaapiFailedToInitializeImage;
  }

  gl_image_ = image;
  if (!gl_image_->BindTexImage(texture_target_)) {
    LOG(ERROR) << "Failed to bind texture to GLImage";
    return StatusCode::kVaapiFailedToBindTexture;
  }

  if (bind_image_cb_ &&
      !bind_image_cb_.Run(client_texture_id_, texture_target_, gl_image_,
                          true /* can_bind_to_sampler */)) {
    LOG(ERROR) << "Failed to bind client_texture_id";
    return StatusCode::kVaapiFailedToBindImage;
  }

  return OkStatus();
}

Status VaapiPictureNativePixmapOzone::Allocate(gfx::BufferFormat format) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance();
  ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone();
  auto pixmap = factory->CreateNativePixmap(
      gfx::kNullAcceleratedWidget, VK_NULL_HANDLE, size_, format,
      gfx::BufferUsage::SCANOUT_VDA_WRITE, /*framebuffer_size=*/visible_size_);
  if (!pixmap) {
    return StatusCode::kVaapiNoPixmap;
  }

  return Initialize(std::move(pixmap));
}

bool VaapiPictureNativePixmapOzone::ImportGpuMemoryBufferHandle(
    gfx::BufferFormat format,
    gfx::GpuMemoryBufferHandle gpu_memory_buffer_handle) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  const auto& plane = gpu_memory_buffer_handle.native_pixmap_handle.planes[0];
  if (size_.width() > static_cast<int>(plane.stride) ||
      size_.GetArea() > static_cast<int>(plane.size)) {
    DLOG(ERROR) << "GpuMemoryBufferHandle (stride=" << plane.stride
                << ", size=" << plane.size
                << "is smaller than size_=" << size_.ToString();
    return false;
  }

  ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance();
  ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone();
  // CreateNativePixmapFromHandle() will take ownership of the handle.
  auto pixmap = factory->CreateNativePixmapFromHandle(
      gfx::kNullAcceleratedWidget, size_, format,
      std::move(gpu_memory_buffer_handle.native_pixmap_handle));

  if (!pixmap) {
    LOG(ERROR) << "Failed creating a pixmap from a native handle";
    return false;
  }

  return Initialize(std::move(pixmap)).is_ok();
}

}  // namespace media