// Copyright 2016 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/windows/dxva_picture_buffer_win.h"

#include "base/metrics/histogram_functions.h"
#include "media/base/win/mf_helpers.h"
#include "media/gpu/windows/dxva_video_decode_accelerator_win.h"
#include "third_party/angle/include/EGL/egl.h"
#include "third_party/angle/include/EGL/eglext.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_fence.h"
#include "ui/gl/gl_image.h"
#include "ui/gl/gl_image_dxgi.h"
#include "ui/gl/gl_surface_egl.h"
#include "ui/gl/scoped_binders.h"

namespace media {

namespace {

// These GLImage subclasses are just used to hold references to the underlying
// image content so it can be destroyed when the textures are.
class DummyGLImage : public gl::GLImage {
 public:
  DummyGLImage(const gfx::Size& size) : size_(size) {}

  // gl::GLImage implementation.
  gfx::Size GetSize() override { return size_; }
  unsigned GetInternalFormat() override { return GL_BGRA_EXT; }
  unsigned GetDataType() override { return GL_UNSIGNED_BYTE; }
  BindOrCopy ShouldBindOrCopy() override { return BIND; }
  // PbufferPictureBuffer::CopySurfaceComplete does the actual binding, so
  // this doesn't do anything and always succeeds.
  bool BindTexImage(unsigned target) override { return true; }
  void ReleaseTexImage(unsigned target) override {}
  bool CopyTexImage(unsigned target) override {
    NOTREACHED();
    return false;
  }
  bool CopyTexSubImage(unsigned target,
                       const gfx::Point& offset,
                       const gfx::Rect& rect) override {
    return false;
  }
  void SetColorSpace(const gfx::ColorSpace& color_space) override {}
  void Flush() override {}
  void OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd,
                    uint64_t process_tracing_id,
                    const std::string& dump_name) override {}

 protected:
  ~DummyGLImage() override {}

 private:
  gfx::Size size_;
};

class GLImagePbuffer : public DummyGLImage {
 public:
  GLImagePbuffer(const gfx::Size& size, EGLSurface surface)
      : DummyGLImage(size), surface_(surface) {}

 private:
  ~GLImagePbuffer() override {
    EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay();

    eglReleaseTexImage(egl_display, surface_, EGL_BACK_BUFFER);

    eglDestroySurface(egl_display, surface_);
  }

  EGLSurface surface_;
};

}  // namespace

enum {
  // The keyed mutex should always be released before the other thread
  // attempts to acquire it, so AcquireSync should always return immediately.
  kAcquireSyncWaitMs = 0,
};

// static
std::unique_ptr<DXVAPictureBuffer> DXVAPictureBuffer::Create(
    const DXVAVideoDecodeAccelerator& decoder,
    const PictureBuffer& buffer,
    EGLConfig egl_config) {
  switch (decoder.GetPictureBufferMechanism()) {
    case DXVAVideoDecodeAccelerator::PictureBufferMechanism::BIND: {
      auto picture_buffer = std::make_unique<EGLStreamPictureBuffer>(buffer);
      if (!picture_buffer->Initialize())
        return nullptr;

      return picture_buffer;
    }
    case DXVAVideoDecodeAccelerator::PictureBufferMechanism::
        DELAYED_COPY_TO_NV12: {
      auto picture_buffer =
          std::make_unique<EGLStreamDelayedCopyPictureBuffer>(buffer);
      if (!picture_buffer->Initialize(decoder))
        return nullptr;

      return picture_buffer;
    }
    case DXVAVideoDecodeAccelerator::PictureBufferMechanism::COPY_TO_NV12: {
      auto picture_buffer =
          std::make_unique<EGLStreamCopyPictureBuffer>(buffer);
      if (!picture_buffer->Initialize(decoder))
        return nullptr;

      return picture_buffer;
    }
    case DXVAVideoDecodeAccelerator::PictureBufferMechanism::COPY_TO_RGB: {
      auto picture_buffer = std::make_unique<PbufferPictureBuffer>(buffer);

      if (!picture_buffer->Initialize(decoder, egl_config))
        return nullptr;

      return picture_buffer;
    }
  }
  NOTREACHED();
  return nullptr;
}

DXVAPictureBuffer::~DXVAPictureBuffer() {}

