/** * vmw_stdu_crtc_page_flip - Binds a buffer to a screen target * * @crtc: CRTC to attach FB to * @fb: FB to attach * @event: Event to be posted. This event should've been alloced * using k[mz]alloc, and should've been completely initialized. * @page_flip_flags: Input flags. * * If the STDU uses the same display and content buffers, i.e. a true flip, * this function will replace the existing display buffer with the new content * buffer. * * If the STDU uses different display and content buffers, i.e. a blit, then * only the content buffer will be updated. * * RETURNS: * 0 on success, error code on failure */ static int vmw_stdu_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *new_fb, struct drm_pending_vblank_event *event, uint32_t flags) { struct vmw_private *dev_priv = vmw_priv(crtc->dev); struct vmw_screen_target_display_unit *stdu; struct drm_vmw_rect vclips; struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(new_fb); int ret; dev_priv = vmw_priv(crtc->dev); stdu = vmw_crtc_to_stdu(crtc); if (!stdu->defined || !vmw_kms_crtc_flippable(dev_priv, crtc)) return -EINVAL; ret = vmw_stdu_bind_fb(dev_priv, crtc, &crtc->mode, new_fb); if (ret) return ret; if (stdu->base.is_implicit) vmw_kms_update_implicit_fb(dev_priv, crtc); vclips.x = crtc->x; vclips.y = crtc->y; vclips.w = crtc->mode.hdisplay; vclips.h = crtc->mode.vdisplay; if (vfb->dmabuf) ret = vmw_kms_stdu_dma(dev_priv, NULL, vfb, NULL, NULL, &vclips, 1, 1, true, false); else ret = vmw_kms_stdu_surface_dirty(dev_priv, vfb, NULL, &vclips, NULL, 0, 0, 1, 1, NULL); if (ret) return ret; if (event) { struct vmw_fence_obj *fence = NULL; struct drm_file *file_priv = event->base.file_priv; vmw_execbuf_fence_commands(NULL, dev_priv, &fence, NULL); if (!fence) return -ENOMEM; ret = vmw_event_fence_action_queue(file_priv, fence, &event->base, &event->event.tv_sec, &event->event.tv_usec, true); vmw_fence_obj_unreference(&fence); } else { vmw_fifo_flush(dev_priv, false); } return 0; }
/** * vmw_stdu_crtc_page_flip - Binds a buffer to a screen target * * @crtc: CRTC to attach FB to * @fb: FB to attach * @event: Event to be posted. This event should've been alloced * using k[mz]alloc, and should've been completely initialized. * @page_flip_flags: Input flags. * * If the STDU uses the same display and content buffers, i.e. a true flip, * this function will replace the existing display buffer with the new content * buffer. * * If the STDU uses different display and content buffers, i.e. a blit, then * only the content buffer will be updated. * * RETURNS: * 0 on success, error code on failure */ static int vmw_stdu_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *new_fb, struct drm_pending_vblank_event *event, uint32_t flags) { struct vmw_private *dev_priv = vmw_priv(crtc->dev); struct vmw_screen_target_display_unit *stdu; int ret; if (crtc == NULL) return -EINVAL; dev_priv = vmw_priv(crtc->dev); stdu = vmw_crtc_to_stdu(crtc); crtc->primary->fb = new_fb; stdu->content_fb = new_fb; if (stdu->display_srf) { /* * If the display surface is the same as the content surface * then remove the reference */ if (stdu->content_fb_type == SAME_AS_DISPLAY) { if (stdu->defined) { /* Unbind the current surface */ ret = vmw_stdu_bind_st(dev_priv, stdu, NULL); if (unlikely(ret != 0)) goto err_out; } vmw_stdu_unpin_display(stdu); stdu->display_srf = NULL; } } if (!new_fb) { /* Blanks the display */ (void) vmw_stdu_update_st(dev_priv, stdu); return 0; } if (stdu->content_fb_type == SAME_AS_DISPLAY) { stdu->display_srf = vmw_framebuffer_to_vfbs(new_fb)->surface; ret = vmw_stdu_pin_display(stdu); if (ret) { stdu->display_srf = NULL; goto err_out; } /* Bind display surface */ ret = vmw_stdu_bind_st(dev_priv, stdu, &stdu->display_srf->res); if (unlikely(ret != 0)) goto err_unpin_display_and_content; } /* Update display surface: after this point everything is bound */ ret = vmw_stdu_update_st(dev_priv, stdu); if (unlikely(ret != 0)) return ret; if (event) { struct vmw_fence_obj *fence = NULL; struct drm_file *file_priv = event->base.file_priv; vmw_execbuf_fence_commands(NULL, dev_priv, &fence, NULL); if (!fence) return -ENOMEM; ret = vmw_event_fence_action_queue(file_priv, fence, &event->base, &event->event.tv_sec, &event->event.tv_usec, true); vmw_fence_obj_unreference(&fence); } return ret; err_unpin_display_and_content: vmw_stdu_unpin_display(stdu); err_out: crtc->primary->fb = NULL; stdu->content_fb = NULL; return ret; }