普通文本  |  337行  |  11.9 KB

// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// To use runtime linking, uncomment the #define OPENGL_ES_IMPORT_FUNCTIONS,
// and pass libGLESxx.so libEGLxx.so in the command line as input
// parameters.
// Otherwise, comment out #define OPENGL_ES_IMPORT_FUNCTIONS and pass no
// parameters in the command line.

#include <stdio.h>

#include <EGL/egl.h>
#include <GLES2/gl2.h>

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

#define OPENGL_ES_IMPORT_FUNCTIONS

#ifdef OPENGL_ES_IMPORT_FUNCTIONS

#include <dlfcn.h>

EGLDisplay (*FP_eglGetDisplay)(NativeDisplayType display) = NULL;
EGLBoolean (*FP_eglInitialize)(EGLDisplay dpy,
                               EGLint* major,
                               EGLint* minor) = NULL;
EGLBoolean (*FP_eglGetConfigs)(EGLDisplay dpy,
                               EGLConfig* configs,
                               EGLint config_size,
                               EGLint* num_config) = NULL;
EGLBoolean (*FP_eglChooseConfig)(EGLDisplay dpy,
                                 const EGLint* attrib_list,
                                 EGLConfig* configs,
                                 EGLint config_size,
                                 EGLint* num_config) = NULL;
EGLContext (*FP_eglCreateContext)(EGLDisplay dpy,
                                  EGLConfig config,
                                  EGLContext share_list,
                                  const EGLint* attrib_list) = NULL;
EGLBoolean (*FP_eglGetConfigAttrib)(EGLDisplay dpy,
                                    EGLConfig config,
                                    EGLint attribute,
                                    EGLint* value) = NULL;
EGLSurface (*FP_eglCreateWindowSurface)(EGLDisplay dpy,
                                        EGLConfig config,
                                        NativeWindowType window,
                                        const EGLint* attrib_list) = NULL;
EGLBoolean (*FP_eglMakeCurrent)(EGLDisplay dpy,
                                EGLSurface draw,
                                EGLSurface read,
                                EGLContext ctx) = NULL;
EGLBoolean (*FP_eglDestroyContext)(EGLDisplay dpy, EGLContext ctx) = NULL;
EGLBoolean (*FP_eglDestroySurface)(EGLDisplay dpy, EGLSurface surface) = NULL;
EGLBoolean (*FP_eglTerminate)(EGLDisplay dpy) = NULL;
const char* (*FP_eglQueryString)(EGLDisplay dpy, EGLint name) = NULL;
const GLubyte* (*FP_glGetString)(GLenum name) = NULL;

#define eglGetDisplay FP_eglGetDisplay
#define eglInitialize FP_eglInitialize
#define eglGetConfigs FP_eglGetConfigs
#define eglChooseConfig FP_eglChooseConfig
#define eglCreateContext FP_eglCreateContext
#define eglGetConfigAttrib FP_eglGetConfigAttrib
#define eglCreateWindowSurface FP_eglCreateWindowSurface
#define eglMakeCurrent FP_eglMakeCurrent
#define eglDestroyContext FP_eglDestroyContext
#define eglDestroySurface FP_eglDestroySurface
#define eglTerminate FP_eglTerminate
#define eglQueryString FP_eglQueryString
#define glGetString FP_glGetString

typedef EGLDisplay (*FT_eglGetDisplay)(NativeDisplayType);
typedef EGLBoolean (*FT_eglInitialize)(EGLDisplay, EGLint*, EGLint*);
typedef EGLBoolean (*FT_eglGetConfigs)(EGLDisplay, EGLConfig*,
                                       EGLint, EGLint*);
typedef EGLBoolean (*FT_eglChooseConfig)(EGLDisplay, const EGLint*,
                                         EGLConfig*, EGLint, EGLint*);
typedef EGLContext (*FT_eglCreateContext)(EGLDisplay, EGLConfig,
                                          EGLContext, const EGLint*);
typedef EGLBoolean (*FT_eglGetConfigAttrib)(EGLDisplay, EGLConfig,
                                            EGLint, EGLint*);
typedef EGLSurface (*FT_eglCreateWindowSurface)(EGLDisplay, EGLConfig,
                                                NativeWindowType,
                                                const EGLint*);
typedef EGLBoolean (*FT_eglMakeCurrent)(EGLDisplay, EGLSurface,
                                        EGLSurface, EGLContext);
typedef EGLBoolean (*FT_eglDestroyContext)(EGLDisplay, EGLContext);
typedef EGLBoolean (*FT_eglDestroySurface)(EGLDisplay, EGLSurface);
typedef EGLBoolean (*FT_eglTerminate)(EGLDisplay);
typedef const char* (*FT_eglQueryString)(EGLDisplay, EGLint);
typedef const GLubyte* (*FT_glGetString)(GLenum);

