Krita Source Code Documentation
Loading...
Searching...
No Matches
KisOpenGLCanvasRenderer Class Reference

#include <KisOpenGLCanvasRenderer.h>

+ Inheritance diagram for KisOpenGLCanvasRenderer:

Classes

class  CanvasBridge
 
struct  Private
 

Public Member Functions

void channelSelectionChanged (const QBitArray &channelFlags)
 
void finishResizingImage (qint32 w, qint32 h)
 
void initializeGL ()
 
 KisOpenGLCanvasRenderer (CanvasBridge *canvasBridge, KisImageWSP image, const KisDisplayConfig &displayConfig, QSharedPointer< KisDisplayFilter > displayFilter)
 
void notifyImageColorSpaceChanged (const KoColorSpace *cs)
 
KisOpenGLImageTexturesSP openGLImageTextures () const
 
void paintCanvasOnly (const QRect &canvasImageDirtyRect, const QRect &viewportUpdateRect=QRect())
 
void paintToolOutline (const KisOptimizedBrushOutline &path, const QRect &viewportUpdateRect, const int thickness=1)
 
void resizeGL (int width, int height)
 
void setDisplayConfig (const KisDisplayConfig &config)
 
void setDisplayFilter (QSharedPointer< KisDisplayFilter > displayFilter)
 
void setLodResetInProgress (bool value)
 
void setWrapAroundViewingMode (bool value)
 
void setWrapAroundViewingModeAxis (WrapAroundAxis value)
 
KisUpdateInfoSP startUpdateCanvasProjection (const QRect &rc)
 
QRect updateCanvasProjection (KisUpdateInfoSP info)
 
void updateConfig ()
 
void updateCursorColor ()
 
void updatePixelGridMode ()
 
bool wrapAroundViewingMode () const
 
WrapAroundAxis wrapAroundViewingModeAxis () const
 
 ~KisOpenGLCanvasRenderer ()
 

Private Member Functions

QColor borderColor () const
 
KisCanvas2canvas () const
 
QOpenGLContext * context () const
 
KisCoordinatesConvertercoordinatesConverter () const
 
qreal devicePixelRatioF () const
 
void drawBackground (const QRect &updateRect)
 
void drawCheckers (const QRect &updateRect)
 
void drawGrid (const QRect &updateRect)
 
void drawImage (const QRect &updateRect)
 
void drawImageTiles (int firstCol, int lastCol, int firstRow, int lastRow, qreal scaleX, qreal scaleY, const QPoint &wrapAroundOffset)
 
void initializeDisplayShader ()
 
void initializeShaders ()
 
void renderCanvasGL (const QRect &updateRect)
 
void reportFailedShaderCompilation (const QString &context)
 
void setDisplayFilterImpl (QSharedPointer< KisDisplayFilter > displayFilter, bool initializing)
 
QRectF surfaceToWidget (const QRectF &rc)
 
QRectF widgetToSurface (const QRectF &rc)
 

Private Attributes

Private *const d
 

Detailed Description

KisOpenGLCanvasRenderer is the class that shows the actual image using OpenGL

Definition at line 43 of file KisOpenGLCanvasRenderer.h.

Constructor & Destructor Documentation

◆ KisOpenGLCanvasRenderer()

KisOpenGLCanvasRenderer::KisOpenGLCanvasRenderer ( CanvasBridge * canvasBridge,
KisImageWSP image,
const KisDisplayConfig & displayConfig,
QSharedPointer< KisDisplayFilter > displayFilter )

Definition at line 143 of file KisOpenGLCanvasRenderer.cpp.

147 : d(new Private())
148{
149 d->canvasBridge = canvasBridge;
150
151 const KisDisplayConfig &config = displayConfig;
152
155 config.profile,
156 config.intent,
157 config.conversionFlags);
158
159
160 setDisplayFilterImpl(displayFilter, true);
161}
KisDisplayConfig This class keeps track of the color management configuration for image to display....
KoColorConversionTransformation::ConversionFlags conversionFlags
const KoColorProfile * profile
KoColorConversionTransformation::Intent intent
void setDisplayFilterImpl(QSharedPointer< KisDisplayFilter > displayFilter, bool initializing)
static KisOpenGLImageTexturesSP createImageTextures(KisImageWSP image, const KoColorProfile *monitorProfile, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags)

References KisOpenGLCanvasRenderer::Private::canvasBridge, KisDisplayConfig::conversionFlags, KisOpenGLImageTextures::createImageTextures(), d, KisDisplayConfig::intent, KisOpenGLCanvasRenderer::Private::openGLImageTextures, KisDisplayConfig::profile, and setDisplayFilterImpl().

◆ ~KisOpenGLCanvasRenderer()

KisOpenGLCanvasRenderer::~KisOpenGLCanvasRenderer ( )

Definition at line 163 of file KisOpenGLCanvasRenderer.cpp.

164{
165 delete d;
166}

References d.

Member Function Documentation

◆ borderColor()

QColor KisOpenGLCanvasRenderer::borderColor ( ) const
private

◆ canvas()

KisCanvas2 * KisOpenGLCanvasRenderer::canvas ( ) const
private

◆ channelSelectionChanged()

void KisOpenGLCanvasRenderer::channelSelectionChanged ( const QBitArray & channelFlags)

◆ context()

QOpenGLContext * KisOpenGLCanvasRenderer::context ( ) const
private

◆ coordinatesConverter()

KisCoordinatesConverter * KisOpenGLCanvasRenderer::coordinatesConverter ( ) const
private

◆ devicePixelRatioF()

qreal KisOpenGLCanvasRenderer::devicePixelRatioF ( ) const
private

◆ drawBackground()

void KisOpenGLCanvasRenderer::drawBackground ( const QRect & updateRect)
private

Definition at line 585 of file KisOpenGLCanvasRenderer.cpp.

586{
587 Q_UNUSED(updateRect);
588
589 // Draw the border (that is, clear the whole widget to the border color)
590 QColor widgetBackgroundColor = borderColor();
591
592 const KoColorSpace *finalColorSpace =
596
597 KoColor convertedBackgroundColor = KoColor(widgetBackgroundColor, KoColorSpaceRegistry::instance()->rgb8());
598 convertedBackgroundColor.convertTo(finalColorSpace);
599
600 QVector<float> channels = QVector<float>(4);
601 convertedBackgroundColor.colorSpace()->normalisedChannelsValue(convertedBackgroundColor.data(), channels);
602
603
604 // Data returned by KoRgbU8ColorSpace comes in the order: blue, green, red.
605 glClearColor(channels[2], channels[1], channels[0], 1.0);
606 glClear(GL_COLOR_BUFFER_BIT);
607}
const KoID RGBAColorModelID("RGBA", ki18n("RGB/Alpha"))
const KoColorProfile * monitorProfile()
KisOpenGLUpdateInfoBuilder & updateInfoBuilder()
virtual KoID colorDepthId() const =0
virtual void normalisedChannelsValue(const quint8 *pixel, QVector< float > &channels) const =0
void convertTo(const KoColorSpace *cs, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags)
Definition KoColor.cpp:136
quint8 * data()
Definition KoColor.h:144
const KoColorSpace * colorSpace() const
return the current colorSpace
Definition KoColor.h:82
QString id() const
Definition KoID.cpp:63
const KoColorSpace * destinationColorSpace() const
const KoColorSpace * colorSpace(const QString &colorModelId, const QString &colorDepthId, const KoColorProfile *profile)
static KoColorSpaceRegistry * instance()

References borderColor(), KoColorSpace::colorDepthId(), KoColor::colorSpace(), KoColorSpaceRegistry::colorSpace(), KoColor::convertTo(), d, KoColor::data(), KisOpenGLUpdateInfoBuilder::destinationColorSpace(), KoID::id(), KoColorSpaceRegistry::instance(), KisOpenGLImageTextures::monitorProfile(), KoColorSpace::normalisedChannelsValue(), KisOpenGLCanvasRenderer::Private::openGLImageTextures, RGBAColorModelID, and KisOpenGLImageTextures::updateInfoBuilder().

◆ drawCheckers()

