[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    koffice/krita/ui
From:       Dmitry Kazakov <dimula73 () gmail ! com>
Date:       2010-11-07 7:24:21
Message-ID: 20101107072421.76181AC89E () svn ! kde ! org
[Download RAW message or body]

SVN commit 1193812 by dkazakov:

Fix the border effects in OpenGL canvas

This patch makes the textures representing the image overlap. The size
of the textures is still 256x256 pixels, But effectively they carry
254x254 pixels of information. The overlapping 1px border makes linear
interpolation algorithm happy, so scaling is done in the right way.

The patch fixes "image->bounds()" border effect as well. How does it
solve it? It just repeats the first and the last pixels of every row
and column. So the interpolation runs successfully.

BUG:251113


 M  +1 -0      CMakeLists.txt  
 M  +4 -4      opengl/kis_opengl_canvas2.cpp  
 M  +34 -12    opengl/kis_opengl_image_textures.cpp  
 M  +2 -2      opengl/kis_opengl_image_textures.h  
 A             opengl/kis_texture_tile.cpp   [License: GPL (v2+)]
 M  +27 -80    opengl/kis_texture_tile.h  
 M  +18 -7     opengl/kis_texture_tile_update_info.h  


--- trunk/koffice/krita/ui/CMakeLists.txt #1193811:1193812
@@ -108,6 +108,7 @@
     opengl/kis_opengl.cpp 
     opengl/kis_opengl_canvas2.cpp
     opengl/kis_opengl_image_textures.cpp
+    opengl/kis_texture_tile.cpp
     openrastertk/kis_open_raster_stack_load_visitor.cpp
     openrastertk/kis_open_raster_stack_save_visitor.cpp
     recorder/kis_recorded_action_editor_factory.cc
--- trunk/koffice/krita/ui/opengl/kis_opengl_canvas2.cpp #1193811:1193812
@@ -269,16 +269,16 @@
                 m_d->openGLImageTextures->getTextureTileCR(col, row);
 
             glBindTexture(GL_TEXTURE_2D, tile->textureId());
+
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
             if (scaleX > 2.0) {
                 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
                 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
             } else {
                 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
             }
 
             tile->drawPoints();
--- trunk/koffice/krita/ui/opengl/kis_opengl_image_textures.cpp #1193811:1193812
@@ -127,22 +127,25 @@
 
     destroyImageTextureTiles();
     updateTextureFormat();
+    m_texturesInfo.imageRect = m_image->bounds();
 
+
     const int lastCol = xToCol(m_image->width());
     const int lastRow = yToRow(m_image->height());
     m_numCols = lastCol + 1;
 
     // Default color is transparent black
     const int pixelSize = 4;
-    QByteArray emptyTileData(m_texturesInfo.width * m_texturesInfo.height * pixelSize, 0);
+    QByteArray emptyTileData((m_texturesInfo.width) * (m_texturesInfo.height) * pixelSize, 0);
 
     for (int row = 0; row <= lastRow; row++) {
         for (int col = 0; col <= lastCol; col++) {
-            QRect tileRect(col * m_texturesInfo.width,
-                           row * m_texturesInfo.height,
-                           m_texturesInfo.width, m_texturesInfo.height);
+            QRect tileRect(col * m_texturesInfo.effectiveWidth,
+                           row * m_texturesInfo.effectiveHeight,
+                           m_texturesInfo.effectiveWidth,
+                           m_texturesInfo.effectiveHeight);
 
-            KisTextureTile *tile = new KisTextureTile(tileRect,
+            KisTextureTile *tile = new KisTextureTile(tileRect & m_texturesInfo.imageRect,
                                                       &m_texturesInfo,
                                                       emptyTileData.constData());
             m_textureTiles.append(tile);
@@ -169,11 +172,24 @@
     QRect updateRect = rect & m_image->bounds();
     if (updateRect.isEmpty()) return info;
 
-    int firstColumn = xToCol(updateRect.left());
-    int lastColumn = xToCol(updateRect.right());
-    int firstRow = yToRow(updateRect.top());
-    int lastRow = yToRow(updateRect.bottom());
 
+    /**
+     * Why the rect is artificial? That's easy!
+     * It does not represent any real piece of the image. It is
+     * intentionally stretched to get through the overlappping
+     * stripes of neutrality and poke neighbouring tiles.
+     * Thanks to the rect we get the coordinates of all the tiles
+     * involved into update process
+     */
+
+    QRect artificialRect = stretchRect(updateRect, m_texturesInfo.border);
+
+    int firstColumn = xToCol(artificialRect.left());
+    int lastColumn = xToCol(artificialRect.right());
+    int firstRow = yToRow(artificialRect.top());
+    int lastRow = yToRow(artificialRect.bottom());
+
+
     qint32 numItems = (lastColumn - firstColumn + 1) * (lastRow - firstRow + 1);
     info->tileList.reserve(numItems);
 
@@ -182,8 +198,10 @@
 
             KisTextureTile *tile = getTextureTileCR(col, row);
 
-            KisTextureTileUpdateInfo tileInfo(tile->tileRectInImagePixels(),
+            KisTextureTileUpdateInfo tileInfo(tile,
+                                              tile->textureRectInImagePixels(),
                                               updateRect);
+
             tileInfo.retrieveData(m_image);
             info->tileList.append(tileInfo);
         }
@@ -224,8 +242,7 @@
         }
 
         tileInfo.convertTo(dstCS);
-        KisTextureTile *tile = getTextureTile(tileInfo.tileRect().x(), tileInfo.tileRect().y());
-        tile->update(tileInfo);
+        tileInfo.relatedTile()->update(tileInfo);
         tileInfo.destroy();
 
         KIS_OPENGL_PRINT_ERROR();
@@ -351,6 +368,11 @@
 
     texturesInfo->width = qMin(preferredTextureSize, maxTextureSize);
     texturesInfo->height = qMin(preferredTextureSize, maxTextureSize);
+
+    texturesInfo->border = 1;
+
+    texturesInfo->effectiveWidth = texturesInfo->width - 2 * texturesInfo->border;
+    texturesInfo->effectiveHeight = texturesInfo->height - 2 * texturesInfo->border;
 }
 
 void KisOpenGLImageTextures::updateTextureFormat()
--- trunk/koffice/krita/ui/opengl/kis_opengl_image_textures.h #1193811:1193812
@@ -116,11 +116,11 @@
 
 public:
     inline int xToCol(int x) {
-        return x / m_texturesInfo.width;
+        return x / m_texturesInfo.effectiveWidth;
     }
 
     inline int yToRow(int y) {
-        return y / m_texturesInfo.height;
+        return y / m_texturesInfo.effectiveHeight;
     }
 
     inline KisTextureTile* getTextureTileCR(int col, int row) {
--- trunk/koffice/krita/ui/opengl/kis_texture_tile.h #1193811:1193812
@@ -18,102 +18,47 @@
 #ifndef KIS_TEXTURE_TILE_H_
 #define KIS_TEXTURE_TILE_H_
 
+#include <opengl/kis_opengl.h>
+
 #ifdef HAVE_OPENGL
 
 #include "kis_texture_tile_update_info.h"
 
+#include <QRect>
+#include <QRectF>
+#include <opengl/kis_opengl.h>
 
+
 struct KisGLTexturesInfo {
     int width;
     int height;
 
+    int effectiveWidth;
+    int effectiveHeight;
+
+    int border;
+
     GLint format;
     GLint type;
+
+    QRect imageRect;
 };
 
+inline QRect stretchRect(const QRect &rc, int delta)
+{
+    return rc.adjusted(-delta, -delta, delta, delta);
+}
 
 class KisTextureTile
 {
 public:
     KisTextureTile(QRect imageRect, const KisGLTexturesInfo *texturesInfo,
-                   const GLvoid *fillData)
+                   const GLvoid *fillData);
+    ~KisTextureTile();
 
-        : m_tileRectInImagePixels(imageRect), m_texturesInfo(texturesInfo)
-    {
-        m_textureRectInImagePixels =
-            m_tileRectInImagePixels/*.adjusted(-1,-1,1,1)*/;
+    void update(const KisTextureTileUpdateInfo &updateInfo);
+    void drawPoints();
 
-//        m_tileRectInTexturePixels = QRectF(0.0, 0.0, 1.0, 1.0);
-
-        glGenTextures(1, &m_textureId);
-        glBindTexture(GL_TEXTURE_2D, m_textureId);
-        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-        glTexImage2D(GL_TEXTURE_2D, 0,
-                     m_texturesInfo->format,
-                     m_texturesInfo->height, m_texturesInfo->width, 0,
-                     GL_BGRA, GL_UNSIGNED_BYTE, fillData);
-    }
-
-    ~KisTextureTile() {
-        glDeleteTextures(1, &m_textureId);
-    }
-
-    inline void update(KisTextureTileUpdateInfo updateInfo) {
-        glBindTexture(GL_TEXTURE_2D, m_textureId);
-        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-
-        if (updateInfo.isEntireTileUpdated()) {
-            glTexImage2D(GL_TEXTURE_2D, 0,
-                         m_texturesInfo->format,
-                         m_texturesInfo->height, m_texturesInfo->width, 0,
-                         GL_BGRA, m_texturesInfo->type,
-                         updateInfo.data());
-        } else {
-            QPoint patchOffset = updateInfo.patchOffset();
-            QSize patchSize = updateInfo.patchSize();
-            glTexSubImage2D(GL_TEXTURE_2D, 0,
-                            patchOffset.x(), patchOffset.y(),
-                            patchSize.width(), patchSize.height(),
-                            GL_BGRA, m_texturesInfo->type,
-                            updateInfo.data());
-        }
-
-    }
-
-    inline void drawPoints() {
-        /**
-         * We create a float rect here to workaround Qt's
-         * "history reasons" in calculation of right()
-         * and bottom() coordinates of integer rects.
-         */
-        QRectF imageRect(m_tileRectInImagePixels);
-        QPointF pt;
-
-        glBegin(GL_QUADS);
-
-        pt = imageRect.topLeft();
-        glTexCoord2f(0.0, 0.0);
-        glVertex2f(pt.x(), pt.y());
-
-        pt = imageRect.topRight();
-        glTexCoord2f(1.0, 0.0);
-        glVertex2f(pt.x(), pt.y());
-
-        pt = imageRect.bottomRight();
-        glTexCoord2f(1.0, 1.0);
-        glVertex2f(pt.x(), pt.y());
-
-        pt = imageRect.bottomLeft();
-        glTexCoord2f(0.0, 1.0);
-        glVertex2f(pt.x(), pt.y());
-
-        glEnd();
-    }
-
-//    inline QRectF tileRectInTexturePixels() {
-//        return m_tileRectInTexturePixels;
-//    }
-
     inline QRect tileRectInImagePixels() {
         return m_tileRectInImagePixels;
     }
@@ -122,16 +67,18 @@
         return m_textureId;
     }
 
-//    inline QRect textureRectInImagePixels() {
-//        return m_textureRectInImagePixels;
-//    }
+    inline QRect textureRectInImagePixels() {
+        return m_textureRectInImagePixels;
+    }
 
+private:
+    void repeatStripes(const KisTextureTileUpdateInfo &updateInfo);
 
 private:
     GLuint m_textureId;
 
     QRect m_tileRectInImagePixels;
-//    QRectF m_tileRectInTexturePixels;
+    QRectF m_tileRectInTexturePixels;
     QRect m_textureRectInImagePixels;
 
     const KisGLTexturesInfo *m_texturesInfo;
--- trunk/koffice/krita/ui/opengl/kis_texture_tile_update_info.h #1193811:1193812
@@ -25,6 +25,8 @@
 #include "kis_image.h"
 #include "kis_paint_device.h"
 
+class KisTextureTile;
+
 class KisTextureTileUpdateInfo;
 typedef QVector<KisTextureTileUpdateInfo> KisTextureTileUpdateInfoList;
 
@@ -35,7 +37,8 @@
         m_patchPixels = 0;
     }
 
-    KisTextureTileUpdateInfo(QRect tileRect, QRect updateRect) {
+    KisTextureTileUpdateInfo(KisTextureTile *tile, QRect tileRect, QRect updateRect) {
+        m_textureTile = tile;
         m_tileRect = tileRect;
         m_patchRect = m_tileRect & updateRect;
         m_patchPixels = 0;
@@ -50,7 +53,6 @@
 
     void retrieveData(KisImageWSP image) {
         m_patchColorSpace = image->projection()->colorSpace();
-
         m_patchPixels = m_patchColorSpace->allocPixelBuffer(m_patchRect.width() * m_patchRect.height());
         image->projection()->readBytes(m_patchPixels,
                                        m_patchRect.x(), m_patchRect.y(),
@@ -71,28 +73,37 @@
         m_patchPixels = dstBuffer;
     }
 
-    inline quint8* data() {
+    inline quint8* data() const {
         return m_patchPixels;
     }
 
-    inline bool isEntireTileUpdated() {
+    inline bool isEntireTileUpdated() const {
         return m_patchRect == m_tileRect;
     }
 
-    inline QPoint patchOffset() {
+    inline QPoint patchOffset() const {
         return QPoint(m_patchRect.x() - m_tileRect.x(),
                       m_patchRect.y() - m_tileRect.y());
     }
 
-    inline QSize patchSize() {
+    inline QSize patchSize() const {
         return m_patchRect.size();
     }
 
-    inline QRect tileRect() {
+    inline QRect tileRect() const {
         return m_tileRect;
     }
 
+    KisTextureTile *relatedTile() const {
+        return m_textureTile;
+    }
+
+    quint32 pixelSize() const {
+        return m_patchColorSpace->pixelSize();
+    }
+
 private:
+    KisTextureTile *m_textureTile;
     QRect m_tileRect;
     QRect m_patchRect;
     const KoColorSpace* m_patchColorSpace;
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic