chromium/content/renderer/media/win/dcomp_texture_host.cc

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

#include "content/renderer/media/win/dcomp_texture_host.h"

#include "base/task/bind_post_task.h"
#include "base/task/sequenced_task_runner.h"
#include "base/unguessable_token.h"
#include "gpu/ipc/client/gpu_channel_host.h"
#include "gpu/ipc/common/command_buffer_id.h"
#include "gpu/ipc/common/gpu_channel.mojom.h"
#include "ipc/ipc_message_macros.h"
#include "ipc/ipc_mojo_bootstrap.h"
#include "media/base/win/mf_helpers.h"

namespace content {

DCOMPTextureHost::DCOMPTextureHost(
    scoped_refptr<gpu::GpuChannelHost> channel,
    int32_t route_id,
    scoped_refptr<base::SequencedTaskRunner> media_task_runner,
    mojo::PendingAssociatedRemote<gpu::mojom::DCOMPTexture> texture,
    Listener* listener)
    : channel_(std::move(channel)), route_id_(route_id), listener_(listener) {
  DVLOG_FUNC(1);
  DCHECK(media_task_runner->RunsTasksInCurrentSequence());
  DCHECK(channel_);
  DCHECK(route_id_);
  DCHECK(listener_);

  // `allow_binding` is needed to make sure `texture_remote_` and `receiver_`
  // are both bound on `media_task_runner`. See crbug.com/1229833.
  IPC::ScopedAllowOffSequenceChannelAssociatedBindings allow_binding;
  texture_remote_.Bind(std::move(texture), media_task_runner);
  texture_remote_->StartListening(
      receiver_.BindNewEndpointAndPassRemote(media_task_runner));
  texture_remote_.set_disconnect_handler(base::BindOnce(
      &DCOMPTextureHost::OnDisconnectedFromGpuProcess, base::Unretained(this)));
}

DCOMPTextureHost::~DCOMPTextureHost() {
  DVLOG_FUNC(1);

  if (!channel_)
    return;

  // We destroy the DCOMPTexture as a deferred message followed by a flush
  // to ensure this is ordered correctly with regards to previous deferred
  // messages, such as CreateSharedImage.
  uint32_t flush_id = channel_->EnqueueDeferredMessage(
      gpu::mojom::DeferredRequestParams::NewDestroyDcompTexture(route_id_),
      /*sync_token_fences=*/{}, /*release_count=*/0);
  channel_->EnsureFlush(flush_id);
}

void DCOMPTextureHost::SetTextureSize(const gfx::Size& size) {
  DVLOG_FUNC(3);
  if (texture_remote_)
    texture_remote_->SetTextureSize(size);
}

void DCOMPTextureHost::SetDCOMPSurfaceHandle(
    const base::UnguessableToken& token,
    SetDCOMPSurfaceHandleCB set_dcomp_surface_handle_cb) {
  DVLOG_FUNC(1);
  if (texture_remote_) {
    texture_remote_->SetDCOMPSurfaceHandle(
        token, std::move(set_dcomp_surface_handle_cb));
  }
}

void DCOMPTextureHost::OnDisconnectedFromGpuProcess() {
  DVLOG_FUNC(1);
  channel_ = nullptr;
  texture_remote_.reset();
  receiver_.reset();
}

void DCOMPTextureHost::OnSharedImageMailboxBound(const gpu::Mailbox& mailbox) {
  DVLOG_FUNC(1);
  listener_->OnSharedImageMailboxBound(mailbox);
}

void DCOMPTextureHost::OnOutputRectChange(const gfx::Rect& output_rect) {
  DVLOG_FUNC(3);
  listener_->OnOutputRectChange(output_rect);
}

}  // namespace content