void KisOpenGLCanvasRenderer::drawCheckers ( const QRect & updateRect)
private

Definition at line 609 of file KisOpenGLCanvasRenderer.cpp.

610{
611 Q_UNUSED(updateRect);
612
613 if (!d->checkerShader) {
614 return;
615 }
616
618 QTransform textureTransform;
619 QTransform modelTransform;
620 QRectF textureRect;
621 QRectF modelRect;
622
623 const QSizeF &widgetSize = d->pixelAlignedWidgetSize;
624 QRectF viewportRect;
625 if (!d->wrapAroundMode) {
626 viewportRect = converter->imageRectInViewportPixels();
627 }
628 else {
629 const QRectF ir = converter->imageRectInViewportPixels();
630 viewportRect = converter->widgetToViewport(QRectF(0, 0, widgetSize.width(), widgetSize.height()));
632 viewportRect.setTop(ir.top());
633 viewportRect.setBottom(ir.bottom());
634 }
636 viewportRect.setLeft(ir.left());
637 viewportRect.setRight(ir.right());
638 }
639 }
640
641 // TODO: check if it works correctly
642 if (!canvas()->renderingLimit().isEmpty()) {
643 const QRect vrect = converter->imageToViewport(canvas()->renderingLimit()).toAlignedRect();
644 viewportRect &= vrect;
645 }
646
647 converter->getOpenGLCheckersInfo(viewportRect,
648 &textureTransform, &modelTransform, &textureRect, &modelRect, d->scrollCheckers);
649
650 textureTransform *= QTransform::fromScale(d->checkSizeScale / KisOpenGLImageTextures::BACKGROUND_TEXTURE_SIZE,
652
653 if (!d->checkerShader->bind()) {
654 qWarning() << "Could not bind checker shader";
655 return;
656 }
657
658 QMatrix4x4 projectionMatrix;
659 projectionMatrix.setToIdentity();
660 // FIXME: It may be better to have the projection in device pixel, but
661 // this requires introducing a new coordinate system.
662 projectionMatrix.ortho(0, widgetSize.width(), widgetSize.height(), 0, NEAR_VAL, FAR_VAL);
663
664 // Set view/projection matrices
665 QMatrix4x4 modelMatrix(modelTransform);
666 modelMatrix.optimize();
667 modelMatrix = projectionMatrix * modelMatrix;
668 d->checkerShader->setUniformValue(d->checkerShader->location(Uniform::ModelViewProjection), modelMatrix);
669
670 QMatrix4x4 textureMatrix(textureTransform);
671 d->checkerShader->setUniformValue(d->checkerShader->location(Uniform::TextureMatrix), textureMatrix);
672
673 //Setup the geometry for rendering
676 QOpenGLBuffer *vertexBuf = d->checkersVertexBuffer.getNextBuffer();
677
678 vertexBuf->bind();
679 vertexBuf->write(0, d->vertices, 3 * 6 * sizeof(float));
680 glVertexAttribPointer(PROGRAM_VERTEX_ATTRIBUTE, 3, GL_FLOAT, GL_FALSE, 0, 0);
681
682
684 QOpenGLBuffer *vertexTextureBuf = d->checkersTextureVertexBuffer.getNextBuffer();
685
686 vertexTextureBuf->bind();
687 vertexTextureBuf->write(0, d->texCoords, 2 * 6 * sizeof(float));
688 glVertexAttribPointer(PROGRAM_TEXCOORD_ATTRIBUTE, 2, GL_FLOAT, GL_FALSE, 0, 0);
689 }
690 else {
692 d->checkerShader->enableAttributeArray(PROGRAM_VERTEX_ATTRIBUTE);
693 d->checkerShader->setAttributeArray(PROGRAM_VERTEX_ATTRIBUTE, d->vertices);
694
696 d->checkerShader->enableAttributeArray(PROGRAM_TEXCOORD_ATTRIBUTE);
698 }
699
700 // render checkers
701 glActiveTexture(GL_TEXTURE0);
702 glBindTexture(GL_TEXTURE_2D, d->openGLImageTextures->checkerTexture());
703
704 glDrawArrays(GL_TRIANGLES, 0, 6);
705
706 glBindTexture(GL_TEXTURE_2D, 0);
707 d->checkerShader->release();
708 glBindBuffer(GL_ARRAY_BUFFER, 0);
709}
#define NEAR_VAL
#define FAR_VAL
@ WRAPAROUND_HORIZONTAL
@ WRAPAROUND_VERTICAL
_Private::Traits< T >::Result widgetToViewport(const T &obj) const
void getOpenGLCheckersInfo(const QRectF &viewportRect, QTransform *textureTransform, QTransform *modelTransform, QRectF *textureRect, QRectF *modelRect, const bool scrollCheckers) const
_Private::Traits< T >::Result imageToViewport(const T &obj) const
KisCoordinatesConverter * coordinatesConverter() const
static bool supportsVAO()
int location(Uniform uniform)
#define PROGRAM_TEXCOORD_ATTRIBUTE
#define PROGRAM_VERTEX_ATTRIBUTE
@ ModelViewProjection
void rectToTexCoords(QVector2D *texCoords, const QRectF &rc)
void rectToVertices(QVector3D *vertices, const QRectF &rc)
KisOpenGLBufferCircularStorage checkersVertexBuffer
KisOpenGLBufferCircularStorage checkersTextureVertexBuffer

References KisOpenGLImageTextures::BACKGROUND_TEXTURE_SIZE, canvas(), KisOpenGLCanvasRenderer::Private::checkerShader, KisOpenGLCanvasRenderer::Private::checkersTextureVertexBuffer, KisOpenGLCanvasRenderer::Private::checkersVertexBuffer, KisOpenGLImageTextures::checkerTexture(), KisOpenGLCanvasRenderer::Private::checkSizeScale, coordinatesConverter(), d, FAR_VAL, KisOpenGLBufferCircularStorage::getNextBuffer(), KisCoordinatesConverter::getOpenGLCheckersInfo(), KisCoordinatesConverter::imageRectInViewportPixels(), KisCoordinatesConverter::imageToViewport(), KisShaderProgram::location(), ModelViewProjection, NEAR_VAL, KisOpenGLCanvasRenderer::Private::openGLImageTextures, KisOpenGLCanvasRenderer::Private::pixelAlignedWidgetSize, PROGRAM_TEXCOORD_ATTRIBUTE, PROGRAM_VERTEX_ATTRIBUTE, KisPaintingTweaks::rectToTexCoords(), KisPaintingTweaks::rectToVertices(), KisOpenGLCanvasRenderer::Private::scrollCheckers, KisOpenGL::supportsVAO(), KisOpenGLCanvasRenderer::Private::texCoords, TextureMatrix, KisOpenGLCanvasRenderer::Private::vertices, KisCoordinatesConverter::widgetToViewport(), WRAPAROUND_HORIZONTAL, WRAPAROUND_VERTICAL, KisOpenGLCanvasRenderer::Private::wrapAroundMode, and KisOpenGLCanvasRenderer::Private::wrapAroundModeAxis.

◆ drawGrid()

void KisOpenGLCanvasRenderer::drawGrid ( const QRect & updateRect)
private

Definition at line 711 of file KisOpenGLCanvasRenderer.cpp.

