Esempio n. 1
0
void test_triangle_smoothed(GLenum mode)
{
	GLint width, height;

	GLfloat vVertices[] = {
			 0.0f,  0.5f, 0.0f,
			-0.5f, -0.5f, 0.0f,
			 0.5f, -0.5f, 0.0f };
	GLfloat vColors[] = {
			1.0f, 0.0f, 0.0f, 1.0f,
			0.0f, 1.0f, 0.0f, 1.0f,
			0.0f, 0.0f, 1.0f, 1.0f};
	EGLSurface surface;

	RD_START("triangle-smoothed", "");

	display = get_display();

	/* get an appropriate EGL frame buffer configuration */
	ECHK(eglChooseConfig(display, config_attribute_list, &config, 1, &num_config));
	DEBUG_MSG("num_config: %d", num_config);

	/* create an EGL rendering context */
	ECHK(context = eglCreateContext(display, config, EGL_NO_CONTEXT, context_attribute_list));

	surface = make_window(display, config, 400, 240);

	ECHK(eglQuerySurface(display, surface, EGL_WIDTH, &width));
	ECHK(eglQuerySurface(display, surface, EGL_HEIGHT, &height));

	DEBUG_MSG("Buffer: %dx%d", width, height);

	/* connect the context to the surface */
	ECHK(eglMakeCurrent(display, surface, surface, context));

	program = get_program(vertex_shader_source, fragment_shader_source);

	GCHK(glBindAttribLocation(program, 0, "aPosition"));
	GCHK(glBindAttribLocation(program, 1, "aColor"));

	link_program(program);

	GCHK(glViewport(0, 0, width, height));

	GCHK(glFrontFace(mode));

	/* clear the color buffer */
	GCHK(glClearColor(0.0, 0.0, 0.0, 1.0));
	GCHK(glClear(GL_COLOR_BUFFER_BIT));

	GCHK(glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vVertices));
	GCHK(glEnableVertexAttribArray(0));

	GCHK(glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, vColors));
	GCHK(glEnableVertexAttribArray(1));

	GCHK(glDrawArrays(GL_TRIANGLES, 0, 3));

	ECHK(eglSwapBuffers(display, surface));
	GCHK(glFlush());

	ECHK(eglDestroySurface(display, surface));

	ECHK(eglTerminate(display));

	RD_END();
}
Esempio n. 2
0
/*
 * Create an RGB, double-buffered X window.
 * Return the window and context handles.
 */
