ardera / flutter-pi

A light-weight Flutter Engine Embedder for Linux Embedded that runs without X11 or Wayland.
MIT License
1.63k stars 162 forks source link

Smooth scrolling question #441

Closed TeunVR closed 1 month ago

TeunVR commented 2 months ago

Not a bug, but i am having a hard time getting my PageView to scroll smoothly. I am testing on an Odroid M1S board with two different displays. One display is the stock Odroid Vu5S, a 480x854 panel running at 59.987086Hz. The other display is a custom round 480x480 display that i am trying to get to work. Both are MIPI-DSI panels.

I have adjusted the timing (pclk, horizontal/vertical porches and sync width) of our panel so that it runs at 60.100422Hz.

The Vu5S panel is scrolling much smoother than our panel. I have create a basic app with a PageView that scrolls between two pages with 24px margin in between. In total it has to scroll 504px in 600ms (animation duration). This should result in around 36frames of around 14px i think? 600/1000 * 60Hz = 36frames. 504/36 = 14px.

On the Vu5S this seems to be the case. It scrolls really smooth. On our custom panel it looks like the steps are twice the size, resulting in a much less smooth scrolling experience. See attached slow motion videos.

Do you have any idea what can cause this? Where i should look to fix this? Unfortunately i cannot increase the PCLK of my display since that results in artifacts. Both panels are configured to the same refresh rate. One difference i can see is that the line duration for one line is 1.8 times as long for our panel vs the Vu5S. The framerate is the same though because its only 480 vs 854 lines. So longer per line but less lines.

Note: i increased the horizontal sync width to 182 to get to 60Hz refresh rate. That results in a htotal of 722 (vs htotal of 494 on the Vu5S). I can decrease the horizontal sync width but then the refresh rate goes to 76Hz and the profile overlay in Flutter shows a sawtooth graph. The scrolling is still not smooth in that case.

Custom panel: [ 4596.253928] rockchip-drm display-subsystem: [drm:drm_calc_timestamping_constants] crtc 93: hwmode: htotal 722, vtotal 507, vdisplay 480 [ 4596.253936] rockchip-drm display-subsystem: [drm:drm_calc_timestamping_constants] crtc 93: clock 22000 kHz framedur 16638818 linedur 32818

Vu5S: [12727.086668] rockchip-drm display-subsystem: [drm:drm_calc_timestamping_constants] crtc 93: hwmode: htotal 494, vtotal 928, vdisplay 854 [12727.086680] rockchip-drm display-subsystem: [drm:drm_calc_timestamping_constants] crtc 93: clock 27500 kHz framedur 16670254 linedur 17963

https://github.com/user-attachments/assets/701f4dbb-b448-4ccc-97c0-f842d070808a

https://github.com/user-attachments/assets/302a8e81-9dda-4e8f-a3c7-e96ec90c9dd0

TeunVR commented 2 months ago

Could this be a double buffering issue? That double buffering is not working for my round display and it is only drawing half of the frames?

ardera commented 2 months ago

Interesting issue, it does seem like it skips every other frame, though not sure how that'd work.

I have adjusted the timing (pclk, horizontal/vertical porches and sync width) of our panel so that it runs at 60.100422Hz.

Do panels like this not normally have one specific timing they're supposed to work with? At least that's my experience, it's new to me that you have to fiddle with timings etc to get it to work. What's the normal timings (if it has that)?

Can you do two things for me?

TeunVR commented 2 months ago

Yes the display has specific timing values, but i can tweak a bit with the horizontal porches and hsync-width. (Vertical is more strict, no room to tweak there without black bars on top etc). Also the pixel clock can be tweaked. The default values are a pixel clock of 22000-23000, where 22000 results in around 75fps. This produces a sawtooth graph in the flutter performance overlay. If i reduce the clock to 17350 i get around 60fps and a horizontal graph in the performance overlay. I cannot go higher than 23000 for the pixel-clock without an issue with a white line in the middle of a black to white gradient. If i go to 30000, i get around 110fps and the motion is a bit smoother, but this is no solution of course because of the artifacts.

I emailed Sitronix, the manufacturer of the ST7701S display controller and their response was: This is not an FPS issue. It's because your data format or data refresh speed is slow.

Unfortunately not a really clear solution yet.

I made a 75fps and a 60fps slow motion video.

https://github.com/user-attachments/assets/44f89039-da70-41b5-905f-17098df6ba0e

https://github.com/user-attachments/assets/360fd1eb-ff2d-4b37-8bed-468d5995851a

The dmesg-output for 60fps: scroll60fps.log

The devtools timeline (flutter-pi is not running in DEBUG mode i think, i noticed there are TRACE_* macros, are they for logging?): dart_devtools_2024-09-02_14_12_14.484.json

I will also try to decode the other display's MIPI DSI settings, see what they are doing differently. But that display seems to be using another controller, not a ST7701S.

ardera commented 2 months ago

I emailed Sitronix, the manufacturer of the ST7701S display controller and their response was: This is not an FPS issue. It's because your data format or data refresh speed is slow.

I mean it seems like it is not a data issue, but also a hardware issue like that would indeed be pretty rare, so yeah idk

The devtools timeline (flutter-pi is not running in DEBUG mode i think, i noticed there are TRACE_* macros, are they for logging?): dart_devtools_2024-09-02_14_12_14.484.json

Yes, the TRACE_* macros add events to the dart/flutter timeline if flutter-pi was compiled with CMAKE_BUILD_TYPE=Debug. flutterpi_tool should automatically use a debug flutter-pi if you're running in debug mode, and I can see the flutter-pi events in the timeline (e.g. kms_req_commit_nonblocking) so seems like that works.

The timeline and dmesg output look fine, both are running at 60FPS and the framebuffers are switched as expected (See the Set [FB:168] for ... messages, with the fb id alternating between 168 and 170.)

Does kmscube run smooth on that display (with and without --atomic)? If --atomic doesn't work, use this one with --atomic: https://github.com/ardera/kmscube_using_pageflips. kmscube also shows an FPS count every few seconds, does that match up with the screen refreshrate?

Btw I used

awk '/DRM_IOCTL_MODE_ATOMIC/ {print $2}' scroll60fps.log | \
    LC_NUMERIC=C awk -F'[][]' '{gsub(",", ".", $1); print $1}' | \
    LC_NUMERIC=C awk 'NR > 1 {fps=1/($1-prev); printf "FPS: %.2f at time %.6f\n", fps, $1} {prev=$1}'

to get the FPS for each frame, if you wanna check yourself

TeunVR commented 2 months ago

Yes kmscube is running pretty smooth actually. Looks the same on both displays. kmscube --atomic is not working:

Using display 0x55b74ca960 with EGL version 1.4
===================================
EGL information:
  version: "1.4 Bifrost-"r25p0-01eac0""
  vendor: "ARM"
  client extensions: "EGL_EXT_client_extensions EGL_EXT_platform_base EGL_KHR_client_get_all_proc_addresses EGL_KHR_platform_gbm EGL_KHR_platform_wayland EGL_EXT_platform_wayland"
  display extensions: "EGL_WL_bind_wayland_display EGL_KHR_partial_update EGL_KHR_config_attribs EGL_KHR_image EGL_KHR_image_base EGL_KHR_fence_sync EGL_KHR_wait_sync EGL_KHR_gl_colorspace EGL_KHR_get_all_proc_addresses EGL_IMG_context_priority EGL_KHR_no_config_context EGL_EXT_image_dma_buf_import EGL_EXT_pixel_format_float EGL_ARM_pixmap_multisample_discard EGL_ARM_implicit_external_sync EGL_KHR_gl_texture_2D_image EGL_KHR_gl_renderbuffer_image EGL_KHR_create_context EGL_KHR_surfaceless_context EGL_KHR_gl_texture_cubemap_image EGL_EXT_image_gl_colorspace EGL_EXT_create_context_robustness"
