4343#define vmw_connector_to_stdu (x ) \
4444 container_of(x, struct vmw_screen_target_display_unit, base.connector)
4545
46-
46+ /*
47+ * Some renderers such as llvmpipe will align the width and height of their
48+ * buffers to match their tile size. We need to keep this in mind when exposing
49+ * modes to userspace so that this possible over-allocation will not exceed
50+ * graphics memory. 64x64 pixels seems to be a reasonable upper bound for the
51+ * tile size of current renderers.
52+ */
53+ #define GPU_TILE_SIZE 64
4754
4855enum stdu_content_type {
4956 SAME_AS_DISPLAY = 0 ,
@@ -85,11 +92,6 @@ struct vmw_stdu_update {
8592 SVGA3dCmdUpdateGBScreenTarget body ;
8693};
8794
88- struct vmw_stdu_dma {
89- SVGA3dCmdHeader header ;
90- SVGA3dCmdSurfaceDMA body ;
91- };
92-
9395struct vmw_stdu_surface_copy {
9496 SVGA3dCmdHeader header ;
9597 SVGA3dCmdSurfaceCopy body ;
@@ -414,6 +416,7 @@ static void vmw_stdu_crtc_atomic_disable(struct drm_crtc *crtc,
414416{
415417 struct vmw_private * dev_priv ;
416418 struct vmw_screen_target_display_unit * stdu ;
419+ struct drm_crtc_state * new_crtc_state ;
417420 int ret ;
418421
419422 if (!crtc ) {
@@ -423,6 +426,7 @@ static void vmw_stdu_crtc_atomic_disable(struct drm_crtc *crtc,
423426
424427 stdu = vmw_crtc_to_stdu (crtc );
425428 dev_priv = vmw_priv (crtc -> dev );
429+ new_crtc_state = drm_atomic_get_new_crtc_state (state , crtc );
426430
427431 if (dev_priv -> vkms_enabled )
428432 drm_crtc_vblank_off (crtc );
@@ -434,6 +438,14 @@ static void vmw_stdu_crtc_atomic_disable(struct drm_crtc *crtc,
434438
435439 (void ) vmw_stdu_update_st (dev_priv , stdu );
436440
441+ /* Don't destroy the Screen Target if we are only setting the
442+ * display as inactive
443+ */
444+ if (new_crtc_state -> enable &&
445+ !new_crtc_state -> active &&
446+ !new_crtc_state -> mode_changed )
447+ return ;
448+
437449 ret = vmw_stdu_destroy_st (dev_priv , stdu );
438450 if (ret )
439451 DRM_ERROR ("Failed to destroy Screen Target\n" );
@@ -829,7 +841,41 @@ static void vmw_stdu_connector_destroy(struct drm_connector *connector)
829841 vmw_stdu_destroy (vmw_connector_to_stdu (connector ));
830842}
831843
844+ static enum drm_mode_status
845+ vmw_stdu_connector_mode_valid (struct drm_connector * connector ,
846+ struct drm_display_mode * mode )
847+ {
848+ enum drm_mode_status ret ;
849+ struct drm_device * dev = connector -> dev ;
850+ struct vmw_private * dev_priv = vmw_priv (dev );
851+ u64 assumed_cpp = dev_priv -> assume_16bpp ? 2 : 4 ;
852+ /* Align width and height to account for GPU tile over-alignment */
853+ u64 required_mem = ALIGN (mode -> hdisplay , GPU_TILE_SIZE ) *
854+ ALIGN (mode -> vdisplay , GPU_TILE_SIZE ) *
855+ assumed_cpp ;
856+ required_mem = ALIGN (required_mem , PAGE_SIZE );
857+
858+ ret = drm_mode_validate_size (mode , dev_priv -> stdu_max_width ,
859+ dev_priv -> stdu_max_height );
860+ if (ret != MODE_OK )
861+ return ret ;
862+
863+ ret = drm_mode_validate_size (mode , dev_priv -> texture_max_width ,
864+ dev_priv -> texture_max_height );
865+ if (ret != MODE_OK )
866+ return ret ;
832867
868+ if (required_mem > dev_priv -> max_primary_mem )
869+ return MODE_MEM ;
870+
871+ if (required_mem > dev_priv -> max_mob_pages * PAGE_SIZE )
872+ return MODE_MEM ;
873+
874+ if (required_mem > dev_priv -> max_mob_size )
875+ return MODE_MEM ;
876+
877+ return MODE_OK ;
878+ }
833879
834880static const struct drm_connector_funcs vmw_stdu_connector_funcs = {
835881 .dpms = vmw_du_connector_dpms ,
@@ -845,7 +891,7 @@ static const struct drm_connector_funcs vmw_stdu_connector_funcs = {
845891static const struct
846892drm_connector_helper_funcs vmw_stdu_connector_helper_funcs = {
847893 .get_modes = vmw_connector_get_modes ,
848- .mode_valid = vmw_connector_mode_valid
894+ .mode_valid = vmw_stdu_connector_mode_valid
849895};
850896
851897
0 commit comments