static void
make_x_window(Display *x_dpy, EGLDisplay egl_dpy,
              const char *name,
              int x, int y, int width, int height,
              Window *winRet,
              EGLContext *ctxRet,
              EGLSurface *surfRet)
{
   static const EGLint attribs[] = {
      EGL_RED_SIZE, 1,
      EGL_GREEN_SIZE, 1,
      EGL_BLUE_SIZE, 1,
      EGL_DEPTH_SIZE, 1,
      EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
      EGL_NONE
   };
   static const EGLint ctx_attribs[] = {
      EGL_CONTEXT_CLIENT_VERSION, 2,
      EGL_NONE
   };
   int scrnum;
   XSetWindowAttributes attr;
   unsigned long mask;
   Window root;
   Window win;
   XVisualInfo *visInfo, visTemplate;
   int num_visuals;
   EGLContext ctx;
   EGLConfig config;
   EGLint num_configs;
   EGLint vid;

   scrnum = DefaultScreen( x_dpy );
   root = RootWindow( x_dpy, scrnum );

   if (!eglChooseConfig( egl_dpy, attribs, &config, 1, &num_configs)) {
      printf("Error: couldn't get an EGL visual config\n");
      exit(1);
   }

   assert(config);
   assert(num_configs > 0);

   if (!eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
      printf("Error: eglGetConfigAttrib() failed\n");
      exit(1);
   }

   /* The X window visual must match the EGL config */
   visTemplate.visualid = vid;
   visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
   if (!visInfo) {
      printf("Error: couldn't get X visual\n");
      exit(1);
   }

   /* window attributes */
   attr.background_pixel = 0;
   attr.border_pixel = 0;
   attr.colormap = XCreateColormap( x_dpy, root, visInfo->visual, AllocNone);
   attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask;
   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;

   win = XCreateWindow( x_dpy, root, 0, 0, width, height,
                        0, visInfo->depth, InputOutput,
                        visInfo->visual, mask, &attr );

   /* set hints and properties */
   {
      XSizeHints sizehints;
      sizehints.x = x;
      sizehints.y = y;
      sizehints.width  = width;
      sizehints.height = height;
      sizehints.flags = USSize | USPosition;
      XSetNormalHints(x_dpy, win, &sizehints);
      XSetStandardProperties(x_dpy, win, name, name,
                              None, (char **)NULL, 0, &sizehints);
   }

#if USE_FULL_GL /* XXX fix this when eglBindAPI() works */
   eglBindAPI(EGL_OPENGL_API);
#else
   eglBindAPI(EGL_OPENGL_ES_API);
#endif

   ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, ctx_attribs );
   if (!ctx) {
      printf("Error: eglCreateContext failed\n");
      exit(1);
   }

   /* test eglQueryContext() */
   {
      EGLint val;
      eglQueryContext(egl_dpy, ctx, EGL_CONTEXT_CLIENT_VERSION, &val);
      assert(val == 2);
   }

   *surfRet = eglCreateWindowSurface(egl_dpy, config, win, NULL);
   if (!*surfRet) {
      printf("Error: eglCreateWindowSurface failed\n");
      exit(1);
   }

   /* sanity checks */
   {
      EGLint val;
      eglQuerySurface(egl_dpy, *surfRet, EGL_WIDTH, &val);
      assert(val == width);
      eglQuerySurface(egl_dpy, *surfRet, EGL_HEIGHT, &val);
      assert(val == height);
      assert(eglGetConfigAttrib(egl_dpy, config, EGL_SURFACE_TYPE, &val));
      assert(val & EGL_WINDOW_BIT);
   }

   XFree(visInfo);

   *winRet = win;
   *ctxRet = ctx;
}
Esempio n. 3
0
static int egl_create_context(struct vo_wayland_state *wl,
                              MPGLContext *ctx,
                              bool enable_alpha)
{
    EGLint major, minor, n;

    GL *gl = ctx->gl;
    const char *eglstr = "";

    if (!(wl->egl_context.egl.dpy = eglGetDisplay(wl->display.display)))
        return -1;

    EGLint config_attribs[] = {
        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
        EGL_RED_SIZE, 1,
        EGL_GREEN_SIZE, 1,
        EGL_BLUE_SIZE, 1,
        EGL_ALPHA_SIZE, enable_alpha,
        EGL_DEPTH_SIZE, 1,
        EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
        EGL_NONE
    };

    /* major and minor here returns the supported EGL version (e.g.: 1.4) */
    if (eglInitialize(wl->egl_context.egl.dpy, &major, &minor) != EGL_TRUE)
        return -1;

    MP_VERBOSE(wl, "EGL version %d.%d\n", major, minor);

    EGLint context_attribs[] = {
        // aka EGL_CONTEXT_MAJOR_VERSION_KHR
        EGL_CONTEXT_CLIENT_VERSION, 3,
        EGL_NONE
    };

    if (eglBindAPI(EGL_OPENGL_API) != EGL_TRUE)
        return -1;

    eglChooseConfig(wl->egl_context.egl.dpy, config_attribs,
                    &wl->egl_context.egl.conf, 1, &n);

    wl->egl_context.egl.ctx = eglCreateContext(wl->egl_context.egl.dpy,
                                               wl->egl_context.egl.conf,
                                               EGL_NO_CONTEXT,
                                               context_attribs);
    if (!wl->egl_context.egl.ctx) {
        /* fallback to any GL version */
        MP_WARN(wl, "can't create context for requested OpenGL version: "
                    "fall back to any version available\n");
        context_attribs[0] = EGL_NONE;
        wl->egl_context.egl.ctx = eglCreateContext(wl->egl_context.egl.dpy,
                                                   wl->egl_context.egl.conf,
                                                   EGL_NO_CONTEXT,
                                                   context_attribs);

        if (!wl->egl_context.egl.ctx)
            return -1;
    }

    eglMakeCurrent(wl->egl_context.egl.dpy, NULL, NULL, wl->egl_context.egl.ctx);

    eglstr = eglQueryString(wl->egl_context.egl.dpy, EGL_EXTENSIONS);

    mpgl_load_functions(gl, (void*(*)(const GLubyte*))eglGetProcAddress, eglstr,
                        wl->log);

    ctx->native_display_type = "wl";
    ctx->native_display = wl->display.display;

    return 0;
}
Esempio n. 4
0
///
// CreateEGLContext()
//
//    Creates an EGL rendering context and all associated elements
//
EGLBoolean CreateEGLContext ( EGLNativeWindowType hWnd, EGLDisplay* eglDisplay,
                              EGLContext* eglContext, EGLSurface* eglSurface,
                              EGLint attribList[])
{
   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 };

   // Get Display
   display = eglGetDisplay((EGLNativeDisplayType)x_display);
   if ( display == EGL_NO_DISPLAY )
   {
      return EGL_FALSE;
   }

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

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

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

   // Create a surface
   surface = eglCreateWindowSurface(display, config, (EGLNativeWindowType)hWnd, 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;
   }
   
   *eglDisplay = display;
   *eglSurface = surface;
   *eglContext = context;
   return EGL_TRUE;
} 
void EGLPlatformContext::init(const QSurfaceFormat &format, QPlatformOpenGLContext *share)
{
    m_format = EglUtils::glFormatFromConfig(m_eglDisplay, m_eglConfig);
    // m_format now has the renderableType() resolved (it cannot be Default anymore)
    // but does not yet contain version, profile, options.
    m_shareContext = share ? static_cast<EGLPlatformContext *>(share)->m_eglContext : 0;

    QVector<EGLint> contextAttrs;
    contextAttrs.append(EGL_CONTEXT_CLIENT_VERSION);
    contextAttrs.append(format.majorVersion());
    const bool hasKHRCreateContext = EglUtils::hasEglExtension(m_eglDisplay, "EGL_KHR_create_context");
    if (hasKHRCreateContext) {
        contextAttrs.append(EGL_CONTEXT_MINOR_VERSION_KHR);
        contextAttrs.append(format.minorVersion());
        int flags = 0;
        // The debug bit is supported both for OpenGL and OpenGL ES.
        if (format.testOption(QSurfaceFormat::DebugContext))
            flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
        // The fwdcompat bit is only for OpenGL 3.0+.
        if (m_format.renderableType() == QSurfaceFormat::OpenGL
                && format.majorVersion() >= 3
                && !format.testOption(QSurfaceFormat::DeprecatedFunctions))
            flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
        if (flags) {
            contextAttrs.append(EGL_CONTEXT_FLAGS_KHR);
            contextAttrs.append(flags);
        }
        // Profiles are OpenGL only and mandatory in 3.2+. The value is silently ignored for < 3.2.
        if (m_format.renderableType() == QSurfaceFormat::OpenGL) {
            contextAttrs.append(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR);
            contextAttrs.append(format.profile() == QSurfaceFormat::CoreProfile
                                ? EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR
                                : EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR);
        }
    }
    contextAttrs.append(EGL_NONE);
    m_contextAttrs = contextAttrs;

    switch (m_format.renderableType()) {
    case QSurfaceFormat::OpenVG:
        m_api = EGL_OPENVG_API;
        break;
#ifdef EGL_VERSION_1_4
    case QSurfaceFormat::OpenGL:
        m_api = EGL_OPENGL_API;
        break;
#endif // EGL_VERSION_1_4
    default:
        m_api = EGL_OPENGL_ES_API;
        break;
    }

    eglBindAPI(m_api);
    m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig, m_shareContext, contextAttrs.constData());
    if (m_eglContext == EGL_NO_CONTEXT && m_shareContext != EGL_NO_CONTEXT) {
        m_shareContext = 0;
        m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig, 0, contextAttrs.constData());
    }

    if (m_eglContext == EGL_NO_CONTEXT) {
        qCWarning(lcEglConvenience, "Failed to create context: %x", eglGetError());
        return;
    }

    static const bool printConfig = qEnvironmentVariableIntValue("GREENISLAND_QPA_DEBUG");
    if (printConfig) {
        qCInfo(lcEglConvenience) << "Created context for format" << format << "with config:";
        EglUtils::printEglConfig(m_eglDisplay, m_eglConfig);
    }

    // Cannot just call updateFormatFromGL() since it relies on virtuals. Defer it to initialize().
}
void EGLPlatformContext::updateFormatFromGL()
{
#ifndef QT_NO_OPENGL
    // Have to save & restore to prevent QOpenGLContext::currentContext() from becoming
    // inconsistent after QOpenGLContext::create().
    EGLDisplay prevDisplay = eglGetCurrentDisplay();
    if (prevDisplay == EGL_NO_DISPLAY) // when no context is current
        prevDisplay = m_eglDisplay;
    EGLContext prevContext = eglGetCurrentContext();
    EGLSurface prevSurfaceDraw = eglGetCurrentSurface(EGL_DRAW);
    EGLSurface prevSurfaceRead = eglGetCurrentSurface(EGL_READ);

    // Rely on the surfaceless extension, if available. This is beneficial since we can
    // avoid creating an extra pbuffer surface which is apparently troublesome with some
    // drivers (Mesa) when certain attributes are present (multisampling).
    EGLSurface tempSurface = EGL_NO_SURFACE;
    EGLContext tempContext = EGL_NO_CONTEXT;
    if (m_flags.testFlag(NoSurfaceless) || !EglUtils::hasEglExtension(m_eglDisplay, "EGL_KHR_surfaceless_context"))
        tempSurface = createTemporaryOffscreenSurface();

    EGLBoolean ok = eglMakeCurrent(m_eglDisplay, tempSurface, tempSurface, m_eglContext);
    if (!ok) {
        EGLConfig config = EglUtils::configFromGLFormat(m_eglDisplay, m_format, false, EGL_PBUFFER_BIT);
        tempContext = eglCreateContext(m_eglDisplay, config, 0, m_contextAttrs.constData());
        if (tempContext != EGL_NO_CONTEXT)
            ok = eglMakeCurrent(m_eglDisplay, tempSurface, tempSurface, tempContext);
    }
    if (ok) {
        if (m_format.renderableType() == QSurfaceFormat::OpenGL
                || m_format.renderableType() == QSurfaceFormat::OpenGLES) {
            const GLubyte *s = glGetString(GL_VERSION);
            if (s) {
                QByteArray version = QByteArray(reinterpret_cast<const char *>(s));
                int major, minor;
                if (QPlatformOpenGLContext::parseOpenGLVersion(version, major, minor)) {
#ifdef Q_OS_ANDROID
                    // Some Android 4.2.2 devices report OpenGL ES 3.0 without the functions being available.
                    static int apiLevel = QtAndroidPrivate::androidSdkVersion();
                    if (apiLevel <= 17 && major >= 3) {
                        major = 2;
                        minor = 0;
                    }
#endif
                    m_format.setMajorVersion(major);
                    m_format.setMinorVersion(minor);
                }
            }
            m_format.setProfile(QSurfaceFormat::NoProfile);
            m_format.setOptions(QSurfaceFormat::FormatOptions());
            if (m_format.renderableType() == QSurfaceFormat::OpenGL) {
                // Check profile and options.
                if (m_format.majorVersion() < 3) {
                    m_format.setOption(QSurfaceFormat::DeprecatedFunctions);
                } else {
                    GLint value = 0;
                    glGetIntegerv(GL_CONTEXT_FLAGS, &value);
                    if (!(value & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT))
                        m_format.setOption(QSurfaceFormat::DeprecatedFunctions);
                    if (value & GL_CONTEXT_FLAG_DEBUG_BIT)
                        m_format.setOption(QSurfaceFormat::DebugContext);
                    if (m_format.version() >= qMakePair(3, 2)) {
                        value = 0;
                        glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &value);
                        if (value & GL_CONTEXT_CORE_PROFILE_BIT)
                            m_format.setProfile(QSurfaceFormat::CoreProfile);
                        else if (value & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
                            m_format.setProfile(QSurfaceFormat::CompatibilityProfile);
                    }
                }
            }
        }
        runGLchecks();
        eglMakeCurrent(prevDisplay, prevSurfaceDraw, prevSurfaceRead, prevContext);
    } else {
        qCWarning(lcEglConvenience, "Failed to make temporary surface current, format not updated (%x)", eglGetError());
    }
    if (tempSurface != EGL_NO_SURFACE)
        destroyTemporaryOffscreenSurface(tempSurface);
    if (tempContext != EGL_NO_CONTEXT)
        eglDestroyContext(m_eglDisplay, tempContext);
#endif // QT_NO_OPENGL
}
Esempio n. 7
0
static bool egl_create_context(struct vo_wayland_state *wl,
                               struct egl_context *egl_ctx,
                               MPGLContext *ctx,
                               bool enable_alpha)
{
    EGLint major, minor, n;

    GL *gl = ctx->gl;
    const char *eglstr = "";

    if (!(egl_ctx->egl.dpy = eglGetDisplay(wl->display.display)))
        return false;

    EGLint config_attribs[] = {
        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
        EGL_RED_SIZE, 1,
        EGL_GREEN_SIZE, 1,
        EGL_BLUE_SIZE, 1,
        EGL_ALPHA_SIZE, enable_alpha,
        EGL_DEPTH_SIZE, 1,
        EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
        EGL_NONE
    };

    /* major and minor here returns the supported EGL version (e.g.: 1.4) */
    if (eglInitialize(egl_ctx->egl.dpy, &major, &minor) != EGL_TRUE)
        return false;

    MP_VERBOSE(wl->vo, "EGL version %d.%d\n", major, minor);

    EGLint context_attribs[] = {
        EGL_CONTEXT_MAJOR_VERSION_KHR,
        MPGL_VER_GET_MAJOR(ctx->requested_gl_version),
        /* EGL_CONTEXT_MINOR_VERSION_KHR, */
        /* MPGL_VER_GET_MINOR(ctx->requested_gl_version), */
        /* EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR, 0, */
        /* Segfaults on anything else than the major version */
        EGL_NONE
    };

    if (eglBindAPI(EGL_OPENGL_API) != EGL_TRUE)
        return false;

    eglChooseConfig(egl_ctx->egl.dpy, config_attribs,
                    &egl_ctx->egl.conf, 1, &n);

    egl_ctx->egl.ctx = eglCreateContext(egl_ctx->egl.dpy,
                                        egl_ctx->egl.conf,
                                        EGL_NO_CONTEXT,
                                        context_attribs);
    if (!egl_ctx->egl.ctx) {
        /* fallback to any GL version */
        context_attribs[0] = EGL_NONE;
        egl_ctx->egl.ctx = eglCreateContext(egl_ctx->egl.dpy,
                                            egl_ctx->egl.conf,
                                            EGL_NO_CONTEXT,
                                            context_attribs);

        if (!egl_ctx->egl.ctx)
            return false;
    }

    eglMakeCurrent(egl_ctx->egl.dpy, NULL, NULL, egl_ctx->egl.ctx);

    eglstr = eglQueryString(egl_ctx->egl.dpy, EGL_EXTENSIONS);

    mpgl_load_functions(gl, (void*(*)(const GLubyte*))eglGetProcAddress, eglstr);
    if (!gl->BindProgram)
        mpgl_load_functions(gl, NULL, eglstr);

    return true;
}
Esempio n. 8
0
static gboolean _initialize_opengl_backend (gboolean bForceOpenGL)
{
	gboolean bStencilBufferAvailable = TRUE, bAlphaAvailable = TRUE;
	
	// open a connection (= Display) to the graphic server
	EGLNativeDisplayType display_id = EGL_DEFAULT_DISPLAY;  // XDisplay*, wl_display*, etc; Note: we could pass our X Display instead of making a new connection...
	EGLDisplay *dpy = s_eglDisplay = eglGetDisplay (display_id);
	
	int major, minor;
	if (! eglInitialize (dpy, &major, &minor))
	{
		cd_warning ("Can't initialise EGL display, OpenGL will not be available");
		return FALSE;
	}
	g_print ("EGL version: %d;%d\n", major, minor);
	
	// find a Frame Buffer Configuration (= Visual) that supports the features we need
	EGLint config_attribs[] = {
		EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
		EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,  // EGL_OPENGL_ES2_BIT
		EGL_RED_SIZE, 8,
		EGL_GREEN_SIZE, 8,
		EGL_BLUE_SIZE, 8,
		EGL_DEPTH_SIZE, 1,
		EGL_ALPHA_SIZE, 8,
		EGL_STENCIL_SIZE , 1,
		EGL_SAMPLES, 4,
		EGL_SAMPLE_BUFFERS, 1,
		EGL_NONE
	};
	const EGLint ctx_attribs[] = {
		EGL_NONE
	};
	
	EGLConfig config;
	EGLint numConfigs=0;
	eglChooseConfig (dpy, config_attribs, &config, 1, &numConfigs);
	if (numConfigs == 0)
	{
		cd_warning ("couldn't find an appropriate visual, trying to get one without Stencil buffer\n(it may cause some little deterioration in the rendering) ...");
		config_attribs[14] = EGL_NONE;
		bStencilBufferAvailable = FALSE;
		eglChooseConfig (dpy, config_attribs, &config, 1, &numConfigs);
		
		if (numConfigs == 0 && bForceOpenGL)
		{
			// if still no luck, and user insisted on using OpenGL, give up on transparency.
			if (bForceOpenGL)
			{
				cd_warning ("we could not get an ARGB-visual, trying to get an RGB one (fake transparency will be used in return) ...");
				config_attribs[12] = None;
				bAlphaAvailable = FALSE;
				eglChooseConfig (dpy, config_attribs, &config, 1, &numConfigs);
			}
		}
		
		if (numConfigs == 0)
		{
			cd_warning ("No EGL config matching an RGBA buffer, OpenGL will not be available");
			return FALSE;
		}
	}
	g_openglConfig.bStencilBufferAvailable = bStencilBufferAvailable;
	g_openglConfig.bAlphaAvailable = bAlphaAvailable;
	s_eglConfig = config;
	
	// create a rendering context (All other context will share ressources with it, and it will be the default context in case no other context exist)
	eglBindAPI (EGL_OPENGL_API);  // specify the type of client API context before we create one.
	
	s_eglContext = eglCreateContext (dpy, config, EGL_NO_CONTEXT, ctx_attribs);
	if (s_eglContext == EGL_NO_CONTEXT)
	{
		cd_warning ("Couldn't create an EGL context, OpenGL will not be available");
		return FALSE;
	}
	
	// check some texture abilities
	g_openglConfig.bTextureFromPixmapAvailable = _check_client_egl_extension ("EGL_EXT_texture_from_pixmap");
	cd_debug ("bTextureFromPixmapAvailable: %d", g_openglConfig.bTextureFromPixmapAvailable);
	if (g_openglConfig.bTextureFromPixmapAvailable)
	{
		g_openglConfig.bindTexImage = (gpointer)eglGetProcAddress ("eglBindTexImageEXT");
		g_openglConfig.releaseTexImage = (gpointer)eglGetProcAddress ("eglReleaseTexImageEXT");
		g_openglConfig.bTextureFromPixmapAvailable = (g_openglConfig.bindTexImage && g_openglConfig.releaseTexImage);
	}
	
	return TRUE;
}
Esempio n. 9
0
//display
int init_display()
{
	int32_t			success = 0;
	EGLBoolean		result;
	EGLint			num_config;

	DISPMANX_ELEMENT_HANDLE_T	dispman_element;
	DISPMANX_DISPLAY_HANDLE_T	dispman_display;
	DISPMANX_UPDATE_HANDLE_T	dispman_update;
	VC_RECT_T					dst_rect;
	VC_RECT_T					src_rect;
	EGLConfig					config;

	//creates problem is func eglCreateContext
	static const EGLint attribute_list[] =
	{
		//EGL_COLOR_BUFFER_TYPE,	 	EGL_LUMINANCE_BUFFER, //EGL_RGB_BUFFER
		EGL_RED_SIZE,   			8,	// default is 0
		EGL_GREEN_SIZE, 			8,
		EGL_BLUE_SIZE,  			8,
		EGL_ALPHA_SIZE, 			8,
		//EGL_LUMINANCE_SIZE, 		8,
		EGL_SURFACE_TYPE, 			EGL_WINDOW_BIT,
		EGL_NONE
	};

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

	memset( &m_display, 0, sizeof(display) );

	bcm_host_init(); // must be called be4 any gpu function is called

	m_display.display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
	if (m_display.display==EGL_NO_DISPLAY)
	{
		printf("init_opengl : error in eglGetDisplay\n");
		exit(-1);
	}

	result = eglInitialize(m_display.display, NULL, NULL);
	if (EGL_FALSE == result)
	{
		printf("init_opengl : error in initializing EGL Display\n");
		exit(-1);
	}

	result = eglChooseConfig(m_display.display, attribute_list, &config, 17*sizeof(attribute_list[0]), &num_config);
	if (EGL_FALSE == result)
	{
		printf("init_opengl : error in getting egl frame buffer configuration\n");
		exit(-1);
	}

	result = eglBindAPI(EGL_OPENGL_ES_API);
	if (EGL_FALSE == result)
	{
		printf("init_opengl : error in binding api\n");
		exit(-1);
	}

	m_display.context = eglCreateContext(m_display.display, config, EGL_NO_CONTEXT, context_attributes);
	if (m_display.context==EGL_NO_CONTEXT)
	{
		printf("init_opengl : error in creating context . \n");
		exit(-1);
	}


	// create an EGL window surface (video core api)(bug 1920*1080 always)(only for rpi)
	success = graphics_get_display_size(0 /*display number*/, &m_display.scr_width, &m_display.scr_height);
	if ( success < 0 )
	{
		printf("init_opengl : error in creating EGL window surface\n");
		exit(-1);
	}

	if ( glGetError() != 0 )
	{
		printf("init_opengl : error - exit point 1.\n");
		exit(-1);
	}

	dst_rect.x = 0;
	dst_rect.y = 0;
	dst_rect.width = m_display.scr_width;
	dst_rect.height = m_display.scr_height;

	src_rect.x = 0;
	src_rect.y = 0;
	src_rect.width = m_display.scr_width << 16;
	src_rect.height = m_display.scr_height << 16;        

	dispman_display = vc_dispmanx_display_open( 0 /*display number*/);
	dispman_update = vc_dispmanx_update_start( 0 );

	dispman_element = 
	vc_dispmanx_element_add(dispman_update, dispman_display,
							0/*layer*/, &dst_rect, 0/*src*/,
							&src_rect, DISPMANX_PROTECTION_NONE, 
							0 /*alpha*/, 0/*clamp*/, (DISPMANX_TRANSFORM_T)0/*transform*/);

	m_display.nativewindow.element = dispman_element;
	m_display.nativewindow.width   = m_display.scr_width;
	m_display.nativewindow.height  = m_display.scr_height;
	vc_dispmanx_update_submit_sync( dispman_update );
	if ( glGetError() != 0 )
	{
		printf("init_opengl : error - exit point 2.\n");
		exit(-1);
	}

	m_display.surface = eglCreateWindowSurface( m_display.display, config, &m_display.nativewindow, NULL );
	if(m_display.surface == EGL_NO_SURFACE)
	{
		printf("init_opengl : error could not create window surface\n");
		exit(-1);
	}

	// connect the context to the surface
	result = eglMakeCurrent(m_display.display, m_display.surface, m_display.surface, m_display.context);
	if ( EGL_FALSE == result )
	{
		printf("init_opengl : error - could not connect context to surface\n");
		exit(-1);
	}
	if ( glGetError() != 0 )
	{
		printf("init_opengl : error - exit point 3.\n");
		exit(-1);
	}

	glClear( GL_COLOR_BUFFER_BIT );
	glViewport ( 0, 0, m_display.scr_width, m_display.scr_height ); 
	if ( glGetError() != 0 )
	{
		printf("init_opengl : error - exit point 4.\n");
		exit(-1);
	}

	m_display.scr_aspect_ratio = (float) ( ((float)m_display.scr_width) / ((float)m_display.scr_height) );
	return(0);
}
Esempio n. 10
0
///
//  esCreateWindow()
//
//      width - width of window to create
//      height - height of window to create
//      flags  - bitwise or of window creation flags
//          ES_WINDOW_ALPHA       - specifies that the framebuffer should have alpha
//          ES_WINDOW_DEPTH       - specifies that a depth buffer should be created
//          ES_WINDOW_STENCIL     - specifies that a stencil buffer should be created
//          ES_WINDOW_MULTISAMPLE - specifies that a multi-sample buffer should be created
//
GLboolean ESUTIL_API esCreateWindow(ESContext *esContext, GLint width, GLint height, GLuint flags) {
  EGLint attribList[] = {
    EGL_RED_SIZE,       8,
    EGL_GREEN_SIZE,     8,
    EGL_BLUE_SIZE,      8,
    EGL_ALPHA_SIZE,  8,
    EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
    EGL_NONE
  };

  if (esContext == NULL) {
    return GL_FALSE;
  }

  esContext->width = width;
  esContext->height = height;

  int32_t success = 0;

  static EGL_DISPMANX_WINDOW_T nativewindow;

  DISPMANX_ELEMENT_HANDLE_T dispman_element;
  DISPMANX_DISPLAY_HANDLE_T dispman_display;
  DISPMANX_UPDATE_HANDLE_T dispman_update;
  VC_RECT_T dst_rect;
  VC_RECT_T src_rect;


  int display_width;
  int display_height;

  // create an EGL window surface, passing context width/height
  success = graphics_get_display_size(0 /* LCD */, &display_width, &display_height);
  if (success < 0) {
    return EGL_FALSE;
  }

  dst_rect.x = 0;
  dst_rect.y = 0;
  dst_rect.width = display_width;
  dst_rect.height = display_height;

  src_rect.x = 0;
  src_rect.y = 0;
  src_rect.width = display_width << 16;
  src_rect.height = display_height << 16;

  dispman_display = vc_dispmanx_display_open(0 /* LCD */);
  dispman_update = vc_dispmanx_update_start(0);

  dispman_element = vc_dispmanx_element_add(dispman_update, dispman_display,
                    0/*layer*/, &dst_rect, 0/*src*/,
                    &src_rect, DISPMANX_PROTECTION_NONE, 0 /*alpha*/, 0/*clamp*/, 0/*transform*/);

  nativewindow.element = dispman_element;
  nativewindow.width = display_width;
  nativewindow.height = display_height;
  vc_dispmanx_update_submit_sync(dispman_update);

  esContext->hWnd = &nativewindow;
  esContext->width = display_width;
  esContext->height = display_height;


  EGLint numConfigs;
  EGLint majorVersion;
  EGLint minorVersion;
  EGLDisplay display;
  EGLContext context;
  EGLSurface surface;
  EGLConfig config;
  EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };


  display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
  if (display == EGL_NO_DISPLAY) {
    return GL_FALSE;
  }

  if (!eglInitialize(display, &majorVersion, &minorVersion)) {
    return GL_FALSE;
  }

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

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


  // Create a surface
  surface = eglCreateWindowSurface(display, config, esContext->hWnd, NULL);
  if (surface == EGL_NO_SURFACE) {
    return GL_FALSE;
  }

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

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

  esContext->eglDisplay = display;
  esContext->eglSurface = surface;
  esContext->eglContext = context;
  return GL_TRUE;
}
Esempio n. 11
0
		void RenderWorld::init()
		{
			const EGLint attribs[] =
			{
				EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
				EGL_BLUE_SIZE, 8,
				EGL_GREEN_SIZE, 8,
				EGL_RED_SIZE, 8,
				EGL_DEPTH_SIZE, 16,
				EGL_NONE
			};
			EGLint format;
			EGLint numConfigs;
			EGLConfig config;

			mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
			eglInitialize(mDisplay, 0, 0);
			eglChooseConfig(mDisplay, attribs, &config, 1, &numConfigs);
			eglGetConfigAttrib(mDisplay, config, EGL_NATIVE_VISUAL_ID, &format);

			ANativeWindow_setBuffersGeometry(mAndroidApp->window, 0, 0, format);

			mSurface = eglCreateWindowSurface(mDisplay, config, mAndroidApp->window, NULL);

			EGLint c_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
			mContext = eglCreateContext(mDisplay, config, 0, c_attribs);

			if (eglMakeCurrent(mDisplay, mSurface, mSurface, mContext) == EGL_FALSE)
				throw Exception("eglMakeCurrent failed");

			eglQuerySurface(mDisplay, mSurface, EGL_WIDTH, &mWidth);
			eglQuerySurface(mDisplay, mSurface, EGL_HEIGHT, &mHeight);

			mView = Matrix::createLookAt(Vector3::ONE*25, Vector3::ZERO, Vector3::UNIT_Y);
			mProj = Matrix::createPerspectiveFOV(Math::PI/3.0f, (float)mWidth/(float)mHeight, 1.0f, 1000.0f);

			glEnable(GL_DEPTH_TEST);
			glDepthFunc(GL_LESS);

			glEnable(GL_CULL_FACE);
			glCullFace(GL_BACK);

			shared_ptr<ResourceLoader> vloader(new VertexShaderLoader);
			shared_ptr<ResourceLoader> ploader(new PixelShaderLoader);
			shared_ptr<ResourceLoader> mloader(new MeshLoader);
			shared_ptr<ResourceLoader> tloader(new TextureLoader);
			shared_ptr<ResourceLoader> mtloader(new MaterialLoader);
			shared_ptr<ResourceLoader> skloader(new SkinLoader);

			ResourceManager& rman = Engine::getPtr()->getResourceManager();
			rman.addLoader(vloader);
			rman.addLoader(ploader);
			rman.addLoader(mloader);
			rman.addLoader(tloader);
			rman.addLoader(mtloader);
			rman.addLoader(skloader);

			VertexShader* vshader = rman.get<VertexShader>("test.vs");
			PixelShader* pshader = rman.get<PixelShader>("test.fs");

			mProgram = new Program;
			mProgram->attach(*vshader);
			mProgram->attach(*pshader);
			mProgram->link();
		}