void DXVAPictureBuffer::ResetReuseFence() {
  NOTREACHED();
}

bool DXVAPictureBuffer::CopyOutputSampleDataToPictureBuffer(
    DXVAVideoDecodeAccelerator* decoder,
    IDirect3DSurface9* dest_surface,
    ID3D11Texture2D* dx11_texture,
    int input_buffer_id) {
  NOTREACHED();
  return false;
}

void DXVAPictureBuffer::set_bound() {
  DCHECK_EQ(UNUSED, state_);
  state_ = BOUND;
}

gl::GLFence* DXVAPictureBuffer::reuse_fence() {
  return nullptr;
}

bool DXVAPictureBuffer::CopySurfaceComplete(IDirect3DSurface9* src_surface,
                                            IDirect3DSurface9* dest_surface) {
  NOTREACHED();
  return false;
}

DXVAPictureBuffer::DXVAPictureBuffer(const PictureBuffer& buffer)
    : picture_buffer_(buffer) {}

bool DXVAPictureBuffer::BindSampleToTexture(
    DXVAVideoDecodeAccelerator* decoder,
    Microsoft::WRL::ComPtr<IMFSample> sample) {
  NOTREACHED();
  return false;
}

bool PbufferPictureBuffer::Initialize(const DXVAVideoDecodeAccelerator& decoder,
                                      EGLConfig egl_config) {
  RETURN_ON_FAILURE(!picture_buffer_.service_texture_ids().empty(),
                    "No service texture ids provided", false);

  EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay();
  EGLint use_rgb = 1;
  eglGetConfigAttrib(egl_display, egl_config, EGL_BIND_TO_TEXTURE_RGB,
                     &use_rgb);

  EGLint red_bits = 8;
  eglGetConfigAttrib(egl_display, egl_config, EGL_RED_SIZE, &red_bits);

  if (!InitializeTexture(decoder, !!use_rgb, red_bits == 16))
    return false;

  EGLint attrib_list[] = {EGL_WIDTH,
                          size().width(),
                          EGL_HEIGHT,
                          size().height(),
                          EGL_TEXTURE_FORMAT,
                          use_rgb ? EGL_TEXTURE_RGB : EGL_TEXTURE_RGBA,
                          EGL_TEXTURE_TARGET,
                          EGL_TEXTURE_2D,
                          EGL_NONE};

  decoding_surface_ = eglCreatePbufferFromClientBuffer(
      egl_display, EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, texture_share_handle_,
      egl_config, attrib_list);
  RETURN_ON_FAILURE(decoding_surface_, "Failed to create surface", false);
  gl_image_ = base::MakeRefCounted<GLImagePbuffer>(size(), decoding_surface_);
  if (decoder.d3d11_device_ && decoder.use_keyed_mutex_) {
    void* keyed_mutex = nullptr;
    EGLBoolean ret =
        eglQuerySurfacePointerANGLE(egl_display, decoding_surface_,
                                    EGL_DXGI_KEYED_MUTEX_ANGLE, &keyed_mutex);
    RETURN_ON_FAILURE(keyed_mutex && ret == EGL_TRUE,
                      "Failed to query ANGLE keyed mutex", false);
    egl_keyed_mutex_ = Microsoft::WRL::ComPtr<IDXGIKeyedMutex>(
        static_cast<IDXGIKeyedMutex*>(keyed_mutex));
  }
  use_rgb_ = !!use_rgb;
  return true;
}

