void KisTextureTile::update(const KisTextureTileUpdateInfo &updateInfo) {
    glBindTexture(GL_TEXTURE_2D, m_textureId);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    if (updateInfo.isEntireTileUpdated()) {

        glTexImage2D(GL_TEXTURE_2D, 0,
                     m_texturesInfo->internalFormat,
                     m_texturesInfo->width,
                     m_texturesInfo->height, 0,
                     m_texturesInfo->format,
                     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(),
                        m_texturesInfo->format,
                        m_texturesInfo->type,
                        updateInfo.data());

    }

    /**
     * On the boundaries of KisImage, there is a border-effect as well.
     * So we just repeat the bounding pixels of the image to make
     * bilinear interpolator happy.
     */
    repeatStripes(updateInfo);
}
inline void KisTextureTile::repeatStripes(const KisTextureTileUpdateInfo &updateInfo) {
    /**
     * WARN: This function can repeat stripes of 1px width only!
     */

    const int pixelSize = updateInfo.pixelSize();
    const QRect imageRect = updateInfo.imageRect();
    const QPoint patchOffset = updateInfo.patchOffset();
    const QSize patchSize = updateInfo.patchSize();
    const QRect patchRect = QRect(m_textureRectInImagePixels.topLeft() +
                                  patchOffset,
                                  patchSize);

    if(imageRect.top() == patchRect.top()) {
        glTexSubImage2D(GL_TEXTURE_2D, 0,
                        patchOffset.x(), patchOffset.y() - 1,
                        patchSize.width(), 1,
                        m_texturesInfo->format,
                        m_texturesInfo->type,
                        updateInfo.data());

    }

    if(imageRect.bottom() == patchRect.bottom()) {
        int shift = patchSize.width() * (patchSize.height() - 1) *
            pixelSize;

        glTexSubImage2D(GL_TEXTURE_2D, 0,
                        patchOffset.x(), patchOffset.y() + patchSize.height(),
                        patchSize.width(), 1,
                        m_texturesInfo->format,
                        m_texturesInfo->type,
                        updateInfo.data() + shift);

    }

    if(imageRect.left() == patchRect.left()) {
        QByteArray columnBuffer(patchSize.height() * pixelSize, 0);

        quint8 *srcPtr = updateInfo.data();
        quint8 *dstPtr = (quint8*) columnBuffer.data();
        for(int i = 0; i < patchSize.height(); i++) {
            memcpy(dstPtr, srcPtr, pixelSize);

            srcPtr += patchSize.width() * pixelSize;
            dstPtr += pixelSize;
        }

        glTexSubImage2D(GL_TEXTURE_2D, 0,
                        patchOffset.x() - 1, patchOffset.y(),
                        1, patchSize.height(),
                        m_texturesInfo->format,
                        m_texturesInfo->type,
                        columnBuffer.constData());
    }

    if(imageRect.right() == patchRect.right()) {
        QByteArray columnBuffer(patchSize.height() * pixelSize, 0);

        quint8 *srcPtr = updateInfo.data() + (patchSize.width() - 1) * pixelSize;
        quint8 *dstPtr = (quint8*) columnBuffer.data();
        for(int i = 0; i < patchSize.height(); i++) {
            memcpy(dstPtr, srcPtr, pixelSize);

            srcPtr += patchSize.width() * pixelSize;
            dstPtr += pixelSize;
        }

        glTexSubImage2D(GL_TEXTURE_2D, 0,
                        patchOffset.x() + patchSize.width(), patchOffset.y(),
                        1, patchSize.height(),
                        m_texturesInfo->format,
                        m_texturesInfo->type,
                        columnBuffer.constData());
    }

}
Beispiel #3
0
void KisTextureTile::update(const KisTextureTileUpdateInfo &updateInfo)
{
    glBindTexture(GL_TEXTURE_2D, m_textureId);

    setTextureParameters();

    const GLvoid *fd = updateInfo.data();
#ifdef USE_PIXEL_BUFFERS
    KisConfig cfg;
    if (!m_glBuffer) {
        QByteArray ba;
        ba.fromRawData((const char*)updateInfo.data(), updateInfo.patchPixelsLength());
        createTextureBuffer(ba);
    }
#endif

    if (updateInfo.isEntireTileUpdated()) {

#ifdef USE_PIXEL_BUFFERS

        if (cfg.useOpenGLTextureBuffer()) {

            m_glBuffer->bind();
            m_glBuffer->allocate(updateInfo.patchPixelsLength());

            void *vid = m_glBuffer->map(QGLBuffer::WriteOnly);
            memcpy(vid, fd, updateInfo.patchPixelsLength());
            m_glBuffer->unmap();

            // we set fill data to 0 so the next glTexImage2D call uses our buffer
            fd = 0;
        }
#endif

        glTexImage2D(GL_TEXTURE_2D, 0,
                     m_texturesInfo->internalFormat,
                     m_texturesInfo->width,
                     m_texturesInfo->height, 0,
                     m_texturesInfo->format,
                     m_texturesInfo->type,
                     fd);

#ifdef USE_PIXEL_BUFFERS
        if (cfg.useOpenGLTextureBuffer()) {
            m_glBuffer->release();
        }
#endif

    }
    else {
        QPoint patchOffset = updateInfo.patchOffset();
        QSize patchSize = updateInfo.patchSize();

#ifdef USE_PIXEL_BUFFERS
        if (cfg.useOpenGLTextureBuffer()) {
            m_glBuffer->bind();
            quint32 size = patchSize.width() * patchSize.height() * updateInfo.pixelSize();
            m_glBuffer->allocate(size);

            void *vid = m_glBuffer->map(QGLBuffer::WriteOnly);
            memcpy(vid, fd, size);
            m_glBuffer->unmap();

            // we set fill data to 0 so the next glTexImage2D call uses our buffer
            fd = 0;
        }
#endif

        glTexSubImage2D(GL_TEXTURE_2D, 0,
                        patchOffset.x(), patchOffset.y(),
                        patchSize.width(), patchSize.height(),
                        m_texturesInfo->format,
                        m_texturesInfo->type,
                        fd);

#ifdef USE_PIXEL_BUFFERS
        if (cfg.useOpenGLTextureBuffer()) {
            m_glBuffer->release();
        }
#endif

    }

    /**
     * On the boundaries of KisImage, there is a border-effect as well.
     * So we just repeat the bounding pixels of the image to make
     * bilinear interpolator happy.
     */

    /**
     * WARN: The width of the stripes will be equal to the broder
     *       width of the tiles.
     */

    const int pixelSize = updateInfo.pixelSize();
    const QRect imageRect = updateInfo.imageRect();
    const QPoint patchOffset = updateInfo.patchOffset();
    const QSize patchSize = updateInfo.patchSize();
    const QRect patchRect = QRect(m_textureRectInImagePixels.topLeft() +
                                  patchOffset,
                                  patchSize);
    const QSize tileSize = updateInfo.tileRect().size();


    if(imageRect.top() == patchRect.top()) {
        int start = 0;
        int end = patchOffset.y() - 1;
        for (int i = start; i <= end; i++) {
            glTexSubImage2D(GL_TEXTURE_2D, 0,
                            patchOffset.x(), i,
                            patchSize.width(), 1,
                            m_texturesInfo->format,
                            m_texturesInfo->type,
                            updateInfo.data());
        }
    }

    if (imageRect.bottom() == patchRect.bottom()) {
        int shift = patchSize.width() * (patchSize.height() - 1) *
                    pixelSize;

        int start = patchOffset.y() + patchSize.height();
        int end = tileSize.height() - 1;
        for (int i = start; i < end; i++) {
            glTexSubImage2D(GL_TEXTURE_2D, 0,
                            patchOffset.x(), i,
                            patchSize.width(), 1,
                            m_texturesInfo->format,
                            m_texturesInfo->type,
                            updateInfo.data() + shift);
        }
    }

    if (imageRect.left() == patchRect.left()) {

        QByteArray columnBuffer(patchSize.height() * pixelSize, 0);

        quint8 *srcPtr = updateInfo.data();
        quint8 *dstPtr = (quint8*) columnBuffer.data();
        for(int i = 0; i < patchSize.height(); i++) {
            memcpy(dstPtr, srcPtr, pixelSize);

            srcPtr += patchSize.width() * pixelSize;
            dstPtr += pixelSize;
        }

        int start = 0;
        int end = patchOffset.x() - 1;
        for (int i = start; i <= end; i++) {
            glTexSubImage2D(GL_TEXTURE_2D, 0,
                            i, patchOffset.y(),
                            1, patchSize.height(),
                            m_texturesInfo->format,
                            m_texturesInfo->type,
                            columnBuffer.constData());
        }
    }

    if (imageRect.right() == patchRect.right()) {

        QByteArray columnBuffer(patchSize.height() * pixelSize, 0);

        quint8 *srcPtr = updateInfo.data() + (patchSize.width() - 1) * pixelSize;
        quint8 *dstPtr = (quint8*) columnBuffer.data();
        for(int i = 0; i < patchSize.height(); i++) {
            memcpy(dstPtr, srcPtr, pixelSize);

            srcPtr += patchSize.width() * pixelSize;
            dstPtr += pixelSize;
        }

        int start = patchOffset.x() + patchSize.width();
        int end = tileSize.width() - 1;
        for (int i = start; i <= end; i++) {
            glTexSubImage2D(GL_TEXTURE_2D, 0,
                            i, patchOffset.y(),
                            1, patchSize.height(),
                            m_texturesInfo->format,
                            m_texturesInfo->type,
                            columnBuffer.constData());
        }
    }

    setNeedsMipmapRegeneration();
}