bool LoadDLFunction(void** func_handle,
                    const char* func_name,
                    void* dl_handle) {
  *func_handle = dlsym(dl_handle, func_name);
  if (*func_handle == NULL) {
    printf("ERROR: fail to load %s\n", func_name);
    return false;
  }
  return true;
}

bool EntryImportGL(char* lib_gles, char* lib_egl,
                   void** handle_gles, void** handle_egl) {
  *handle_gles = dlopen(lib_gles, RTLD_LAZY);
  if (*handle_gles == NULL) {
    printf("ERROR: %s\n", dlerror());
    return false;
  }
  *handle_egl = dlopen(lib_egl, RTLD_LAZY);
  if (*handle_egl == NULL) {
    printf("ERROR: %s\n", dlerror());
    return false;
  }

  bool rt = true;
  void* tmp;
  rt &= LoadDLFunction(&tmp, "eglGetDisplay", *handle_egl);
  FP_eglGetDisplay = reinterpret_cast<FT_eglGetDisplay>(tmp);
  rt &= LoadDLFunction(&tmp, "eglInitialize", *handle_egl);
  FP_eglInitialize = reinterpret_cast<FT_eglInitialize>(tmp);
  rt &= LoadDLFunction(&tmp, "eglGetConfigs", *handle_egl);
  FP_eglGetConfigs = reinterpret_cast<FT_eglGetConfigs>(tmp);
  rt &= LoadDLFunction(&tmp, "eglChooseConfig", *handle_egl);
  FP_eglChooseConfig = reinterpret_cast<FT_eglChooseConfig>(tmp);
  rt &= LoadDLFunction(&tmp, "eglCreateContext", *handle_egl);
  FP_eglCreateContext = reinterpret_cast<FT_eglCreateContext>(tmp);
  rt &= LoadDLFunction(&tmp, "eglGetConfigAttrib", *handle_egl);
  FP_eglGetConfigAttrib = reinterpret_cast<FT_eglGetConfigAttrib>(tmp);
  rt &= LoadDLFunction(&tmp, "eglCreateWindowSurface", *handle_egl);
  FP_eglCreateWindowSurface = reinterpret_cast<FT_eglCreateWindowSurface>(tmp);
  rt &= LoadDLFunction(&tmp, "eglMakeCurrent", *handle_egl);
  FP_eglMakeCurrent = reinterpret_cast<FT_eglMakeCurrent>(tmp);
  rt &= LoadDLFunction(&tmp, "eglDestroyContext", *handle_egl);
  FP_eglDestroyContext = reinterpret_cast<FT_eglDestroyContext>(tmp);
  rt &= LoadDLFunction(&tmp, "eglDestroySurface", *handle_egl);
  FP_eglDestroySurface = reinterpret_cast<FT_eglDestroySurface>(tmp);
  rt &= LoadDLFunction(&tmp, "eglTerminate", *handle_egl);
  FP_eglTerminate = reinterpret_cast<FT_eglTerminate>(tmp);
  rt &= LoadDLFunction(&tmp, "eglQueryString", *handle_egl);
  FP_eglQueryString = reinterpret_cast<FT_eglQueryString>(tmp);
  rt &= LoadDLFunction(&tmp, "glGetString", *handle_gles);
  FP_glGetString = reinterpret_cast<FT_glGetString>(tmp);
  return rt;
}

void ExitImportGL(void* handle_gles, void* handle_egl) {
  if (handle_gles != NULL)
    dlclose(handle_gles);
  if (handle_egl != NULL)
    dlclose(handle_egl);
}

#endif  // OPENGL_ES_IMPORT_FUNCTIONS

bool InitGraphics(Display** display,
                  EGLDisplay* egl_display,
                  EGLContext* egl_context,
                  EGLSurface* egl_surface) {
  const int kWindowWidth = 100;
  const int kWindowHeight = 100;
  const EGLint config_attribs[] = {
    EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
    EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
    EGL_NONE
  };
  const EGLint context_attribs[] = {
    EGL_CONTEXT_CLIENT_VERSION, 2,
    EGL_NONE
  };

  // XWindow init.
  *display = XOpenDisplay(NULL);
  if (*display == NULL) {
    printf("ERROR: XOpenDisplay failed\n");
    return false;
  }

  int screen = XDefaultScreen(*display);
  Window window = XCreateSimpleWindow(*display, RootWindow(*display, screen),
                                      0, 0, kWindowWidth, kWindowHeight,
                                      0, 0, WhitePixel(*display, screen));
  XMapWindow(*display, window);
  XSync(*display, True);

  // EGL init.
  *egl_display = eglGetDisplay((EGLNativeDisplayType)*display);
  EGLint no_major, no_minor;
  EGLBoolean rt_code = eglInitialize(*egl_display, &no_major, &no_minor);
  if (rt_code == EGL_FALSE) {
    printf("ERROR: eglInitialize failed\n");
    return false;
  }
  // Print out version info.
  printf("EGL_VERSION = %d.%d\n",
         static_cast<int>(no_major),
         static_cast<int>(no_minor));
  // Config.
  EGLint num_configs;
  EGLConfig egl_config;
  rt_code = eglChooseConfig(*egl_display, config_attribs,
                            &egl_config, 1, &num_configs);
  if (rt_code == EGL_FALSE || num_configs != 1) {
    printf("ERROR: eglChooseConfig failed\n");
    return false;
  }
  // Surface.
  *egl_surface = eglCreateWindowSurface(*egl_display, egl_config,
                                        (NativeWindowType)window, NULL);
  if (*egl_surface == EGL_NO_SURFACE) {
    printf("ERROR: eglCreateWindowSurface failed\n");
    return false;
  }
  // Context.
  *egl_context = eglCreateContext(*egl_display, egl_config, EGL_NO_CONTEXT,
                                  context_attribs);
  if (*egl_context == EGL_NO_CONTEXT) {
    printf("ERROR: eglCreateContext failed\n");
    return false;
  }
  // Make current.
  rt_code = eglMakeCurrent(*egl_display, *egl_surface,
                           *egl_surface, *egl_context);
  if (rt_code == EGL_FALSE) {
    printf("ERROR: eglMakeCurrent failed\n");
    return false;
  }
  return true;
}

