Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
XU4
#1
Ok this is of course the beast in the Odroid Range, well loved for its emulation ability and octocore performance.

And of course as a target machine it is an utter beast to use, hardware acceleration on the OpenGLES, and able to handle OpenGLES3.1
It has an Mali T628 MP6 on board which is really a major boost, and if you want to get very fancy with it it can do OpenCL for some very intense muli system coding, not that its very practical on a games target.

I love this machine though it does have one niggle, the noisy fan, which does come on and off a lot when you are running it hard and can be an irritant. They do have a silent version basically a big lump of metal heat sink. Not sure of it suffers from overheating with it or not. I can't bring myself to buy 2 of them, as they are a bit pricey. Close to my limit when you factor in the shipping.

So far I've only used mine in anger as an OpenGLES2.0 system for my test code, though I have run a few ES3.0 demos to see it working in its glory :Big Grin
If you plan to do any OpenGLES3.0 this is the one. I am not 100% sure though that the OpenGLES3.1 claim is true as I was unable to get anything to work on 3.1 demos, however I didn't spend a lot of time so maybe I was just not setting it up right

Set up of the XU4 for ES2.0 really isn't too hard. I use their supplied Ubuntu MATE OS which I think came ready to go with no need to install anything else, but its over a year since I got mine and memory might have failed me. If you can't find the OpenGLES2.0 folders then simple apt-get the mesa libs.

Set up in Visual GDB is typical for most non Raspberry systems you need these include libs, assuming you have glm and bullet installed

/usr/include /usr/include/bullet /usr/include/bullet/BulletCollision/CollisionShapes . glm Headers /usr/include/GLES2 /usr/include/arm-linux-gnueabihf /usr/include/arm-linux-gnueabihf/c++/5


and then just this Binary Lib Dir
/usr/lib/arm-linux-gnueabihf

Library names are...
GLESv2 EGL pthread BulletCollision BulletSoftBody BulletDynamics LinearMath X11

Finally you will need to include some flags for g++
-ggdb -ffunction-sections -std=c++11 -O0 -DGL_GLEXT_PROTOTYPES
the 1st set are normal but the Odroids UbuntuMate version of gcc needs that -DGL_GLEXT_PROTOTYPES or it won't compile


Make sure you don't include BCMHost.h  in any non Raspberry Build

There after there are only 2 issues.. How to get the screen size to set up full screen, and how to set up an EGL window, this time displayed by X11

So make sure you don't define a preprocessor define for RASPBERRY
and you can use this code for both systems.

Code:
/*
Set up the EGL and in the case of Raspberry DispamX
Set up OpenGL states needed
*/
#ifdef RASPBERRY

