static void _evas_outbuf_buffer_put(Outbuf *ob, Buffer *buffer, Eina_Rectangle *rects, unsigned int count) { /* validate input params */ if ((!ob) || (!buffer)) return; #ifdef DRM_MODE_FEATURE_DIRTYFB drmModeClip *clip; unsigned int i = 0; int ret; clip = alloca(count * sizeof(drmModeClip)); for (i = 0; i < count; i++) { clip[i].x1 = rects[i].x; clip[i].y1 = rects[i].y; clip[i].x2 = rects[i].w; clip[i].y2 = rects[i].h; } /* DBG("Marking FB Dirty: %d", buffer->fb); */ ret = drmModeDirtyFB(ob->priv.fd, buffer->fb, clip, count); if (ret) { if (ret == -EINVAL) ERR("Could not set FB Dirty: %m"); } #endif }
static void end_flush (ply_renderer_driver_t *driver, uint32_t buffer_id) { ply_renderer_buffer_t *buffer; buffer = get_buffer_from_id (driver, buffer_id); assert (buffer != NULL); if (driver->requires_explicit_flushing) { struct drm_clip_rect flush_area; int ret; flush_area.x1 = 0; flush_area.y1 = 0; flush_area.x2 = buffer->width; flush_area.y2 = buffer->height; ret = drmModeDirtyFB (driver->device_fd, buffer->id, &flush_area, 1); if (ret == -ENOSYS) driver->requires_explicit_flushing = false; } }
static int test2(void) { drm_intel_bo *test_intel_bo; uint32_t fb_id; drmModeClip clip; int prime_fd; uint32_t udl_handle; int ret; test_intel_bo = drm_intel_bo_alloc(bufmgr, "test bo", BO_SIZE, 4096); drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd); ret = drmPrimeFDToHandle(udl_fd, prime_fd, &udl_handle); if (ret) goto out; ret = drmModeAddFB(udl_fd, 640, 480, 16, 16, 640, udl_handle, &fb_id); if (ret) goto out; clip.x1 = 0; clip.y1 = 0; clip.x2 = 10; clip.y2 = 10; ret = drmModeDirtyFB(udl_fd, fb_id, &clip, 1); if (ret) { return ret; } out: dumb_bo_destroy(udl_fd, udl_handle); drm_intel_bo_unreference(test_intel_bo); return ret; }
static int dispatch_dirty_region(ScrnInfoPtr scrn, PixmapPtr pixmap, DamagePtr damage, int fb_id) { modesettingPtr ms = modesettingPTR(scrn); RegionPtr dirty = DamageRegion(damage); unsigned num_cliprects = REGION_NUM_RECTS(dirty); int ret = 0; if (num_cliprects) { drmModeClip *clip = malloc(num_cliprects * sizeof(drmModeClip)); BoxPtr rect = REGION_RECTS(dirty); int i; if (!clip) return -ENOMEM; /* XXX no need for copy? */ for (i = 0; i < num_cliprects; i++, rect++) { clip[i].x1 = rect->x1; clip[i].y1 = rect->y1; clip[i].x2 = rect->x2; clip[i].y2 = rect->y2; } /* TODO query connector property to see if this is needed */ ret = drmModeDirtyFB(ms->fd, fb_id, clip, num_cliprects); free(clip); DamageEmpty(damage); } return ret; }
static boolean drm_surface_flush_frontbuffer(struct native_surface *nsurf) { #ifdef DRM_MODE_FEATURE_DIRTYFB struct drm_surface *drmsurf = drm_surface(nsurf); struct drm_display *drmdpy = drmsurf->drmdpy; if (drmsurf->front_fb.is_passive) drmModeDirtyFB(drmdpy->fd, drmsurf->front_fb.buffer_id, NULL, 0); #endif return TRUE; }
/* * Program CRTC. */ static int drm_kms_set_crtc(struct gralloc_drm_t *drm, int fb_id) { int ret; ret = drmModeSetCrtc(drm->fd, drm->crtc_id, fb_id, 0, 0, &drm->connector_id, 1, &drm->mode); if (ret) { LOGE("failed to set crtc"); return ret; } if (drm->mode_quirk_vmwgfx) ret = drmModeDirtyFB(drm->fd, fb_id, &drm->clip, 1); return ret; }
static void draw_rect(struct igt_fb *fb, enum igt_draw_method method, uint32_t color) { drmModeClip clip; int rc; switch (opts.draw_size) { case 0: clip.x1 = fb->width / 2 - 32; clip.x2 = fb->width / 2 + 32; clip.y1 = fb->height / 2 - 32; clip.y2 = fb->height / 2 + 32; break; case 1: clip.x1 = fb->width / 4; clip.x2 = fb->width / 4 + fb->width / 2; clip.y1 = fb->height / 4; clip.y2 = fb->height / 4 + fb->height / 2; break; case 2: clip.x1 = 0; clip.x2 = fb->width; clip.y1 = 0; clip.y2 = fb->height; break; default: igt_assert(false); } igt_draw_rect_fb(drm.fd, drm.bufmgr, NULL, fb, method, clip.x1, clip.y1, clip.x2 - clip.x1, clip.y2 - clip.y1, color); if (method == IGT_DRAW_MMAP_WC) { rc = drmModeDirtyFB(drm.fd, fb->fb_id, &clip, 1); igt_assert(rc == 0 || rc == -ENOSYS); } }
/* * Post a bo. This is not thread-safe. */ int gralloc_drm_bo_post(struct gralloc_drm_bo_t *bo) { struct gralloc_drm_t *drm = bo->drm; int ret; if (!bo->fb_id && drm->swap_mode != DRM_SWAP_COPY) { LOGE("unable to post bo %p without fb", bo); return -EINVAL; } /* TODO spawn a thread to avoid waiting and race */ if (drm->first_post) { if (drm->swap_mode == DRM_SWAP_COPY) { struct gralloc_drm_bo_t *dst; dst = (drm->next_front) ? drm->next_front : drm->current_front; drm->drv->copy(drm->drv, dst, bo, 0, 0, bo->handle->width, bo->handle->height); bo = dst; } ret = drm_kms_set_crtc(drm, bo->fb_id); if (!ret) { drm->first_post = 0; drm->current_front = bo; if (drm->next_front == bo) drm->next_front = NULL; } return ret; } switch (drm->swap_mode) { case DRM_SWAP_FLIP: if (drm->swap_interval > 1) drm_kms_wait_for_post(drm, 1); ret = drm_kms_page_flip(drm, bo); if (drm->next_front) { /* * wait if the driver says so or the current front * will be written by CPU */ if (drm->mode_sync_flip || (drm->current_front->handle->usage & GRALLOC_USAGE_SW_WRITE_MASK)) drm_kms_page_flip(drm, NULL); } break; case DRM_SWAP_COPY: drm_kms_wait_for_post(drm, 0); drm->drv->copy(drm->drv, drm->current_front, bo, 0, 0, bo->handle->width, bo->handle->height); if (drm->mode_quirk_vmwgfx) ret = drmModeDirtyFB(drm->fd, drm->current_front->fb_id, &drm->clip, 1); ret = 0; break; case DRM_SWAP_SETCRTC: drm_kms_wait_for_post(drm, 0); ret = drm_kms_set_crtc(drm, bo->fb_id); drm->current_front = bo; break; default: /* no-op */ ret = 0; break; } return ret; }
static Bool CreateScreenResources(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); modesettingPtr ms = modesettingPTR(pScrn); PixmapPtr rootPixmap; Bool ret; void *pixels = NULL; int err; pScreen->CreateScreenResources = ms->createScreenResources; ret = pScreen->CreateScreenResources(pScreen); pScreen->CreateScreenResources = CreateScreenResources; if (!drmmode_set_desired_modes(pScrn, &ms->drmmode)) return FALSE; if (!drmmode_glamor_handle_new_screen_pixmap(&ms->drmmode)) return FALSE; drmmode_uevent_init(pScrn, &ms->drmmode); if (!ms->drmmode.sw_cursor) drmmode_map_cursor_bos(pScrn, &ms->drmmode); if (!ms->drmmode.gbm) { pixels = drmmode_map_front_bo(&ms->drmmode); if (!pixels) return FALSE; } rootPixmap = pScreen->GetScreenPixmap(pScreen); if (ms->drmmode.shadow_enable) pixels = ms->drmmode.shadow_fb; if (!pScreen->ModifyPixmapHeader(rootPixmap, -1, -1, -1, -1, -1, pixels)) FatalError("Couldn't adjust screen pixmap\n"); if (ms->drmmode.shadow_enable) { if (!shadowAdd(pScreen, rootPixmap, msUpdatePacked, msShadowWindow, 0, 0)) return FALSE; } err = drmModeDirtyFB(ms->fd, ms->drmmode.fb_id, NULL, 0); if (err != -EINVAL && err != -ENOSYS) { ms->damage = DamageCreate(NULL, NULL, DamageReportNone, TRUE, pScreen, rootPixmap); if (ms->damage) { DamageRegister(&rootPixmap->drawable, ms->damage); ms->dirty_enabled = TRUE; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Damage tracking initialized\n"); } else { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to create screen damage record\n"); return FALSE; } } return ret; }