diff --git a/krita/ui/opengl/kis_opengl_canvas2.cpp b/krita/ui/opengl/kis_opengl_canvas2.cpp index 8ac6ecd7931..3f6c8d48b81 100644 --- a/krita/ui/opengl/kis_opengl_canvas2.cpp +++ b/krita/ui/opengl/kis_opengl_canvas2.cpp @@ -1,704 +1,692 @@ /* This file is part of the KDE project * Copyright (C) Boudewijn Rempt , (C) 2006-2013 * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #define GL_GLEXT_PROTOTYPES #include "opengl/kis_opengl_canvas2.h" #ifdef HAVE_OPENGL #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "KoToolProxy.h" #include "kis_config.h" #include "kis_types.h" #include #include "canvas/kis_canvas2.h" #include "kis_coordinates_converter.h" #include "kis_image.h" #include "opengl/kis_opengl_image_textures.h" #include "kis_canvas_resource_provider.h" #include "kis_config.h" #include "kis_config_notifier.h" #include "kis_debug.h" #include "opengl/kis_opengl_canvas2_p.h" #include "kis_coordinates_converter.h" #include "canvas/kis_display_filter.h" #define NEAR_VAL -1000.0 #define FAR_VAL 1000.0 #ifndef GL_CLAMP_TO_EDGE #define GL_CLAMP_TO_EDGE 0x812F #endif #define PROGRAM_VERTEX_ATTRIBUTE 0 #define PROGRAM_TEXCOORD_ATTRIBUTE 1 static bool OPENGL_SUCCESS = false; namespace { const GLuint NO_PROGRAM = 0; } struct KisOpenGLCanvas2::Private { public: Private() : canvasInitialized(false) , displayShader(0) , checkerShader(0) , glSyncObject(0) , wrapAroundMode(false) { vertices = new QVector3D[6]; texCoords = new QVector2D[6]; } ~Private() { delete displayShader; delete checkerShader; delete[] vertices; delete[] texCoords; Sync::deleteSync(glSyncObject); } bool canvasInitialized; QVector3D *vertices; QVector2D *texCoords; KisOpenGLImageTexturesSP openGLImageTextures; QOpenGLShaderProgram *displayShader; int displayUniformLocationModelViewProjection; int displayUniformLocationTextureMatrix; int displayUniformLocationViewPortScale; int displayUniformLocationTexelSize; int displayUniformLocationTexture0; int displayUniformLocationTexture1; QOpenGLShaderProgram *checkerShader; int checkerUniformLocationModelViewProjection; int checkerUniformLocationTextureMatrix; KisDisplayFilter* displayFilter; KisTextureTile::FilterMode filterMode; GLsync glSyncObject; bool firstDrawImage; qreal scaleX, scaleY; bool wrapAroundMode; int xToColWithWrapCompensation(int x, const QRect &imageRect) { int firstImageColumn = openGLImageTextures->xToCol(imageRect.left()); int lastImageColumn = openGLImageTextures->xToCol(imageRect.right()); int colsPerImage = lastImageColumn - firstImageColumn + 1; int numWraps = floor(qreal(x) / imageRect.width()); int remainder = x - imageRect.width() * numWraps; return colsPerImage * numWraps + openGLImageTextures->xToCol(remainder); } int yToRowWithWrapCompensation(int y, const QRect &imageRect) { int firstImageRow = openGLImageTextures->yToRow(imageRect.top()); int lastImageRow = openGLImageTextures->yToRow(imageRect.bottom()); int rowsPerImage = lastImageRow - firstImageRow + 1; int numWraps = floor(qreal(y) / imageRect.height()); int remainder = y - imageRect.height() * numWraps; return rowsPerImage * numWraps + openGLImageTextures->yToRow(remainder); } }; KisOpenGLCanvas2::KisOpenGLCanvas2(KisCanvas2 *canvas, KisCoordinatesConverter *coordinatesConverter, QWidget *parent, KisOpenGLImageTexturesSP imageTextures) : QOpenGLWidget(parent) , KisCanvasWidgetBase(canvas, coordinatesConverter) , d(new Private()) { QSurfaceFormat format; format.setDepthBufferSize(24); setFormat(format); KisConfig cfg; cfg.writeEntry("canvasState", "OPENGL_STARTED"); d->openGLImageTextures = imageTextures; setAcceptDrops(true); setFocusPolicy(Qt::StrongFocus); setAttribute(Qt::WA_NoSystemBackground); setAttribute(Qt::WA_AcceptTouchEvents); setAutoFillBackground(false); setAttribute(Qt::WA_InputMethodEnabled, true); setAttribute(Qt::WA_DontCreateNativeAncestors, true); connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), SLOT(slotConfigChanged())); slotConfigChanged(); cfg.writeEntry("canvasState", "OPENGL_SUCCESS"); } KisOpenGLCanvas2::~KisOpenGLCanvas2() { delete d; } void KisOpenGLCanvas2::setDisplayFilter(KisDisplayFilter* displayFilter) { d->displayFilter = displayFilter; if (d->canvasInitialized) { d->canvasInitialized = false; initializeDisplayShader(); initializeCheckerShader(); d->canvasInitialized = true; } } void KisOpenGLCanvas2::setWrapAroundViewingMode(bool value) { d->wrapAroundMode = value; update(); } void KisOpenGLCanvas2::initializeGL() { // KisConfig cfg; // if (cfg.disableVSync()) { // if (!VSyncWorkaround::tryDisableVSync(this)) { // qWarning(); // qWarning() << "WARNING: We didn't manage to switch off VSync on your graphics adapter."; // qWarning() << "WARNING: It means either your hardware or driver doesn't support it,"; // qWarning() << "WARNING: or we just don't know about this hardware. Please report us a bug"; // qWarning() << "WARNING: with the output of \'glxinfo\' for your card."; // qWarning(); // qWarning() << "WARNING: Trying to workaround it by disabling Double Buffering."; // qWarning() << "WARNING: You may see some flickering when painting with some tools. It doesn't"; // qWarning() << "WARNING: affect the quality of the final image, though."; // qWarning(); // if (cfg.disableDoubleBuffering() && QOpenGLContext::currentContext()->format().swapBehavior() == QSurfaceFormat::DoubleBuffer) { // qCritical() << "CRITICAL: Failed to disable Double Buffering. Lines may look \"bended\" on your image."; // qCritical() << "CRITICAL: Your graphics card or driver does not fully support Krita's OpenGL canvas."; // qCritical() << "CRITICAL: For an optimal experience, please disable OpenGL"; // qCritical(); // } // } // } KisConfig cfg; qDebug() << "OpenGL: Preparing to initialize OpenGL for KisCanvas"; int glVersion = KisOpenGL::initializeContext(context()); qDebug() << "OpenGL: Context gives version" << glVersion; initializeOpenGLFunctions(); VSyncWorkaround::tryDisableVSync(context()); d->openGLImageTextures->initGL((QOpenGLFunctions *)this); d->openGLImageTextures->generateCheckerTexture(createCheckersImage(cfg.checkSize())); initializeCheckerShader(); initializeDisplayShader(); Sync::init(); d->canvasInitialized = true; } void KisOpenGLCanvas2::resizeGL(int width, int height) { coordinatesConverter()->setCanvasWidgetSize(QSize(width, height)); paintGL(); } void KisOpenGLCanvas2::paintGL() { if (!OPENGL_SUCCESS) { KisConfig cfg; cfg.writeEntry("canvasState", "OPENGL_PAINT_STARTED"); } QPainter gc(this); gc.beginNativePainting(); renderCanvasGL(); if (d->glSyncObject) { Sync::deleteSync(d->glSyncObject); } d->glSyncObject = Sync::getSync(); gc.endNativePainting(); renderDecorations(&gc); gc.end(); if (!OPENGL_SUCCESS) { KisConfig cfg; cfg.writeEntry("canvasState", "OPENGL_SUCCESS"); OPENGL_SUCCESS = true; } } bool KisOpenGLCanvas2::isBusy() const { return Sync::syncStatus(d->glSyncObject) == Sync::Unsignaled; } inline void rectToVertices(QVector3D* vertices, const QRectF &rc) { vertices[0] = QVector3D(rc.left(), rc.bottom(), 0.f); vertices[1] = QVector3D(rc.left(), rc.top(), 0.f); vertices[2] = QVector3D(rc.right(), rc.bottom(), 0.f); vertices[3] = QVector3D(rc.left(), rc.top(), 0.f); vertices[4] = QVector3D(rc.right(), rc.top(), 0.f); vertices[5] = QVector3D(rc.right(), rc.bottom(), 0.f); } inline void rectToTexCoords(QVector2D* texCoords, const QRectF &rc) { texCoords[0] = QVector2D(rc.left(), rc.bottom()); texCoords[1] = QVector2D(rc.left(), rc.top()); texCoords[2] = QVector2D(rc.right(), rc.bottom()); texCoords[3] = QVector2D(rc.left(), rc.top()); texCoords[4] = QVector2D(rc.right(), rc.top()); texCoords[5] = QVector2D(rc.right(), rc.bottom()); } void KisOpenGLCanvas2::drawCheckers() { if (!d->checkerShader) { return; } KisCoordinatesConverter *converter = coordinatesConverter(); QTransform textureTransform; QTransform modelTransform; QRectF textureRect; QRectF modelRect; QRectF viewportRect = !d->wrapAroundMode ? converter->imageRectInViewportPixels() : converter->widgetToViewport(this->rect()); converter->getOpenGLCheckersInfo(viewportRect, &textureTransform, &modelTransform, &textureRect, &modelRect); // XXX: getting a config object every time we draw the checkers is bad for performance! KisConfig cfg; GLfloat checkSizeScale = KisOpenGLImageTextures::BACKGROUND_TEXTURE_CHECK_SIZE / static_cast(cfg.checkSize()); textureTransform *= QTransform::fromScale(checkSizeScale / KisOpenGLImageTextures::BACKGROUND_TEXTURE_SIZE, checkSizeScale / KisOpenGLImageTextures::BACKGROUND_TEXTURE_SIZE); d->checkerShader->bind(); QMatrix4x4 projectionMatrix; projectionMatrix.setToIdentity(); projectionMatrix.ortho(0, width(), height(), 0, NEAR_VAL, FAR_VAL); // Set view/projection matrices QMatrix4x4 modelMatrix(modelTransform); modelMatrix.optimize(); modelMatrix = projectionMatrix * modelMatrix; d->checkerShader->setUniformValue(d->checkerUniformLocationModelViewProjection, modelMatrix); QMatrix4x4 textureMatrix(textureTransform); d->checkerShader->setUniformValue(d->checkerUniformLocationTextureMatrix, textureMatrix); //Setup the geometry for rendering rectToVertices(d->vertices, modelRect); d->checkerShader->enableAttributeArray(PROGRAM_VERTEX_ATTRIBUTE); d->checkerShader->setAttributeArray(PROGRAM_VERTEX_ATTRIBUTE, d->vertices); rectToTexCoords(d->texCoords, textureRect); d->checkerShader->enableAttributeArray(PROGRAM_TEXCOORD_ATTRIBUTE); d->checkerShader->setAttributeArray(PROGRAM_TEXCOORD_ATTRIBUTE, d->texCoords); // render checkers glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, d->openGLImageTextures->checkerTexture()); glDrawArrays(GL_TRIANGLES, 0, 6); glBindTexture(GL_TEXTURE_2D, 0); d->checkerShader->release(); } void KisOpenGLCanvas2::drawImage() { if (!d->displayShader) { return; } glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); KisCoordinatesConverter *converter = coordinatesConverter(); d->displayShader->bind(); QMatrix4x4 projectionMatrix; projectionMatrix.setToIdentity(); projectionMatrix.ortho(0, width(), height(), 0, NEAR_VAL, FAR_VAL); // Set view/projection matrices QMatrix4x4 modelMatrix(coordinatesConverter()->imageToWidgetTransform()); modelMatrix.optimize(); modelMatrix = projectionMatrix * modelMatrix; d->displayShader->setUniformValue(d->displayUniformLocationModelViewProjection, modelMatrix); QMatrix4x4 textureMatrix; textureMatrix.setToIdentity(); d->displayShader->setUniformValue(d->displayUniformLocationTextureMatrix, textureMatrix); QRectF widgetRect(0,0, width(), height()); QRectF widgetRectInImagePixels = converter->documentToImage(converter->widgetToDocument(widgetRect)); qreal scaleX, scaleY; converter->imageScale(&scaleX, &scaleY); d->displayShader->setUniformValue(d->displayUniformLocationViewPortScale, (GLfloat) scaleX); d->displayShader->setUniformValue(d->displayUniformLocationTexelSize, (GLfloat) d->openGLImageTextures->texelSize()); QRect ir = d->openGLImageTextures->storedImageBounds(); QRect wr = widgetRectInImagePixels.toAlignedRect(); if (!d->wrapAroundMode) { // if we don't want to paint wrapping images, just limit the // processing area, and the code will handle all the rest wr &= ir; } int firstColumn = d->xToColWithWrapCompensation(wr.left(), ir); int lastColumn = d->xToColWithWrapCompensation(wr.right(), ir); int firstRow = d->yToRowWithWrapCompensation(wr.top(), ir); int lastRow = d->yToRowWithWrapCompensation(wr.bottom(), ir); int minColumn = d->openGLImageTextures->xToCol(ir.left()); int maxColumn = d->openGLImageTextures->xToCol(ir.right()); int minRow = d->openGLImageTextures->yToRow(ir.top()); int maxRow = d->openGLImageTextures->yToRow(ir.bottom()); int imageColumns = maxColumn - minColumn + 1; int imageRows = maxRow - minRow + 1; for (int col = firstColumn; col <= lastColumn; col++) { for (int row = firstRow; row <= lastRow; row++) { int effectiveCol = col; int effectiveRow = row; QPointF tileWrappingTranslation; if (effectiveCol > maxColumn || effectiveCol < minColumn) { int translationStep = floor(qreal(col) / imageColumns); int originCol = translationStep * imageColumns; effectiveCol = col - originCol; tileWrappingTranslation.rx() = translationStep * ir.width(); } if (effectiveRow > maxRow || effectiveRow < minRow) { int translationStep = floor(qreal(row) / imageRows); int originRow = translationStep * imageRows; effectiveRow = row - originRow; tileWrappingTranslation.ry() = translationStep * ir.height(); } KisTextureTile *tile = d->openGLImageTextures->getTextureTileCR(effectiveCol, effectiveRow); if (!tile) { qWarning() << "OpenGL: Trying to paint texture tile but it has not been created yet."; continue; } /* * We create a float rect here to workaround Qt's * "history reasons" in calculation of right() * and bottom() coordinates of integer rects. */ QRectF textureRect(tile->tileRectInTexturePixels()); QRectF modelRect(tile->tileRectInImagePixels().translated(tileWrappingTranslation.x(), tileWrappingTranslation.y())); //Setup the geometry for rendering rectToVertices(d->vertices, modelRect); d->displayShader->enableAttributeArray(PROGRAM_VERTEX_ATTRIBUTE); d->displayShader->setAttributeArray(PROGRAM_VERTEX_ATTRIBUTE, d->vertices); rectToTexCoords(d->texCoords, textureRect); d->displayShader->enableAttributeArray(PROGRAM_TEXCOORD_ATTRIBUTE); d->displayShader->setAttributeArray(PROGRAM_TEXCOORD_ATTRIBUTE, d->texCoords); if (d->displayFilter) { glActiveTexture(GL_TEXTURE0 + 1); glBindTexture(GL_TEXTURE_3D, d->displayFilter->lutTexture()); d->displayShader->setUniformValue(d->displayUniformLocationTexture1, 1); } glActiveTexture(GL_TEXTURE0); tile->bindToActiveTexture(); if (SCALE_MORE_OR_EQUAL_TO(scaleX, scaleY, 2.0)) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); switch(d->filterMode) { case KisTextureTile::NearestFilterMode: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); break; case KisTextureTile::BilinearFilterMode: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); break; case KisTextureTile::TrilinearFilterMode: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); break; case KisTextureTile::HighQualityFiltering: if (SCALE_LESS_THAN(scaleX, scaleY, 0.5)) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } break; } } glDrawArrays(GL_TRIANGLES, 0, 6); } } glBindTexture(GL_TEXTURE_2D, 0); d->displayShader->release(); } void KisOpenGLCanvas2::reportShaderLinkFailedAndExit(bool result, const QString &context, const QString &log) { KisConfig cfg; if (cfg.useVerboseOpenGLDebugOutput()) { qDebug() << "GL-log:" << context << log; } if (result) return; QMessageBox::critical(this, i18nc("@title:window", "Krita"), QString(i18n("Krita could not initialize the OpenGL canvas:\n\n%1\n\n%2\n\n Krita will disable OpenGL and close now.")).arg(context).arg(log), QMessageBox::Close); cfg.setUseOpenGL(false); cfg.setCanvasState("OPENGL_FAILED"); } void KisOpenGLCanvas2::initializeCheckerShader() { if (d->canvasInitialized) return; delete d->checkerShader; d->checkerShader = new QOpenGLShaderProgram(); QString vertexShaderName; QString fragmentShaderName; if (KisOpenGL::supportsGLSL13()) { vertexShaderName = KGlobal::dirs()->findResource("data", "krita/shaders/matrix_transform.vert"); fragmentShaderName = KGlobal::dirs()->findResource("data", "krita/shaders/simple_texture.frag"); } else { vertexShaderName = KGlobal::dirs()->findResource("data", "krita/shaders/matrix_transform_legacy.vert"); fragmentShaderName = KGlobal::dirs()->findResource("data", "krita/shaders/simple_texture_legacy.frag"); } bool result; result = d->checkerShader->addShaderFromSourceFile(QOpenGLShader::Vertex, vertexShaderName); reportShaderLinkFailedAndExit(result, "Checker vertex shader", d->checkerShader->log()); result = d->checkerShader->addShaderFromSourceFile(QOpenGLShader::Fragment, fragmentShaderName); reportShaderLinkFailedAndExit(result, "Checker fragment shader", d->checkerShader->log()); d->checkerShader->bindAttributeLocation("a_vertexPosition", PROGRAM_VERTEX_ATTRIBUTE); d->checkerShader->bindAttributeLocation("a_textureCoordinate", PROGRAM_TEXCOORD_ATTRIBUTE); result = d->checkerShader->link(); reportShaderLinkFailedAndExit(result, "Checker shader (link)", d->checkerShader->log()); Q_ASSERT(d->checkerShader->isLinked()); d->checkerUniformLocationModelViewProjection = d->checkerShader->uniformLocation("modelViewProjection"); d->checkerUniformLocationTextureMatrix = d->checkerShader->uniformLocation("textureMatrix"); } QByteArray KisOpenGLCanvas2::buildFragmentShader() { QByteArray shaderText; bool haveDisplayFilter = d->displayFilter && !d->displayFilter->program().isEmpty(); bool useHiQualityFiltering = d->filterMode == KisTextureTile::HighQualityFiltering; bool haveGLSL13 = KisOpenGL::supportsGLSL13(); QString filename = haveGLSL13 && useHiQualityFiltering ? "highq_downscale" : "simple_texture"; QString legacyPostfix = !haveGLSL13 ? "_legacy" : ""; QString filterPostfix = haveDisplayFilter ? "_ocio" : ""; QString prefaceKey = QString("krita/shaders/%1%2_preface.frag.inc") .arg(filename) .arg(legacyPostfix); QString mainKey = QString("krita/shaders/%1%2_main%3.frag.inc") .arg(filename) .arg(legacyPostfix) .arg(filterPostfix); { QFile prefaceFile(KGlobal::dirs()->findResource("data", prefaceKey)); prefaceFile.open(QIODevice::ReadOnly); shaderText.append(prefaceFile.readAll()); } if (haveDisplayFilter) { shaderText.append(d->displayFilter->program().toLatin1()); } { QFile mainFile(KGlobal::dirs()->findResource("data", mainKey)); mainFile.open(QIODevice::ReadOnly); shaderText.append(mainFile.readAll()); } return shaderText; } void KisOpenGLCanvas2::initializeDisplayShader() { if (d->canvasInitialized) return; delete d->displayShader; d->displayShader = new QOpenGLShaderProgram(); bool result = d->displayShader->addShaderFromSourceCode(QOpenGLShader::Fragment, buildFragmentShader()); reportShaderLinkFailedAndExit(result, "Display fragment shader", d->displayShader->log()); if (KisOpenGL::supportsGLSL13()) { result = d->displayShader->addShaderFromSourceFile(QOpenGLShader::Vertex, KGlobal::dirs()->findResource("data", "krita/shaders/matrix_transform.vert")); } else { result = d->displayShader->addShaderFromSourceFile(QOpenGLShader::Vertex, KGlobal::dirs()->findResource("data", "krita/shaders/matrix_transform_legacy.vert")); } reportShaderLinkFailedAndExit(result, "Display vertex shader", d->displayShader->log()); d->displayShader->bindAttributeLocation("a_vertexPosition", PROGRAM_VERTEX_ATTRIBUTE); d->displayShader->bindAttributeLocation("a_textureCoordinate", PROGRAM_TEXCOORD_ATTRIBUTE); result = d->displayShader->link(); reportShaderLinkFailedAndExit(result, "Display shader (link)", d->displayShader->log()); Q_ASSERT(d->displayShader->isLinked()); d->displayUniformLocationModelViewProjection = d->displayShader->uniformLocation("modelViewProjection"); d->displayUniformLocationTextureMatrix = d->displayShader->uniformLocation("textureMatrix"); d->displayUniformLocationViewPortScale = d->displayShader->uniformLocation("viewportScale"); d->displayUniformLocationTexelSize = d->displayShader->uniformLocation("texelSize"); d->displayUniformLocationTexture0 = d->displayShader->uniformLocation("texture0"); d->displayUniformLocationTexture1 = d->displayShader->uniformLocation("texture1"); } void KisOpenGLCanvas2::slotConfigChanged() { KisConfig cfg; d->openGLImageTextures->generateCheckerTexture(createCheckersImage(cfg.checkSize())); d->openGLImageTextures->updateConfig(cfg.useOpenGLTextureBuffer(), cfg.numMipmapLevels()); d->filterMode = (KisTextureTile::FilterMode) cfg.openGLFilteringMode(); notifyConfigChanged(); } QVariant KisOpenGLCanvas2::inputMethodQuery(Qt::InputMethodQuery query) const { return processInputMethodQuery(query); } void KisOpenGLCanvas2::inputMethodEvent(QInputMethodEvent *event) { processInputMethodEvent(event); } void KisOpenGLCanvas2::renderCanvasGL() { // Draw the border (that is, clear the whole widget to the border color) QColor widgetBackgroundColor = borderColor(); glClearColor(widgetBackgroundColor.redF(), widgetBackgroundColor.greenF(), widgetBackgroundColor.blueF(), 1.0); glClear(GL_COLOR_BUFFER_BIT); drawCheckers(); drawImage(); } void KisOpenGLCanvas2::renderDecorations(QPainter *painter) { QRect boundingRect = coordinatesConverter()->imageRectInWidgetPixels().toAlignedRect(); drawDecorations(*painter, boundingRect); } bool KisOpenGLCanvas2::callFocusNextPrevChild(bool next) { return focusNextPrevChild(next); } -//void KisOpenGLCanvas2::paintEvent(QPaintEvent* event) -//{ -// // Workaround for bug 322808, paint events with only a partial rect cause flickering -// // Drop those event and trigger a new full update -// if (event->rect().width() == width() && event->rect().height() == height()) { -// QOpenGLWidget::paintEvent(event); -// } else { -// update(); -// } -//} - - #endif // HAVE_OPENGL diff --git a/krita/ui/opengl/kis_opengl_canvas2.h b/krita/ui/opengl/kis_opengl_canvas2.h index f492189c355..e913528a450 100644 --- a/krita/ui/opengl/kis_opengl_canvas2.h +++ b/krita/ui/opengl/kis_opengl_canvas2.h @@ -1,114 +1,113 @@ /* * Copyright (C) Boudewijn Rempt , (C) 2006 * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_OPENGL_CANVAS_2_H #define KIS_OPENGL_CANVAS_2_H #include #ifdef HAVE_OPENGL #include #include #include #include "canvas/kis_canvas_widget_base.h" #include "opengl/kis_opengl_image_textures.h" #include "krita_export.h" class QWidget; class QPaintEvent; class KisCanvas2; /** * KisOpenGLCanvas is the widget that shows the actual image using OpenGL * * NOTE: if you change something in the event handling here, also change it * in the qpainter canvas. * */ class KRITAUI_EXPORT KisOpenGLCanvas2 : public QOpenGLWidget, public QOpenGLFunctions, public KisCanvasWidgetBase { Q_OBJECT public: KisOpenGLCanvas2(KisCanvas2 * canvas, KisCoordinatesConverter *coordinatesConverter, QWidget * parent, KisOpenGLImageTexturesSP imageTextures); virtual ~KisOpenGLCanvas2(); void setDisplayFilter(KisDisplayFilter* displayFilter); void setWrapAroundViewingMode(bool value); public: // QWidget virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const; virtual void inputMethodEvent(QInputMethodEvent *event); - //virtual void paintEvent(QPaintEvent* event); public: bool isBusy() const; void initializeCheckerShader(); void initializeDisplayShader(); void renderCanvasGL(); void renderDecorations(QPainter *painter); private Q_SLOTS: void slotConfigChanged(); public: void resizeGL(int width, int height); void initializeGL(); void paintGL(); public: QWidget *widget() { return this; } protected: // KisCanvasWidgetBase virtual bool callFocusNextPrevChild(bool next); private: void reportShaderLinkFailedAndExit(bool result, const QString &context, const QString &log); private: struct Private; Private * const d; void drawImage(); void drawCheckers(); QByteArray buildFragmentShader(); }; #endif // HAVE_OPENGL #endif // KIS_OPENGL_CANVAS_2_H