示例#1
0
/* Sets up an OpenGL ES 2 context. Returnes NULL if it succeeds, or
 * an error message on failure.
 */
char *egl_init(int interval) {
    SDL_SysWMinfo wminfo;
    EGLint major, minor;
    EGLint num_config;
    
    const EGLint attrs[] = {
         EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
         EGL_ALPHA_SIZE, 8,
         EGL_NONE
     };

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

    SDL_VERSION(&wminfo.version);
    SDL_GetWMInfo(&wminfo);

    if (! initialized) {

    	display = eglGetDisplay(GetDC(wminfo.window));
		egl_check("getting display");

		eglInitialize(display, &major, &minor);
		egl_check("initializing EGL");

		eglBindAPI(EGL_OPENGL_ES_API);
		egl_check("binding OpenGL ES");

		eglChooseConfig(display, attrs, &config, 1, &num_config);
		egl_check("choosing EGL config");

		context = eglCreateContext(display, config, EGL_NO_CONTEXT, context_attrs);
		egl_check("creating EGL context");

    	surface = eglCreateWindowSurface(display, config, wminfo.window, NULL);
    	egl_check("creating EGL surface");


    } else if (window != wminfo.window) {

    	eglDestroySurface(display, surface);
    	egl_check("destroying existing EGL surface")

    	surface = eglCreateWindowSurface(display, config, wminfo.window, NULL);
    	egl_check("creating EGL surface");

    }

	eglMakeCurrent(display, surface, surface, context);
	egl_check("making EGL context current");

    eglSwapInterval(display, interval);
    egl_check("setting swap interval")

	initialized = 1;
	window = wminfo.window;

    return NULL;
}
示例#2
0
static int atomic_run(const struct gbm *gbm, const struct egl *egl)
{
	struct gbm_bo *bo = NULL;
	struct drm_fb *fb;
	uint32_t i = 0;
	uint32_t flags = DRM_MODE_ATOMIC_NONBLOCK;
	struct timeval timeout;
	fd_set fds;
	int ret;

	if (egl_check(egl, eglDupNativeFenceFDANDROID) ||
	    egl_check(egl, eglCreateSyncKHR) ||
	    egl_check(egl, eglDestroySyncKHR) ||
	    egl_check(egl, eglWaitSyncKHR) ||
	    egl_check(egl, eglClientWaitSyncKHR))
		return -1;

	/* Allow a modeset change for the first commit only. */
	flags |= DRM_MODE_ATOMIC_ALLOW_MODESET;

	while (1) {
		struct gbm_bo *next_bo;
		EGLSyncKHR gpu_fence = NULL;   /* out-fence from gpu, in-fence to kms */
		EGLSyncKHR kms_fence = NULL;   /* in-fence to gpu, out-fence from kms */

		if (drm.kms_out_fence_fd != -1) {
			kms_fence = create_fence(egl, drm.kms_out_fence_fd);
			assert(kms_fence);

			/* driver now has ownership of the fence fd: */
			drm.kms_out_fence_fd = -1;

			/* wait "on the gpu" (ie. this won't necessarily block, but
			 * will block the rendering until fence is signaled), until
			 * the previous pageflip completes so we don't render into
			 * the buffer that is still on screen.
			 */
			egl->eglWaitSyncKHR(egl->display, kms_fence, 0);
		}

		egl->draw(i++);

		/* insert fence to be singled in cmdstream.. this fence will be
		 * signaled when gpu rendering done
		 */
		gpu_fence = create_fence(egl, EGL_NO_NATIVE_FENCE_FD_ANDROID);
		assert(gpu_fence);

		eglSwapBuffers(egl->display, egl->surface);

		/* after swapbuffers, gpu_fence should be flushed, so safe
		 * to get fd:
		 */
		drm.kms_in_fence_fd = egl->eglDupNativeFenceFDANDROID(egl->display, gpu_fence);
		egl->eglDestroySyncKHR(egl->display, gpu_fence);
		assert(drm.kms_in_fence_fd != -1);

		next_bo = gbm_surface_lock_front_buffer(gbm->surface);
		if (!next_bo) {
			printf("Failed to lock frontbuffer\n");
			return -1;
		}
		fb = drm_fb_get_from_bo(next_bo);
		if (!fb) {
			printf("Failed to get a new framebuffer BO\n");
			return -1;
		}

		if (kms_fence) {
			EGLint status;

			/* Wait on the CPU side for the _previous_ commit to
			 * complete before we post the flip through KMS, as
			 * atomic will reject the commit if we post a new one
			 * whilst the previous one is still pending.
			 */
			do {
				status = egl->eglClientWaitSyncKHR(egl->display,
								   kms_fence,
								   0,
								   EGL_FOREVER_KHR);
			} while (status != EGL_CONDITION_SATISFIED_KHR);

			egl->eglDestroySyncKHR(egl->display, kms_fence);
		}

		/*
		 * Here you could also update drm plane layers if you want
		 * hw composition
		 */
		ret = drm_atomic_commit(fb->fb_id, flags);
		if (ret) {
			printf("failed to commit: %s\n", strerror(errno));
			return -1;
		}

		/* release last buffer to render on again: */
		if (bo)
			gbm_surface_release_buffer(gbm->surface, bo);
		bo = next_bo;

		/* Allow a modeset change for the first commit only. */
		flags &= ~(DRM_MODE_ATOMIC_ALLOW_MODESET);

		/* watch for user interruption */
		FD_ZERO(&fds);
		FD_SET(0, &fds);
		memset(&timeout, 0, sizeof(timeout));

		ret = select(1, &fds, NULL, NULL, &timeout);
		if (ret < 0) {
			printf("select() failed: %s\n", strerror(errno));
			break;
		}

		/*
		 * select() will immediately timeout if there was no user
		 * interrupt because of the 0 timeout. However, that's an
		 * expected situation, not an error, so we just ignore it
		 * here.
		 */
		if (FD_ISSET(0, &fds)) {
			printf("user interrupted!\n");
			break;
		}
	}

	return ret;
}