Add dynamic render backend adapter scaffold
This commit is contained in:
@@ -26,6 +26,9 @@ set(OLIVE_SOURCES
|
||||
render/audioplaybackcache.h
|
||||
render/audiowaveformcache.cpp
|
||||
render/audiowaveformcache.h
|
||||
render/backend/dynamicrenderer.cpp
|
||||
render/backend/dynamicrenderer.h
|
||||
render/backend/renderbackend_c.h
|
||||
render/cancelatom.h
|
||||
render/colorprocessor.cpp
|
||||
render/colorprocessor.h
|
||||
|
||||
@@ -0,0 +1,228 @@
|
||||
#include "dynamicrenderer.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QOpenGLContext>
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
DynamicRenderer::DynamicRenderer(const QString &backend, QObject *parent)
|
||||
: Renderer(parent)
|
||||
, backend_(backend.toLower())
|
||||
{
|
||||
}
|
||||
|
||||
DynamicRenderer::~DynamicRenderer()
|
||||
{
|
||||
Destroy();
|
||||
PostDestroy();
|
||||
if (handle_ && destroy_) {
|
||||
destroy_(handle_);
|
||||
handle_ = nullptr;
|
||||
}
|
||||
if (library_.isLoaded()) {
|
||||
library_.unload();
|
||||
}
|
||||
}
|
||||
|
||||
QString DynamicRenderer::LibraryFilename() const
|
||||
{
|
||||
const QString base = backend_ == QStringLiteral("vulkan")
|
||||
? QStringLiteral("oakvulkan")
|
||||
: QStringLiteral("oakgl");
|
||||
#if defined(Q_OS_WIN)
|
||||
const QString filename = base + QStringLiteral(".dll");
|
||||
#elif defined(Q_OS_MAC)
|
||||
const QString filename = QStringLiteral("lib") + base + QStringLiteral(".dylib");
|
||||
#else
|
||||
const QString filename = QStringLiteral("lib") + base + QStringLiteral(".so");
|
||||
#endif
|
||||
return QDir(QCoreApplication::applicationDirPath()).filePath(
|
||||
filename);
|
||||
}
|
||||
|
||||
bool DynamicRenderer::Load()
|
||||
{
|
||||
if (handle_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
library_.setFileName(LibraryFilename());
|
||||
if (!library_.load()) {
|
||||
if (backend_ == QStringLiteral("vulkan")) {
|
||||
qWarning() << "Failed to load Vulkan render backend"
|
||||
<< library_.fileName() << library_.errorString()
|
||||
<< "falling back to OpenGL backend";
|
||||
backend_ = QStringLiteral("opengl");
|
||||
library_.setFileName(LibraryFilename());
|
||||
}
|
||||
|
||||
if (!library_.load()) {
|
||||
qWarning() << "Failed to load render backend" << backend_
|
||||
<< library_.fileName() << library_.errorString();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ResolveFunctions()) {
|
||||
qWarning() << "Render backend is missing required symbols" << backend_;
|
||||
library_.unload();
|
||||
return false;
|
||||
}
|
||||
|
||||
handle_ = create_(this->parent());
|
||||
return handle_ != nullptr;
|
||||
}
|
||||
|
||||
bool DynamicRenderer::ResolveFunctions()
|
||||
{
|
||||
#define RESOLVE(member, type, symbol) \
|
||||
member = reinterpret_cast<type>(library_.resolve(symbol)); \
|
||||
if (!member) return false
|
||||
|
||||
RESOLVE(create_, OakBackendCreateFn, "oak_renderer_create");
|
||||
RESOLVE(destroy_, OakBackendDestroyFn, "oak_renderer_destroy");
|
||||
RESOLVE(init_, OakBackendInitFn, "oak_renderer_init");
|
||||
RESOLVE(init_with_context_, OakBackendInitWithContextFn,
|
||||
"oak_renderer_init_with_context");
|
||||
RESOLVE(post_init_, OakBackendPostInitFn, "oak_renderer_post_init");
|
||||
RESOLVE(post_destroy_, OakBackendPostDestroyFn,
|
||||
"oak_renderer_post_destroy");
|
||||
RESOLVE(destroy_internal_, OakBackendDestroyInternalFn,
|
||||
"oak_renderer_destroy_internal");
|
||||
RESOLVE(clear_destination_, OakBackendClearDestinationFn,
|
||||
"oak_renderer_clear_destination");
|
||||
RESOLVE(create_native_texture_, OakBackendCreateNativeTextureFn,
|
||||
"oak_renderer_create_native_texture");
|
||||
RESOLVE(destroy_native_texture_, OakBackendDestroyNativeTextureFn,
|
||||
"oak_renderer_destroy_native_texture");
|
||||
RESOLVE(create_native_shader_, OakBackendCreateNativeShaderFn,
|
||||
"oak_renderer_create_native_shader");
|
||||
RESOLVE(destroy_native_shader_, OakBackendDestroyNativeShaderFn,
|
||||
"oak_renderer_destroy_native_shader");
|
||||
RESOLVE(upload_to_texture_, OakBackendUploadToTextureFn,
|
||||
"oak_renderer_upload_to_texture");
|
||||
RESOLVE(download_from_texture_, OakBackendDownloadFromTextureFn,
|
||||
"oak_renderer_download_from_texture");
|
||||
RESOLVE(flush_, OakBackendFlushFn, "oak_renderer_flush");
|
||||
RESOLVE(get_pixel_from_texture_, OakBackendGetPixelFromTextureFn,
|
||||
"oak_renderer_get_pixel_from_texture");
|
||||
RESOLVE(blit_, OakBackendBlitFn, "oak_renderer_blit");
|
||||
RESOLVE(opengl_context_, OakBackendOpenGLContextFn,
|
||||
"oak_renderer_opengl_context");
|
||||
#undef RESOLVE
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DynamicRenderer::Init()
|
||||
{
|
||||
return Load() && init_(handle_);
|
||||
}
|
||||
|
||||
bool DynamicRenderer::InitWithOpenGLContext(QOpenGLContext *context)
|
||||
{
|
||||
if (!Load()) {
|
||||
return false;
|
||||
}
|
||||
init_with_context_(handle_, context);
|
||||
return true;
|
||||
}
|
||||
|
||||
void DynamicRenderer::PostDestroy()
|
||||
{
|
||||
if (handle_ && post_destroy_) {
|
||||
post_destroy_(handle_);
|
||||
}
|
||||
}
|
||||
|
||||
void DynamicRenderer::PostInit()
|
||||
{
|
||||
if (handle_) {
|
||||
post_init_(handle_);
|
||||
}
|
||||
}
|
||||
|
||||
void DynamicRenderer::ClearDestination(Texture *texture, double r, double g,
|
||||
double b, double a)
|
||||
{
|
||||
clear_destination_(handle_, texture, r, g, b, a);
|
||||
}
|
||||
|
||||
QVariant DynamicRenderer::CreateNativeShader(ShaderCode code)
|
||||
{
|
||||
QVariant out;
|
||||
create_native_shader_(handle_, &code, &out);
|
||||
return out;
|
||||
}
|
||||
|
||||
void DynamicRenderer::DestroyNativeShader(QVariant shader)
|
||||
{
|
||||
destroy_native_shader_(handle_, &shader);
|
||||
}
|
||||
|
||||
void DynamicRenderer::UploadToTexture(const QVariant &handle,
|
||||
const VideoParams ¶ms, const void *data,
|
||||
int linesize)
|
||||
{
|
||||
upload_to_texture_(handle_, &handle, ¶ms, data, linesize);
|
||||
}
|
||||
|
||||
void DynamicRenderer::DownloadFromTexture(const QVariant &handle,
|
||||
const VideoParams ¶ms, void *data,
|
||||
int linesize)
|
||||
{
|
||||
download_from_texture_(handle_, &handle, ¶ms, data, linesize);
|
||||
}
|
||||
|
||||
void DynamicRenderer::Flush()
|
||||
{
|
||||
flush_(handle_);
|
||||
}
|
||||
|
||||
Color DynamicRenderer::GetPixelFromTexture(Texture *texture, const QPointF &pt)
|
||||
{
|
||||
Color out;
|
||||
get_pixel_from_texture_(handle_, texture, &pt, &out);
|
||||
return out;
|
||||
}
|
||||
|
||||
QOpenGLContext *DynamicRenderer::OpenGLContext() const
|
||||
{
|
||||
return opengl_context_ && handle_
|
||||
? static_cast<QOpenGLContext *>(opengl_context_(handle_))
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
void DynamicRenderer::Blit(QVariant shader, AcceleratedJob &job,
|
||||
Texture *destination, VideoParams destination_params,
|
||||
bool clear_destination)
|
||||
{
|
||||
blit_(handle_, &shader, &job, destination, &destination_params,
|
||||
clear_destination);
|
||||
}
|
||||
|
||||
QVariant DynamicRenderer::CreateNativeTexture(int width, int height, int depth,
|
||||
PixelFormat format, int channel_count,
|
||||
const void *data, int linesize)
|
||||
{
|
||||
QVariant out;
|
||||
create_native_texture_(handle_, width, height, depth, format, channel_count,
|
||||
data, linesize, &out);
|
||||
return out;
|
||||
}
|
||||
|
||||
void DynamicRenderer::DestroyNativeTexture(QVariant texture)
|
||||
{
|
||||
destroy_native_texture_(handle_, &texture);
|
||||
}
|
||||
|
||||
void DynamicRenderer::DestroyInternal()
|
||||
{
|
||||
if (handle_) {
|
||||
destroy_internal_(handle_);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
#ifndef DYNAMICRENDERER_H
|
||||
#define DYNAMICRENDERER_H
|
||||
|
||||
#include <QLibrary>
|
||||
#include <QString>
|
||||
|
||||
#include "render/backend/renderbackend_c.h"
|
||||
#include "render/opengl/openglcontextprovider.h"
|
||||
#include "render/renderer.h"
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class DynamicRenderer : public Renderer, public OpenGLContextProvider {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DynamicRenderer(const QString &backend, QObject *parent = nullptr);
|
||||
virtual ~DynamicRenderer() override;
|
||||
|
||||
bool Load();
|
||||
bool InitWithOpenGLContext(QOpenGLContext *context);
|
||||
|
||||
virtual bool Init() override;
|
||||
virtual void PostDestroy() override;
|
||||
virtual void PostInit() override;
|
||||
virtual void ClearDestination(Texture *texture = nullptr,
|
||||
double r = 0.0, double g = 0.0,
|
||||
double b = 0.0, double a = 0.0) override;
|
||||
virtual QVariant CreateNativeShader(ShaderCode code) override;
|
||||
virtual void DestroyNativeShader(QVariant shader) override;
|
||||
virtual void UploadToTexture(const QVariant &handle,
|
||||
const VideoParams ¶ms, const void *data,
|
||||
int linesize) override;
|
||||
virtual void DownloadFromTexture(const QVariant &handle,
|
||||
const VideoParams ¶ms, void *data,
|
||||
int linesize) override;
|
||||
virtual void Flush() override;
|
||||
virtual Color GetPixelFromTexture(Texture *texture,
|
||||
const QPointF &pt) override;
|
||||
virtual QOpenGLContext *OpenGLContext() const override;
|
||||
|
||||
protected:
|
||||
virtual void Blit(QVariant shader, AcceleratedJob &job,
|
||||
Texture *destination, VideoParams destination_params,
|
||||
bool clear_destination) override;
|
||||
virtual QVariant CreateNativeTexture(int width, int height, int depth,
|
||||
PixelFormat format, int channel_count,
|
||||
const void *data = nullptr,
|
||||
int linesize = 0) override;
|
||||
virtual void DestroyNativeTexture(QVariant texture) override;
|
||||
virtual void DestroyInternal() override;
|
||||
|
||||
private:
|
||||
bool ResolveFunctions();
|
||||
QString LibraryFilename() const;
|
||||
|
||||
QString backend_;
|
||||
QLibrary library_;
|
||||
OakRenderBackendHandle handle_ = nullptr;
|
||||
|
||||
OakBackendCreateFn create_ = nullptr;
|
||||
OakBackendDestroyFn destroy_ = nullptr;
|
||||
OakBackendInitFn init_ = nullptr;
|
||||
OakBackendInitWithContextFn init_with_context_ = nullptr;
|
||||
OakBackendPostInitFn post_init_ = nullptr;
|
||||
OakBackendPostDestroyFn post_destroy_ = nullptr;
|
||||
OakBackendDestroyInternalFn destroy_internal_ = nullptr;
|
||||
OakBackendClearDestinationFn clear_destination_ = nullptr;
|
||||
OakBackendCreateNativeTextureFn create_native_texture_ = nullptr;
|
||||
OakBackendDestroyNativeTextureFn destroy_native_texture_ = nullptr;
|
||||
OakBackendCreateNativeShaderFn create_native_shader_ = nullptr;
|
||||
OakBackendDestroyNativeShaderFn destroy_native_shader_ = nullptr;
|
||||
OakBackendUploadToTextureFn upload_to_texture_ = nullptr;
|
||||
OakBackendDownloadFromTextureFn download_from_texture_ = nullptr;
|
||||
OakBackendFlushFn flush_ = nullptr;
|
||||
OakBackendGetPixelFromTextureFn get_pixel_from_texture_ = nullptr;
|
||||
OakBackendBlitFn blit_ = nullptr;
|
||||
OakBackendOpenGLContextFn opengl_context_ = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // DYNAMICRENDERER_H
|
||||
@@ -0,0 +1,64 @@
|
||||
#ifndef RENDERBACKEND_C_H
|
||||
#define RENDERBACKEND_C_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define OAK_RENDER_BACKEND_EXPORT extern "C" __declspec(dllexport)
|
||||
#else
|
||||
#define OAK_RENDER_BACKEND_EXPORT extern "C" __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void *OakRenderBackendHandle;
|
||||
|
||||
typedef OakRenderBackendHandle (*OakBackendCreateFn)(void *parent);
|
||||
typedef void (*OakBackendDestroyFn)(OakRenderBackendHandle handle);
|
||||
typedef bool (*OakBackendInitFn)(OakRenderBackendHandle handle);
|
||||
typedef void (*OakBackendInitWithContextFn)(OakRenderBackendHandle handle,
|
||||
void *context);
|
||||
typedef void (*OakBackendPostInitFn)(OakRenderBackendHandle handle);
|
||||
typedef void (*OakBackendPostDestroyFn)(OakRenderBackendHandle handle);
|
||||
typedef void (*OakBackendDestroyInternalFn)(OakRenderBackendHandle handle);
|
||||
typedef void (*OakBackendClearDestinationFn)(OakRenderBackendHandle handle,
|
||||
void *texture, double r, double g,
|
||||
double b, double a);
|
||||
typedef void (*OakBackendCreateNativeTextureFn)(OakRenderBackendHandle handle,
|
||||
int width, int height, int depth,
|
||||
int format, int channel_count,
|
||||
const void *data, int linesize,
|
||||
void *out_variant);
|
||||
typedef void (*OakBackendDestroyNativeTextureFn)(OakRenderBackendHandle handle,
|
||||
const void *variant);
|
||||
typedef void (*OakBackendCreateNativeShaderFn)(OakRenderBackendHandle handle,
|
||||
const void *shader_code,
|
||||
void *out_variant);
|
||||
typedef void (*OakBackendDestroyNativeShaderFn)(OakRenderBackendHandle handle,
|
||||
const void *variant);
|
||||
typedef void (*OakBackendUploadToTextureFn)(OakRenderBackendHandle handle,
|
||||
const void *variant,
|
||||
const void *video_params,
|
||||
const void *data, int linesize);
|
||||
typedef void (*OakBackendDownloadFromTextureFn)(OakRenderBackendHandle handle,
|
||||
const void *variant,
|
||||
const void *video_params,
|
||||
void *data, int linesize);
|
||||
typedef void (*OakBackendFlushFn)(OakRenderBackendHandle handle);
|
||||
typedef void (*OakBackendGetPixelFromTextureFn)(OakRenderBackendHandle handle,
|
||||
void *texture, const void *point,
|
||||
void *out_color);
|
||||
typedef void (*OakBackendBlitFn)(OakRenderBackendHandle handle,
|
||||
const void *shader, void *job,
|
||||
void *destination,
|
||||
const void *destination_params,
|
||||
bool clear_destination);
|
||||
typedef void *(*OakBackendOpenGLContextFn)(OakRenderBackendHandle handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // RENDERBACKEND_C_H
|
||||
@@ -0,0 +1,155 @@
|
||||
#include "render/backend/renderbackend_c.h"
|
||||
|
||||
#include <QOpenGLContext>
|
||||
#include <QPointF>
|
||||
#include <QVariant>
|
||||
|
||||
#include "render/job/acceleratedjob.h"
|
||||
#include "render/opengl/openglrenderer.h"
|
||||
#include "render/shadercode.h"
|
||||
#include "render/texture.h"
|
||||
#include "render/videoparams.h"
|
||||
|
||||
namespace {
|
||||
|
||||
class BackendOpenGLRenderer : public olive::OpenGLRenderer {
|
||||
public:
|
||||
using olive::OpenGLRenderer::OpenGLRenderer;
|
||||
using olive::OpenGLRenderer::Blit;
|
||||
using olive::OpenGLRenderer::CreateNativeTexture;
|
||||
using olive::OpenGLRenderer::DestroyInternal;
|
||||
using olive::OpenGLRenderer::DestroyNativeTexture;
|
||||
};
|
||||
|
||||
BackendOpenGLRenderer *Renderer(OakRenderBackendHandle handle)
|
||||
{
|
||||
return static_cast<BackendOpenGLRenderer *>(handle);
|
||||
}
|
||||
|
||||
const QVariant &VariantRef(const void *variant)
|
||||
{
|
||||
return *static_cast<const QVariant *>(variant);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT OakRenderBackendHandle oak_renderer_create(void *parent)
|
||||
{
|
||||
return new BackendOpenGLRenderer(static_cast<QObject *>(parent));
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT void oak_renderer_destroy(OakRenderBackendHandle handle)
|
||||
{
|
||||
delete Renderer(handle);
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT bool oak_renderer_init(OakRenderBackendHandle handle)
|
||||
{
|
||||
return Renderer(handle)->Init();
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT void oak_renderer_init_with_context(
|
||||
OakRenderBackendHandle handle, void *context)
|
||||
{
|
||||
Renderer(handle)->Init(static_cast<QOpenGLContext *>(context));
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT void oak_renderer_post_init(OakRenderBackendHandle handle)
|
||||
{
|
||||
Renderer(handle)->PostInit();
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT void oak_renderer_post_destroy(OakRenderBackendHandle handle)
|
||||
{
|
||||
Renderer(handle)->PostDestroy();
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT void oak_renderer_destroy_internal(
|
||||
OakRenderBackendHandle handle)
|
||||
{
|
||||
Renderer(handle)->DestroyInternal();
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT void oak_renderer_clear_destination(
|
||||
OakRenderBackendHandle handle, void *texture, double r, double g, double b,
|
||||
double a)
|
||||
{
|
||||
Renderer(handle)->ClearDestination(static_cast<olive::Texture *>(texture),
|
||||
r, g, b, a);
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT void oak_renderer_create_native_texture(
|
||||
OakRenderBackendHandle handle, int width, int height, int depth, int format,
|
||||
int channel_count, const void *data, int linesize, void *out_variant)
|
||||
{
|
||||
*static_cast<QVariant *>(out_variant) = Renderer(handle)->CreateNativeTexture(
|
||||
width, height, depth, static_cast<olive::PixelFormat::Format>(format),
|
||||
channel_count, data, linesize);
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT void oak_renderer_destroy_native_texture(
|
||||
OakRenderBackendHandle handle, const void *variant)
|
||||
{
|
||||
Renderer(handle)->DestroyNativeTexture(VariantRef(variant));
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT void oak_renderer_create_native_shader(
|
||||
OakRenderBackendHandle handle, const void *shader_code, void *out_variant)
|
||||
{
|
||||
*static_cast<QVariant *>(out_variant) = Renderer(handle)->CreateNativeShader(
|
||||
*static_cast<const olive::ShaderCode *>(shader_code));
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT void oak_renderer_destroy_native_shader(
|
||||
OakRenderBackendHandle handle, const void *variant)
|
||||
{
|
||||
Renderer(handle)->DestroyNativeShader(VariantRef(variant));
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT void oak_renderer_upload_to_texture(
|
||||
OakRenderBackendHandle handle, const void *variant, const void *video_params,
|
||||
const void *data, int linesize)
|
||||
{
|
||||
Renderer(handle)->UploadToTexture(
|
||||
VariantRef(variant), *static_cast<const olive::VideoParams *>(video_params),
|
||||
data, linesize);
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT void oak_renderer_download_from_texture(
|
||||
OakRenderBackendHandle handle, const void *variant, const void *video_params,
|
||||
void *data, int linesize)
|
||||
{
|
||||
Renderer(handle)->DownloadFromTexture(
|
||||
VariantRef(variant), *static_cast<const olive::VideoParams *>(video_params),
|
||||
data, linesize);
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT void oak_renderer_flush(OakRenderBackendHandle handle)
|
||||
{
|
||||
Renderer(handle)->Flush();
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT void oak_renderer_get_pixel_from_texture(
|
||||
OakRenderBackendHandle handle, void *texture, const void *point,
|
||||
void *out_color)
|
||||
{
|
||||
*static_cast<olive::Color *>(out_color) = Renderer(handle)->GetPixelFromTexture(
|
||||
static_cast<olive::Texture *>(texture), *static_cast<const QPointF *>(point));
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT void oak_renderer_blit(
|
||||
OakRenderBackendHandle handle, const void *shader, void *job,
|
||||
void *destination, const void *destination_params, bool clear_destination)
|
||||
{
|
||||
Renderer(handle)->Blit(
|
||||
VariantRef(shader), *static_cast<olive::AcceleratedJob *>(job),
|
||||
static_cast<olive::Texture *>(destination),
|
||||
*static_cast<const olive::VideoParams *>(destination_params),
|
||||
clear_destination);
|
||||
}
|
||||
|
||||
OAK_RENDER_BACKEND_EXPORT void *oak_renderer_opengl_context(
|
||||
OakRenderBackendHandle handle)
|
||||
{
|
||||
return Renderer(handle)->context();
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef OPENGLCONTEXTPROVIDER_H
|
||||
#define OPENGLCONTEXTPROVIDER_H
|
||||
|
||||
class QOpenGLContext;
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class OpenGLContextProvider {
|
||||
public:
|
||||
virtual ~OpenGLContextProvider() = default;
|
||||
virtual QOpenGLContext *OpenGLContext() const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // OPENGLCONTEXTPROVIDER_H
|
||||
@@ -30,12 +30,13 @@
|
||||
#include <QThread>
|
||||
#include <QTimer>
|
||||
|
||||
#include "render/opengl/openglcontextprovider.h"
|
||||
#include "render/renderer.h"
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class OpenGLRenderer : public Renderer {
|
||||
class OpenGLRenderer : public Renderer, public OpenGLContextProvider {
|
||||
Q_OBJECT
|
||||
public:
|
||||
OpenGLRenderer(QObject *parent = nullptr);
|
||||
@@ -76,6 +77,11 @@ public:
|
||||
return context_;
|
||||
}
|
||||
|
||||
virtual QOpenGLContext *OpenGLContext() const override
|
||||
{
|
||||
return context();
|
||||
}
|
||||
|
||||
bool EnsureContextCurrent(const char *caller);
|
||||
|
||||
protected:
|
||||
|
||||
@@ -27,6 +27,9 @@
|
||||
|
||||
#include "config/config.h"
|
||||
#include "core.h"
|
||||
#ifdef OAK_ENABLE_DYNAMIC_RENDER_BACKEND
|
||||
#include "render/backend/dynamicrenderer.h"
|
||||
#endif
|
||||
#include "render/opengl/openglrenderer.h"
|
||||
#include "renderprocessor.h"
|
||||
#include "renderworkerpool.h"
|
||||
@@ -88,7 +91,11 @@ RenderManager::RenderManager(QObject *parent)
|
||||
}
|
||||
|
||||
if (backend_ == kOpenGL) {
|
||||
#ifdef OAK_ENABLE_DYNAMIC_RENDER_BACKEND
|
||||
context_ = new DynamicRenderer(BackendToString(requested_backend_));
|
||||
#else
|
||||
context_ = new OpenGLRenderer();
|
||||
#endif
|
||||
decoder_cache_ = new DecoderCache();
|
||||
shader_cache_ = new ShaderCache();
|
||||
} else {
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QOpenGLContext>
|
||||
#include <QThreadStorage>
|
||||
#include <QVector2D>
|
||||
#include <QVector3D>
|
||||
#include <QVector4D>
|
||||
@@ -32,6 +33,7 @@
|
||||
#include "node/block/transition/transition.h"
|
||||
#include "node/project.h"
|
||||
#include "rendermanager.h"
|
||||
#include "render/opengl/openglcontextprovider.h"
|
||||
#include "render/opengl/openglrenderer.h"
|
||||
#include "render/plugin/pluginrenderer.h"
|
||||
#include "pluginSupport/OliveClip.h"
|
||||
@@ -711,18 +713,21 @@ TexturePtr RenderProcessor::ProcessPluginJob(TexturePtr texture,
|
||||
|
||||
plugin::PluginRenderer *plugin_renderer = nullptr;
|
||||
{
|
||||
thread_local static std::shared_ptr<plugin::PluginRenderer>
|
||||
cached_plugin_renderer;
|
||||
if (!cached_plugin_renderer) {
|
||||
auto *gl = dynamic_cast<OpenGLRenderer *>(render_ctx_);
|
||||
if (gl && gl->context()) {
|
||||
cached_plugin_renderer =
|
||||
static QThreadStorage<std::shared_ptr<plugin::PluginRenderer>>
|
||||
cached_plugin_renderers;
|
||||
if (!cached_plugin_renderers.hasLocalData()) {
|
||||
auto *gl = dynamic_cast<OpenGLContextProvider *>(render_ctx_);
|
||||
if (gl && gl->OpenGLContext()) {
|
||||
auto cached_plugin_renderer =
|
||||
std::make_shared<plugin::PluginRenderer>();
|
||||
cached_plugin_renderer->Init(gl->context());
|
||||
cached_plugin_renderer->Init(gl->OpenGLContext());
|
||||
cached_plugin_renderer->PostInit();
|
||||
cached_plugin_renderers.setLocalData(cached_plugin_renderer);
|
||||
}
|
||||
}
|
||||
plugin_renderer = cached_plugin_renderer.get();
|
||||
if (cached_plugin_renderers.hasLocalData()) {
|
||||
plugin_renderer = cached_plugin_renderers.localData().get();
|
||||
}
|
||||
}
|
||||
|
||||
if (!plugin_renderer) {
|
||||
|
||||
Reference in New Issue
Block a user