Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Failed to draw a triangle with Emscripten, SDL 3.0 and OpenGL ES 2.0 on old phone Redmi 4X, Android 7 #9047

Open
8Observer8 opened this issue Feb 11, 2024 · 0 comments
Milestone

Comments

@8Observer8
Copy link

8Observer8 commented Feb 11, 2024

The next example draws a triangle using OpenGL ES 2.0 and SDL 3.0 and it works on Infinix Hot 30, Android 13 without problems: https://65c8fc0851792f3dc1fbd7d9--spiffy-trifle-f2dd69.netlify.app/ Short url: t.ly/b9Wbp But it doesn't work on old phone Redmi 4X, Android 7. Is it possible to solve it? I use the next template with guide: https://github.com/Ravbug/sdl3-sample

Note. Open CMakeLists.txt and set target_link_libraries adding android EGL GLESv2 here:

target_link_libraries(${EXECUTABLE_NAME} PUBLIC SDL3::SDL3 android EGL GLESv2)

image

main.cpp

#include <SDL.h>
#include <cmath>
#include <iostream>
#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
// On UWP, we need to not have SDL_main otherwise we'll get a linker error
#define SDL_MAIN_HANDLED
#endif
#include <SDL_main.h>
#if __EMSCRIPTEN__
#include <emscripten.h>
#endif

#include <SDL_opengles2.h>

void SDL_Fail()
{
    SDL_LogError(SDL_LOG_CATEGORY_CUSTOM, "Error %s", SDL_GetError());
    exit(1);
}

static bool app_quit = false;
SDL_Window *window = nullptr;
const float maxFPS = 5.f;

const char *vertexShaderSource =
    "attribute vec2 aPosition;\n"
    "void main()"
    "{\n"
    "    gl_Position = vec4(aPosition, 0.0, 1.0);\n"
    "}\n";

const char *fragmentShaderSource =
    "void main()"
    "{\n"
    "    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
    "}\n";

GLuint createShader(const char *shaderSource, int shaderType)
{
    GLuint shader = glCreateShader(shaderType);
    glShaderSource(shader, 1, &shaderSource, NULL);
    glCompileShader(shader);
    GLint status;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
    if (status == GL_FALSE)
    {
        GLint maxLength = 0;
        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
        std::vector<GLchar> errorLog(maxLength);
        glGetShaderInfoLog(shader, maxLength, &maxLength, &errorLog[0]);
        glDeleteShader(shader); // Don't leak the shader.
        std::printf("%s\n", &(errorLog[0]));
        // fatalError("Shader failed to compile");
    }
    return shader;
}

GLuint createShaderProgram()
{
    GLuint program = glCreateProgram();
    GLuint vShader = createShader(vertexShaderSource, GL_VERTEX_SHADER);
    GLuint fShader = createShader(fragmentShaderSource, GL_FRAGMENT_SHADER);

    glAttachShader(program, vShader);
    glAttachShader(program, fShader);
    glLinkProgram(program);
    glUseProgram(program);

    return program;
}

void initVertexBuffers(GLuint program)
{
    float vertPositions[] = {
        -1.f, -1.f,
        1.f, -1.f,
        0.f, 1.f
    };
    GLuint vertPosBuffer;
    glGenBuffers(1, &vertPosBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertPosBuffer);
    int amount = sizeof(vertPositions) / sizeof(vertPositions[0]);
    glBufferData(GL_ARRAY_BUFFER, amount * sizeof(GLfloat),
        vertPositions, GL_STATIC_DRAW);
    GLint aPositionLocation = glGetAttribLocation(program, "aPosition");
    glVertexAttribPointer(aPositionLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(aPositionLocation);
}

void main_loop()
{
    // Get events. If you are making a game, you probably want SDL_PollEvent instead of SDL_WaitEvent.
    // you cannot use WaitEvent on Emscripten, because you cannot block the main thread there.

    SDL_Event event;
    while (SDL_PollEvent(&event))
    {
        if (event.type == SDL_EVENT_QUIT)
            app_quit = true;
        break;
    }
    float startTicks = SDL_GetTicks();

    // draw a color
    // auto time = SDL_GetTicks() / 1000.f;
    // auto red = (std::sin(time) + 1) / 2.0 * 255;
    // auto green = (std::sin(time / 2) + 1) / 2.0 * 255;
    // auto blue = (std::sin(time) * 2 + 1) / 2.0 * 255;
    // auto red = 50;
    // auto green = 255;
    // auto blue = 50;
    auto red = 0.2f;
    auto green = 0.2f;
    auto blue = 0.2f;

    glClearColor(red, green, blue, 1.f);
    glClear(GL_COLOR_BUFFER_BIT);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    SDL_GL_SwapWindow(window);
    // Limit FPS to the max FPS
    float frameTicks = SDL_GetTicks() - startTicks;
    if (1000.f / maxFPS > frameTicks)
    {
        SDL_Delay(1000.f / maxFPS - frameTicks);
    }
}

// Note: your main function __must__ take this form, otherwise on nonstandard platforms (iOS, etc), your app will not launch.
int main(int argc, char *argv[])
{
    // init the library, here we make a window so we only need the Video capabilities.
    if (SDL_Init(SDL_INIT_VIDEO))
    {
        SDL_Fail();
    }

    // create a window
    SDL_Window *window = SDL_CreateWindow("Window", 352, 430, SDL_WINDOW_OPENGL);
    if (!window)
    {
        SDL_Fail();
    }

    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GLContext glContext = SDL_GL_CreateContext(window);
    if (!glContext)
    {
        SDL_Fail();
    }

    GLuint program = createShaderProgram();
    initVertexBuffers(program);

    // print some information about the window
    SDL_ShowWindow(window);
    {
        int width, height, bbwidth, bbheight;
        SDL_GetWindowSize(window, &width, &height);
        SDL_GetWindowSizeInPixels(window, &bbwidth, &bbheight);
        SDL_Log("Window size: %ix%i", width, height);
        SDL_Log("Backbuffer size: %ix%i", bbwidth, bbheight);
        if (width != bbwidth)
        {
            SDL_Log("This is a highdpi environment.");
        }
    }

    SDL_Log("Application started successfully!");

#if __EMSCRIPTEN__
    // on Emscripten, we cannot have an infinite loop in main. Instead, we must
    // tell emscripten to call our main loop.
    emscripten_set_main_loop(main_loop, 0, 1);
#else
    while (!app_quit)
    {
        main_loop();
    }
#endif

    // cleanup everything at the end
#if !__EMSCRIPTEN__
    SDL_DestroyWindow(window);
    SDL_Quit();
    SDL_Log("Application quit successfully!");
#endif
    return 0;
}

Topics:

@slouken slouken added this to the 3.2.0 milestone Mar 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants