如何解决如何创建与EGL一起使用的本机X11窗口
如何创建可在EGL中运行的本机X11窗口?遍历eglintro(https://www.khronos.org/registry/EGL/sdk/docs/man/html/eglIntro.xhtml)时,有关此问题的文档很少。或者,是否可以通过EGL本身创建本机窗口?我假设可以使用EGLNativeWindowType
来代替X11的本机窗口类型。
解决方法
否,EGL本身不提供Xlib包装器。您必须自己创建窗口。
以下是帮助您入门的最小样本。它指的是GLES2,但也应与GLES1一起使用。
首先,您声明Xlib对象(显示和窗口)。
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
#include <GLES2/gl2.h>
#include <EGL/egl.h>
// Native handles for window and display
Window win;
Display* xdisplay;
// EGL-related objects
EGLDisplay egl_display;
EGLConfig egl_conf;
EGLContext egl_context;
EGLSurface egl_surface;
int init_egl()
{
EGLint attr[] = {
EGL_SURFACE_TYPE,EGL_WINDOW_BIT,EGL_RED_SIZE,8,EGL_GREEN_SIZE,EGL_BLUE_SIZE,// EGL_RENDERABLE_TYPE,EGL_OPENGL_ES2_BIT,/* If one needs GLES2 */
EGL_NONE
};
EGLint num_config;
EGLint major,minor;
EGLint ctxattr[] = {
EGL_CONTEXT_CLIENT_VERSION,2,EGL_NONE
};
egl_display = eglGetDisplay( (EGLNativeDisplayType) xdisplay );
if ( egl_display == EGL_NO_DISPLAY ) {
printf("Error getting EGL display\n");
return 0;
}
if ( !eglInitialize( egl_display,&major,&minor ) ) {
printf("Error initializing EGL\n");
return 0;
}
printf("EGL major: %d,minor %d\n",major,minor);
/* create EGL rendering context */
if ( !eglChooseConfig( shell->egl_display,attr,&shell->egl_conf,1,&num_config ) ) {
printf("Failed to choose config (eglError: %x)\n",eglGetError());
return 0;
}
if ( num_config != 1 ) {
return 0;
}
egl_surface = eglCreateWindowSurface ( egl_display,egl_conf,win,NULL );
if (egl_surface == EGL_NO_SURFACE ) {
printf("CreateWindowSurface,EGL eglError: %d\n",eglGetError() );
return 0;
}
egl_context = eglCreateContext ( egl_display,EGL_NO_CONTEXT,ctxattr );
if ( egl_context == EGL_NO_CONTEXT ) {
printf("CreateContext,eglGetError() );
return 0;
}
return 1;
}
通过main
函数,您将调用X事件处理程序过程。我已对printf
调用进行了注释,以显示事件值的命名方式,因此无需查找文档。如果“事件循环”的概念不清楚,那么我建议阅读有关常规UI事件处理的文章。
void process_xevent(XEvent xev) {
// XNextEvent( xdisplay,&xev );
switch (xev.type)
{
case MotionNotify:
// printf("motion: %d %d\n",xev.xbutton.x,xev.xbutton.y);
break;
case KeyRelease:
// printf("rel (%d)\n",XLookupKeysym (&xev.xkey,0));
break;
case KeyPress:
// printf("keypress (%d)\n",0));
break;
case ButtonPress:
// printf("BPress: state = %d,button = %d,x = %d,y = %d\n",xev.xbutton.state,xev.xbutton.button,xev.xbutton.y);
// printf("Type=%d\n",(int)xev.xbutton.type);
break;
case ButtonRelease:
// printf("BRelease: state = %d,(int)xev.xbutton.type);
break;
}
}
最后,在main()例程中创建并打开display / Xwindow。
int main()
{
int egl_error;
Window root;
XSetWindowAttributes swa;
/* open standard display (primary screen) */
xdisplay = XOpenDisplay ( NULL );
if ( xdisplay == NULL ) {
printf("Error opening X display\n");
return 0;
}
打开显示器后,便会创建并显示该窗口。
最后,在main()例程中创建并打开display / Xwindow。
// get the root window (usually the whole screen)
root = DefaultRootWindow( shell->xdisplay );
// list all events this window accepts
swa.event_mask =
StructureNotifyMask |
ExposureMask |
PointerMotionMask |
KeyPressMask |
KeyReleaseMask |
ButtonPressMask |
ButtonReleaseMask;
// Xlib's window creation
win = XCreateWindow (
xdisplay,root,640,480,CopyFromParent,InputOutput,CWEventMask,&swa );
XMapWindow ( xdisplay,win ); // make window visible
XStoreName ( xdisplay,"EGL" );
打开窗口后,初始化EGL。
egl_error = init_egl();
if (!egl_error) {
return 1;
}
一旦有了EGL和Xlib对象,就可以开始事件处理循环。
while (1) {
int keycode;
XEvent xev;
if ( XPending ( xdisplay ) )
if (XCheckWindowEvent(shell->xdisplay,shell->win,global_event_mask,&xev))
process_xevent(shell,xev);
/* if (should_exit) { break; } // set some global flag if you want to exit */
eglMakeCurrent( egl_display,egl_surface,egl_context );
/* Call OpenGL as you see fit */
/* get rendered buffer to the screen */
eglSwapBuffers ( egl_display,egl_surface );
}
// deinitialize
}
这应该使您入门。该代码是从一个较大的项目中提取的,因此在删除不相关的内容时可能会引入错别字。
为得出答案并更精确地说,这里EGLNativeWindowType
专用于Window
头中的X11/Xlib.h
,而EGLNativeDisplayType
是Display*
。
一种更简单的方法可能是使用libxcb
,但是我没有经过测试的示例代码。 GLFW library是依赖于操作系统的OpenGL上下文创建例程的有用来源。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。