예제 #1
0
static void
flip_all_crtcs (CoglDisplay *display, CoglFlipKMS *flip, int fb_id)
{
  CoglDisplayEGL *egl_display = display->winsys;
  CoglDisplayKMS *kms_display = egl_display->platform;
  CoglRendererEGL *egl_renderer = display->renderer->winsys;
  CoglRendererKMS *kms_renderer = egl_renderer->platform;
  GList *l;

  for (l = kms_display->crtcs; l; l = l->next)
    {
      CoglKmsCrtc *crtc = l->data;
      int ret = 0;

      if (crtc->count == 0 || crtc->ignore)
        continue;

      ret = drmModePageFlip (kms_renderer->fd,
                             crtc->id, fb_id,
                             DRM_MODE_PAGE_FLIP_EVENT, flip);

      if (ret)
        {
          g_warning ("Failed to flip: %m");
          continue;
        }

      if (ret == 0)
        flip->pending++;
    }
}
/*
 * Schedule a page flip.
 */
static int drm_kms_page_flip(struct gralloc_drm_t *drm,
		struct gralloc_drm_bo_t *bo)
{
	int ret;

	/* there is another flip pending */
	while (drm->next_front) {
		drm->waiting_flip = 1;
		drmHandleEvent(drm->fd, &drm->evctx);
		drm->waiting_flip = 0;
		if (drm->next_front) {
			/* record an error and break */
			LOGE("drmHandleEvent returned without flipping");
			drm->current_front = drm->next_front;
			drm->next_front = NULL;
		}
	}

	if (!bo)
		return 0;

	ret = drmModePageFlip(drm->fd, drm->crtc_id, bo->fb_id,
			DRM_MODE_PAGE_FLIP_EVENT, (void *) drm);
	if (ret)
		LOGE("failed to perform page flip");
	else
		drm->next_front = bo;

