static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *new_fb, struct drm_pending_vblank_event *event, uint32_t flags, struct drm_modeset_acquire_ctx *ctx) { struct vmw_private *dev_priv = vmw_priv(crtc->dev); int ret; if (!vmw_kms_crtc_flippable(dev_priv, crtc)) return -EINVAL; ret = drm_atomic_helper_page_flip(crtc, new_fb, event, flags, ctx); if (ret) { DRM_ERROR("Page flip error %d.\n", ret); return ret; } if (vmw_crtc_to_du(crtc)->is_implicit) vmw_kms_update_implicit_fb(dev_priv, crtc); return ret; }
int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, uint32_t handle, uint32_t width, uint32_t height) { struct vmw_private *dev_priv = vmw_priv(crtc->dev); struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; struct vmw_display_unit *du = vmw_crtc_to_du(crtc); struct vmw_surface *surface = NULL; struct vmw_dma_buffer *dmabuf = NULL; int ret; if (handle) { ret = vmw_user_surface_lookup_handle(dev_priv, tfile, handle, &surface); if (!ret) { if (!surface->snooper.image) { DRM_ERROR("surface not suitable for cursor\n"); return -EINVAL; } } else { ret = vmw_user_dmabuf_lookup(tfile, handle, &dmabuf); if (ret) { DRM_ERROR("failed to find surface or dmabuf: %i\n", ret); return -EINVAL; } } } /* takedown old cursor */ if (du->cursor_surface) { du->cursor_surface->snooper.crtc = NULL; vmw_surface_unreference(&du->cursor_surface); } if (du->cursor_dmabuf) vmw_dmabuf_unreference(&du->cursor_dmabuf); /* setup new image */ if (surface) { /* vmw_user_surface_lookup takes one reference */ du->cursor_surface = surface; du->cursor_surface->snooper.crtc = crtc; du->cursor_age = du->cursor_surface->snooper.age; vmw_cursor_update_image(dev_priv, surface->snooper.image, 64, 64, du->hotspot_x, du->hotspot_y); } else if (dmabuf) { struct ttm_bo_kmap_obj map; unsigned long kmap_offset; unsigned long kmap_num; void *virtual; bool dummy; /* vmw_user_surface_lookup takes one reference */ du->cursor_dmabuf = dmabuf; kmap_offset = 0; kmap_num = (64*64*4) >> PAGE_SHIFT; ret = ttm_bo_reserve(&dmabuf->base, true, false, false, 0); if (unlikely(ret != 0)) { DRM_ERROR("reserve failed\n"); return -EINVAL; } ret = ttm_bo_kmap(&dmabuf->base, kmap_offset, kmap_num, &map); if (unlikely(ret != 0)) goto err_unreserve; virtual = ttm_kmap_obj_virtual(&map, &dummy); vmw_cursor_update_image(dev_priv, virtual, 64, 64, du->hotspot_x, du->hotspot_y); ttm_bo_kunmap(&map); err_unreserve: ttm_bo_unreserve(&dmabuf->base); } else {
static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, struct drm_pending_vblank_event *event, uint32_t flags) { struct vmw_private *dev_priv = vmw_priv(crtc->dev); struct drm_framebuffer *old_fb = crtc->primary->fb; struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(fb); struct vmw_fence_obj *fence = NULL; struct drm_vmw_rect vclips; int ret; if (!vmw_kms_crtc_flippable(dev_priv, crtc)) return -EINVAL; crtc->primary->fb = fb; /* do a full screen dirty update */ vclips.x = crtc->x; vclips.y = crtc->y; vclips.w = crtc->mode.hdisplay; vclips.h = crtc->mode.vdisplay; if (vfb->dmabuf) ret = vmw_kms_sou_do_dmabuf_dirty(dev_priv, vfb, NULL, &vclips, 1, 1, true, &fence); else ret = vmw_kms_sou_do_surface_dirty(dev_priv, vfb, NULL, &vclips, NULL, 0, 0, 1, 1, &fence); if (ret != 0) goto out_no_fence; if (!fence) { ret = -EINVAL; goto out_no_fence; } if (event) { struct drm_file *file_priv = event->base.file_priv; ret = vmw_event_fence_action_queue(file_priv, fence, &event->base, &event->event.tv_sec, &event->event.tv_usec, true); } /* * No need to hold on to this now. The only cleanup * we need to do if we fail is unref the fence. */ vmw_fence_obj_unreference(&fence); if (vmw_crtc_to_du(crtc)->is_implicit) vmw_kms_update_implicit_fb(dev_priv, crtc); return ret; out_no_fence: crtc->primary->fb = old_fb; return ret; }
static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, struct drm_pending_vblank_event *event, uint32_t flags) { struct vmw_private *dev_priv = vmw_priv(crtc->dev); struct drm_framebuffer *old_fb = crtc->primary->fb; struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(fb); struct vmw_fence_obj *fence = NULL; struct drm_clip_rect clips; int ret; /* require ScreenObject support for page flipping */ if (!dev_priv->sou_priv) return -ENOSYS; if (!vmw_sou_screen_object_flippable(dev_priv, crtc)) return -EINVAL; crtc->primary->fb = fb; /* do a full screen dirty update */ clips.x1 = clips.y1 = 0; clips.x2 = fb->width; clips.y2 = fb->height; if (vfb->dmabuf) ret = vmw_kms_sou_do_dmabuf_dirty(dev_priv, vfb, &clips, 1, 1, true, &fence); else ret = vmw_kms_sou_do_surface_dirty(dev_priv, vfb, &clips, NULL, NULL, 0, 0, 1, 1, &fence); if (ret != 0) goto out_no_fence; if (!fence) { ret = -EINVAL; goto out_no_fence; } if (event) { struct drm_file *file_priv = event->base.file_priv; ret = vmw_event_fence_action_queue(file_priv, fence, &event->base, &event->event.tv_sec, &event->event.tv_usec, true); } /* * No need to hold on to this now. The only cleanup * we need to do if we fail is unref the fence. */ vmw_fence_obj_unreference(&fence); if (vmw_crtc_to_du(crtc)->is_implicit) vmw_sou_update_implicit_fb(dev_priv, crtc); return ret; out_no_fence: crtc->primary->fb = old_fb; return ret; }
static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *new_fb, struct drm_pending_vblank_event *event, uint32_t flags, struct drm_modeset_acquire_ctx *ctx) { struct vmw_private *dev_priv = vmw_priv(crtc->dev); struct drm_framebuffer *old_fb = crtc->primary->fb; struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(new_fb); struct vmw_fence_obj *fence = NULL; struct drm_vmw_rect vclips; int ret; if (!vmw_kms_crtc_flippable(dev_priv, crtc)) return -EINVAL; flags &= ~DRM_MODE_PAGE_FLIP_ASYNC; ret = drm_atomic_helper_page_flip(crtc, new_fb, NULL, flags, ctx); if (ret) { DRM_ERROR("Page flip error %d.\n", ret); return ret; } /* do a full screen dirty update */ vclips.x = crtc->x; vclips.y = crtc->y; vclips.w = crtc->mode.hdisplay; vclips.h = crtc->mode.vdisplay; if (vfb->dmabuf) ret = vmw_kms_sou_do_dmabuf_dirty(dev_priv, vfb, NULL, &vclips, 1, 1, true, &fence); else ret = vmw_kms_sou_do_surface_dirty(dev_priv, vfb, NULL, &vclips, NULL, 0, 0, 1, 1, &fence); if (ret != 0) goto out_no_fence; if (!fence) { ret = -EINVAL; goto out_no_fence; } if (event) { struct drm_file *file_priv = event->base.file_priv; ret = vmw_event_fence_action_queue(file_priv, fence, &event->base, &event->event.tv_sec, &event->event.tv_usec, true); } /* * No need to hold on to this now. The only cleanup * we need to do if we fail is unref the fence. */ vmw_fence_obj_unreference(&fence); if (vmw_crtc_to_du(crtc)->is_implicit) vmw_kms_update_implicit_fb(dev_priv, crtc); return ret; out_no_fence: drm_atomic_set_fb_for_plane(crtc->primary->state, old_fb); return ret; }