Forums
Raspberry Pi 4 is different, book code won't work! - Printable Version

+- Forums (http://www.scratchpadgames.net/forums)
+-- Forum: Main Forums (http://www.scratchpadgames.net/forums/forumdisplay.php?fid=1)
+--- Forum: Help my code won't work?? (http://www.scratchpadgames.net/forums/forumdisplay.php?fid=22)
+--- Thread: Raspberry Pi 4 is different, book code won't work! (/showthread.php?tid=507)



Raspberry Pi 4 is different, book code won't work! - Brian Beuken - 07-03-2019

Well it had to happen, the new Raspi4 is a lovely machine with some impressive graphic potential, but it does not work the same way as all the other Raspberries so the book examples won't work, there has to be a new version of the graphics startup code.

The previous Raspberries used Broadcom IV graphic drivers with binaries and libs located in opt/vc/lib and opt/vc/include

The Pi4 still has these libraries and locations but they don't work on the 4, though you can use the Buster OS with any other Raspberry.


1st things 1st you need mesa libs which can be installed by opening a terminal and typing

sudo apt-get install libgles2-mesa-dev 

Now you need to change some of your project library needs and directory access. The increased number of libs needed to run on the older RPis has been reduced to just 3,  EGL, GLES2 AND X11 (other display systems are possible though but not right now)


And include libs are now usr/lib for the libraries and usr/include for the h files
Also, and this is very important, do not disable the OpenGL drivers as we had to do in older Raspberry's


If you are using one of the multi build configs on the site, basically Raspberry has reverted to the normal way to build a Linux project, so remove the RASPBERRY pre processor instruction and let it build like a normal Linux build and it should be fine.
Here's the init code to set up an X11 window, EGL and get ready to work with OpenGLES2.0

Code:
///
// CreateEGLContext()
//
//    Creates an EGL rendering context and all associated elements

static Display* x_display = NULL;

void Graphics::init_ogl(Target_State *state, int width, int height, int FBResX, int FBResY)

{
    
    
#define ES_WINDOW_RGB           0
    state->width = width;
    state->height = height;

    EGLint numConfigs;
    EGLint majorVersion;
    EGLint minorVersion;
    
    EGLDisplay display;
    EGLContext context;
    EGLSurface surface;
    EGLConfig config;
    EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE };

    
      /* create a native window */
    
    Window root;
    XSetWindowAttributes swa;
    XSetWindowAttributes  xattr;
    Atom wm_state;
    XWMHints hints;
    XEvent xev;
    EGLConfig ecfg;
    EGLint num_config;
    Window win;
    Screen *screen;

        /*
         * X11 native display initialization
         */

    
        
    x_display = XOpenDisplay(NULL);

        if (x_display == NULL)
        {
            
            printf("Sorry to say we can't create an Xwindow and this will fail");
            exit(0); //return ; // we need to trap this;
        }
    eglBindAPI(EGL_OPENGL_ES_API);
    root = DefaultRootWindow(x_display);
    screen = ScreenOfDisplay(x_display, 0);

    
    state->width = width;
    state->height = height;

    swa.event_mask  =  ExposureMask | PointerMotionMask | KeyPressMask | KeyReleaseMask;
    swa.background_pixmap = None;
    swa.background_pixel  = 0;
    swa.border_pixel      = 0;
    swa.override_redirect = true;
    
    win = XCreateWindow(
        x_display,
        root,
        0,
        0,
        width,
        height,
        0,
        CopyFromParent,
        InputOutput,
        CopyFromParent,
        CWEventMask,
        &swa);
    
    XSelectInput(x_display, win, KeyPressMask | KeyReleaseMask);
    
    xattr.override_redirect = TRUE;
    XChangeWindowAttributes(x_display, win, CWOverrideRedirect, &xattr);
    
    hints.input = TRUE;
    hints.flags = InputHint;
    XSetWMHints(x_display, win, &hints);
    
    
    char* title = (char*)"x11 window Maze3dHunt";
        // make the window visible on the screen
    XMapWindow(x_display, win);
    XStoreName(x_display, win, title);

        // get identifiers for the provided atom name strings
    wm_state = XInternAtom(x_display, "_NET_WM_STATE", FALSE);
    
    memset(&xev, 0, sizeof(xev));
    xev.type                 = ClientMessage;
    xev.xclient.window       = win;
    xev.xclient.message_type = wm_state;
    xev.xclient.format       = 32;
    xev.xclient.data.l[0]    = 1;
    xev.xclient.data.l[1]    = FALSE;
    XSendEvent(
      x_display,
        DefaultRootWindow(x_display),
        FALSE,
        SubstructureNotifyMask,
        &xev);
    

    state->nativewindow = (EGLNativeWindowType) win;
    
    // Get Display    
    display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    if (display == EGL_NO_DISPLAY)
    {
        printf("Sorry to say we have an EGLinit error and this will fail");
        EGLint err = eglGetError();
        return; // EGL_FALSE;
    }
    
        
    // Initialize EGL
    if (!eglInitialize(display, &majorVersion,&minorVersion))
    {
    
        printf("Sorry to say we have an EGLinit error and this will fail");
        EGLint err = eglGetError();
        return;// EGL_FALSE;
    }

    // Get configs
    if (!eglGetConfigs(display, NULL, 0, &numConfigs))
    {
        printf("Sorry to say we have EGL config errors and this will fail");
        EGLint err = eglGetError();
        return;// EGL_FALSE;
    }

    // Choose config
    if (!eglChooseConfig(display, attribute_list, &config, 1, &numConfigs))
    {
        printf("Sorry to say we have config choice issues, and this will fail");
        EGLint err = eglGetError();
        return;// EGL_FALSE;
    }


    
    
    // Create a surface
    
    
    surface = eglCreateWindowSurface(display, config, state->nativewindow, NULL);
    if (surface == EGL_NO_SURFACE)
    {
        EGLint err = eglGetError();
        return;// EGL_FALSE;
    }

    // Create a GL context
    context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs);
    if (context == EGL_NO_CONTEXT)
    {
        EGLint err = eglGetError();
        return;// EGL_FALSE;
    }

    // Make the context current
    if (!eglMakeCurrent(display, surface, surface, context))
    {
        EGLint err = eglGetError();
        return;// EGL_FALSE;
    }

    state->display = display;
    state->surface = surface;
    state->context = context;
    
// just for fun lets see what we can do with this GPU        
    printf("This SBC supports version %i.%i of EGL\n", majorVersion, minorVersion);
    printf("This GPU supplied by  :%s\n", glGetString(GL_VENDOR));
    printf("This GPU supports     :%s\n", glGetString(GL_VERSION));
    printf("This GPU Renders with :%s\n", glGetString(GL_RENDERER));
    printf("This GPU supports     :%s\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
    printf("This GPU supports these extensions    :%s\n", glGetString(GL_EXTENSIONS));

    
    
    EGLBoolean GLtest = eglGetConfigAttrib(    display,
        config,
        EGL_MAX_SWAP_INTERVAL,
        &minorVersion);
    
    EGLBoolean test = eglSwapInterval(display, 1);    // 1 to lock speed to 60fps (assuming we are able to maintain it), 0 for immediate swap (may cause tearing) which will indicate actual frame rate
    // on xu4 this seems to have no effect

    // Some OpenGLES2.0 states that we might need

    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);
    glDepthMask(TRUE);
    glDepthRangef(0.0f, 1.0f);
    glClearDepthf(1.0f);

//these are the options you can have for the depth, play with them?
//#define GL_NEVER                          0x0200
//#define GL_LESS                           0x0201
//#define GL_EQUAL                          0x0202
//#define GL_LEQUAL                         0x0203
//#define GL_GREATER                        0x0204
//#define GL_NOTEQUAL                       0x0205
//#define GL_GEQUAL                         0x0206
//
    glViewport(0, 0, state->width, state->height);
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glCullFace(GL_BACK);
    if (glGetError() == GL_NO_ERROR)    return ;
    else
        printf("Oh bugger, Some part of the EGL/OGL graphic init failed\n");    
}




I will put new builds forPi4 up on the site as soon as I can, if you need help, just ping me on here or drop me a mail


RE: Raspberry Pi 4 is different, book code won't work! - jomoengineer - 09-08-2019

Brian,

Did you ever post an update to the examples that work with the RasPi 4? I have one of these boards and will be looking to migrate from the RasPi 3B+.

Cheers,

Jon


RE: Raspberry Pi 4 is different, book code won't work! - Brian Beuken - 09-08-2019

Essentially you need to use the traditional X11 systems to work. But that has a few issues I'm trying (and failing) to overcome
With X11 you seem to be limited to the resolution of your screen, or a window...With Broadcom we could set the display res to screen size but the display buffer to any size. The screen would scale accordingly.
This had the advanatge of giving you 1080p res on screen but 720p update for 2x the speed and not a massive amount of visual difference.

Since X11 does not allow that (as far as I can tell), I've been looking at other methods, but so far without success.

Thats stopped me doing any updates just yet, as I want both Pi3 and Pi4 systems to work the same way at the same update rate. I'm still trying to come up with a solution, but other things are getting in the way, but I will return to it soon.