712{
713 if (!d->solidColorShader->bind()) {
714 return;
715 }
716
717 const QSizeF &widgetSize = d->pixelAlignedWidgetSize;
718
719 QMatrix4x4 projectionMatrix;
720 projectionMatrix.setToIdentity();
721 // FIXME: It may be better to have the projection in device pixel, but
722 // this requires introducing a new coordinate system.
723 projectionMatrix.ortho(0, widgetSize.width(), widgetSize.height(), 0, NEAR_VAL, FAR_VAL);
724
725 // Set view/projection matrices
726 QMatrix4x4 modelMatrix(coordinatesConverter()->imageToWidgetTransform());
727 modelMatrix.optimize();
728 modelMatrix = projectionMatrix * modelMatrix;
730
731 glEnable(GL_BLEND);
732 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
733
734 d->solidColorShader->setUniformValue(
736 QVector4D(d->gridColor.redF(), d->gridColor.greenF(), d->gridColor.blueF(), 0.5f));
737
738 QRectF widgetRect(0,0, widgetSize.width(), widgetSize.height());
739 QRectF widgetRectInImagePixels = coordinatesConverter()->documentToImage(coordinatesConverter()->widgetToDocument(widgetRect));
740 QRect wr = widgetRectInImagePixels.toAlignedRect();
741
742 if (!d->wrapAroundMode) {
744 }
745
746 if (!updateRect.isEmpty()) {
747 const QRect updateRectInImagePixels = coordinatesConverter()->widgetToImage(updateRect).toAlignedRect();
748 wr &= updateRectInImagePixels;
749 }
750
751 QPoint topLeftCorner = wr.topLeft();
752 QPoint bottomRightCorner = wr.bottomRight() + QPoint(1, 1);
754
755 for (int i = topLeftCorner.x(); i <= bottomRightCorner.x(); ++i) {
756 grid.append(QVector3D(i, topLeftCorner.y(), 0));
757 grid.append(QVector3D(i, bottomRightCorner.y(), 0));
758 }
759 for (int i = topLeftCorner.y(); i <= bottomRightCorner.y(); ++i) {
760 grid.append(QVector3D(topLeftCorner.x(), i, 0));
761 grid.append(QVector3D(bottomRightCorner.x(), i, 0));
762 }
763
765 d->outlineVAO.bind();
766 d->lineVertexBuffer.bind();
767 d->lineVertexBuffer.allocate(grid.constData(), 3 * grid.size() * sizeof(float));
768 }
769 else {
770 d->solidColorShader->enableAttributeArray(PROGRAM_VERTEX_ATTRIBUTE);
771 d->solidColorShader->setAttributeArray(PROGRAM_VERTEX_ATTRIBUTE, grid.constData());
772 }
773
774 glDrawArrays(GL_LINES, 0, grid.size());
775
777 d->lineVertexBuffer.release();
778 d->outlineVAO.release();
779 }
780
781 d->solidColorShader->release();
782 glDisable(GL_BLEND);
783}
_Private::Traits< T >::Result widgetToImage(const T &obj) const
_Private::Traits< T >::Result documentToImage(const T &obj) const

References coordinatesConverter(), d, KisCoordinatesConverter::documentToImage(), FAR_VAL, FragmentColor, KisOpenGLCanvasRenderer::Private::gridColor, KisOpenGLCanvasRenderer::Private::lineVertexBuffer, KisShaderProgram::location(), ModelViewProjection, NEAR_VAL, KisOpenGLCanvasRenderer::Private::openGLImageTextures, KisOpenGLCanvasRenderer::Private::outlineVAO, KisOpenGLCanvasRenderer::Private::pixelAlignedWidgetSize, PROGRAM_VERTEX_ATTRIBUTE, KisOpenGLCanvasRenderer::Private::solidColorShader, KisOpenGLImageTextures::storedImageBounds(), KisOpenGL::supportsVAO(), KisCoordinatesConverter::widgetToImage(), and KisOpenGLCanvasRenderer::Private::wrapAroundMode.

◆ drawImage()

void KisOpenGLCanvasRenderer::drawImage ( const QRect & updateRect)
private

Definition at line 785 of file KisOpenGLCanvasRenderer.cpp.

786{
787 if (!d->displayShader) {
788 return;
789 }
790
791 glEnable(GL_BLEND);
792 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
793
795
796 d->displayShader->bind();
797
798 const QSizeF &widgetSize = d->pixelAlignedWidgetSize;
799
800 QMatrix4x4 textureMatrix;
801 textureMatrix.setToIdentity();
802 d->displayShader->setUniformValue(d->displayShader->location(Uniform::TextureMatrix), textureMatrix);
803
804 QRectF widgetRect(0,0, widgetSize.width(), widgetSize.height());
805
806 if (!updateRect.isEmpty()) {
807 widgetRect &= updateRect;
808 }
809
810 QRectF widgetRectInImagePixels = converter->documentToImage(converter->widgetToDocument(widgetRect));
811
812 const QRect renderingLimit = canvas()->renderingLimit();
813
814 if (!renderingLimit.isEmpty()) {
815 widgetRectInImagePixels &= renderingLimit;
816 }
817
818 qreal scaleX, scaleY;
819 converter->imagePhysicalScale(&scaleX, &scaleY);
820
821 d->displayShader->setUniformValue(d->displayShader->location(Uniform::ViewportScale), (GLfloat) scaleX);
823
825 QRect wr = widgetRectInImagePixels.toAlignedRect();
826
827 if (!d->wrapAroundMode) {
828 // if we don't want to paint wrapping images, just limit the
829 // processing area, and the code will handle all the rest
830 wr &= ir;
831 }
833 wr.setTop(ir.top());
834 wr.setBottom(ir.bottom());
835 }
837 wr.setLeft(ir.left());
838 wr.setRight(ir.right());
839 }
840
841 const int firstColumn = d->xToColWithWrapCompensation(wr.left(), ir);
842 const int lastColumn = d->xToColWithWrapCompensation(wr.right(), ir);
843 const int firstRow = d->yToRowWithWrapCompensation(wr.top(), ir);
844 const int lastRow = d->yToRowWithWrapCompensation(wr.bottom(), ir);
845
846 const int minColumn = d->openGLImageTextures->xToCol(ir.left());
847 const int maxColumn = d->openGLImageTextures->xToCol(ir.right());
848 const int minRow = d->openGLImageTextures->yToRow(ir.top());
849 const int maxRow = d->openGLImageTextures->yToRow(ir.bottom());
850
851 const int imageColumns = maxColumn - minColumn + 1;
852 const int imageRows = maxRow - minRow + 1;
853
854 if (d->displayFilter) {
855 d->displayFilter->setupTextures(this, d->displayShader);
856 }
857
858 const int firstCloneX = qFloor(qreal(firstColumn) / imageColumns);
859 const int lastCloneX = qFloor(qreal(lastColumn) / imageColumns);
860 const int firstCloneY = qFloor(qreal(firstRow) / imageRows);
861 const int lastCloneY = qFloor(qreal(lastRow) / imageRows);
862
863 for (int cloneY = firstCloneY; cloneY <= lastCloneY; cloneY++) {
864 for (int cloneX = firstCloneX; cloneX <= lastCloneX; cloneX++) {
865
866 const int localFirstCol = cloneX == firstCloneX ? KisAlgebra2D::wrapValue(firstColumn, imageColumns) : 0;
867 const int localLastCol = cloneX == lastCloneX ? KisAlgebra2D::wrapValue(lastColumn, imageColumns) : imageColumns - 1;
868
869 const int localFirstRow = cloneY == firstCloneY ? KisAlgebra2D::wrapValue(firstRow, imageRows) : 0;
870 const int localLastRow = cloneY == lastCloneY ? KisAlgebra2D::wrapValue(lastRow, imageRows) : imageRows - 1;
871
872 drawImageTiles(localFirstCol, localLastCol,
873 localFirstRow, localLastRow,
874 scaleX, scaleY, QPoint(cloneX, cloneY));
875 }
876 }
877
878 d->displayShader->release();
879
880 glDisable(GL_BLEND);
881}
QRect renderingLimit
_Private::Traits< T >::Result widgetToDocument(const T &obj) const
void imagePhysicalScale(qreal *scaleX, qreal *scaleY) const
void drawImageTiles(int firstCol, int lastCol, int firstRow, int lastRow, qreal scaleX, qreal scaleY, const QPoint &wrapAroundOffset)
T wrapValue(T value, T wrapBounds)
int yToRowWithWrapCompensation(int y, const QRect &imageRect)
int xToColWithWrapCompensation(int x, const QRect &imageRect)
QSharedPointer< KisDisplayFilter > displayFilter