Esempio n. 12
0
bool RendererGlAndroid::initialize( ANativeWindow *nativeWindow, RendererRef sharedRenderer )
{
	std::vector<EGLint> configAttribs;

	// OpenGL ES 3 also uses EGL_OPENGL_ES2_BIT
	configAttribs.push_back( EGL_RENDERABLE_TYPE ); configAttribs.push_back( EGL_OPENGL_ES2_BIT );
	configAttribs.push_back( EGL_SURFACE_TYPE    ); configAttribs.push_back( EGL_WINDOW_BIT );
	configAttribs.push_back( EGL_RED_SIZE        ); configAttribs.push_back( 8 );
	configAttribs.push_back( EGL_GREEN_SIZE      ); configAttribs.push_back( 8 );
	configAttribs.push_back( EGL_BLUE_SIZE       ); configAttribs.push_back( 8 );
	configAttribs.push_back( EGL_ALPHA_SIZE      ); configAttribs.push_back( EGL_DONT_CARE );
	configAttribs.push_back( EGL_DEPTH_SIZE      ); configAttribs.push_back( mRenderer->getOptions().getDepthBufferDepth() );
	configAttribs.push_back( EGL_STENCIL_SIZE    ); configAttribs.push_back( mRenderer->getOptions().getStencil() ? 8 : EGL_DONT_CARE );
	configAttribs.push_back( EGL_SAMPLE_BUFFERS  ); configAttribs.push_back( 1 );
	configAttribs.push_back( EGL_NONE            );

	EGLint surfaceAttribList[] =
	{
		EGL_NONE, EGL_NONE
	};

	mDisplay = eglGetDisplay( EGL_DEFAULT_DISPLAY );
	if( mDisplay == EGL_NO_DISPLAY) {
		return false;
	}

	EGLint majorVersion, minorVersion;
	if( ! eglInitialize( mDisplay, &majorVersion, &minorVersion ) ) {
		return false;
	}

	eglBindAPI( EGL_OPENGL_ES_API );
	if( eglGetError() != EGL_SUCCESS ) {
		return false;
	}

	EGLint configCount;
	if( ! eglChooseConfig( mDisplay, configAttribs.data(), &mConfig, 1, &configCount ) || (configCount != 1) ) {
		return false;
	}

	//
	// EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is
	// guaranteed to be accepted by ANativeWindow_setBuffersGeometry().
	// As soon as we picked a EGLConfig, we can safely reconfigure the
	// ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID.
	//
	EGLint format;
	eglGetConfigAttrib( mDisplay, mConfig, EGL_NATIVE_VISUAL_ID, &format );
	ANativeWindow_setBuffersGeometry( nativeWindow, 0, 0, format );	

	mSurface = eglCreateWindowSurface( mDisplay, mConfig, nativeWindow, NULL );

	auto err = eglGetError();
	if( err != EGL_SUCCESS ) {
		return false;
	}

	EGLint contextAttibutes[] = {
#if defined( CINDER_GL_ES_3 )
		EGL_CONTEXT_CLIENT_VERSION, 3,
#else
		EGL_CONTEXT_CLIENT_VERSION, 2,
#endif
		EGL_NONE
	};

	mContext = eglCreateContext( mDisplay, mConfig, NULL, contextAttibutes );
	if( eglGetError() != EGL_SUCCESS ) {
		return false;
	}
	checkGlStatus();

	eglMakeCurrent( mDisplay, mSurface, mSurface, mContext );
	if( eglGetError() != EGL_SUCCESS ) {
		return false;
	}
	checkGlStatus();

	gl::Environment::setEs();
	gl::env()->initializeFunctionPointers();
	checkGlStatus();

	std::shared_ptr<gl::PlatformDataAndroid> platformData( new gl::PlatformDataAndroid( mContext, mDisplay, mSurface, mConfig ) );
	platformData->mObjectTracking = mRenderer->getOptions().getObjectTracking();

	mCinderContext = gl::Context::createFromExisting( platformData );
	checkGlStatus();

	// Get device screen size
	{
		EGLint width;
		EGLint height;
		eglQuerySurface( mDisplay, mSurface, EGL_WIDTH, &width );
		eglQuerySurface( mDisplay, mSurface, EGL_HEIGHT, &height );
		RendererGlAndroid::sSurfaceSize = ivec2( width, height );
	}

	mCinderContext->makeCurrent();
	checkGlStatus();

	// NOTE: 'interval' value of 0 causes the Samsung S6 to not render correctly on startup.
	//
	eglSwapInterval( mDisplay, 1 );
	checkGlStatus();

	return true;
}
Esempio n. 13
0
	void GlContext::create(uint32_t _width, uint32_t _height)
	{
#	if BX_PLATFORM_RPI
		bcm_host_init();
#	endif // BX_PLATFORM_RPI

		m_eglLibrary = eglOpen();

		if (NULL == g_platformData.context)
		{
#	if BX_PLATFORM_RPI
			g_platformData.ndt = EGL_DEFAULT_DISPLAY;
#	endif // BX_PLATFORM_RPI

			BX_UNUSED(_width, _height);
			EGLNativeDisplayType ndt = (EGLNativeDisplayType)g_platformData.ndt;
			EGLNativeWindowType  nwh = (EGLNativeWindowType )g_platformData.nwh;

#	if BX_PLATFORM_WINDOWS
			if (NULL == g_platformData.ndt)
			{
				ndt = GetDC( (HWND)g_platformData.nwh);
			}
#	endif // BX_PLATFORM_WINDOWS

			m_display = eglGetDisplay(ndt);
			BGFX_FATAL(m_display != EGL_NO_DISPLAY, Fatal::UnableToInitialize, "Failed to create display %p", m_display);

			EGLint major = 0;
			EGLint minor = 0;
			EGLBoolean success = eglInitialize(m_display, &major, &minor);
			BGFX_FATAL(success && major >= 1 && minor >= 3, Fatal::UnableToInitialize, "Failed to initialize %d.%d", major, minor);

			BX_TRACE("EGL info:");
			const char* clientApis = eglQueryString(m_display, EGL_CLIENT_APIS);
			BX_TRACE("   APIs: %s", clientApis); BX_UNUSED(clientApis);

			const char* vendor = eglQueryString(m_display, EGL_VENDOR);
			BX_TRACE(" Vendor: %s", vendor); BX_UNUSED(vendor);

			const char* version = eglQueryString(m_display, EGL_VERSION);
			BX_TRACE("Version: %s", version); BX_UNUSED(version);

			const char* extensions = eglQueryString(m_display, EGL_EXTENSIONS);
			BX_TRACE("Supported EGL extensions:");
			dumpExtensions(extensions);

			EGLint attrs[] =
			{
				EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,

#	if BX_PLATFORM_ANDROID
				EGL_DEPTH_SIZE, 16,
#	else
				EGL_DEPTH_SIZE, 24,
#	endif // BX_PLATFORM_
				EGL_STENCIL_SIZE, 8,

				EGL_NONE
			};

			EGLint numConfig = 0;
			success = eglChooseConfig(m_display, attrs, &m_config, 1, &numConfig);
			BGFX_FATAL(success, Fatal::UnableToInitialize, "eglChooseConfig");

#	if BX_PLATFORM_ANDROID

			EGLint format;
			eglGetConfigAttrib(m_display, m_config, EGL_NATIVE_VISUAL_ID, &format);
			ANativeWindow_setBuffersGeometry( (ANativeWindow*)g_platformData.nwh, _width, _height, format);

#	elif BX_PLATFORM_RPI
			DISPMANX_DISPLAY_HANDLE_T dispmanDisplay = vc_dispmanx_display_open(0);
			DISPMANX_UPDATE_HANDLE_T  dispmanUpdate  = vc_dispmanx_update_start(0);

			VC_RECT_T dstRect = { 0, 0, int32_t(_width),        int32_t(_height)       };
			VC_RECT_T srcRect = { 0, 0, int32_t(_width)  << 16, int32_t(_height) << 16 };

			DISPMANX_ELEMENT_HANDLE_T dispmanElement = vc_dispmanx_element_add(dispmanUpdate
				, dispmanDisplay
				, 0
				, &dstRect
				, 0
				, &srcRect
				, DISPMANX_PROTECTION_NONE
				, NULL
				, NULL
				, DISPMANX_NO_ROTATE
				);

			s_dispmanWindow.element = dispmanElement;
			s_dispmanWindow.width   = _width;
			s_dispmanWindow.height  = _height;
			nwh = &s_dispmanWindow;

			vc_dispmanx_update_submit_sync(dispmanUpdate);
#	endif // BX_PLATFORM_ANDROID

			m_surface = eglCreateWindowSurface(m_display, m_config, nwh, NULL);
			BGFX_FATAL(m_surface != EGL_NO_SURFACE, Fatal::UnableToInitialize, "Failed to create surface.");

			const bool hasEglKhrCreateContext = !!bx::findIdentifierMatch(extensions, "EGL_KHR_create_context");
			const bool hasEglKhrNoError       = !!bx::findIdentifierMatch(extensions, "EGL_KHR_create_context_no_error");

			for (uint32_t ii = 0; ii < 2; ++ii)
			{
				bx::StaticMemoryBlockWriter writer(s_contextAttrs, sizeof(s_contextAttrs) );

				EGLint flags = 0;

#	if BX_PLATFORM_RPI
				BX_UNUSED(hasEglKhrCreateContext, hasEglKhrNoError);
#else
				if (hasEglKhrCreateContext)
				{
					bx::write(&writer, EGLint(EGL_CONTEXT_MAJOR_VERSION_KHR) );
					bx::write(&writer, EGLint(BGFX_CONFIG_RENDERER_OPENGLES / 10) );

					bx::write(&writer, EGLint(EGL_CONTEXT_MINOR_VERSION_KHR) );
					bx::write(&writer, EGLint(BGFX_CONFIG_RENDERER_OPENGLES % 10) );

					flags |= BGFX_CONFIG_DEBUG && hasEglKhrNoError ? 0
						| EGL_CONTEXT_FLAG_NO_ERROR_BIT_KHR
						: 0
						;

					if (0 == ii)
					{
						flags |= BGFX_CONFIG_DEBUG ? 0
							| EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR
//							| EGL_OPENGL_ES3_BIT_KHR
							: 0
							;

						bx::write(&writer, EGLint(EGL_CONTEXT_FLAGS_KHR) );
						bx::write(&writer, flags);
					}
				}
				else
#	endif // BX_PLATFORM_RPI
				{
					bx::write(&writer, EGLint(EGL_CONTEXT_CLIENT_VERSION) );
					bx::write(&writer, 2);
				}

				bx::write(&writer, EGLint(EGL_NONE) );

				m_context = eglCreateContext(m_display, m_config, EGL_NO_CONTEXT, s_contextAttrs);
				if (NULL != m_context)
				{
					break;
				}

				BX_TRACE("Failed to create EGL context with EGL_CONTEXT_FLAGS_KHR (%08x).", flags);
			}

			BGFX_FATAL(m_context != EGL_NO_CONTEXT, Fatal::UnableToInitialize, "Failed to create context.");

			success = eglMakeCurrent(m_display, m_surface, m_surface, m_context);
			BGFX_FATAL(success, Fatal::UnableToInitialize, "Failed to set context.");
			m_current = NULL;

			eglSwapInterval(m_display, 0);
		}

		import();
	}
Esempio n. 14
0
int main(int argc, char *argv[])
{
    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    assert(display != EGL_NO_DISPLAY);
    assert(eglGetError() == EGL_SUCCESS);

    EGLint major = 0, minor = 0;
    EGLBoolean ret = eglInitialize(display, &major, &minor);
    assert(eglGetError() == EGL_SUCCESS);
    assert(ret == EGL_TRUE);
    assert(major * 10000 + minor >= 10004);

    EGLint numConfigs;
    ret = eglGetConfigs(display, NULL, 0, &numConfigs);
    assert(eglGetError() == EGL_SUCCESS);
    assert(ret == EGL_TRUE);

    EGLint attribs[] = {
        EGL_RED_SIZE, 5,
        EGL_GREEN_SIZE, 6,
        EGL_BLUE_SIZE, 5,
        EGL_NONE
    };
    EGLConfig config;
    ret = eglChooseConfig(display, attribs, &config, 1, &numConfigs);
    assert(eglGetError() == EGL_SUCCESS);
    assert(ret == EGL_TRUE);

    EGLNativeWindowType dummyWindow;
    EGLSurface surface = eglCreateWindowSurface(display, config, dummyWindow, NULL);
    assert(eglGetError() == EGL_SUCCESS);
    assert(surface != 0);

    // WebGL maps to GLES2. GLES1 is not supported.
    EGLint contextAttribsOld[] =
    {
        EGL_CONTEXT_CLIENT_VERSION, 1,
        EGL_NONE
    };
    EGLContext context = eglCreateContext(display, config, NULL, contextAttribsOld);
    assert(eglGetError() != EGL_SUCCESS);

    //Test for invalid attribs
    EGLint contextInvalidAttribs[] =
    {
        EGL_CONTEXT_CLIENT_VERSION, 2,
        0xFFFF, -1,
        EGL_NONE
    };
    context = eglCreateContext(display, config, NULL, contextInvalidAttribs);
    assert(eglGetError() != EGL_SUCCESS);
    assert(context == 0);
    //Test for missing terminator
    EGLint contextAttribsMissingTerm[] =
    {
        EGL_CONTEXT_CLIENT_VERSION, 2,
    };
    context = eglCreateContext(display, config, NULL, contextAttribsMissingTerm);
    assert(eglGetError() != EGL_SUCCESS);
    assert(context == 0);
    //Test for null terminator
    EGLint contextAttribsNullTerm[] =
    {
        EGL_CONTEXT_CLIENT_VERSION, 2,
        0
    };
    context = eglCreateContext(display, config, NULL, contextAttribsNullTerm);
    assert(eglGetError() != EGL_SUCCESS);
    assert(context == 0);
    //Test for invalid and null terminator
    EGLint contextAttribsNullTermInvalid[] =
    {
        0,
    };
    context = eglCreateContext(display, config, NULL, contextAttribsNullTermInvalid);
    assert(eglGetError() != EGL_SUCCESS);
    assert(context == 0);

    // The correct attributes, should create a good EGL context
    EGLint contextAttribs[] =
    {
        EGL_CONTEXT_CLIENT_VERSION, 2,
        EGL_NONE
    };
    context = eglCreateContext(display, config, NULL, contextAttribs);
    assert(eglGetError() == EGL_SUCCESS);
    assert(context != 0);

    assert(eglGetCurrentContext() == 0); // Creating a context does not yet activate it.
    assert(eglGetError() == EGL_SUCCESS);

    ret = eglMakeCurrent(display, surface, surface, context);
    assert(eglGetError() == EGL_SUCCESS);
    assert(ret == EGL_TRUE);
    assert(eglGetCurrentContext() == context);
    assert(eglGetCurrentSurface(EGL_READ) == surface);
    assert(eglGetCurrentSurface(EGL_DRAW) == surface);

    glClearColor(1.0,0.0,0.0,0.5);
    glClear(GL_COLOR_BUFFER_BIT);

    ret = eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    assert(eglGetError() == EGL_SUCCESS);
    assert(ret == EGL_TRUE);
    assert(eglGetCurrentContext() == EGL_NO_CONTEXT);
    assert(eglGetCurrentSurface(EGL_READ) == EGL_NO_SURFACE);
    assert(eglGetCurrentSurface(EGL_DRAW) == EGL_NO_SURFACE);

    assert(eglSwapInterval(display, 0) == EGL_TRUE);
    assert(eglGetError() == EGL_SUCCESS);
    assert(eglSwapInterval(display, 1) == EGL_TRUE);
    assert(eglGetError() == EGL_SUCCESS);
    assert(eglSwapInterval(display, 2) == EGL_TRUE);
    assert(eglGetError() == EGL_SUCCESS);

    ret = eglTerminate(display);
    assert(eglGetError() == EGL_SUCCESS);
    assert(ret == EGL_TRUE);

    // eglGetProcAddress() without active GL context and/or connected EGL display (after eglTerminate) is required to work, even though the returned function
    // pointers cannot be called unless an active context is available:
    // "return value of NULL indicates that the specified function does not exist for the implementation."
    // "Client API function pointers returned by eglGetProcAddress are independent of the display and the currently bound client API context, and may be used by any client API context which supports the function."
    // At https://www.khronos.org/registry/EGL/specs/eglspec.1.5.pdf, pages 82-32.
    assert(eglGetProcAddress("glClear") != 0);
    assert(eglGetProcAddress("glWakaWaka") == 0);

#ifdef REPORT_RESULT
    REPORT_RESULT(result);
#endif
}
Esempio n. 15
0
/* Must be called in the gl thread */
GstGLWindow *
gst_gl_window_new (gulong external_gl_context)
{
    GstGLWindow *window = g_object_new (GST_GL_TYPE_WINDOW, NULL);
    GstGLWindowPrivate *priv = window->priv;

    EGLint config_attrib[] = {
        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
        EGL_DEPTH_SIZE, 16,
        EGL_NONE
    };

    EGLint context_attrib[] = {
        EGL_CONTEXT_CLIENT_VERSION, 2,
        EGL_NONE
    };

    EGLint majorVersion;
    EGLint minorVersion;
    EGLint numConfigs;
    EGLConfig config;

    XSetWindowAttributes win_attr;
    XTextProperty text_property;
    XWMHints wm_hints;
    unsigned long mask;
    const gchar *title = "OpenGL renderer";
    Atom wm_atoms[3];

    static gint x = 0;
    static gint y = 0;

    setlocale (LC_NUMERIC, "C");

    priv->x_lock = g_mutex_new ();
    priv->cond_send_message = g_cond_new ();
    priv->running = TRUE;
    priv->visible = FALSE;
    priv->parent = 0;
    priv->allow_extra_expose_events = TRUE;

    g_mutex_lock (priv->x_lock);

    priv->device = XOpenDisplay (priv->display_name);

    XSynchronize (priv->device, FALSE);

    g_debug ("gl device id: %ld\n", (gulong) priv->device);

    priv->disp_send = XOpenDisplay (priv->display_name);

    XSynchronize (priv->disp_send, FALSE);

    g_debug ("gl display sender: %ld\n", (gulong) priv->disp_send);

    priv->screen_num = DefaultScreen (priv->device);
    priv->root = RootWindow (priv->device, priv->screen_num);
    priv->depth = DefaultDepth (priv->device, priv->screen_num);

    g_debug ("gl root id: %lud\n", (gulong) priv->root);

    priv->device_width = DisplayWidth (priv->device, priv->screen_num);
    priv->device_height = DisplayHeight (priv->device, priv->screen_num);

    priv->visual_info = g_new0 (XVisualInfo, 1);
    XMatchVisualInfo (priv->device, priv->screen_num, priv->depth, TrueColor,
                      priv->visual_info);

    win_attr.event_mask =
        StructureNotifyMask | ExposureMask | VisibilityChangeMask;
    win_attr.do_not_propagate_mask = NoEventMask;

    win_attr.background_pixmap = None;
    win_attr.background_pixel = 0;
    win_attr.border_pixel = 0;

    win_attr.colormap =
        XCreateColormap (priv->device, priv->root, priv->visual_info->visual,
                         AllocNone);

    mask = CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask;

    x += 20;
    y += 20;

    priv->internal_win_id = XCreateWindow (priv->device, priv->root, x, y,
                                           1, 1, 0, priv->visual_info->depth, InputOutput,
                                           priv->visual_info->visual, mask, &win_attr);

    if (!priv->internal_win_id) {
        g_debug ("XCreateWindow failed\n");
        goto failure;
    }

    XSync (priv->device, FALSE);

    XSetWindowBackgroundPixmap (priv->device, priv->internal_win_id, None);

    g_debug ("gl window id: %lud\n", (gulong) priv->internal_win_id);

    g_debug ("gl window props: x:%d y:%d\n", x, y);

    wm_atoms[0] = XInternAtom (priv->device, "WM_DELETE_WINDOW", True);
    if (wm_atoms[0] == None)
        g_debug ("Cannot create WM_DELETE_WINDOW\n");

    wm_atoms[1] = XInternAtom (priv->device, "WM_GL_WINDOW", False);
    if (wm_atoms[1] == None)
        g_debug ("Cannot create WM_GL_WINDOW\n");

    wm_atoms[2] = XInternAtom (priv->device, "WM_QUIT_LOOP", False);
    if (wm_atoms[2] == None)
        g_debug ("Cannot create WM_QUIT_LOOP\n");

    XSetWMProtocols (priv->device, priv->internal_win_id, wm_atoms, 2);

    wm_hints.flags = StateHint;
    wm_hints.initial_state = NormalState;
    wm_hints.input = False;

    XStringListToTextProperty ((char **) &title, 1, &text_property);

    XSetWMProperties (priv->device, priv->internal_win_id, &text_property,
                      &text_property, 0, 0, NULL, &wm_hints, NULL);

    XFree (text_property.value);

    priv->gl_display = eglGetDisplay ((EGLNativeDisplayType) priv->device);

    if (eglInitialize (priv->gl_display, &majorVersion, &minorVersion))
        g_debug ("egl initialized: %d.%d\n", majorVersion, minorVersion);
    else {
        g_debug ("failed to initialize egl %ld, %s\n", (gulong) priv->gl_display,
                 EGLErrorString ());
        goto failure;
    }

    if (eglChooseConfig (priv->gl_display, config_attrib, &config, 1,
                         &numConfigs))
        g_debug ("config set: %ld, %ld\n", (gulong) config, (gulong) numConfigs);
    else {
        g_debug ("failed to set config %ld, %s\n", (gulong) priv->gl_display,
                 EGLErrorString ());
        goto failure;
    }

    priv->gl_surface =
        eglCreateWindowSurface (priv->gl_display, config,
                                (EGLNativeWindowType) priv->internal_win_id, NULL);
    if (priv->gl_surface != EGL_NO_SURFACE)
        g_debug ("surface created: %ld\n", (gulong) priv->gl_surface);
    else {
        g_debug ("failed to create surface %ld, %ld, %ld, %s\n",
                 (gulong) priv->gl_display, (gulong) priv->gl_surface,
                 (gulong) priv->gl_display, EGLErrorString ());
        goto failure;
    }

    g_debug ("about to create gl context\n");

    priv->gl_context =
        eglCreateContext (priv->gl_display, config,
                          (EGLContext) (guint) external_gl_context, context_attrib);

    if (priv->gl_context != EGL_NO_CONTEXT)
        g_debug ("gl context created: %ld\n", (gulong) priv->gl_context);
    else {
        g_debug ("failed to create glcontext %ld, %ld, %s\n",
                 (gulong) priv->gl_context, (gulong) priv->gl_display,
                 EGLErrorString ());
        goto failure;
    }

    if (!eglMakeCurrent (priv->gl_display, priv->gl_surface, priv->gl_surface,
                         priv->gl_context)) {
        g_debug ("failed to make opengl context current %ld, %s\n",
                 (gulong) priv->gl_display, EGLErrorString ());
        goto failure;
    }

    g_mutex_unlock (priv->x_lock);

    return window;

failure:
    g_mutex_unlock (priv->x_lock);
    g_object_unref (G_OBJECT (window));
    return NULL;
}
Esempio n. 16
0
/*****************************************************************************
* Function Name  : ApiInitAPI
* Returns        : true for success
* Description    : Initialise the 3D API
*****************************************************************************/
bool PVRShellInit::ApiInitAPI()
{
	int					bDone;

	m_NDT = (EGLNativeDisplayType)OsGetNativeDisplayType();
	m_NPT = (EGLNativePixmapType) OsGetNativePixmapType();
	m_NWT = (EGLNativeWindowType) OsGetNativeWindowType();

	m_EGLContext = 0;

	do
	{
		bDone = true;

		m_EGLDisplay = eglGetDisplay(m_NDT);

		if(m_EGLDisplay == EGL_NO_DISPLAY)
		{
#if defined(BUILD_OGLES2) || defined(BUILD_OVG) || defined(BUILD_OGLES3)
			m_EGLDisplay = eglGetDisplay((EGLNativeDisplayType)EGL_DEFAULT_DISPLAY);
#else
			m_EGLDisplay = eglGetDisplay((NativeDisplayType)EGL_DEFAULT_DISPLAY);
#endif
		}

		if(!eglInitialize(m_EGLDisplay, &m_MajorVersion, &m_MinorVersion))
		{
			m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Unable to initialise EGL\n");
			m_pShell->PVRShellOutputDebug("PVRShell: EGL Error (%s)\n", StringFrom_eglGetError());
			return false;
		}

		m_pShell->PVRShellOutputDebug("PVRShell: EGL %d.%d initialized\n", m_MajorVersion, m_MinorVersion);

		// Check Extension avaliablility after EGL initialization
		if (m_MajorVersion > 1 || (m_MajorVersion == 1 && m_MinorVersion >= 1))
		{
			m_bPowerManagementSupported = true;
		}
		else
		{
			m_bPowerManagementSupported = PVRShellIsExtensionSupported(m_EGLDisplay,"EGL_IMG_power_management");
		}

		do
		{
			// bind OpenVG API if requested
			if(m_pShell->m_pShellData->bNeedOpenVG)
			{
#ifndef BUILD_OVG
				m_pShell->PVRShellSet(prefExitMessage, "PVRShell: OpenVG not supported. Compile with BUILD_OVG defined.");
				return false;
#else
				if(!eglBindAPI(EGL_OPENVG_API))
				{
					m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Failed to bind OpenVG API\n");
					return false;
				}

				m_pShell->PVRShellOutputDebug("PVRShell: OpenVG bound\n");
#endif
			}
			else
			{
#if defined(BUILD_OGL)
				if(!eglBindAPI(EGL_OPENGL_API))
				{
					m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Failed to bind OpenGL API\n");
					return false;
				}
#else
#if defined EGL_VERSION_1_3 && defined GL_ES_VERSION_2_0

				if(!eglBindAPI(EGL_OPENGL_ES_API))
				{
					m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Failed to bind OpenGL ES API\n");
					return false;
				}
#endif
#endif
			}

			// Find an EGL config
			m_EGLConfig = SelectEGLConfiguration(m_pShell->m_pShellData);
			eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_CONFIG_ID, &m_iConfig);

			// Destroy the context if we already created one
			if (m_EGLContext)
			{
				eglDestroyContext(m_EGLDisplay, m_EGLContext);
			}

			// Attempt to create a context
			EGLint ai32ContextAttribs[32];
			int	i = 0;

#if defined(EGL_VERSION_1_3) && defined(GL_ES_VERSION_2_0)
			ai32ContextAttribs[i++] = EGL_CONTEXT_CLIENT_VERSION;
			ai32ContextAttribs[i++] = 2;
#endif

#if defined(BUILD_OGLES2) || defined(BUILD_OGLES) || defined(BUILD_OGLES3)
			if(PVRShellIsExtensionSupported(m_EGLDisplay,"EGL_IMG_context_priority"))
			{
				ai32ContextAttribs[i++] = EGL_CONTEXT_PRIORITY_LEVEL_IMG;
				switch(m_pShell->PVRShellGet(prefPriority))
				{
					case 0: ai32ContextAttribs[i++] = EGL_CONTEXT_PRIORITY_LOW_IMG; break;
					case 1: ai32ContextAttribs[i++] = EGL_CONTEXT_PRIORITY_MEDIUM_IMG; break;
					default:ai32ContextAttribs[i++] = EGL_CONTEXT_PRIORITY_HIGH_IMG;
				}
			}
#endif
			ai32ContextAttribs[i] = EGL_NONE;

			m_EGLContext = eglCreateContext(m_EGLDisplay, m_EGLConfig, NULL, ai32ContextAttribs);

			if(m_EGLContext == EGL_NO_CONTEXT)
			{
				if(m_iRequestedConfig > 0)
				{
					// We failed to create a context
					m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Unable to create a context\n");
					return false;
				}
				else if(m_pShell->m_pShellData->bNeedPbuffer)
				{
					// Disable P-buffer and try again
					m_pShell->m_pShellData->bNeedPbuffer = false;
				}
				else if(m_pShell->m_pShellData->bNeedStencilBuffer)
				{
                    // Disable Stencil Buffer and try again
					m_pShell->m_pShellData->bNeedStencilBuffer = false;
				}
				else if(m_pShell->m_pShellData->nFSAAMode > 0)
				{
					// Still failing, reduce the mode of AA and try again
					--m_pShell->m_pShellData->nFSAAMode;
				}
				else
				{
					m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Unable to create a context\n");
					return false;
				}
			}
		} while(m_EGLContext == EGL_NO_CONTEXT);

#if defined(__QNXNTO__)
		int format = SCREEN_FORMAT_RGBX8888;
	    if(screen_set_window_property_iv((_screen_window*) m_NWT, SCREEN_PROPERTY_FORMAT, &format))
	    {
	    	m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Failed to set window property SCREEN_PROPERTY_FORMAT\n");
	    	return false;
	    }

#if defined(BUILD_OGLES2)
	    int usage = SCREEN_USAGE_OPENGL_ES2;
#else
#if defined(BUILD_OGLES)
	    int usage = SCREEN_USAGE_OPENGL_ES1;
#else
#if defined(BUILD_OVG)
	    int usage = SCREEN_USAGE_OPENVG;
#endif
#endif
#endif
	    if(screen_set_window_property_iv((_screen_window*) m_NWT, SCREEN_PROPERTY_USAGE, &usage))
	    {
	    	m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Failed to set window property SCREEN_PROPERTY_USAGE\n");
	    	return false;
	    }

	    if(screen_create_window_buffers((_screen_window*) m_NWT, 2))
	    {
	    	m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Failed to create window buffers\n");
	    	return false;
	    }
#endif
		EGLint		attrib_list[16];
		int	i = 0;
#if defined(EGL_VERSION_1_2)
		if(m_pShell->m_pShellData->bNeedAlphaFormatPre) // The default is EGL_ALPHA_FORMAT_NONPRE
		{
			attrib_list[i++] = EGL_ALPHA_FORMAT;
			attrib_list[i++] = EGL_ALPHA_FORMAT_PRE;
		}
#endif
		// Terminate the attribute list with EGL_NONE
		attrib_list[i] = EGL_NONE;

		if(m_pShell->m_pShellData->bNeedPixmap)
		{
			m_pShell->PVRShellOutputDebug("InitAPI() Using pixmaps, about to create egl surface\n");
			m_EGLWindow = eglCreatePixmapSurface(m_EGLDisplay, m_EGLConfig, m_NPT, attrib_list);
		}
		else
		{
#if defined(ANDROID)
			EGLint visualID;
		    eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_NATIVE_VISUAL_ID, &visualID);

		    // Change the format of our window to match our config
    		ANativeWindow_setBuffersGeometry(m_NWT, 0, 0, visualID);
#endif
			m_EGLWindow = eglCreateWindowSurface(m_EGLDisplay, m_EGLConfig, m_NWT, attrib_list);

            // If we have failed to create a surface then try using Null
			if(m_EGLWindow == EGL_NO_SURFACE)
			{
				m_EGLWindow = eglCreateWindowSurface(m_EGLDisplay, m_EGLConfig, NULL, attrib_list);
			}
		}

		if (m_EGLWindow == EGL_NO_SURFACE)
		{
			m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Unable to create surface\n");
			return false;
		}

		if (!eglMakeCurrent(m_EGLDisplay, m_EGLWindow, m_EGLWindow, m_EGLContext))
		{
#ifdef EGL_VERSION_1_3
			if((eglGetError() == EGL_CONTEXT_LOST))
#else
			if((eglGetError() == EGL_CONTEXT_LOST_IMG) && m_bPowerManagementSupported)
#endif
			{
				bDone = false;
			}
			else
			{
				m_pShell->PVRShellSet(prefExitMessage, "PVRShell: Unable to make context current\n");
				return false;
			}
		}
	} while(!bDone);

	/*
	 	Get correct screen width and height and
		save them into
		m_pShell->m_pShellData->nShellDimX and
		m_pShell->m_pShellData->nShellDimY
	*/
	eglQuerySurface(m_EGLDisplay, m_EGLWindow,
			EGL_WIDTH,  (EGLint*)&m_pShell->m_pShellData->nShellDimX
		);
	eglQuerySurface(m_EGLDisplay, m_EGLWindow,
			EGL_HEIGHT, (EGLint*)&m_pShell->m_pShellData->nShellDimY
		);

