various: pixel optimizations
Several things are accomplished in this commit, including: - Use OIIO instead of our own functions for pixel format conversions (cleaner code/less for us to maintain) - Fold all PixelService functions into the PixelFormat class (cleaner code) - Moved OpenGL pixel definitions to OpenGL classes and out of the global classes. - Add support for RGB buffers as well as RGBA (optimization)
This commit is contained in:
@@ -3,7 +3,9 @@
|
||||
AVPixelFormat FFmpegCommon::GetCompatiblePixelFormat(const AVPixelFormat &pix_fmt)
|
||||
{
|
||||
AVPixelFormat possible_pix_fmts[] = {
|
||||
AV_PIX_FMT_RGB24,
|
||||
AV_PIX_FMT_RGBA,
|
||||
AV_PIX_FMT_RGB48,
|
||||
AV_PIX_FMT_RGBA64,
|
||||
AV_PIX_FMT_NONE
|
||||
};
|
||||
@@ -73,8 +75,14 @@ AVPixelFormat FFmpegCommon::GetFFmpegPixelFormat(const PixelFormat::Format &pix_
|
||||
return AV_PIX_FMT_RGBA;
|
||||
case PixelFormat::PIX_FMT_RGBA16U:
|
||||
return AV_PIX_FMT_RGBA64;
|
||||
case PixelFormat::PIX_FMT_RGB8:
|
||||
return AV_PIX_FMT_RGB24;
|
||||
case PixelFormat::PIX_FMT_RGB16U:
|
||||
return AV_PIX_FMT_RGB48;
|
||||
case PixelFormat::PIX_FMT_RGBA16F:
|
||||
case PixelFormat::PIX_FMT_RGBA32F:
|
||||
case PixelFormat::PIX_FMT_RGB16F:
|
||||
case PixelFormat::PIX_FMT_RGB32F:
|
||||
case PixelFormat::PIX_FMT_INVALID:
|
||||
case PixelFormat::PIX_FMT_COUNT:
|
||||
break;
|
||||
@@ -86,8 +94,14 @@ AVPixelFormat FFmpegCommon::GetFFmpegPixelFormat(const PixelFormat::Format &pix_
|
||||
PixelFormat::Format FFmpegCommon::GetCompatiblePixelFormat(const PixelFormat::Format &pix_fmt)
|
||||
{
|
||||
switch (pix_fmt) {
|
||||
case PixelFormat::PIX_FMT_RGB8:
|
||||
return PixelFormat::PIX_FMT_RGB8;
|
||||
case PixelFormat::PIX_FMT_RGBA8:
|
||||
return PixelFormat::PIX_FMT_RGBA8;
|
||||
case PixelFormat::PIX_FMT_RGB16U:
|
||||
case PixelFormat::PIX_FMT_RGB16F:
|
||||
case PixelFormat::PIX_FMT_RGB32F:
|
||||
return PixelFormat::PIX_FMT_RGB16U;
|
||||
case PixelFormat::PIX_FMT_RGBA16U:
|
||||
case PixelFormat::PIX_FMT_RGBA16F:
|
||||
case PixelFormat::PIX_FMT_RGBA32F:
|
||||
|
||||
@@ -40,7 +40,7 @@ extern "C" {
|
||||
#include "common/timecodefunctions.h"
|
||||
#include "ffmpegcommon.h"
|
||||
#include "render/diskmanager.h"
|
||||
#include "render/pixelservice.h"
|
||||
#include "render/pixelformat.h"
|
||||
|
||||
FFmpegDecoder::FFmpegDecoder() :
|
||||
fmt_ctx_(nullptr),
|
||||
@@ -154,11 +154,20 @@ bool FFmpegDecoder::Open()
|
||||
|
||||
// Determine which Olive native pixel format we retrieved
|
||||
// Note that FFmpeg doesn't support float formats
|
||||
if (ideal_pix_fmt_ == AV_PIX_FMT_RGBA) {
|
||||
switch (ideal_pix_fmt_) {
|
||||
case AV_PIX_FMT_RGB24:
|
||||
native_pix_fmt_ = PixelFormat::PIX_FMT_RGB8;
|
||||
break;
|
||||
case AV_PIX_FMT_RGBA:
|
||||
native_pix_fmt_ = PixelFormat::PIX_FMT_RGBA8;
|
||||
} else if (ideal_pix_fmt_ == AV_PIX_FMT_RGBA64) {
|
||||
break;
|
||||
case AV_PIX_FMT_RGB48:
|
||||
native_pix_fmt_ = PixelFormat::PIX_FMT_RGB16U;
|
||||
break;
|
||||
case AV_PIX_FMT_RGBA64:
|
||||
native_pix_fmt_ = PixelFormat::PIX_FMT_RGBA16U;
|
||||
} else {
|
||||
break;
|
||||
default:
|
||||
// We should never get here, but just in case...
|
||||
qFatal("Invalid output format");
|
||||
}
|
||||
@@ -378,7 +387,7 @@ FramePtr FFmpegDecoder::RetrieveVideo(const rational &timecode)
|
||||
|
||||
// Convert frame to RGBA for the rest of the pipeline
|
||||
uint8_t* output_data = reinterpret_cast<uint8_t*>(working_frame_converted->data());
|
||||
int output_linesize = working_frame_converted->width() * kRGBAChannels * PixelService::BytesPerChannel(native_pix_fmt_);
|
||||
int output_linesize = working_frame_converted->width() * PixelFormat::ChannelCount(native_pix_fmt_) * PixelFormat::BytesPerChannel(native_pix_fmt_);
|
||||
|
||||
sws_scale(scale_ctx_,
|
||||
working_frame->data,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <QFile>
|
||||
|
||||
#include "ffmpegcommon.h"
|
||||
#include "render/pixelservice.h"
|
||||
#include "render/pixelformat.h"
|
||||
|
||||
FFmpegEncoder::FFmpegEncoder(const EncodingParams ¶ms) :
|
||||
Encoder(params),
|
||||
@@ -188,12 +188,12 @@ void FFmpegEncoder::WriteInternal(FramePtr frame)
|
||||
|
||||
// We may need to convert this frame to a frame that swscale will understand
|
||||
if (frame->format() != video_conversion_fmt_) {
|
||||
frame = PixelService::ConvertPixelFormat(frame, video_conversion_fmt_);
|
||||
frame = PixelFormat::ConvertPixelFormat(frame, video_conversion_fmt_);
|
||||
}
|
||||
|
||||
// Use swscale context to convert formats/linesizes
|
||||
input_data = frame->const_data();
|
||||
input_linesize = frame->width() * PixelService::BytesPerPixel(video_conversion_fmt_);
|
||||
input_linesize = frame->width() * PixelFormat::BytesPerPixel(video_conversion_fmt_);
|
||||
error_code = sws_scale(video_scale_ctx_,
|
||||
reinterpret_cast<const uint8_t**>(&input_data),
|
||||
&input_linesize,
|
||||
|
||||
+1
-3
@@ -23,8 +23,6 @@
|
||||
#include <QDebug>
|
||||
#include <QtGlobal>
|
||||
|
||||
#include "render/pixelservice.h"
|
||||
|
||||
Frame::Frame() :
|
||||
width_(0),
|
||||
height_(0),
|
||||
@@ -139,7 +137,7 @@ void Frame::allocate()
|
||||
{
|
||||
// Assume this frame is intended to be a video frame
|
||||
if (width_ > 0 && height_ > 0) {
|
||||
data_.resize(PixelService::GetBufferSize(static_cast<PixelFormat::Format>(format_), width_, height_));
|
||||
data_.resize(PixelFormat::GetBufferSize(static_cast<PixelFormat::Format>(format_), width_, height_));
|
||||
} else if (sample_count_ > 0) {
|
||||
data_.resize(audio_params_.samples_to_bytes(sample_count_));
|
||||
}
|
||||
|
||||
@@ -115,25 +115,24 @@ bool OIIODecoder::Open()
|
||||
width_ = spec.width;
|
||||
height_ = spec.height;
|
||||
|
||||
is_rgba_ = (spec.nchannels == kRGBAChannels);
|
||||
|
||||
// Weirdly, switch statement doesn't work correctly here
|
||||
if (spec.format == OIIO::TypeDesc::UINT8) {
|
||||
pix_fmt_ = PixelFormat::PIX_FMT_RGBA8;
|
||||
pix_fmt_ = is_rgba_ ? PixelFormat::PIX_FMT_RGBA8 : PixelFormat::PIX_FMT_RGB8;
|
||||
} else if (spec.format == OIIO::TypeDesc::UINT16) {
|
||||
pix_fmt_ = PixelFormat::PIX_FMT_RGBA16U;
|
||||
pix_fmt_ = is_rgba_ ? PixelFormat::PIX_FMT_RGBA16U : PixelFormat::PIX_FMT_RGB16U;
|
||||
} else if (spec.format == OIIO::TypeDesc::HALF) {
|
||||
pix_fmt_ = PixelFormat::PIX_FMT_RGBA16F;
|
||||
pix_fmt_ = is_rgba_ ? PixelFormat::PIX_FMT_RGBA16F : PixelFormat::PIX_FMT_RGB16F;
|
||||
} else if (spec.format == OIIO::TypeDesc::FLOAT) {
|
||||
pix_fmt_ = PixelFormat::PIX_FMT_RGBA32F;
|
||||
pix_fmt_ = is_rgba_ ? PixelFormat::PIX_FMT_RGBA32F : PixelFormat::PIX_FMT_RGB32F;
|
||||
} else {
|
||||
qWarning() << "Failed to convert OIIO::ImageDesc to native pixel format";
|
||||
return false;
|
||||
}
|
||||
|
||||
// FIXME: Many OIIO pixel formats are not handled here
|
||||
|
||||
is_rgba_ = (spec.nchannels == kRGBAChannels);
|
||||
|
||||
pix_fmt_info_ = PixelService::GetPixelFormatInfo(static_cast<PixelFormat::Format>(pix_fmt_));
|
||||
type_ = PixelFormat::GetOIIOTypeDesc(pix_fmt_);
|
||||
|
||||
open_ = true;
|
||||
|
||||
@@ -170,12 +169,7 @@ FramePtr OIIODecoder::RetrieveVideo(const rational &timecode)
|
||||
frame_->allocate();
|
||||
|
||||
// Use the native format to determine what format OIIO should return
|
||||
// FIXME: Behavior of RGB images as opposed to RGBA?
|
||||
image_->read_image(pix_fmt_info_.oiio_desc, frame_->data());
|
||||
|
||||
if (!is_rgba_) {
|
||||
PixelService::ConvertRGBtoRGBA(frame_);
|
||||
}
|
||||
image_->read_image(type_, frame_->data());
|
||||
}
|
||||
|
||||
return frame_;
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include <OpenImageIO/imageio.h>
|
||||
|
||||
#include "codec/decoder.h"
|
||||
#include "render/pixelservice.h"
|
||||
#include "render/pixelformat.h"
|
||||
|
||||
class OIIODecoder : public Decoder
|
||||
{
|
||||
@@ -57,7 +57,7 @@ private:
|
||||
|
||||
PixelFormat::Format pix_fmt_;
|
||||
|
||||
PixelFormat::Info pix_fmt_info_;
|
||||
OIIO::TypeDesc type_;
|
||||
|
||||
bool is_rgba_;
|
||||
|
||||
|
||||
+3
-3
@@ -48,7 +48,7 @@
|
||||
#include "render/backend/opengl/opengltexturecache.h"
|
||||
#include "render/colormanager.h"
|
||||
#include "render/diskmanager.h"
|
||||
#include "render/pixelservice.h"
|
||||
#include "render/pixelformat.h"
|
||||
#include "task/taskmanager.h"
|
||||
#include "ui/style/style.h"
|
||||
#include "undo/undostack.h"
|
||||
@@ -145,7 +145,7 @@ void Core::Stop()
|
||||
|
||||
DiskManager::DestroyInstance();
|
||||
|
||||
PixelService::DestroyInstance();
|
||||
PixelFormat::DestroyInstance();
|
||||
|
||||
NodeFactory::Destroy();
|
||||
|
||||
@@ -385,7 +385,7 @@ void Core::StartGUI(bool full_screen)
|
||||
TaskManager::CreateInstance();
|
||||
|
||||
// Initialize pixel service
|
||||
PixelService::CreateInstance();
|
||||
PixelFormat::CreateInstance();
|
||||
|
||||
// Connect the PanelFocusManager to the application's focus change signal
|
||||
connect(qApp,
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include "project/item/sequence/sequence.h"
|
||||
#include "project/project.h"
|
||||
#include "render/backend/exporter.h"
|
||||
#include "render/pixelservice.h"
|
||||
#include "render/pixelformat.h"
|
||||
#include "ui/icons/icons.h"
|
||||
|
||||
ExportDialog::ExportDialog(ViewerOutput *viewer_node, QWidget *parent) :
|
||||
@@ -210,7 +210,7 @@ void ExportDialog::accept()
|
||||
VideoRenderingParams video_render_params(dest_width,
|
||||
dest_height,
|
||||
video_tab_->frame_rate().flipped(),
|
||||
PixelService::instance()->GetConfiguredFormatForMode(render_mode),
|
||||
PixelFormat::instance()->GetConfiguredFormatForMode(render_mode),
|
||||
render_mode);
|
||||
|
||||
AudioRenderingParams audio_render_params(audio_tab_->sample_rate_combobox()->currentData().toInt(),
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "render/colormanager.h"
|
||||
#include "render/pixelservice.h"
|
||||
#include "render/pixelformat.h"
|
||||
|
||||
PreferencesQualityTab::PreferencesQualityTab()
|
||||
{
|
||||
@@ -26,13 +26,13 @@ PreferencesQualityTab::PreferencesQualityTab()
|
||||
quality_stack_ = new QStackedWidget();
|
||||
|
||||
offline_group_ = new PreferencesQualityGroup(tr("Offline Quality"));
|
||||
offline_group_->bit_depth_combobox()->setCurrentIndex(PixelService::instance()->GetConfiguredFormatForMode(RenderMode::kOffline));
|
||||
offline_group_->bit_depth_combobox()->setCurrentIndex(PixelFormat::instance()->GetConfiguredFormatForMode(RenderMode::kOffline));
|
||||
offline_group_->sample_fmt_combobox()->setCurrentIndex(SampleFormat::GetConfiguredFormatForMode(RenderMode::kOffline));
|
||||
offline_group_->ocio_method()->setCurrentIndex(ColorManager::GetOCIOMethodForMode(RenderMode::kOffline));
|
||||
quality_stack_->addWidget(offline_group_);
|
||||
|
||||
online_group_ = new PreferencesQualityGroup(tr("Online Quality"));
|
||||
online_group_->bit_depth_combobox()->setCurrentIndex(PixelService::instance()->GetConfiguredFormatForMode(RenderMode::kOnline));
|
||||
online_group_->bit_depth_combobox()->setCurrentIndex(PixelFormat::instance()->GetConfiguredFormatForMode(RenderMode::kOnline));
|
||||
online_group_->sample_fmt_combobox()->setCurrentIndex(SampleFormat::GetConfiguredFormatForMode(RenderMode::kOnline));
|
||||
online_group_->ocio_method()->setCurrentIndex(ColorManager::GetOCIOMethodForMode(RenderMode::kOnline));
|
||||
quality_stack_->addWidget(online_group_);
|
||||
@@ -46,8 +46,8 @@ void PreferencesQualityTab::Accept()
|
||||
{
|
||||
ColorManager::SetOCIOMethodForMode(RenderMode::kOffline, static_cast<ColorManager::OCIOMethod>(offline_group_->ocio_method()->currentIndex()));
|
||||
ColorManager::SetOCIOMethodForMode(RenderMode::kOnline, static_cast<ColorManager::OCIOMethod>(online_group_->ocio_method()->currentIndex()));
|
||||
PixelService::instance()->SetConfiguredFormatForMode(RenderMode::kOffline, static_cast<PixelFormat::Format>(offline_group_->bit_depth_combobox()->currentData().toInt()));
|
||||
PixelService::instance()->SetConfiguredFormatForMode(RenderMode::kOnline, static_cast<PixelFormat::Format>(online_group_->bit_depth_combobox()->currentData().toInt()));
|
||||
PixelFormat::instance()->SetConfiguredFormatForMode(RenderMode::kOffline, static_cast<PixelFormat::Format>(offline_group_->bit_depth_combobox()->currentData().toInt()));
|
||||
PixelFormat::instance()->SetConfiguredFormatForMode(RenderMode::kOnline, static_cast<PixelFormat::Format>(online_group_->bit_depth_combobox()->currentData().toInt()));
|
||||
SampleFormat::SetConfiguredFormatForMode(RenderMode::kOffline, static_cast<SampleFormat::Format>(offline_group_->sample_fmt_combobox()->currentData().toInt()));
|
||||
SampleFormat::SetConfiguredFormatForMode(RenderMode::kOnline, static_cast<SampleFormat::Format>(online_group_->sample_fmt_combobox()->currentData().toInt()));
|
||||
}
|
||||
@@ -70,8 +70,13 @@ PreferencesQualityGroup::PreferencesQualityGroup(const QString &title, QWidget *
|
||||
|
||||
// Populate with bit depths
|
||||
for (int i=0;i<PixelFormat::PIX_FMT_COUNT;i++) {
|
||||
bit_depth_combobox_->addItem(PixelService::GetPixelFormatInfo(static_cast<PixelFormat::Format>(i)).name,
|
||||
i);
|
||||
PixelFormat::Format pix_fmt = static_cast<PixelFormat::Format>(i);
|
||||
|
||||
// We always render with an alpha channel internally
|
||||
if (PixelFormat::FormatHasAlphaChannel(pix_fmt)) {
|
||||
bit_depth_combobox_->addItem(PixelFormat::GetName(pix_fmt),
|
||||
i);
|
||||
}
|
||||
}
|
||||
|
||||
video_layout->addWidget(bit_depth_combobox_, row, 1);
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include "codec/ffmpeg/ffmpegdecoder.h"
|
||||
#include "core.h"
|
||||
#include "project/item/footage/footage.h"
|
||||
#include "render/pixelservice.h"
|
||||
#include "render/pixelformat.h"
|
||||
|
||||
VideoInput::VideoInput()
|
||||
{
|
||||
|
||||
@@ -28,8 +28,6 @@ set(OLIVE_SOURCES
|
||||
render/diskmanager.cpp
|
||||
render/pixelformat.h
|
||||
render/pixelformat.cpp
|
||||
render/pixelservice.h
|
||||
render/pixelservice.cpp
|
||||
render/rendermodes.h
|
||||
render/videoparams.h
|
||||
render/videoparams.cpp
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "render/backend/audio/audiobackend.h"
|
||||
#include "render/backend/opengl/openglbackend.h"
|
||||
#include "render/colormanager.h"
|
||||
#include "render/pixelservice.h"
|
||||
#include "render/pixelformat.h"
|
||||
|
||||
Exporter::Exporter(ViewerOutput* viewer,
|
||||
Encoder *encoder,
|
||||
@@ -121,7 +121,7 @@ void Exporter::EncodeFrame()
|
||||
|
||||
// OCIO conversion requires a frame in 32F format
|
||||
if (frame->format() != PixelFormat::PIX_FMT_RGBA32F) {
|
||||
frame = PixelService::ConvertPixelFormat(frame, PixelFormat::PIX_FMT_RGBA32F);
|
||||
frame = PixelFormat::ConvertPixelFormat(frame, PixelFormat::PIX_FMT_RGBA32F);
|
||||
}
|
||||
|
||||
// Color conversion must be done with unassociated alpha, and the pipeline is always associated
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "openglcolorprocessor.h"
|
||||
#include "openglrenderfunctions.h"
|
||||
#include "render/colormanager.h"
|
||||
#include "render/pixelservice.h"
|
||||
#include "render/pixelformat.h"
|
||||
|
||||
OpenGLProxy::OpenGLProxy(QObject *parent) :
|
||||
QObject(parent),
|
||||
@@ -90,7 +90,7 @@ void OpenGLProxy::FrameToValue(DecoderPtr decoder, StreamPtr stream, const TimeR
|
||||
}
|
||||
|
||||
// Convert frame to float for OCIO
|
||||
frame = PixelService::ConvertPixelFormat(frame, PixelFormat::PIX_FMT_RGBA32F);
|
||||
frame = PixelFormat::ConvertPixelFormat(frame, PixelFormat::PIX_FMT_RGBA32F);
|
||||
|
||||
// Perform color transform
|
||||
color_processor->ConvertFrame(frame);
|
||||
@@ -384,8 +384,6 @@ void OpenGLProxy::TextureToBuffer(const QVariant &tex_in, void *buffer)
|
||||
{
|
||||
OpenGLTextureCache::ReferencePtr texture = tex_in.value<OpenGLTextureCache::ReferencePtr>();
|
||||
|
||||
PixelFormat::Info format_info = PixelService::GetPixelFormatInfo(video_params_.format());
|
||||
|
||||
QOpenGLFunctions* f = QOpenGLContext::currentContext()->functions();
|
||||
buffer_.Attach(texture->texture());
|
||||
buffer_.Bind();
|
||||
@@ -394,8 +392,8 @@ void OpenGLProxy::TextureToBuffer(const QVariant &tex_in, void *buffer)
|
||||
0,
|
||||
video_params_.effective_width(),
|
||||
video_params_.effective_height(),
|
||||
format_info.pixel_format,
|
||||
format_info.gl_pixel_type,
|
||||
OpenGLRenderFunctions::GetPixelFormat(video_params_.format()),
|
||||
OpenGLRenderFunctions::GetPixelType(video_params_.format()),
|
||||
buffer);
|
||||
|
||||
buffer_.Release();
|
||||
|
||||
@@ -71,6 +71,67 @@ void OpenGLRenderFunctions::PrepareToDraw(QOpenGLFunctions* f) {
|
||||
f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
|
||||
GLint OpenGLRenderFunctions::GetInternalFormat(const PixelFormat::Format &format)
|
||||
{
|
||||
switch (format) {
|
||||
case PixelFormat::PIX_FMT_RGB8:
|
||||
return GL_RGB8;
|
||||
case PixelFormat::PIX_FMT_RGBA8:
|
||||
return GL_RGBA8;
|
||||
case PixelFormat::PIX_FMT_RGB16U:
|
||||
return GL_RGB16;
|
||||
case PixelFormat::PIX_FMT_RGBA16U:
|
||||
return GL_RGBA16;
|
||||
case PixelFormat::PIX_FMT_RGB16F:
|
||||
return GL_RGB16F;
|
||||
case PixelFormat::PIX_FMT_RGBA16F:
|
||||
return GL_RGBA16F;
|
||||
case PixelFormat::PIX_FMT_RGB32F:
|
||||
return GL_RGB32F;
|
||||
case PixelFormat::PIX_FMT_RGBA32F:
|
||||
return GL_RGBA32F;
|
||||
|
||||
case PixelFormat::PIX_FMT_INVALID:
|
||||
case PixelFormat::PIX_FMT_COUNT:
|
||||
break;
|
||||
}
|
||||
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
GLenum OpenGLRenderFunctions::GetPixelFormat(const PixelFormat::Format &format)
|
||||
{
|
||||
if (PixelFormat::FormatHasAlphaChannel(format)) {
|
||||
return GL_RGBA;
|
||||
} else {
|
||||
return GL_RGB;
|
||||
}
|
||||
}
|
||||
|
||||
GLenum OpenGLRenderFunctions::GetPixelType(const PixelFormat::Format &format)
|
||||
{
|
||||
switch (format) {
|
||||
case PixelFormat::PIX_FMT_RGB8:
|
||||
case PixelFormat::PIX_FMT_RGBA8:
|
||||
return GL_UNSIGNED_BYTE;
|
||||
case PixelFormat::PIX_FMT_RGB16U:
|
||||
case PixelFormat::PIX_FMT_RGBA16U:
|
||||
return GL_UNSIGNED_SHORT;
|
||||
case PixelFormat::PIX_FMT_RGB16F:
|
||||
case PixelFormat::PIX_FMT_RGBA16F:
|
||||
return GL_HALF_FLOAT;
|
||||
case PixelFormat::PIX_FMT_RGB32F:
|
||||
case PixelFormat::PIX_FMT_RGBA32F:
|
||||
return GL_FLOAT;
|
||||
|
||||
case PixelFormat::PIX_FMT_INVALID:
|
||||
case PixelFormat::PIX_FMT_COUNT:
|
||||
break;
|
||||
}
|
||||
|
||||
return GL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
void OpenGLRenderFunctions::Blit(OpenGLShaderPtr pipeline, bool flipped, QMatrix4x4 matrix) {
|
||||
// FIXME: is currentContext() reliable here?
|
||||
QOpenGLFunctions* func = QOpenGLContext::currentContext()->functions();
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <QOpenGLFunctions>
|
||||
|
||||
#include "openglshader.h"
|
||||
#include "render/pixelformat.h"
|
||||
|
||||
class OpenGLRenderFunctions {
|
||||
public:
|
||||
@@ -50,6 +51,12 @@ public:
|
||||
|
||||
static void PrepareToDraw(QOpenGLFunctions* f);
|
||||
|
||||
static GLint GetInternalFormat(const PixelFormat::Format& format);
|
||||
|
||||
static GLenum GetPixelFormat(const PixelFormat::Format& format);
|
||||
|
||||
static GLenum GetPixelType(const PixelFormat::Format& format);
|
||||
|
||||
};
|
||||
|
||||
#endif // OPENGLFUNCTIONS_H
|
||||
|
||||
@@ -23,7 +23,8 @@
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
|
||||
#include "render/pixelservice.h"
|
||||
#include "openglrenderfunctions.h"
|
||||
#include "render/pixelformat.h"
|
||||
|
||||
OpenGLTexture::OpenGLTexture() :
|
||||
created_ctx_(nullptr),
|
||||
@@ -120,16 +121,14 @@ void OpenGLTexture::Upload(const void *data)
|
||||
|
||||
Bind();
|
||||
|
||||
PixelFormat::Info info = PixelService::GetPixelFormatInfo(format_);
|
||||
|
||||
created_ctx_->functions()->glTexSubImage2D(GL_TEXTURE_2D,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
width_,
|
||||
height_,
|
||||
info.pixel_format,
|
||||
info.gl_pixel_type,
|
||||
OpenGLRenderFunctions::GetPixelFormat(format_),
|
||||
OpenGLRenderFunctions::GetPixelType(format_),
|
||||
data);
|
||||
|
||||
Release();
|
||||
@@ -152,16 +151,14 @@ void OpenGLTexture::CreateInternal(QOpenGLContext* create_ctx, GLuint* tex, cons
|
||||
f->glBindTexture(GL_TEXTURE_2D, *tex);
|
||||
|
||||
// Allocate storage for texture
|
||||
const PixelFormat::Info& bit_depth = PixelService::GetPixelFormatInfo(format_);
|
||||
|
||||
f->glTexImage2D(GL_TEXTURE_2D,
|
||||
0,
|
||||
bit_depth.internal_format,
|
||||
OpenGLRenderFunctions::GetInternalFormat(format_),
|
||||
width_,
|
||||
height_,
|
||||
0,
|
||||
bit_depth.pixel_format,
|
||||
bit_depth.gl_pixel_type,
|
||||
OpenGLRenderFunctions::GetPixelFormat(format_),
|
||||
OpenGLRenderFunctions::GetPixelType(format_),
|
||||
data);
|
||||
|
||||
// Set texture filtering to bilinear
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include "openglcolorprocessor.h"
|
||||
#include "openglrenderfunctions.h"
|
||||
#include "render/colormanager.h"
|
||||
#include "render/pixelservice.h"
|
||||
#include "render/pixelformat.h"
|
||||
|
||||
OpenGLWorker::OpenGLWorker(VideoRenderFrameCache *frame_cache, DecoderCache* decoder_cache, QObject *parent) :
|
||||
VideoRenderWorker(frame_cache, decoder_cache, parent)
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include "config/config.h"
|
||||
#include "render/diskmanager.h"
|
||||
#include "render/diskmanager.h"
|
||||
#include "render/pixelservice.h"
|
||||
#include "render/pixelformat.h"
|
||||
#include "videorenderworker.h"
|
||||
|
||||
VideoRenderBackend::VideoRenderBackend(QObject *parent) :
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
#include "videorenderworker.h"
|
||||
|
||||
#include "common/define.h"
|
||||
#include "common/functiontimer.h"
|
||||
#include "node/block/transition/transition.h"
|
||||
#include "node/node.h"
|
||||
#include "project/project.h"
|
||||
#include "render/pixelservice.h"
|
||||
#include "render/pixelformat.h"
|
||||
|
||||
VideoRenderWorker::VideoRenderWorker(VideoRenderFrameCache *frame_cache, DecoderCache* decoder_cache, QObject *parent) :
|
||||
RenderWorker(decoder_cache, parent),
|
||||
frame_cache_(frame_cache),
|
||||
operating_mode_(kHashRenderCache)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
const VideoRenderingParams &VideoRenderWorker::video_params()
|
||||
@@ -225,10 +225,11 @@ void VideoRenderWorker::CloseInternal()
|
||||
|
||||
void VideoRenderWorker::Download(const rational& time, QVariant texture, QString filename)
|
||||
{
|
||||
PixelFormat::Info format_info = PixelService::GetPixelFormatInfo(video_params().format());
|
||||
|
||||
// Set up OIIO::ImageSpec for compressing cached images on disk
|
||||
OIIO::ImageSpec spec(video_params().effective_width(), video_params().effective_height(), kRGBAChannels, format_info.oiio_desc);
|
||||
OIIO::ImageSpec spec(video_params().effective_width(),
|
||||
video_params().effective_height(),
|
||||
PixelFormat::ChannelCount(video_params().format()),
|
||||
PixelFormat::GetOIIOTypeDesc(video_params().format()));
|
||||
|
||||
if (video_params_.format() != PixelFormat::PIX_FMT_RGBA8
|
||||
&& video_params_.format() != PixelFormat::PIX_FMT_RGBA16U) {
|
||||
@@ -249,7 +250,7 @@ void VideoRenderWorker::Download(const rational& time, QVariant texture, QString
|
||||
|
||||
if (out) {
|
||||
out->open(working_fn_std, spec);
|
||||
out->write_image(format_info.oiio_desc, download_buffer_.data());
|
||||
out->write_image(PixelFormat::GetOIIOTypeDesc(video_params().format()), download_buffer_.data());
|
||||
out->close();
|
||||
|
||||
#if OIIO_VERSION < 10903
|
||||
@@ -276,7 +277,7 @@ void VideoRenderWorker::Download(const rational& time, QVariant texture, QString
|
||||
|
||||
void VideoRenderWorker::ResizeDownloadBuffer()
|
||||
{
|
||||
download_buffer_.resize(PixelService::GetBufferSize(video_params_.format(), video_params_.effective_width(), video_params_.effective_height()));
|
||||
download_buffer_.resize(PixelFormat::GetBufferSize(video_params_.format(), video_params_.effective_width(), video_params_.effective_height()));
|
||||
}
|
||||
|
||||
NodeValueTable VideoRenderWorker::RenderBlock(const TrackOutput *track, const TimeRange &range)
|
||||
|
||||
@@ -123,6 +123,11 @@ void ColorManager::SetOCIOMethodForMode(RenderMode::Mode mode, ColorManager::OCI
|
||||
|
||||
void ColorManager::AssociateAlphaPixFmtFilter(ColorManager::AlphaAction action, FramePtr f)
|
||||
{
|
||||
if (!PixelFormat::FormatHasAlphaChannel(f->format())) {
|
||||
// This frame has no alpha channel, do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
int pixel_count = f->width() * f->height() * kRGBAChannels;
|
||||
|
||||
switch (static_cast<PixelFormat::Format>(f->format())) {
|
||||
@@ -130,15 +135,19 @@ void ColorManager::AssociateAlphaPixFmtFilter(ColorManager::AlphaAction action,
|
||||
case PixelFormat::PIX_FMT_COUNT:
|
||||
qWarning() << "Alpha association functions received an invalid pixel format";
|
||||
break;
|
||||
case PixelFormat::PIX_FMT_RGB8:
|
||||
case PixelFormat::PIX_FMT_RGBA8:
|
||||
case PixelFormat::PIX_FMT_RGB16U:
|
||||
case PixelFormat::PIX_FMT_RGBA16U:
|
||||
qWarning() << "Alpha association functions only works on float-based pixel formats at this time";
|
||||
break;
|
||||
case PixelFormat::PIX_FMT_RGB16F:
|
||||
case PixelFormat::PIX_FMT_RGBA16F:
|
||||
{
|
||||
AssociateAlphaInternal<qfloat16>(action, reinterpret_cast<qfloat16*>(f->data()), pixel_count);
|
||||
break;
|
||||
}
|
||||
case PixelFormat::PIX_FMT_RGB32F:
|
||||
case PixelFormat::PIX_FMT_RGBA32F:
|
||||
{
|
||||
AssociateAlphaInternal<float>(action, reinterpret_cast<float*>(f->data()), pixel_count);
|
||||
|
||||
@@ -38,7 +38,7 @@ ColorProcessor::ColorProcessor(OCIO::ConstConfigRcPtr config,
|
||||
|
||||
void ColorProcessor::ConvertFrame(FramePtr f)
|
||||
{
|
||||
OCIO::PackedImageDesc img(reinterpret_cast<float*>(f->data()), f->width(), f->height(), kRGBAChannels);
|
||||
OCIO::PackedImageDesc img(reinterpret_cast<float*>(f->data()), f->width(), f->height(), PixelFormat::ChannelCount(f->format()));
|
||||
|
||||
processor->apply(img);
|
||||
}
|
||||
|
||||
@@ -19,3 +19,237 @@
|
||||
***/
|
||||
|
||||
#include "pixelformat.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QFloat16>
|
||||
|
||||
#include "common/define.h"
|
||||
#include "core.h"
|
||||
|
||||
bool PixelFormat::FormatHasAlphaChannel(const PixelFormat::Format &format)
|
||||
{
|
||||
switch (format) {
|
||||
case PixelFormat::PIX_FMT_RGBA8:
|
||||
case PixelFormat::PIX_FMT_RGBA16U:
|
||||
case PixelFormat::PIX_FMT_RGBA16F:
|
||||
case PixelFormat::PIX_FMT_RGBA32F:
|
||||
return true;
|
||||
case PixelFormat::PIX_FMT_RGB8:
|
||||
case PixelFormat::PIX_FMT_RGB16U:
|
||||
case PixelFormat::PIX_FMT_RGB16F:
|
||||
case PixelFormat::PIX_FMT_RGB32F:
|
||||
case PixelFormat::PIX_FMT_INVALID:
|
||||
case PixelFormat::PIX_FMT_COUNT:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
OIIO::TypeDesc PixelFormat::GetOIIOTypeDesc(const PixelFormat::Format &format)
|
||||
{
|
||||
switch (format) {
|
||||
case PixelFormat::PIX_FMT_RGB8:
|
||||
case PixelFormat::PIX_FMT_RGBA8:
|
||||
return OIIO::TypeDesc::UINT8;
|
||||
case PixelFormat::PIX_FMT_RGB16U:
|
||||
case PixelFormat::PIX_FMT_RGBA16U:
|
||||
return OIIO::TypeDesc::UINT16;
|
||||
case PixelFormat::PIX_FMT_RGB16F:
|
||||
case PixelFormat::PIX_FMT_RGBA16F:
|
||||
return OIIO::TypeDesc::HALF;
|
||||
case PixelFormat::PIX_FMT_RGB32F:
|
||||
case PixelFormat::PIX_FMT_RGBA32F:
|
||||
return OIIO::TypeDesc::FLOAT;
|
||||
case PixelFormat::PIX_FMT_INVALID:
|
||||
case PixelFormat::PIX_FMT_COUNT:
|
||||
break;
|
||||
}
|
||||
|
||||
return OIIO::TypeDesc::UNKNOWN;
|
||||
}
|
||||
|
||||
QString PixelFormat::GetName(const PixelFormat::Format &format)
|
||||
{
|
||||
switch (format) {
|
||||
case PixelFormat::PIX_FMT_RGB8:
|
||||
case PixelFormat::PIX_FMT_RGBA8:
|
||||
return tr("8-bit");
|
||||
case PixelFormat::PIX_FMT_RGB16U:
|
||||
case PixelFormat::PIX_FMT_RGBA16U:
|
||||
return tr("16-bit Integer");
|
||||
case PixelFormat::PIX_FMT_RGB16F:
|
||||
case PixelFormat::PIX_FMT_RGBA16F:
|
||||
return tr("Half-Float (16-bit)");
|
||||
case PixelFormat::PIX_FMT_RGB32F:
|
||||
case PixelFormat::PIX_FMT_RGBA32F:
|
||||
return tr("Full-Float (32-bit)");
|
||||
case PixelFormat::PIX_FMT_INVALID:
|
||||
case PixelFormat::PIX_FMT_COUNT:
|
||||
break;
|
||||
}
|
||||
|
||||
return tr("Unknown (%1)").arg(format);
|
||||
}
|
||||
|
||||
PixelFormat* PixelFormat::instance_ = nullptr;
|
||||
|
||||
void PixelFormat::CreateInstance()
|
||||
{
|
||||
instance_ = new PixelFormat();
|
||||
}
|
||||
|
||||
void PixelFormat::DestroyInstance()
|
||||
{
|
||||
delete instance_;
|
||||
}
|
||||
|
||||
PixelFormat *PixelFormat::instance()
|
||||
{
|
||||
return instance_;
|
||||
}
|
||||
|
||||
PixelFormat::Format PixelFormat::GetConfiguredFormatForMode(RenderMode::Mode mode)
|
||||
{
|
||||
return static_cast<PixelFormat::Format>(Core::GetPreferenceForRenderMode(mode, QStringLiteral("PixelFormat")).toInt());
|
||||
}
|
||||
|
||||
void PixelFormat::SetConfiguredFormatForMode(RenderMode::Mode mode, PixelFormat::Format format)
|
||||
{
|
||||
if (format != GetConfiguredFormatForMode(mode)) {
|
||||
Core::SetPreferenceForRenderMode(mode, QStringLiteral("PixelFormat"), format);
|
||||
|
||||
emit FormatChanged();
|
||||
}
|
||||
}
|
||||
|
||||
PixelFormat::Format PixelFormat::OIIOFormatToOliveFormat(OIIO::TypeDesc desc, bool has_alpha)
|
||||
{
|
||||
if (desc == OIIO::TypeDesc::UINT8) {
|
||||
return has_alpha ? PixelFormat::PIX_FMT_RGBA8 : PixelFormat::PIX_FMT_RGB8;
|
||||
} else if (desc == OIIO::TypeDesc::UINT16) {
|
||||
return has_alpha ? PixelFormat::PIX_FMT_RGBA16U : PixelFormat::PIX_FMT_RGB16U;
|
||||
} else if (desc == OIIO::TypeDesc::HALF) {
|
||||
return has_alpha ? PixelFormat::PIX_FMT_RGBA16F : PixelFormat::PIX_FMT_RGB16F;
|
||||
} else if (desc == OIIO::TypeDesc::FLOAT) {
|
||||
return has_alpha ? PixelFormat::PIX_FMT_RGBA32F : PixelFormat::PIX_FMT_RGB32F;
|
||||
}
|
||||
|
||||
return PixelFormat::PIX_FMT_INVALID;
|
||||
}
|
||||
|
||||
/*PixelFormat::Info PixelFormat::GetPixelFormatInfo(const PixelFormat::Format &format)
|
||||
{
|
||||
PixelFormat::Info info;
|
||||
|
||||
switch (format) {
|
||||
case PixelFormat::PIX_FMT_RGB8:
|
||||
case PixelFormat::PIX_FMT_RGBA8:
|
||||
info.name = tr("8-bit");
|
||||
info.internal_format = (format == PixelFormat::PIX_FMT_RGB8) ? GL_RGB8 : GL_RGBA8;
|
||||
info.gl_pixel_type = GL_UNSIGNED_BYTE;
|
||||
info.oiio_desc = OIIO::TypeDesc::UINT8;
|
||||
break;
|
||||
case PixelFormat::PIX_FMT_RGB16U:
|
||||
case PixelFormat::PIX_FMT_RGBA16U:
|
||||
info.name = tr("16-bit Integer");
|
||||
info.internal_format = (format == PixelFormat::PIX_FMT_RGB16U) ? GL_RGB8 : GL_RGBA16;
|
||||
info.gl_pixel_type = GL_UNSIGNED_SHORT;
|
||||
info.oiio_desc = OIIO::TypeDesc::UINT16;
|
||||
break;
|
||||
case PixelFormat::PIX_FMT_RGB16F:
|
||||
case PixelFormat::PIX_FMT_RGBA16F:
|
||||
info.name = tr("Half-Float (16-bit)");
|
||||
info.internal_format = (format == PixelFormat::PIX_FMT_RGB8) ? GL_RGB8 : GL_RGBA16F;
|
||||
info.gl_pixel_type = GL_HALF_FLOAT;
|
||||
info.oiio_desc = OIIO::TypeDesc::HALF;
|
||||
break;
|
||||
case PixelFormat::PIX_FMT_RGB32F:
|
||||
case PixelFormat::PIX_FMT_RGBA32F:
|
||||
info.name = tr("Full-Float (32-bit)");
|
||||
info.internal_format = (format == PixelFormat::PIX_FMT_RGB8) ? GL_RGB8 : GL_RGBA32F;
|
||||
info.gl_pixel_type = GL_FLOAT;
|
||||
info.oiio_desc = OIIO::TypeDesc::FLOAT;
|
||||
break;
|
||||
case PixelFormat::PIX_FMT_INVALID:
|
||||
case PixelFormat::PIX_FMT_COUNT:
|
||||
qFatal("Invalid pixel format requested");
|
||||
}
|
||||
|
||||
info.pixel_format = GL_RGBA;
|
||||
info.bytes_per_pixel = BytesPerPixel(format);
|
||||
|
||||
return info;
|
||||
}*/
|
||||
|
||||
int PixelFormat::GetBufferSize(const PixelFormat::Format &format, const int &width, const int &height)
|
||||
{
|
||||
return BytesPerPixel(format) * width * height;
|
||||
}
|
||||
|
||||
int PixelFormat::BytesPerPixel(const PixelFormat::Format &format)
|
||||
{
|
||||
return BytesPerChannel(format) * ChannelCount(format);
|
||||
}
|
||||
|
||||
int PixelFormat::BytesPerChannel(const PixelFormat::Format &format)
|
||||
{
|
||||
switch (format) {
|
||||
case PixelFormat::PIX_FMT_RGB8:
|
||||
case PixelFormat::PIX_FMT_RGBA8:
|
||||
return 1;
|
||||
case PixelFormat::PIX_FMT_RGB16U:
|
||||
case PixelFormat::PIX_FMT_RGB16F:
|
||||
case PixelFormat::PIX_FMT_RGBA16U:
|
||||
case PixelFormat::PIX_FMT_RGBA16F:
|
||||
return 2;
|
||||
case PixelFormat::PIX_FMT_RGB32F:
|
||||
case PixelFormat::PIX_FMT_RGBA32F:
|
||||
return 4;
|
||||
case PixelFormat::PIX_FMT_INVALID:
|
||||
case PixelFormat::PIX_FMT_COUNT:
|
||||
break;
|
||||
}
|
||||
|
||||
qFatal("Invalid pixel format requested");
|
||||
|
||||
// qFatal will abort so we won't get here, but this suppresses compiler warnings
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PixelFormat::ChannelCount(const PixelFormat::Format &format)
|
||||
{
|
||||
if (PixelFormat::FormatHasAlphaChannel(format)) {
|
||||
return kRGBAChannels;
|
||||
} else {
|
||||
return kRGBChannels;
|
||||
}
|
||||
}
|
||||
|
||||
FramePtr PixelFormat::ConvertPixelFormat(FramePtr frame, const PixelFormat::Format &dest_format)
|
||||
{
|
||||
if (frame->format() == dest_format) {
|
||||
return frame;
|
||||
}
|
||||
|
||||
FramePtr converted = Frame::Create();
|
||||
|
||||
// Copy parameters
|
||||
converted->set_width(frame->width());
|
||||
converted->set_height(frame->height());
|
||||
converted->set_timestamp(frame->timestamp());
|
||||
converted->set_format(dest_format);
|
||||
converted->allocate();
|
||||
|
||||
OIIO::TypeDesc src_type = GetOIIOTypeDesc(frame->format());
|
||||
OIIO::TypeDesc dst_type = GetOIIOTypeDesc(dest_format);
|
||||
|
||||
if (OIIO::convert_type(src_type, frame->data(), dst_type, converted->data())) {
|
||||
return converted;
|
||||
} else {
|
||||
qDebug() << "Failed to convert type:" << OIIO::geterror().c_str();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+89
-17
@@ -25,7 +25,14 @@
|
||||
#include <QOpenGLExtraFunctions>
|
||||
#include <QString>
|
||||
|
||||
class PixelFormat {
|
||||
#include "render/rendermodes.h"
|
||||
|
||||
class Frame;
|
||||
using FramePtr = std::shared_ptr<Frame>;
|
||||
|
||||
class PixelFormat : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
* @brief Olive's internal supported pixel formats.
|
||||
@@ -38,27 +45,92 @@ public:
|
||||
PIX_FMT_RGBA16F,
|
||||
PIX_FMT_RGBA32F,
|
||||
|
||||
PIX_FMT_RGB8,
|
||||
PIX_FMT_RGB16U,
|
||||
PIX_FMT_RGB16F,
|
||||
PIX_FMT_RGB32F,
|
||||
|
||||
PIX_FMT_COUNT
|
||||
};
|
||||
|
||||
static void CreateInstance();
|
||||
static void DestroyInstance();
|
||||
static PixelFormat* instance();
|
||||
|
||||
/**
|
||||
* @brief A struct of information pertaining to each enum PixelFormat.
|
||||
*
|
||||
* Primarily this is a means of retrieving OpenGL texture information for different pixel formats/bit depths. Both
|
||||
* RAM and VRAM buffers will need a PixelFormat. To keep consistency between the OpenGL code and CPU code when using
|
||||
* a given PixelFormat, the PixelFormatInfo struct contains all necessary variables that you'll need to plug into
|
||||
* OpenGL.
|
||||
*
|
||||
* Use the static function PixelService::GetPixelFormatInfo to generate a PixelFormatInfo object.
|
||||
* @brief Returns the configured pixel format for a given mode
|
||||
*/
|
||||
struct Info {
|
||||
QString name;
|
||||
GLint internal_format;
|
||||
GLenum pixel_format;
|
||||
GLenum gl_pixel_type;
|
||||
int bytes_per_pixel;
|
||||
OIIO::TypeDesc oiio_desc;
|
||||
};
|
||||
Format GetConfiguredFormatForMode(RenderMode::Mode mode);
|
||||
void SetConfiguredFormatForMode(RenderMode::Mode mode, PixelFormat::Format format);
|
||||
|
||||
static Format OIIOFormatToOliveFormat(OIIO::TypeDesc desc, bool has_alpha);
|
||||
|
||||
/**
|
||||
* @brief Returns the minimum buffer size (in bytes) necessary for a given format, width, and height.
|
||||
*
|
||||
* @param format
|
||||
*
|
||||
* The format of the data the buffer should contain. Must be a member of the olive::PixelFormat enum.
|
||||
*
|
||||
* @param width
|
||||
*
|
||||
* The width (in pixels) of the buffer.
|
||||
*
|
||||
* @param height
|
||||
*
|
||||
* The height (in pixels) of the buffer.
|
||||
*/
|
||||
static int GetBufferSize(const Format &format, const int& width, const int& height);
|
||||
|
||||
/**
|
||||
* @brief Returns the number of bytes per pixel for a certain format
|
||||
*
|
||||
* Different formats use different sizes of data for pixels. Use this function to determine how many bytes a pixel
|
||||
* requires for a certain format. The number of bytes will always be a multiple of 4 since all formats use RGBA and
|
||||
* are at least 1 bpc.
|
||||
*/
|
||||
static int BytesPerPixel(const Format &format);
|
||||
|
||||
/**
|
||||
* @brief Returns the number of bytes per channel for a certain format
|
||||
*/
|
||||
static int BytesPerChannel(const Format& format);
|
||||
|
||||
/**
|
||||
* @brief Return the number of channels in this format
|
||||
*/
|
||||
static int ChannelCount(const Format& format);
|
||||
|
||||
/**
|
||||
* @brief Convert a frame to a pixel format
|
||||
*
|
||||
* If the frame's pixel format == the destination format, this just returns `frame`.
|
||||
*/
|
||||
static FramePtr ConvertPixelFormat(FramePtr frame, const Format &dest_format);
|
||||
|
||||
/**
|
||||
* @brief Simple convenience function returning whether a pixel format has an alpha channel or not
|
||||
*/
|
||||
static bool FormatHasAlphaChannel(const Format& format);
|
||||
|
||||
/**
|
||||
* @brief Get corresponding OpenImageIO TypeDesc for a given pixel format
|
||||
*/
|
||||
static OIIO::TypeDesc GetOIIOTypeDesc(const Format& format);
|
||||
|
||||
/**
|
||||
* @brief Get format name
|
||||
*/
|
||||
static QString GetName(const Format& format);
|
||||
|
||||
signals:
|
||||
void FormatChanged();
|
||||
|
||||
private:
|
||||
PixelFormat() = default;
|
||||
|
||||
static PixelFormat* instance_;
|
||||
|
||||
};
|
||||
|
||||
#endif // BITDEPTHS_H
|
||||
|
||||
@@ -1,366 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2019 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "pixelservice.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QFloat16>
|
||||
|
||||
#include "common/define.h"
|
||||
#include "core.h"
|
||||
|
||||
PixelService* PixelService::instance_ = nullptr;
|
||||
|
||||
void PixelService::CreateInstance()
|
||||
{
|
||||
instance_ = new PixelService();
|
||||
}
|
||||
|
||||
void PixelService::DestroyInstance()
|
||||
{
|
||||
delete instance_;
|
||||
}
|
||||
|
||||
PixelService *PixelService::instance()
|
||||
{
|
||||
return instance_;
|
||||
}
|
||||
|
||||
PixelFormat::Format PixelService::GetConfiguredFormatForMode(RenderMode::Mode mode)
|
||||
{
|
||||
return static_cast<PixelFormat::Format>(Core::GetPreferenceForRenderMode(mode, QStringLiteral("PixelFormat")).toInt());
|
||||
}
|
||||
|
||||
void PixelService::SetConfiguredFormatForMode(RenderMode::Mode mode, PixelFormat::Format format)
|
||||
{
|
||||
if (format != GetConfiguredFormatForMode(mode)) {
|
||||
Core::SetPreferenceForRenderMode(mode, QStringLiteral("PixelFormat"), format);
|
||||
|
||||
emit FormatChanged();
|
||||
}
|
||||
}
|
||||
|
||||
PixelFormat::Format PixelService::OIIOFormatToOliveFormat(OIIO::TypeDesc desc)
|
||||
{
|
||||
if (desc == OIIO::TypeDesc::UINT8) {
|
||||
return PixelFormat::PIX_FMT_RGBA8;
|
||||
} else if (desc == OIIO::TypeDesc::UINT16) {
|
||||
return PixelFormat::PIX_FMT_RGBA16U;
|
||||
} else if (desc == OIIO::TypeDesc::HALF) {
|
||||
return PixelFormat::PIX_FMT_RGBA16F;
|
||||
} else if (desc == OIIO::TypeDesc::FLOAT) {
|
||||
return PixelFormat::PIX_FMT_RGBA32F;
|
||||
}
|
||||
|
||||
return PixelFormat::PIX_FMT_INVALID;
|
||||
}
|
||||
|
||||
PixelFormat::Info PixelService::GetPixelFormatInfo(const PixelFormat::Format &format)
|
||||
{
|
||||
PixelFormat::Info info;
|
||||
|
||||
switch (format) {
|
||||
case PixelFormat::PIX_FMT_RGBA8:
|
||||
info.name = tr("8-bit");
|
||||
info.internal_format = GL_RGBA8;
|
||||
info.gl_pixel_type = GL_UNSIGNED_BYTE;
|
||||
info.oiio_desc = OIIO::TypeDesc::UINT8;
|
||||
break;
|
||||
case PixelFormat::PIX_FMT_RGBA16U:
|
||||
info.name = tr("16-bit Integer");
|
||||
info.internal_format = GL_RGBA16;
|
||||
info.gl_pixel_type = GL_UNSIGNED_SHORT;
|
||||
info.oiio_desc = OIIO::TypeDesc::UINT16;
|
||||
break;
|
||||
case PixelFormat::PIX_FMT_RGBA16F:
|
||||
info.name = tr("Half-Float (16-bit)");
|
||||
info.internal_format = GL_RGBA16F;
|
||||
info.gl_pixel_type = GL_HALF_FLOAT;
|
||||
info.oiio_desc = OIIO::TypeDesc::HALF;
|
||||
break;
|
||||
case PixelFormat::PIX_FMT_RGBA32F:
|
||||
info.name = tr("Full-Float (32-bit)");
|
||||
info.internal_format = GL_RGBA32F;
|
||||
info.gl_pixel_type = GL_FLOAT;
|
||||
info.oiio_desc = OIIO::TypeDesc::FLOAT;
|
||||
break;
|
||||
case PixelFormat::PIX_FMT_INVALID:
|
||||
case PixelFormat::PIX_FMT_COUNT:
|
||||
qFatal("Invalid pixel format requested");
|
||||
}
|
||||
|
||||
info.pixel_format = GL_RGBA;
|
||||
info.bytes_per_pixel = BytesPerPixel(format);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
int PixelService::GetBufferSize(const PixelFormat::Format &format, const int &width, const int &height)
|
||||
{
|
||||
return BytesPerPixel(format) * width * height;
|
||||
}
|
||||
|
||||
int PixelService::BytesPerPixel(const PixelFormat::Format &format)
|
||||
{
|
||||
return BytesPerChannel(format) * kRGBAChannels;
|
||||
}
|
||||
|
||||
int PixelService::BytesPerChannel(const PixelFormat::Format &format)
|
||||
{
|
||||
switch (format) {
|
||||
case PixelFormat::PIX_FMT_RGBA8:
|
||||
return 1;
|
||||
case PixelFormat::PIX_FMT_RGBA16U:
|
||||
case PixelFormat::PIX_FMT_RGBA16F:
|
||||
return 2;
|
||||
case PixelFormat::PIX_FMT_RGBA32F:
|
||||
return 4;
|
||||
case PixelFormat::PIX_FMT_INVALID:
|
||||
case PixelFormat::PIX_FMT_COUNT:
|
||||
break;
|
||||
}
|
||||
|
||||
qFatal("Invalid pixel format requested");
|
||||
|
||||
// qFatal will abort so we won't get here, but this suppresses compiler warnings
|
||||
return 0;
|
||||
}
|
||||
|
||||
FramePtr PixelService::ConvertPixelFormat(FramePtr frame, const PixelFormat::Format &dest_format)
|
||||
{
|
||||
if (frame->format() == dest_format) {
|
||||
return frame;
|
||||
}
|
||||
|
||||
// FIXME: It'd be nice if this was multithreaded soon
|
||||
|
||||
FramePtr converted = Frame::Create();
|
||||
|
||||
// Copy parameters
|
||||
converted->set_width(frame->width());
|
||||
converted->set_height(frame->height());
|
||||
converted->set_timestamp(frame->timestamp());
|
||||
converted->set_format(dest_format);
|
||||
converted->allocate();
|
||||
|
||||
int pix_count = frame->width() * frame->height() * kRGBAChannels;
|
||||
|
||||
bool valid = true;
|
||||
|
||||
switch (static_cast<PixelFormat::Format>(frame->format())) {
|
||||
case PixelFormat::PIX_FMT_RGBA8:
|
||||
{
|
||||
uint8_t* source = reinterpret_cast<uint8_t*>(frame->data());
|
||||
|
||||
switch (dest_format) {
|
||||
case PixelFormat::PIX_FMT_RGBA16U: // 8-bit Integer -> 16-bit Integer
|
||||
{
|
||||
uint16_t* destination = reinterpret_cast<uint16_t*>(converted->data());
|
||||
for (int i=0;i<pix_count;i++) {
|
||||
destination[i] = static_cast<uint16_t>(source[i] * 257);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PixelFormat::PIX_FMT_RGBA16F: // 8-bit Integer -> 16-bit Float
|
||||
{
|
||||
qfloat16* destination = reinterpret_cast<qfloat16*>(converted->data());
|
||||
for (int i=0;i<pix_count;i++) {
|
||||
destination[i] = source[i] / 255.0f;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PixelFormat::PIX_FMT_RGBA32F: // 8-bit Integer -> 32-bit Float
|
||||
{
|
||||
float* destination = reinterpret_cast<float*>(converted->data());
|
||||
for (int i=0;i<pix_count;i++) {
|
||||
destination[i] = source[i] / 255.0f;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PixelFormat::PIX_FMT_INVALID:
|
||||
case PixelFormat::PIX_FMT_RGBA8:
|
||||
case PixelFormat::PIX_FMT_COUNT:
|
||||
valid = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PixelFormat::PIX_FMT_RGBA16U:
|
||||
{
|
||||
uint16_t* source = reinterpret_cast<uint16_t*>(frame->data());
|
||||
|
||||
switch (dest_format) {
|
||||
case PixelFormat::PIX_FMT_RGBA8: // 16-bit Integer -> 8-bit Integer
|
||||
{
|
||||
uint8_t* destination = reinterpret_cast<uint8_t*>(converted->data());
|
||||
for (int i=0;i<pix_count;i++) {
|
||||
destination[i] = static_cast<uint8_t>(source[i] / 257);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PixelFormat::PIX_FMT_RGBA16F: // 16-bit Integer -> 16-bit Float
|
||||
{
|
||||
qfloat16* destination = reinterpret_cast<qfloat16*>(converted->data());
|
||||
for (int i=0;i<pix_count;i++) {
|
||||
destination[i] = source[i] / 65535.0f;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PixelFormat::PIX_FMT_RGBA32F: // 16-bit Integer -> 32-bit Float
|
||||
{
|
||||
float* destination = reinterpret_cast<float*>(converted->data());
|
||||
for (int i=0;i<pix_count;i++) {
|
||||
destination[i] = source[i] / 65535.0f;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PixelFormat::PIX_FMT_INVALID:
|
||||
case PixelFormat::PIX_FMT_RGBA16U:
|
||||
case PixelFormat::PIX_FMT_COUNT:
|
||||
valid = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PixelFormat::PIX_FMT_RGBA16F:
|
||||
{
|
||||
qfloat16* source = reinterpret_cast<qfloat16*>(frame->data());
|
||||
|
||||
switch (dest_format) {
|
||||
case PixelFormat::PIX_FMT_RGBA8: // 16-bit Float -> 8-bit Integer
|
||||
{
|
||||
uint8_t* destination = reinterpret_cast<uint8_t*>(converted->data());
|
||||
for (int i=0;i<pix_count;i++) {
|
||||
destination[i] = static_cast<uint8_t>(source[i] * 255.0f);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PixelFormat::PIX_FMT_RGBA16U: // 16-bit Float -> 16-bit Integer
|
||||
{
|
||||
uint16_t* destination = reinterpret_cast<uint16_t*>(converted->data());
|
||||
for (int i=0;i<pix_count;i++) {
|
||||
destination[i] = static_cast<uint16_t>(source[i] * 65535.0f);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PixelFormat::PIX_FMT_RGBA32F: // 16-bit Float -> 32-bit Float
|
||||
{
|
||||
float* destination = reinterpret_cast<float*>(converted->data());
|
||||
for (int i=0;i<pix_count;i++) {
|
||||
destination[i] = source[i];
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PixelFormat::PIX_FMT_INVALID:
|
||||
case PixelFormat::PIX_FMT_RGBA16F:
|
||||
case PixelFormat::PIX_FMT_COUNT:
|
||||
valid = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PixelFormat::PIX_FMT_RGBA32F:
|
||||
{
|
||||
float* source = reinterpret_cast<float*>(frame->data());
|
||||
|
||||
switch (dest_format) {
|
||||
case PixelFormat::PIX_FMT_RGBA8: // 32-bit Float -> 8-bit Integer
|
||||
{
|
||||
uint8_t* destination = reinterpret_cast<uint8_t*>(converted->data());
|
||||
for (int i=0;i<pix_count;i++) {
|
||||
destination[i] = static_cast<uint8_t>(source[i] * 255.0f);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PixelFormat::PIX_FMT_RGBA16U: // 32-bit Float -> 16-bit Integer
|
||||
{
|
||||
uint16_t* destination = reinterpret_cast<uint16_t*>(converted->data());
|
||||
for (int i=0;i<pix_count;i++) {
|
||||
destination[i] = static_cast<uint16_t>(source[i] * 65535.0f);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PixelFormat::PIX_FMT_RGBA16F: // 32-bit Float -> 16-bit Float
|
||||
{
|
||||
qfloat16* destination = reinterpret_cast<qfloat16*>(converted->data());
|
||||
for (int i=0;i<pix_count;i++) {
|
||||
destination[i] = source[i];
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PixelFormat::PIX_FMT_INVALID:
|
||||
case PixelFormat::PIX_FMT_RGBA32F:
|
||||
case PixelFormat::PIX_FMT_COUNT:
|
||||
valid = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PixelFormat::PIX_FMT_INVALID:
|
||||
case PixelFormat::PIX_FMT_COUNT:
|
||||
valid = false;
|
||||
}
|
||||
|
||||
if (valid) {
|
||||
return converted;
|
||||
}
|
||||
|
||||
qWarning() << "Invalid parameters called for pixel format conversion";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void PixelService::ConvertRGBtoRGBA(FramePtr frame)
|
||||
{
|
||||
PixelFormat::Format dest_format = static_cast<PixelFormat::Format>(frame->format());
|
||||
|
||||
int rgb_pixel_size = BytesPerChannel(dest_format) * kRGBChannels;
|
||||
int rgb_frame_size = frame->width() * frame->height() * rgb_pixel_size;
|
||||
int rgb_iter = rgb_frame_size - rgb_pixel_size;
|
||||
|
||||
int rgba_pixel_size = BytesPerChannel(dest_format) * kRGBAChannels;
|
||||
int rgba_frame_size = frame->width() * frame->height() * rgba_pixel_size;
|
||||
int rgba_iter = rgba_frame_size - rgba_pixel_size;
|
||||
|
||||
// Work backwards to save time
|
||||
while (rgb_iter >= 0) {
|
||||
memcpy(&frame->data()[rgba_iter], &frame->data()[rgb_iter], static_cast<size_t>(rgb_pixel_size));
|
||||
|
||||
uint8_t* alpha_ptr = reinterpret_cast<uint8_t*>(frame->data()) + rgba_iter + rgb_pixel_size;
|
||||
|
||||
// Write a full alpha value according to the format
|
||||
switch (dest_format) {
|
||||
case PixelFormat::PIX_FMT_RGBA8:
|
||||
*alpha_ptr = UINT8_MAX;
|
||||
break;
|
||||
case PixelFormat::PIX_FMT_RGBA16U:
|
||||
*reinterpret_cast<uint16_t*>(alpha_ptr) = UINT16_MAX;
|
||||
break;
|
||||
case PixelFormat::PIX_FMT_RGBA16F:
|
||||
*reinterpret_cast<qfloat16*>(alpha_ptr) = 1.0f;
|
||||
break;
|
||||
case PixelFormat::PIX_FMT_RGBA32F:
|
||||
*reinterpret_cast<float*>(alpha_ptr) = 1.0f;
|
||||
break;
|
||||
case PixelFormat::PIX_FMT_INVALID:
|
||||
case PixelFormat::PIX_FMT_COUNT:
|
||||
qFatal("Invalid pixel format requested");
|
||||
}
|
||||
|
||||
rgb_iter -= rgb_pixel_size;
|
||||
rgba_iter -= rgba_pixel_size;
|
||||
}
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2019 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef PIXELSERVICE_H
|
||||
#define PIXELSERVICE_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include "codec/frame.h"
|
||||
#include "pixelformat.h"
|
||||
#include "render/rendermodes.h"
|
||||
|
||||
class PixelService : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
static void CreateInstance();
|
||||
static void DestroyInstance();
|
||||
static PixelService* instance();
|
||||
|
||||
/**
|
||||
* @brief Returns the configured pixel format for a given mode
|
||||
*/
|
||||
PixelFormat::Format GetConfiguredFormatForMode(RenderMode::Mode mode);
|
||||
void SetConfiguredFormatForMode(RenderMode::Mode mode, PixelFormat::Format format);
|
||||
|
||||
static PixelFormat::Format OIIOFormatToOliveFormat(OIIO::TypeDesc desc);
|
||||
|
||||
/**
|
||||
* @brief Return a PixelFormatInfo containing information for a certain format
|
||||
*
|
||||
* \see PixelFormatInfo
|
||||
*/
|
||||
static PixelFormat::Info GetPixelFormatInfo(const PixelFormat::Format& format);
|
||||
|
||||
/**
|
||||
* @brief Returns the minimum buffer size (in bytes) necessary for a given format, width, and height.
|
||||
*
|
||||
* @param format
|
||||
*
|
||||
* The format of the data the buffer should contain. Must be a member of the olive::PixelFormat enum.
|
||||
*
|
||||
* @param width
|
||||
*
|
||||
* The width (in pixels) of the buffer.
|
||||
*
|
||||
* @param height
|
||||
*
|
||||
* The height (in pixels) of the buffer.
|
||||
*/
|
||||
static int GetBufferSize(const PixelFormat::Format &format, const int& width, const int& height);
|
||||
|
||||
/**
|
||||
* @brief Returns the number of bytes per pixel for a certain format
|
||||
*
|
||||
* Different formats use different sizes of data for pixels. Use this function to determine how many bytes a pixel
|
||||
* requires for a certain format. The number of bytes will always be a multiple of 4 since all formats use RGBA and
|
||||
* are at least 1 bpc.
|
||||
*/
|
||||
static int BytesPerPixel(const PixelFormat::Format &format);
|
||||
|
||||
/**
|
||||
* @brief Returns the number of bytes per channel for a certain format
|
||||
*/
|
||||
static int BytesPerChannel(const PixelFormat::Format& format);
|
||||
|
||||
/**
|
||||
* @brief Convert a frame to a pixel format
|
||||
*
|
||||
* If the frame's pixel format == the destination format, this just returns `frame`.
|
||||
*/
|
||||
static FramePtr ConvertPixelFormat(FramePtr frame, const PixelFormat::Format &dest_format);
|
||||
|
||||
/**
|
||||
* @brief Convert an RGB image to an RGBA image
|
||||
*/
|
||||
static void ConvertRGBtoRGBA(FramePtr frame);
|
||||
|
||||
signals:
|
||||
void FormatChanged();
|
||||
|
||||
private:
|
||||
PixelService() = default;
|
||||
|
||||
static PixelService* instance_;
|
||||
|
||||
};
|
||||
|
||||
#endif // PIXELSERVICE_H
|
||||
@@ -31,7 +31,7 @@
|
||||
#include "config/config.h"
|
||||
#include "project/item/sequence/sequence.h"
|
||||
#include "project/project.h"
|
||||
#include "render/pixelservice.h"
|
||||
#include "render/pixelformat.h"
|
||||
#include "widget/menu/menu.h"
|
||||
|
||||
ViewerWidget::ViewerWidget(QWidget *parent) :
|
||||
@@ -85,7 +85,7 @@ ViewerWidget::ViewerWidget(QWidget *parent) :
|
||||
connect(video_renderer_, &VideoRenderBackend::RangeInvalidated, ruler(), &TimeRuler::CacheInvalidatedRange);
|
||||
audio_renderer_ = new AudioBackend(this);
|
||||
|
||||
connect(PixelService::instance(), &PixelService::FormatChanged, this, &ViewerWidget::UpdateRendererParameters);
|
||||
connect(PixelFormat::instance(), &PixelFormat::FormatChanged, this, &ViewerWidget::UpdateRendererParameters);
|
||||
|
||||
SetAutoMaxScrollBar(true);
|
||||
}
|
||||
@@ -296,7 +296,7 @@ void ViewerWidget::UpdateRendererParameters()
|
||||
RenderMode::Mode render_mode = RenderMode::kOffline;
|
||||
|
||||
VideoRenderingParams vparam(GetConnectedNode()->video_params(),
|
||||
PixelService::instance()->GetConfiguredFormatForMode(render_mode),
|
||||
PixelFormat::instance()->GetConfiguredFormatForMode(render_mode),
|
||||
render_mode,
|
||||
divider_);
|
||||
|
||||
|
||||
@@ -27,9 +27,10 @@
|
||||
#include <QOpenGLFunctions>
|
||||
#include <QOpenGLTexture>
|
||||
|
||||
#include "common/define.h"
|
||||
#include "render/backend/opengl/openglrenderfunctions.h"
|
||||
#include "render/backend/opengl/openglshader.h"
|
||||
#include "render/pixelservice.h"
|
||||
#include "render/pixelformat.h"
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
bool ViewerGLWidget::nouveau_check_done_ = false;
|
||||
@@ -83,7 +84,8 @@ void ViewerGLWidget::SetImage(const QString &fn)
|
||||
|
||||
if (input) {
|
||||
|
||||
PixelFormat::Format image_format = PixelService::OIIOFormatToOliveFormat(input->spec().format);
|
||||
PixelFormat::Format image_format = PixelFormat::OIIOFormatToOliveFormat(input->spec().format,
|
||||
input->spec().nchannels == kRGBAChannels);
|
||||
|
||||
// Ensure the following texture operations are done in our context (in case we're in a separate window for instance)
|
||||
makeCurrent();
|
||||
|
||||
Reference in New Issue
Block a user