	return ret;
}
예제 #3
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;
    }
}
예제 #4
0
static bool test(data_t *data, enum pipe pipe, igt_output_t *output)
{
	igt_plane_t *primary;
	drmModeModeInfo *mode;
	struct igt_fb fb[2];
	int fd, ret;

	/* select the pipe we want to use */
	igt_output_set_pipe(output, pipe);
	igt_display_commit(&data->display);

	if (!output->valid) {
		igt_output_set_pipe(output, PIPE_ANY);
		igt_display_commit(&data->display);
		return false;
	}

	primary = igt_output_get_plane(output, IGT_PLANE_PRIMARY);
	mode = igt_output_get_mode(output);

	igt_create_color_fb(data->drm_fd, mode->hdisplay, mode->vdisplay,
			    DRM_FORMAT_XRGB8888,
			    LOCAL_I915_FORMAT_MOD_X_TILED,
			    0.0, 0.0, 0.0, &fb[0]);

	igt_plane_set_fb(primary, &fb[0]);
	igt_display_commit2(&data->display, COMMIT_LEGACY);

	fd = drm_open_driver(DRIVER_INTEL);

	ret = drmDropMaster(data->drm_fd);
	igt_assert_eq(ret, 0);

	ret = drmSetMaster(fd);
	igt_assert_eq(ret, 0);

	igt_create_color_fb(fd, mode->hdisplay, mode->vdisplay,
			    DRM_FORMAT_XRGB8888,
			    LOCAL_I915_FORMAT_MOD_X_TILED,
			    0.0, 0.0, 0.0, &fb[1]);
	ret = drmModePageFlip(fd, output->config.crtc->crtc_id,
			      fb[1].fb_id, DRM_MODE_PAGE_FLIP_EVENT,
			      data);
	igt_assert_eq(ret, 0);

	ret = close(fd);
	igt_assert_eq(ret, 0);

	ret = drmSetMaster(data->drm_fd);
	igt_assert_eq(ret, 0);

	igt_plane_set_fb(primary, NULL);
	igt_output_set_pipe(output, PIPE_ANY);
	igt_display_commit(&data->display);

	igt_remove_fb(data->drm_fd, &fb[0]);

	return true;
}
예제 #5
0
파일: device.c 프로젝트: magcius/drmdemo
static void
device_page_flip (Device *device,
                  int buffer_id,
                  void *data)
{
  drmModePageFlip (device->fd,
                   device->crtc->crtc_id,
                   buffer_id, DRM_MODE_PAGE_FLIP_EVENT, data);
}
예제 #6
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;
}
예제 #7
0
static void page_flip(void)
{
	struct igt_fb *tmp_fb;
	int rc;

	rc = drmModePageFlip(drm.fd, modeset.crtc_id, back_fb->fb_id, 0, NULL);
	igt_assert(rc == 0);

	tmp_fb = front_fb;
	front_fb = back_fb;
	back_fb = tmp_fb;
}
예제 #8
0
파일: drm_ctx.c 프로젝트: Ezio-PS/RetroArch
static bool gfx_ctx_drm_queue_flip(void)
{
   struct drm_fb *fb = NULL;
   g_next_bo         = gbm_surface_lock_front_buffer(g_gbm_surface);
   fb                = (struct drm_fb*)drm_fb_get_from_bo(g_next_bo);

   if (drmModePageFlip(g_drm_fd, g_crtc_id, fb->fb_id,
         DRM_MODE_PAGE_FLIP_EVENT, &waiting_for_flip) == 0)
      return true;
   
   /* Failed to queue page flip. */
   return false;
}
예제 #9
0
void QKmsScreen::performPageFlip()
{
    quint32 displayFramebufferId = m_bufferManager.displayFramebufferId();
    //qDebug() << "Flipping to framebuffer: " << displayFramebufferId;

    int pageFlipStatus = drmModePageFlip(m_device->fd(), m_crtcId,
                                         displayFramebufferId,
                                         DRM_MODE_PAGE_FLIP_EVENT, this);
    if (pageFlipStatus)
        qWarning("Pageflip status: %d", pageFlipStatus);

    m_flipReady = false;
}
예제 #10
0
void DisplayOzone::presentScreen()
{
    if (!mCRTC)
    {
        // no monitor
        return;
    }

    // see if pending flip has finished, without blocking
    int fd = gbm_device_get_fd(mGBM);
    if (mPending)
    {
        pollfd pfd;
        pfd.fd     = fd;
        pfd.events = POLLIN;
        if (poll(&pfd, 1, 0) < 0)
        {
            std::cerr << "poll failed: " << errno << " " << strerror(errno) << std::endl;
        }
        if (pfd.revents & POLLIN)
        {
            drmEventContext event;
            event.version           = DRM_EVENT_CONTEXT_VERSION;
            event.page_flip_handler = pageFlipHandler;
            drmHandleEvent(fd, &event);
        }
    }

    // if pending flip has finished, schedule next one
    if (!mPending && mDrawing)
    {
        flushGL();
        if (mSetCRTC)
        {
            if (drmModeSetCrtc(fd, mCRTC->crtc_id, mDrawing->getDRMFB(), 0, 0,
                               &mConnector->connector_id, 1, mMode))
            {
                std::cerr << "set crtc failed: " << errno << " " << strerror(errno) << std::endl;
            }
            mSetCRTC = false;
        }
        if (drmModePageFlip(fd, mCRTC->crtc_id, mDrawing->getDRMFB(), DRM_MODE_PAGE_FLIP_EVENT,
                            this))
        {
            std::cerr << "page flip failed: " << errno << " " << strerror(errno) << std::endl;
        }
        mPending = mDrawing;
        mDrawing = nullptr;
    }
}
예제 #11
0
static void
swap(struct gbm_winsys *winsys)
{
        struct gbm_dev *dev = winsys->dev;
        struct gbm_context *context = winsys->context;
        struct gbm_bo *bo;
        uint32_t handle, stride;
        uint32_t width, height;
        uint32_t fb_id;

        eglSwapBuffers(context->edpy, context->egl_surface);

        bo = gbm_surface_lock_front_buffer(context->gbm_surface);
        width = gbm_bo_get_width(bo);
        height = gbm_bo_get_height(bo);
        stride = gbm_bo_get_stride(bo);
        handle = gbm_bo_get_handle(bo).u32;

        if (drmModeAddFB(dev->fd,
                         width, height,
                         24, /* depth */
                         32, /* bpp */
                         stride,
                         handle,
                         &fb_id)) {
                fprintf(stderr,
                        "Failed to create new back buffer handle: %m\n");
        } else {
                if (dev->saved_crtc == NULL &&
                    set_initial_crtc(dev, fb_id))
                        return;

                if (drmModePageFlip(dev->fd,
                                    dev->crtc,
                                    fb_id,
                                    DRM_MODE_PAGE_FLIP_EVENT,
                                    dev)) {
                        fprintf(stderr, "Failed to page flip: %m\n");
                        return;
                }

                dev->pending_swap = 1;

                wait_swap(dev);

                free_current_bo(context);
                context->current_bo = bo;
                context->current_fb_id = fb_id;
        }
}
예제 #12
0
파일: kmsfps.c 프로젝트: Spudd86/julia-vis
void swap_buffers(void) 
{
	eglSwapBuffers(gl.display, gl.surface);
	next_bo = gbm_surface_lock_front_buffer(gbm.surface);
	fb = drm_fb_get_from_bo(next_bo);
	
	waiting_for_flip = 1;
	
	int 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));
		exit(-1);
	}
}
예제 #13
0
static void drm_egl_swap_buffers(MPGLContext *ctx)
{
    struct priv *p = ctx->priv;
    eglSwapBuffers(p->egl.display, p->egl.surface);
    p->gbm.next_bo = gbm_surface_lock_front_buffer(p->gbm.surface);
    p->waiting_for_flip = true;
    update_framebuffer_from_bo(ctx, p->gbm.next_bo);
    int ret = drmModePageFlip(p->kms->fd, p->kms->crtc_id, p->fb.id,
                              DRM_MODE_PAGE_FLIP_EVENT, p);
    if (ret) {
        MP_WARN(ctx->vo, "Failed to queue page flip: %s\n", mp_strerror(errno));
    }

    // poll page flip finish event
    const int timeout_ms = 3000;
    struct pollfd fds[1] = { { .events = POLLIN, .fd = p->kms->fd } };
예제 #14
0
static void queue_flip(void)
{
   g_next_bo = gbm_surface_lock_front_buffer(g_gbm_surface);
   struct drm_fb *fb = drm_fb_get_from_bo(g_next_bo);

   int ret = drmModePageFlip(g_drm_fd, g_crtc_id, fb->fb_id,
         DRM_MODE_PAGE_FLIP_EVENT, &waiting_for_flip);

   if (ret < 0)
   {
      RARCH_ERR("[KMS/EGL]: Failed to queue page flip.\n");
      return;
   }

   waiting_for_flip = true;
}
예제 #15
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;
    }
}
예제 #16
0
bool CDRMLegacy::QueueFlip()
{
  m_next_bo = gbm_surface_lock_front_buffer(m_gbm->surface);
  m_drm_fb = CDRMUtils::DrmFbGetFromBo(m_next_bo);

  auto ret = drmModePageFlip(m_drm->fd,
                             m_drm->crtc_id,
                             m_drm_fb->fb_id,
                             DRM_MODE_PAGE_FLIP_EVENT,
                             &flip_happening);

  if(ret)
  {
    CLog::Log(LOGDEBUG, "CDRMLegacy::%s - failed to queue DRM page flip", __FUNCTION__);
    return false;
  }

  return true;
}
예제 #17
0
static void queue_flip(void)
{
   g_next_bo = gbm_surface_lock_front_buffer(g_gbm_surface);
   struct drm_fb *fb = drm_fb_get_from_bo(g_next_bo);

   int ret = drmModePageFlip(g_drm_fd, g_crtc_id, fb->fb_id,
         DRM_MODE_PAGE_FLIP_EVENT, &waiting_for_flip);

   if (ret < 0)
   {
      RARCH_ERR("[KMS/EGL]: Failed to queue page flip.\n");
      return;
   }

   struct timeval tv;
   gettimeofday(&tv, NULL);
   flip_request_usec = (uint64_t)tv.tv_sec * 1000000 + tv.tv_usec;

   waiting_for_flip = true;
}
예제 #18
0
static int exynos_flip(struct hook_data *data, struct exynos_page *page) {
  /* We don't queue multiple page flips. */
  if (data->pageflip_pending > 0) {
    wait_flip(data->fliphandler);
  }

  /* Issue a page flip at the next vblank interval. */
  if (drmModePageFlip(data->drm_fd, data->drm->crtc_id, page->buf_id,
                      DRM_MODE_PAGE_FLIP_EVENT, page)) {
    fprintf(stderr, "[exynos_flip] error: failed to issue page flip\n");
    return -1;
  } else {
    data->pageflip_pending++;
  }

  /* On startup no frame is displayed. We therefore wait for the initial flip to finish. */
  if (data->cur_page == NULL) wait_flip(data->fliphandler);

  return 0;
}
static int fb_post(struct framebuffer_device_t *dev, buffer_handle_t buffer)
{
	if (private_handle_t::validate(buffer) < 0)
		return -EINVAL;

	fb_context_t *ctx = (fb_context_t *)dev;

	private_handle_t const *hnd =
		static_cast<private_handle_t const *>(buffer);
	private_module_t *m =
		reinterpret_cast<private_module_t *>(dev->common.module);

	if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
		int err = drmModePageFlip(m->fd, m->crtc,
					  m->buffers[hnd->index].fb,
					  0 /* DRM_MODE_PAGE_FLIP_EVENT */, 0);
		if (err < 0) {
			LOGE("drmModePageFlip failed (%d)", err);
			m->base.unlock(&m->base, buffer);
			return err;
		}
	} else {
		/* If we can't do the page_flip, just copy the buffer to the
		 * front.
		 * FIXME: use copybit HAL instead of memcpy
		 */
		void *buffer_vaddr;

		m->base.lock(&m->base, buffer,
			     GRALLOC_USAGE_SW_READ_RARELY, 0, 0,
			     m->mode->hdisplay, m->mode->vdisplay,
			     &buffer_vaddr);

		memcpy(m->buffers[0].vaddr, buffer_vaddr,
		       m->stride * m->mode->vdisplay);

		m->base.unlock(&m->base, buffer);
	}

	return 0;
}
예제 #20
0
파일: modeset.c 프로젝트: nikai3d/mesa
static boolean
drm_surface_swap_buffers(struct native_surface *nsurf)
{
   struct drm_surface *drmsurf = drm_surface(nsurf);
   struct drm_crtc *drmcrtc = &drmsurf->current_crtc;
   struct drm_display *drmdpy = drmsurf->drmdpy;
   struct drm_framebuffer tmp_fb;
   int err;

   if (!drmsurf->have_pageflip)
      return drm_surface_copy_swap(nsurf);

   if (!drmsurf->back_fb.buffer_id) {
      if (!drm_surface_init_framebuffers(&drmsurf->base, TRUE))
         return FALSE;
   }

   if (drmsurf->is_shown && drmcrtc->crtc) {
      err = drmModePageFlip(drmdpy->fd, drmcrtc->crtc->crtc_id,
			    drmsurf->back_fb.buffer_id, 0, NULL);
      if (err) {
	 drmsurf->have_pageflip = FALSE;
         return drm_surface_copy_swap(nsurf);
      }
   }

   /* swap the buffers */
   tmp_fb = drmsurf->front_fb;
   drmsurf->front_fb = drmsurf->back_fb;
   drmsurf->back_fb = tmp_fb;

   resource_surface_swap_buffers(drmsurf->rsurf,
         NATIVE_ATTACHMENT_FRONT_LEFT, NATIVE_ATTACHMENT_BACK_LEFT, FALSE);
   /* the front/back textures are swapped */
   drmsurf->sequence_number++;
   drmdpy->event_handler->invalid_surface(&drmdpy->base,
         &drmsurf->base, drmsurf->sequence_number);

   return TRUE;
}
예제 #21
0
static void queue_flip(void)
{
   int ret;
   struct drm_fb *fb = NULL;
   gfx_ctx_drm_egl_data_t *drm = (gfx_ctx_drm_egl_data_t*)
   driver.video_context_data;

   drm->g_next_bo = gbm_surface_lock_front_buffer(drm->g_gbm_surface);

   fb = (struct drm_fb*)drm_fb_get_from_bo(drm, drm->g_next_bo);

   ret = drmModePageFlip(drm->g_drm_fd, drm->g_crtc_id, fb->fb_id,
         DRM_MODE_PAGE_FLIP_EVENT, &waiting_for_flip);

   if (ret < 0)
   {
      RARCH_ERR("[KMS/EGL]: Failed to queue page flip.\n");
      return;
   }

   waiting_for_flip = true;
}
예제 #22
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;
}
예제 #23
0
static int display_swap(struct uterm_display *disp)
{
	int ret;

	if (!display_is_online(disp) || !video_is_awake(disp->video))
		return -EINVAL;
	if (disp->dpms != UTERM_DPMS_ON)
		return -EINVAL;

	errno = 0;
	disp->dumb.current_rb ^= 1;
	ret = drmModePageFlip(disp->video->dumb.fd, disp->dumb.crtc_id,
				disp->dumb.rb[disp->dumb.current_rb].fb,
				DRM_MODE_PAGE_FLIP_EVENT, disp);
	if (ret) {
		log_warn("page-flip failed %d %d", ret, errno);
		return -EFAULT;
	}
	uterm_display_ref(disp);
	disp->flags |= DISPLAY_VSYNC;

	return 0;
}
예제 #24
0
static DFBResult
drmkmsUpdateFlipRegion( CoreLayer             *layer,
                        void                  *driver_data,
                        void                  *layer_data,
                        void                  *region_data,
                        CoreSurface           *surface,
                        DFBSurfaceFlipFlags    flags,
                        const DFBRegion       *left_update,
                        CoreSurfaceBufferLock *left_lock,
                        const DFBRegion       *right_update,
                        CoreSurfaceBufferLock *right_lock,
                        bool                   flip )
{
     int               ret, i;
     DRMKMSData       *drmkms = driver_data;
     DRMKMSDataShared *shared = drmkms->shared;
     DRMKMSLayerData  *data   = layer_data;

     D_DEBUG_AT( DRMKMS_Layer, "%s()\n", __FUNCTION__ );

     if (!drmkms->resources) {
          if (flip)
               dfb_surface_flip( surface, false );

          if (left_lock->buffer)
               dfb_surface_notify_display( surface, left_lock->buffer );

          if (right_lock && right_lock->buffer)
               dfb_surface_notify_display( surface, right_lock->buffer );

          if (left_lock->task)
               Task_Done( left_lock->task );

          if (right_lock && right_lock->task)
               Task_Done( right_lock->task );

          return DFB_OK;
     }


     direct_mutex_lock( &data->lock );


     while (data->flip_pending) {
          D_DEBUG_AT( DRMKMS_Layer, "  -> waiting for pending flip (previous)\n" );

          if (direct_waitqueue_wait_timeout( &data->wq_event, &data->lock, 30000 ) == DR_TIMEOUT)
               break;
     }


     dfb_surface_ref( surface );
     data->surface = surface;
     data->surfacebuffer_index = left_lock->buffer->index;

     /* Task */
     data->pending_task = left_lock->task;

     D_DEBUG_AT( DRMKMS_Layer, "  -> calling drmModePageFlip()\n" );

     data->flip_pending = true;

     ret = drmModePageFlip( drmkms->fd, drmkms->encoder[data->layer_index]->crtc_id, (u32)(long)left_lock->handle, DRM_MODE_PAGE_FLIP_EVENT, layer_data );
     if (ret) {
          D_PERROR( "DirectFB/DRMKMS: drmModePageFlip() failed on layer %d!\n", data->index );

          direct_mutex_unlock( &data->lock );

          return DFB_FAILURE;
     }

     if (shared->mirror_outputs) {
          for (i=1; i<shared->enabled_crtcs; i++) {
               ret = drmModePageFlip( drmkms->fd, drmkms->encoder[i]->crtc_id, (u32)(long)left_lock->handle, 0, 0);
               if (ret)
                    D_WARN( "DirectFB/DRMKMS: drmModePageFlip() failed for mirror on crtc id %d!\n", drmkms->encoder[i]->crtc_id );
          }
     }

     shared->primary_fb = (u32)(long)left_lock->handle;

     if (flip)
          dfb_surface_flip( surface, false );

     if ((flags & DSFLIP_WAITFORSYNC) == DSFLIP_WAITFORSYNC) {
          while (data->flip_pending) {
               D_DEBUG_AT( DRMKMS_Layer, "  -> waiting for pending flip (WAITFORSYNC)\n" );

               if (direct_waitqueue_wait_timeout( &data->wq_event, &data->lock, 30000 ) == DR_TIMEOUT)
                    break;
          }
     }

     direct_mutex_unlock( &data->lock );

     return DFB_OK;
}
예제 #25
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);
    }
}
예제 #26
0
static Bool
queue_flip_on_crtc(ScreenPtr screen, xf86CrtcPtr crtc,
                   struct ms_flipdata *flipdata,
                   int ref_crtc_vblank_pipe, uint32_t flags)
{
    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
    modesettingPtr ms = modesettingPTR(scrn);
    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
    struct ms_crtc_pageflip *flip;
    uint32_t seq;
    int err;

    flip = calloc(1, sizeof(struct ms_crtc_pageflip));
    if (flip == NULL) {
        xf86DrvMsg(scrn->scrnIndex, X_WARNING,
                   "flip queue: carrier alloc failed.\n");
        return FALSE;
    }

    /* Only the reference crtc will finally deliver its page flip
     * completion event. All other crtc's events will be discarded.
     */
    flip->on_reference_crtc = (drmmode_crtc->vblank_pipe == ref_crtc_vblank_pipe);
    flip->flipdata = flipdata;

    seq = ms_drm_queue_alloc(crtc, flip, ms_flip_handler, ms_present_flip_abort);
    if (!seq) {
        free(flip);
        return FALSE;
    }

    DebugPresent(("\t\tms:fq %lld c %d -> %d seq %llu\n",
                  (long long) flipdata->event->event_id,
                  flipdata->flip_count, flipdata->flip_count + 1,
                  (long long) seq));

    /* take a reference on flipdata for use in flip */
    flipdata->flip_count++;

    while (drmModePageFlip(ms->fd, drmmode_crtc->mode_crtc->crtc_id,
                           ms->drmmode.fb_id, flags, (void *) (uintptr_t) seq)) {
        err = errno;
        /* We may have failed because the event queue was full.  Flush it
         * and retry.  If there was nothing to flush, then we failed for
         * some other reason and should just return an error.
         */
        if (ms_flush_drm_events(screen) <= 0) {
            xf86DrvMsg(scrn->scrnIndex, X_WARNING,
                       "flip queue failed: %s\n", strerror(err));
            /* Aborting will also decrement flip_count and free(flip). */
            ms_drm_abort_seq(scrn, seq);
            return FALSE;
        }

        /* We flushed some events, so try again. */
        xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue retry\n");
    }

    /* The page flip succeded. */
    return TRUE;
}
예제 #27
0
/*!***********************************************************************
 @Function		OsRenderComplete
 @Returns		false when the app should quit
 @description	Main message loop / render loop
*************************************************************************/
void PVRShellInit::OsRenderComplete()
{
	int		ckb = 0;
	size_t  bytes_read;
	int ret, i;
	struct gbm_bo *bo;
	struct SDrmFbWrapper *fb;
	int waiting_for_flip = 1;
	fd_set fds;
	drmEventContext evctx;
	evctx.version = DRM_EVENT_CONTEXT_VERSION;
	evctx.page_flip_handler = pfnCallbackDrmPageFlip;

	bo = gbm_surface_lock_front_buffer(m_psGbmSurface);
	fb = DrmFbGetFromBo(bo);
	
	if(!m_ui32CurrentFb) 
	{
		ret = drmModeSetCrtc(m_i32DrmFile, m_ui32DrmCrtcId, fb->ui32FbId, 0, 0,
				&m_ui32DrmConnectorId, 1, m_psDrmMode);

		if (ret) 
		{
			m_pShell->PVRShellOutputDebug("display failed to set mode: %s\n", strerror(errno));
			return;
		}
	} else 
	{
		ret = drmModePageFlip(m_i32DrmFile, m_ui32DrmCrtcId, fb->ui32FbId,
				DRM_MODE_PAGE_FLIP_EVENT, &waiting_for_flip);

		if (ret) 
		{
			m_pShell->PVRShellOutputDebug("display failed to flip page: %s\n", strerror(errno));
			return;
		}

		FD_ZERO(&fds);
		FD_SET(m_i32DrmFile, &fds);

		while (waiting_for_flip) 
		{
			ret = select(m_i32DrmFile + 1, &fds, NULL, NULL, NULL);

			if (ret < 0) 
			{
				m_pShell->PVRShellOutputDebug("Select Error: %s\n", strerror(errno));
				return;
			} 
			else if (ret == 0) 
			{
				m_pShell->PVRShellOutputDebug("Select Timeout\n");
				return;
			} 
			else if (FD_ISSET(0, &fds)) 
			{
				continue;
			}

			drmHandleEvent(m_i32DrmFile, &evctx);
		}
	}
	// Check keyboard and keypad

	// Keyboard.
	if(devfd > 0)
	{
		while ((bytes_read = read(devfd, &ckb, 1)) == 1);

		switch(ckb)
		{
		case '0':
		case 'q':
		case 'Q':
			nLastKeyPressed = PVRShellKeyNameQUIT;
			break;
		case 13:
			nLastKeyPressed = PVRShellKeyNameSELECT;
			break;
		case ' ':
		case '1':
			nLastKeyPressed = PVRShellKeyNameACTION1;
			break;
		case '2':
			nLastKeyPressed = PVRShellKeyNameACTION2;
			break;
		case 65: // Up Arrow
			nLastKeyPressed = m_eKeyMapUP;
			break;
		case 66: // Down Arrow
			nLastKeyPressed = m_eKeyMapDOWN;
			break;
		case 68: // Left Arrow
			nLastKeyPressed = m_eKeyMapLEFT;
			break;
		case 67: // Right Arrow
			nLastKeyPressed = m_eKeyMapRIGHT;
			break;
		default:
			break;
		}

	}


}
예제 #28
0
static int test_format(const char *test_name,
		       struct kmstest_connector_config *cconf,
		       drmModeModeInfo *mode, uint32_t format,
		       enum test_flags flags)
{
	int width;
	int height;
	struct igt_fb fb[2];
	char *mode_format_str;
	char *cconf_str;
	int ret;

