• Szabolcs David's avatar
    Support middle click navigation · 6cbeac50
    Szabolcs David authored
    
    When the user does a middle click on a link which originally opens a
    new tab (target="_blank"), the newly created RenderView is hidden, so
    the new tab has no visible content. We need to unhide it explicitly.
    
    This also adds background tab support for the Quick example browsers
    and fixes the profile mismatching warning in the case when we adopt
    a new tab without WebContents.
    
    Change-Id: Ia3c2e752a4784d32133cee0ff278c2849b151582
    Reviewed-by: default avatarAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>
    6cbeac50
qopengltextureglyphcache.cpp 16.71 KiB
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
** $QT_END_LICENSE$
****************************************************************************/
#include "qopengltextureglyphcache_p.h"
#include "qopenglpaintengine_p.h"
#include "private/qopenglengineshadersource_p.h"
#include "qopenglextensions_p.h"
#include <qrgb.h>
#include <private/qdrawhelper_p.h>
QT_BEGIN_NAMESPACE
QBasicAtomicInt qopengltextureglyphcache_serial_number = Q_BASIC_ATOMIC_INITIALIZER(1);
QOpenGLTextureGlyphCache::QOpenGLTextureGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix)
    : QImageTextureGlyphCache(format, matrix)
    , m_textureResource(0)
    , pex(0)
    , m_blitProgram(0)
    , m_filterMode(Nearest)
    , m_serialNumber(qopengltextureglyphcache_serial_number.fetchAndAddRelaxed(1))
    , m_buffer(QOpenGLBuffer::VertexBuffer)
#ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG
    qDebug(" -> QOpenGLTextureGlyphCache() %p for context %p.", this, QOpenGLContext::currentContext());
