QskPaintedNode/QskTextureRenderer added
This commit is contained in:
parent
c4160ac539
commit
da0fb28290
|
@ -7,7 +7,8 @@
|
||||||
|
|
||||||
#include <QskGraphic.h>
|
#include <QskGraphic.h>
|
||||||
#include <QskGraphicIO.h>
|
#include <QskGraphicIO.h>
|
||||||
#include <QskGraphicTextureFactory.h>
|
#include <QskColorFilter.h>
|
||||||
|
#include <QskTextureRenderer.h>
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
@ -116,14 +117,15 @@ bool Benchmark::run( const QString& dirName )
|
||||||
|
|
||||||
timer.start();
|
timer.start();
|
||||||
|
|
||||||
const QRect targetRect( 0, 0, 200, 200 );
|
const QSize targetSize( 200, 200 );
|
||||||
const QskColorFilter colorFilter;
|
const QskColorFilter colorFilter;
|
||||||
|
|
||||||
for ( int i = 0; i < qvgFiles.size(); i++ )
|
for ( int i = 0; i < qvgFiles.size(); i++ )
|
||||||
{
|
{
|
||||||
const auto textureId = QskGraphicTextureFactory::createTexture(
|
using namespace QskTextureRenderer;
|
||||||
QskGraphicTextureFactory::OpenGL, targetRect, Qt::KeepAspectRatio,
|
|
||||||
graphics[ i ], colorFilter );
|
const auto textureId = createTextureFromGraphic(
|
||||||
|
OpenGL, targetSize, graphics[ i ], colorFilter );
|
||||||
|
|
||||||
if ( textureId == 0 )
|
if ( textureId == 0 )
|
||||||
{
|
{
|
||||||
|
@ -140,14 +142,15 @@ bool Benchmark::run( const QString& dirName )
|
||||||
|
|
||||||
timer.start();
|
timer.start();
|
||||||
|
|
||||||
const QRect targetRect( 0, 0, 100, 100 );
|
const QSize targetSize( 200, 200 );
|
||||||
const QskColorFilter colorFilter;
|
const QskColorFilter colorFilter;
|
||||||
|
|
||||||
for ( int i = 0; i < qvgFiles.size(); i++ )
|
for ( int i = 0; i < qvgFiles.size(); i++ )
|
||||||
{
|
{
|
||||||
const auto textureId = QskGraphicTextureFactory::createTexture(
|
using namespace QskTextureRenderer;
|
||||||
QskGraphicTextureFactory::Raster, targetRect, Qt::KeepAspectRatio,
|
|
||||||
graphics[ i ], colorFilter );
|
const auto textureId = createTextureFromGraphic(
|
||||||
|
Raster, targetSize, graphics[ i ], colorFilter );
|
||||||
|
|
||||||
if ( textureId == 0 )
|
if ( textureId == 0 )
|
||||||
{
|
{
|
||||||
|
|
|
@ -76,11 +76,11 @@ static inline QSGNode* qskUpdateGraphicNode(
|
||||||
if ( rect.isEmpty() )
|
if ( rect.isEmpty() )
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
auto mode = QskGraphicTextureFactory::OpenGL;
|
auto mode = QskTextureRenderer::OpenGL;
|
||||||
|
|
||||||
const auto control = skinnable->owningControl();
|
const auto control = skinnable->owningControl();
|
||||||
if ( control && control->testControlFlag( QskControl::PreferRasterForTextures ) )
|
if ( control && control->testControlFlag( QskControl::PreferRasterForTextures ) )
|
||||||
mode = QskGraphicTextureFactory::Raster;
|
mode = QskTextureRenderer::Raster;
|
||||||
|
|
||||||
auto graphicNode = static_cast< QskGraphicNode* >( node );
|
auto graphicNode = static_cast< QskGraphicNode* >( node );
|
||||||
if ( graphicNode == nullptr )
|
if ( graphicNode == nullptr )
|
||||||
|
|
|
@ -4,120 +4,10 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include "QskGraphicTextureFactory.h"
|
#include "QskGraphicTextureFactory.h"
|
||||||
|
#include "QskTextureRenderer.h"
|
||||||
|
|
||||||
#include <qopenglcontext.h>
|
|
||||||
#include <qopenglframebufferobject.h>
|
|
||||||
#include <qopenglfunctions.h>
|
|
||||||
#include <qopenglextrafunctions.h>
|
|
||||||
#include <qopenglpaintdevice.h>
|
|
||||||
#include <qopengltexture.h>
|
|
||||||
|
|
||||||
#include <qpainter.h>
|
|
||||||
#include <qquickwindow.h>
|
#include <qquickwindow.h>
|
||||||
|
|
||||||
static uint qskTextureFBO(
|
|
||||||
const QRect& rect, Qt::AspectRatioMode scalingMode,
|
|
||||||
const QskGraphic& graphic, const QskColorFilter& filter )
|
|
||||||
{
|
|
||||||
QOpenGLFramebufferObjectFormat format1;
|
|
||||||
format1.setAttachment( QOpenGLFramebufferObject::CombinedDepthStencil );
|
|
||||||
// ### TODO: get samples from window instead
|
|
||||||
format1.setSamples( QOpenGLContext::currentContext()->format().samples() );
|
|
||||||
|
|
||||||
const QRect sourceRect( QPoint(), rect.size() );
|
|
||||||
|
|
||||||
QOpenGLFramebufferObject multisampledFbo( sourceRect.size(), format1 );
|
|
||||||
|
|
||||||
QOpenGLPaintDevice pd( sourceRect.size() );
|
|
||||||
|
|
||||||
QPainter painter( &pd );
|
|
||||||
|
|
||||||
graphic.render( &painter, sourceRect, filter, scalingMode );
|
|
||||||
|
|
||||||
#if 1
|
|
||||||
if ( format1.samples() > 0 )
|
|
||||||
{
|
|
||||||
// multisampling in the window surface might get lost
|
|
||||||
// as a side effect of rendering to the FBO.
|
|
||||||
// weired, needs to be investigated more
|
|
||||||
painter.setRenderHint( QPainter::Antialiasing, true );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
painter.end();
|
|
||||||
|
|
||||||
QOpenGLFramebufferObjectFormat format2;
|
|
||||||
format2.setAttachment( QOpenGLFramebufferObject::NoAttachment );
|
|
||||||
|
|
||||||
QOpenGLFramebufferObject fbo( sourceRect.size(), format2 );
|
|
||||||
|
|
||||||
// mirror vertically to be compliant with what QQuickTextureFactory expects.
|
|
||||||
// for some reason we have to add 1 pixel to avoid that the mirrored
|
|
||||||
// image gets cut off.
|
|
||||||
|
|
||||||
const QRect targetRect( sourceRect.x(), sourceRect.bottom() + 1,
|
|
||||||
sourceRect.width(), -sourceRect.height() );
|
|
||||||
|
|
||||||
QOpenGLFramebufferObject::blitFramebuffer(
|
|
||||||
&fbo, sourceRect, &multisampledFbo, targetRect );
|
|
||||||
|
|
||||||
return fbo.takeTexture();
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint qskTextureRaster(
|
|
||||||
const QRect& rect, Qt::AspectRatioMode scalingMode,
|
|
||||||
const QskGraphic& graphic, const QskColorFilter& filter )
|
|
||||||
{
|
|
||||||
QImage image( rect.size(), QImage::Format_RGBA8888_Premultiplied );
|
|
||||||
image.fill( Qt::transparent );
|
|
||||||
|
|
||||||
{
|
|
||||||
QPainter painter( &image );
|
|
||||||
graphic.render( &painter, rect, filter, scalingMode );
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto target = QOpenGLTexture::Target2D;
|
|
||||||
|
|
||||||
auto context = QOpenGLContext::currentContext();
|
|
||||||
if ( context == nullptr )
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
auto& f = *context->functions();
|
|
||||||
|
|
||||||
GLint oldTexture; // we can't rely on having OpenGL Direct State Access
|
|
||||||
f.glGetIntegerv( QOpenGLTexture::BindingTarget2D, &oldTexture );
|
|
||||||
|
|
||||||
GLuint textureId;
|
|
||||||
f.glGenTextures( 1, &textureId );
|
|
||||||
|
|
||||||
f.glBindTexture( target, textureId );
|
|
||||||
|
|
||||||
f.glTexParameteri( target, GL_TEXTURE_MIN_FILTER, QOpenGLTexture::Nearest );
|
|
||||||
f.glTexParameteri( target, GL_TEXTURE_MAG_FILTER, QOpenGLTexture::Nearest );
|
|
||||||
|
|
||||||
f.glTexParameteri( target, GL_TEXTURE_WRAP_S, QOpenGLTexture::ClampToEdge );
|
|
||||||
f.glTexParameteri( target, GL_TEXTURE_WRAP_T, QOpenGLTexture::ClampToEdge );
|
|
||||||
|
|
||||||
if ( QOpenGLTexture::hasFeature( QOpenGLTexture::ImmutableStorage ) )
|
|
||||||
{
|
|
||||||
auto& ef = *context->extraFunctions();
|
|
||||||
ef.glTexStorage2D( target, 1,
|
|
||||||
QOpenGLTexture::RGBA8_UNorm, image.width(), image.height() );
|
|
||||||
|
|
||||||
f.glTexSubImage2D( target, 0, 0, 0, image.width(), image.height(),
|
|
||||||
QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, image.constBits() );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
f.glTexImage2D( target, 0, QOpenGLTexture::RGBA8_UNorm,
|
|
||||||
image.width(), image.height(), 0,
|
|
||||||
QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, image.constBits() );
|
|
||||||
}
|
|
||||||
|
|
||||||
f.glBindTexture( target, oldTexture );
|
|
||||||
|
|
||||||
return textureId;
|
|
||||||
}
|
|
||||||
|
|
||||||
QskGraphicTextureFactory::QskGraphicTextureFactory()
|
QskGraphicTextureFactory::QskGraphicTextureFactory()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -135,10 +25,8 @@ QskGraphicTextureFactory::~QskGraphicTextureFactory()
|
||||||
|
|
||||||
QSGTexture* QskGraphicTextureFactory::createTexture( QQuickWindow* window ) const
|
QSGTexture* QskGraphicTextureFactory::createTexture( QQuickWindow* window ) const
|
||||||
{
|
{
|
||||||
const QRect textureRect( 0, 0, m_size.width(), m_size.height() );
|
const uint textureId = QskTextureRenderer::createTextureFromGraphic(
|
||||||
|
QskTextureRenderer::OpenGL, m_size, m_graphic, m_colorFilter );
|
||||||
const uint textureId = createTexture( QskGraphicTextureFactory::OpenGL,
|
|
||||||
textureRect, Qt::KeepAspectRatio, m_graphic, m_colorFilter );
|
|
||||||
|
|
||||||
const auto flags = static_cast< QQuickWindow::CreateTextureOptions >(
|
const auto flags = static_cast< QQuickWindow::CreateTextureOptions >(
|
||||||
QQuickWindow::TextureHasAlphaChannel | QQuickWindow::TextureOwnsGLTexture );
|
QQuickWindow::TextureHasAlphaChannel | QQuickWindow::TextureOwnsGLTexture );
|
||||||
|
@ -160,14 +48,3 @@ QImage QskGraphicTextureFactory::image() const
|
||||||
{
|
{
|
||||||
return m_graphic.toImage( m_size, Qt::KeepAspectRatio );
|
return m_graphic.toImage( m_size, Qt::KeepAspectRatio );
|
||||||
}
|
}
|
||||||
|
|
||||||
// ### TODO: get the FBO samples from the window
|
|
||||||
uint QskGraphicTextureFactory::createTexture(
|
|
||||||
RenderMode mode, const QRect& rect, Qt::AspectRatioMode scalingMode,
|
|
||||||
const QskGraphic& graphic, const QskColorFilter& filter )
|
|
||||||
{
|
|
||||||
if ( mode == QskGraphicTextureFactory::Raster )
|
|
||||||
return qskTextureRaster( rect, scalingMode, graphic, filter );
|
|
||||||
else
|
|
||||||
return qskTextureFBO( rect, scalingMode, graphic, filter );
|
|
||||||
}
|
|
||||||
|
|
|
@ -8,17 +8,12 @@
|
||||||
|
|
||||||
#include "QskColorFilter.h"
|
#include "QskColorFilter.h"
|
||||||
#include "QskGraphic.h"
|
#include "QskGraphic.h"
|
||||||
|
|
||||||
#include <qquickimageprovider.h>
|
#include <qquickimageprovider.h>
|
||||||
|
|
||||||
class QSK_EXPORT QskGraphicTextureFactory : public QQuickTextureFactory
|
class QSK_EXPORT QskGraphicTextureFactory : public QQuickTextureFactory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum RenderMode
|
|
||||||
{
|
|
||||||
Raster,
|
|
||||||
OpenGL
|
|
||||||
};
|
|
||||||
|
|
||||||
QskGraphicTextureFactory();
|
QskGraphicTextureFactory();
|
||||||
QskGraphicTextureFactory( const QskGraphic&, const QSize& size );
|
QskGraphicTextureFactory( const QskGraphic&, const QSize& size );
|
||||||
|
|
||||||
|
@ -39,9 +34,6 @@ class QSK_EXPORT QskGraphicTextureFactory : public QQuickTextureFactory
|
||||||
|
|
||||||
QImage image() const override;
|
QImage image() const override;
|
||||||
|
|
||||||
static uint createTexture( RenderMode, const QRect& rect,
|
|
||||||
Qt::AspectRatioMode, const QskGraphic&, const QskColorFilter& );
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QskGraphic m_graphic;
|
QskGraphic m_graphic;
|
||||||
QskColorFilter m_colorFilter;
|
QskColorFilter m_colorFilter;
|
||||||
|
|
|
@ -4,10 +4,12 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include "QskGraphicNode.h"
|
#include "QskGraphicNode.h"
|
||||||
|
#include "QskGraphic.h"
|
||||||
|
#include "QskColorFilter.h"
|
||||||
|
|
||||||
static inline uint qskHash(
|
static inline uint qskHash(
|
||||||
const QskGraphic& graphic, const QskColorFilter& colorFilter,
|
const QskGraphic& graphic, const QskColorFilter& colorFilter,
|
||||||
QskGraphicTextureFactory::RenderMode renderMode )
|
QskTextureRenderer::RenderMode renderMode )
|
||||||
{
|
{
|
||||||
uint hash = 0;
|
uint hash = 0;
|
||||||
|
|
||||||
|
@ -45,7 +47,7 @@ QskGraphicNode::~QskGraphicNode()
|
||||||
|
|
||||||
void QskGraphicNode::setGraphic(
|
void QskGraphicNode::setGraphic(
|
||||||
const QskGraphic& graphic, const QskColorFilter& colorFilter,
|
const QskGraphic& graphic, const QskColorFilter& colorFilter,
|
||||||
QskGraphicTextureFactory::RenderMode renderMode, const QRect& rect )
|
QskTextureRenderer::RenderMode renderMode, const QRect& rect )
|
||||||
{
|
{
|
||||||
bool isTextureDirty = ( QskTextureNode::textureId() == 0 );
|
bool isTextureDirty = ( QskTextureNode::textureId() == 0 );
|
||||||
|
|
||||||
|
@ -67,10 +69,8 @@ void QskGraphicNode::setGraphic(
|
||||||
|
|
||||||
if ( isTextureDirty )
|
if ( isTextureDirty )
|
||||||
{
|
{
|
||||||
const QRect textureRect( 0, 0, rect.width(), rect.height() );
|
const uint textureId = QskTextureRenderer::createTextureFromGraphic(
|
||||||
|
renderMode, rect.size(), graphic, colorFilter );
|
||||||
uint textureId = QskGraphicTextureFactory::createTexture(
|
|
||||||
renderMode, textureRect, Qt::IgnoreAspectRatio, graphic, colorFilter );
|
|
||||||
|
|
||||||
QskTextureNode::setTextureId( textureId );
|
QskTextureNode::setTextureId( textureId );
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#ifndef QSK_GRAPHIC_NODE_H
|
#ifndef QSK_GRAPHIC_NODE_H
|
||||||
#define QSK_GRAPHIC_NODE_H
|
#define QSK_GRAPHIC_NODE_H
|
||||||
|
|
||||||
#include "QskGraphicTextureFactory.h"
|
#include "QskTextureRenderer.h"
|
||||||
#include "QskTextureNode.h"
|
#include "QskTextureNode.h"
|
||||||
|
|
||||||
class QskGraphic;
|
class QskGraphic;
|
||||||
|
@ -19,7 +19,7 @@ class QSK_EXPORT QskGraphicNode : public QskTextureNode
|
||||||
~QskGraphicNode() override;
|
~QskGraphicNode() override;
|
||||||
|
|
||||||
void setGraphic( const QskGraphic&, const QskColorFilter&,
|
void setGraphic( const QskGraphic&, const QskColorFilter&,
|
||||||
QskGraphicTextureFactory::RenderMode, const QRect& );
|
QskTextureRenderer::RenderMode, const QRect& );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setTextureId( int ) = delete;
|
void setTextureId( int ) = delete;
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* This file may be used under the terms of the QSkinny License, Version 1.0
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "QskPaintedNode.h"
|
||||||
|
#include "QskTextureRenderer.h"
|
||||||
|
|
||||||
|
class QskPaintedNode::PaintHelper : public QskTextureRenderer::PaintHelper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline PaintHelper( QskPaintedNode* node )
|
||||||
|
: m_node( node )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void paint( QPainter* painter, const QSize& size ) override
|
||||||
|
{
|
||||||
|
m_node->paint( painter, size );
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QskPaintedNode* m_node;
|
||||||
|
};
|
||||||
|
|
||||||
|
QskPaintedNode::QskPaintedNode()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QskPaintedNode::~QskPaintedNode()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskPaintedNode::update(
|
||||||
|
QskTextureRenderer::RenderMode renderMode, const QRect& rect )
|
||||||
|
{
|
||||||
|
bool isTextureDirty = ( QskTextureNode::textureId() == 0 );
|
||||||
|
|
||||||
|
if ( !isTextureDirty )
|
||||||
|
{
|
||||||
|
const auto oldRect = QskTextureNode::rect();
|
||||||
|
isTextureDirty = ( rect.width() != static_cast< int >( oldRect.width() ) ) ||
|
||||||
|
( rect.height() != static_cast< int >( oldRect.height() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
QskTextureNode::setRect( rect );
|
||||||
|
|
||||||
|
const uint newHash = hash();
|
||||||
|
if ( ( newHash == 0 ) || ( newHash != m_hash ) )
|
||||||
|
{
|
||||||
|
m_hash = newHash;
|
||||||
|
isTextureDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( isTextureDirty )
|
||||||
|
{
|
||||||
|
PaintHelper helper( this );
|
||||||
|
const uint textureId =
|
||||||
|
QskTextureRenderer::createTexture( renderMode, rect.size(), &helper );
|
||||||
|
|
||||||
|
QskTextureNode::setTextureId( textureId );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* This file may be used under the terms of the QSkinny License, Version 1.0
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QSK_PAINTED_NODE_H
|
||||||
|
#define QSK_PAINTED_NODE_H
|
||||||
|
|
||||||
|
#include "QskTextureNode.h"
|
||||||
|
#include "QskTextureRenderer.h"
|
||||||
|
|
||||||
|
class QSK_EXPORT QskPaintedNode : public QskTextureNode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QskPaintedNode();
|
||||||
|
~QskPaintedNode() override;
|
||||||
|
|
||||||
|
void update( QskTextureRenderer::RenderMode, const QRect& );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void paint( QPainter*, const QSizeF& ) = 0;
|
||||||
|
|
||||||
|
// a hash value of '0' always results in repainting
|
||||||
|
virtual uint hash() = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
class PaintHelper;
|
||||||
|
|
||||||
|
void setTextureId( int ) = delete;
|
||||||
|
void setRect( const QRectF& ) = delete;
|
||||||
|
|
||||||
|
uint m_hash;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,176 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* This file may be used under the terms of the QSkinny License, Version 1.0
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "QskTextureRenderer.h"
|
||||||
|
#include "QskColorFilter.h"
|
||||||
|
#include "QskGraphic.h"
|
||||||
|
#include "QskSetup.h"
|
||||||
|
|
||||||
|
#include <qopenglcontext.h>
|
||||||
|
#include <qopenglextrafunctions.h>
|
||||||
|
#include <qopenglframebufferobject.h>
|
||||||
|
#include <qopenglfunctions.h>
|
||||||
|
#include <qopenglpaintdevice.h>
|
||||||
|
#include <qopengltexture.h>
|
||||||
|
|
||||||
|
#include <qimage.h>
|
||||||
|
#include <qpainter.h>
|
||||||
|
|
||||||
|
static uint qskCreateTextureOpenGL(
|
||||||
|
const QSize& size, QskTextureRenderer::PaintHelper* helper )
|
||||||
|
{
|
||||||
|
const int width = size.width();
|
||||||
|
const int height = size.height();
|
||||||
|
|
||||||
|
QOpenGLFramebufferObjectFormat format1;
|
||||||
|
format1.setAttachment( QOpenGLFramebufferObject::CombinedDepthStencil );
|
||||||
|
|
||||||
|
// ### TODO: get samples from window instead
|
||||||
|
format1.setSamples( QOpenGLContext::currentContext()->format().samples() );
|
||||||
|
|
||||||
|
QOpenGLFramebufferObject multisampledFbo( width, height, format1 );
|
||||||
|
|
||||||
|
QOpenGLPaintDevice pd( width, height );
|
||||||
|
|
||||||
|
{
|
||||||
|
QPainter painter( &pd );
|
||||||
|
|
||||||
|
helper->paint( &painter, size );
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
if ( format1.samples() > 0 )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Multisampling in the window surface might get lost
|
||||||
|
as a side effect of rendering to the FBO.
|
||||||
|
weired, needs to be investigated more
|
||||||
|
*/
|
||||||
|
painter.setRenderHint( QPainter::Antialiasing, true );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
QOpenGLFramebufferObjectFormat format2;
|
||||||
|
format2.setAttachment( QOpenGLFramebufferObject::NoAttachment );
|
||||||
|
|
||||||
|
QOpenGLFramebufferObject fbo( width, height, format2 );
|
||||||
|
|
||||||
|
/*
|
||||||
|
Mirror vertically to be compliant with what QQuickTextureFactory expects.
|
||||||
|
for some reason we have to add 1 pixel to avoid that the mirrored
|
||||||
|
image gets cut off.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const QRect sourceRect( 0, 0, width, height );
|
||||||
|
const QRect targetRect( 0, height + 1, width, -height );
|
||||||
|
|
||||||
|
QOpenGLFramebufferObject::blitFramebuffer(
|
||||||
|
&fbo, sourceRect, &multisampledFbo, targetRect );
|
||||||
|
|
||||||
|
return fbo.takeTexture();
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint qskCreateTextureRaster(
|
||||||
|
const QSize& size, QskTextureRenderer::PaintHelper* helper )
|
||||||
|
{
|
||||||
|
QImage image( size, QImage::Format_RGBA8888_Premultiplied );
|
||||||
|
image.fill( Qt::transparent );
|
||||||
|
|
||||||
|
{
|
||||||
|
QPainter painter( &image );
|
||||||
|
helper->paint( &painter, size );
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto target = QOpenGLTexture::Target2D;
|
||||||
|
|
||||||
|
auto context = QOpenGLContext::currentContext();
|
||||||
|
if ( context == nullptr )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
auto& f = *context->functions();
|
||||||
|
|
||||||
|
GLint oldTexture; // we can't rely on having OpenGL Direct State Access
|
||||||
|
f.glGetIntegerv( QOpenGLTexture::BindingTarget2D, &oldTexture );
|
||||||
|
|
||||||
|
GLuint textureId;
|
||||||
|
f.glGenTextures( 1, &textureId );
|
||||||
|
|
||||||
|
f.glBindTexture( target, textureId );
|
||||||
|
|
||||||
|
f.glTexParameteri( target, GL_TEXTURE_MIN_FILTER, QOpenGLTexture::Nearest );
|
||||||
|
f.glTexParameteri( target, GL_TEXTURE_MAG_FILTER, QOpenGLTexture::Nearest );
|
||||||
|
|
||||||
|
f.glTexParameteri( target, GL_TEXTURE_WRAP_S, QOpenGLTexture::ClampToEdge );
|
||||||
|
f.glTexParameteri( target, GL_TEXTURE_WRAP_T, QOpenGLTexture::ClampToEdge );
|
||||||
|
|
||||||
|
if ( QOpenGLTexture::hasFeature( QOpenGLTexture::ImmutableStorage ) )
|
||||||
|
{
|
||||||
|
auto& ef = *context->extraFunctions();
|
||||||
|
ef.glTexStorage2D( target, 1,
|
||||||
|
QOpenGLTexture::RGBA8_UNorm, image.width(), image.height() );
|
||||||
|
|
||||||
|
f.glTexSubImage2D( target, 0, 0, 0, image.width(), image.height(),
|
||||||
|
QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, image.constBits() );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
f.glTexImage2D( target, 0, QOpenGLTexture::RGBA8_UNorm,
|
||||||
|
image.width(), image.height(), 0,
|
||||||
|
QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, image.constBits() );
|
||||||
|
}
|
||||||
|
|
||||||
|
f.glBindTexture( target, oldTexture );
|
||||||
|
|
||||||
|
return textureId;
|
||||||
|
}
|
||||||
|
|
||||||
|
QskTextureRenderer::PaintHelper::~PaintHelper()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
uint QskTextureRenderer::createTexture(
|
||||||
|
RenderMode renderMode, const QSize& size, PaintHelper* helper )
|
||||||
|
{
|
||||||
|
if ( renderMode == AutoDetect )
|
||||||
|
{
|
||||||
|
if ( qskSetup->controlFlags() & QskSetup::PreferRasterForTextures )
|
||||||
|
renderMode = Raster;
|
||||||
|
else
|
||||||
|
renderMode = OpenGL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( renderMode == Raster )
|
||||||
|
return qskCreateTextureRaster( size, helper );
|
||||||
|
else
|
||||||
|
return qskCreateTextureOpenGL( size, helper );
|
||||||
|
}
|
||||||
|
|
||||||
|
uint QskTextureRenderer::createTextureFromGraphic(
|
||||||
|
RenderMode renderMode, const QSize& size,
|
||||||
|
const QskGraphic& graphic, const QskColorFilter& colorFilter )
|
||||||
|
{
|
||||||
|
class PaintHelper : public QskTextureRenderer::PaintHelper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PaintHelper( const QskGraphic& graphic, const QskColorFilter& filter )
|
||||||
|
: m_graphic( graphic )
|
||||||
|
, m_filter( filter )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void paint( QPainter* painter, const QSize& size ) override
|
||||||
|
{
|
||||||
|
const QRect rect( 0, 0, size.width(), size.height() );
|
||||||
|
m_graphic.render( painter, rect, m_filter, Qt::KeepAspectRatio );
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const QskGraphic& m_graphic;
|
||||||
|
const QskColorFilter& m_filter;
|
||||||
|
};
|
||||||
|
|
||||||
|
PaintHelper helper( graphic, colorFilter );
|
||||||
|
return createTexture( renderMode, size, &helper );
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* This file may be used under the terms of the QSkinny License, Version 1.0
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QSK_TEXTURE_RENDERER_H
|
||||||
|
#define QSK_TEXTURE_RENDERER_H
|
||||||
|
|
||||||
|
#include "QskGlobal.h"
|
||||||
|
|
||||||
|
class QskGraphic;
|
||||||
|
class QskColorFilter;
|
||||||
|
|
||||||
|
class QPainter;
|
||||||
|
class QSize;
|
||||||
|
|
||||||
|
namespace QskTextureRenderer
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Raster usually provides a better antialiasing and is less buggy,
|
||||||
|
while OpenGL might be faster - depending on the content that has
|
||||||
|
to be painted.
|
||||||
|
|
||||||
|
Since Qt 5.10 X11 is back and could be an interesting option
|
||||||
|
with good quality and hardware accelerated performance. TODO ...
|
||||||
|
*/
|
||||||
|
enum RenderMode
|
||||||
|
{
|
||||||
|
AutoDetect, // depends on QskSetup::controlFlags()
|
||||||
|
|
||||||
|
Raster,
|
||||||
|
OpenGL
|
||||||
|
};
|
||||||
|
|
||||||
|
class QSK_EXPORT PaintHelper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~PaintHelper();
|
||||||
|
virtual void paint( QPainter*, const QSize& ) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
QSK_EXPORT uint createTexture(
|
||||||
|
RenderMode, const QSize&, PaintHelper* helper );
|
||||||
|
|
||||||
|
QSK_EXPORT uint createTextureFromGraphic(
|
||||||
|
RenderMode, const QSize&, const QskGraphic&, const QskColorFilter& );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
23
src/src.pro
23
src/src.pro
|
@ -95,11 +95,13 @@ HEADERS += \
|
||||||
nodes/QskBoxRenderer.h \
|
nodes/QskBoxRenderer.h \
|
||||||
nodes/QskBoxRendererColorMap.h \
|
nodes/QskBoxRendererColorMap.h \
|
||||||
nodes/QskGraphicNode.h \
|
nodes/QskGraphicNode.h \
|
||||||
|
nodes/QskPaintedNode.h \
|
||||||
nodes/QskPlainTextRenderer.h \
|
nodes/QskPlainTextRenderer.h \
|
||||||
nodes/QskRichTextRenderer.h \
|
nodes/QskRichTextRenderer.h \
|
||||||
nodes/QskTextRenderer.h \
|
|
||||||
nodes/QskTextNode.h \
|
nodes/QskTextNode.h \
|
||||||
|
nodes/QskTextRenderer.h \
|
||||||
nodes/QskTextureNode.h \
|
nodes/QskTextureNode.h \
|
||||||
|
nodes/QskTextureRenderer.h \
|
||||||
nodes/QskVertex.h
|
nodes/QskVertex.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
|
@ -109,11 +111,13 @@ SOURCES += \
|
||||||
nodes/QskBoxRendererEllipse.cpp \
|
nodes/QskBoxRendererEllipse.cpp \
|
||||||
nodes/QskBoxRendererDEllipse.cpp \
|
nodes/QskBoxRendererDEllipse.cpp \
|
||||||
nodes/QskGraphicNode.cpp \
|
nodes/QskGraphicNode.cpp \
|
||||||
|
nodes/QskPaintedNode.cpp \
|
||||||
nodes/QskPlainTextRenderer.cpp \
|
nodes/QskPlainTextRenderer.cpp \
|
||||||
nodes/QskRichTextRenderer.cpp \
|
nodes/QskRichTextRenderer.cpp \
|
||||||
nodes/QskTextRenderer.cpp \
|
|
||||||
nodes/QskTextNode.cpp \
|
nodes/QskTextNode.cpp \
|
||||||
|
nodes/QskTextRenderer.cpp \
|
||||||
nodes/QskTextureNode.cpp \
|
nodes/QskTextureNode.cpp \
|
||||||
|
nodes/QskTextureRenderer.cpp \
|
||||||
nodes/QskVertex.cpp
|
nodes/QskVertex.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
|
@ -295,6 +299,14 @@ SOURCES += \
|
||||||
dialogs/QskSelectionSubWindow.cpp \
|
dialogs/QskSelectionSubWindow.cpp \
|
||||||
dialogs/QskSelectionWindow.cpp
|
dialogs/QskSelectionWindow.cpp
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
inputpanel/QskTextPredictor.h \
|
||||||
|
inputpanel/QskInputContext.h \
|
||||||
|
inputpanel/QskInputPanel.h \
|
||||||
|
inputpanel/QskInputPanelBox.h \
|
||||||
|
inputpanel/QskInputPredictionBar.h \
|
||||||
|
inputpanel/QskVirtualKeyboard.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
inputpanel/QskTextPredictor.cpp \
|
inputpanel/QskTextPredictor.cpp \
|
||||||
inputpanel/QskInputContext.cpp \
|
inputpanel/QskInputContext.cpp \
|
||||||
|
@ -303,10 +315,3 @@ SOURCES += \
|
||||||
inputpanel/QskInputPredictionBar.cpp \
|
inputpanel/QskInputPredictionBar.cpp \
|
||||||
inputpanel/QskVirtualKeyboard.cpp
|
inputpanel/QskVirtualKeyboard.cpp
|
||||||
|
|
||||||
HEADERS += \
|
|
||||||
inputpanel/QskTextPredictor.h \
|
|
||||||
inputpanel/QskInputContext.h \
|
|
||||||
inputpanel/QskInputPanel.h \
|
|
||||||
inputpanel/QskInputPanelBox.h \
|
|
||||||
inputpanel/QskInputPredictionBar.h \
|
|
||||||
inputpanel/QskVirtualKeyboard.h
|
|
||||||
|
|
Loading…
Reference in New Issue