===================================
OpenGL ES 2.x information:
  version: "OpenGL ES 3.2 v1.r25p0-01eac0.9771aca0686ac609bad539142d5c7fce"
  shading language version: "OpenGL ES GLSL ES 3.20"
  vendor: "ARM"
  renderer: "Mali-G52"
  extensions: "GL_ARM_rgba8 GL_ARM_mali_shader_binary GL_OES_depth24 GL_OES_depth_texture GL_OES_depth_texture_cube_map GL_OES_packed_depth_stencil GL_OES_rgb8_rgba8 GL_EXT_read_format_bgra GL_OES_compressed_paletted_texture GL_OES_compressed_ETC1_RGB8_texture GL_OES_standard_derivatives GL_OES_EGL_image GL_OES_EGL_image_external GL_OES_EGL_image_external_essl3 GL_OES_EGL_sync GL_OES_texture_npot GL_OES_vertex_half_float GL_OES_required_internalformat GL_OES_vertex_array_object GL_OES_mapbuffer GL_EXT_texture_format_BGRA8888 GL_EXT_texture_rg GL_EXT_texture_type_2_10_10_10_REV GL_OES_fbo_render_mipmap GL_OES_element_index_uint GL_EXT_shadow_samplers GL_OES_texture_compression_astc GL_KHR_texture_compression_astc_ldr GL_KHR_texture_compression_astc_hdr GL_KHR_texture_compression_astc_sliced_3d GL_EXT_texture_compression_astc_decode_mode GL_EXT_texture_compression_astc_decode_mode_rgb9e5 GL_KHR_debug GL_EXT_occlusion_query_boolean GL_EXT_disjoint_timer_query GL_EXT_blend_minmax GL_EXT_discard_framebuffer GL_OES_get_program_binary GL_OES_texture_3D GL_EXT_texture_storage GL_EXT_multisampled_render_to_texture GL_EXT_multisampled_render_to_texture2 GL_OES_surfaceless_context GL_OES_texture_stencil8 GL_EXT_shader_pixel_local_storage GL_ARM_shader_framebuffer_fetch GL_ARM_shader_framebuffer_fetch_depth_stencil GL_ARM_mali_program_binary GL_EXT_sRGB GL_EXT_sRGB_write_control GL_EXT_texture_sRGB_decode GL_EXT_texture_sRGB_R8 GL_EXT_texture_sRGB_RG8 GL_KHR_blend_equation_advanced GL_KHR_blend_equation_advanced_coherent GL_OES_texture_storage_multisample_2d_array GL_OES_shader_image_atomic GL_EXT_robustness GL_EXT_draw_buffers_indexed GL_OES_draw_buffers_indexed GL_EXT_texture_border_clamp GL_OES_texture_border_clamp GL_EXT_texture_cube_map_array GL_OES_texture_cube_map_array GL_OES_sample_variables GL_OES_sample_shading GL_OES_shader_multisample_interpolation GL_EXT_shader_io_blocks GL_OES_shader_io_blocks GL_EXT_tessellation_shader GL_OES_tessellation_shader GL_EXT_primitive_bounding_box GL_OES_primitive_bounding_box GL_EXT_geometry_shader GL_OES_geometry_shader GL_ANDROID_extension_pack_es31a GL_EXT_gpu_shader5 GL_OES_gpu_shader5 GL_EXT_texture_buffer GL_OES_texture_buffer GL_EXT_copy_image GL_OES_copy_image GL_EXT_shader_non_constant_global_initializers GL_EXT_color_buffer_half_float GL_EXT_color_buffer_float GL_EXT_YUV_target GL_OVR_multiview GL_OVR_multiview2 GL_OVR_multiview_multisampled_render_to_texture GL_KHR_robustness GL_KHR_robust_buffer_access_behavior GL_EXT_draw_elements_base_vertex GL_OES_draw_elements_base_vertex GL_EXT_buffer_storage GL_EXT_texture_filter_anisotropic GL_ARM_texture_unnormalized_coordinates "
===================================
no eglDupNativeFenceFDANDROID

Using your version of kmscube without atomic shows only the first frame, then it quits:

odroid@odroid-audio:~/kmscube_using_pageflips/build$ ./kmscube
Using display 0x2ebc0200 with EGL version 1.4
===================================
EGL information:
  version: "1.4 Bifrost-"r25p0-01eac0""
  vendor: "ARM"
  client extensions: "EGL_EXT_client_extensions EGL_EXT_platform_base EGL_KHR_client_get_all_proc_addresses EGL_KHR_platform_gbm EGL_KHR_platform_wayland EGL_EXT_platform_wayland"
  display extensions: "EGL_WL_bind_wayland_display EGL_KHR_partial_update EGL_KHR_config_attribs EGL_KHR_image EGL_KHR_image_base EGL_KHR_fence_sync EGL_KHR_wait_sync EGL_KHR_gl_colorspace EGL_KHR_get_all_proc_addresses EGL_IMG_context_priority EGL_KHR_no_config_context EGL_EXT_image_dma_buf_import EGL_EXT_pixel_format_float EGL_ARM_pixmap_multisample_discard EGL_ARM_implicit_external_sync EGL_KHR_gl_texture_2D_image EGL_KHR_gl_renderbuffer_image EGL_KHR_create_context EGL_KHR_surfaceless_context EGL_KHR_gl_texture_cubemap_image EGL_EXT_image_gl_colorspace EGL_EXT_create_context_robustness"
===================================
OpenGL ES 2.x information:
  version: "OpenGL ES 3.2 v1.r25p0-01eac0.9771aca0686ac609bad539142d5c7fce"
  shading language version: "OpenGL ES GLSL ES 3.20"
  vendor: "ARM"
  renderer: "Mali-G52"
  extensions: "GL_ARM_rgba8 GL_ARM_mali_shader_binary GL_OES_depth24 GL_OES_depth_texture GL_OES_depth_texture_cube_map GL_OES_packed_depth_stencil GL_OES_rgb8_rgba8 GL_EXT_read_format_bgra GL_OES_compressed_paletted_texture GL_OES_compressed_ETC1_RGB8_texture GL_OES_standard_derivatives GL_OES_EGL_image GL_OES_EGL_image_external GL_OES_EGL_image_external_essl3 GL_OES_EGL_sync GL_OES_texture_npot GL_OES_vertex_half_float GL_OES_required_internalformat GL_OES_vertex_array_object GL_OES_mapbuffer GL_EXT_texture_format_BGRA8888 GL_EXT_texture_rg GL_EXT_texture_type_2_10_10_10_REV GL_OES_fbo_render_mipmap GL_OES_element_index_uint GL_EXT_shadow_samplers GL_OES_texture_compression_astc GL_KHR_texture_compression_astc_ldr GL_KHR_texture_compression_astc_hdr GL_KHR_texture_compression_astc_sliced_3d GL_EXT_texture_compression_astc_decode_mode GL_EXT_texture_compression_astc_decode_mode_rgb9e5 GL_KHR_debug GL_EXT_occlusion_query_boolean GL_EXT_disjoint_timer_query GL_EXT_blend_minmax GL_EXT_discard_framebuffer GL_OES_get_program_binary GL_OES_texture_3D GL_EXT_texture_storage GL_EXT_multisampled_render_to_texture GL_EXT_multisampled_render_to_texture2 GL_OES_surfaceless_context GL_OES_texture_stencil8 GL_EXT_shader_pixel_local_storage GL_ARM_shader_framebuffer_fetch GL_ARM_shader_framebuffer_fetch_depth_stencil GL_ARM_mali_program_binary GL_EXT_sRGB GL_EXT_sRGB_write_control GL_EXT_texture_sRGB_decode GL_EXT_texture_sRGB_R8 GL_EXT_texture_sRGB_RG8 GL_KHR_blend_equation_advanced GL_KHR_blend_equation_advanced_coherent GL_OES_texture_storage_multisample_2d_array GL_OES_shader_image_atomic GL_EXT_robustness GL_EXT_draw_buffers_indexed GL_OES_draw_buffers_indexed GL_EXT_texture_border_clamp GL_OES_texture_border_clamp GL_EXT_texture_cube_map_array GL_OES_texture_cube_map_array GL_OES_sample_variables GL_OES_sample_shading GL_OES_shader_multisample_interpolation GL_EXT_shader_io_blocks GL_OES_shader_io_blocks GL_EXT_tessellation_shader GL_OES_tessellation_shader GL_EXT_primitive_bounding_box GL_OES_primitive_bounding_box GL_EXT_geometry_shader GL_OES_geometry_shader GL_ANDROID_extension_pack_es31a GL_EXT_gpu_shader5 GL_OES_gpu_shader5 GL_EXT_texture_buffer GL_OES_texture_buffer GL_EXT_copy_image GL_OES_copy_image GL_EXT_shader_non_constant_global_initializers GL_EXT_color_buffer_half_float GL_EXT_color_buffer_float GL_EXT_YUV_target GL_OVR_multiview GL_OVR_multiview2 GL_OVR_multiview_multisampled_render_to_texture GL_KHR_robustness GL_KHR_robust_buffer_access_behavior GL_EXT_draw_elements_base_vertex GL_OES_draw_elements_base_vertex GL_EXT_buffer_storage GL_EXT_texture_filter_anisotropic GL_ARM_texture_unnormalized_coordinates "
===================================
failed to queue page flip: Device or resource busy

With atomic it does not show anything but it keeps running:

