blob: c22a2030cff8f4829b1ad814896a83b574732526 [file] [log] [blame]
/*
* Copyright 2022 The ChromiumOS Authors
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef CAMERA_GPU_GPU_RESOURCES_H_
#define CAMERA_GPU_GPU_RESOURCES_H_
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <hardware/gralloc.h>
#include <base/location.h>
#include <base/memory/scoped_refptr.h>
#include <base/sequence_checker.h>
#include <base/task/single_thread_task_runner.h>
#include "cros-camera/camera_buffer_manager.h"
#include "cros-camera/camera_thread.h"
#include "cros-camera/export.h"
#include "gpu/egl/egl_context.h"
#include "gpu/image_processor.h"
#include "gpu/shared_image.h"
// The tracing macros from perfetto_sdk and libchrome clashes when building
// some test packages.
//
// TODO(jcliang): Enable the trace event once b/244257898 is fixed.
// #include "gpu/tracing.h"
namespace cros {
class GpuResources;
struct GpuResourcesOptions {
// The name of the GpuResources instance.
std::string name = "GpuResources";
// The GpuResources instance to share resources with.
GpuResources* shared_resources = nullptr;
};
// GpuResources holds the resources required to perform GPU operations. A
// GpuResources instance manages a GPU thread and the context running on the
// thread. There's only one GpuResources instance in the whole camera process.
// It's guaranteed that the GpuResources is created before we load the camera
// HAL adapter, and is destroyed only after the HAL adapter is destroyed.
//
// Processing blocks in the camera service can run GPU operations using the
// PostGpuTask*() helpers. By sharing the GPU context and running on the same
// thread, the different processing blocks can share GPU resources like textures
// and shader programs.
//
// The GetCache() and SetCache() allow a processing block to preserve states
// across different camera sessions. For example, some GL processing pipeline
// running ML models can take several hundreds of ms to initialize. It's
// desirable to create the pipeline once and reuse it across different camera
// device sessions.
class CROS_CAMERA_EXPORT GpuResources {
public:
// A user can extend the CacheContainer class to store the data they want and
// use GetCache()/SetCache() to fetch/store the cached data.
class CacheContainer {
public:
virtual ~CacheContainer() = default;
};
explicit GpuResources(
const GpuResourcesOptions& options = GpuResourcesOptions());
~GpuResources();
// Disallow copy, assign and move since there should be only one instance of
// GpuResources in the process.
GpuResources(GpuResources&) = delete;
GpuResources& operator=(GpuResources&) = delete;
GpuResources(GpuResources&&) = delete;
GpuResources& operator=(GpuResources&&) = delete;
[[nodiscard]] static bool IsSupported();
[[nodiscard]] bool Initialize();
template <typename T>
int PostGpuTask(const base::Location& from_here,
base::OnceCallback<T()> task) {
return gpu_thread_.PostTaskAsync(from_here, std::move(task));
}
template <typename T>
int PostGpuTaskSync(const base::Location& from_here,
base::OnceCallback<T()> task,
T* result) {
return gpu_thread_.PostTaskSync(from_here, std::move(task), result);
}
int PostGpuTaskSync(const base::Location& from_here, base::OnceClosure task) {
return gpu_thread_.PostTaskSync(from_here, std::move(task));
}
scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner() const {
return gpu_thread_.task_runner();
}
const EglContext* egl_context() const { return egl_context_.get(); }
// All the methods below need to run on |gpu_thread_|.
// Gets and sets a cache entry keyed by |id|.
template <typename T>
T* GetCache(const std::string id) {
DCHECK(gpu_thread_.IsCurrentThread());
// The tracing macros from perfetto_sdk and libchrome clashes when building
// some test packages.
//
// TODO(jcliang): Enable the trace event once b/244257898 is fixed.
// TRACE_GPU();
if (cache_.count(id) == 1) {
return reinterpret_cast<T*>(cache_.at(id).get());
}
return nullptr;
}
void SetCache(const std::string id,
std::unique_ptr<CacheContainer> container);
void ClearCache(const std::string id);
// Returns a GpuImageProcessor instance pre-allocated by the GpuResources
// instance. It should be run on GpuResources::gpu_task_runner().
GpuImageProcessor* image_processor() const { return image_processor_.get(); }
// Dumps the raw pixel data from shared image |image| to |output_file_path|.
void DumpSharedImage(const SharedImage& image,
base::FilePath output_file_path);
private:
void InitializeOnGpuThread(base::OnceCallback<void(bool)> cb);
CameraThread gpu_thread_;
GpuResources* shared_resources_ = nullptr;
// Access to the following members must be sequenced on |gpu_thread_|.
std::unique_ptr<EglContext> egl_context_;
std::unique_ptr<GpuImageProcessor> image_processor_;
std::map<std::string, std::unique_ptr<CacheContainer>> cache_;
// A buffer that's only allocated when we need to dump the intermediate images
// for debugging.
ScopedBufferHandle dump_buffer_ = nullptr;
SharedImage dump_image_;
// A sequence checker to verify we start and stop |gpu_thread_| on the same
// sequence.
SEQUENCE_CHECKER(gpu_thread_sequence);
};
} // namespace cros
#endif // CAMERA_GPU_GPU_RESOURCES_H_