References canvas(), coordinatesConverter(), d, KisOpenGLCanvasRenderer::Private::displayFilter, KisOpenGLCanvasRenderer::Private::displayShader, KisCoordinatesConverter::documentToImage(), drawImageTiles(), KisCoordinatesConverter::imagePhysicalScale(), KisShaderProgram::location(), KisOpenGLCanvasRenderer::Private::openGLImageTextures, KisOpenGLCanvasRenderer::Private::pixelAlignedWidgetSize, KisCanvas2::renderingLimit, KisOpenGLImageTextures::storedImageBounds(), KisOpenGLImageTextures::texelSize(), TexelSize, TextureMatrix, ViewportScale, KisCoordinatesConverter::widgetToDocument(), WRAPAROUND_HORIZONTAL, WRAPAROUND_VERTICAL, KisOpenGLCanvasRenderer::Private::wrapAroundMode, KisOpenGLCanvasRenderer::Private::wrapAroundModeAxis, KisAlgebra2D::wrapValue(), KisOpenGLImageTextures::xToCol(), KisOpenGLCanvasRenderer::Private::xToColWithWrapCompensation(), KisOpenGLImageTextures::yToRow(), and KisOpenGLCanvasRenderer::Private::yToRowWithWrapCompensation().

◆ drawImageTiles()

void KisOpenGLCanvasRenderer::drawImageTiles ( int firstCol,
int lastCol,
int firstRow,
int lastRow,
qreal scaleX,
qreal scaleY,
const QPoint & wrapAroundOffset )
private

Definition at line 883 of file KisOpenGLCanvasRenderer.cpp.

884{
886 const QSizeF &widgetSize = d->pixelAlignedWidgetSize;
887
888 QMatrix4x4 projectionMatrix;
889 projectionMatrix.setToIdentity();
890 // FIXME: It may be better to have the projection in device pixel, but
891 // this requires introducing a new coordinate system.
892 projectionMatrix.ortho(0, widgetSize.width(), widgetSize.height(), 0, NEAR_VAL, FAR_VAL);
893
894 QTransform modelTransform = converter->imageToWidgetTransform();
895
896 if (!wrapAroundOffset.isNull()) {
897 const QRect ir = d->openGLImageTextures->storedImageBounds();
898
899 const QTransform wrapAroundTranslate = QTransform::fromTranslate(ir.width() * wrapAroundOffset.x(),
900 ir.height() * wrapAroundOffset.y());
901 modelTransform = wrapAroundTranslate * modelTransform;
902 }
903
904 // Set view/projection matrices
905 QMatrix4x4 modelMatrix(modelTransform);
906 modelMatrix.optimize();
907 modelMatrix = projectionMatrix * modelMatrix;
908 d->displayShader->setUniformValue(d->displayShader->location(Uniform::ModelViewProjection), modelMatrix);
909
910 int lastTileLodPlane = -1;
911
912 for (int col = firstCol; col <= lastCol; col++) {
913 for (int row = firstRow; row <= lastRow; row++) {
914
915 KisTextureTile *tile =
917
918 if (!tile) {
919 warnUI << "OpenGL: Trying to paint texture tile but it has not been created yet.";
920 continue;
921 }
922
923 //Setup the geometry for rendering
925 const int tileIndex = d->openGLImageTextures->getTextureBufferIndexCR(col, row);
926
927 const int vertexRectSize = 6 * 3 * sizeof(float);
929 glVertexAttribPointer(PROGRAM_VERTEX_ATTRIBUTE, 3, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void*>(tileIndex * vertexRectSize));
930
931 const int textureRectSize = 6 * 2 * sizeof(float);
933 glVertexAttribPointer(PROGRAM_TEXCOORD_ATTRIBUTE, 2, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void*>(tileIndex * textureRectSize));
934
935 } else {
936
937 const QRectF textureRect = tile->tileRectInTexturePixels();
938 const QRectF modelRect = tile->tileRectInImagePixels();
939
941 d->checkerShader->enableAttributeArray(PROGRAM_VERTEX_ATTRIBUTE);
942 d->checkerShader->setAttributeArray(PROGRAM_VERTEX_ATTRIBUTE, d->vertices);
943
945 d->checkerShader->enableAttributeArray(PROGRAM_TEXCOORD_ATTRIBUTE);
947 }
948
949 glActiveTexture(GL_TEXTURE0);
950
951 // switching uniform is a rather expensive operation on macOS, so we change it only
952 // when it is really needed
953 const int currentLodPlane = tile->bindToActiveTexture(d->lodSwitchInProgress);
955 (lastTileLodPlane < 0 || lastTileLodPlane != currentLodPlane)) {
956
958 (GLfloat) currentLodPlane);
959 lastTileLodPlane = currentLodPlane;
960 }
961
962 if (currentLodPlane > 0) {
963 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
964 } else if (SCALE_MORE_OR_EQUAL_TO(scaleX, scaleY, 2.0)) {
965 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
966 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
967 } else {
968 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
969
970 switch(d->filterMode) {
972 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
973 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
974 break;
976 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
977 break;
979 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
980 break;
982 if (SCALE_LESS_THAN(scaleX, scaleY, 0.5)) {
983 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
984 } else {
985 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
986 }
987 break;
988 }
989 }
990
991 glDrawArrays(GL_TRIANGLES, 0, 6);
992 }
993 }
994
995 glBindTexture(GL_TEXTURE_2D, 0);
996 glBindBuffer(GL_ARRAY_BUFFER, 0);
997}
int getTextureBufferIndexCR(int col, int row)
KisTextureTile * getTextureTileCR(int col, int row)
@ NearestFilterMode
Definition kis_opengl.h:34
@ HighQualityFiltering
Definition kis_opengl.h:37
@ BilinearFilterMode
Definition kis_opengl.h:35
@ TrilinearFilterMode
Definition kis_opengl.h:36
QRect tileRectInImagePixels()
QRectF tileRectInTexturePixels()
int bindToActiveTexture(bool blockMipmapRegeneration)
#define SCALE_LESS_THAN(scX, scY, value)
#define SCALE_MORE_OR_EQUAL_TO(scX, scY, value)
#define warnUI
Definition kis_debug.h:94

References KisOpenGL::BilinearFilterMode, KisTextureTile::bindToActiveTexture(), KisOpenGLCanvasRenderer::Private::checkerShader, coordinatesConverter(), d, KisOpenGLCanvasRenderer::Private::displayShader, FAR_VAL, KisOpenGLCanvasRenderer::Private::filterMode, FixedLodLevel, KisOpenGLImageTextures::getTextureBufferIndexCR(), KisOpenGLImageTextures::getTextureTileCR(), KisOpenGL::HighQualityFiltering, KisCoordinatesConverter::imageToWidgetTransform(), KisShaderProgram::location(), KisOpenGLCanvasRenderer::Private::lodSwitchInProgress, ModelViewProjection, NEAR_VAL, KisOpenGL::NearestFilterMode, KisOpenGLCanvasRenderer::Private::openGLImageTextures, KisOpenGLCanvasRenderer::Private::pixelAlignedWidgetSize, PROGRAM_TEXCOORD_ATTRIBUTE, PROGRAM_VERTEX_ATTRIBUTE, KisPaintingTweaks::rectToTexCoords(), KisPaintingTweaks::rectToVertices(), SCALE_LESS_THAN, SCALE_MORE_OR_EQUAL_TO, KisOpenGLImageTextures::storedImageBounds(), KisOpenGL::supportsVAO(), KisOpenGLCanvasRenderer::Private::texCoords, KisTextureTile::tileRectInImagePixels(), KisTextureTile::tileRectInTexturePixels(), KisOpenGLImageTextures::tileTexCoordBuffer(), KisOpenGLImageTextures::tileVertexBuffer(), KisOpenGL::TrilinearFilterMode, KisOpenGLCanvasRenderer::Private::vertices, and warnUI.

◆ finishResizingImage()

◆ initializeDisplayShader()

void KisOpenGLCanvasRenderer::initializeDisplayShader ( )
private

Definition at line 307 of file KisOpenGLCanvasRenderer.cpp.