void Graphics::init_ogl(Target_State *state, int width, int height, int FBResX, int FBResY)
{
    int32_t success = 0;
    EGLBoolean result;
    EGLint num_config;


    
    

    
    
//RPI setup is a little different to normal EGL
    DISPMANX_ELEMENT_HANDLE_T DispmanElementH;
    DISPMANX_DISPLAY_HANDLE_T DispmanDisplayH;
    DISPMANX_UPDATE_HANDLE_T DispmanUpdateH;
    VC_RECT_T dest_rect;
    VC_RECT_T src_rect;
    EGLConfig config;

// get an EGL display connection
    state->display = eglGetDisplay(EGL_DEFAULT_DISPLAY);

// initialize the EGL display connection
    result = eglInitialize(state->display, NULL, NULL);

// get an appropriate EGL frame buffer configuration
    result = eglChooseConfig(state->display, attribute_list, &config, 1, &num_config);
    assert(EGL_FALSE != result);

// get an appropriate EGL frame buffer configuration
    result = eglBindAPI(EGL_OPENGL_ES_API);
    assert(EGL_FALSE != result);

// create an EGL rendering context
    state->context = eglCreateContext(state->display, config, EGL_NO_CONTEXT, context_attributes);
    assert(state->context != EGL_NO_CONTEXT);

// create an EGL window surface

    state->width = FBResX;
    state->height = FBResY;

    
    dest_rect.x = 0; // (1920/2)-FBResX/2; // if using a non display size you can center it here
    dest_rect.y = 0; // (1080/2)+(FBResY/2);
    dest_rect.width = width; // it needs to know our window size
    dest_rect.height = height; //state->height;

    src_rect.x = 0;
    src_rect.y = 0;
    src_rect.width = (FBResX) << 16;
    src_rect.height = (FBResY) << 16;
    
    
    

    DispmanDisplayH = vc_dispmanx_display_open(0);
    DispmanUpdateH = vc_dispmanx_update_start(0);

    DispmanElementH =     vc_dispmanx_element_add(
        DispmanUpdateH,
        DispmanDisplayH,
        1/*layer*/,
        &dest_rect,
        0/*source*/,
        &src_rect,
        DISPMANX_PROTECTION_NONE,
        0 /*alpha value*/,
        0/*clamp*/,
        (DISPMANX_TRANSFORM_T) 0/*transform*/);

    state->nativewindow.element = DispmanElementH;
    state->nativewindow.width = FBResX; //state->width;
    state->nativewindow.height = FBResY; //state->height;
    vc_dispmanx_update_submit_sync(DispmanUpdateH);



// normal EGL updates are different
    
    
    state->surface = eglCreateWindowSurface(state->display, config, &(state->nativewindow), NULL);
    assert(state->surface != EGL_NO_SURFACE);

       // connect the context to the surface
    result = eglMakeCurrent(state->display, state->surface, state->surface, state->context);
    assert(EGL_FALSE != result);

// Some OpenGLES2.0 states that we might need
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);

    glViewport(0, 0, state->width, state->height);
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    
    glCullFace(GL_BACK);

    
// stops the targets desktop showing through if we have alpha (but at a frame cost, you can remove if you are sure there are no transparencies)
//    glEnable(GL_BLEND);
//    glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
    

    eglSwapInterval(state->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
    
    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));
}

#else

#include  <X11/Xlib.h>
#include  <X11/Xatom.h>
#include  <X11/Xutil.h>

#define EGL_FALSE            0
#define EGL_TRUE            1


///
// 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 };

//    EGLint result = eglChooseConfig(state->display, attribute_list, &config, 1, &numConfigs);
    
      /* 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;
    eglBindAPI(EGL_OPENGL_ES_API);
        /*
         * X11 native display initialization
         */

    x_display = XOpenDisplay(NULL);
    
    if (x_display == NULL)
    {
        return ; // we need to trap this;
    }
    root = DefaultRootWindow(x_display);
    screen = ScreenOfDisplay(x_display, 0);
    width = screen->width;
    height = screen->height; // resplution of screen
    
    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)
    {
        return; // EGL_FALSE;
    }

    // Initialize EGL
    if (!eglInitialize(display, &minorVersion,&majorVersion))
    {
    
        EGLint err = eglGetError();
        return;// EGL_FALSE;
    }

    // Get configs
    if (!eglGetConfigs(display, NULL, 0, &numConfigs))
    {
        return;// EGL_FALSE;
    }

    // Choose config
    if (!eglChooseConfig(display, attribute_list, &config, 1, &numConfigs))
    {
        return;// EGL_FALSE;
    }

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

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

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

    state->display = display;
    state->surface = surface;
    state->context = context;
    //return;// EGL_TRUE;
    
        
    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));

    
}

#endif // RASPBERRY

This is pretty much the same for every basic SBC system with an X11 display (in other words not Raspberry),  as long as the graphics systems are on the target.
The XU4 needs you to use the root though so when you create the ssh connection use root, or it won't let you send files to the target,
Brian Beuken
Lecturer in Game Programming at Breda University of Applied Sciences.
Author of The Fundamentals of C/C++ Game Programming: Using Target-based Development on SBC's 



