It all started with this bug. The description sounded humble and harmless: the browser ignored some command line flag on Wayland. A screenshot was attached where it was clearly seen that Chromium (version 72 at that time, 2019 spring) did not respect the screen density and looked blurry on a HiDPI screen.
HiDPI literally means small pixels. It is hard to tell now what was the first HiDPI screen, but I assume that their wide recognition came around 2010 with Apple’s Retina displays. Ultra HD had been standardised in 2012, defining the minimum resolution and aspect ratio for what today is known informally as 4K—and 4K screens for laptops have pixels that are small enough to call it HiDPI. This Chromium issue, dated 2012, says that the Linux port lacks support for HiDPI while the Mac version has it already. On the other hand, HiDPI on Windows was tricky even in 2014.
‘That should be easy. Apparently it’s upscaled from low resolution. Wayland allows setting scale for the back buffers, likely you’ll have to add a single call somewhere in the window initialisation’, a colleague said.
Like many stories that begin this way, this turned out to be wrong. It was not so easy. Setting the buffer scale did the right thing indeed, but it was absolutely not enough. It turned out that support for HiDPI screens was entirely missing in our implementation of the Wayland client. On my way to the solution, I have found that scaling support in Wayland is non-trivial and sometimes confusing. Since I finished this work, I have been asked a few times about what happens there, so I thought that writing it all down in a post would be useful.
Background
Modern desktop environments usually allow configuring the scale of the display at global system level. This allows all standard controls and window decorations to be sized proportionally. For applications that use those standard controls, this is a happy end: everything will be scaled automatically. Those which prefer doing everything themselves have to get the current scale from the environment and adjust rendering. Chromium does exactly that: inside it has a so-called device scale factor. This factor is applied equally to all sizes, locations, and when rendering images and fonts. No code has to bother ever. It works within this scaled coordinate system, known as device independent pixels, or DIP. The device scale factor can take fractional values like 1.5, but, because it is applied at the stage of rendering, the result looks nice. The system scale is used as default device scale factor, and the user can override it using the command line flag named --force-device-scale-factor
. However, this is the very flag which did not work in the bug mentioned in the beginning of this story.
Note that for X11 the ‘natural’ scale is still the physical pixels. Despite having the system-wide scale, the system talks to the application in pixels, not in DIP. It is the application that is responsible to handle the scale properly. If it does not, it will look perfectly sharp, but its details will be perhaps too small for the naked eye.
However, Wayland does it a bit differently. The system scale there is respected by the compositor when pasting buffers rendered by clients. So, if some application has no idea about the system scale and renders itself normally, the compositor will upscale it. This is what originally happened to Chromium: it simply drew itself at 100%, and that image was then stretched by the system compositor. Remember that the Wayland way is giving a buffer to each application and then compositing the screen from those buffers, so this approach of upscaling buffers rendered by applications is natural. The picture below shows what that looks like. The screenshot is taken on a HiDPI display, so in order to see the difference better, you may want to see the full version (click the picture to open).
How do Wayland clients support HiDPI then?
Level 1. Basic support
Each physical output device is represented at the Wayland level by an object named output. This object has a special integer property named buffer scale that tells literally how many physical pixels are used to represent the single logical pixel. The application’s back buffer has that property too. If scales do not match, Wayland will simply scale the raster image, thus emulating the ‘normal DPI’ device for the application that is not aware of any buffer scales.
The first thing the window is supposed to do is to check the buffer scale of the output that it currently resides at, and to set the same value to its back buffer scale. This will basically make the application using all available physical pixels: as scales of the buffer and the output are the same, Wayland will not re-scale the image.
The next thing is fixing the rendering so it would scale things to the right size. Using the output buffer scale as default is a good choice: the result will be ‘normal size’. For Chromium, this means simply setting the device scale factor to the output buffer scale.
The final bit is slightly trickier. Wayland sends UI events in DIP, but expects the client to send surface bounds in physical pixels. That means that if we implement something like interactive resize of the window, we will also have to do some math to convert the units properly.
This is enough for the basic support. The application will work well on a modern laptop with 4K display. But what if more than a single display is connected, and they have different pixel density?
Level 2. Multiple displays
If there are several output devices present in the system, each one may have its own scale. This makes things more complicated, so a few improvements are needed.
First, the window wants to know that it has been moved to another device. When that happens, the window will ask for the new buffer scale and update itself.
Second, there may be implementation-specific issues. For example, some Wayland servers initially put the new sub-surface (which is used for menus) onto the default output, even if its parent surface has been moved to another output. This may cause weird changes of their scale during their initialisation. In Chromium, we just made it so the sub-surface always takes its scale from the parent.
Level 3? Fractional scaling?
Not really. Fractional scaling is basically ‘non-even’ scales like 125%. The entire feature had been somewhat controversial when it had been announced, because of how rendering in Wayland is performed. Here, non-even scale inevitably uses raster operations which make the image blurry. However, all that is transparent to the applications. Nothing new has been introduced at the level of Wayland protocols.
Conclusion
Although this task was not as simple as we thought, in the end it turned out to be not too hard. Check the output scale, set the back buffer scale, scale the rendering, translate pixels to DIP and vice versa in certain points. Pretty straightforward, and if you are trying to do something related, I hope this post helps you.
The issue is that there are many implementations of Wayland servers out there, not all of them are consistent, and some of them have bugs. It is worth testing the solution on a few distinct Linux distributions and looking for discrepancies in behaviour.
Anyway, Chromium with native Wayland support has recently reached beta—and it supports HiDPI! There may be bugs too, but the basic support should work well. Try it, and let us know if something is not right.
Note: the Wayland support is so far experimental. To try it, you would need to launch chrome via the command line with two flags:
--enable-features=UseOzonePlatform
--ozone-platform=wayland
That was a great reading, thanks. You haven’t dwelt upon the subject I’m most interested in understanding: fractional scaling. I reckon this is because there’s not much Chromium is doing there, given that the protocol only specifies integer scales. Does this mean that, even though Chromium is perfectly capable to produce output at any scale, it will have to produce output at integer scales that will be later downscaled by the compositor using some sort of raster interpolation? That is, does it mean we will end up with degraded output quality and increased output raster size (and reduced battery life) just because the compositor doesn’t pass a fractional scale because it was overlooked by the spec? This is not only for Chromium, of course, other toolkits and engines can manage fractional scaling too, like Qt. It sounds appalling, but maybe I’m wrong regarding the way this is done or its implications. Could you share your thoughts on that? Thank you again.
I never tried fractional scaling myself, but as I see it, and as colleagues who touched fractional scaling explained to me, your vision is correct. The final image is done by the system compositor as a raster operation above what application has rendered. Logically, the result cannot be perfect, and it aligns well with practice: some people shared that fractional scaling is tolerable but not more.
The good news is that Chromium will see the real pixel density of the output, and render sharp image, so the system will downscale from a source of good quality.
Another good news is that as Chromium is capable of rendering at any scale, perhaps it would be worth setting the even scale at the system level and then run Chromium with the fractional one using the –force-device-scale-factor command line flag (WordPress eats double hyphen that the flag should start with). Web browsers cover so much of our daily tasks so perhaps one could live with some minor applications that look a bit too large.
A really helpful article! I run
chromium --enable-features=UseOzonePlatform --ozone-platform=wayland
and it works perfectly in KDE Wayland with 150% scale. Unluckily, this method doesn’t work with Electron based app, like Visual Studio Code. Do you have suggestion? Thanks!I think it depends on the application. I remember that I once tried running VS Code in a Wayland session (for me it did not work there properly), I tried passing in the Ozone-related command line flags, and it said that these flags are unknown to it but nevertheless it propagates them to Chromium inside; though, that did not help. I assume the result depends on which version of Chromium is bundled.
I would suggest searching in their knowledge base, and maybe asking there.
Thanks for this post Alex, you’ve made my day! It’s really great to find a post from somebody from my own company explaining the solution to a problem I’m having. 🤩🤩🤩
You are welcome! What was the issue, may I ask?
The explanation to the HiDPI support that I explained in this post is simplified, maybe even too much. The real implementation that we finally have got in Chromium is more complicated because of the multi-process nature of the application.
The problem was that Chrome was blurried in a 4K external screen (the laptop screen is FullHD, so no problem there) when launched from a KDE Plasma Wayland session. Modifying the launch shortcut to include `–enable-features=UseOzonePlatform –ozone-platform=wayland` solved the issue.
I see. This post is slightly out of date regarding that. Enabling the UseOzonePlatform feature is no longer necessary since version 95, and since version 97 Chrome has a flag (see chrome://flags) that enables auto detection of Wayland. That is, soon you will be able to roll back your modifications to the shortcut.
Thanks for the explanation, I understood why Chromium became tiny after an update. The only solution I could find was to disable ozone platform, but now I realized I could enable fractional scaling undef Wayland and it worked fine. Before that I had to either disable ozone platform or disable wayland support, which occurs to me might be one and the same thing, one runtime and the other compile time. Now the problem arises with plenty of other applications which seem to not be (properly) wayland aware.
Now the problem is Chromium doesn’t care if I set font scaling in Gnome and again, I either need to disable ozone platform or set 150% zoom in chromium settings which will bring web content to comfortable size, but I have to accept the tiny UI.
Any advice would be appreciated.
Can you please post here your about://gpu from Chromium/Wayland running with the settings you say do not work. Thanks!
Hello and thank you for your replay.
Here are the contents of about://gpu page:
Graphics Feature Status
Canvas: Hardware accelerated
Canvas out-of-process rasterization: Disabled
Compositing: Hardware accelerated
Multiple Raster Threads: Enabled
Out-of-process Rasterization: Disabled
OpenGL: Enabled
Rasterization: Software only. Hardware acceleration disabled
Raw Draw: Disabled
Skia Renderer: Enabled
Video Decode: Software only. Hardware acceleration disabled
Video Encode: Software only. Hardware acceleration disabled
Vulkan: Disabled
WebGL: Hardware accelerated
WebGL2: Hardware accelerated
Driver Bug Workarounds
adjust_src_dst_region_for_blitframebuffer
clear_pixel_unpack_buffer_before_copyteximage
clear_uniforms_before_first_program_use
count_all_in_varyings_packing
decode_encode_srgb_for_generatemipmap
disable_software_to_accelerated_canvas_upgrade
enable_webgl_timer_query_extensions
exit_on_context_lost
force_cube_map_positive_x_allocation
force_int_or_srgb_cube_texture_complete
init_texture_max_anisotropy
regenerate_struct_names
disabled_extension_GL_KHR_blend_equation_advanced
disabled_extension_GL_KHR_blend_equation_advanced_coherent
Problems Detected
Accelerated video encode has been disabled, either via blocklist, about:flags or the command line.
Disabled Features: video_encode
Accelerated video decode has been disabled, either via blocklist, about:flags or the command line.
Disabled Features: video_decode
Clear uniforms before first program use on all platforms: 124764, 349137
Applied Workarounds: clear_uniforms_before_first_program_use
Mesa drivers in Linux handle varyings without static use incorrectly: 333885
Applied Workarounds: count_all_in_varyings_packing
Linux AMD drivers incorrectly return initial value of 1 for TEXTURE_MAX_ANISOTROPY: 348237
Applied Workarounds: init_texture_max_anisotropy
Linux AMD drivers handle struct scopes incorrectly: 403957
Applied Workarounds: regenerate_struct_names
Linux ATI drivers crash on binding incomplete cube map texture to FBO: 518889
Applied Workarounds: force_cube_map_positive_x_allocation
adjust src/dst region if blitting pixels outside framebuffer on Linux AMD: 664740
Applied Workarounds: adjust_src_dst_region_for_blitframebuffer
Disable KHR_blend_equation_advanced until cc shaders are updated: 661715
Applied Workarounds: disable(GL_KHR_blend_equation_advanced), disable(GL_KHR_blend_equation_advanced_coherent)
Decode and Encode before generateMipmap for srgb format textures on Linux AMD: 634519
Applied Workarounds: decode_encode_srgb_for_generatemipmap
Software to Accelerated canvas update breaks Linux AMD: 710029
Applied Workarounds: disable_software_to_accelerated_canvas_upgrade
Force integer or srgb cube map texture complete on Linux AMD: 712117
Applied Workarounds: force_int_or_srgb_cube_texture_complete
Expose WebGL’s disjoint_timer_query extensions on platforms with site isolation: 808744, 870491
Applied Workarounds: enable_webgl_timer_query_extensions
AMD Linux driver crashes when copyTexImage2D is called with PIXEL_UNPACK_BUFFER set to an uninitialized buffer: 859998
Applied Workarounds: clear_pixel_unpack_buffer_before_copyteximage
Some drivers can’t recover after OUT_OF_MEM and context lost: 893177
Applied Workarounds: exit_on_context_lost
DAWN Info
Vulkan backend – AMD RADV RENOIR
[Default Toggle Names]
lazy_clear_resource_on_first_use: https://crbug.com/dawn/145: Clears resource to zero on first usage. This initializes the resource so that no dirty bits from recycled memory is present in the new resource.
use_temporary_buffer_in_texture_to_texture_copy: https://crbug.com/dawn/42: Split texture-to-texture copy into two copies: copy from source texture into a temporary buffer, and copy from the temporary buffer into the destination texture when copying between compressed textures that don’t have block-aligned sizes. This workaround is enabled by default on all Vulkan drivers to solve an issue in the Vulkan SPEC about the texture-to-texture copies with compressed formats. See #1005 (https://github.com/KhronosGroup/Vulkan-Docs/issues/1005) for more details.
vulkan_use_d32s8: https://crbug.com/dawn/286: Vulkan mandates support of either D32_FLOAT_S8 or D24_UNORM_S8. When available the backend will use D32S8 (toggle to on) but setting the toggle to off will make ituse the D24S8 format when possible.
disallow_unsafe_apis: http://crbug.com/1138528: Produces validation errors on API entry points or parameter combinations that aren’t considered secure yet.
[WebGPU Forced Toggles – enabled]
disallow_spirv: https://crbug.com/1214923: Disallow usage of SPIR-V completely so that only WGSL is used for shader modules.This is useful to prevent a Chromium renderer process from successfully sendingSPIR-V code to be compiled in the GPU process.
[Supported Features]
texture-compression-bc
pipeline-statistics-query
timestamp-query
depth-clamping
dawn-internal-usages
Vulkan backend – NVIDIA GeForce RTX 3060 Laptop GPU
[Default Toggle Names]
lazy_clear_resource_on_first_use: https://crbug.com/dawn/145: Clears resource to zero on first usage. This initializes the resource so that no dirty bits from recycled memory is present in the new resource.
use_temporary_buffer_in_texture_to_texture_copy: https://crbug.com/dawn/42: Split texture-to-texture copy into two copies: copy from source texture into a temporary buffer, and copy from the temporary buffer into the destination texture when copying between compressed textures that don’t have block-aligned sizes. This workaround is enabled by default on all Vulkan drivers to solve an issue in the Vulkan SPEC about the texture-to-texture copies with compressed formats. See #1005 (https://github.com/KhronosGroup/Vulkan-Docs/issues/1005) for more details.
vulkan_use_d32s8: https://crbug.com/dawn/286: Vulkan mandates support of either D32_FLOAT_S8 or D24_UNORM_S8. When available the backend will use D32S8 (toggle to on) but setting the toggle to off will make ituse the D24S8 format when possible.
disallow_unsafe_apis: http://crbug.com/1138528: Produces validation errors on API entry points or parameter combinations that aren’t considered secure yet.
[WebGPU Forced Toggles – enabled]
disallow_spirv: https://crbug.com/1214923: Disallow usage of SPIR-V completely so that only WGSL is used for shader modules.This is useful to prevent a Chromium renderer process from successfully sendingSPIR-V code to be compiled in the GPU process.
[Supported Features]
texture-compression-bc
pipeline-statistics-query
timestamp-query
depth-clamping
dawn-internal-usages
Version Information
Data exported 2022-01-24T10:07:40.762Z
Chrome version Chrome/97.0.4692.99
Operating system Linux 5.15.13-default
Software rendering list URL https://chromium.googlesource.com/chromium/src/+/d740da257583289dbebd2eb37e8668928fac5ead/gpu/config/software_rendering_list.json
Driver bug list URL https://chromium.googlesource.com/chromium/src/+/d740da257583289dbebd2eb37e8668928fac5ead/gpu/config/gpu_driver_bug_list.json
ANGLE commit id unknown hash
2D graphics backend Skia/97 b4d28b2f35396ae4dd69338254415066629dfd25
Command Line chromium-browser –extra-plugin-dir=/usr/lib64/nsbrowser/plugins –ozone-platform=wayland –enable-crashpad –flag-switches-begin –flag-switches-end
Driver Information
Initialization time 1360
In-process GPU false
Passthrough Command Decoder false
Sandboxed false
GPU0 VENDOR= 0x1002, DEVICE=0x1638 *ACTIVE*
GPU1 VENDOR= 0x10de, DEVICE=0x2560
Optimus false
AMD switchable false
Driver vendor Mesa
Driver version 21.3.4
GPU CUDA compute capability major version 0
Pixel shader version 3.20
Vertex shader version 3.20
Max. MSAA samples 8
Machine model name
Machine model version
GL_VENDOR AMD
GL_RENDERER AMD RENOIR (DRM 3.42.0, 5.15.13-default, LLVM 13.0.0)
GL_VERSION OpenGL ES 3.2 Mesa 21.3.4
GL_EXTENSIONS GL_EXT_blend_minmax GL_EXT_multi_draw_arrays GL_EXT_texture_filter_anisotropic GL_EXT_texture_compression_s3tc GL_EXT_texture_compression_dxt1 GL_EXT_texture_compression_rgtc GL_EXT_texture_format_BGRA8888 GL_OES_compressed_ETC1_RGB8_texture GL_OES_depth24 GL_OES_element_index_uint GL_OES_fbo_render_mipmap GL_OES_mapbuffer GL_OES_rgb8_rgba8 GL_OES_standard_derivatives GL_OES_stencil8 GL_OES_texture_3D GL_OES_texture_float GL_OES_texture_float_linear GL_OES_texture_half_float GL_OES_texture_half_float_linear GL_OES_texture_npot GL_OES_vertex_half_float GL_EXT_draw_instanced GL_EXT_texture_sRGB_decode GL_OES_EGL_image GL_OES_depth_texture GL_AMD_performance_monitor GL_OES_packed_depth_stencil GL_EXT_texture_type_2_10_10_10_REV GL_NV_conditional_render GL_OES_get_program_binary GL_APPLE_texture_max_level GL_EXT_discard_framebuffer GL_EXT_read_format_bgra GL_EXT_frag_depth GL_NV_fbo_color_attachments GL_OES_EGL_image_external GL_OES_EGL_sync GL_OES_vertex_array_object GL_OES_viewport_array GL_ANGLE_pack_reverse_row_order GL_ANGLE_texture_compression_dxt3 GL_ANGLE_texture_compression_dxt5 GL_EXT_occlusion_query_boolean GL_EXT_robustness GL_EXT_texture_rg GL_EXT_unpack_subimage GL_NV_draw_buffers GL_NV_read_buffer GL_NV_read_depth GL_NV_read_depth_stencil GL_NV_read_stencil GL_EXT_draw_buffers GL_EXT_map_buffer_range GL_KHR_debug GL_KHR_robustness GL_KHR_texture_compression_astc_ldr GL_NV_pixel_buffer_object GL_OES_depth_texture_cube_map GL_OES_required_internalformat GL_OES_surfaceless_context GL_EXT_color_buffer_float GL_EXT_sRGB_write_control GL_EXT_separate_shader_objects GL_EXT_shader_group_vote GL_EXT_shader_implicit_conversions GL_EXT_shader_integer_mix GL_EXT_tessellation_point_size GL_EXT_tessellation_shader GL_ANDROID_extension_pack_es31a GL_EXT_base_instance GL_EXT_compressed_ETC1_RGB8_sub_texture GL_EXT_copy_image GL_EXT_draw_buffers_indexed GL_EXT_draw_elements_base_vertex GL_EXT_gpu_shader5 GL_EXT_polygon_offset_clamp GL_EXT_primitive_bounding_box GL_EXT_render_snorm GL_EXT_shader_io_blocks GL_EXT_texture_border_clamp GL_EXT_texture_buffer GL_EXT_texture_cube_map_array GL_EXT_texture_norm16 GL_EXT_texture_view GL_KHR_blend_equation_advanced GL_KHR_context_flush_control GL_KHR_robust_buffer_access_behavior GL_NV_image_formats GL_OES_copy_image GL_OES_draw_buffers_indexed GL_OES_draw_elements_base_vertex GL_OES_gpu_shader5 GL_OES_primitive_bounding_box GL_OES_sample_shading GL_OES_sample_variables GL_OES_shader_io_blocks GL_OES_shader_multisample_interpolation GL_OES_tessellation_point_size GL_OES_tessellation_shader GL_OES_texture_border_clamp GL_OES_texture_buffer GL_OES_texture_cube_map_array GL_OES_texture_stencil8 GL_OES_texture_storage_multisample_2d_array GL_OES_texture_view GL_EXT_blend_func_extended GL_EXT_buffer_storage GL_EXT_float_blend GL_EXT_geometry_point_size GL_EXT_geometry_shader GL_EXT_shader_samples_identical GL_EXT_texture_sRGB_R8 GL_KHR_no_error GL_KHR_texture_compression_astc_sliced_3d GL_OES_EGL_image_external_essl3 GL_OES_geometry_point_size GL_OES_geometry_shader GL_OES_shader_image_atomic GL_EXT_clear_texture GL_EXT_clip_cull_distance GL_EXT_disjoint_timer_query GL_EXT_texture_compression_s3tc_srgb GL_EXT_window_rectangles GL_MESA_shader_integer_functions GL_EXT_clip_control GL_EXT_color_buffer_half_float GL_EXT_memory_object GL_EXT_memory_object_fd GL_EXT_semaphore GL_EXT_semaphore_fd GL_EXT_texture_compression_bptc GL_EXT_texture_mirror_clamp_to_edge GL_KHR_parallel_shader_compile GL_NV_alpha_to_coverage_dither_control GL_AMD_framebuffer_multisample_advanced GL_EXT_EGL_image_storage GL_EXT_texture_shadow_lod GL_INTEL_blackhole_render GL_MESA_framebuffer_flip_y GL_NV_compute_shader_derivatives GL_EXT_demote_to_helper_invocation GL_EXT_depth_clamp GL_EXT_texture_query_lod GL_MESA_bgra
Disabled Extensions GL_KHR_blend_equation_advanced GL_KHR_blend_equation_advanced_coherent
Disabled WebGL Extensions
Window system binding vendor Mesa Project
Window system binding version 1.5
Window system binding extensions EGL_ANDROID_blob_cache EGL_ANDROID_native_fence_sync EGL_EXT_buffer_age EGL_EXT_create_context_robustness EGL_EXT_image_dma_buf_import EGL_EXT_image_dma_buf_import_modifiers EGL_EXT_protected_surface EGL_EXT_present_opaque EGL_EXT_swap_buffers_with_damage EGL_KHR_cl_event2 EGL_KHR_config_attribs EGL_KHR_create_context EGL_KHR_create_context_no_error EGL_KHR_fence_sync EGL_KHR_get_all_proc_addresses EGL_KHR_gl_colorspace EGL_KHR_gl_renderbuffer_image EGL_KHR_gl_texture_2D_image EGL_KHR_gl_texture_3D_image EGL_KHR_gl_texture_cubemap_image EGL_KHR_image_base EGL_KHR_no_config_context EGL_KHR_reusable_sync EGL_KHR_surfaceless_context EGL_KHR_swap_buffers_with_damage EGL_EXT_pixel_format_float EGL_KHR_wait_sync EGL_MESA_configless_context EGL_MESA_drm_image EGL_MESA_image_dma_buf_export EGL_MESA_query_driver EGL_WL_bind_wayland_display EGL_WL_create_wayland_buffer_from_image
XDG_CURRENT_DESKTOP GNOME
XDG_SESSION_TYPE wayland
GDMSESSION gnome
Interfaces exposed by the Wayland compositor wl_compositor:4 wl_shm:1 wl_output:2 zxdg_output_manager_v1:3 wl_data_device_manager:3 zwp_primary_selection_device_manager_v1:1 gtk_primary_selection_device_manager:1 wl_subcompositor:1 xdg_wm_base:3 zxdg_shell_v6:1 wl_shell:1 gtk_shell1:5 wp_viewporter:1 zwp_pointer_gestures_v1:1 zwp_tablet_manager_v2:1 wl_seat:5 zwp_relative_pointer_manager_v1:1 zwp_pointer_constraints_v1:1 zxdg_exporter_v1:1 zxdg_importer_v1:1 zwp_keyboard_shortcuts_inhibit_manager_v1:1 zwp_text_input_manager_v3:1 gtk_text_input_manager:1 wp_presentation:1 xdg_activation_v1:1 zwp_linux_dmabuf_v1:3 wl_drm:2
Ozone platform wayland
Direct rendering version unknown
Reset notification strategy 0x8252
GPU process crash count 0
gfx::BufferFormats supported for allocation and texturing R_8: not supported, R_16: not supported, RG_88: not supported, RG_1616: not supported, BGR_565: not supported, RGBA_4444: not supported, RGBX_8888: not supported, RGBA_8888: not supported, BGRX_8888: not supported, BGRA_1010102: not supported, RGBA_1010102: not supported, BGRA_8888: not supported, RGBA_F16: not supported, YVU_420: not supported, YUV_420_BIPLANAR: not supported, P010: not supported
Compositor Information
Tile Update Mode One-copy
Partial Raster Enabled
GpuMemoryBuffers Status
R_8 Software only
R_16 Software only
RG_88 Software only
RG_1616 Software only
BGR_565 GPU_READ
RGBA_4444 Software only
RGBX_8888 GPU_READ, SCANOUT, SCANOUT_CPU_READ_WRITE, SCANOUT_FRONT_RENDERING
RGBA_8888 GPU_READ, SCANOUT, SCANOUT_CPU_READ_WRITE, SCANOUT_FRONT_RENDERING
BGRX_8888 GPU_READ, SCANOUT, SCANOUT_CPU_READ_WRITE, SCANOUT_FRONT_RENDERING
BGRA_1010102 SCANOUT, SCANOUT_CPU_READ_WRITE, SCANOUT_FRONT_RENDERING
RGBA_1010102 SCANOUT, SCANOUT_CPU_READ_WRITE, SCANOUT_FRONT_RENDERING
BGRA_8888 GPU_READ, SCANOUT, SCANOUT_CPU_READ_WRITE, SCANOUT_FRONT_RENDERING
RGBA_F16 Software only
YVU_420 Software only
YUV_420_BIPLANAR Software only
P010 Software only
Display(s) Information
Info Display[4] bounds=[0,0 2560×1600], workarea=[0,0 2560×1600], scale=1, rotation=0, panel_rotation=0 external.
Color space (all) {primaries:BT709, transfer:IEC61966_2_1, matrix:RGB, range:FULL}
Buffer format (all) RGBA_8888
SDR white level in nits 100
Bits per color component 8
Bits per pixel 24
Video Acceleration Information
Encoding
Vulkan Information
Device Performance Information
Log Messages
[7708:7708:0124/120722.108973:ERROR:gl_surface_egl.cc(783)] : EGL Driver message (Error) eglQueryDeviceStringEXT: EGL_BAD_PARAMETER error: In internal function: Additional INFO may be available
[7708:7708:0124/120722.125830:ERROR:gpu_init.cc(457)] : Passthrough is not supported, GL is egl, ANGLE is
[7708:7708:0124/120722.129994:ERROR:sandbox_linux.cc(378)] : InitializeSandbox() called with multiple threads in process gpu-process.
I am using Wayland on own Laptop and everything is more or less OK. By default Chrome is running under XWayland but I wish to try it to run natively.
–enable-features=UseOzonePlatform –ozone-platform=wayland
Previously I’ve also used ‘–force-device-scale-factor=1’ Chrome flag for slightly increasing UI. Now seems it’s not working. Maybe you can advice me something? Thanks.
Since version 97 Chrome supports selecting the preferred backend so that you would not have to specify it via the command line. To configure that, open chrome://flags and find there “Preferred Ozone platform”.
Forcing the device scale factor is very problematic on Wayland, that is why it is not currently supported as a product feature for this platform. It may work, but stability is not guaranteed. Likely something has changed so it stopped behaving as you expected.