bool PbufferPictureBuffer::InitializeTexture(
    const DXVAVideoDecodeAccelerator& decoder,
    bool use_rgb,
    bool use_fp16) {
  DCHECK(!texture_share_handle_);
  if (decoder.d3d11_device_) {
    D3D11_TEXTURE2D_DESC desc;
    desc.Width = picture_buffer_.size().width();
    desc.Height = picture_buffer_.size().height();
    desc.MipLevels = 1;
    desc.ArraySize = 1;
    if (use_fp16) {
      desc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT;
    } else {
      desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
    }
    desc.SampleDesc.Count = 1;
    desc.SampleDesc.Quality = 0;
    desc.Usage = D3D11_USAGE_DEFAULT;
    desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
    desc.CPUAccessFlags = 0;
    desc.MiscFlags = decoder.use_keyed_mutex_
                         ? D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX
                         : D3D11_RESOURCE_MISC_SHARED;

    HRESULT hr = decoder.d3d11_device_->CreateTexture2D(
        &desc, nullptr, &dx11_decoding_texture_);
    RETURN_ON_HR_FAILURE(hr, "Failed to create texture", false);
    RETURN_ON_HR_FAILURE(
        SetDebugName(dx11_decoding_texture_.Get(), "DXVADecoder_PictureBuffer"),
        "SetDebugNameFail", false);
    if (decoder.use_keyed_mutex_) {
      hr = dx11_decoding_texture_.As(&dx11_keyed_mutex_);
      RETURN_ON_HR_FAILURE(hr, "Failed to get keyed mutex", false);
    }

    Microsoft::WRL::ComPtr<IDXGIResource> resource;
    hr = dx11_decoding_texture_.As(&resource);
    DCHECK(SUCCEEDED(hr));
    hr = resource->GetSharedHandle(&texture_share_handle_);
    RETURN_ON_FAILURE(SUCCEEDED(hr) && texture_share_handle_,
                      "Failed to query shared handle", false);

  } else {
    HRESULT hr = E_FAIL;
    hr = decoder.d3d9_device_ex_->CreateTexture(
        picture_buffer_.size().width(), picture_buffer_.size().height(), 1,
        D3DUSAGE_RENDERTARGET, use_rgb ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8,
        D3DPOOL_DEFAULT, &decoding_texture_, &texture_share_handle_);
    RETURN_ON_HR_FAILURE(hr, "Failed to create texture", false);
    RETURN_ON_FAILURE(texture_share_handle_, "Failed to query shared handle",
                      false);
  }
  return true;
}

void PbufferPictureBuffer::ResetReuseFence() {
  DCHECK_EQ(IN_CLIENT, state_);
  if (!reuse_fence_ || !reuse_fence_->ResetSupported())
    reuse_fence_ = gl::GLFence::Create();
  else
    reuse_fence_->ResetState();
  state_ = WAITING_TO_REUSE;
}

bool PbufferPictureBuffer::CopyOutputSampleDataToPictureBuffer(
    DXVAVideoDecodeAccelerator* decoder,
    IDirect3DSurface9* dest_surface,
    ID3D11Texture2D* dx11_texture,
    int input_buffer_id) {
  DCHECK_EQ(BOUND, state_);
  state_ = COPYING;
  DCHECK(dest_surface || dx11_texture);
  if (dx11_texture) {
    // Grab a reference on the decoder texture. This reference will be released
    // when we receive a notification that the copy was completed or when the
    // DXVAPictureBuffer instance is destroyed.
    decoder_dx11_texture_ = dx11_texture;
    if (!decoder->CopyTexture(dx11_texture, dx11_decoding_texture_.Get(),
                              dx11_keyed_mutex_, keyed_mutex_value_, id(),
                              input_buffer_id, color_space_)) {
      // |this| might be destroyed.
      return false;
    }
    return true;
  }
  D3DSURFACE_DESC surface_desc;
  HRESULT hr = dest_surface->GetDesc(&surface_desc);
  RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false);

  D3DSURFACE_DESC texture_desc;
  decoding_texture_->GetLevelDesc(0, &texture_desc);

  if (texture_desc.Width != surface_desc.Width ||
      texture_desc.Height != surface_desc.Height) {
    NOTREACHED() << "Decode surface of different dimension than texture";
    return false;
  }

  hr = decoder->d3d9_->CheckDeviceFormatConversion(
      D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, surface_desc.Format,
      use_rgb_ ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8);
  RETURN_ON_HR_FAILURE(hr, "Device does not support format converision", false);

  // The same picture buffer can be reused for a different frame. Release the
  // target surface and the decoder references here.
  target_surface_.Reset();
  decoder_surface_.Reset();

  // Grab a reference on the decoder surface and the target surface. These
  // references will be released when we receive a notification that the
  // copy was completed or when the DXVAPictureBuffer instance is destroyed.
  // We hold references here as it is easier to manage their lifetimes.
  hr = decoding_texture_->GetSurfaceLevel(0, &target_surface_);
  RETURN_ON_HR_FAILURE(hr, "Failed to get surface from texture", false);

  decoder_surface_ = dest_surface;

  decoder->CopySurface(decoder_surface_.Get(), target_surface_.Get(), id(),
                       input_buffer_id, color_space_);
  color_space_ = gfx::ColorSpace();
  return true;
}

