blob: bc2742518f54e869cb4516c305dba9370c94daf5 [file] [log] [blame]
// Copyright 2018 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 <stddef.h>
#include <stdint.h>
#include <memory>
#include <vector>
#include "base/containers/queue.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "base/synchronization/lock.h"
#include "base/thread_annotations.h"
#include "gpu/command_buffer/service/sequence_id.h"
#include "gpu/ipc/common/gpu_messages.h"
#include "third_party/skia/include/core/SkImageInfo.h"
#include "ui/gfx/geometry/size.h"
namespace base {
class SingleThreadTaskRunner;
} // namespace base
namespace IPC {
class Message;
} // namespace IPC
namespace gpu {
class GpuChannel;
class ImageDecodeAcceleratorWorker;
class SyncPointClientState;
// Processes incoming image decode requests from renderers: it schedules the
// decode with the appropriate hardware decode accelerator and releases sync
// tokens as decodes complete. These sync tokens must be generated on the client
// side (in ImageDecodeAcceleratorProxy) using the following information:
// - The command buffer namespace is GPU_IO.
// - The command buffer ID is created using the
// CommandBufferIdFromChannelAndRoute() function using
// GpuChannelReservedRoutes::kImageDecodeAccelerator as the route ID.
// - The release count should be incremented for each decode request.
// An object of this class is meant to be used in
// both the IO thread (for receiving decode requests) and the main thread (for
// processing completed decodes).
class ImageDecodeAcceleratorStub
: public base::RefCountedThreadSafe<ImageDecodeAcceleratorStub> {
// TODO(andrescj): right now, we only accept one worker to be used for JPEG
// decoding. If we want to use multiple workers, we need to ensure that sync
// tokens are released in order.
ImageDecodeAcceleratorStub(ImageDecodeAcceleratorWorker* worker,
GpuChannel* channel,
int32_t route_id);
// Processes a message from the renderer. Should be called on the IO thread.
bool OnMessageReceived(const IPC::Message& msg);
// Called on the main thread to indicate that |channel_| should no longer be
// used.
void Shutdown();
friend class base::RefCountedThreadSafe<ImageDecodeAcceleratorStub>;
void OnScheduleImageDecode(
const GpuChannelMsg_ScheduleImageDecode_Params& params,
uint64_t release_count);
// Creates the service-side cache entry for a completed decode and releases
// the decode sync token.
void ProcessCompletedDecode(GpuChannelMsg_ScheduleImageDecode_Params params,
uint64_t decode_release_count);
// The |worker_| calls this when a decode is completed. If the decode is
// successful (i.e., |output| is not empty), |sequence_| will be enabled so
// that ProcessCompletedDecode() is called. If the decode is not successful,
// we destroy the channel (see OnError()).
void OnDecodeCompleted(gfx::Size expected_output_size,
std::vector<uint8_t> output,
size_t row_bytes,
SkImageInfo image_info);
// Triggers the destruction of the channel asynchronously and makes it so that
// we stop accepting completed decodes. On entry, |channel_| must not be
// nullptr.
// The object to which the actual decoding can be delegated.
ImageDecodeAcceleratorWorker* worker_ = nullptr;
struct CompletedDecode {
CompletedDecode(std::vector<uint8_t> output,
size_t row_bytes,
SkImageInfo image_info);
std::vector<uint8_t> output;
size_t row_bytes;
SkImageInfo image_info;
base::Lock lock_;
GpuChannel* channel_ GUARDED_BY(lock_) = nullptr;
SequenceId sequence_ GUARDED_BY(lock_);
scoped_refptr<SyncPointClientState> sync_point_client_state_
base::queue<std::unique_ptr<CompletedDecode>> pending_completed_decodes_
bool destroying_channel_ GUARDED_BY(lock_) = false;
uint64_t last_release_count_ GUARDED_BY(lock_) = 0;
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
} // namespace gpu