308{
310
311 bool useHiQualityFiltering = d->filterMode == KisOpenGL::HighQualityFiltering;
312
313 delete d->displayShader;
314 d->displayShader = 0;
315
316 try {
317 d->displayShader = d->shaderLoader.loadDisplayShader(d->displayFilter, useHiQualityFiltering);
319 } catch (const ShaderLoaderException &e) {
321 }
322}
void reportFailedShaderCompilation(const QString &context)
KisShaderProgram * loadDisplayShader(QSharedPointer< KisDisplayFilter > displayFilter, bool useHiQualityFiltering)
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128

References KisOpenGLCanvasRenderer::Private::canvasInitialized, d, KisOpenGLCanvasRenderer::Private::displayFilter, KisOpenGLCanvasRenderer::Private::displayShader, KisOpenGLCanvasRenderer::Private::displayShaderCompiledWithDisplayFilterSupport, KisOpenGLCanvasRenderer::Private::filterMode, KisOpenGL::HighQualityFiltering, KIS_SAFE_ASSERT_RECOVER_RETURN, KisOpenGLShaderLoader::loadDisplayShader(), reportFailedShaderCompilation(), and KisOpenGLCanvasRenderer::Private::shaderLoader.

◆ initializeGL()

void KisOpenGLCanvasRenderer::initializeGL ( )

Definition at line 245 of file KisOpenGLCanvasRenderer.cpp.

246{
248 initializeOpenGLFunctions();
249
250 KisConfig cfg(true);
251 d->openGLImageTextures->setProofingConfig(canvas()->proofingConfiguration());
252 d->openGLImageTextures->initGL(context()->functions());
254
256
257 // If we support OpenGL 3.0, then prepare our VAOs and VBOs for drawing
259 d->quadVAO.create();
260 d->quadVAO.bind();
261
262 glEnableVertexAttribArray(PROGRAM_VERTEX_ATTRIBUTE);
263 glEnableVertexAttribArray(PROGRAM_TEXCOORD_ATTRIBUTE);
264
265 d->checkersVertexBuffer.allocate(NumberOfBuffers, 6 * 3 * sizeof(float));
266 d->checkersTextureVertexBuffer.allocate(NumberOfBuffers, 6 * 2 * sizeof(float));
267
268 // Create the outline buffer, this buffer will store the outlines of
269 // tools and will frequently change data
270 d->outlineVAO.create();
271 d->outlineVAO.bind();
272
273 glEnableVertexAttribArray(PROGRAM_VERTEX_ATTRIBUTE);
274
275 // The outline buffer has a StreamDraw usage pattern, because it changes constantly
276 d->lineVertexBuffer.create();
277 d->lineVertexBuffer.setUsagePattern(QOpenGLBuffer::StreamDraw);
278 d->lineVertexBuffer.bind();
279 glVertexAttribPointer(PROGRAM_VERTEX_ATTRIBUTE, 3, GL_FLOAT, GL_FALSE, 0, 0);
280 }
281
282 d->canvasInitialized = true;
283}
static constexpr int NumberOfBuffers
static QImage createCheckersImage(qint32 checkSize=-1)
QOpenGLContext * context() const
void generateCheckerTexture(const QImage &checkImage)
void initGL(QOpenGLFunctions *f)
void setProofingConfig(KisProofingConfigurationSP)
static void initializeContext(QOpenGLContext *ctx)
Initialize shared OpenGL context.
void allocate(int numBuffers, int bufferSize)

References KisOpenGLBufferCircularStorage::allocate(), canvas(), KisOpenGLCanvasRenderer::Private::canvasInitialized, KisOpenGLCanvasRenderer::Private::checkersTextureVertexBuffer, KisOpenGLCanvasRenderer::Private::checkersVertexBuffer, KisConfig::checkSize(), context(), KisCanvasWidgetBase::createCheckersImage(), d, KisOpenGLImageTextures::generateCheckerTexture(), KisOpenGLImageTextures::initGL(), KisOpenGL::initializeContext(), initializeShaders(), KisOpenGLCanvasRenderer::Private::lineVertexBuffer, NumberOfBuffers, KisOpenGLCanvasRenderer::Private::openGLImageTextures, KisOpenGLCanvasRenderer::Private::outlineVAO, PROGRAM_TEXCOORD_ATTRIBUTE, PROGRAM_VERTEX_ATTRIBUTE, KisOpenGLCanvasRenderer::Private::quadVAO, KisOpenGLImageTextures::setProofingConfig(), and KisOpenGL::supportsVAO().

◆ initializeShaders()

◆ notifyImageColorSpaceChanged()

void KisOpenGLCanvasRenderer::notifyImageColorSpaceChanged ( const KoColorSpace * cs)

Definition at line 215 of file KisOpenGLCanvasRenderer.cpp.

216{
217 // FIXME: on color space change the data is refetched multiple
218 // times by different actors!
219
221 canvas()->startUpdateInPatches(canvas()->image()->bounds());
222 }
223}
void startUpdateInPatches(const QRect &imageRect)
bool setImageColorSpace(const KoColorSpace *cs)
#define bounds(x, a, b)

References bounds, canvas(), d, KisOpenGLCanvasRenderer::Private::openGLImageTextures, KisOpenGLImageTextures::setImageColorSpace(), and KisCanvas2::startUpdateInPatches().

◆ openGLImageTextures()

KisOpenGLImageTexturesSP KisOpenGLCanvasRenderer::openGLImageTextures ( ) const

Definition at line 1136 of file KisOpenGLCanvasRenderer.cpp.

1137{
1138 return d->openGLImageTextures;
1139}

References d, and KisOpenGLCanvasRenderer::Private::openGLImageTextures.

◆ paintCanvasOnly()

void KisOpenGLCanvasRenderer::paintCanvasOnly ( const QRect & canvasImageDirtyRect,
const QRect & viewportUpdateRect = QRect() )

Paint only the canvas background and image tiles.

Definition at line 370 of file KisOpenGLCanvasRenderer.cpp.

371{
372 if (d->canvasFBO) {
373 if (!canvasImageDirtyRect.isEmpty()) {
374 d->canvasFBO->bind();
375 renderCanvasGL(canvasImageDirtyRect);
376 d->canvasFBO->release();
377 }
378 QRect blitRect;
379 if (viewportUpdateRect.isEmpty()) {
380 blitRect = QRect(QPoint(), d->viewportDevicePixelSize);
381 } else {
382 const QTransform scale = QTransform::fromScale(1.0, -1.0) * QTransform::fromTranslate(0, d->pixelAlignedWidgetSize.height()) * QTransform::fromScale(devicePixelRatioF(), devicePixelRatioF());
383 blitRect = scale.mapRect(QRectF(viewportUpdateRect)).toAlignedRect();
384 }
385 QOpenGLFramebufferObject::blitFramebuffer(nullptr, blitRect, d->canvasFBO.data(), blitRect, GL_COLOR_BUFFER_BIT, GL_NEAREST);
386 QOpenGLFramebufferObject::bindDefault();
387 } else {
388 QRect fullUpdateRect = canvasImageDirtyRect | viewportUpdateRect;
389 if (fullUpdateRect.isEmpty()) {
390 fullUpdateRect = QRect(QPoint(), d->viewportDevicePixelSize);
391 }
392 renderCanvasGL(fullUpdateRect);
393 }
394}
void renderCanvasGL(const QRect &updateRect)
QScopedPointer< QOpenGLFramebufferObject > canvasFBO

References KisOpenGLCanvasRenderer::Private::canvasFBO, d, devicePixelRatioF(), KisOpenGLCanvasRenderer::Private::pixelAlignedWidgetSize, renderCanvasGL(), and KisOpenGLCanvasRenderer::Private::viewportDevicePixelSize.

◆ paintToolOutline()

void KisOpenGLCanvasRenderer::paintToolOutline ( const KisOptimizedBrushOutline & path,
const QRect & viewportUpdateRect,
const int thickness = 1 )

Definition at line 396 of file KisOpenGLCanvasRenderer.cpp.