gl::GLFence* PbufferPictureBuffer::reuse_fence() {
  return reuse_fence_.get();
}

bool PbufferPictureBuffer::CopySurfaceComplete(
    IDirect3DSurface9* src_surface,
    IDirect3DSurface9* dest_surface) {
  DCHECK_EQ(COPYING, state_);
  state_ = IN_CLIENT;

  GLint current_texture = 0;
  glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);

  glBindTexture(GL_TEXTURE_2D, picture_buffer_.service_texture_ids()[0]);

  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

  if (src_surface && dest_surface) {
    DCHECK_EQ(src_surface, decoder_surface_.Get());
    DCHECK_EQ(dest_surface, target_surface_.Get());
    decoder_surface_.Reset();
    target_surface_.Reset();
  } else {
    DCHECK(decoder_dx11_texture_.Get());
    decoder_dx11_texture_.Reset();
  }
  if (egl_keyed_mutex_) {
    keyed_mutex_value_++;
    HRESULT result =
        egl_keyed_mutex_->AcquireSync(keyed_mutex_value_, kAcquireSyncWaitMs);
    RETURN_ON_FAILURE(result == S_OK, "Could not acquire sync mutex", false);
  }

  EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay();
  eglBindTexImage(egl_display, decoding_surface_, EGL_BACK_BUFFER);

  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glBindTexture(GL_TEXTURE_2D, current_texture);
  return true;
}

bool PbufferPictureBuffer::AllowOverlay() const {
  return false;
}

bool PbufferPictureBuffer::CanBindSamples() const {
  return false;
}

PbufferPictureBuffer::PbufferPictureBuffer(const PictureBuffer& buffer)
    : DXVAPictureBuffer(buffer),
      decoding_surface_(NULL),
      texture_share_handle_(nullptr),
      keyed_mutex_value_(0),
      use_rgb_(true) {}

PbufferPictureBuffer::~PbufferPictureBuffer() {
  // decoding_surface_ will be deleted by gl_image_.
}

bool PbufferPictureBuffer::ReusePictureBuffer() {
  DCHECK_NE(UNUSED, state_);
  DCHECK(decoding_surface_);
  EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay();
  eglReleaseTexImage(egl_display, decoding_surface_, EGL_BACK_BUFFER);

  decoder_surface_.Reset();
  target_surface_.Reset();
  decoder_dx11_texture_.Reset();
  state_ = UNUSED;
  if (egl_keyed_mutex_) {
    HRESULT hr = egl_keyed_mutex_->ReleaseSync(++keyed_mutex_value_);
    RETURN_ON_FAILURE(hr == S_OK, "Could not release sync mutex", false);
  }
  return true;
}

EGLStreamPictureBuffer::EGLStreamPictureBuffer(const PictureBuffer& buffer)
    : DXVAPictureBuffer(buffer), stream_(nullptr) {}

EGLStreamPictureBuffer::~EGLStreamPictureBuffer() {
  // stream_ will be deleted by gl_image_.
}

