1

I am trying to fill the screen by red color in my native activity but it crashes on eglSwapBuffers with

07-19 10:36:40.497 3197-3232/com.contedevel.davinci A/libc: Fatal signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 0xf4169e90 in tid 3232 (tedevel.davinci), pid 3197 (tedevel.davinci)

Here is my native activity code:

#include <initializer_list>
#include <memory>
#include <cstdlib>
#include <cstring>
#include <jni.h>
#include <errno.h>
#include <cassert>
#include <dlfcn.h>

#include <EGL/egl.h>
#include <GLES/gl.h>

#include <android/sensor.h>
#include <android/log.h>
#include <android_native_app_glue.h>

#include "../include/window.h"

#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "camera-activity", __VA_ARGS__))
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "camera-activity", __VA_ARGS__))

/**
 * Shared state for our app.
 */
struct engine {
    struct android_app *app;
    davinci::window *wnd = nullptr;

    ~engine() {
        if (wnd) { delete wnd; }
    }
};

/**
 * Initialize an EGL context for the current display.
 */
static int engine_init_display(struct engine *engine) {
    const EGLint attrs[] = {
            EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
            EGL_BLUE_SIZE, 8,
            EGL_GREEN_SIZE, 8,
            EGL_RED_SIZE, 8,
            EGL_NONE
    };
    EGLint w, h, format;
    EGLint numConfigs;
    EGLConfig config;
    EGLSurface surface;
    EGLContext context;

    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);

    eglInitialize(display, 0, 0);

    eglChooseConfig(display, attrs, nullptr, 0, &numConfigs);
    std::unique_ptr<EGLConfig[]> supportedConfigs(new EGLConfig[numConfigs]);
    assert(supportedConfigs);
    eglChooseConfig(display, attrs, supportedConfigs.get(), numConfigs, &numConfigs);
    assert(numConfigs);
    auto i = 0;
    for (; i < numConfigs; i++) {
        auto& cfg = supportedConfigs[i];
        EGLint r, g, b, d;
        if (eglGetConfigAttrib(display, cfg, EGL_RED_SIZE, &r)   &&
            eglGetConfigAttrib(display, cfg, EGL_GREEN_SIZE, &g) &&
            eglGetConfigAttrib(display, cfg, EGL_BLUE_SIZE, &b)  &&
            eglGetConfigAttrib(display, cfg, EGL_DEPTH_SIZE, &d) &&
            r == 8 && g == 8 && b == 8 && d == 0 ) {

            config = supportedConfigs[i];
            break;
        }
    }
    if (i == numConfigs) {
        config = supportedConfigs[0];
    }

    eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
    surface = eglCreateWindowSurface(display, config, engine->app->window, NULL);
    context = eglCreateContext(display, config, NULL, NULL);

    if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
        LOGW("Unable to eglMakeCurrent");
        return -1;
    }

    eglQuerySurface(display, surface, EGL_WIDTH, &w);
    eglQuerySurface(display, surface, EGL_HEIGHT, &h);

    engine->wnd = new davinci::window(display, context, surface, w, h);

    // Check openGL on the system
    auto opengl_info = {GL_VENDOR, GL_RENDERER, GL_VERSION, GL_EXTENSIONS};
    for (auto name : opengl_info) {
        auto info = glGetString(name);
        LOGI("OpenGL Info: %s", info);
    }
    // Initialize GL state.
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
    glEnable(GL_CULL_FACE);
    glShadeModel(GL_SMOOTH);
    glDisable(GL_DEPTH_TEST);

    return 0;
}

/**
 * Just the current frame in the display.
 */
static void engine_draw_frame(struct engine* engine) {
    if (engine->wnd->display() == NULL) { return; }
    glClearColor(1, 0, 0, 0);
    glClear(GL_COLOR_BUFFER_BIT);
    engine->wnd->swap_buffers();
}

/**
 * Tear down the EGL context currently associated with the display.
 */
