bool OsmAnd::AtlasMapRenderer_OpenGL::doInitializeRendering()
{
    GL_CHECK_PRESENT(glClearColor);
    GL_CHECK_PRESENT(glClearDepthf);

    bool ok;

    ok = AtlasMapRenderer::doInitializeRendering();
    if(!ok)
        return false;

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    GL_CHECK_RESULT;

    glClearDepthf(1.0f);
    GL_CHECK_RESULT;

    _skyStage.initialize();
    _rasterMapStage.initialize();
    _symbolsStage.initialize();
#if OSMAND_DEBUG
    _debugStage.initialize();
#endif

    return true;
}
bool OsmAnd::GPUAPI_OpenGL_Common::releaseResourceInGPU( const ResourceInGPU::Type type, const RefInGPU& refInGPU )
{
    switch (type)
    {
    case ResourceInGPU::Type::Texture:
        {
            GL_CHECK_PRESENT(glDeleteTextures);

            GLuint texture = static_cast<GLuint>(reinterpret_cast<intptr_t>(refInGPU));
            glDeleteTextures(1, &texture);
            GL_CHECK_RESULT;

            return true;
        }
    case ResourceInGPU::Type::ArrayBuffer:
        {
            GL_CHECK_PRESENT(glDeleteBuffers);

            GLuint arrayBuffer = static_cast<GLuint>(reinterpret_cast<intptr_t>(refInGPU));
            glDeleteBuffers(1, &arrayBuffer);
            GL_CHECK_RESULT;

            return true;
        }
    }

    return false;
}
bool OsmAnd::AtlasMapRendererDebugStage_OpenGL::releaseQuads3D()
{
    const auto gpuAPI = getGPUAPI();

    GL_CHECK_PRESENT(glDeleteBuffers);
    GL_CHECK_PRESENT(glDeleteProgram);

    if (_vaoQuad3D.isValid())
    {
        gpuAPI->releaseVAO(_vaoQuad3D);
        _vaoQuad3D.reset();
    }
    
    if (_iboQuad3D.isValid())
    {
        glDeleteBuffers(1, &_iboQuad3D);
        GL_CHECK_RESULT;
        _iboQuad3D.reset();
    }
    if (_vboQuad3D.isValid())
    {
        glDeleteBuffers(1, &_vboQuad3D);
        GL_CHECK_RESULT;
        _vboQuad3D.reset();
    }
    
    if (_programQuad3D.id.isValid())
    {
        glDeleteProgram(_programQuad3D.id);
        GL_CHECK_RESULT;
        _programQuad3D = ProgramQuad3D();
    }

    return true;
}
void OsmAnd::AtlasMapRendererDebugStage_OpenGL::releaseQuads3D()
{
    const auto gpuAPI = getGPUAPI();

    GL_CHECK_PRESENT(glDeleteBuffers);
    GL_CHECK_PRESENT(glDeleteProgram);

    if(_iboQuad3D)
    {
        glDeleteBuffers(1, &_iboQuad3D);
        GL_CHECK_RESULT;
        _iboQuad3D.reset();
    }
    if(_vboQuad3D)
    {
        glDeleteBuffers(1, &_vboQuad3D);
        GL_CHECK_RESULT;
        _vboQuad3D.reset();
    }
    if(_vaoQuad3D)
    {
        gpuAPI->glDeleteVertexArrays_wrapper(1, &_vaoQuad3D);
        GL_CHECK_RESULT;
        _vaoQuad3D.reset();
    }
    if(_programQuad3D.id)
    {
        glDeleteProgram(_programQuad3D.id);
        GL_CHECK_RESULT;
        _programQuad3D = ProgramQuad3D();
    }
}
Пример #5
0
void OsmAnd::GPUAPI_OpenGLES2::uploadDataToTexture2D(
    GLenum target, GLint level,
    GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
    const GLvoid *data, GLsizei dataRowLengthInElements, GLsizei elementSize,
    const SourceFormat sourceFormat)
{
    GL_CHECK_PRESENT(glTexSubImage2D);

    // Try to use glPixelStorei to unpack
    if (isSupported_EXT_unpack_subimage)
    {
        GL_CHECK_PRESENT(glPixelStorei);

        glPixelStorei(GL_UNPACK_ROW_LENGTH, dataRowLengthInElements);
        GL_CHECK_RESULT;

        glTexSubImage2D(target, level,
            xoffset, yoffset, width, height,
            static_cast<GLenum>(sourceFormat.format),
            static_cast<GLenum>(sourceFormat.type),
            data);
        GL_CHECK_RESULT;

        return;
    }

    // Otherwise fallback to manual unpacking

    // In case our row length is 0 or equals to image width (has no extra stride, just load as-is)
    if (dataRowLengthInElements == 0 || dataRowLengthInElements == width)
    {
        // Upload data
        glTexSubImage2D(target, level,
            xoffset, yoffset, width, height,
            static_cast<GLenum>(sourceFormat.format),
            static_cast<GLenum>(sourceFormat.type),
            data);
        GL_CHECK_RESULT;
        return;
    }

    // Otherwise we need to or load row by row
    auto pRow = reinterpret_cast<const uint8_t*>(data);
    for (auto rowIdx = 0; rowIdx < height; rowIdx++)
    {
        glTexSubImage2D(target, level,
            xoffset, yoffset + rowIdx, width, 1,
            static_cast<GLenum>(sourceFormat.format),
            static_cast<GLenum>(sourceFormat.type),
            pRow);
        GL_CHECK_RESULT;

        pRow += dataRowLengthInElements*elementSize;
    }
}
void OsmAnd::AtlasMapRendererSkyStage_OpenGL::release()
{
    const auto gpuAPI = getGPUAPI();

    GL_CHECK_PRESENT(glDeleteBuffers);

    if(_skyplaneIBO)
    {
        glDeleteBuffers(1, &_skyplaneIBO);
        GL_CHECK_RESULT;
        _skyplaneIBO.reset();
    }
    if(_skyplaneVBO)
    {
        glDeleteBuffers(1, &_skyplaneVBO);
        GL_CHECK_RESULT;
        _skyplaneVBO.reset();
    }
    if(_skyplaneVAO)
    {
        gpuAPI->glDeleteVertexArrays_wrapper(1, &_skyplaneVAO);
        GL_CHECK_RESULT;
        _skyplaneVAO.reset();
    }

    if(_program.id)
    {
        glDeleteProgram(_program.id);
        GL_CHECK_RESULT;
        _program = Program();
    }
}
void OsmAnd::GPUAPI_OpenGL_Common::findVariableLocation( GLuint program, GLint& location, const QString& name, const GLShaderVariableType& type )
{
    GL_CHECK_PRESENT(glGetAttribLocation);
    GL_CHECK_PRESENT(glGetUniformLocation);

    if(type == GLShaderVariableType::In)
        location = glGetAttribLocation(program, qPrintable(name));
    else if(type == GLShaderVariableType::Uniform)
        location = glGetUniformLocation(program, qPrintable(name));
    GL_CHECK_RESULT;
    if(location == -1)
        LogPrintf(LogSeverityLevel::Error, "Variable '%s' (%s) was not found in GLSL program %d", qPrintable(name), type == GLShaderVariableType::In ? "In" : "Uniform", program);
    assert(location != -1);
    assert(!_programVariables[program].contains(type, location));
    _programVariables[program].insert(type, location);
}
Пример #8
0
void OsmAnd::GPUAPI_OpenGLES2::glBindVertexArray_wrapper(GLuint array)
{
    assert(isSupported_vertex_array_object);

    GL_CHECK_PRESENT(glBindVertexArrayOES);

    glBindVertexArrayOES(array);
}
Пример #9
0
void OsmAnd::GPUAPI_OpenGLES2::glDeleteVertexArrays_wrapper(GLsizei n, const GLuint* arrays)
{
    assert(isSupported_vertex_array_object);

    GL_CHECK_PRESENT(glDeleteVertexArraysOES);

    glDeleteVertexArraysOES(n, arrays);
}
bool OsmAnd::AtlasMapRendererDebugStage_OpenGL::releaseLines3D(const bool gpuContextLost)
{
    const auto gpuAPI = getGPUAPI();

    GL_CHECK_PRESENT(glDeleteBuffers);
    GL_CHECK_PRESENT(glDeleteProgram);

    if (_vaoLine3D.isValid())
    {
        gpuAPI->releaseVAO(_vaoLine3D, gpuContextLost);
        _vaoLine3D.reset();
    }
    
    if (_iboLine3D.isValid())
    {
        if (!gpuContextLost)
        {
            glDeleteBuffers(1, &_iboLine3D);
            GL_CHECK_RESULT;
        }
        _iboLine3D.reset();
    }
    if (_vboLine3D.isValid())
    {
        if (!gpuContextLost)
        {
            glDeleteBuffers(1, &_vboLine3D);
            GL_CHECK_RESULT;
        }
        _vboLine3D.reset();
    }
    
    if (_programLine3D.id.isValid())
    {
        if (!gpuContextLost)
        {
            glDeleteProgram(_programLine3D.id);
            GL_CHECK_RESULT;
        }
        _programLine3D = ProgramLine3D();
    }

    return true;
}
void OsmAnd::AtlasMapRendererDebugStage_OpenGL::renderLines3D()
{
    const auto gpuAPI = getGPUAPI();

    GL_CHECK_PRESENT(glUseProgram);
    GL_CHECK_PRESENT(glUniformMatrix4fv);
    GL_CHECK_PRESENT(glUniform1f);
    GL_CHECK_PRESENT(glUniform2f);
    GL_CHECK_PRESENT(glUniform3f);
    GL_CHECK_PRESENT(glDrawElements);

    gpuAPI->glBindVertexArray_wrapper(_vaoLine3D);
    GL_CHECK_RESULT;

    // Activate program
    glUseProgram(_programLine3D.id);
    GL_CHECK_RESULT;

    // Set projection*view*model matrix:
    const auto& mProjectionView = internalState.mPerspectiveProjection * internalState.mCameraView;
    glUniformMatrix4fv(_programLine3D.vs.param.mProjectionViewModel, 1, GL_FALSE, glm::value_ptr(mProjectionView));
    GL_CHECK_RESULT;

    for(const auto& primitive : constOf(_lines3D))
    {
        const auto& line = primitive.first;
        const auto& color = primitive.second;

        // Set line color
        glUniform4f(_programLine3D.fs.param.color, SkColorGetR(color) / 255.0f, SkColorGetG(color) / 255.0f, SkColorGetB(color) / 255.0f, SkColorGetA(color) / 255.0f);
        GL_CHECK_RESULT;

        // Iterate over pairs of points
        auto itV0 = line.cbegin();
        auto itV1 = itV0 + 1;
        for(const auto itEnd = line.cend(); itV1 != itEnd; itV0 = itV1, ++itV1)
        {
            const auto& v0 = *itV0;
            const auto& v1 = *itV1;

            // Set line coordinates
            glUniform4f(_programLine3D.vs.param.v0, v0.x, v0.y, v0.z, 1.0f);
            GL_CHECK_RESULT;
            glUniform4f(_programLine3D.vs.param.v1, v1.x, v1.y, v1.z, 1.0f);
            GL_CHECK_RESULT;

            // Draw the line actually
            glDrawElements(GL_LINES, 2, GL_UNSIGNED_SHORT, nullptr);
            GL_CHECK_RESULT;
        }
    }

    // Deactivate program
    glUseProgram(0);
    GL_CHECK_RESULT;

    // Deselect VAO
    gpuAPI->glBindVertexArray_wrapper(0);
    GL_CHECK_RESULT;
}
Пример #12
0
void OsmAnd::GPUAPI_OpenGLES2::setMipMapLevelsLimit(GLenum target, const uint32_t mipmapLevelsCount)
{
#if defined(OSMAND_TARGET_OS_ios)
    // Limit MipMap max level if possible
    if (isSupported_APPLE_texture_max_level)
    {
        GL_CHECK_PRESENT(glTexParameteri);

        glTexParameteri(target, GL_TEXTURE_MAX_LEVEL_APPLE, mipmapLevelsCount);
        GL_CHECK_RESULT;
    }
#endif //OSMAND_TARGET_OS_ios
}
bool OsmAnd::AtlasMapRendererDebugStage_OpenGL::renderLines2D()
{
    const auto gpuAPI = getGPUAPI();
    const auto& internalState = getInternalState();

    GL_CHECK_PRESENT(glUseProgram);
    GL_CHECK_PRESENT(glUniformMatrix4fv);
    GL_CHECK_PRESENT(glUniform1f);
    GL_CHECK_PRESENT(glUniform2f);
    GL_CHECK_PRESENT(glUniform3f);
    GL_CHECK_PRESENT(glDrawElements);

    gpuAPI->useVAO(_vaoLine2D);

    // Activate program
    glUseProgram(_programLine2D.id);
    GL_CHECK_RESULT;

    // Set projection*view*model matrix:
    glUniformMatrix4fv(_programLine2D.vs.param.mProjectionViewModel, 1, GL_FALSE, glm::value_ptr(internalState.mOrthographicProjection));
    GL_CHECK_RESULT;

    for(const auto& primitive : constOf(_lines2D))
    {
        const auto& line = primitive.first;
        const auto& color = primitive.second;

        // Set line color
        glUniform4f(_programLine2D.fs.param.color, SkColorGetR(color) / 255.0f, SkColorGetG(color) / 255.0f, SkColorGetB(color) / 255.0f, SkColorGetA(color) / 255.0f);
        GL_CHECK_RESULT;

        // Iterate over pairs of points
        auto itV0 = line.cbegin();
        auto itV1 = itV0 + 1;
        for(const auto itEnd = line.cend(); itV1 != itEnd; itV0 = itV1, ++itV1)
        {
            const auto& v0 = *itV0;
            const auto& v1 = *itV1;

            // Set line coordinates
            glUniform2f(_programLine2D.vs.param.v0, v0.x, currentState.windowSize.y - v0.y);
            GL_CHECK_RESULT;
            glUniform2f(_programLine2D.vs.param.v1, v1.x, currentState.windowSize.y - v1.y);
            GL_CHECK_RESULT;

            // Draw the line actually
            glDrawElements(GL_LINES, 2, GL_UNSIGNED_SHORT, nullptr);
            GL_CHECK_RESULT;
        }
    }

    // Deactivate program
    glUseProgram(0);
    GL_CHECK_RESULT;

    gpuAPI->unuseVAO();

    return true;
}
void OsmAnd::AtlasMapRendererDebugStage_OpenGL::renderQuads3D()
{
    const auto gpuAPI = getGPUAPI();

    GL_CHECK_PRESENT(glUseProgram);
    GL_CHECK_PRESENT(glUniformMatrix4fv);
    GL_CHECK_PRESENT(glUniform1f);
    GL_CHECK_PRESENT(glUniform2f);
    GL_CHECK_PRESENT(glUniform3f);
    GL_CHECK_PRESENT(glDrawElements);

    gpuAPI->glBindVertexArray_wrapper(_vaoQuad3D);
    GL_CHECK_RESULT;

    // Activate program
    glUseProgram(_programQuad3D.id);
    GL_CHECK_RESULT;

    // Set projection*view*model matrix:
    const auto& mProjectionView = internalState.mPerspectiveProjection * internalState.mCameraView;
    glUniformMatrix4fv(_programQuad3D.vs.param.mProjectionViewModel, 1, GL_FALSE, glm::value_ptr(mProjectionView));
    GL_CHECK_RESULT;

    for(const auto& primitive : constOf(_quads3D))
    {
        const auto& p0 = std::get<0>(primitive);
        const auto& p1 = std::get<1>(primitive);
        const auto& p2 = std::get<2>(primitive);
        const auto& p3 = std::get<3>(primitive);
        const auto& color = std::get<4>(primitive);

        // Set quad color
        glUniform4f(_programQuad3D.fs.param.color, SkColorGetR(color) / 255.0f, SkColorGetG(color) / 255.0f, SkColorGetB(color) / 255.0f, SkColorGetA(color) / 255.0f);
        GL_CHECK_RESULT;

        // Set points
        glUniform4f(_programQuad3D.vs.param.v0, p0.x, p0.y, p0.z, 1.0f);
        GL_CHECK_RESULT;
        glUniform4f(_programQuad3D.vs.param.v1, p1.x, p1.y, p1.z, 1.0f);
        GL_CHECK_RESULT;
        glUniform4f(_programQuad3D.vs.param.v2, p2.x, p2.y, p2.z, 1.0f);
        GL_CHECK_RESULT;
        glUniform4f(_programQuad3D.vs.param.v3, p3.x, p3.y, p3.z, 1.0f);
        GL_CHECK_RESULT;

        // Draw the quad actually
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
        GL_CHECK_RESULT;
    }

    // Deactivate program
    glUseProgram(0);
    GL_CHECK_RESULT;

    // Deselect VAO
    gpuAPI->glBindVertexArray_wrapper(0);
    GL_CHECK_RESULT;
}
Пример #15
0
bool OsmAnd::GPUAPI_OpenGLES2::isShaderPrecisionFormatSupported(GLenum shaderType, GLenum precisionType)
{
    GL_CHECK_PRESENT(glGetShaderPrecisionFormat);

    GLint range[] = { 0, 0 };
    GLint precision = 0;
    glGetShaderPrecisionFormat(shaderType, precisionType, range, &precision);
    GL_CHECK_RESULT;

    if (range[0] == 0 && range[1] == 0)
        return false;

    return true;
}
bool OsmAnd::GPUAPI_OpenGL_Common::uploadTileAsArrayBufferToGPU(const std::shared_ptr< const MapTile >& tile, std::shared_ptr< const ResourceInGPU >& resourceInGPU)
{
    GL_CHECK_PRESENT(glBindBuffer);
    GL_CHECK_PRESENT(glBufferData);

    if(tile->dataType != MapTileDataType::ElevationData)
    {
        assert(false);
        return false;
    }
    const auto elevationTile = std::static_pointer_cast<const MapElevationDataTile>(tile);
    
    // Create array buffer
    GLuint buffer;
    glGenBuffers(1, &buffer);
    GL_CHECK_RESULT;

    // Bind it
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    GL_CHECK_RESULT;

    // Upload data
    const auto itemsCount = tile->size*tile->size;
    assert(tile->size*sizeof(float) == tile->rowLength);
    glBufferData(GL_ARRAY_BUFFER, itemsCount*sizeof(float), tile->data, GL_STATIC_DRAW);
    GL_CHECK_RESULT;

    // Unbind it
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    GL_CHECK_RESULT;

    auto arrayBufferInGPU = new ArrayBufferInGPU(this, reinterpret_cast<RefInGPU>(buffer), itemsCount);
    resourceInGPU.reset(static_cast<ResourceInGPU*>(arrayBufferInGPU));

    return true;
}
Пример #17
0
void OsmAnd::GPUAPI_OpenGLES2::allocateTexture2D(GLenum target, GLsizei levels, GLsizei width, GLsizei height, const TextureFormat format)
{
    // Use glTexStorage2D if possible
    if (isSupported_EXT_texture_storage)
    {
        GL_CHECK_PRESENT(glTexStorage2DEXT);

        glTexStorage2DEXT(target, levels, static_cast<GLenum>(format), width, height);
        GL_CHECK_RESULT;
        return;
    }

    // Fallback to dumb allocation
    GPUAPI_OpenGL::allocateTexture2D(target, levels, width, height, format);
}
void OsmAnd::AtlasMapRendererDebugStage_OpenGL::renderRects2D()
{
    const auto gpuAPI = getGPUAPI();

    GL_CHECK_PRESENT(glUseProgram);
    GL_CHECK_PRESENT(glUniformMatrix4fv);
    GL_CHECK_PRESENT(glUniform1f);
    GL_CHECK_PRESENT(glUniform2f);
    GL_CHECK_PRESENT(glUniform3f);
    GL_CHECK_PRESENT(glDrawElements);

    gpuAPI->glBindVertexArray_wrapper(_vaoRect2D);
    GL_CHECK_RESULT;

    // Activate program
    glUseProgram(_programRect2D.id);
    GL_CHECK_RESULT;

    // Set projection*view*model matrix:
    glUniformMatrix4fv(_programRect2D.vs.param.mProjectionViewModel, 1, GL_FALSE, glm::value_ptr(internalState.mOrthographicProjection));
    GL_CHECK_RESULT;

    for(const auto& primitive : constOf(_rects2D))
    {
        const auto& rect = std::get<0>(primitive);
        const auto& color = std::get<1>(primitive);
        const auto& angle = std::get<2>(primitive);

        // Set rectangle coordinates
        const auto center = rect.center();
        glUniform4f(_programRect2D.vs.param.rect, currentState.windowSize.y - center.y, center.x, rect.height(), rect.width());
        GL_CHECK_RESULT;

        // Set rotation angle
        glUniform1f(_programRect2D.vs.param.angle, angle);
        GL_CHECK_RESULT;

        // Set rectangle color
        glUniform4f(_programRect2D.fs.param.color, SkColorGetR(color) / 255.0f, SkColorGetG(color) / 255.0f, SkColorGetB(color) / 255.0f, SkColorGetA(color) / 255.0f);
        GL_CHECK_RESULT;

        // Draw the rectangle actually
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
        GL_CHECK_RESULT;
    }

    // Deactivate program
    glUseProgram(0);
    GL_CHECK_RESULT;

    // Deselect VAO
    gpuAPI->glBindVertexArray_wrapper(0);
    GL_CHECK_RESULT;
}
void OsmAnd::AtlasMapRendererSkyStage_OpenGL::render()
{
    const auto gpuAPI = getGPUAPI();

    GL_PUSH_GROUP_MARKER(QLatin1String("sky"));

    GL_CHECK_PRESENT(glUseProgram);
    GL_CHECK_PRESENT(glUniformMatrix4fv);
    GL_CHECK_PRESENT(glUniform1f);
    GL_CHECK_PRESENT(glUniform2f);
    GL_CHECK_PRESENT(glUniform3f);
    GL_CHECK_PRESENT(glDrawElements);

    // Set sky plane VAO
    gpuAPI->glBindVertexArray_wrapper(_skyplaneVAO);
    GL_CHECK_RESULT;

    // Activate program
    glUseProgram(_program.id);
    GL_CHECK_RESULT;

    // Set projection*view*model matrix:
    const auto mFogTranslate = glm::translate(glm::vec3(0.0f, 0.0f, -internalState.correctedFogDistance));
    const auto mModel = internalState.mAzimuthInv * mFogTranslate;
    const auto mProjectionViewModel = internalState.mPerspectiveProjection * internalState.mCameraView * mModel;
    glUniformMatrix4fv(_program.vs.param.mProjectionViewModel, 1, GL_FALSE, glm::value_ptr(mProjectionViewModel));
    GL_CHECK_RESULT;

    // Set size of the skyplane
    glUniform2f(_program.vs.param.planeSize, internalState.skyplaneSize.x, internalState.skyplaneSize.y);
    GL_CHECK_RESULT;

    // Set sky parameters
    glUniform4f(_program.fs.param.skyColor, currentState.skyColor.r, currentState.skyColor.g, currentState.skyColor.b, 1.0f);
    GL_CHECK_RESULT;

    // Draw the skyplane actually
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
    GL_CHECK_RESULT;

    // Deactivate program
    glUseProgram(0);
    GL_CHECK_RESULT;

    // Deselect VAO
    gpuAPI->glBindVertexArray_wrapper(0);
    GL_CHECK_RESULT;

    GL_POP_GROUP_MARKER;
}
GLuint OsmAnd::GPUAPI_OpenGL_Common::compileShader( GLenum shaderType, const char* source )
{
    GL_CHECK_PRESENT(glCreateShader);
    GL_CHECK_PRESENT(glShaderSource);
    GL_CHECK_PRESENT(glCompileShader);
    GL_CHECK_PRESENT(glGetShaderiv);
    GL_CHECK_PRESENT(glGetShaderInfoLog);
    GL_CHECK_PRESENT(glDeleteShader);

    GLuint shader;

    shader = glCreateShader(shaderType);
    GL_CHECK_RESULT;

    const GLint sourceLen = static_cast<GLint>(strlen(source));
    glShaderSource(shader, 1, &source, &sourceLen);
    GL_CHECK_RESULT;

    glCompileShader(shader);
    GL_CHECK_RESULT;

    // Check if compiled
    GLint didCompile;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &didCompile);
    GL_CHECK_RESULT;
    if(didCompile != GL_TRUE)
    {
        GLint logBufferLen = 0;
        GLsizei logLen = 0;
        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logBufferLen);
        GL_CHECK_RESULT;
        if (logBufferLen > 1)
        {
            GLchar* log = (GLchar*)malloc(logBufferLen);
            glGetShaderInfoLog(shader, logBufferLen, &logLen, log);
            GL_CHECK_RESULT;
            assert(logLen + 1 == logBufferLen);
            LogPrintf(LogSeverityLevel::Error, "Failed to compile GLSL shader:\n%s\nSources:\n%s", log, source);
            free(log);
        }

        glDeleteShader(shader);
        shader = 0;
        return shader;
    }

    return shader;
}
void OsmAnd::AtlasMapRendererDebugStage_OpenGL::initializeQuads3D()
{
    const auto gpuAPI = getGPUAPI();

    GL_CHECK_PRESENT(glGenBuffers);
    GL_CHECK_PRESENT(glBindBuffer);
    GL_CHECK_PRESENT(glBufferData);
    GL_CHECK_PRESENT(glEnableVertexAttribArray);
    GL_CHECK_PRESENT(glVertexAttribPointer);

    // Compile vertex shader
    const QString vertexShader = QLatin1String(
        // Input data
        // (1.0, 0.0, 0.0, 0.0) for first point
        // (0.0, 1.0, 0.0, 0.0) for second point
        // (0.0, 0.0, 1.0, 0.0) for third point
        // (0.0, 0.0, 0.0, 1.0) for fourth point
        "INPUT vec4 in_vs_vertexPosition;                                                                                   ""\n"
        "                                                                                                                   ""\n"
        // Parameters: common data
        "uniform mat4 param_vs_mProjectionViewModel;                                                                        ""\n"
        "uniform vec4 param_vs_v0;                                                                                          ""\n"
        "uniform vec4 param_vs_v1;                                                                                          ""\n"
        "uniform vec4 param_vs_v2;                                                                                          ""\n"
        "uniform vec4 param_vs_v3;                                                                                          ""\n"
        "                                                                                                                   ""\n"
        "void main()                                                                                                        ""\n"
        "{                                                                                                                  ""\n"
        "    vec4 v =                                                                                                       ""\n"
        "        in_vs_vertexPosition.x*param_vs_v0 +                                                                       ""\n"
        "        in_vs_vertexPosition.y*param_vs_v1 +                                                                       ""\n"
        "        in_vs_vertexPosition.z*param_vs_v2 +                                                                       ""\n"
        "        in_vs_vertexPosition.w*param_vs_v3;                                                                        ""\n"
        "                                                                                                                   ""\n"
        "    gl_Position = param_vs_mProjectionViewModel * v;                                                               ""\n"
        "}                                                                                                                  ""\n");
    auto preprocessedVertexShader = vertexShader;
    gpuAPI->preprocessVertexShader(preprocessedVertexShader);
    gpuAPI->optimizeVertexShader(preprocessedVertexShader);
    const auto vsId = gpuAPI->compileShader(GL_VERTEX_SHADER, qPrintable(preprocessedVertexShader));
    assert(vsId != 0);

    // Compile fragment shader
    const QString fragmentShader = QLatin1String(
        // Parameters: common data
        "uniform lowp vec4 param_fs_color;                                                                                  ""\n"
        "                                                                                                                   ""\n"
        "void main()                                                                                                        ""\n"
        "{                                                                                                                  ""\n"
        "    FRAGMENT_COLOR_OUTPUT = param_fs_color;                                                                        ""\n"
        "}                                                                                                                  ""\n");
    auto preprocessedFragmentShader = fragmentShader;
    QString preprocessedFragmentShader_UnrolledPerLayerProcessingCode;
    gpuAPI->preprocessFragmentShader(preprocessedFragmentShader);
    gpuAPI->optimizeFragmentShader(preprocessedFragmentShader);
    const auto fsId = gpuAPI->compileShader(GL_FRAGMENT_SHADER, qPrintable(preprocessedFragmentShader));
    assert(fsId != 0);

    // Link everything into program object
    GLuint shaders[] = { vsId, fsId };
    _programQuad3D.id = gpuAPI->linkProgram(2, shaders);
    assert(_programQuad3D.id);

    const auto& lookup = gpuAPI->obtainVariablesLookupContext(_programQuad3D.id);
    lookup->lookupLocation(_programQuad3D.vs.in.vertexPosition, "in_vs_vertexPosition", GLShaderVariableType::In);
    lookup->lookupLocation(_programQuad3D.vs.param.mProjectionViewModel, "param_vs_mProjectionViewModel", GLShaderVariableType::Uniform);
    lookup->lookupLocation(_programQuad3D.vs.param.v0, "param_vs_v0", GLShaderVariableType::Uniform);
    lookup->lookupLocation(_programQuad3D.vs.param.v1, "param_vs_v1", GLShaderVariableType::Uniform);
    lookup->lookupLocation(_programQuad3D.vs.param.v2, "param_vs_v2", GLShaderVariableType::Uniform);
    lookup->lookupLocation(_programQuad3D.vs.param.v3, "param_vs_v3", GLShaderVariableType::Uniform);
    lookup->lookupLocation(_programQuad3D.fs.param.color, "param_fs_color", GLShaderVariableType::Uniform);

    // Vertex data (x,y,z,w)
    float vertices[4][4] =
    {
        { 1.0f, 0.0f, 0.0f, 0.0f },
        { 0.0f, 1.0f, 0.0f, 0.0f },
        { 0.0f, 0.0f, 1.0f, 0.0f },
        { 0.0f, 0.0f, 0.0f, 1.0f }
    };
    const auto verticesCount = 4;

    // Index data
    GLushort indices[6] =
    {
        0, 1, 2,
        0, 2, 3
    };
    const auto indicesCount = 6;

    // Create Vertex Array Object
    gpuAPI->glGenVertexArrays_wrapper(1, &_vaoQuad3D);
    GL_CHECK_RESULT;
    gpuAPI->glBindVertexArray_wrapper(_vaoQuad3D);
    GL_CHECK_RESULT;

    // Create vertex buffer and associate it with VAO
    glGenBuffers(1, &_vboQuad3D);
    GL_CHECK_RESULT;
    glBindBuffer(GL_ARRAY_BUFFER, _vboQuad3D);
    GL_CHECK_RESULT;
    glBufferData(GL_ARRAY_BUFFER, verticesCount * sizeof(float)*4, vertices, GL_STATIC_DRAW);
    GL_CHECK_RESULT;
    glEnableVertexAttribArray(*_programQuad3D.vs.in.vertexPosition);
    GL_CHECK_RESULT;
    glVertexAttribPointer(*_programQuad3D.vs.in.vertexPosition, 4, GL_FLOAT, GL_FALSE, sizeof(float)*4, nullptr);
    GL_CHECK_RESULT;

    // Create index buffer and associate it with VAO
    glGenBuffers(1, &_iboQuad3D);
    GL_CHECK_RESULT;
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iboQuad3D);
    GL_CHECK_RESULT;
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesCount * sizeof(GLushort), indices, GL_STATIC_DRAW);
    GL_CHECK_RESULT;

    gpuAPI->glBindVertexArray_wrapper(0);
    GL_CHECK_RESULT;
}
void OsmAnd::AtlasMapRendererDebugStage_OpenGL::initializeRects2D()
{
    const auto gpuAPI = getGPUAPI();

    GL_CHECK_PRESENT(glGenBuffers);
    GL_CHECK_PRESENT(glBindBuffer);
    GL_CHECK_PRESENT(glBufferData);
    GL_CHECK_PRESENT(glEnableVertexAttribArray);
    GL_CHECK_PRESENT(glVertexAttribPointer);

    // Compile vertex shader
    const QString vertexShader = QLatin1String(
        // Input data
        "INPUT vec2 in_vs_vertexPosition;                                                                                   ""\n"
        "                                                                                                                   ""\n"
        // Parameters: common data
        "uniform mat4 param_vs_mProjectionViewModel;                                                                        ""\n"
        "uniform vec4 param_vs_rect;                                                                                        ""\n"
        "uniform float param_vs_angle;                                                                                      ""\n"
        "                                                                                                                   ""\n"
        "void main()                                                                                                        ""\n"
        "{                                                                                                                  ""\n"
        "    vec2 rectCenter = param_vs_rect.yx;                                                                            ""\n"
        "    vec2 p = in_vs_vertexPosition*param_vs_rect.wz + rectCenter;                                                   ""\n"
        "    vec4 v;                                                                                                        ""\n"
        "    float cos_a = cos(param_vs_angle);                                                                             ""\n"
        "    float sin_a = sin(param_vs_angle);                                                                             ""\n"
        "    p -= rectCenter;                                                                                               ""\n"
        "    v.x = rectCenter.x + p.x*cos_a - p.y*sin_a;                                                                    ""\n"
        "    v.y = rectCenter.y + p.x*sin_a + p.y*cos_a;                                                                    ""\n"
        "    v.z = -1.0;                                                                                                    ""\n"
        "    v.w = 1.0;                                                                                                     ""\n"
        "                                                                                                                   ""\n"
        "    gl_Position = param_vs_mProjectionViewModel * v;                                                               ""\n"
        "}                                                                                                                  ""\n");
    auto preprocessedVertexShader = vertexShader;
    gpuAPI->preprocessVertexShader(preprocessedVertexShader);
    gpuAPI->optimizeVertexShader(preprocessedVertexShader);
    const auto vsId = gpuAPI->compileShader(GL_VERTEX_SHADER, qPrintable(preprocessedVertexShader));
    assert(vsId != 0);

    // Compile fragment shader
    const QString fragmentShader = QLatin1String(
        // Parameters: common data
        "uniform lowp vec4 param_fs_color;                                                                                  ""\n"
        "                                                                                                                   ""\n"
        "void main()                                                                                                        ""\n"
        "{                                                                                                                  ""\n"
        "    FRAGMENT_COLOR_OUTPUT = param_fs_color;                                                                        ""\n"
        "}                                                                                                                  ""\n");
    auto preprocessedFragmentShader = fragmentShader;
    QString preprocessedFragmentShader_UnrolledPerLayerProcessingCode;
    gpuAPI->preprocessFragmentShader(preprocessedFragmentShader);
    gpuAPI->optimizeFragmentShader(preprocessedFragmentShader);
    const auto fsId = gpuAPI->compileShader(GL_FRAGMENT_SHADER, qPrintable(preprocessedFragmentShader));
    assert(fsId != 0);

    // Link everything into program object
    GLuint shaders[] = { vsId, fsId };
    _programRect2D.id = gpuAPI->linkProgram(2, shaders);
    assert(_programRect2D.id);

    const auto& lookup = gpuAPI->obtainVariablesLookupContext(_programRect2D.id);
    lookup->lookupLocation(_programRect2D.vs.in.vertexPosition, "in_vs_vertexPosition", GLShaderVariableType::In);
    lookup->lookupLocation(_programRect2D.vs.param.mProjectionViewModel, "param_vs_mProjectionViewModel", GLShaderVariableType::Uniform);
    lookup->lookupLocation(_programRect2D.vs.param.rect, "param_vs_rect", GLShaderVariableType::Uniform);
    lookup->lookupLocation(_programRect2D.vs.param.angle, "param_vs_angle", GLShaderVariableType::Uniform);
    lookup->lookupLocation(_programRect2D.fs.param.color, "param_fs_color", GLShaderVariableType::Uniform);

    // Vertex data (x,y)
    float vertices[4][2] =
    {
        { -0.5f, -0.5f },
        { -0.5f,  0.5f },
        {  0.5f,  0.5f },
        {  0.5f, -0.5f }
    };
    const auto verticesCount = 4;

    // Index data
    GLushort indices[6] =
    {
        0, 1, 2,
        0, 2, 3
    };
    const auto indicesCount = 6;

    // Create Vertex Array Object
    gpuAPI->glGenVertexArrays_wrapper(1, &_vaoRect2D);
    GL_CHECK_RESULT;
    gpuAPI->glBindVertexArray_wrapper(_vaoRect2D);
    GL_CHECK_RESULT;

    // Create vertex buffer and associate it with VAO
    glGenBuffers(1, &_vboRect2D);
    GL_CHECK_RESULT;
    glBindBuffer(GL_ARRAY_BUFFER, _vboRect2D);
    GL_CHECK_RESULT;
    glBufferData(GL_ARRAY_BUFFER, verticesCount * sizeof(float)* 2, vertices, GL_STATIC_DRAW);
    GL_CHECK_RESULT;
    glEnableVertexAttribArray(*_programRect2D.vs.in.vertexPosition);
    GL_CHECK_RESULT;
    glVertexAttribPointer(*_programRect2D.vs.in.vertexPosition, 2, GL_FLOAT, GL_FALSE, sizeof(float)* 2, nullptr);
    GL_CHECK_RESULT;

    // Create index buffer and associate it with VAO
    glGenBuffers(1, &_iboRect2D);
    GL_CHECK_RESULT;
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iboRect2D);
    GL_CHECK_RESULT;
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesCount * sizeof(GLushort), indices, GL_STATIC_DRAW);
    GL_CHECK_RESULT;

    gpuAPI->glBindVertexArray_wrapper(0);
    GL_CHECK_RESULT;
}
bool OsmAnd::AtlasMapRenderer_OpenGL::doRenderFrame()
{
    GL_PUSH_GROUP_MARKER(QLatin1String("OsmAndCore"));

    GL_CHECK_PRESENT(glViewport);
    GL_CHECK_PRESENT(glEnable);
    GL_CHECK_PRESENT(glDisable);
    GL_CHECK_PRESENT(glBlendFunc);
    GL_CHECK_PRESENT(glClear);

#if OSMAND_DEBUG
    _debugStage.clear();
#endif

    // Setup viewport
    glViewport(
        currentState.viewport.left,
        currentState.windowSize.y - currentState.viewport.bottom,
        currentState.viewport.width(),
        currentState.viewport.height());
    GL_CHECK_RESULT;

    // Clear buffers
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    GL_CHECK_RESULT;

    // Turn off blending for sky and map stages
    glDisable(GL_BLEND);
    GL_CHECK_RESULT;

    // Turn on depth testing for sky stage (since with disabled depth test, write to depth buffer is blocked),
    // but since sky is on top of everything, accept all fragments
    glEnable(GL_DEPTH_TEST);
    GL_CHECK_RESULT;
    glDepthFunc(GL_ALWAYS);
    GL_CHECK_RESULT;

    // Render the sky
    _skyStage.render();

    // Change depth test function prior to raster map stage and further stages
    glDepthFunc(GL_LEQUAL);
    GL_CHECK_RESULT;

    // Raster map stage is rendered without blending, since it's done in fragment shader
    _rasterMapStage.render();

    // Turn on blending since now objects with transparency are going to be rendered
    glEnable(GL_BLEND);
    GL_CHECK_RESULT;
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    GL_CHECK_RESULT;

    // Render map symbols without writing depth buffer, since symbols use own sorting and intersection checking
    //NOTE: Currently map symbols are incompatible with height-maps
    glDepthMask(GL_FALSE);
    GL_CHECK_RESULT;
    _symbolsStage.render();
    glDepthMask(GL_TRUE);
    GL_CHECK_RESULT;

    //TODO: render special fog object some day

#if OSMAND_DEBUG
    glDisable(GL_DEPTH_TEST);
    GL_CHECK_RESULT;

    _debugStage.render();

    glEnable(GL_DEPTH_TEST);
    GL_CHECK_RESULT;
#endif

    GL_POP_GROUP_MARKER;

    return true;
}
GLuint OsmAnd::GPUAPI_OpenGL_Common::linkProgram( GLuint shadersCount, GLuint *shaders )
{
    GL_CHECK_PRESENT(glCreateProgram);
    GL_CHECK_PRESENT(glAttachShader);
    GL_CHECK_PRESENT(glLinkProgram);
    GL_CHECK_PRESENT(glGetProgramiv);
    GL_CHECK_PRESENT(glGetProgramInfoLog);
    GL_CHECK_PRESENT(glDeleteProgram);

    GLuint program = 0;

    program = glCreateProgram();
    GL_CHECK_RESULT;

    for(auto shaderIdx = 0u; shaderIdx < shadersCount; shaderIdx++)
    {
        glAttachShader(program, shaders[shaderIdx]);
        GL_CHECK_RESULT;
    }

    glLinkProgram(program);
    GL_CHECK_RESULT;

    GLint linkSuccessful;
    glGetProgramiv(program, GL_LINK_STATUS, &linkSuccessful);
    GL_CHECK_RESULT;
    if(linkSuccessful != GL_TRUE)
    {
        GLint logBufferLen = 0;
        GLsizei logLen = 0;
        glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logBufferLen);
        GL_CHECK_RESULT;
        if (logBufferLen > 1)
        {
            GLchar* log = (GLchar*)malloc(logBufferLen);
            glGetProgramInfoLog(program, logBufferLen, &logLen, log);
            GL_CHECK_RESULT;
            assert(logLen + 1 == logBufferLen);
            LogPrintf(LogSeverityLevel::Error, "Failed to link GLSL program:\n%s", log);
            free(log);
        }

        glDeleteProgram(program);
        GL_CHECK_RESULT;
        program = 0;
        return program;
    }

    // Show some info
    GLint attributesCount;
    glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &attributesCount);
    GL_CHECK_RESULT;
    LogPrintf(LogSeverityLevel::Info, "GLSL program %d has %d input variable(s)", program, attributesCount);

    GLint uniformsCount;
    glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniformsCount);
    GL_CHECK_RESULT;
    LogPrintf(LogSeverityLevel::Info, "GLSL program %d has %d parameter variable(s)", program, uniformsCount);

    return program;
}
Пример #25
0
void OsmAnd::GPUAPI_OpenGLES2::glClearDepth_wrapper(const float depth)
{
    GL_CHECK_PRESENT(glClearDepthf);

    glClearDepthf(depth);
}
Пример #26
0
void OsmAnd::GPUAPI_OpenGLES2::glPopGroupMarkerEXT_wrapper()
{
    GL_CHECK_PRESENT(glPopGroupMarkerEXT);
    glPopGroupMarkerEXT();
}
Пример #27
0
void OsmAnd::GPUAPI_OpenGLES2::glPushGroupMarkerEXT_wrapper(GLsizei length, const GLchar* marker)
{
    GL_CHECK_PRESENT(glPushGroupMarkerEXT);
    glPushGroupMarkerEXT(length, marker);
}
bool OsmAnd::GPUAPI_OpenGL_Common::uploadSymbolAsTextureToGPU(const std::shared_ptr< const MapSymbol >& symbol, std::shared_ptr< const ResourceInGPU >& resourceInGPU)
{
    GL_CHECK_PRESENT(glGenTextures);
    GL_CHECK_PRESENT(glBindTexture);
    GL_CHECK_PRESENT(glGenerateMipmap);
    GL_CHECK_PRESENT(glTexParameteri);

    // Determine texture properties:
    GLsizei sourcePixelByteSize = 0;
    bool symbolUsesPalette = false;
    switch(symbol->bitmap->getConfig())
    {
    case SkBitmap::Config::kARGB_8888_Config:
        sourcePixelByteSize = 4;
        break;
    case SkBitmap::Config::kARGB_4444_Config:
    case SkBitmap::Config::kRGB_565_Config:
        sourcePixelByteSize = 2;
        break;
    case SkBitmap::Config::kIndex8_Config:
        sourcePixelByteSize = 1;
        symbolUsesPalette = true;
        break;
    default:
        assert(false);
        return false;
    }
    const auto textureFormat = getTextureFormat(symbol);

    // Symbols don't use mipmapping, so there is no difference between POT vs NPOT size of texture.
    // In OpenGLES 2.0 and OpenGL 3.0+, NPOT textures are supported in general.
    // OpenGLES 2.0 has some limitations without isSupported_texturesNPOT:
    //  - no mipmaps
    //  - only LINEAR or NEAREST minification filter.

    // Create texture id
    GLuint texture;
    glGenTextures(1, &texture);
    GL_CHECK_RESULT;
    assert(texture != 0);

    // Activate texture
    glBindTexture(GL_TEXTURE_2D, texture);
    GL_CHECK_RESULT;

    if(!symbolUsesPalette)
    {
        // Allocate square 2D texture
        allocateTexture2D(GL_TEXTURE_2D, 1, symbol->bitmap->width(), symbol->bitmap->height(), textureFormat);

        // Upload data
        uploadDataToTexture2D(GL_TEXTURE_2D, 0,
            0, 0, (GLsizei)symbol->bitmap->width(), (GLsizei)symbol->bitmap->height(),
            symbol->bitmap->getPixels(), symbol->bitmap->rowBytes() / sourcePixelByteSize, sourcePixelByteSize,
            getSourceFormat(symbol));

        // Set maximal mipmap level to 0
        setMipMapLevelsLimit(GL_TEXTURE_2D, 0);
    }
    else
    {
        //TODO: palettes are not yet supported
        assert(false);
    }

    // Deselect atlas as active texture
    glBindTexture(GL_TEXTURE_2D, 0);
    GL_CHECK_RESULT;

    // Create resource-in-GPU descriptor
    const auto textureInGPU = new TextureInGPU(this, reinterpret_cast<RefInGPU>(texture), symbol->bitmap->width(), symbol->bitmap->height(), 1);
    resourceInGPU.reset(static_cast<ResourceInGPU*>(textureInGPU));

    return true;
}
Пример #29
0
void OsmAnd::GPUAPI_OpenGLES2::applyTextureBlockToTexture(const GLenum texture, const GLenum textureBlock)
{
    GL_CHECK_PRESENT(glTexParameteri);

    const auto samplerType = _textureBlocksSamplers[textureBlock];
    if (samplerType == SamplerType::ElevationDataTile)
    {
        glTexParameteri(texture, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        GL_CHECK_RESULT;
        glTexParameteri(texture, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        GL_CHECK_RESULT;
        glTexParameteri(texture, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        GL_CHECK_RESULT;
        glTexParameteri(texture, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        GL_CHECK_RESULT;
    }
    else if (samplerType == SamplerType::BitmapTile_Bilinear)
    {
        glTexParameteri(texture, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        GL_CHECK_RESULT;
        glTexParameteri(texture, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        GL_CHECK_RESULT;
        glTexParameteri(texture, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        GL_CHECK_RESULT;
        glTexParameteri(texture, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        GL_CHECK_RESULT;
    }
    else if (samplerType == SamplerType::BitmapTile_BilinearMipmap)
    {
        glTexParameteri(texture, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        GL_CHECK_RESULT;
        glTexParameteri(texture, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        GL_CHECK_RESULT;
        glTexParameteri(texture, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
        GL_CHECK_RESULT;
        glTexParameteri(texture, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        GL_CHECK_RESULT;
    }
    else if (samplerType == SamplerType::BitmapTile_TrilinearMipmap)
    {
        glTexParameteri(texture, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        GL_CHECK_RESULT;
        glTexParameteri(texture, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        GL_CHECK_RESULT;
        glTexParameteri(texture, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
        GL_CHECK_RESULT;
        glTexParameteri(texture, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        GL_CHECK_RESULT;
    }
    else if (samplerType == SamplerType::Symbol)
    {
        glTexParameteri(texture, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        GL_CHECK_RESULT;
        glTexParameteri(texture, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        GL_CHECK_RESULT;
        glTexParameteri(texture, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        GL_CHECK_RESULT;
        glTexParameteri(texture, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        GL_CHECK_RESULT;
    }
}
bool OsmAnd::AtlasMapRendererDebugStage_OpenGL::initializeLines3D()
{
    const auto gpuAPI = getGPUAPI();

    GL_CHECK_PRESENT(glGenBuffers);
    GL_CHECK_PRESENT(glBindBuffer);
    GL_CHECK_PRESENT(glBufferData);
    GL_CHECK_PRESENT(glEnableVertexAttribArray);
    GL_CHECK_PRESENT(glVertexAttribPointer);
    GL_CHECK_PRESENT(glDeleteShader);
    GL_CHECK_PRESENT(glDeleteProgram);

    // Compile vertex shader
    const QString vertexShader = QLatin1String(
        // Input data
        "INPUT vec2 in_vs_vertexPosition; // (1.0, 0.0) for first point, (0.0, 1.0) for second                              ""\n"
        "                                                                                                                   ""\n"
        // Parameters: common data
        "uniform mat4 param_vs_mProjectionViewModel;                                                                        ""\n"
        "uniform vec4 param_vs_v0;                                                                                          ""\n"
        "uniform vec4 param_vs_v1;                                                                                          ""\n"
        "                                                                                                                   ""\n"
        "void main()                                                                                                        ""\n"
        "{                                                                                                                  ""\n"
        "    vec4 v;                                                                                                        ""\n"
        "    v = in_vs_vertexPosition.x*param_vs_v0 + in_vs_vertexPosition.y*param_vs_v1;                                   ""\n"
        "                                                                                                                   ""\n"
        "    gl_Position = param_vs_mProjectionViewModel * v;                                                               ""\n"
        "}                                                                                                                  ""\n");
    auto preprocessedVertexShader = vertexShader;
    gpuAPI->preprocessVertexShader(preprocessedVertexShader);
    gpuAPI->optimizeVertexShader(preprocessedVertexShader);
    const auto vsId = gpuAPI->compileShader(GL_VERTEX_SHADER, qPrintable(preprocessedVertexShader));
    if (vsId == 0)
    {
        LogPrintf(LogSeverityLevel::Error,
            "Failed to compile AtlasMapRendererDebugStage_OpenGL vertex shader");
        return false;
    }

    // Compile fragment shader
    const QString fragmentShader = QLatin1String(
        // Parameters: common data
        "uniform lowp vec4 param_fs_color;                                                                                  ""\n"
        "                                                                                                                   ""\n"
        "void main()                                                                                                        ""\n"
        "{                                                                                                                  ""\n"
        "    FRAGMENT_COLOR_OUTPUT = param_fs_color;                                                                        ""\n"
        "}                                                                                                                  ""\n");
    auto preprocessedFragmentShader = fragmentShader;
    QString preprocessedFragmentShader_UnrolledPerLayerProcessingCode;
    gpuAPI->preprocessFragmentShader(preprocessedFragmentShader);
    gpuAPI->optimizeFragmentShader(preprocessedFragmentShader);
    const auto fsId = gpuAPI->compileShader(GL_FRAGMENT_SHADER, qPrintable(preprocessedFragmentShader));
    if (fsId == 0)
    {
        glDeleteShader(vsId);
        GL_CHECK_RESULT;

        LogPrintf(LogSeverityLevel::Error,
            "Failed to compile AtlasMapRendererDebugStage_OpenGL fragment shader");
        return false;
    }

    // Link everything into program object
    GLuint shaders[] = { vsId, fsId };
    QHash< QString, GPUAPI_OpenGL::GlslProgramVariable > variablesMap;
    _programLine3D.id = gpuAPI->linkProgram(2, shaders, true, &variablesMap);
    if (!_programLine3D.id.isValid())
    {
        LogPrintf(LogSeverityLevel::Error,
            "Failed to link AtlasMapRendererDebugStage_OpenGL program");
        return false;
    }

    bool ok = true;
    const auto& lookup = gpuAPI->obtainVariablesLookupContext(_programLine3D.id, variablesMap);
    ok = ok && lookup->lookupLocation(_programLine3D.vs.in.vertexPosition, "in_vs_vertexPosition", GlslVariableType::In);
    ok = ok && lookup->lookupLocation(_programLine3D.vs.param.mProjectionViewModel, "param_vs_mProjectionViewModel", GlslVariableType::Uniform);
    ok = ok && lookup->lookupLocation(_programLine3D.vs.param.v0, "param_vs_v0", GlslVariableType::Uniform);
    ok = ok && lookup->lookupLocation(_programLine3D.vs.param.v1, "param_vs_v1", GlslVariableType::Uniform);
    ok = ok && lookup->lookupLocation(_programLine3D.fs.param.color, "param_fs_color", GlslVariableType::Uniform);
    if (!ok)
    {
        glDeleteProgram(_programLine3D.id);
        GL_CHECK_RESULT;
        _programLine3D.id.reset();

        return false;
    }

    // Vertex data (x,y)
    float vertices[2][2] =
    {
        { 1.0f, 0.0f },
        { 0.0f, 1.0f }
    };
    const auto verticesCount = 2;

    // Index data
    GLushort indices[2] =
    {
        0, 1
    };
    const auto indicesCount = 2;

    _vaoLine3D = gpuAPI->allocateUninitializedVAO();

    // Create vertex buffer and associate it with VAO
    glGenBuffers(1, &_vboLine3D);
    GL_CHECK_RESULT;
    glBindBuffer(GL_ARRAY_BUFFER, _vboLine3D);
    GL_CHECK_RESULT;
    glBufferData(GL_ARRAY_BUFFER, verticesCount * sizeof(float)* 2, vertices, GL_STATIC_DRAW);
    GL_CHECK_RESULT;
    glEnableVertexAttribArray(*_programLine3D.vs.in.vertexPosition);
    GL_CHECK_RESULT;
    glVertexAttribPointer(*_programLine3D.vs.in.vertexPosition, 2, GL_FLOAT, GL_FALSE, sizeof(float)* 2, nullptr);
    GL_CHECK_RESULT;

    // Create index buffer and associate it with VAO
    glGenBuffers(1, &_iboLine3D);
    GL_CHECK_RESULT;
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iboLine3D);
    GL_CHECK_RESULT;
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesCount * sizeof(GLushort), indices, GL_STATIC_DRAW);
    GL_CHECK_RESULT;

    gpuAPI->initializeVAO(_vaoLine3D);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    GL_CHECK_RESULT;
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    GL_CHECK_RESULT;

    return true;
}