chromium/media/gpu/windows/d3d11_texture_wrapper_unittest.cc

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/gpu/windows/d3d11_texture_wrapper.h"

#include <utility>

#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/task_environment.h"
#include "media/gpu/test/fake_command_buffer_helper.h"
#include "media/gpu/windows/d3d11_picture_buffer.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gl/gl_context_egl.h"
#include "ui/gl/gl_egl_api_implementation.h"
#include "ui/gl/gl_share_group.h"
#include "ui/gl/gl_surface.h"
#include "ui/gl/init/gl_factory.h"
#include "ui/gl/test/gl_surface_test_support.h"

using ::testing::_;
using ::testing::Bool;
using ::testing::Combine;
using ::testing::Return;
using ::testing::Values;

namespace media {

class D3D11TextureWrapperUnittest : public ::testing::Test {
 public:
  void SetUp() override {
    task_runner_ = task_environment_.GetMainThreadTaskRunner();

    display_ = gl::GLSurfaceTestSupport::InitializeOneOffImplementation(
        gl::GLImplementationParts(gl::ANGLEImplementation::kD3D11));
    surface_ = gl::init::CreateOffscreenGLSurface(display_, gfx::Size());
    share_group_ = new gl::GLShareGroup();
    context_ = gl::init::CreateGLContext(share_group_.get(), surface_.get(),
                                         gl::GLContextAttribs());
    context_->MakeCurrent(surface_.get());

    // Create some objects that most tests want.
    fake_command_buffer_helper_ =
        base::MakeRefCounted<FakeCommandBufferHelper>(task_runner_);
    get_helper_cb_ = base::BindRepeating(
        [](scoped_refptr<CommandBufferHelper> helper) { return helper; },
        fake_command_buffer_helper_);
  }

  void TearDown() override {
    context_->ReleaseCurrent(surface_.get());
    context_ = nullptr;
    share_group_ = nullptr;
    surface_ = nullptr;
    gl::GLSurfaceTestSupport::ShutdownGL(display_);
  }

  base::test::TaskEnvironment task_environment_;
  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;

  scoped_refptr<gl::GLSurface> surface_;
  scoped_refptr<gl::GLShareGroup> share_group_;
  scoped_refptr<gl::GLContext> context_;

  // Made-up size for the images.
  const gfx::Size size_{100, 200};
  // Made-up color space for the images.
  const gfx::ColorSpace color_space_ = gfx::ColorSpace::CreateSRGB();

  // CommandBufferHelper, and a callback that returns it.  Useful to initialize
  // a wrapper.
  scoped_refptr<FakeCommandBufferHelper> fake_command_buffer_helper_;
  GetCommandBufferHelperCB get_helper_cb_;

  raw_ptr<gl::GLDisplay> display_ = nullptr;
};

TEST_F(D3D11TextureWrapperUnittest, NV12InitSucceeds) {
  const DXGI_FORMAT dxgi_format = DXGI_FORMAT_NV12;

  auto wrapper = std::make_unique<DefaultTexture2DWrapper>(size_, color_space_,
                                                           dxgi_format,
                                                           /*device=*/nullptr);
  const D3D11Status init_result = wrapper->Init(
      task_runner_, get_helper_cb_, /*in_texture=*/nullptr,
      /*array_slice=*/0, /*picture_buffer=*/nullptr,
      /*picture_buffer_gpu_resource_init_done_cb=*/base::DoNothing());
  EXPECT_EQ(init_result.code(), D3D11Status::Codes::kOk);

  // TODO: verify that ProcessTexture processes both textures.
}

TEST_F(D3D11TextureWrapperUnittest, BGRA8InitSucceeds) {
  const DXGI_FORMAT dxgi_format = DXGI_FORMAT_B8G8R8A8_UNORM;

  auto wrapper = std::make_unique<DefaultTexture2DWrapper>(size_, color_space_,
                                                           dxgi_format,
                                                           /*device=*/nullptr);
  const D3D11Status init_result = wrapper->Init(
      task_runner_, get_helper_cb_, /*in_texture=*/nullptr,
      /*array_slice=*/0, /*picture_buffer=*/nullptr,
      /*picture_buffer_gpu_resource_init_done_cb=*/base::DoNothing());
  EXPECT_EQ(init_result.code(), D3D11Status::Codes::kOk);
}

TEST_F(D3D11TextureWrapperUnittest, FP16InitSucceeds) {
  const DXGI_FORMAT dxgi_format = DXGI_FORMAT_R16G16B16A16_FLOAT;

  auto wrapper = std::make_unique<DefaultTexture2DWrapper>(size_, color_space_,
                                                           dxgi_format,
                                                           /*device=*/nullptr);
  const D3D11Status init_result = wrapper->Init(
      task_runner_, get_helper_cb_, /*in_texture=*/nullptr,
      /*array_slice=*/0, /*picture_buffer=*/nullptr,
      /*picture_buffer_gpu_resource_init_done_cb=*/base::DoNothing());
  EXPECT_EQ(init_result.code(), D3D11Status::Codes::kOk);
}

TEST_F(D3D11TextureWrapperUnittest, P010InitSucceeds) {
  const DXGI_FORMAT dxgi_format = DXGI_FORMAT_P010;

  auto wrapper = std::make_unique<DefaultTexture2DWrapper>(size_, color_space_,
                                                           dxgi_format,
                                                           /*device=*/nullptr);
  const D3D11Status init_result = wrapper->Init(
      task_runner_, get_helper_cb_, /*in_texture=*/nullptr,
      /*array_slice=*/0, /*picture_buffer=*/nullptr,
      /*picture_buffer_gpu_resource_init_done_cb=*/base::DoNothing());
  EXPECT_EQ(init_result.code(), D3D11Status::Codes::kOk);
}

TEST_F(D3D11TextureWrapperUnittest, UnknownInitFails) {
  const DXGI_FORMAT dxgi_format = DXGI_FORMAT_UNKNOWN;

  auto wrapper = std::make_unique<DefaultTexture2DWrapper>(size_, color_space_,
                                                           dxgi_format,
                                                           /*device=*/nullptr);
  const D3D11Status init_result = wrapper->Init(
      task_runner_, get_helper_cb_, /*in_texture=*/nullptr,
      /*array_slice=*/0, /*picture_buffer=*/nullptr,
      /*picture_buffer_gpu_resource_init_done_cb=*/base::DoNothing());
  EXPECT_NE(init_result.code(), D3D11Status::Codes::kOk);
}

}  // namespace media