bool EGLStreamPictureBuffer::Initialize() {
  RETURN_ON_FAILURE(picture_buffer_.service_texture_ids().size() >= 2,
                    "Not enough texture ids provided", false);

  EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay();
  const EGLint stream_attributes[] = {
      EGL_CONSUMER_LATENCY_USEC_KHR,
      0,
      EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR,
      0,
      EGL_NONE,
  };
  stream_ = eglCreateStreamKHR(egl_display, stream_attributes);
  RETURN_ON_FAILURE(!!stream_, "Could not create stream", false);
  gl_image_ = base::MakeRefCounted<gl::GLImageDXGI>(size(), stream_);
  gl::ScopedActiveTexture texture0(GL_TEXTURE0);
  gl::ScopedTextureBinder texture0_binder(
      GL_TEXTURE_EXTERNAL_OES, picture_buffer_.service_texture_ids()[0]);
  gl::ScopedActiveTexture texture1(GL_TEXTURE1);
  gl::ScopedTextureBinder texture1_binder(
      GL_TEXTURE_EXTERNAL_OES, picture_buffer_.service_texture_ids()[1]);

  EGLAttrib consumer_attributes[] = {
      EGL_COLOR_BUFFER_TYPE,
      EGL_YUV_BUFFER_EXT,
      EGL_YUV_NUMBER_OF_PLANES_EXT,
      2,
      EGL_YUV_PLANE0_TEXTURE_UNIT_NV,
      0,
      EGL_YUV_PLANE1_TEXTURE_UNIT_NV,
      1,
      EGL_NONE,
  };
  EGLBoolean result = eglStreamConsumerGLTextureExternalAttribsNV(
      egl_display, stream_, consumer_attributes);
  RETURN_ON_FAILURE(result, "Could not set stream consumer", false);

  EGLAttrib producer_attributes[] = {
      EGL_NONE,
  };

  result = eglCreateStreamProducerD3DTextureANGLE(egl_display, stream_,
                                                  producer_attributes);
  RETURN_ON_FAILURE(result, "Could not create stream producer", false);
  return true;
}

bool EGLStreamPictureBuffer::ReusePictureBuffer() {
  DCHECK_NE(UNUSED, state_);
  EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay();

  if (stream_) {
    EGLBoolean result = eglStreamConsumerReleaseKHR(egl_display, stream_);
    RETURN_ON_FAILURE(result, "Could not release stream", false);
  }
  if (current_d3d_sample_) {
    dx11_decoding_texture_.Reset();
    current_d3d_sample_.Reset();
  }
  state_ = UNUSED;
  return true;
}

bool EGLStreamPictureBuffer::BindSampleToTexture(
    DXVAVideoDecodeAccelerator* decoder,
    Microsoft::WRL::ComPtr<IMFSample> sample) {
  DCHECK_EQ(BOUND, state_);
  state_ = IN_CLIENT;

  shared_images_.resize(picture_buffer_.service_texture_ids().size());

  current_d3d_sample_ = sample;
  EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay();

  Microsoft::WRL::ComPtr<IMFMediaBuffer> output_buffer;
  HRESULT hr = current_d3d_sample_->GetBufferByIndex(0, &output_buffer);
  RETURN_ON_HR_FAILURE(hr, "Failed to get buffer from output sample", false);

  Microsoft::WRL::ComPtr<IMFDXGIBuffer> dxgi_buffer;
  hr = output_buffer.As(&dxgi_buffer);
  RETURN_ON_HR_FAILURE(hr, "Failed to get DXGIBuffer from output sample",
                       false);
  hr = dxgi_buffer->GetResource(IID_PPV_ARGS(&dx11_decoding_texture_));
  RETURN_ON_HR_FAILURE(hr, "Failed to get texture from output sample", false);
  UINT subresource;
  dxgi_buffer->GetSubresourceIndex(&subresource);

  EGLAttrib frame_attributes[] = {
      EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE,
      static_cast<EGLAttrib>(subresource),
      EGL_NONE,
  };

  EGLBoolean result = eglStreamPostD3DTextureANGLE(
      egl_display, stream_, static_cast<void*>(dx11_decoding_texture_.Get()),
      frame_attributes);
  RETURN_ON_FAILURE(result, "Could not post texture", false);
  result = eglStreamConsumerAcquireKHR(egl_display, stream_);
  RETURN_ON_FAILURE(result, "Could not post acquire stream", false);
  gl::GLImageDXGI* gl_image_dxgi =
      static_cast<gl::GLImageDXGI*>(gl_image_.get());
  DCHECK(gl_image_dxgi);

  gl_image_dxgi->SetTexture(dx11_decoding_texture_, subresource);
  return true;
}

bool EGLStreamPictureBuffer::AllowOverlay() const {
  return true;
}

bool EGLStreamPictureBuffer::CanBindSamples() const {
  return true;
}

EGLStreamDelayedCopyPictureBuffer::EGLStreamDelayedCopyPictureBuffer(
    const PictureBuffer& buffer)
    : DXVAPictureBuffer(buffer), stream_(nullptr) {}

EGLStreamDelayedCopyPictureBuffer::~EGLStreamDelayedCopyPictureBuffer() {
  // stream_ will be deleted by gl_image_.
}