397{
398 if (!d->solidColorShader->bind()) {
399 return;
400 }
401
402 const QSizeF &widgetSize = d->pixelAlignedWidgetSize;
403
404 // setup the mvp transformation
405 QMatrix4x4 projectionMatrix;
406 projectionMatrix.setToIdentity();
407 // FIXME: It may be better to have the projection in device pixel, but
408 // this requires introducing a new coordinate system.
409 projectionMatrix.ortho(0, widgetSize.width(), widgetSize.height(), 0, NEAR_VAL, FAR_VAL);
410
411 // Set view/projection matrices
412 QMatrix4x4 modelMatrix(coordinatesConverter()->flakeToWidgetTransform());
413 modelMatrix.optimize();
414 modelMatrix = projectionMatrix * modelMatrix;
416
417 d->solidColorShader->setUniformValue(
419 QVector4D(d->cursorColor.redF(), d->cursorColor.greenF(), d->cursorColor.blueF(), 1.0f));
420
421 glEnable(GL_BLEND);
422 glBlendFuncSeparate(GL_ONE, GL_SRC_COLOR, GL_ONE, GL_ONE);
423 glBlendEquationSeparate(GL_FUNC_SUBTRACT, GL_FUNC_ADD);
424
425
426 if (!viewportUpdateRect.isEmpty()) {
427 const QRect deviceUpdateRect = widgetToSurface(viewportUpdateRect).toAlignedRect();
428 glScissor(deviceUpdateRect.x(), deviceUpdateRect.y(), deviceUpdateRect.width(), deviceUpdateRect.height());
429 glEnable(GL_SCISSOR_TEST);
430 }
431
432 // Paint the tool outline
434 d->outlineVAO.bind();
435 d->lineVertexBuffer.bind();
436 }
437
438
439 if (thickness > 1) {
440 // Because glLineWidth is not supported on all versions of OpenGL (or rather,
441 // is limited to 1, as returned by GL_ALIASED_LINE_WIDTH_RANGE),
442 // we'll instead generate mitered-triangles.
443
444 const qreal halfWidth = (thickness * 0.5) / devicePixelRatioF();
445 const qreal miterLimit = (5 * thickness) / devicePixelRatioF();
446
447 for (auto it = path.begin(); it != path.end(); ++it) {
448 const QPolygonF& polygon = *it;
449
450 if (KisAlgebra2D::maxDimension(polygon.boundingRect()) < 0.5 * thickness) {
451 continue;
452 }
453
454 int triangleCount = 0;
456 d->lineVerticesStagingBuffer.reserve((polygon.count() - 1) * 6);
457 const bool closed = polygon.isClosed();
458
459 for( int i = 1; i < polygon.count(); i++) {
460 bool adjustFirst = closed? true: i > 1;
461 bool adjustSecond = closed? true: i + 1 < polygon.count();
462
463 QPointF p1 = polygon.at(i - 1);
464 QPointF p2 = polygon.at(i);
465 QPointF normal = p2 - p1;
466 normal = KisAlgebra2D::normalize(QPointF(-normal.y(), normal.x()));
467
468 QPointF c1 = p1 - (normal * halfWidth);
469 QPointF c2 = p1 + (normal * halfWidth);
470 QPointF c3 = p2 - (normal * halfWidth);
471 QPointF c4 = p2 + (normal * halfWidth);
472
473 // Add miter
474 if (adjustFirst) {
475 QPointF pPrev = i >= 2 ?
476 QPointF(polygon.at(i-2)) :
477 QPointF(polygon.at(qMax(polygon.count() - 2, 0)));
478
479 pPrev = p1 - pPrev;
480
481 QPointF miter =
484 QPointF(-pPrev.y(), pPrev.x())));
485
486 const qreal dot = KisAlgebra2D::dotProduct(miter, normal);
487
488 if (KisAlgebra2D::norm((miter * halfWidth) / dot) < miterLimit) {
489 c1 = p1 + ((miter * -halfWidth) / dot);
490 c2 = p1 + ((miter * halfWidth) / dot);
491 }
492 }
493
494 if (adjustSecond) {
495 QPointF pNext = i + 1 < polygon.count()? QPointF(polygon.at(i+1))
496 : QPointF(polygon.at(qMin(polygon.count(), 1)));
497 pNext = pNext - p2;
498 QPointF miter =
500 normal + KisAlgebra2D::normalize(QPointF(-pNext.y(), pNext.x())));
501 const qreal dot = KisAlgebra2D::dotProduct(miter, normal);
502
503 if (KisAlgebra2D::norm((miter * halfWidth) / dot) < miterLimit) {
504 c3 = p2 + ((miter * -halfWidth) / dot);
505 c4 = p2 + (miter * halfWidth) / dot;
506 }
507 }
508
509 d->lineVerticesStagingBuffer.append(QVector3D(c1));
510 d->lineVerticesStagingBuffer.append(QVector3D(c3));
511 d->lineVerticesStagingBuffer.append(QVector3D(c2));
512 d->lineVerticesStagingBuffer.append(QVector3D(c4));
513 d->lineVerticesStagingBuffer.append(QVector3D(c2));
514 d->lineVerticesStagingBuffer.append(QVector3D(c3));
515 triangleCount += 2;
516 }
517
519 d->lineVertexBuffer.bind();
520 d->lineVertexBuffer.allocate(d->lineVerticesStagingBuffer.constData(), 3 * d->lineVerticesStagingBuffer.size() * sizeof(float));
521 }
522 else {
523 d->solidColorShader->enableAttributeArray(PROGRAM_VERTEX_ATTRIBUTE);
524 d->solidColorShader->setAttributeArray(PROGRAM_VERTEX_ATTRIBUTE, d->lineVerticesStagingBuffer.constData());
525 }
526
527 glDrawArrays(GL_TRIANGLES, 0, triangleCount * 3);
528 }
529 } else {
530 // Convert every disjointed subpath to a polygon and draw that polygon
531 for (auto it = path.begin(); it != path.end(); ++it) {
532 const QPolygonF& polygon = *it;
533
534 if (KisAlgebra2D::maxDimension(polygon.boundingRect()) < 0.5) {
535 continue;
536 }
537
538 const int verticesCount = polygon.count();
539
540 if (d->lineVerticesStagingBuffer.size() < verticesCount) {
541 d->lineVerticesStagingBuffer.resize(verticesCount);
542 }
543
544 for (int vertIndex = 0; vertIndex < verticesCount; vertIndex++) {
545 QPointF point = polygon.at(vertIndex);
546 d->lineVerticesStagingBuffer[vertIndex].setX(point.x());
547 d->lineVerticesStagingBuffer[vertIndex].setY(point.y());
548 }
550 d->lineVertexBuffer.bind();
551 d->lineVertexBuffer.allocate(d->lineVerticesStagingBuffer.constData(), 3 * verticesCount * sizeof(float));
552 }
553 else {
554 d->solidColorShader->enableAttributeArray(PROGRAM_VERTEX_ATTRIBUTE);
555 d->solidColorShader->setAttributeArray(PROGRAM_VERTEX_ATTRIBUTE, d->lineVerticesStagingBuffer.constData());
556 }
557
558
559
560 glDrawArrays(GL_LINE_STRIP, 0, verticesCount);
561 }
562 }
563
565 d->lineVertexBuffer.release();
566 d->outlineVAO.release();
567 }
568
569 if (!viewportUpdateRect.isEmpty()) {
570 glDisable(GL_SCISSOR_TEST);
571 }
572
573 glBlendEquation(GL_FUNC_ADD);
574 glBlendFunc(GL_ONE, GL_ZERO);
575 glDisable(GL_BLEND);
576
577 d->solidColorShader->release();
578}
QPointF p2
QPointF p1
QRectF widgetToSurface(const QRectF &rc)
auto maxDimension(Size size) -> decltype(size.width())
Point normalize(const Point &a)
qreal norm(const T &a)
PointTypeTraits< T >::value_type dotProduct(const T &a, const T &b)