Reply
#2
hmmm interesting, I fired up an update of the XU4 and then tested my demo, and it didnt work...grrrr

ok I'll look into this.
Brian Beuken
Lecturer in Game Programming at Breda University of Applied Sciences.
Author of The Fundamentals of C/C++ Game Programming: Using Target-based Development on SBC's 



Reply
#3
There seems to be an issue with the current version of Ubuntu and using Visual GDB to fire up a project, it appears to lose access to its Display env label and as a result it can't open an X11 window.. I've now had this on 2 other Ubuntu based boards. I'll try to find a fix!
Brian Beuken
Lecturer in Game Programming at Breda University of Applied Sciences.
Author of The Fundamentals of C/C++ Game Programming: Using Target-based Development on SBC's 



Reply
#4
I think the fix is to enter
xhost +

in a terminal.. I'll set up my XU4 and try it out
Brian Beuken
Lecturer in Game Programming at Breda University of Applied Sciences.
Author of The Fundamentals of C/C++ Game Programming: Using Target-based Development on SBC's 



Reply
#5
Working fine now, the beast is back, just remember to log in as root, or use the xhost + to give access to xserver featrues like graphics.

The XU4 really is amazing. Big Grin What a machine it is, it's so much faster and now this niggle is out of the way, just as easy as the pi to code, everything feels smooth and amazing....love this machine, if only it was a little cheaper.

Can't wait for their next offering, the N1 didn't get into full produciton sadly, but an N2 is on the horizon...can't wait to see what they do.

I really like Hardkernal systems, they are no where near as well supported but are clearly trying to appeal to the same broad market as Raspberry without actually limiting themselves to 1 design, that allows for quite some range in performance.
Brian Beuken
Lecturer in Game Programming at Breda University of Applied Sciences.
Author of The Fundamentals of C/C++ Game Programming: Using Target-based Development on SBC's 



Reply
#6
I see the ODROID XU4 is on sale for $49.00.  Is this a decent board to work on for Mali dev?

https://www.hardkernel.com/shop/odroid-x...ial-price/

The XU3 is listed with the ARM Graphics and Game dev and the XU4 should work I guess.
https://developer.arm.com/solutions/grap...odroid-xu3

Thoughts?
Reply
#7
yes, its a few years old now but it is still an absolute monster of a CPU with a monster of GPU, its still ranks in the top 5 power systems even against the RK3399 units. Its well supported for OS and has importantly got drivers for ES2.0 and ES3.0/1 and possibly, but I've not tested recently ES3.2
One thing to be aware of is buy their power unit, it needs it. The XU3 is obsolete now but everything the XU3 could do the XU4 can do a bit better.
Brian Beuken
Lecturer in Game Programming at Breda University of Applied Sciences.
Author of The Fundamentals of C/C++ Game Programming: Using Target-based Development on SBC's 



Reply
#8
I just did an update and ran GLMark2 tests to add to the list, its still amazing Big Grin
Brian Beuken
Lecturer in Game Programming at Breda University of Applied Sciences.
Author of The Fundamentals of C/C++ Game Programming: Using Target-based Development on SBC's 



Reply
#9
And it runs all my demo's lighting fast....which actually is a bit of an issue, it does not sync to the EGL frame swap, whcih is normally done with this command

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

but like the comment says, the XU4 isn't having any of it.. so my demos run at 150-200 fps.... its cool to see them run so fast, but its not quite what I want, I would have to add a delta time wait to ensure a usable frame rate, but only for the XU4. I've posted on their forums to see if there's a fix.
Brian Beuken
Lecturer in Game Programming at Breda University of Applied Sciences.
Author of The Fundamentals of C/C++ Game Programming: Using Target-based Development on SBC's 



Reply
#10
Brian,
When using the XU4, are you running with an uSD card or an eMMC card installed?

Since I need to a emmc for the C4, I was looking at this as well since it seems to have a ton of support.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)