bool EGLStreamDelayedCopyPictureBuffer::Initialize(
    const DXVAVideoDecodeAccelerator& decoder) {
  RETURN_ON_FAILURE(picture_buffer_.service_texture_ids().size() >= 2,
                    "Not enough texture ids provided", false);

  EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay();
  const EGLint stream_attributes[] = {
      EGL_CONSUMER_LATENCY_USEC_KHR,
      0,
      EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR,
      0,
      EGL_NONE,
  };
  stream_ = eglCreateStreamKHR(egl_display, stream_attributes);
  RETURN_ON_FAILURE(!!stream_, "Could not create stream", false);
  gl::ScopedActiveTexture texture0(GL_TEXTURE0);
  gl::ScopedTextureBinder texture0_binder(
      GL_TEXTURE_EXTERNAL_OES, picture_buffer_.service_texture_ids()[0]);
  gl::ScopedActiveTexture texture1(GL_TEXTURE1);
  gl::ScopedTextureBinder texture1_binder(
      GL_TEXTURE_EXTERNAL_OES, picture_buffer_.service_texture_ids()[1]);

  EGLAttrib consumer_attributes[] = {
      EGL_COLOR_BUFFER_TYPE,
      EGL_YUV_BUFFER_EXT,
      EGL_YUV_NUMBER_OF_PLANES_EXT,
      2,
      EGL_YUV_PLANE0_TEXTURE_UNIT_NV,
      0,
      EGL_YUV_PLANE1_TEXTURE_UNIT_NV,
      1,
      EGL_NONE,
  };
  EGLBoolean result = eglStreamConsumerGLTextureExternalAttribsNV(
      egl_display, stream_, consumer_attributes);
  RETURN_ON_FAILURE(result, "Could not set stream consumer", false);

  EGLAttrib producer_attributes[] = {
      EGL_NONE,
  };

  result = eglCreateStreamProducerD3DTextureANGLE(egl_display, stream_,
                                                  producer_attributes);
  RETURN_ON_FAILURE(result, "Could not create stream producer", false);
  scoped_refptr<gl::CopyingGLImageDXGI> copying_image_ =
      base::MakeRefCounted<gl::CopyingGLImageDXGI>(
          ComD3D11Device(decoder.D3D11Device()), size(), stream_);
  gl_image_ = copying_image_;
  return copying_image_->Initialize();
}

bool EGLStreamDelayedCopyPictureBuffer::ReusePictureBuffer() {
  DCHECK_NE(UNUSED, state_);

  static_cast<gl::CopyingGLImageDXGI*>(gl_image_.get())->UnbindFromTexture();
  if (current_d3d_sample_) {
    dx11_decoding_texture_.Reset();
    current_d3d_sample_.Reset();
  }
  state_ = UNUSED;
  return true;
}

bool EGLStreamDelayedCopyPictureBuffer::BindSampleToTexture(
    DXVAVideoDecodeAccelerator* decoder,
    Microsoft::WRL::ComPtr<IMFSample> sample) {
  DCHECK_EQ(BOUND, state_);
  state_ = IN_CLIENT;

  current_d3d_sample_ = sample;

  Microsoft::WRL::ComPtr<IMFMediaBuffer> output_buffer;
  HRESULT hr = current_d3d_sample_->GetBufferByIndex(0, &output_buffer);
  RETURN_ON_HR_FAILURE(hr, "Failed to get buffer from output sample", false);

  Microsoft::WRL::ComPtr<IMFDXGIBuffer> dxgi_buffer;
  hr = output_buffer.As(&dxgi_buffer);
  RETURN_ON_HR_FAILURE(hr, "Failed to get DXGIBuffer from output sample",
                       false);
  hr = dxgi_buffer->GetResource(IID_PPV_ARGS(&dx11_decoding_texture_));
  RETURN_ON_HR_FAILURE(hr, "Failed to get texture from output sample", false);
  UINT subresource;
  dxgi_buffer->GetSubresourceIndex(&subresource);
  if (!decoder->InitializeID3D11VideoProcessor(size().width(), size().height(),
                                               color_space_))
    return false;

  DCHECK(decoder->d3d11_processor_);
  DCHECK(decoder->enumerator_);

  gl::CopyingGLImageDXGI* gl_image_dxgi =
      static_cast<gl::CopyingGLImageDXGI*>(gl_image_.get());
  DCHECK(gl_image_dxgi);

  gl_image_dxgi->SetTexture(dx11_decoding_texture_, subresource);
  return gl_image_dxgi->InitializeVideoProcessor(decoder->d3d11_processor_,
                                                 decoder->enumerator_);
}