References coordinatesConverter(), KisOpenGLCanvasRenderer::Private::cursorColor, d, devicePixelRatioF(), KisAlgebra2D::dotProduct(), FAR_VAL, FragmentColor, KisOpenGLCanvasRenderer::Private::lineVertexBuffer, KisOpenGLCanvasRenderer::Private::lineVerticesStagingBuffer, KisShaderProgram::location(), KisAlgebra2D::maxDimension(), ModelViewProjection, NEAR_VAL, KisAlgebra2D::norm(), KisAlgebra2D::normalize(), KisOpenGLCanvasRenderer::Private::outlineVAO, p1, p2, KisOpenGLCanvasRenderer::Private::pixelAlignedWidgetSize, PROGRAM_VERTEX_ATTRIBUTE, KisOpenGLCanvasRenderer::Private::solidColorShader, KisOpenGL::supportsVAO(), and widgetToSurface().

◆ renderCanvasGL()

void KisOpenGLCanvasRenderer::renderCanvasGL ( const QRect & updateRect)
private

Definition at line 1051 of file KisOpenGLCanvasRenderer.cpp.

1052{
1053 if ((d->displayFilter && d->displayFilter->updateShader()) ||
1055
1057
1058 d->canvasInitialized = false; // TODO: check if actually needed?
1060 d->canvasInitialized = true;
1061 }
1062
1063 if (KisOpenGL::supportsVAO()) {
1064 d->quadVAO.bind();
1065 }
1066
1067 QRect alignedUpdateRect = updateRect;
1068
1069 if (!updateRect.isEmpty()) {
1070 const QRect deviceUpdateRect = widgetToSurface(updateRect).toAlignedRect();
1071 alignedUpdateRect = surfaceToWidget(deviceUpdateRect).toAlignedRect();
1072
1073 glScissor(deviceUpdateRect.x(), deviceUpdateRect.y(), deviceUpdateRect.width(), deviceUpdateRect.height());
1074 glEnable(GL_SCISSOR_TEST);
1075 }
1076
1077 drawBackground(alignedUpdateRect);
1078 drawCheckers(alignedUpdateRect);
1079 drawImage(alignedUpdateRect);
1080
1081 if ((coordinatesConverter()->effectivePhysicalZoom() > d->pixelGridDrawingThreshold - 0.00001) && d->pixelGridEnabled) {
1082 drawGrid(alignedUpdateRect);
1083 }
1084
1085 if (!updateRect.isEmpty()) {
1086 glDisable(GL_SCISSOR_TEST);
1087 }
1088
1089 if (KisOpenGL::supportsVAO()) {
1090 d->quadVAO.release();
1091 }
1092}
void drawImage(const QRect &updateRect)
void drawBackground(const QRect &updateRect)
QRectF surfaceToWidget(const QRectF &rc)
void drawGrid(const QRect &updateRect)
void drawCheckers(const QRect &updateRect)
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:130

References KisOpenGLCanvasRenderer::Private::canvasInitialized, coordinatesConverter(), d, KisOpenGLCanvasRenderer::Private::displayFilter, KisOpenGLCanvasRenderer::Private::displayShaderCompiledWithDisplayFilterSupport, drawBackground(), drawCheckers(), drawGrid(), drawImage(), initializeDisplayShader(), KIS_SAFE_ASSERT_RECOVER_NOOP, KisOpenGLCanvasRenderer::Private::pixelGridDrawingThreshold, KisOpenGLCanvasRenderer::Private::pixelGridEnabled, KisOpenGLCanvasRenderer::Private::quadVAO, KisOpenGL::supportsVAO(), surfaceToWidget(), and widgetToSurface().

◆ reportFailedShaderCompilation()

void KisOpenGLCanvasRenderer::reportFailedShaderCompilation ( const QString & context)
private

Displays a message box telling the user that shader compilation failed and turns off OpenGL.

Definition at line 328 of file KisOpenGLCanvasRenderer.cpp.

329{
330 KisConfig cfg(false);
331
332 qDebug() << "Shader Compilation Failure: " << context;
333 // TODO: Should do something else when using QtQuick2
334 QMessageBox::critical(qApp->activeWindow(), i18nc("@title:window", "Krita"),
335 i18n("Krita could not initialize the OpenGL canvas:\n\n%1\n\n Krita will disable OpenGL and close now.", context),
336 QMessageBox::Close);
337
338 cfg.disableOpenGL();
339 cfg.setCanvasState("OPENGL_FAILED");
340}

References context(), KisConfig::disableOpenGL(), and KisConfig::setCanvasState().

◆ resizeGL()

void KisOpenGLCanvasRenderer::resizeGL ( int width,
int height )

Definition at line 342 of file KisOpenGLCanvasRenderer.cpp.

343{
344 {
345 // just a sanity check!
346 //
347 // This is how QOpenGLCanvas sets the FBO and the viewport size. If
348 // devicePixelRatioF() is non-integral, the result is truncated.
349 // *Correction*: The FBO size is actually rounded, but the glViewport call
350 // uses integer truncation and that's what really matters.
351 int viewportWidth = static_cast<int>(width * devicePixelRatioF());
352 int viewportHeight = static_cast<int>(height * devicePixelRatioF());
353
354 // We expect the size to be adjusted in the converter at the higher
355 // level of hierarchy. It happens in KisCanvasControllerWidget, which
356 // then explicitly resizes the canvas widget.
357 KIS_SAFE_ASSERT_RECOVER_NOOP(QSize(viewportWidth, viewportHeight) == coordinatesConverter()->viewportDevicePixelSize());
358 }
359
362
364 QOpenGLFramebufferObjectFormat format;
365 format.setInternalTextureFormat(d->canvasBridge->internalTextureFormat());
366 d->canvasFBO.reset(new QOpenGLFramebufferObject(d->viewportDevicePixelSize, format));
367 }
368}
virtual GLenum internalTextureFormat() const =0
static bool useFBOForToolOutlineRendering()
supportsRenderToFBO

References KisOpenGLCanvasRenderer::Private::canvasBridge, KisOpenGLCanvasRenderer::Private::canvasFBO, coordinatesConverter(), d, devicePixelRatioF(), KisCoordinatesConverter::getCanvasWidgetSize(), KisOpenGLCanvasRenderer::CanvasBridge::internalTextureFormat(), KIS_SAFE_ASSERT_RECOVER_NOOP, KisOpenGLCanvasRenderer::Private::pixelAlignedWidgetSize, KisOpenGL::useFBOForToolOutlineRendering(), KisCoordinatesConverter::viewportDevicePixelSize(), and KisOpenGLCanvasRenderer::Private::viewportDevicePixelSize.

◆ setDisplayConfig()

void KisOpenGLCanvasRenderer::setDisplayConfig ( const KisDisplayConfig & config)

Definition at line 1094 of file KisOpenGLCanvasRenderer.cpp.

1095{
1097 config.intent,
1098 config.conversionFlags);
1099}
void setMonitorProfile(const KoColorProfile *monitorProfile, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags)

References KisDisplayConfig::conversionFlags, d, KisDisplayConfig::intent, KisOpenGLCanvasRenderer::Private::openGLImageTextures, KisDisplayConfig::profile, and KisOpenGLImageTextures::setMonitorProfile().

◆ setDisplayFilter()

void KisOpenGLCanvasRenderer::setDisplayFilter ( QSharedPointer< KisDisplayFilter > displayFilter)

Definition at line 193 of file KisOpenGLCanvasRenderer.cpp.

194{
195 setDisplayFilterImpl(displayFilter, false);
196}

References setDisplayFilterImpl().

◆ setDisplayFilterImpl()

void KisOpenGLCanvasRenderer::setDisplayFilterImpl ( QSharedPointer< KisDisplayFilter > displayFilter,
bool initializing )
private

Definition at line 198 of file KisOpenGLCanvasRenderer.cpp.

199{
200 bool needsInternalColorManagement =
201 !displayFilter || displayFilter->useInternalColorManagement();
202
203 bool needsFullRefresh = d->openGLImageTextures->setInternalColorManagementActive(needsInternalColorManagement, initializing);
204
205 d->displayFilter = displayFilter;
206
207 if (!initializing && needsFullRefresh) {
208 canvas()->startUpdateInPatches(canvas()->image()->bounds());
209 }
210 else if (!initializing) {
211 canvas()->updateCanvas();
212 }
213}
void updateCanvas(const QRectF &rc) override
bool setInternalColorManagementActive(bool value, bool iniializing=false)