odroid@odroid-audio:~/kmscube_using_pageflips/build$ ./kmscube --atomic
Using display 0x315a8200 with EGL version 1.4
===================================
EGL information:
  version: "1.4 Bifrost-"r25p0-01eac0""
  vendor: "ARM"
  client extensions: "EGL_EXT_client_extensions EGL_EXT_platform_base EGL_KHR_client_get_all_proc_addresses EGL_KHR_platform_gbm EGL_KHR_platform_wayland EGL_EXT_platform_wayland"
  display extensions: "EGL_WL_bind_wayland_display EGL_KHR_partial_update EGL_KHR_config_attribs EGL_KHR_image EGL_KHR_image_base EGL_KHR_fence_sync EGL_KHR_wait_sync EGL_KHR_gl_colorspace EGL_KHR_get_all_proc_addresses EGL_IMG_context_priority EGL_KHR_no_config_context EGL_EXT_image_dma_buf_import EGL_EXT_pixel_format_float EGL_ARM_pixmap_multisample_discard EGL_ARM_implicit_external_sync EGL_KHR_gl_texture_2D_image EGL_KHR_gl_renderbuffer_image EGL_KHR_create_context EGL_KHR_surfaceless_context EGL_KHR_gl_texture_cubemap_image EGL_EXT_image_gl_colorspace EGL_EXT_create_context_robustness"
===================================
OpenGL ES 2.x information:
  version: "OpenGL ES 3.2 v1.r25p0-01eac0.9771aca0686ac609bad539142d5c7fce"
  shading language version: "OpenGL ES GLSL ES 3.20"
  vendor: "ARM"
  renderer: "Mali-G52"
  extensions: "GL_ARM_rgba8 GL_ARM_mali_shader_binary GL_OES_depth24 GL_OES_depth_texture GL_OES_depth_texture_cube_map GL_OES_packed_depth_stencil GL_OES_rgb8_rgba8 GL_EXT_read_format_bgra GL_OES_compressed_paletted_texture GL_OES_compressed_ETC1_RGB8_texture GL_OES_standard_derivatives GL_OES_EGL_image GL_OES_EGL_image_external GL_OES_EGL_image_external_essl3 GL_OES_EGL_sync GL_OES_texture_npot GL_OES_vertex_half_float GL_OES_required_internalformat GL_OES_vertex_array_object GL_OES_mapbuffer GL_EXT_texture_format_BGRA8888 GL_EXT_texture_rg GL_EXT_texture_type_2_10_10_10_REV GL_OES_fbo_render_mipmap GL_OES_element_index_uint GL_EXT_shadow_samplers GL_OES_texture_compression_astc GL_KHR_texture_compression_astc_ldr GL_KHR_texture_compression_astc_hdr GL_KHR_texture_compression_astc_sliced_3d GL_EXT_texture_compression_astc_decode_mode GL_EXT_texture_compression_astc_decode_mode_rgb9e5 GL_KHR_debug GL_EXT_occlusion_query_boolean GL_EXT_disjoint_timer_query GL_EXT_blend_minmax GL_EXT_discard_framebuffer GL_OES_get_program_binary GL_OES_texture_3D GL_EXT_texture_storage GL_EXT_multisampled_render_to_texture GL_EXT_multisampled_render_to_texture2 GL_OES_surfaceless_context GL_OES_texture_stencil8 GL_EXT_shader_pixel_local_storage GL_ARM_shader_framebuffer_fetch GL_ARM_shader_framebuffer_fetch_depth_stencil GL_ARM_mali_program_binary GL_EXT_sRGB GL_EXT_sRGB_write_control GL_EXT_texture_sRGB_decode GL_EXT_texture_sRGB_R8 GL_EXT_texture_sRGB_RG8 GL_KHR_blend_equation_advanced GL_KHR_blend_equation_advanced_coherent GL_OES_texture_storage_multisample_2d_array GL_OES_shader_image_atomic GL_EXT_robustness GL_EXT_draw_buffers_indexed GL_OES_draw_buffers_indexed GL_EXT_texture_border_clamp GL_OES_texture_border_clamp GL_EXT_texture_cube_map_array GL_OES_texture_cube_map_array GL_OES_sample_variables GL_OES_sample_shading GL_OES_shader_multisample_interpolation GL_EXT_shader_io_blocks GL_OES_shader_io_blocks GL_EXT_tessellation_shader GL_OES_tessellation_shader GL_EXT_primitive_bounding_box GL_OES_primitive_bounding_box GL_EXT_geometry_shader GL_OES_geometry_shader GL_ANDROID_extension_pack_es31a GL_EXT_gpu_shader5 GL_OES_gpu_shader5 GL_EXT_texture_buffer GL_OES_texture_buffer GL_EXT_copy_image GL_OES_copy_image GL_EXT_shader_non_constant_global_initializers GL_EXT_color_buffer_half_float GL_EXT_color_buffer_float GL_EXT_YUV_target GL_OVR_multiview GL_OVR_multiview2 GL_OVR_multiview_multisampled_render_to_texture GL_KHR_robustness GL_KHR_robust_buffer_access_behavior GL_EXT_draw_elements_base_vertex GL_OES_draw_elements_base_vertex GL_EXT_buffer_storage GL_EXT_texture_filter_anisotropic GL_ARM_texture_unnormalized_coordinates "