bool EGLStreamDelayedCopyPictureBuffer::AllowOverlay() const {
  return true;
}

bool EGLStreamDelayedCopyPictureBuffer::CanBindSamples() const {
  return true;
}

EGLStreamCopyPictureBuffer::EGLStreamCopyPictureBuffer(
    const PictureBuffer& buffer)
    : DXVAPictureBuffer(buffer), stream_(nullptr) {}

EGLStreamCopyPictureBuffer::~EGLStreamCopyPictureBuffer() {
  // stream_ will be deleted by gl_image_.
}

bool EGLStreamCopyPictureBuffer::Initialize(
    const DXVAVideoDecodeAccelerator& decoder) {
  RETURN_ON_FAILURE(picture_buffer_.service_texture_ids().size() >= 2,
                    "Not enough texture ids provided", false);

  EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay();
  const EGLint stream_attributes[] = {
      EGL_CONSUMER_LATENCY_USEC_KHR,
      0,
      EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR,
      0,
      EGL_NONE,
  };
  stream_ = eglCreateStreamKHR(egl_display, stream_attributes);
  RETURN_ON_FAILURE(!!stream_, "Could not create stream", false);
  gl_image_ = base::MakeRefCounted<gl::GLImageDXGI>(size(), stream_);
  gl::ScopedActiveTexture texture0(GL_TEXTURE0);
  gl::ScopedTextureBinder texture0_binder(
      GL_TEXTURE_EXTERNAL_OES, picture_buffer_.service_texture_ids()[0]);
  gl::ScopedActiveTexture texture1(GL_TEXTURE1);
  gl::ScopedTextureBinder texture1_binder(
      GL_TEXTURE_EXTERNAL_OES, picture_buffer_.service_texture_ids()[1]);

  EGLAttrib consumer_attributes[] = {
      EGL_COLOR_BUFFER_TYPE,
      EGL_YUV_BUFFER_EXT,
      EGL_YUV_NUMBER_OF_PLANES_EXT,
      2,
      EGL_YUV_PLANE0_TEXTURE_UNIT_NV,
      0,
      EGL_YUV_PLANE1_TEXTURE_UNIT_NV,
      1,
      EGL_NONE,
  };
  EGLBoolean result = eglStreamConsumerGLTextureExternalAttribsNV(
      egl_display, stream_, consumer_attributes);
  RETURN_ON_FAILURE(result, "Could not set stream consumer", false);

  EGLAttrib producer_attributes[] = {
      EGL_NONE,
  };

  result = eglCreateStreamProducerD3DTextureANGLE(egl_display, stream_,
                                                  producer_attributes);
  RETURN_ON_FAILURE(result, "Could not create stream producer", false);

  DCHECK(decoder.use_keyed_mutex_);
  D3D11_TEXTURE2D_DESC desc;
  desc.Width = picture_buffer_.size().width();
  desc.Height = picture_buffer_.size().height();
  desc.MipLevels = 1;
  desc.ArraySize = 1;
  desc.Format = DXGI_FORMAT_NV12;
  desc.SampleDesc.Count = 1;
  desc.SampleDesc.Quality = 0;
  desc.Usage = D3D11_USAGE_DEFAULT;
  desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
  desc.CPUAccessFlags = 0;
  desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;

  HRESULT hr = decoder.d3d11_device_->CreateTexture2D(&desc, nullptr,
                                                      &decoder_copy_texture_);
  RETURN_ON_HR_FAILURE(hr, "Failed to create texture", false);
  RETURN_ON_HR_FAILURE(SetDebugName(decoder_copy_texture_.Get(),
                                    "DXVADecoder_EGLStreamCopyPictureBuffer"),
                       "SetDebugNameFail", false);
  DCHECK(decoder.use_keyed_mutex_);
  hr = decoder_copy_texture_.As(&dx11_keyed_mutex_);
  RETURN_ON_HR_FAILURE(hr, "Failed to get keyed mutex", false);

  Microsoft::WRL::ComPtr<IDXGIResource> resource;
  hr = decoder_copy_texture_.As(&resource);
  DCHECK(SUCCEEDED(hr));
  hr = resource->GetSharedHandle(&texture_share_handle_);
  RETURN_ON_FAILURE(SUCCEEDED(hr) && texture_share_handle_,
                    "Failed to query shared handle", false);

  hr = decoder.angle_device_->OpenSharedResource(
      texture_share_handle_, IID_PPV_ARGS(&angle_copy_texture_));
  RETURN_ON_HR_FAILURE(hr, "Failed to open shared resource", false);
  hr = angle_copy_texture_.As(&egl_keyed_mutex_);
  RETURN_ON_HR_FAILURE(hr, "Failed to get ANGLE mutex", false);
  return true;
}