static void engine_term_display(struct engine* engine) {
    if (engine->wnd->display() != EGL_NO_DISPLAY) {
        eglMakeCurrent(engine->wnd->display(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
        if (engine->wnd->context() != EGL_NO_CONTEXT) {
            eglDestroyContext(engine->wnd->display(), engine->wnd->context());
        }
        if (engine->wnd->surface() != EGL_NO_SURFACE) {
            eglDestroySurface(engine->wnd->display(), engine->wnd->surface());
        }
        eglTerminate(engine->wnd->display());
    }
    engine->wnd->display(EGL_NO_DISPLAY);
    engine->wnd->context(EGL_NO_CONTEXT);
    engine->wnd->surface(EGL_NO_SURFACE);
}

/**
 * Process the next main command.
 */
static void engine_handle_cmd(struct android_app* app, int32_t cmd) {
    struct engine* engine = (struct engine*)app->userData;
    switch (cmd) {
        case APP_CMD_INIT_WINDOW:
            // The window is being shown, get it ready.
            if (engine->app->window != NULL) {
                engine_init_display(engine);
                engine_draw_frame(engine);
            }
            break;
        case APP_CMD_TERM_WINDOW:
            // The window is being hidden or closed, clean it up.
            engine_term_display(engine);
            break;
    }
}

void android_main(struct android_app* state) {
    struct engine engine;

    memset(&engine, 0, sizeof(engine));
    state->userData = &engine;
    state->onAppCmd = engine_handle_cmd;
    engine.app = state;

    // loop waiting for stuff to do.
    while (1) {
        // Read all pending events.
        int ident;
        int events;
        struct android_poll_source* source;

        while ((ident=ALooper_pollAll(0, NULL, &events, (void**)&source)) >= 0) {

            // Process this event.
            if (source != NULL) {
                source->process(state, source);
            }

            // Check if we are exiting.
            if (state->destroyRequested != 0) {
                engine_term_display(&engine);
                return;
            }
        }
    }
}

And my window class:
window.h:

#include <EGL/egl.h>

namespace davinci {
    class window {
        EGLDisplay m_display;
        EGLSurface m_surface;
        EGLContext m_context;
        int32_t m_width;
        int32_t m_height;
    public:
        window(EGLDisplay display, EGLSurface surface, EGLContext ctx,
               int32_t width, int32_t height);
        ~window();
        // Getters
        EGLDisplay display() const;
        EGLSurface surface() const;
        EGLContext context() const;
        int32_t width() const;
        int32_t height() const;
        // Setters
        void display(EGLDisplay d);
        void surface(EGLSurface s);
        void context(EGLContext ctx);
        // Methods
        void swap_buffers();
    };
};

window.cpp:

#include "../include/window.h"

using namespace davinci;

window::window(EGLDisplay display, EGLSurface surface, EGLContext ctx,
               int32_t width, int32_t height) :
    m_display{display}, m_surface{surface}, m_context{ctx}, m_width{width}, m_height{height}
{

}

window::~window() {

}

EGLDisplay window::display() const { return m_display; }
EGLSurface window::surface() const { return m_surface; }
EGLContext window::context() const { return m_context; }
int32_t window::width() const { return m_width; }
int32_t window::height() const { return m_height; }

void window::display(EGLDisplay d) { m_display = d; }
void window::surface(EGLSurface s) { m_surface = s; }
void window::context(EGLContext ctx) { m_context = ctx; }

void window::swap_buffers() { eglSwapBuffers(m_display, m_surface); }

What am I doing wrong?

Denis Sologub
  • 7,277
  • 11
  • 56
  • 123
  • 1
    "What am I doing wrong?" You have to debug. Identify the location of the crash, determine the context (variable values, call stack and alike), compare the IS-state with the SHOULD-state. A debugger tool will be helpful. – Jodocus Jul 19 '18 at 07:46
  • @Jodocus, I have a debugger but in debug mode it crashes on `while ((ident=ALooper_pollAll(0, NULL, &events, (void**)&source)) >= 0)`. But it doesn't seem due to errors, just my debugger can't stop on some breakpoints. Honestly, it works very weird, it seems the debugger can't work normally in my Android Studio. P.S. I know how to work with debugger... it works really weird for native code. – Denis Sologub Jul 19 '18 at 07:52
  • I just put log one by one line to localize where is an error. If I remove `eglSwapBuffers` app works. – Denis Sologub Jul 19 '18 at 07:54
  • Hi @Шах did you find a way to solve this? I am incurring in the same error as you. – Iñigo Mar 08 '22 at 11:28
  • I am using the ndk-helper context although. – Iñigo Mar 08 '22 at 11:40
  • @Iñigo hello! Unfortunately, no – Denis Sologub Mar 08 '22 at 11:42

1 Answers1

0

You are swapping the surface for the context. In your davinci::window's constructor you take display, surface and context as parameters (notice the order), but when you instantiate it inside engine_init_display you pass them in a different order (display, context and surface). You don't get a compile error because internally they are both just typedef void pointers.

AotoDev
  • 31
  • 3