===================================
atomic_request 0x3183a120: conn  164: ["CRTC_ID"] = 93
atomic_request 0x3183a120: crtc   93: ["MODE_ID"] = 168
atomic_request 0x3183a120: crtc   93: ["ACTIVE"] = 1
atomic_request 0x3183a120: plane  57: ["FB_ID"] = 167
atomic_request 0x3183a120: plane  57: ["CRTC_ID"] = 93
atomic_request 0x3183a120: plane  57: ["SRC_X"] = 0
atomic_request 0x3183a120: plane  57: ["SRC_Y"] = 0
atomic_request 0x3183a120: plane  57: ["SRC_W"] = 31457280
atomic_request 0x3183a120: plane  57: ["SRC_H"] = 31457280
atomic_request 0x3183a120: plane  57: ["CRTC_X"] = 0
atomic_request 0x3183a120: plane  57: ["CRTC_Y"] = 0
atomic_request 0x3183a120: plane  57: ["CRTC_W"] = 480
atomic_request 0x3183a120: plane  57: ["CRTC_H"] = 480
committing 0x3183a120
page flip event ocurred:   320.817359
atomic_request 0x315140b0: plane  57: ["FB_ID"] = 166
atomic_request 0x315140b0: plane  57: ["CRTC_ID"] = 93
atomic_request 0x315140b0: plane  57: ["SRC_X"] = 0
atomic_request 0x315140b0: plane  57: ["SRC_Y"] = 0
atomic_request 0x315140b0: plane  57: ["SRC_W"] = 31457280
atomic_request 0x315140b0: plane  57: ["SRC_H"] = 31457280
atomic_request 0x315140b0: plane  57: ["CRTC_X"] = 0
atomic_request 0x315140b0: plane  57: ["CRTC_Y"] = 0
atomic_request 0x315140b0: plane  57: ["CRTC_W"] = 480
atomic_request 0x315140b0: plane  57: ["CRTC_H"] = 480
committing 0x315140b0
page flip event ocurred:   320.834020
atomic_request 0x315140b0: plane  57: ["FB_ID"] = 167
atomic_request 0x315140b0: plane  57: ["CRTC_ID"] = 93
atomic_request 0x315140b0: plane  57: ["SRC_X"] = 0
atomic_request 0x315140b0: plane  57: ["SRC_Y"] = 0
atomic_request 0x315140b0: plane  57: ["SRC_W"] = 31457280
atomic_request 0x315140b0: plane  57: ["SRC_H"] = 31457280
atomic_request 0x315140b0: plane  57: ["CRTC_X"] = 0
atomic_request 0x315140b0: plane  57: ["CRTC_Y"] = 0
atomic_request 0x315140b0: plane  57: ["CRTC_W"] = 480
atomic_request 0x315140b0: plane  57: ["CRTC_H"] = 480
committing 0x315140b0
...
ardera commented 2 months ago

I think kmscube_using_pageflips was running into the driver issue described in https://github.com/ardera/flutter-pi/issues/412

I updated it to work around it. Can you try again (with --atomic)? In case it doesn't work, please send the complete output.

TeunVR commented 1 month ago

The new version with --atomic is working. (without --atomic still only first frame).

odroid@odroid-audio:~/kmscube_using_pageflips/build$ ./kmscube --atomic
Reusing currently used primary plane.
Using display 0x2e283200 with EGL version 1.4
===================================
EGL information:
  version: "1.4 Bifrost-"r25p0-01eac0""
  vendor: "ARM"
  client extensions: "EGL_EXT_client_extensions EGL_EXT_platform_base EGL_KHR_client_get_all_proc_addresses EGL_KHR_platform_gbm EGL_KHR_platform_wayland EGL_EXT_platform_wayland"
  display extensions: "EGL_WL_bind_wayland_display EGL_KHR_partial_update EGL_KHR_config_attribs EGL_KHR_image EGL_KHR_image_base EGL_KHR_fence_sync EGL_KHR_wait_sync EGL_KHR_gl_colorspace EGL_KHR_get_all_proc_addresses EGL_IMG_context_priority EGL_KHR_no_config_context EGL_EXT_image_dma_buf_import EGL_EXT_pixel_format_float EGL_ARM_pixmap_multisample_discard EGL_ARM_implicit_external_sync EGL_KHR_gl_texture_2D_image EGL_KHR_gl_renderbuffer_image EGL_KHR_create_context EGL_KHR_surfaceless_context EGL_KHR_gl_texture_cubemap_image EGL_EXT_image_gl_colorspace EGL_EXT_create_context_robustness"
===================================
OpenGL ES 2.x information:
  version: "OpenGL ES 3.2 v1.r25p0-01eac0.9771aca0686ac609bad539142d5c7fce"
  shading language version: "OpenGL ES GLSL ES 3.20"
  vendor: "ARM"
  renderer: "Mali-G52"
  extensions: "GL_ARM_rgba8 GL_ARM_mali_shader_binary GL_OES_depth24 GL_OES_depth_texture GL_OES_depth_texture_cube_map GL_OES_packed_depth_stencil GL_OES_rgb8_rgba8 GL_EXT_read_format_bgra GL_OES_compressed_paletted_texture GL_OES_compressed_ETC1_RGB8_texture GL_OES_standard_derivatives GL_OES_EGL_image GL_OES_EGL_image_external GL_OES_EGL_image_external_essl3 GL_OES_EGL_sync GL_OES_texture_npot GL_OES_vertex_half_float GL_OES_required_internalformat GL_OES_vertex_array_object GL_OES_mapbuffer GL_EXT_texture_format_BGRA8888 GL_EXT_texture_rg GL_EXT_texture_type_2_10_10_10_REV GL_OES_fbo_render_mipmap GL_OES_element_index_uint GL_EXT_shadow_samplers GL_OES_texture_compression_astc GL_KHR_texture_compression_astc_ldr GL_KHR_texture_compression_astc_hdr GL_KHR_texture_compression_astc_sliced_3d GL_EXT_texture_compression_astc_decode_mode GL_EXT_texture_compression_astc_decode_mode_rgb9e5 GL_KHR_debug GL_EXT_occlusion_query_boolean GL_EXT_disjoint_timer_query GL_EXT_blend_minmax GL_EXT_discard_framebuffer GL_OES_get_program_binary GL_OES_texture_3D GL_EXT_texture_storage GL_EXT_multisampled_render_to_texture GL_EXT_multisampled_render_to_texture2 GL_OES_surfaceless_context GL_OES_texture_stencil8 GL_EXT_shader_pixel_local_storage GL_ARM_shader_framebuffer_fetch GL_ARM_shader_framebuffer_fetch_depth_stencil GL_ARM_mali_program_binary GL_EXT_sRGB GL_EXT_sRGB_write_control GL_EXT_texture_sRGB_decode GL_EXT_texture_sRGB_R8 GL_EXT_texture_sRGB_RG8 GL_KHR_blend_equation_advanced GL_KHR_blend_equation_advanced_coherent GL_OES_texture_storage_multisample_2d_array GL_OES_shader_image_atomic GL_EXT_robustness GL_EXT_draw_buffers_indexed GL_OES_draw_buffers_indexed GL_EXT_texture_border_clamp GL_OES_texture_border_clamp GL_EXT_texture_cube_map_array GL_OES_texture_cube_map_array GL_OES_sample_variables GL_OES_sample_shading GL_OES_shader_multisample_interpolation GL_EXT_shader_io_blocks GL_OES_shader_io_blocks GL_EXT_tessellation_shader GL_OES_tessellation_shader GL_EXT_primitive_bounding_box GL_OES_primitive_bounding_box GL_EXT_geometry_shader GL_OES_geometry_shader GL_ANDROID_extension_pack_es31a GL_EXT_gpu_shader5 GL_OES_gpu_shader5 GL_EXT_texture_buffer GL_OES_texture_buffer GL_EXT_copy_image GL_OES_copy_image GL_EXT_shader_non_constant_global_initializers GL_EXT_color_buffer_half_float GL_EXT_color_buffer_float GL_EXT_YUV_target GL_OVR_multiview GL_OVR_multiview2 GL_OVR_multiview_multisampled_render_to_texture GL_KHR_robustness GL_KHR_robust_buffer_access_behavior GL_EXT_draw_elements_base_vertex GL_OES_draw_elements_base_vertex GL_EXT_buffer_storage GL_EXT_texture_filter_anisotropic GL_ARM_texture_unnormalized_coordinates "
===================================
Rendered 122 frames in 2.016470 sec (60.501780 fps)
Rendered 243 frames in 4.032331 sec (60.262910 fps)
Rendered 364 frames in 6.048126 sec (60.183933 fps)
Rendered 485 frames in 8.064013 sec (60.143750 fps)
Rendered 605 frames in 10.079844 sec (60.020773 fps)

