diff --git a/src/surface.c b/src/surface.c index abcabe3..3f89b8f 100644 --- a/src/surface.c +++ b/src/surface.c @@ -677,9 +677,38 @@ VAStatus RequestExportSurfaceHandle(VADriverContextP context, for (i = 0; i < planes_count; i++) size += surface_object->destination_sizes[i]; + /* + * Iteration 2 Fix 2: choose drm_format_modifier conditionally on + * pitch alignment. Mesa's WSI / Panfrost compositor path rejects + * DRM_FORMAT_MOD_NONE (= LINEAR explicit) buffers whose pitch isn't + * GPU-aligned (typically 64+ bytes for Mali). For 1920-wide content + * the pitch is 1920 (64-aligned, fine); for 864-wide content the + * pitch is 864 (only 16-aligned), Mesa rejects with "WSI pitch not + * properly aligned" and Firefox falls back to SW. + * + * Setting DRM_FORMAT_MOD_INVALID tells the importer "modifier + * unknown, treat as implicit / texture-only" — Firefox's + * DMABufSurface.cpp:1920 explicitly omits modifier attribs from + * eglCreateImage when the value is MOD_INVALID, bypassing Mesa's + * scanout-alignment check. The buffer is then texture-imported + * (small perf cost) instead of WSI scanout-imported, which is + * the correct behavior for a buffer that doesn't meet scanout + * alignment requirements. + * + * We branch on pitch alignment to preserve LINEAR semantics for + * already-aligned content (avoids unnecessary perf cost on the + * common 1920-wide case). + * + * Sonnet Phase 5 review (iter2 question 4) endorsed this + * conditional approach over a universal MOD_INVALID change. + */ for (i = 0; i < export_fds_count; i++) { - surface_descriptor->objects[i].drm_format_modifier = - video_format->drm_modifier; + uint64_t modifier = video_format->drm_modifier; + unsigned int bytesperline = + surface_object->destination_bytesperlines[0]; + if (bytesperline & 63) /* not 64-byte aligned */ + modifier = DRM_FORMAT_MOD_INVALID; + surface_descriptor->objects[i].drm_format_modifier = modifier; surface_descriptor->objects[i].fd = export_fds[i]; surface_descriptor->objects[i].size = export_fds_count == 1 ? size :