KisTextureTile::~KisTextureTile() { #ifdef USE_PIXEL_BUFFERS KisConfig cfg; if (cfg.useOpenGLTextureBuffer()) { delete m_glBuffer; } #endif glDeleteTextures(1, &m_textureId); }
void KisOpenGLCanvas2::slotConfigChanged() { KisConfig cfg; d->checkSizeScale = KisOpenGLImageTextures::BACKGROUND_TEXTURE_CHECK_SIZE / static_cast<GLfloat>(cfg.checkSize()); d->scrollCheckers = cfg.scrollCheckers(); d->openGLImageTextures->generateCheckerTexture(createCheckersImage(cfg.checkSize())); d->openGLImageTextures->updateConfig(cfg.useOpenGLTextureBuffer(), cfg.numMipmapLevels()); d->filterMode = (KisOpenGL::FilterMode) cfg.openGLFilteringMode(); notifyConfigChanged(); }
KisTextureTile::KisTextureTile(QRect imageRect, const KisGLTexturesInfo *texturesInfo, const QByteArray &fillData, FilterMode filter) : m_textureId(0) #ifdef USE_PIXEL_BUFFERS , m_glBuffer(0) #endif , m_tileRectInImagePixels(imageRect) , m_filter(filter) , m_texturesInfo(texturesInfo) , m_needsMipmapRegeneration(false) { const GLvoid *fd = fillData.constData(); m_textureRectInImagePixels = stretchRect(m_tileRectInImagePixels, texturesInfo->border); m_tileRectInTexturePixels = relativeRect(m_textureRectInImagePixels, m_tileRectInImagePixels, m_texturesInfo); glGenTextures(1, &m_textureId); glBindTexture(GL_TEXTURE_2D, m_textureId); setTextureParameters(); #ifdef USE_PIXEL_BUFFERS createTextureBuffer(fillData); // 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 KisConfig cfg; if (cfg.useOpenGLTextureBuffer()) { m_glBuffer->release(); } #endif setNeedsMipmapRegeneration(); }
void KisTextureTile::createTextureBuffer(const QByteArray &fillData) { KisConfig cfg; if (cfg.useOpenGLTextureBuffer()) { m_glBuffer = new QGLBuffer(QGLBuffer::PixelUnpackBuffer); m_glBuffer->setUsagePattern(QGLBuffer::DynamicDraw); m_glBuffer->create(); m_glBuffer->bind(); m_glBuffer->allocate(fillData.size()); void *vid = m_glBuffer->map(QGLBuffer::WriteOnly); memcpy(vid, fillData.constData(), fillData.size()); m_glBuffer->unmap(); } else { m_glBuffer = 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(); }