	ret = asprintf(&mode_format_str, "%s @ %dHz / %s",
		 mode->name, mode->vrefresh, igt_format_str(format));
	igt_assert_lt(0, ret);
	ret = asprintf(&cconf_str, "pipe %s, encoder %s, connector %s",
		       kmstest_pipe_name(cconf->pipe),
		       kmstest_encoder_type_str(cconf->encoder->encoder_type),
		       kmstest_connector_type_str(cconf->connector->connector_type));
	igt_assert_lt(0, ret);

	igt_info("Beginning test %s with %s on %s\n",
		 test_name, mode_format_str, cconf_str);

	width = mode->hdisplay;
	height = mode->vdisplay;

	if (!igt_create_fb(drm_fd, width, height, format,
			   LOCAL_DRM_FORMAT_MOD_NONE, &fb[0]))
		goto err1;

	if (!igt_create_fb(drm_fd, width, height, format,
			   LOCAL_DRM_FORMAT_MOD_NONE,	&fb[1]))
		goto err2;

	if (drmModeSetCrtc(drm_fd, cconf->crtc->crtc_id, fb[0].fb_id,
				 0, 0, &cconf->connector->connector_id, 1,
				 mode))
		goto err2;
	do_or_die(drmModePageFlip(drm_fd, cconf->crtc->crtc_id, fb[0].fb_id,
				  0, NULL));
	sleep(2);