#if defined(ANDROID) && !defined(BUILD_OVG)
	glViewport(0,0,m_pShell->m_pShellData->nShellDimX, m_pShell->m_pShellData->nShellDimY);
#endif
	/*
		Done - activate requested features
	*/
	ApiActivatePreferences();
	return true;
}
Esempio n. 17
0
static struct window *window_create(struct display *display, const char *name,
				    unsigned int x, unsigned int y,
				    unsigned int width, unsigned int height)
{
	static const EGLint attribs[] = {
		EGL_RED_SIZE, 1,
		EGL_GREEN_SIZE, 1,
		EGL_BLUE_SIZE, 1,
		EGL_DEPTH_SIZE, 1,
		EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
		EGL_NONE
	};
	static const EGLint attrs[] = {
		EGL_CONTEXT_CLIENT_VERSION, 2,
		EGL_NONE
	};
	XSetWindowAttributes attr;
	struct window *window;
	unsigned long mask;
	XVisualInfo visual;
	EGLint num_configs;
	XVisualInfo *info;
	XSizeHints hints;
	EGLConfig config;
	int num_visuals;
	EGLint version;
	Window root;
	int screen;
	EGLint vid;

	window = calloc(1, sizeof(*window));
	if (!window)
		return NULL;

	window->display = display;

	screen = DefaultScreen(display->x11);
	root = RootWindow(display->x11, screen);

	if (!eglChooseConfig(display->egl, attribs, &config, 1, &num_configs)) {
		free(window);
		return NULL;
	}

	if (!eglGetConfigAttrib(display->egl, config, EGL_NATIVE_VISUAL_ID, &vid)) {
		free(window);
		return NULL;
	}

	visual.visualid = vid;

	info = XGetVisualInfo(display->x11, VisualIDMask, &visual, &num_visuals);
	if (!info) {
		free(window);
		return NULL;
	}

	memset(&attr, 0, sizeof(attr));
	attr.background_pixel = 0;
	attr.border_pixel = 0;
	attr.colormap = XCreateColormap(display->x11, root, info->visual, AllocNone);
	attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
	mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;

	window->x11 = XCreateWindow(display->x11, root, 0, 0, width, height,
				    0, info->depth, InputOutput, info->visual,
				    mask, &attr);
	if (!window->x11) {
		free(window);
		return NULL;
	}

	memset(&hints, 0, sizeof(hints));
	hints.x = x;
	hints.y = y;
	hints.width = width;
	hints.height = height;
	hints.flags = USSize | USPosition;

	XSetNormalHints(display->x11, window->x11, &hints);
	XSetStandardProperties(display->x11, window->x11, name, name, None,
			       NULL, 0, &hints);

	eglBindAPI(EGL_OPENGL_ES_API);

	window->context = eglCreateContext(display->egl, config,
					   EGL_NO_CONTEXT, attrs);
	if (window->context == EGL_NO_CONTEXT) {
		free(window);
		return NULL;
	}

	eglQueryContext(display->egl, window->context, EGL_CONTEXT_CLIENT_VERSION, &version);
	printf("OpenGL ES: %d\n", version);

	window->surface = eglCreateWindowSurface(display->egl, config,
						 window->x11, NULL);
	if (window->surface == EGL_NO_SURFACE) {
		free(window);
		return NULL;
	}

	XFree(info);

	window->width = width;
	window->height = height;

	return window;
}