summaryrefslogtreecommitdiff
path: root/src/mbgl/renderer/painter_debug.cpp
blob: 9ddae289ee2ab4c4a1bce783d494832cb5bcc8ca (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include <mbgl/renderer/painter.hpp>
#include <mbgl/renderer/debug_bucket.hpp>
#include <mbgl/renderer/render_tile.hpp>
#include <mbgl/tile/tile.hpp>
#include <mbgl/shader/plain_shader.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/gl/debugging.hpp>
#include <mbgl/gl/gl.hpp>
#include <mbgl/gl/gl_values.hpp>
#include <mbgl/gl/gl_helper.hpp>
#include <mbgl/util/color.hpp>

using namespace mbgl;

void Painter::renderTileDebug(const RenderTile& tile) {
    MBGL_DEBUG_GROUP(std::string { "debug " } + util::toString(tile.id));
    if (frame.debugOptions != MapDebugOptions::NoDebug) {
        setClipping(tile.clip);
        if (frame.debugOptions & (MapDebugOptions::Timestamps | MapDebugOptions::ParseStatus)) {
            renderDebugText(tile.tile, tile.matrix);
        }
        if (frame.debugOptions & MapDebugOptions::TileBorders) {
            renderDebugFrame(tile.matrix);
        }
    }
}

void Painter::renderDebugText(Tile& tile, const mat4 &matrix) {
    MBGL_DEBUG_GROUP("debug text");

    config.depthTest = GL_FALSE;

    if (!tile.debugBucket || tile.debugBucket->renderable != tile.isRenderable() ||
        tile.debugBucket->complete != tile.isComplete() ||
        !(tile.debugBucket->modified == tile.modified) ||
        !(tile.debugBucket->expires == tile.expires) ||
        tile.debugBucket->debugMode != frame.debugOptions) {
        tile.debugBucket = std::make_unique<DebugBucket>(
            tile.id, tile.isRenderable(), tile.isComplete(), tile.modified,
            tile.expires, frame.debugOptions);
    }

    config.program = plainShader->getID();
    plainShader->u_matrix = matrix;

    // Draw white outline
    plainShader->u_color = Color::white();
    config.lineWidth = 4.0f * frame.pixelRatio;
    tile.debugBucket->drawLines(*plainShader, store);

#ifndef GL_ES_VERSION_2_0
    // Draw line "end caps"
    MBGL_CHECK_ERROR(glPointSize(2));
    tile.debugBucket->drawPoints(*plainShader, store);
#endif

    // Draw black text.
    plainShader->u_color = Color::black();
    config.lineWidth = 2.0f * frame.pixelRatio;
    tile.debugBucket->drawLines(*plainShader, store);

    config.depthFunc.reset();
    config.depthTest = GL_TRUE;
}

void Painter::renderDebugFrame(const mat4 &matrix) {
    MBGL_DEBUG_GROUP("debug frame");

    // Disable depth test and don't count this towards the depth buffer,
    // but *don't* disable stencil test, as we want to clip the red tile border
    // to the tile viewport.
    config.depthTest = GL_FALSE;
    config.stencilOp.reset();
    config.stencilTest = GL_TRUE;

    config.program = plainShader->getID();
    plainShader->u_matrix = matrix;

    // draw tile outline
    tileBorderArray.bind(*plainShader, tileBorderBuffer, BUFFER_OFFSET_0, store);
    plainShader->u_color = { 1.0f, 0.0f, 0.0f, 1.0f };
    config.lineWidth = 4.0f * frame.pixelRatio;
    MBGL_CHECK_ERROR(glDrawArrays(GL_LINE_STRIP, 0, (GLsizei)tileBorderBuffer.index()));
}

void Painter::renderClipMasks() {
    config.stencilTest = GL_FALSE;
    config.depthTest = GL_FALSE;
    config.program = 0;
    config.colorMask = { GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE };

#ifndef GL_ES_VERSION_2_0
    config.pixelZoom = { 1, 1 };
    config.rasterPos = {{ -1, -1, 0, 0 }};

    // Read the stencil buffer
    const auto& fbSize = frame.framebufferSize;
    auto pixels = std::make_unique<uint8_t[]>(fbSize[0] * fbSize[1]);
    MBGL_CHECK_ERROR(glReadPixels(
                0,                // GLint x
                0,                // GLint y
                fbSize[0],        // GLsizei width
                fbSize[1],        // GLsizei height
                GL_STENCIL_INDEX, // GLenum format
                GL_UNSIGNED_BYTE, // GLenum type
                pixels.get()      // GLvoid * data
                ));

    // Scale the Stencil buffer to cover the entire color space.
    auto it = pixels.get();
    auto end = it + fbSize[0] * fbSize[1];
    const auto factor = 255.0f / *std::max_element(it, end);
    for (; it != end; ++it) {
        *it *= factor;
    }

    MBGL_CHECK_ERROR(glWindowPos2i(0, 0));
    MBGL_CHECK_ERROR(glDrawPixels(fbSize[0], fbSize[1], GL_LUMINANCE, GL_UNSIGNED_BYTE, pixels.get()));
#endif // GL_ES_VERSION_2_0
}