Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha) { int w = size.width(); int h = size.height(); QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); while (funcs->glGetError()); #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN QImage img(size, (alpha_format && include_alpha) ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32); #ifdef QT_OPENGL_ES GLint fmt = GL_BGRA_EXT; #else GLint fmt = GL_BGRA; #endif funcs->glReadPixels(0, 0, w, h, fmt, GL_UNSIGNED_BYTE, img.bits()); if (!funcs->glGetError()) return img.mirrored(); #endif QImage rgbaImage(size, (alpha_format && include_alpha) ? QImage::Format_RGBA8888_Premultiplied : QImage::Format_RGBX8888); funcs->glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, rgbaImage.bits()); return rgbaImage.mirrored(); }
void QSGDistanceFieldGlyphCache::saveTexture(GLuint textureId, int width, int height) const { QOpenGLFunctions *functions = QOpenGLContext::currentContext()->functions(); GLuint fboId; functions->glGenFramebuffers(1, &fboId); GLuint tmpTexture = 0; functions->glGenTextures(1, &tmpTexture); functions->glBindTexture(GL_TEXTURE_2D, tmpTexture); functions->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); functions->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); functions->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); functions->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); functions->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); functions->glBindTexture(GL_TEXTURE_2D, 0); functions->glBindFramebuffer(GL_FRAMEBUFFER_EXT, fboId); functions->glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, tmpTexture, 0); functions->glActiveTexture(GL_TEXTURE0); functions->glBindTexture(GL_TEXTURE_2D, textureId); functions->glDisable(GL_STENCIL_TEST); functions->glDisable(GL_DEPTH_TEST); functions->glDisable(GL_SCISSOR_TEST); functions->glDisable(GL_BLEND); GLfloat textureCoordinateArray[8]; textureCoordinateArray[0] = 0.0f; textureCoordinateArray[1] = 0.0f; textureCoordinateArray[2] = 1.0f; textureCoordinateArray[3] = 0.0f; textureCoordinateArray[4] = 1.0f; textureCoordinateArray[5] = 1.0f; textureCoordinateArray[6] = 0.0f; textureCoordinateArray[7] = 1.0f; GLfloat vertexCoordinateArray[8]; vertexCoordinateArray[0] = -1.0f; vertexCoordinateArray[1] = -1.0f; vertexCoordinateArray[2] = 1.0f; vertexCoordinateArray[3] = -1.0f; vertexCoordinateArray[4] = 1.0f; vertexCoordinateArray[5] = 1.0f; vertexCoordinateArray[6] = -1.0f; vertexCoordinateArray[7] = 1.0f; functions->glViewport(0, 0, width, height); functions->glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertexCoordinateArray); functions->glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinateArray); { static const char *vertexShaderSource = "attribute vec4 vertexCoordsArray; \n" "attribute vec2 textureCoordArray; \n" "varying vec2 textureCoords; \n" "void main(void) \n" "{ \n" " gl_Position = vertexCoordsArray; \n" " textureCoords = textureCoordArray; \n" "} \n"; static const char *fragmentShaderSource = "varying vec2 textureCoords; \n" "uniform sampler2D texture; \n" "void main() \n" "{ \n" " gl_FragColor = texture2D(texture, textureCoords); \n" "} \n"; GLuint vertexShader = functions->glCreateShader(GL_VERTEX_SHADER); GLuint fragmentShader = functions->glCreateShader(GL_FRAGMENT_SHADER); if (vertexShader == 0 || fragmentShader == 0) { GLenum error = functions->glGetError(); qWarning("QSGDistanceFieldGlyphCache::saveTexture: Failed to create shaders. (GL error: %x)", error); return; } functions->glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); functions->glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL); functions->glCompileShader(vertexShader); GLint len = 1; functions->glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &len); char infoLog[2048]; functions->glGetShaderInfoLog(vertexShader, 2048, NULL, infoLog); if (qstrlen(infoLog) > 0) qWarning("Problems compiling vertex shader:\n %s", infoLog); functions->glCompileShader(fragmentShader); functions->glGetShaderInfoLog(fragmentShader, 2048, NULL, infoLog); if (qstrlen(infoLog) > 0) qWarning("Problems compiling fragment shader:\n %s", infoLog); GLuint shaderProgram = functions->glCreateProgram(); functions->glAttachShader(shaderProgram, vertexShader); functions->glAttachShader(shaderProgram, fragmentShader); functions->glBindAttribLocation(shaderProgram, 0, "vertexCoordsArray"); functions->glBindAttribLocation(shaderProgram, 1, "textureCoordArray"); functions->glLinkProgram(shaderProgram); functions->glGetProgramInfoLog(shaderProgram, 2048, NULL, infoLog); if (qstrlen(infoLog) > 0) qWarning("Problems linking shaders:\n %s", infoLog); functions->glUseProgram(shaderProgram); functions->glEnableVertexAttribArray(0); functions->glEnableVertexAttribArray(1); int textureUniformLocation = functions->glGetUniformLocation(shaderProgram, "texture"); functions->glUniform1i(textureUniformLocation, 0); } functions->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); { GLenum error = functions->glGetError(); if (error != GL_NO_ERROR) qWarning("glDrawArrays reported error 0x%x", error); } uchar *data = new uchar[width * height * 4]; functions->glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data); QImage image(data, width, height, QImage::Format_ARGB32); QByteArray fileName = m_referenceFont.familyName().toLatin1() + '_' + QByteArray::number(textureId); fileName = fileName.replace('/', '_').replace(' ', '_') + ".png"; image.save(QString::fromLocal8Bit(fileName)); { GLenum error = functions->glGetError(); if (error != GL_NO_ERROR) qWarning("glReadPixels reported error 0x%x", error); } functions->glDisableVertexAttribArray(0); functions->glDisableVertexAttribArray(1); functions->glDeleteFramebuffers(1, &fboId); functions->glDeleteTextures(1, &tmpTexture); delete[] data; }