Пример #1
0
void
NativeStateDRM::flip()
{
    gbm_bo* next = gbm_surface_lock_front_buffer(surface_);
    fb_ = fb_get_from_bo(next);
    unsigned int waiting(1);

    if (!crtc_set_) {
        int status = drmModeSetCrtc(fd_, encoder_->crtc_id, fb_->fb_id, 0, 0,
                                    &connector_->connector_id, 1, mode_);
        if (status >= 0) {
            crtc_set_ = true;
            bo_ = next;
        }
        else {
            Log::error("Failed to set crtc: %d\n", status);
        }
        return;
    }

    int status = drmModePageFlip(fd_, encoder_->crtc_id, fb_->fb_id,
                                 DRM_MODE_PAGE_FLIP_EVENT, &waiting);
    if (status < 0) {
        Log::error("Failed to enqueue page flip: %d\n", status);
        return;
    }

    fd_set fds;
    FD_ZERO(&fds);
    FD_SET(fd_, &fds);
    drmEventContext evCtx;
    evCtx.version = DRM_EVENT_CONTEXT_VERSION;
    evCtx.page_flip_handler = page_flip_handler;

    while (waiting) {
        status = select(fd_ + 1, &fds, 0, 0, 0);
        if (status < 0) {
            // Most of the time, select() will return an error because the
            // user pressed Ctrl-C.  So, only print out a message in debug
            // mode, and just check for the likely condition and release
            // the current buffer object before getting out.
            Log::debug("Error in select\n");
            if (should_quit()) {
                gbm_surface_release_buffer(surface_, bo_);
                bo_ = next;
            }
            return;
        }
        drmHandleEvent(fd_, &evCtx);
    }

    gbm_surface_release_buffer(surface_, bo_);
    bo_ = next;
}
Пример #2
0
static bool gfx_ctx_drm_wait_flip(bool block)
{
   int timeout = 0;

   if (!waiting_for_flip)
      return false;
   
   if (block)
      timeout = -1;

   while (waiting_for_flip)
   {
      if (!drm_wait_flip(timeout))
         break;
   }

   if (waiting_for_flip)
      return true;

   /* Page flip has taken place. */

   /* This buffer is not on-screen anymore. Release it to GBM. */
   gbm_surface_release_buffer(g_gbm_surface, g_bo);
   /* This buffer is being shown now. */
   g_bo = g_next_bo; 

   return false;
}
Пример #3
0
static void wait_flip(bool block)
{
   struct pollfd fds = {0};
   fds.fd     = g_drm_fd;
   fds.events = POLLIN;

   drmEventContext evctx   = {0};
   evctx.version           = DRM_EVENT_CONTEXT_VERSION;
   evctx.page_flip_handler = page_flip_handler;
   
   int timeout = block ? -1 : 0;

   while (waiting_for_flip)
   {
      fds.revents = 0;
      if (poll(&fds, 1, timeout) < 0)
         break;

      if (fds.revents & (POLLHUP | POLLERR))
         break;

      if (fds.revents & POLLIN)
         drmHandleEvent(g_drm_fd, &evctx);
      else
         break;
   }

   if (!waiting_for_flip) // Page flip has taken place.
   {
      gbm_surface_release_buffer(g_gbm_surface, g_bo); // This buffer is not on-screen anymore. Release it to GBM.
      g_bo = g_next_bo; // This buffer is being shown now.
   }
}
Пример #4
0
void QEglFSKmsGbmScreen::flip()
{
    if (!m_gbm_surface) {
        qWarning("Cannot sync before platform init!");
        return;
    }

    m_gbm_bo_next = gbm_surface_lock_front_buffer(m_gbm_surface);
    if (!m_gbm_bo_next) {
        qWarning("Could not lock GBM surface front buffer!");
        return;
    }

    FrameBuffer *fb = framebufferForBufferObject(m_gbm_bo_next);

    QKmsOutput &op(output());
    const int fd = device()->fd();
    const uint32_t w = op.modes[op.mode].hdisplay;
    const uint32_t h = op.modes[op.mode].vdisplay;

    if (!op.mode_set) {
        int ret = drmModeSetCrtc(fd,
                                 op.crtc_id,
                                 fb->fb,
                                 0, 0,
                                 &op.connector_id, 1,
                                 &op.modes[op.mode]);

        if (ret == -1) {
            qErrnoWarning(errno, "Could not set DRM mode!");
        } else {
            op.mode_set = true;
            setPowerState(PowerStateOn);

            if (!op.plane_set) {
                op.plane_set = true;
                if (op.wants_plane) {
                    int ret = drmModeSetPlane(fd, op.plane_id, op.crtc_id,
                                              uint32_t(-1), 0,
                                              0, 0, w, h,
                                              0 << 16, 0 << 16, w << 16, h << 16);
                    if (ret == -1)
                        qErrnoWarning(errno, "drmModeSetPlane failed");
                }
            }
        }
    }

    int ret = drmModePageFlip(fd,
                              op.crtc_id,
                              fb->fb,
                              DRM_MODE_PAGE_FLIP_EVENT,
                              this);
    if (ret) {
        qErrnoWarning("Could not queue DRM page flip!");
        gbm_surface_release_buffer(m_gbm_surface, m_gbm_bo_next);
        m_gbm_bo_next = Q_NULLPTR;
    }
}
Пример #5
0
void QKmsScreen::handlePageFlipped()
{
    if (m_current_bo)
        gbm_surface_release_buffer(m_gbmSurface, m_current_bo);

    m_current_bo = m_next_bo;
    m_next_bo = 0;
}
Пример #6
0
void QEglFSKmsGbmScreen::flipFinished()
{
    if (m_gbm_bo_current)
        gbm_surface_release_buffer(m_gbm_surface,
                                   m_gbm_bo_current);

    m_gbm_bo_current = m_gbm_bo_next;
    m_gbm_bo_next = Q_NULLPTR;
}
Пример #7
0
void RenderingBackendGBM::Surface::releaseBuffer(uint32_t handle)
{
    auto it = m_lockedBuffers.find(handle);
    assert(it != m_lockedBuffers.end());

    struct gbm_bo* bo = it->second;
    if (bo)
        gbm_surface_release_buffer(m_surface, bo);
}
Пример #8
0
static void
free_current_bo(struct gbm_context *context)
{
        if (context->current_fb_id) {
                drmModeRmFB(context->dev->fd, context->current_fb_id);
                context->current_fb_id = 0;
        }
        if (context->current_bo) {
                gbm_surface_release_buffer(context->gbm_surface,
                                           context->current_bo);
                context->current_bo = NULL;
        }
}
Пример #9
0
static void
page_flip_handler(int fd, unsigned int frame,
		  unsigned int sec, unsigned int usec, void *data)
{
	if (current_fb_id)
		drmModeRmFB(fd, current_fb_id);
	current_fb_id = next_fb_id;
	next_fb_id = 0;

	if (current_bo)
		gbm_surface_release_buffer(gs, current_bo);
	current_bo = next_bo;
	next_bo = NULL;
}
Пример #10
0
void QKmsScreen::performPageFlip()
{
    if (!m_next_bo)
        return;

    uint32_t width = gbm_bo_get_width(m_next_bo);
    uint32_t height = gbm_bo_get_height(m_next_bo);
    uint32_t stride = gbm_bo_get_stride(m_next_bo);
    uint32_t handle = gbm_bo_get_handle(m_next_bo).u32;

    uint32_t fb_id;
    int ret = drmModeAddFB(m_device->fd(), width, height, 24, 32,
                           stride, handle, &fb_id);
    if (ret) {
        qFatal("kms: Failed to create fb: fd %d, w %d, h %d, stride %d, handle %d, ret %d",
               m_device->fd(), width, height, stride, handle, ret);
    }

    if (!m_modeSet) {
        //Set the Mode of the screen.
        int ret = drmModeSetCrtc(m_device->fd(), m_crtcId, fb_id,
                0, 0, &m_connectorId, 1, &m_mode);
        if (ret)
            qFatal("failed to set mode");
        m_modeSet = true;

        // Initialize cursor

        static int hideCursor = qgetenv("QT_QPA_KMS_HIDECURSOR").toInt();
        if (!hideCursor) {
            QCursor cursor(Qt::ArrowCursor);
            m_cursor->changeCursor(&cursor, 0);
        }
    }

    int pageFlipStatus = drmModePageFlip(m_device->fd(), m_crtcId,
                                         fb_id,
                                         DRM_MODE_PAGE_FLIP_EVENT, this);
    if (pageFlipStatus)
    {
        qWarning("Pageflip status: %d", pageFlipStatus);
        gbm_surface_release_buffer(m_gbmSurface, m_next_bo);
        m_next_bo = 0;
    }
}
Пример #11
0
static void wait_flip(bool block)
{
   int timeout = 0;
   struct pollfd fds = {0};
   drmEventContext evctx   = {0};
   driver_t *driver = driver_get_ptr();
   gfx_ctx_drm_egl_data_t *drm = (gfx_ctx_drm_egl_data_t*)
      driver->video_context_data;

   fds.fd     = drm->g_drm_fd;
   fds.events = POLLIN;

   evctx.version           = DRM_EVENT_CONTEXT_VERSION;
   evctx.page_flip_handler = page_flip_handler;
   
   if (block)
      timeout = -1;

   while (waiting_for_flip)
   {
      fds.revents = 0;

      if (poll(&fds, 1, timeout) < 0)
         break;

      if (fds.revents & (POLLHUP | POLLERR))
         break;

      if (fds.revents & POLLIN)
         drmHandleEvent(drm->g_drm_fd, &evctx);
      else
         break;
   }

   if (waiting_for_flip)
      return;

   /* Page flip has taken place. */

   /* This buffer is not on-screen anymore. Release it to GBM. */
   gbm_surface_release_buffer(drm->g_gbm_surface, drm->g_bo);
   /* This buffer is being shown now. */
   drm->g_bo = drm->g_next_bo; 
}
Пример #12
0
bool CDRMLegacy::WaitingForFlip()
{
  if(!flip_happening)
  {
    return false;
  }

  m_drm_fds.fd = m_drm->fd;
  m_drm_fds.events = POLLIN;

  m_drm_evctx.version = DRM_EVENT_CONTEXT_VERSION;
  m_drm_evctx.page_flip_handler = PageFlipHandler;

  m_drm_fds.revents = 0;

  while(flip_happening)
  {
    auto ret = poll(&m_drm_fds, 1, -1);

    if(ret < 0)
    {
      return true;
    }

    if(m_drm_fds.revents & (POLLHUP | POLLERR))
    {
      return true;
    }

    if(m_drm_fds.revents & POLLIN)
    {
      drmHandleEvent(m_drm->fd, &m_drm_evctx);
    }
  }

  gbm_surface_release_buffer(m_gbm->surface, m_bo);
  m_bo = m_next_bo;

  return false;
}
Пример #13
0
int DRM_PageFlip(void){
	int ret;		
	struct gbm_bo *next_bo;
	int waiting_for_flip = 1;

	next_bo = gbm_surface_lock_front_buffer(gbm.surface);
	fb = drm_fb_get_from_bo(next_bo);

	/*
	 * Here you could also update drm plane layers if you want
	 * hw composition
	 */

	ret = drmModePageFlip(drm.fd, drm.crtc_id, fb->fb_id,
			DRM_MODE_PAGE_FLIP_EVENT, &waiting_for_flip);
	if (ret) {
		printf("failed to queue page flip: %s\n", strerror(errno));
		return -1;
	}

	while (waiting_for_flip) {
		//Aquí realmente no nos interesa leer el teclado. Sólo
		//hacemos el select para esperar por drm.fd
		FD_ZERO (&fds);
		
		FD_SET (0, &fds);
		FD_SET (drm.fd, &fds);

		ret = select(drm.fd+1, &fds, NULL, NULL, NULL);
		
		drmHandleEvent(drm.fd, &evctx);
	}

	/* release last buffer to render on again: */
	gbm_surface_release_buffer(gbm.surface, bo);
	bo = next_bo;
	
	return 0;
}
Пример #14
0
bool CDRMLegacy::SetVideoMode(RESOLUTION_INFO res)
{
  gbm_surface_release_buffer(m_gbm->surface, m_bo);

  m_bo = gbm_surface_lock_front_buffer(m_gbm->surface);
  m_drm_fb = CDRMUtils::DrmFbGetFromBo(m_bo);

  auto ret = drmModeSetCrtc(m_drm->fd,
                            m_drm->crtc_id,
                            m_drm_fb->fb_id,
                            0,
                            0,
                            &m_drm->connector_id,
                            1,
                            m_drm->mode);

  if(ret < 0)
  {
    CLog::Log(LOGERROR,
              "CDRMUtils::%s - failed to set crtc mode: %dx%d%s @ %d Hz",
              __FUNCTION__,
              m_drm->mode->hdisplay,
              m_drm->mode->vdisplay,
              m_drm->mode->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "",
              m_drm->mode->vrefresh);

    return false;
  }

  CLog::Log(LOGDEBUG, "CDRMUtils::%s - set crtc mode: %dx%d%s @ %d Hz",
            __FUNCTION__,
            m_drm->mode->hdisplay,
            m_drm->mode->vdisplay,
            m_drm->mode->flags & DRM_MODE_FLAG_INTERLACE ? "i" : "",
            m_drm->mode->vrefresh);

  return true;
}
Пример #15
0
static void
free_current_bo (CoglOnscreen *onscreen)
{
  CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
  CoglOnscreenKMS *kms_onscreen = egl_onscreen->platform;
  CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
  CoglRenderer *renderer = context->display->renderer;
  CoglRendererEGL *egl_renderer = renderer->winsys;
  CoglRendererKMS *kms_renderer = egl_renderer->platform;

  if (kms_onscreen->current_fb_id)
    {
      drmModeRmFB (kms_renderer->fd,
                   kms_onscreen->current_fb_id);
      kms_onscreen->current_fb_id = 0;
    }
  if (kms_onscreen->current_bo)
    {
      gbm_surface_release_buffer (kms_onscreen->surface,
                                  kms_onscreen->current_bo);
      kms_onscreen->current_bo = NULL;
    }
}
Пример #16
0
static void
_cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
{
  CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
  CoglDisplayEGL *egl_display = context->display->winsys;
  CoglDisplayKMS *kms_display = egl_display->platform;
  CoglRenderer *renderer = context->display->renderer;
  CoglRendererEGL *egl_renderer = renderer->winsys;
  CoglRendererKMS *kms_renderer = egl_renderer->platform;
  CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
  CoglOnscreenKMS *kms_onscreen = egl_onscreen->platform;
  uint32_t handle, stride;
  CoglFlipKMS *flip;
  GList *l;

  /* If we already have a pending swap then block until it completes */
  while (kms_onscreen->next_fb_id != 0)
    handle_drm_event (kms_renderer);

  /* First chain-up. This will call eglSwapBuffers */
  parent_vtable->onscreen_swap_buffers (onscreen);

  /* Now we need to set the CRTC to whatever is the front buffer */
  kms_onscreen->next_bo = gbm_surface_lock_front_buffer (kms_onscreen->surface);

#if (COGL_VERSION_ENCODE (COGL_GBM_MAJOR, COGL_GBM_MINOR, COGL_GBM_MICRO) >= \
     COGL_VERSION_ENCODE (8, 1, 0))
  stride = gbm_bo_get_stride (kms_onscreen->next_bo);