References bounds, canvas(), d, KisOpenGLCanvasRenderer::Private::displayFilter, KisOpenGLCanvasRenderer::Private::openGLImageTextures, KisOpenGLImageTextures::setInternalColorManagementActive(), KisCanvas2::startUpdateInPatches(), and KisCanvas2::updateCanvas().

◆ setLodResetInProgress()

void KisOpenGLCanvasRenderer::setLodResetInProgress ( bool value)

Definition at line 580 of file KisOpenGLCanvasRenderer.cpp.

581{
583}
float value(const T *src, size_t ch)

References d, KisOpenGLCanvasRenderer::Private::lodSwitchInProgress, and value().

◆ setWrapAroundViewingMode()

void KisOpenGLCanvasRenderer::setWrapAroundViewingMode ( bool value)

Definition at line 225 of file KisOpenGLCanvasRenderer.cpp.

226{
228}

References d, value(), and KisOpenGLCanvasRenderer::Private::wrapAroundMode.

◆ setWrapAroundViewingModeAxis()

void KisOpenGLCanvasRenderer::setWrapAroundViewingModeAxis ( WrapAroundAxis value)

◆ startUpdateCanvasProjection()

KisUpdateInfoSP KisOpenGLCanvasRenderer::startUpdateCanvasProjection ( const QRect & rc)

Definition at line 1114 of file KisOpenGLCanvasRenderer.cpp.

1115{
1116 if (canvas()->proofingConfigUpdated()) {
1117 d->openGLImageTextures->setProofingConfig(canvas()->proofingConfiguration());
1119 }
1121}
void setProofingConfigUpdated(bool updated)
setProofingConfigUpdated This function is to set whether the proofing config is updated,...
KisOpenGLUpdateInfoSP updateCache(const QRect &rect, KisImageSP srcImage)

References canvas(), d, KisOpenGLImageTextures::image(), KisOpenGLCanvasRenderer::Private::openGLImageTextures, KisOpenGLImageTextures::setProofingConfig(), KisCanvas2::setProofingConfigUpdated(), and KisOpenGLImageTextures::updateCache().

◆ surfaceToWidget()

QRectF KisOpenGLCanvasRenderer::surfaceToWidget ( const QRectF & rc)
private

Definition at line 1040 of file KisOpenGLCanvasRenderer.cpp.

1041{
1042 const qreal ratio = devicePixelRatioF();
1043
1044 return QRectF(rc.x() / ratio,
1045 d->pixelAlignedWidgetSize.height() - (rc.y() + rc.height()) / ratio,
1046 rc.width() / ratio,
1047 rc.height() / ratio);
1048}

References d, devicePixelRatioF(), and KisOpenGLCanvasRenderer::Private::pixelAlignedWidgetSize.

◆ updateCanvasProjection()

QRect KisOpenGLCanvasRenderer::updateCanvasProjection ( KisUpdateInfoSP info)

Definition at line 1124 of file KisOpenGLCanvasRenderer.cpp.

1125{
1126 // See KisQPainterCanvas::updateCanvasProjection for more info
1127 bool isOpenGLUpdateInfo = dynamic_cast<KisOpenGLUpdateInfo*>(info.data());
1128 if (isOpenGLUpdateInfo) {
1130 }
1131
1132 const QRect dirty = kisGrowRect(coordinatesConverter()->imageToWidget(info->dirtyImageRect()).toAlignedRect(), 2);
1133 return dirty;
1134}
void recalculateCache(KisUpdateInfoSP info, bool blockMipmapRegeneration)
T kisGrowRect(const T &rect, U offset)
Definition kis_global.h:186

References coordinatesConverter(), d, KisSharedPtr< T >::data(), kisGrowRect(), KisOpenGLCanvasRenderer::Private::lodSwitchInProgress, KisOpenGLCanvasRenderer::Private::openGLImageTextures, and KisOpenGLImageTextures::recalculateCache().

◆ updateConfig()

void KisOpenGLCanvasRenderer::updateConfig ( )

Definition at line 999 of file KisOpenGLCanvasRenderer.cpp.

1000{
1001 KisConfig cfg(true);
1002 d->checkSizeScale = KisOpenGLImageTextures::BACKGROUND_TEXTURE_CHECK_SIZE / static_cast<GLfloat>(cfg.checkSize());
1003 d->scrollCheckers = cfg.scrollCheckers();
1004
1006 d->openGLImageTextures->updateConfig(cfg.useOpenGLTextureBuffer(), cfg.numMipmapLevels());
1007 d->filterMode = (KisOpenGL::FilterMode) cfg.openGLFilteringMode();
1008
1010}
static const int BACKGROUND_TEXTURE_CHECK_SIZE
void updateConfig(bool useBuffer, int NumMipmapLevels)

References KisOpenGLImageTextures::BACKGROUND_TEXTURE_CHECK_SIZE, KisConfig::checkSize(), KisOpenGLCanvasRenderer::Private::checkSizeScale, KisCanvasWidgetBase::createCheckersImage(), d, KisOpenGLCanvasRenderer::Private::filterMode, KisOpenGLImageTextures::generateCheckerTexture(), KisConfig::numMipmapLevels(), KisConfig::openGLFilteringMode(), KisOpenGLCanvasRenderer::Private::openGLImageTextures, KisConfig::scrollCheckers(), KisOpenGLCanvasRenderer::Private::scrollCheckers, KisOpenGLImageTextures::updateConfig(), updateCursorColor(), and KisConfig::useOpenGLTextureBuffer().

◆ updateCursorColor()

void KisOpenGLCanvasRenderer::updateCursorColor ( )

Definition at line 1012 of file KisOpenGLCanvasRenderer.cpp.

1013{
1014 KisConfig cfg(true);
1015 bool useSeparateEraserCursor = cfg.separateEraserCursor() &&
1017
1018 d->cursorColor = (!useSeparateEraserCursor) ? cfg.getCursorMainColor() : cfg.getEraserCursorMainColor();
1019}
const QString COMPOSITE_ERASE
QPointer< KoCanvasResourceProvider > resourceManager

References canvas(), COMPOSITE_ERASE, KoCanvasResource::CurrentEffectiveCompositeOp, KisOpenGLCanvasRenderer::Private::cursorColor, d, KisConfig::getCursorMainColor(), KisConfig::getEraserCursorMainColor(), KoCanvasBase::resourceManager, and KisConfig::separateEraserCursor().

◆ updatePixelGridMode()

void KisOpenGLCanvasRenderer::updatePixelGridMode ( )

◆ widgetToSurface()

QRectF KisOpenGLCanvasRenderer::widgetToSurface ( const QRectF & rc)
private

Definition at line 1030 of file KisOpenGLCanvasRenderer.cpp.

1031{
1032 const qreal ratio = devicePixelRatioF();
1033
1034 return QRectF(rc.x() * ratio,
1035 (d->pixelAlignedWidgetSize.height() - rc.y() - rc.height()) * ratio,
1036 rc.width() * ratio,
1037 rc.height() * ratio);
1038}

References d, devicePixelRatioF(), and KisOpenGLCanvasRenderer::Private::pixelAlignedWidgetSize.

◆ wrapAroundViewingMode()

bool KisOpenGLCanvasRenderer::wrapAroundViewingMode ( ) const

Definition at line 230 of file KisOpenGLCanvasRenderer.cpp.

231{
232 return d->wrapAroundMode;
233}

References d, and KisOpenGLCanvasRenderer::Private::wrapAroundMode.

◆ wrapAroundViewingModeAxis()

WrapAroundAxis KisOpenGLCanvasRenderer::wrapAroundViewingModeAxis ( ) const

Definition at line 240 of file KisOpenGLCanvasRenderer.cpp.

241{
242 return d->wrapAroundModeAxis;
243}

References d, and KisOpenGLCanvasRenderer::Private::wrapAroundModeAxis.

Member Data Documentation

◆ d

Private* const KisOpenGLCanvasRenderer::d
private

Definition at line 116 of file KisOpenGLCanvasRenderer.h.


The documentation for this class was generated from the following files: