<div dir="ltr">OK ... I think I've gone as far as I could on my own here.<div><br></div><div>Context: prototyping doing an embedded device with GL ES 2 graphics without X, currently using a VMWare Player running a buildroot/busybox Linux environment.</div><div><br></div><div>Kernel 4.0.9 custom built with the VMWare GFX DRM driver.</div><div>Buildroot/busybox built using GlibC.</div><div><br></div><div>MESA 10.6.5 built with:</div><div><br></div><div><div>EFISMESA3D_CONF_OPTS += --enable-gles2 \</div><div>        --disable-glx \</div><div>        --enable-egl \</div><div>        --enable-dri \</div><div>        --with-egl-platforms=drm \</div><div>        --enable-sysfs \</div><div>        --with-dri-drivers= \</div><div>        --with-gallium-drivers=svga \</div><div>        --enable-gbm \</div><div>        --disable-xvmc \</div><div>        --disable-vdpau \</div><div>        --disable-va \</div><div>        --disable-dri3 \</div><div>        --with-llvm-prefix=$(STAGING_DIR)/usr/bin</div></div><div><br></div><div>Which gives me gbm, GLESv2, EGL and glapi. All seems well there.</div><div><br></div><div>also using lbdrm/kms 2.4.64.  I've installed the drm test executables, and modeprint/modetest run as expected.</div><div><br></div><div>So, I've been looking at the eglkms.c demo from mesa demos for inspiration ... oh and BTW, new to this world of OpenGL, and not an expert in C ... fairly experienced with higher level languages however.</div><div><br></div><div>I've modified it for GLES2 instead of OpenGL, and simplified it a bit since I'm targeting an embedded, fixed hardware platform (I don't detect connectors, for example, I hardcode it).</div><div><br></div><div>I've got my version of eglkms.c now compiling fine, and it can be made to run without error, with a few important caveats:</div><div><br></div><div>- For GLES initial testing, I just try to clear the screen with a colour.  This does not work.  Just black.  the Vmware window resizes, but that's it.</div><div>- In my clean up, eglTerminate() and eglDestroySurface() segfault.  If I comment both those out, the program terminates ok. not sure where to start looking for this problem.</div><div>- If I run my executable a few times in a row, I get a BO with a different stride after the first run.  the first run has stride 5120, and then 2560 for every other run after that.  I presume it's due to incorrect cleanup on the first run, but I'm not sure ...</div><div><br></div><div>I've been staring at the demo code and my own for too long now ... I can't see where my error(s) might be.  Always possible the demo itself no longer works right I suppose, I haven't tried to build it, since I don't have full OpenGL ...</div><div><br></div><div>Might anyone be able to have a look and provide some insight? Here is the code:</div><div><br></div><div><div>#include <fcntl.h></div><div>#include <stddef.h></div><div>#include <gbm.h></div><div>#include <stdlib.h></div><div>#include <EGL/egl.h></div><div>#include <GLES2/gl2.h></div><div>#include <stdio.h></div><div>#include <xf86drmMode.h></div><div>#include <unistd.h></div><div><br></div><div>static const EGLint context_client_version[] = {</div><div>EGL_CONTEXT_CLIENT_VERSION, 2,</div><div>EGL_NONE };</div><div><br></div><div>static const EGLint egl_fb_config[] = {</div><div>EGL_SURFACE_TYPE, EGL_WINDOW_BIT,</div><div>EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER,</div><div>EGL_RED_SIZE, 8,</div><div>EGL_GREEN_SIZE, 8,</div><div>EGL_BLUE_SIZE, 8,</div><div>EGL_ALPHA_SIZE, 8,</div><div>EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,</div><div>EGL_CONFORMANT, EGL_OPENGL_ES2_BIT,</div><div>EGL_NONE };</div><div><br></div><div>static const char device_name[] = "/dev/dri/card0";</div><div>static const uint32_t drm_mode_connector_id = 18;</div><div>static const uint32_t drm_mode_crtc_id = 21;</div><div><br></div><div>int main(void) {</div><div><br></div><div><span class="" style="white-space:pre">       </span>// Open the video card device in read/write mode.</div><div><span class="" style="white-space:pre">  </span>int fd;</div><div><span class="" style="white-space:pre">    </span>fd = open(device_name, O_RDWR);</div><div><br></div><div><span class="" style="white-space:pre">   </span>if (fd < 0) {</div><div><span class="" style="white-space:pre">           </span>/* Probably permissions error */</div><div><span class="" style="white-space:pre">           </span>printf("couldn't open %s, skipping\n", device_name);</div><div><span class="" style="white-space:pre">         </span>exit(EXIT_FAILURE);</div><div><span class="" style="white-space:pre">        </span>}</div><div><br></div><div><span class="" style="white-space:pre"> </span>// Create a GBM device out of it.  Keep the fd around though, we'll still need it.</div><div><span class="" style="white-space:pre">    </span>struct gbm_device *gbm;</div><div><span class="" style="white-space:pre">    </span>gbm = gbm_create_device(fd);</div><div><br></div><div><span class="" style="white-space:pre">      </span>if (gbm == NULL) {</div><div><span class="" style="white-space:pre">         </span>printf("GBM Device Creation Failed");</div><div><span class="" style="white-space:pre">            </span>exit(EXIT_FAILURE);</div><div><span class="" style="white-space:pre">        </span>}</div><div><br></div><div><span class="" style="white-space:pre"> </span>// Get an EGL display from the GBM device.</div><div><span class="" style="white-space:pre"> </span>EGLDisplay dpy;</div><div><span class="" style="white-space:pre">    </span>dpy = eglGetDisplay(gbm);</div><div><br></div><div><span class="" style="white-space:pre"> </span>if (dpy == EGL_NO_DISPLAY) {</div><div><span class="" style="white-space:pre">               </span>printf("Could not get EGL display");</div><div><span class="" style="white-space:pre">             </span>exit(EXIT_FAILURE);</div><div><span class="" style="white-space:pre">        </span>}</div><div><br></div><div><span class="" style="white-space:pre"> </span>// Initialize the display. Major and minor are version numbers.</div><div><span class="" style="white-space:pre">    </span>EGLint major, minor;</div><div><span class="" style="white-space:pre">       </span>if (eglInitialize(dpy, &major, &minor) == EGL_FALSE) {</div><div><span class="" style="white-space:pre">             </span>printf("Could initialize EGL display");</div><div><span class="" style="white-space:pre">          </span>exit(EXIT_FAILURE);</div><div><span class="" style="white-space:pre">        </span>}</div><div><br></div><div><span class="" style="white-space:pre"> </span>// Tell the EGL we will be using the GL ES API.</div><div><span class="" style="white-space:pre">    </span>EGLContext ctx;</div><div><br></div><div><span class="" style="white-space:pre">   </span>eglBindAPI(EGL_OPENGL_ES_API);</div><div><br></div><div><span class="" style="white-space:pre">    </span>// Choose the right framebuffer definition matching our requirements.</div><div><span class="" style="white-space:pre">      </span>EGLConfig config;</div><div><span class="" style="white-space:pre">  </span>EGLint n;</div><div><br></div><div><span class="" style="white-space:pre"> </span>if (!eglChooseConfig(dpy, egl_fb_config, &config, 1, &n) || n != 1) {</div><div><span class="" style="white-space:pre">              </span>printf("Failed to choose EGL FB config\n");</div><div><span class="" style="white-space:pre">              </span>exit(EXIT_FAILURE);</div><div><span class="" style="white-space:pre">        </span>}</div><div><br></div><div><span class="" style="white-space:pre"> </span>// Create an EGL context from the chosen config, and specify we want version 2 of GLES.</div><div><span class="" style="white-space:pre">    </span>ctx = eglCreateContext(dpy, config, EGL_NO_CONTEXT, context_client_version);</div><div><br></div><div><span class="" style="white-space:pre">      </span>if (ctx == EGL_NO_CONTEXT) {</div><div><span class="" style="white-space:pre">               </span>printf("Could not create context");</div><div><span class="" style="white-space:pre">              </span>exit(EXIT_FAILURE);</div><div><span class="" style="white-space:pre">        </span>}</div><div><br></div><div><span class="" style="white-space:pre"> </span>drmModeConnector *conn;</div><div><span class="" style="white-space:pre">    </span>uint32_t conn_id, width, height;</div><div><span class="" style="white-space:pre">   </span>drmModeModeInfo modeinfo;</div><div><span class="" style="white-space:pre">  </span>conn = drmModeGetConnector(fd, drm_mode_connector_id);</div><div><span class="" style="white-space:pre">     </span>conn_id = conn->connector_id;</div><div><span class="" style="white-space:pre">   </span>width = conn->modes[0].hdisplay;</div><div><span class="" style="white-space:pre">        </span>height = conn->modes[0].vdisplay;</div><div><span class="" style="white-space:pre">       </span>modeinfo = conn->modes[0];</div><div><span class="" style="white-space:pre">      </span>drmModeFreeConnector(conn);</div><div><br></div><div><span class="" style="white-space:pre">       </span>// Create a GBM surface, and then get an EGL surface from that.</div><div><span class="" style="white-space:pre">    </span>EGLSurface surface;</div><div><span class="" style="white-space:pre">        </span>struct gbm_surface *gs;</div><div><span class="" style="white-space:pre">    </span>gs = gbm_surface_create(gbm, width, height, GBM_BO_FORMAT_ARGB8888,</div><div><span class="" style="white-space:pre">                        </span>GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);</div><div><span class="" style="white-space:pre">        </span>surface = eglCreateWindowSurface(dpy, config, gs, NULL);</div><div><br></div><div><span class="" style="white-space:pre">  </span>if (eglMakeCurrent(dpy, surface, surface, ctx) == EGL_FALSE) {</div><div><span class="" style="white-space:pre">             </span>printf("Could not make context current");</div><div><span class="" style="white-space:pre">        </span>}</div><div><br></div><div><span class="" style="white-space:pre"> </span>// Render stuff. For now just clear the screen with a color, so we can at least tell it works.</div><div><span class="" style="white-space:pre">     </span>glClearColor(1.0f, 0.0f, 0.0f, 0.0f);</div><div><span class="" style="white-space:pre">      </span>glClear(GL_COLOR_BUFFER_BIT);</div><div><br></div><div><span class="" style="white-space:pre">     </span>eglSwapBuffers(dpy, surface);</div><div><br></div><div><span class="" style="white-space:pre">     </span>struct gbm_bo *bo;</div><div><span class="" style="white-space:pre"> </span>uint32_t handle, stride;</div><div><span class="" style="white-space:pre">   </span>bo = gbm_surface_lock_front_buffer(gs);</div><div><span class="" style="white-space:pre">    </span>handle = gbm_bo_get_handle(bo).u32;</div><div><span class="" style="white-space:pre">        </span>stride = gbm_bo_get_stride(bo);</div><div><br></div><div><span class="" style="white-space:pre">   </span>printf("handle=%d, stride=%d\n", handle, stride);</div><div><br></div><div><span class="" style="white-space:pre">       </span>int ret;</div><div><span class="" style="white-space:pre">   </span>uint32_t drm_fb_id;</div><div><span class="" style="white-space:pre">        </span>ret = drmModeAddFB(fd, width, height, 0, 32, stride, handle, &drm_fb_id);</div><div><span class="" style="white-space:pre">      </span>if (ret) {</div><div><span class="" style="white-space:pre">         </span>printf("failed to create fb\n");</div><div><span class="" style="white-space:pre">         </span>exit(EXIT_FAILURE);</div><div><span class="" style="white-space:pre">        </span>}</div><div><br></div><div><span class="" style="white-space:pre"> </span>ret = drmModeSetCrtc(fd, drm_mode_crtc_id, drm_fb_id, 0, 0, &conn_id, 1,</div><div><span class="" style="white-space:pre">                       </span>&modeinfo);</div><div><span class="" style="white-space:pre">    </span>if (ret) {</div><div><span class="" style="white-space:pre">         </span>printf("failed to set mode: %m\n");</div><div><span class="" style="white-space:pre">      </span>}</div><div><br></div><div><span class="" style="white-space:pre"> </span>sleep(2);</div><div><br></div><div><span class="" style="white-space:pre"> </span>gbm_surface_release_buffer(gs, bo);</div><div><span class="" style="white-space:pre">        </span>drmModeRmFB(fd, drm_fb_id);</div><div><span class="" style="white-space:pre">        </span>gbm_bo_destroy(bo);</div><div><span class="" style="white-space:pre">        </span>gbm_surface_destroy(gs);</div><div><span class="" style="white-space:pre">   </span>eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);</div><div><span class="" style="white-space:pre">       </span>eglDestroyContext(dpy, ctx);</div><div>//<span class="" style="white-space:pre">     </span>eglDestroySurface(dpy, surface);</div><div>//<span class="" style="white-space:pre"> </span>eglTerminate(dpy);</div><div><span class="" style="white-space:pre"> </span>gbm_device_destroy(gbm);</div><div><span class="" style="white-space:pre">   </span>close(fd);</div><div><span class="" style="white-space:pre"> </span>return 0;</div><div>}</div><div><br></div></div><div>Minimalistic for now, I know error checking and so on needs improvement ... for now I just want to make sure it is indeed possible to do what I want to do, so I'm doing the minimum required to get some gl commands to show something on the screen!</div><div><br></div><div>Thanks in advance for the help ...</div><div><br></div><div>J.F.</div></div>