#else
  stride = gbm_bo_get_pitch (kms_onscreen->next_bo);
#endif
  handle = gbm_bo_get_handle (kms_onscreen->next_bo).u32;

  if (drmModeAddFB (kms_renderer->fd,
                    kms_display->width,
                    kms_display->height,
                    24, /* depth */
                    32, /* bpp */
                    stride,
                    handle,
                    &kms_onscreen->next_fb_id))
    {
      g_warning ("Failed to create new back buffer handle: %m");
      gbm_surface_release_buffer (kms_onscreen->surface,
                                  kms_onscreen->next_bo);
      kms_onscreen->next_bo = NULL;
      kms_onscreen->next_fb_id = 0;
      return;
    }

  /* If this is the first framebuffer to be presented then we now setup the
   * crtc modes... */
  if (kms_display->pending_set_crtc)
    {
      setup_crtc_modes (context->display, kms_onscreen->next_fb_id);
      kms_display->pending_set_crtc = FALSE;
    }

  flip = g_slice_new0 (CoglFlipKMS);
  flip->onscreen = onscreen;

  for (l = kms_display->outputs; l; l = l->next)
    {
      CoglOutputKMS *output = l->data;

      if (drmModePageFlip (kms_renderer->fd,
                           output->encoder->crtc_id,
                           kms_onscreen->next_fb_id,
                           DRM_MODE_PAGE_FLIP_EVENT,
                           flip))
        {
          g_warning ("Failed to flip: %m");
          continue;
        }

      flip->pending++;
    }

  if (flip->pending == 0)
    {
      drmModeRmFB (kms_renderer->fd, kms_onscreen->next_fb_id);
      gbm_surface_release_buffer (kms_onscreen->surface,
                                  kms_onscreen->next_bo);
      kms_onscreen->next_bo = NULL;
      kms_onscreen->next_fb_id = 0;
      g_slice_free (CoglFlipKMS, flip);
      flip = NULL;
    }
  else
    {
      /* Ensure the onscreen remains valid while it has any pending flips... */
      cogl_object_ref (flip->onscreen);
    }
}
Пример #17
0
int main(int argc, char *argv[])
{
	struct opt_data opts; optproc(argc, argv, &opts);
	if(audio_init(&opts) < 0) exit(1);
	if(opts.w < 0 && opts.h < 0) opts.w = opts.h = 512;
	else if(opts.w < 0) opts.w = opts.h;
	else if(opts.h < 0) opts.h = opts.w;
	
	int ret;

	ret = init_drm(&opts, 512);
	if (ret) {
		printf("failed to initialize DRM\n");
		return ret;
	}

	ret = init_gbm();
	if (ret) {
		printf("failed to initialize GBM\n");
		return ret;
	}

	ret = init_egl();
	if (ret) {
		printf("failed to initialize EGL\n");
		return ret;
	}
	
	// call init_gl
	//init_gl(&opts, drm.mode->hdisplay, drm.mode->vdisplay);
	init_gl(&opts, opts.w, opts.h); //TODO: better dealing with our great big screen
	
	eglSwapBuffers(gl.display, gl.surface);
	struct gbm_bo *bo = gbm_surface_lock_front_buffer(gbm.surface);
	fb = drm_fb_get_from_bo(bo);

	/* set mode: */
	ret = drmModeSetCrtc(drm.fd, drm.crtc_id, fb->fb_id, 0, 0,
			&drm.connector_id, 1, drm.mode);
	if (ret) {
		printf("failed to set mode: %s\n", strerror(errno));
		return ret;
	}
	
	// turn off line buffering on input and echoing of characters
	struct termios term;
	tcgetattr(STDIN_FILENO, &save_term);
    tcgetattr(STDIN_FILENO, &term);
    term.c_lflag &= ~(ICANON|ECHO);
    tcsetattr(STDIN_FILENO, TCSANOW, &term);
    
    atexit(shutdown_cleanup);
	
	drmVBlank vbl;
	/* Get current count first hopefully also sync up with blank too*/
	vbl.request.type = DRM_VBLANK_RELATIVE;
	vbl.request.sequence = 1;
	ret = drmWaitVBlank(drm.fd, &vbl);
	if (ret != 0) {
		printf("drmWaitVBlank (relative, event) failed ret: %i\n", ret);
		return -1;
	}
	printf("starting msc: %d\n", vbl.request.sequence);
	
	/* Queue an event for frame + 1 */
	vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT;
	vbl.request.sequence = 1;
	vbl.request.signal = NULL;
	ret = drmWaitVBlank(drm.fd, &vbl);
	if (ret != 0) {
		printf("drmWaitVBlank (relative, event) failed ret: %i\n", ret);
		return -1;
	}
	
	struct pollfd pfds[] = {
		{drm.fd, POLLIN | POLLPRI, 0 },
		{STDIN_FILENO, POLLIN, 0 },
	};

	int debug_maxsrc = 0, debug_pal = 0, show_mandel = 0, show_fps_hist = 0;
	bool done = false;
	while (!done) {

		render_frame(debug_maxsrc, debug_pal, show_mandel, show_fps_hist);

		while (waiting_for_flip) { // TODO: input handling			
			ret = poll(pfds, 2, -1);
			if (ret < 0) {
				printf("poll err: %s\n", strerror(errno));
				return ret;
			} else if (ret == 0) {
				printf("poll timeout!\n");
				done = true;
				break;
			} 
			
			if (pfds[1].revents) {
				char buf[128];
				int cnt = read(STDIN_FILENO, buf, sizeof(buf));
				if(buf[0] == 27) done = true;
				else if(buf[0] == '1') debug_maxsrc = !debug_maxsrc;
				else if(buf[0] == '2') debug_pal = !debug_pal;
				else if(buf[0] == '3') show_mandel = !show_mandel;
				else if(buf[0] == '4') show_fps_hist = !show_fps_hist;
				//continue;
			}
			
			if(pfds[0].revents)
				drmHandleEvent(drm.fd, &evctx);
		}

		/* release last buffer to render on again: */
		gbm_surface_release_buffer(gbm.surface, bo);
		bo = next_bo;
	}
	
	audio_shutdown();

	return ret;
}
Пример #18
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;
}
Пример #19
0
int init_egl_drm()
{
        fd_set fds;
        drmEventContext evctx = {
                        .version = DRM_EVENT_CONTEXT_VERSION,
                        .vblank_handler = 0,
                        .page_flip_handler = page_flip_handler,
        };
        struct gbm_bo *bo;
        struct drm_fb *fb;
        ret = init_drm();
        if (ret) {
                printf("failed to initialize DRM\n");
                return ret;
        }
        printf("### Primary display => ConnectorId = %d, Resolution = %dx%d\n",
                        drm.connector_id[DISP_ID], drm.mode[DISP_ID]->hdisplay,
                        drm.mode[DISP_ID]->vdisplay);

        FD_ZERO(&fds);
        FD_SET(drm.fd, &fds);

        ret = init_gbm();
        if (ret) {
                printf("failed to initialize GBM\n");
                return ret;
        }

	//Initialise egl regularly here
}