bool EGLStreamCopyPictureBuffer::CopyOutputSampleDataToPictureBuffer(
    DXVAVideoDecodeAccelerator* decoder,
    IDirect3DSurface9* dest_surface,
    ID3D11Texture2D* dx11_texture,
    int input_buffer_id) {
  DCHECK_EQ(BOUND, state_);
  state_ = COPYING;
  DCHECK(dx11_texture);
  // Grab a reference on the decoder texture. This reference will be released
  // when we receive a notification that the copy was completed or when the
  // DXVAPictureBuffer instance is destroyed.
  dx11_decoding_texture_ = dx11_texture;
  if (!decoder->CopyTexture(dx11_texture, decoder_copy_texture_.Get(),
                            dx11_keyed_mutex_, keyed_mutex_value_, id(),
                            input_buffer_id, color_space_)) {
    // |this| might be destroyed
    return false;
  }
  // The texture copy will acquire the current keyed mutex value and release
  // with the value + 1.
  keyed_mutex_value_++;
  return true;
}

bool EGLStreamCopyPictureBuffer::CopySurfaceComplete(
    IDirect3DSurface9* src_surface,
    IDirect3DSurface9* dest_surface) {
  DCHECK(!src_surface);
  DCHECK(!dest_surface);
  DCHECK_EQ(COPYING, state_);
  state_ = IN_CLIENT;

  dx11_decoding_texture_.Reset();

  HRESULT hr =
      egl_keyed_mutex_->AcquireSync(keyed_mutex_value_, kAcquireSyncWaitMs);
  RETURN_ON_FAILURE(hr == S_OK, "Could not acquire sync mutex", false);

  EGLAttrib frame_attributes[] = {
      EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE, 0, EGL_NONE,
  };

  EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay();

  EGLBoolean result = eglStreamPostD3DTextureANGLE(
      egl_display, stream_, static_cast<void*>(angle_copy_texture_.Get()),
      frame_attributes);
  RETURN_ON_FAILURE(result, "Could not post stream", false);
  result = eglStreamConsumerAcquireKHR(egl_display, stream_);
  RETURN_ON_FAILURE(result, "Could not post acquire stream", false);
  gl::GLImageDXGI* gl_image_dxgi =
      static_cast<gl::GLImageDXGI*>(gl_image_.get());
  DCHECK(gl_image_dxgi);

  gl_image_dxgi->SetTexture(angle_copy_texture_, 0);

  return true;
}

bool EGLStreamCopyPictureBuffer::ReusePictureBuffer() {
  DCHECK_NE(UNUSED, state_);
  EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay();

  if (state_ == IN_CLIENT) {
    HRESULT hr = egl_keyed_mutex_->ReleaseSync(++keyed_mutex_value_);
    RETURN_ON_FAILURE(hr == S_OK, "Could not release sync mutex", false);
  }
  state_ = UNUSED;

  if (stream_) {
    EGLBoolean result = eglStreamConsumerReleaseKHR(egl_display, stream_);
    RETURN_ON_FAILURE(result, "Could not release stream", false);
  }
  return true;
}

bool EGLStreamCopyPictureBuffer::AllowOverlay() const {
  return true;
}

bool EGLStreamCopyPictureBuffer::CanBindSamples() const {
  return false;
}

}  // namespace media
