This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TDA4VM: Sample Wayland application of OpenGL to run on TI board

Part Number: TDA4VM

Tool/software:

Hi,

A new openGL user here.

Can I get the source code of a simple open GL ES application running on the TDA4 using Wayland/EGL? I have tried out the following application, but it ends up displaying the Weston background without drawing the required triangle:

/* Copied from a github repo
* A simple Wayland EGL program to show a triangle
*
* cc -o triangle_simple triangle_simple.c -lwayland-client -lwayland-egl -lEGL -lGLESv2
*/

#include <EGL/egl.h>
#include <GLES2/gl2.h>
#include <assert.h>
#include <string.h>
#include <wayland-client.h>
#include <wayland-egl.h>

struct WaylandGlobals {
struct wl_compositor* compositor;
struct wl_shell* shell;
};

/*
* Registry callbacks
*/
static void registry_global(void* data, struct wl_registry* registry, uint32_t id, const char* interface, uint32_t version)
{
struct WaylandGlobals* globals = (struct WaylandGlobals *)data;
if (strcmp(interface, "wl_compositor") == 0) {
globals->compositor = wl_registry_bind(registry, id, &wl_compositor_interface, 1);
} else if (strcmp(interface, "wl_shell") == 0) {
globals->shell = wl_registry_bind(registry, id, &wl_shell_interface, 1);
}
}

static const struct wl_registry_listener registry_listener = { registry_global, NULL };

/*
* Connect to the Wayland display and return the display and the surface
* output wlDisplay
* output wlSurface
*/
static void initWaylandDisplay(struct wl_display** wlDisplay, struct wl_surface** wlSurface)
{
struct WaylandGlobals globals = {0};

*wlDisplay = wl_display_connect(NULL);
assert(*wlDisplay != NULL);

struct wl_registry* registry = wl_display_get_registry(*wlDisplay);
wl_registry_add_listener(registry, &registry_listener, (void *) &globals);

wl_display_dispatch(*wlDisplay);
wl_display_roundtrip(*wlDisplay);
assert(globals.compositor);
assert(globals.shell);

*wlSurface = wl_compositor_create_surface(globals.compositor);
assert(*wlSurface != NULL);

struct wl_shell_surface* shellSurface = wl_shell_get_shell_surface(globals.shell, *wlSurface);
wl_shell_surface_set_toplevel(shellSurface);
}

/*
* Configure EGL and return necessary resources
* input nativeDisplay
* input nativeWindow
* output eglDisplay
* output eglSurface
*/
static void initEGLDisplay(EGLNativeDisplayType nativeDisplay, EGLNativeWindowType nativeWindow, EGLDisplay* eglDisplay, EGLSurface* eglSurface)
{
EGLint number_of_config;
EGLint config_attribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_NONE
};

static const EGLint context_attribs[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};

*eglDisplay = eglGetDisplay(nativeDisplay);
assert(*eglDisplay != EGL_NO_DISPLAY);

EGLBoolean initialized = eglInitialize(*eglDisplay, NULL, NULL);
assert(initialized == EGL_TRUE);

EGLConfig configs[1];

eglChooseConfig(*eglDisplay, config_attribs, configs, 1, &number_of_config);
assert(number_of_config);

EGLContext eglContext = eglCreateContext(*eglDisplay, configs[0], EGL_NO_CONTEXT, context_attribs);

*eglSurface = eglCreateWindowSurface(*eglDisplay, configs[0], nativeWindow, NULL);
assert(*eglSurface != EGL_NO_SURFACE);

EGLBoolean makeCurrent = eglMakeCurrent(*eglDisplay, *eglSurface, *eglSurface, eglContext);
assert(makeCurrent == EGL_TRUE);
}

/*
* Connect Wayland and make EGL
* input width
* input height
* output wlDisplay
* output eglDisplay
* output eglSurface
*/
static void initWindow(GLint width, GLint height, struct wl_display** wlDisplay, EGLDisplay* eglDisplay, EGLSurface* eglSurface)
{
struct wl_surface* wlSurface;
initWaylandDisplay(wlDisplay, &wlSurface);

struct wl_egl_window* wlEglWindow = wl_egl_window_create(wlSurface, width, height);
assert(wlEglWindow != NULL);

initEGLDisplay((EGLNativeDisplayType) *wlDisplay, (EGLNativeWindowType) wlEglWindow, eglDisplay, eglSurface);
}

/*
* Return the loaded and compiled shader
*/
GLuint LoadShader(GLenum type, const char* shaderSrc)
{
GLuint shader = glCreateShader(type);
assert(shader);

glShaderSource(shader, 1, &shaderSrc, NULL);
glCompileShader(shader);

GLint compiled;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
assert(compiled);

return shader;
}

/*
* Initialize the shaders and return the program object
*/
GLuint initProgramObject()
{
char vShaderStr[] = "#version 300 es \n"
"layout(location = 0) in vec4 vPosition; \n"
"void main() \n"
"{ \n"
" gl_Position = vPosition; \n"
"} \n";

char fShaderStr[] = "#version 300 es \n"
"precision mediump float; \n"
"out vec4 fragColor; \n"
"void main() \n"
"{ \n"
" fragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 ); \n"
"} \n";

GLuint vertexShader = LoadShader(GL_VERTEX_SHADER, vShaderStr);
GLuint fragmentShader = LoadShader(GL_FRAGMENT_SHADER, fShaderStr);

GLuint programObject = glCreateProgram();
assert(programObject);

glAttachShader(programObject, vertexShader);
glAttachShader(programObject, fragmentShader);

glLinkProgram(programObject);

GLint linked;
glGetProgramiv(programObject, GL_LINK_STATUS, &linked);
assert(linked);

return programObject;
}

/*
* Draw a triangle
*/
void draw(GLuint programObject, GLint width, GLint height)
{
GLfloat vVertices[] = { -0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f };

glViewport(0, 0, width, height);
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(programObject);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vVertices);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLES, 0, 3);
}

int main(int argc, char** argv)
{
int width = 750;
int height = 500;

struct wl_display* wlDisplay;
EGLDisplay eglDisplay;
EGLSurface eglSurface;

initWindow(width, height, &wlDisplay, &eglDisplay, &eglSurface);

GLuint programObject = initProgramObject();
assert(programObject);

draw(programObject, width, height);
eglSwapBuffers(eglDisplay, eglSurface);

while (wl_display_dispatch(wlDisplay) != -1) {
}

glDeleteProgram(programObject);

wl_display_disconnect(wlDisplay);

return 0;
}

For info, this code is also used in another resolved ticket (https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1214641/faq-tda4vm-sample-wayland-application-of-opengl-to-run-on-ti-board).

As mentioned, Wayland/Weston is running on my board already, so that should not be an issue. I have switched users from root to weston, but of no effect. For reference, I am getting a screen similar to the one below:

I do not necessarily need the above code to run. Any openGL ES application drawing something simple using EGL/Wayland is all I need. 

N.B: The Wayland demos on the board are working fine, but I could not find the associated source code.

Thankyou and best regards,