void ExitGraphics(EGLDisplay egl_display,
                  EGLContext egl_context,
                  EGLSurface egl_surface) {
  if (egl_display != EGL_NO_DISPLAY) {
    eglMakeCurrent(egl_display, NULL, NULL, NULL);
    if (egl_context != EGL_NO_CONTEXT)
      eglDestroyContext(egl_display, egl_context);
    if (egl_surface != EGL_NO_SURFACE)
      eglDestroySurface(egl_display, egl_surface);
    eglTerminate(egl_display);
  }
}

bool GetGLESVersion() {
  const GLubyte* version_string = glGetString(GL_VERSION);
  if (version_string == NULL) {
    printf("ERROR: glGetString(GL_VERSION) failed\n");
    return false;
  }
  printf("GLES_VERSION = %s\n", version_string);
  return true;
}

bool GetGLESExtensions() {
  const GLubyte* ext_string = glGetString(GL_EXTENSIONS);
  if (ext_string == NULL) {
    printf("ERROR: glGetString(GL_EXTENSIONS) failed\n");
    return false;
  }
  printf("GLES_EXTENSIONS = %s\n", ext_string);
  return true;
}

bool GetEGLExtensions(EGLDisplay egl_display) {
  const char* ext_string = eglQueryString(egl_display, EGL_EXTENSIONS);
  if (ext_string == NULL) {
    printf("ERROR: eglQueryString(EGL_EXTENSIONS) failed\n");
    return false;
  }
  printf("EGL_EXTENSIONS = %s\n", ext_string);
  return true;
}

bool GetXExtensions(Display* display) {
  int ext_num;
  char** ext_list = XListExtensions(display, &ext_num);
  printf("X_EXTENSIONS =");
  for (int i = 0; i < ext_num; ++i) {
    printf(" %s", ext_list[i]);
  }
  printf("\n");
  XFreeExtensionList(ext_list);
  return true;
}

int main(int argc, char* argv[]) {
  // Initialize graphics.
  Display* display;
  EGLDisplay egl_display = EGL_NO_DISPLAY;
  EGLContext egl_context = EGL_NO_CONTEXT;
  EGLSurface egl_surface = EGL_NO_SURFACE;

  bool rt_code = true;

#ifdef OPENGL_ES_IMPORT_FUNCTIONS
  if (argc != 3) {
    printf("ERROR: Usage: gles_APICheck libGLESxx.so libEGLxx.so\n");
    return 0;
  }
  void* handle_gles = NULL;
  void* handle_egl = NULL;
  rt_code = EntryImportGL(argv[1], argv[2], &handle_gles, &handle_egl);
#endif  // OPENGL_ES_IMPORT_FUNCTIONS

  // EGL version is printed out in InitGraphics
  if (rt_code)
    rt_code = InitGraphics(&display, &egl_display,
                           &egl_context, &egl_surface);

  // Get GLES version.
  if (rt_code)
    rt_code = GetGLESVersion();

  // Get GLES extentions.
  if (rt_code)
    rt_code = GetGLESExtensions();

  // Get EGL extentions.
  if (rt_code)
    rt_code = GetEGLExtensions(egl_display);

  // Get X11 extensions.
  if (rt_code)
    rt_code = GetXExtensions(display);

  ExitGraphics(egl_display, egl_context, egl_surface);
#ifdef OPENGL_ES_IMPORT_FUNCTIONS
  ExitImportGL(handle_gles, handle_egl);
#endif  // OPENGL_ES_IMPORT_FUNCTIONS
  printf("SUCCEED: run to the end\n");
  return 0;
}