void egl_drm_draw_flip()
{
        /* set mode: */
        if (all_display) {
                for (i=0; i<drm.ndisp; i++) {
                        ret = drmModeSetCrtc(drm.fd, drm.crtc_id[i], fb->fb_id, 0, 0,
                                        &drm.connector_id[i], 1, drm.mode[i]);
                        if (ret) {
                                printf("display %d failed to set mode: %s\n", i, strerror(errno));
                                return ret;
                        }
                }
        } else {
                ret = drmModeSetCrtc(drm.fd, drm.crtc_id[DISP_ID], fb->fb_id,
                                0, 0, &drm.connector_id[DISP_ID], 1, drm.mode[DISP_ID]);
                if (ret) {
                        printf("display %d failed to set mode: %s\n", DISP_ID, strerror(errno));
                        return ret;
                }
        }
	//Draw call here
	//Swapping is involved
                next_bo = gbm_surface_lock_front_buffer(gbm.surface);
                fb = drm_fb_get_from_bo(next_bo);

                /*
                 * Here you could also update drm plane layers if you want
                 * hw composition
                 */

                ret = drmModePageFlip(drm.fd, drm.crtc_id[DISP_ID], fb->fb_id,
                                DRM_MODE_PAGE_FLIP_EVENT, &waiting_for_flip);
                if (ret) {
                        printf("failed to queue page flip: %s\n", strerror(errno));
                        return -1;
                }

                while (waiting_for_flip) {
                        ret = select(drm.fd + 1, &fds, NULL, NULL, NULL);
                        if (ret < 0) {
                                printf("select err: %s\n", strerror(errno));
                                return ret;
                        } else if (ret == 0) {
                                printf("select timeout!\n");
                                return -1;
                        } else if (FD_ISSET(0, &fds)) {
                                continue;
                        }
                        drmHandleEvent(drm.fd, &evctx);
                }
                /* release last buffer to render on again: */
                gbm_surface_release_buffer(gbm.surface, bo);
                bo = next_bo;
}