From 8a7614e814c9bdccb859f0fe41ecd125ad567cfe Mon Sep 17 00:00:00 2001 From: Matthew Waters Date: Fri, 4 Aug 2023 13:02:21 +1000 Subject: [PATCH] qml: handle multiple items with different input formats Issue was that Qt was caching multiple different shadersbased on a static variable location. This static variable location was the same no matter the input video format and so if an item had an input video format of RGB and another of RGBA, they would eventually end up using the same GL shader leading to incorrect colours. Fix by providing different static variable locations for each of the different shaders that will be produced. Part-of: --- .../gst-plugins-good/ext/qt/gstqsgmaterial.cc | 30 +++++++++++++++++++ .../gst-plugins-good/ext/qt/gstqsgmaterial.h | 7 +++-- subprojects/gst-plugins-good/ext/qt/qtitem.cc | 2 +- 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/subprojects/gst-plugins-good/ext/qt/gstqsgmaterial.cc b/subprojects/gst-plugins-good/ext/qt/gstqsgmaterial.cc index a35e998086..f89138d535 100644 --- a/subprojects/gst-plugins-good/ext/qt/gstqsgmaterial.cc +++ b/subprojects/gst-plugins-good/ext/qt/gstqsgmaterial.cc @@ -173,6 +173,36 @@ GstQSGMaterialShader::fragmentShader() const return fragment; } +#define DEFINE_MATERIAL(format) \ +class G_PASTE(GstQSGMaterial_,format) : public GstQSGMaterial { \ +public: \ + G_PASTE(GstQSGMaterial_,format)(); \ + ~G_PASTE(GstQSGMaterial_,format)(); \ + QSGMaterialType *type() const override { static QSGMaterialType type; return &type; }; \ +}; \ +G_PASTE(GstQSGMaterial_,format)::G_PASTE(GstQSGMaterial_,format)() {} \ +G_PASTE(GstQSGMaterial_,format)::~G_PASTE(GstQSGMaterial_,format)() {} + +DEFINE_MATERIAL(RGBA); +DEFINE_MATERIAL(RGBA_SWIZZLE); +DEFINE_MATERIAL(YUV_TRIPLANAR); + +GstQSGMaterial * +GstQSGMaterial::new_for_format(GstVideoFormat format) +{ + switch (format) { + case GST_VIDEO_FORMAT_RGB: + case GST_VIDEO_FORMAT_RGBA: + return static_cast(new GstQSGMaterial_RGBA()); + case GST_VIDEO_FORMAT_BGRA: + return static_cast(new GstQSGMaterial_RGBA_SWIZZLE()); + case GST_VIDEO_FORMAT_YV12: + return static_cast(new GstQSGMaterial_YUV_TRIPLANAR()); + default: + g_assert_not_reached (); + } +} + GstQSGMaterial::GstQSGMaterial () { static gsize _debug; diff --git a/subprojects/gst-plugins-good/ext/qt/gstqsgmaterial.h b/subprojects/gst-plugins-good/ext/qt/gstqsgmaterial.h index 028fbf6a08..e4ee46ad07 100644 --- a/subprojects/gst-plugins-good/ext/qt/gstqsgmaterial.h +++ b/subprojects/gst-plugins-good/ext/qt/gstqsgmaterial.h @@ -35,9 +35,11 @@ class GstQSGMaterialShader; class GstQSGMaterial : public QSGMaterial { +protected: + GstQSGMaterial(); + ~GstQSGMaterial(); public: - GstQSGMaterial (); - ~GstQSGMaterial (); + static GstQSGMaterial *new_for_format (GstVideoFormat format); void setCaps (GstCaps * caps); gboolean setBuffer (GstBuffer * buffer); @@ -47,7 +49,6 @@ public: void bind(GstQSGMaterialShader *); /* QSGMaterial */ - QSGMaterialType *type() const override { static QSGMaterialType type; return &type; }; QSGMaterialShader *createShader() const override; private: diff --git a/subprojects/gst-plugins-good/ext/qt/qtitem.cc b/subprojects/gst-plugins-good/ext/qt/qtitem.cc index ed70e54c68..8ca7015db2 100644 --- a/subprojects/gst-plugins-good/ext/qt/qtitem.cc +++ b/subprojects/gst-plugins-good/ext/qt/qtitem.cc @@ -314,7 +314,7 @@ QtGLVideoItem::updatePaintNode(QSGNode * oldNode, texNode = new QSGGeometryNode(); geometry = new QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4); texNode->setGeometry(geometry); - tex = new GstQSGMaterial(); + tex = GstQSGMaterial::new_for_format(GST_VIDEO_INFO_FORMAT (&this->priv->v_info)); texNode->setMaterial(tex); }