add Comments

This commit is contained in:
2026-07-13 10:19:30 +08:00
parent 3c9592da45
commit e77de49406
12 changed files with 444 additions and 16 deletions
+42
View File
@@ -9,12 +9,16 @@
namespace olive
{
// Stores the requested backend name; the actual backend may later become
// OpenGL if loading or availability checks require a Vulkan fallback.
DynamicRenderer::DynamicRenderer(const QString &backend, QObject *parent)
: Renderer(parent)
, backend_(backend.toLower())
{
}
// Tears down the backend in the reverse order used by Load(): release renderer
// resources, destroy the opaque backend object, then unload the shared library.
DynamicRenderer::~DynamicRenderer()
{
Destroy();
@@ -28,6 +32,9 @@ DynamicRenderer::~DynamicRenderer()
}
}
// Builds the private backend library path for the current platform.
// The search is intentionally restricted to Oak-controlled directories so a
// system libGL/libvulkan loader is never mistaken for an Oak render backend.
QString DynamicRenderer::LibraryFilename() const
{
const QString base = backend_ == QStringLiteral("vulkan")
@@ -58,6 +65,9 @@ QString DynamicRenderer::LibraryFilename() const
return candidates.first();
}
// Loads the selected backend, resolves its C ABI table, creates the opaque
// backend object, and optionally falls back from Vulkan to OpenGL when runtime
// availability checks fail.
bool DynamicRenderer::Load()
{
if (handle_) {
@@ -106,6 +116,8 @@ bool DynamicRenderer::Load()
return handle_ != nullptr;
}
// Resolves the mandatory C ABI entry points from the loaded shared library.
// Optional information probes are resolved after the required render interface.
bool DynamicRenderer::ResolveFunctions()
{
ResetFunctions();
@@ -155,6 +167,8 @@ bool DynamicRenderer::ResolveFunctions()
return true;
}
// Discards a partially-created backend and restarts loading with the OpenGL
// backend. This keeps RenderManager's fallback path inside the adapter.
bool DynamicRenderer::FallbackToOpenGL()
{
if (handle_ && destroy_) {
@@ -169,6 +183,8 @@ bool DynamicRenderer::FallbackToOpenGL()
return Load();
}
// Clears all cached C function pointers so a failed backend cannot leave stale
// call targets behind for a later fallback load.
void DynamicRenderer::ResetFunctions()
{
create_ = nullptr;
@@ -195,16 +211,20 @@ void DynamicRenderer::ResetFunctions()
opengl_context_ = nullptr;
}
// Returns backend metadata exposed by the dynamic library when available.
bool DynamicRenderer::GetBackendInfo(OakRenderBackendInfo *out_info) const
{
return handle_ && get_info_ && out_info && get_info_(handle_, out_info);
}
// Initializes the loaded backend using its own context/device creation path.
bool DynamicRenderer::Init()
{
return Load() && init_(handle_);
}
// Initializes an OpenGL backend against an existing widget context; non-OpenGL
// backends may ignore the context on the library side.
bool DynamicRenderer::InitWithOpenGLContext(QOpenGLContext *context)
{
if (!Load()) {
@@ -214,6 +234,8 @@ bool DynamicRenderer::InitWithOpenGLContext(QOpenGLContext *context)
return true;
}
// Forwards post-destroy cleanup to the backend while the library is still
// loaded and its symbols are still valid.
void DynamicRenderer::PostDestroy()
{
if (handle_ && post_destroy_) {
@@ -221,6 +243,8 @@ void DynamicRenderer::PostDestroy()
}
}
// Runs backend post-initialization after Init/InitWithOpenGLContext has
// established the device or GL context.
void DynamicRenderer::PostInit()
{
if (handle_) {
@@ -228,12 +252,15 @@ void DynamicRenderer::PostInit()
}
}
// Forwards render target clearing through the C ABI.
void DynamicRenderer::ClearDestination(Texture *texture, double r, double g,
double b, double a)
{
clear_destination_(handle_, texture, r, g, b, a);
}
// Creates a backend-native shader and receives the result as an opaque QVariant
// because this first-generation ABI still shares C++/Qt types between modules.
QVariant DynamicRenderer::CreateNativeShader(ShaderCode code)
{
QVariant out;
@@ -241,11 +268,13 @@ QVariant DynamicRenderer::CreateNativeShader(ShaderCode code)
return out;
}
// Releases a backend-native shader handle.
void DynamicRenderer::DestroyNativeShader(QVariant shader)
{
destroy_native_shader_(handle_, &shader);
}
// Uploads CPU pixel data into a backend texture through the dynamic ABI.
void DynamicRenderer::UploadToTexture(const QVariant &handle,
const VideoParams &params, const void *data,
int linesize)
@@ -253,6 +282,7 @@ void DynamicRenderer::UploadToTexture(const QVariant &handle,
upload_to_texture_(handle_, &handle, &params, data, linesize);
}
// Downloads backend texture data into a caller-provided CPU buffer.
void DynamicRenderer::DownloadFromTexture(const QVariant &handle,
const VideoParams &params, void *data,
int linesize)
@@ -260,11 +290,13 @@ void DynamicRenderer::DownloadFromTexture(const QVariant &handle,
download_from_texture_(handle_, &handle, &params, data, linesize);
}
// Waits for backend work to become visible to subsequent CPU or GPU consumers.
void DynamicRenderer::Flush()
{
flush_(handle_);
}
// Reads a single pixel through the backend-provided readback hook.
Color DynamicRenderer::GetPixelFromTexture(Texture *texture, const QPointF &pt)
{
Color out;
@@ -272,6 +304,8 @@ Color DynamicRenderer::GetPixelFromTexture(Texture *texture, const QPointF &pt)
return out;
}
// Exposes the wrapped OpenGL context when the backend is OpenGL; Vulkan returns
// null so callers can avoid GL-only paths.
QOpenGLContext *DynamicRenderer::OpenGLContext() const
{
return opengl_context_ && handle_
@@ -279,11 +313,13 @@ QOpenGLContext *DynamicRenderer::OpenGLContext() const
: nullptr;
}
// Reports the effective backend after any load-time fallback has completed.
bool DynamicRenderer::IsOpenGL() const
{
return backend_ == QStringLiteral("opengl");
}
// Dispatches a shader blit to the loaded backend.
void DynamicRenderer::Blit(QVariant shader, AcceleratedJob &job,
Texture *destination, VideoParams destination_params,
bool clear_destination)
@@ -292,6 +328,7 @@ void DynamicRenderer::Blit(QVariant shader, AcceleratedJob &job,
clear_destination);
}
// Allocates a backend-native texture and wraps its opaque handle in QVariant.
QVariant DynamicRenderer::CreateNativeTexture(int width, int height, int depth,
PixelFormat format, int channel_count,
const void *data, int linesize)
@@ -302,11 +339,14 @@ QVariant DynamicRenderer::CreateNativeTexture(int width, int height, int depth,
return out;
}
// Releases a backend-native texture handle.
void DynamicRenderer::DestroyNativeTexture(QVariant texture)
{
destroy_native_texture_(handle_, &texture);
}
// Releases renderer-owned backend resources before the backend object itself is
// destroyed.
void DynamicRenderer::DestroyInternal()
{
if (handle_) {
@@ -314,6 +354,7 @@ void DynamicRenderer::DestroyInternal()
}
}
// Exposes OFX OpenGL output binding through the dynamic backend when supported.
void DynamicRenderer::AttachOutputTexture(Texture *texture)
{
if (attach_output_texture_ && texture) {
@@ -322,6 +363,7 @@ void DynamicRenderer::AttachOutputTexture(Texture *texture)
}
}
// Clears any OFX output texture binding owned by the backend.
void DynamicRenderer::DetachOutputTexture()
{
if (detach_output_texture_) {
+30
View File
@@ -11,62 +11,92 @@
namespace olive
{
// C++ Renderer adapter that loads an Oak render backend shared library and
// forwards Renderer calls through the backend's C ABI.
class DynamicRenderer : public Renderer, public OpenGLContextProvider {
Q_OBJECT
public:
// Stores the requested backend name; Load() may change it after fallback.
explicit DynamicRenderer(const QString &backend, QObject *parent = nullptr);
// Destroys backend resources and unloads the dynamic library.
virtual ~DynamicRenderer() override;
using Renderer::Blit;
// Loads the backend library, resolves C ABI symbols, and creates the handle.
bool Load();
// Initializes an OpenGL backend with a caller-owned viewer context.
bool InitWithOpenGLContext(QOpenGLContext *context);
// Retrieves backend metadata through the optional info entry point.
bool GetBackendInfo(OakRenderBackendInfo *out_info) const;
// Returns the effective backend after any load-time fallback.
QString backend_name() const
{
return backend_;
}
// Initializes the backend using its default device/context path.
virtual bool Init() override;
// Runs backend post-destroy cleanup.
virtual void PostDestroy() override;
// Runs backend post-init setup.
virtual void PostInit() override;
// Clears either a native texture destination or the backend output target.
virtual void ClearDestination(Texture *texture = nullptr,
double r = 0.0, double g = 0.0,
double b = 0.0, double a = 0.0) override;
// Creates a native shader through the dynamic backend.
virtual QVariant CreateNativeShader(ShaderCode code) override;
// Destroys a native shader through the dynamic backend.
virtual void DestroyNativeShader(QVariant shader) override;
// Uploads CPU pixels to a backend texture.
virtual void UploadToTexture(const QVariant &handle,
const VideoParams &params, const void *data,
int linesize) override;
// Downloads backend texture pixels to CPU memory.
virtual void DownloadFromTexture(const QVariant &handle,
const VideoParams &params, void *data,
int linesize) override;
// Waits for backend work to complete.
virtual void Flush() override;
// Reads one pixel from a backend texture.
virtual Color GetPixelFromTexture(Texture *texture,
const QPointF &pt) override;
// Returns the wrapped OpenGL context for OpenGL backends.
virtual QOpenGLContext *OpenGLContext() const override;
// Reports whether the effective backend is OpenGL.
virtual bool IsOpenGL() const override;
// Attaches a texture for OFX OpenGL output when supported.
virtual void AttachOutputTexture(Texture *texture) override;
// Detaches any OFX output texture binding when supported.
virtual void DetachOutputTexture() override;
protected:
// Dispatches a shader blit through the dynamic backend.
virtual void Blit(QVariant shader, AcceleratedJob &job,
Texture *destination, VideoParams destination_params,
bool clear_destination) override;
// Allocates a native texture through the dynamic backend.
virtual QVariant CreateNativeTexture(int width, int height, int depth,
PixelFormat format, int channel_count,
const void *data = nullptr,
int linesize = 0) override;
// Releases a native texture through the dynamic backend.
virtual void DestroyNativeTexture(QVariant texture) override;
// Releases backend-owned renderer resources.
virtual void DestroyInternal() override;
private:
// Resolves required backend C ABI symbols.
bool ResolveFunctions();
// Replaces a failed Vulkan backend with OpenGL.
bool FallbackToOpenGL();
// Clears all cached function pointers.
void ResetFunctions();
// Resolves the private backend library path.
QString LibraryFilename() const;
QString backend_;
+26
View File
@@ -14,14 +14,17 @@
extern "C" {
#endif
/* Opaque pointer to the backend-owned C++ renderer object. */
typedef void *OakRenderBackendHandle;
/* Identifies the concrete backend behind a dynamically loaded library. */
enum OakRenderBackendKind {
OAK_RENDER_BACKEND_UNKNOWN = 0,
OAK_RENDER_BACKEND_OPENGL = 1,
OAK_RENDER_BACKEND_VULKAN = 2
};
/* Capability bits advertised by a backend through oak_renderer_get_info(). */
enum OakRenderBackendCapability {
OAK_RENDER_BACKEND_CAP_TEXTURES = 1ULL << 0,
OAK_RENDER_BACKEND_CAP_SHADERS = 1ULL << 1,
@@ -32,6 +35,7 @@ enum OakRenderBackendCapability {
OAK_RENDER_BACKEND_CAP_DEVICE = 1ULL << 6
};
/* Static and runtime metadata returned by the backend. */
struct OakRenderBackendInfo {
uint32_t abi_version;
uint32_t kind;
@@ -40,52 +44,74 @@ struct OakRenderBackendInfo {
const char *status;
};
/* Creates a backend renderer object. */
typedef OakRenderBackendHandle (*OakBackendCreateFn)(void *parent);
/* Destroys a backend renderer object created by OakBackendCreateFn. */
typedef void (*OakBackendDestroyFn)(OakRenderBackendHandle handle);
/* Queries backend metadata and capability bits. */
typedef bool (*OakBackendGetInfoFn)(OakRenderBackendHandle handle,
struct OakRenderBackendInfo *out_info);
/* Checks whether the backend can run on the current machine. */
typedef bool (*OakBackendIsAvailableFn)(OakRenderBackendHandle handle);
/* Initializes backend-owned device/context resources. */
typedef bool (*OakBackendInitFn)(OakRenderBackendHandle handle);
/* Initializes the backend against a caller-supplied GL context when applicable. */
typedef void (*OakBackendInitWithContextFn)(OakRenderBackendHandle handle,
void *context);
/* Runs backend post-initialization after the device/context exists. */
typedef void (*OakBackendPostInitFn)(OakRenderBackendHandle handle);
/* Runs backend post-destroy cleanup before the library unloads. */
typedef void (*OakBackendPostDestroyFn)(OakRenderBackendHandle handle);
/* Destroys renderer-owned native resources. */
typedef void (*OakBackendDestroyInternalFn)(OakRenderBackendHandle handle);
/* Clears a texture destination or implicit output target. */
typedef void (*OakBackendClearDestinationFn)(OakRenderBackendHandle handle,
void *texture, double r, double g,
double b, double a);
/* Creates a native texture and writes a QVariant-compatible handle. */
typedef void (*OakBackendCreateNativeTextureFn)(OakRenderBackendHandle handle,
int width, int height, int depth,
int format, int channel_count,
const void *data, int linesize,
void *out_variant);
/* Destroys a native texture represented by a QVariant-compatible handle. */
typedef void (*OakBackendDestroyNativeTextureFn)(OakRenderBackendHandle handle,
const void *variant);
/* Creates a native shader and writes a QVariant-compatible handle. */
typedef void (*OakBackendCreateNativeShaderFn)(OakRenderBackendHandle handle,
const void *shader_code,
void *out_variant);
/* Destroys a native shader represented by a QVariant-compatible handle. */
typedef void (*OakBackendDestroyNativeShaderFn)(OakRenderBackendHandle handle,
const void *variant);
/* Uploads CPU pixel data to a native texture. */
typedef void (*OakBackendUploadToTextureFn)(OakRenderBackendHandle handle,
const void *variant,
const void *video_params,
const void *data, int linesize);
/* Downloads native texture pixels into caller-owned CPU memory. */
typedef void (*OakBackendDownloadFromTextureFn)(OakRenderBackendHandle handle,
const void *variant,
const void *video_params,
void *data, int linesize);
/* Waits for backend work that must be visible to later operations. */
typedef void (*OakBackendFlushFn)(OakRenderBackendHandle handle);
/* Reads one pixel from a texture. */
typedef void (*OakBackendGetPixelFromTextureFn)(OakRenderBackendHandle handle,
void *texture, const void *point,
void *out_color);
/* Executes a shader blit job. */
typedef void (*OakBackendBlitFn)(OakRenderBackendHandle handle,
const void *shader, void *job,
void *destination,
const void *destination_params,
bool clear_destination);
/* Attaches an output texture for OFX OpenGL rendering when supported. */
typedef void (*OakBackendAttachOutputTextureFn)(OakRenderBackendHandle handle,
const void *texture_id);
/* Detaches an OFX output texture when supported. */
typedef void (*OakBackendDetachOutputTextureFn)(OakRenderBackendHandle handle);
/* Returns the backend OpenGL context, or null for non-OpenGL backends. */
typedef void *(*OakBackendOpenGLContextFn)(OakRenderBackendHandle handle);
#ifdef __cplusplus