#endif
    m_vertexCoordinateArray[0] = -1.0f;
    m_vertexCoordinateArray[1] = -1.0f;
    m_vertexCoordinateArray[2] =  1.0f;
    m_vertexCoordinateArray[3] = -1.0f;
    m_vertexCoordinateArray[4] =  1.0f;
    m_vertexCoordinateArray[5] =  1.0f;
    m_vertexCoordinateArray[6] = -1.0f;
    m_vertexCoordinateArray[7] =  1.0f;
    m_textureCoordinateArray[0] = 0.0f;
    m_textureCoordinateArray[1] = 0.0f;
    m_textureCoordinateArray[2] = 1.0f;
    m_textureCoordinateArray[3] = 0.0f;
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
m_textureCoordinateArray[4] = 1.0f; m_textureCoordinateArray[5] = 1.0f; m_textureCoordinateArray[6] = 0.0f; m_textureCoordinateArray[7] = 1.0f; } QOpenGLTextureGlyphCache::~QOpenGLTextureGlyphCache() { #ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG qDebug(" -> ~QOpenGLTextureGlyphCache() %p.", this); #endif clear(); } static inline bool isCoreProfile() { return QOpenGLContext::currentContext()->format().profile() == QSurfaceFormat::CoreProfile; } void QOpenGLTextureGlyphCache::createTextureData(int width, int height) { QOpenGLContext *ctx = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext()); if (ctx == 0) { qWarning("QOpenGLTextureGlyphCache::createTextureData: Called with no context"); return; } // create in QImageTextureGlyphCache baseclass is meant to be called // only to create the initial image and does not preserve the content, // so we don't call when this function is called from resize. if (ctx->d_func()->workaround_brokenFBOReadBack && image().isNull()) QImageTextureGlyphCache::createTextureData(width, height); // Make the lower glyph texture size 16 x 16. if (width < 16) width = 16; if (height < 16) height = 16; if (m_textureResource && !m_textureResource->m_texture) { delete m_textureResource; m_textureResource = 0; } if (!m_textureResource) m_textureResource = new QOpenGLGlyphTexture(ctx); QOpenGLFunctions *funcs = ctx->functions(); funcs->glGenTextures(1, &m_textureResource->m_texture); funcs->glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture); m_textureResource->m_width = width; m_textureResource->m_height = height; if (m_format == QFontEngine::Format_A32 || m_format == QFontEngine::Format_ARGB) { QVarLengthArray<uchar> data(width * height * 4); for (int i = 0; i < data.size(); ++i) data[i] = 0; funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); } else { QVarLengthArray<uchar> data(width * height); for (int i = 0; i < data.size(); ++i) data[i] = 0; #if !defined(QT_OPENGL_ES_2) const GLint internalFormat = isCoreProfile() ? GL_R8 : GL_ALPHA; const GLenum format = isCoreProfile() ? GL_RED : GL_ALPHA; #else const GLint internalFormat = GL_ALPHA; const GLenum format = GL_ALPHA; #endif
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
funcs->glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, GL_UNSIGNED_BYTE, &data[0]); } funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); m_filterMode = Nearest; if (!m_buffer.isCreated()) { m_buffer.create(); m_buffer.bind(); static GLfloat buf[sizeof(m_vertexCoordinateArray) + sizeof(m_textureCoordinateArray)]; memcpy(buf, m_vertexCoordinateArray, sizeof(m_vertexCoordinateArray)); memcpy(buf + (sizeof(m_vertexCoordinateArray) / sizeof(GLfloat)), m_textureCoordinateArray, sizeof(m_textureCoordinateArray)); m_buffer.allocate(buf, sizeof(buf)); m_buffer.release(); } if (!m_vao.isCreated()) m_vao.create(); } void QOpenGLTextureGlyphCache::setupVertexAttribs() { m_buffer.bind(); m_blitProgram->setAttributeBuffer(int(QT_VERTEX_COORDS_ATTR), GL_FLOAT, 0, 2); m_blitProgram->setAttributeBuffer(int(QT_TEXTURE_COORDS_ATTR), GL_FLOAT, sizeof(m_vertexCoordinateArray), 2); m_blitProgram->enableAttributeArray(int(QT_VERTEX_COORDS_ATTR)); m_blitProgram->enableAttributeArray(int(QT_TEXTURE_COORDS_ATTR)); m_buffer.release(); } void QOpenGLTextureGlyphCache::resizeTextureData(int width, int height) { QOpenGLContext *ctx = QOpenGLContext::currentContext(); if (ctx == 0) { qWarning("QOpenGLTextureGlyphCache::resizeTextureData: Called with no context"); return; } QOpenGLFunctions *funcs = ctx->functions(); GLint oldFbo; funcs->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &oldFbo); int oldWidth = m_textureResource->m_width; int oldHeight = m_textureResource->m_height; // Make the lower glyph texture size 16 x 16. if (width < 16) width = 16; if (height < 16) height = 16; GLuint oldTexture = m_textureResource->m_texture; createTextureData(width, height); if (ctx->d_func()->workaround_brokenFBOReadBack) { QImageTextureGlyphCache::resizeTextureData(width, height); Q_ASSERT(image().depth() == 8); funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, oldHeight, GL_ALPHA, GL_UNSIGNED_BYTE, image().constBits()); funcs->glDeleteTextures(1, &oldTexture); return; } // ### the QTextureGlyphCache API needs to be reworked to allow // ### resizeTextureData to fail
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
funcs->glBindFramebuffer(GL_FRAMEBUFFER, m_textureResource->m_fbo); GLuint tmp_texture; funcs->glGenTextures(1, &tmp_texture); funcs->glBindTexture(GL_TEXTURE_2D, tmp_texture); funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, oldWidth, oldHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); m_filterMode = Nearest; funcs->glBindTexture(GL_TEXTURE_2D, 0); funcs->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tmp_texture, 0); funcs->glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); funcs->glBindTexture(GL_TEXTURE_2D, oldTexture); if (pex != 0) pex->transferMode(BrushDrawingMode); funcs->glDisable(GL_STENCIL_TEST); funcs->glDisable(GL_DEPTH_TEST); funcs->glDisable(GL_SCISSOR_TEST); funcs->glDisable(GL_BLEND); funcs->glViewport(0, 0, oldWidth, oldHeight); QOpenGLShaderProgram *blitProgram = 0; if (pex == 0) { if (m_blitProgram == 0) { m_blitProgram = new QOpenGLShaderProgram(ctx); const bool isCoreProfile = ctx->format().profile() == QSurfaceFormat::CoreProfile; { QString source; source.append(QLatin1String(isCoreProfile ? qopenglslMainWithTexCoordsVertexShader_core : qopenglslMainWithTexCoordsVertexShader)); source.append(QLatin1String(isCoreProfile ? qopenglslUntransformedPositionVertexShader_core : qopenglslUntransformedPositionVertexShader)); QOpenGLShader *vertexShader = new QOpenGLShader(QOpenGLShader::Vertex, m_blitProgram); vertexShader->compileSourceCode(source); m_blitProgram->addShader(vertexShader); } { QString source; source.append(QLatin1String(isCoreProfile ? qopenglslMainFragmentShader_core : qopenglslMainFragmentShader)); source.append(QLatin1String(isCoreProfile ? qopenglslImageSrcFragmentShader_core : qopenglslImageSrcFragmentShader)); QOpenGLShader *fragmentShader = new QOpenGLShader(QOpenGLShader::Fragment, m_blitProgram); fragmentShader->compileSourceCode(source); m_blitProgram->addShader(fragmentShader); } m_blitProgram->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); m_blitProgram->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); m_blitProgram->link(); if (m_vao.isCreated()) { m_vao.bind(); setupVertexAttribs(); } } if (m_vao.isCreated()) m_vao.bind();