	if (flags & TEST_DIRECT_RENDER) {
		paint_fb(&fb[0], test_name, mode_format_str, cconf_str);
	} else if (flags & TEST_GPU_BLIT) {
		paint_fb(&fb[1], test_name, mode_format_str, cconf_str);
		gpu_blit(&fb[0], &fb[1]);
	}
	sleep(5);

	igt_info("Test %s with %s on %s: PASSED\n",
		 test_name, mode_format_str, cconf_str);
	free(mode_format_str);
	free(cconf_str);

	igt_remove_fb(drm_fd, &fb[1]);
	igt_remove_fb(drm_fd, &fb[0]);

	return 0;

err2:
	igt_remove_fb(drm_fd, &fb[0]);
err1:
	igt_info("Test %s with %s on %s: SKIPPED\n",
		 test_name, mode_format_str, cconf_str);
	free(mode_format_str);
	free(cconf_str);

	return -1;
}
static Bool
nouveau_present_flip_exec(ScrnInfoPtr scrn, uint64_t event_id, int sync,
			  uint64_t target_msc, PixmapPtr pixmap, Bool vsync)
{
	ScreenPtr screen = scrn->pScreen;
	struct nouveau_pixmap *priv = NULL;
	NVPtr pNv = NVPTR(scrn);
	uint32_t next_fb;
	CARD16 stride;
	CARD32 size;
	void *token;
	int ret;

#ifdef HAVE_GLAMOR
	if (pNv->AccelMethod == GLAMOR &&
	    !(priv = nouveau_glamor_pixmap_get(pixmap))) {
		int fd = glamor_fd_from_pixmap(screen, pixmap, &stride, &size);
		if (fd < 0)
			return FALSE;

		priv = calloc(1, sizeof(*priv));
		if (!priv)
			return FALSE;

		ret = nouveau_bo_prime_handle_ref(pNv->dev, fd, &priv->bo);
		if (ret) {
			free(priv);
			return FALSE;
		}

		nouveau_glamor_pixmap_set(pixmap, priv);
	} else
#endif
	if (!priv)
		priv = nouveau_pixmap(pixmap);

	ret = drmModeAddFB(pNv->dev->fd, pixmap->drawable.width,
			   pixmap->drawable.height, pixmap->drawable.depth,
			   pixmap->drawable.bitsPerPixel, pixmap->devKind,
			   priv->bo->handle, &next_fb);
	if (ret == 0) {
		struct nouveau_present_flip *flip =
			drmmode_event_queue(scrn, event_id, sizeof(*flip),
					    nouveau_present_flip, &token);
		if (flip) {
			xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
			int last = 0, i;

			drmmode_swap(scrn, next_fb, &flip->old);
			flip->fd = pNv->dev->fd;
			flip->msc = target_msc;

			for (i = 0; i < config->num_crtc; i++) {
				if (config->crtc[i]->enabled)
					last = i;
			}

			for (i = 0; i < config->num_crtc; i++) {
				int type = vsync ? 0 : DRM_MODE_PAGE_FLIP_ASYNC;
				int crtc = drmmode_crtc(config->crtc[i]);
				void *user = NULL;

				if (!config->crtc[i]->enabled)
					continue;

				if (token && ((crtc == sync) || (i == last))) {
					type |= DRM_MODE_PAGE_FLIP_EVENT;
					user  = token;
				}

				ret = drmModePageFlip(pNv->dev->fd, crtc,
						      next_fb, type, user);
				if (ret == 0 && user) {
					token = NULL;
				}
			}

			if (token == NULL) {
				return TRUE;
			}

			drmmode_swap(scrn, flip->old, &next_fb);
			drmmode_event_abort(scrn, event_id, false);
		}

		drmModeRmFB(pNv->dev->fd, next_fb);
	}

	return FALSE;
}
예제 #30
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;
}