raspberrypi / bookworm-feedback

13 stars 1 forks source link

OpenGL invalid rendering (rendering artefacts) #260

Open qrp73 opened 3 months ago

qrp73 commented 3 months ago

I catch some issue with OpenGL rendering, originally I found it when used ImGui library. It appears that some pixels are not rendered on Raspberry Pi when line is drawn. But detailed investigation shows that this issue happens in OpenGL rendering driver on Raspberry Pi.

Test code:

test.cpp:

#include <stdio.h>
#include <math.h>
#include <GLFW/glfw3.h>

void drawLine(float sx, float sy, float ex, float ey, float strokeWidth) {
    sx+=0.5f; sy+=0.5f; ex+=0.5f; ey+=0.5f;
    float dx = ex - sx;
    float dy = ey - sy;
    float dl = std::sqrt(dx * dx + dy * dy);
    float nx = dy / dl * strokeWidth / 2.0f;
    float ny = -dx / dl * strokeWidth / 2.0f;
    glBegin(GL_QUADS);
        glVertex2f(sx - nx, sy - ny);
        glVertex2f(sx + nx, sy + ny);
        glVertex2f(ex + nx, ey + ny);
        glVertex2f(ex - nx, ey - ny);
    glEnd();
}
void drawRectInt(float x, float y, float w, float h) {
    x+=0.5f; y+=0.5f;
    glVertex2f(x, y);
    glVertex2f(x + w, y);
    glVertex2f(x + w, y + h);
    glVertex2f(x, y + h);
}
void fillRect(float x, float y, float w, float h) {
    glBegin(GL_QUADS);
        drawRectInt(x, y, w, h);
    glEnd();
}

static void glfw_error_callback(int error, const char* description) {
    fprintf(stderr, "GLFW Error %d: %s\n", error, description);
}

int main(int, char**) {
    glfwSetErrorCallback(glfw_error_callback);
    if (!glfwInit())
        return 1;
    fprintf(stdout, "GLFW:   %s\n", glfwGetVersionString());
    //glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    //glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
    glfwWindowHint(GLFW_SAMPLES, 0);//4); // 4x AA
    GLFWwindow* window = glfwCreateWindow(420, 210, "TEST GLFW", NULL, NULL);
    if (window == NULL)
        return 1;
    glfwMakeContextCurrent(window);
    glfwSwapInterval(1);
    fprintf(stdout, "OpenGL: %s\n", glGetString(GL_VERSION));
    fprintf(stdout, "GLSL:   %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION));

    glClearColor(0, 0, 1, 1);
    while (!glfwWindowShouldClose(window)) {
        glfwPollEvents();
        int display_w, display_h;
        glfwGetFramebufferSize(window, &display_w, &display_h);

        glViewport(0, 0, display_w, display_h);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0, display_w, display_h, 0, -1, 1);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glClear(GL_COLOR_BUFFER_BIT);

        glColor3f(0,0,0);
        fillRect(0,0, display_w, display_h);

        auto thickness = 1;

        glColor3f(1,1,1);
        // simple line test
        for (auto y=2; y < 8; y++) {
            drawLine(5, y, 209, y, thickness);
            drawLine(210, y, 415, y, thickness);
        }
        // more complex test pattern (left)
        auto stepy = 1;
        for (auto y=10; y < 200; y+=stepy,stepy++) {
            auto stepx=1;
            for (auto x=10; x < 200; x+=stepx,stepx++) {
                drawLine(x,   y,
                    x+stepx-1, y,
                    thickness);
                drawLine(x,   y,
                    x,   y+stepy-1,
                    thickness);
                drawLine(x,   y,
                    x+stepx-1, y+stepy-1,
                    thickness);
            }
        }
        // second complex test pattern (right)
        for (auto y=10; y < 200; y+=2) {
            for (auto x=210+10; x < 210+170; x+=2) {
                drawLine(x,   y,
                    x+1, y,
                    thickness);
                drawLine(x,   y,
                    x,   y+1,
                    thickness);
            }
        }
        glfwSwapBuffers(window);
    }
    glfwDestroyWindow(window);
    glfwTerminate();
    return 0;
}

CMakeLists.txt:

cmake_minimum_required(VERSION 3.10)
project(test)

# Add main source code
add_executable(test test.cpp)

# Suppress FindOpenGL warning
cmake_policy(SET CMP0072 NEW)

find_package(PkgConfig)
find_package(OpenGL REQUIRED)
pkg_check_modules(GLFW3 REQUIRED glfw3)

target_include_directories(test PUBLIC
    ${OPENGL_INCLUDE_DIRS}
    ${GLFW3_INCLUDE_DIRS}
)
target_link_directories(test PUBLIC
    ${OPENGL_LIBRARY_DIRS}
    ${GLFW3_LIBRARY_DIRS}
)
target_link_libraries(test PUBLIC
    ${OPENGL_LIBRARIES}
    ${GLFW3_LIBRARIES}
)

Steps to reproduce: 1) create test.cpp and CMakeLists.txt files 2) mkdir build && cd build 3) make .. 4) make -j4 5) ./test

Actual result on RPI4 Bookworm aarch64: bookworm-rpi

Expected result taken on Linux Arch x64 with Nvidia GTX460 video card: linux-arch-nvidia

Expected result taken on Win7 x64 with Nvidia GTX460 video card: win7-nvidia

popcornmix commented 3 months ago

Might be best to report this to mesa. There are no experts on the 3d driver here.

qrp73 commented 3 months ago

can someone test this issue on RPI5 and on environment different than Bookworm Wayland?

ghollingworth commented 3 months ago

Can you try it with labwc, I just tried this with both libglfw and libglfx-wayland and both worked for me (but I'm using labwc)

popcornmix commented 3 months ago

I tried on labwc on a Pi5 and got the reported behaviour (dots, rather than vertical stripes) on the right side of window.

qrp73 commented 2 months ago

Also found that when running OpenGL ES app on Raspberry Pi Zero 2W in KMS DRM mode it has some specific slightly visible artifacts on a solid filled surface. These artifacts are missing when running the same app on Raspberry Pi 4 in KMS DRM mode. Since the code is too large, needs to experiment to reproduce it on a simple example.