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; }
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; } }
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; }
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); }
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; }
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; }
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; }
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; }
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; } }
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; } }
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); } }
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 } };
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; }
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; } }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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); } }
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; }
/*!*********************************************************************** @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; } } }
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; }
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; }