dmesg:

kmscube_pageflip.log

60fps video:

https://github.com/user-attachments/assets/e58d726e-e7a6-4558-9a7a-539d7777b108

slowmotion:

https://github.com/user-attachments/assets/a51649e6-eec3-48a2-8f8c-037b72975567

ardera commented 1 month ago

If kmscube is working fine, that means either flutter-pi is doing something that confuses the rockchip driver, or something with buffer management is wrong. Both are pretty puzzling.

how exactly are you forcing the display timings? Can you try applying the exact same timings you're using for the non-working display to another display? (I think that doesn't hurt the display, but I'm also not 100% sure) Maybe also an HDMI display.

EDIT: Without --atomic it's not supposed to work, it tries to do a non-vsynced pageflip in that case and a lot of driver don't support that.

I also a created small test app specifically for detecting frame skips here: https://github.com/ardera/flutter_frame_skip_test

ardera commented 1 month ago

@TeunVR I wrote an email to the guy from the rockchip weston fork:

Am 04.09.2024 um 17:21 schrieb Jeffy Chen jeffy.chen@rock-chips.com:

hi, if the atomic commit ioctls are in 60fps, and the user is seeing 30fps, that could be low level display driver or hardware issue.

maybe andy has some ideas.

Am 05.09.2024 um 02:32 schrieb Andy Yan andy.yan@rock-chips.com:

My suggestion is : (1) echo 0x20 > /sys/module/drm/parameters/debug, then get the kernel log by dmesg, you will see drm log like this: if the display is work at 60 HZ, you will see vblank count update every 16 ms (2) if (1) is confirmed work as we expected, trace drm_ioctl function at drivers/gpu/drm/drm_ioctl.c, figure out witch part cost time more than 16ms

[0]

[ 1065.689247] rockchip-drm display-subsystem: [drm:drm_update_vblank_count] updating vblank count on crtc 0: current=18348, diff=1, hw=0 hw_last=0 [ 1065.705913] rockchip-drm display-subsystem: [drm:drm_update_vblank_count] updating vblank count on crtc 0: current=18349, diff=1, hw=0 hw_last=0 [ 1065.722579] rockchip-drm display-subsystem: [drm:drm_update_vblank_count] updating vblank count on crtc 0: current=18350, diff=1, hw=0 hw_last=0 [ 1065.739246] rockchip-drm display-subsystem: [drm:drm_update_vblank_count] updating vblank count on crtc 0: current=18351, diff=1, hw=0 hw_last=0 ...

I don't know how straightforward it is to setup this tracing, maybe it's easier to just change stuff in flutter-pi until it works.

TeunVR commented 1 month ago

Thanks for your investigation, I will try to make some more drm logging.

I do have a similar panel here with a RGB interface and a HDMI to RGB converter board (the original panels had an RGB interface, we asked the manufacturer for a MIPI-DSI version, since the RK3566 does not have RGB).

This setup is working ok. It also uses an ST7701S, but in RGB mode. I did try to use the display timings of this board, but they are unfortunately not correct for our MIPI-DSI panels, maybe because of the HDMI-to-RGB conversion.

So for now the only smooth setups i have here is a Vu5S panel via MIPI-DSI (so i know MIPI-DSI can work correctly) and a round panel via HDMI-RGB conversion (so i know the lcd panel can work correctly). Now to find where it goes wrong :)

TeunVR commented 1 month ago

The frameskip test app shows the problem clearly. MIPI-DSI panel:

https://github.com/user-attachments/assets/1b33f74f-a9bc-4adf-a72b-236e5ed305a0

via HDMI-to-RGB converter:

https://github.com/user-attachments/assets/3840d610-de71-4e30-b786-8849c4c0f1b9

MIPI-DSI Vu5S panel is ok:

https://github.com/user-attachments/assets/ce1eb5a1-f327-4d06-881f-c362e00eaf6c

TeunVR commented 1 month ago

I think i found the problem. I noticed the Vu5S (which is a completely different panel) is also using a Sitronix controller. I have copied most of their settings from the dts and when using their vertical front porch setting the issue was solved. Our manufacturer gave me a VFP of 6, but using a VFP of 12 (like the Vu5S) makes everything smooth again.

Thank you for your support and very useful test-app 👍

https://github.com/user-attachments/assets/1e954635-74c3-4bc1-be98-4b19799f96ca