Ali 

  • Ali,

    As mentioned, Wayland/Weston is running on my board already, so that should not be an issue. I have switched users from root to weston, but of no effect. For reference, I am getting a screen similar to the one below:

    These are examples provided in the weston implementation or in other projects that are built from Yocto, which we use to build our Linux distribution. So the source code for these are hosted in different places.

    A simple wayland example should still run, but as we have moved to newer versions of wayland with SDK 9.x, there are some deprecated protocols that require updating the code to use the latest supported wayland configurations.

    To start, let us see how far you have gotten in the setup. Which SDK version are you using?

    N.B: The Wayland demos on the board are working fine, but I could not find the associated source code.

    If you booted up the board and see this screen, you are seeing the weston compositor is up and running and ready to run wayland applications. Now, we need to run a wayland app. A simple one to run is glmark2-es-wayland.

    Any openGL ES application drawing something simple using EGL/Wayland is all I need. 

    Let's see if we can find a reference to a simple app that we can use to test Wayland. Can you share the repository you used for the example code you referenced above?

    Thanks,

    Erick

  • Hi Ercik, 

    Thankyou for the reply. The answers to your queries.

    Which SDK version are you using

    I am using "ti-processor-sdk-linux-edgeai-j721e-evm-09_02_00_05". 

    Can you share the repository you used for the example code you referenced above?

    https://gist.github.com/propella/949261f89d83a6e184fb745a48de27c3

    Can you please provide a link to the "glmark2-es-wayland" app that you mentioned. Or something else that works?

    Best regards,

    Ali 

  • Ali,

    Can you please provide a link to the "glmark2-es-wayland" app that you mentioned. Or something else that works?

    https://github.com/glmark2/glmark2

    This is built in our SDK through Yocto.

    Regards,

    Erick

  • Hi Erick,

    Thanks for the link. I am having a look at it.

    Can you please also provide a link to a small Wayland example that draws something on the screen (a triangle etc.)?

    best regards,

    Ali 

  • Ali,

    Can you please also provide a link to a small Wayland example that draws something on the screen (a triangle etc.)?

    I'll need to find one, we had one for SDK 8.5 (simple_egl example from weston), but we will need to update it to work with SDK 9.0+.

    Regards,

    Erick

  • Hi Erick,

    I'll need to find one, we had one for SDK 8.5 (simple_egl example from weston)

    I have now prepared an SD card with SDK 8.5 "ti-processor-sdk-linux-sk-tda4vm-etcher-image.zip"  (SDK Linux from this link: https://www.ti.com/tool/download/PROCESSOR-SDK-LINUX-SK-TDA4VM/08.05.00.03).

    The problem is that there is no corresponding x86 installer (ti-processor-sdk-linux-j7-evm-08_xx_xx_11-Linux-x86-Install.bin) available .

    I built the application with version 9.2 and got library errors while trying to execute on the 8.5 version running on the TDA4VM. (predictably!)

    Is there a version available with the corresponding x86 installer that I can use to build and run a simple openGL ES/Wayland application?

    best,

    Ali

  • Ali,

    Yes, this is the one I built for SDK 8.5:

    https://github.com/krh/weston/blob/master/clients/simple-egl.c

    Some of the protocols are deprecated for SDK 9.2, hence why it does not work in current SDKs and needs an update.

    Regards,

    Erick

  • hi Erik,

    As I see, I have three possibilities now:

    1. Would the simple-egl.c example also run with Version: 08.06.00.11 (Release date: 14 Mar 2023)? I am asking as this is the oldest version that has both the SD card image and the x86 Linux installer available.

    2. alternatively, can I get the x86 Linux installer for the 8.5 version?

    3. on another note: can you provide the repository for one of the demo examples already running on the SDK9.2?

    Can you please help me with at least one of the above three possibilites?

    regards,

    Ali

  • 1. Would the simple-egl.c example also run with Version: 08.06.00.11 (Release date: 14 Mar 2023)? I am asking as this is the oldest version that has both the SD card image and the x86 Linux installer available.

    Yes, it will run with the 8.6 SDK as well.

    2. alternatively, can I get the x86 Linux installer for the 8.5 version?

    Yes, you can get the x86 Linux installer for the SDK 8.5 here: https://www.ti.com/tool/download/PROCESSOR-SDK-LINUX-J721E/08.05.00.08

    We might have miscommunication about what you mean when you say the x86 Linux installer. We have that available for all the SDK releases we have made.

    3. on another note: can you provide the repository for one of the demo examples already running on the SDK9.2?

    There are quite a few frameworks that run the update wayland protocols, but usually the wayland implementation is buried deep within their Windowing System abstraction layer. You can see the changes made to glmark2 for the updated protocol here: https://github.com/glmark2/glmark2/commit/58763e2c13db39ad7c1a994c261146154e4f0afa

    Of course, the changes in a simpler app were ~10 lines of code.

    Regards,

    Erick

  • We might have miscommunication about what you mean when you say the x86 Linux installer.

    By the  x86 installer, I mean the software package meant for PC installation rounded in blue. The one in red is the SD card image running on the TDA4.

  • As you can see, both are available for the version 8.6 (1th March 2023).

    However, I can only see the SD card image for the version 8.5 as shown below:

    So this has me a bit confused. 

    Does the x86 SDK link provided by you match the SD card image (8.6)?There seem to be 2 pages, one providing SD card images along with the x86 SDK installer. And another page just providing the installer. Or have I got it completely wrong?

    regards,

    Ali

  • Ali,

    I think I understand the situation now. So there are two boards for TDA4VM that TI provides, the EVM and the SK-board. I believe you are using the SK board then. Before SDK 8.6, we provided only the SD card image because they SoC is the same, it just uses a different device tree file, and different boot binaries.

    So, for SDK 8.5, you can download the Linux SDK from this link and it will also work, but it will require that you use different device trees and boot binaries because they are HS-FS devices. Unfortunately these details are lost in the history, but now I think we are on the same page.

    So, if you want to boot the SDK 8.5 on the SK board, you can use the SD card. You can get the components from the Linux SDK from the link above.

    Let me know if that's clear, and now we can see what you need to run the test.

    Regards,

    Erick

  • Hi Erik,

    Sorry for the late reply. 

    I had installed the wrong SDK(meant for the SK board). I have now corrected it to the SDK meant for the EVM board. 

    I am actually using the EVM common board with a TDAVM(J721EXSOMG01EVM). I have now installed the SDK from the link you provided. I am copying that link here for reference:

    https://www.ti.com/tool/download/PROCESSOR-SDK-LINUX-J721E/08.05.00.08

    I have created the SD card from the mksdboot.sh script in the "ti-processor-sdk-linux-j7-evm-08_05_00_08/bin" directory.

    Now I am trying to compile the same example as before (https://gist.github.com/propella/949261f89d83a6e184fb745a48de27c3 with version 8.5.

    I was getting missing "egl.h" error but I resolved it by including an "-I$(SDK_INSTALL_DIR)/targetNFS/usr/include/" with the gcc build command in the Makefile (targetNFS folder was the only place that I could find the egl.h file in the SDK installation ). Now, I am getting the following error from the "eglplatform.h" file:

    • i-processor-sdk-linux-j7-evm-08_05_00_08/targetNFS/usr/include/EGL/eglplatform.h:134:10: fatal error: X11/Xlib.h: No such file or directory
      134 | #include <X11/Xlib.h>

    The X11 folder refernced by "eglplatform.h:" is not there in the SDK installation. 

    The "egl.h" (and hence eglplatform.h are also referenced by the sample application that you built for the SDK8.5 (https://github.com/krh/weston/blob/master/clients/simple-egl.c). So I can not work with that as well. How do I get around this problem?

    regards,

    Ali

  • I was getting missing "egl.h" error but I resolved it by including an "-I$(SDK_INSTALL_DIR)/targetNFS/usr/include/" with the gcc build command in the Makefile (targetNFS folder was the only place that I could find the egl.h file in the SDK installation ). Now, I am getting the following error from the "eglplatform.h" file:

    • i-processor-sdk-linux-j7-evm-08_05_00_08/targetNFS/usr/include/EGL/eglplatform.h:134:10: fatal error: X11/Xlib.h: No such file or directory
      134 | #include <X11/Xlib.h>

    The X11 folder refernced by "eglplatform.h:" is not there in the SDK installation. 

    The "egl.h" (and hence eglplatform.h are also referenced by the sample application that you built for the SDK8.5 (https://github.com/krh/weston/blob/master/clients/simple-egl.c). So I can not work with that as well. How do I get around this problem?

    In the compilation, add the "EGL_NO_X11" flag, for example as defined "-DEGL_NO_X11". This will fix the issue with eglplatform.h.

  • Hi Erik,

    The eglplatform.h issue is resolved. Thanks for that. 

    I have two related issues now as I try to compile the simple-egl.c application that was suggested by you:

    Yes, this is the one I built for SDK 8.5:

    https://github.com/krh/weston/blob/master/clients/simple-egl.c

    I get the following linker errors:

     aarch64-none-linux-gnu/bin/ld: /tmp/ccLFgQIs.o: in function `pointer_handle_enter': simple-egl.c:(.text+0x12d8): undefined reference to `wl_cursor_image_get_buffer'

    I have similar errors for "wl_cursor_theme_load", "wl_cursor_theme_get_cursor" and "wl_cursor_theme_destroy".

    The problem that I have noted is that the header file and library paths (marked in red below) specified by the documentation (https://software-dl.ti.com/jacinto7/esd/processor-sdk-linux-jacinto7/08_05_00_08/exports/docs/linux/Overview/GCC_ToolChain.html) do not exist in the SDK installation on my PC:

    This is how the  "linux-devkit/sysroots" folder on my PC's SDK looks like:

    Therefore , I am pointing the gcc sysroot option to the "{SDK_INSTALL_DIR}/targetNFS" folder with an additional "-L${SDK_INSTALL_DIR}/linux-devkit/sysroots/aarch64-linux/usr/lib " option. 

    I have the following questions now:

    1. How can I fix the missing folder issue (if it is an issue at all)

    2. How can I fix the linker errors? (my understanding is that it is linked to the issue above)

    3. You can also suggest any other example that draws something on the screen. I chose this example as you have already tried it with the 8.5 version, which I am now using.

    regards,

    Ali

  • Ali,

     aarch64-none-linux-gnu/bin/ld: /tmp/ccLFgQIs.o: in function `pointer_handle_enter': simple-egl.c:(.text+0x12d8): undefined reference to `wl_cursor_image_get_buffer'

    Looks like it's missing a definition for this wayland function. One of the libraries in the sysroot should provide this function definition, perhaps libwayland, but need to find where that is located.

    1. How can I fix the missing folder issue (if it is an issue at all)

    Looks like the sysroots are somewhat built, but yes, it seems to be missing your <device-specific> folder in your sysroot. You can fix this by building Yocto on your own again. This is a tedious process with older SDK releases because there are small changes in the upstream projects used that can require small tweaks in the Yocto configurations/recipes to get it to build. But when you build Yocto and build the sysroots, you will get a folder specific to your machine (j7-evm, j721se-evm, etc.)

    2. How can I fix the linker errors? (my understanding is that it is linked to the issue above)

    Just need to install the library that has this function definition. Problem is identifying the library that has this definition and installing it into your sysroot. It's simple if you have a Yocto setup, it can be tedious without one.

    3. You can also suggest any other example that draws something on the screen. I chose this example as you have already tried it with the 8.5 version, which I am now using.

    This was an example that worked with SDK 8.5. Unfortunately the SDK is provided as reference and only has certain headers/libraries included. Sometimes we need to build Yocto pieces to get the dependencies you need. Wayland libraries are sometimes in non-standard locations (/usr/lib and /lib) so you might need to add those libraries to your build as well as the paths to them.

    Regards,

    Erick