drm/gud: Split up gud_flush_work()

In preparation for inlining synchronous flushing split out the part of
gud_flush_work() that can be shared by the sync and async code paths.

Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de>
Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20221122-gud-shadow-plane-v2-3-435037990a83@tronnes.org
This commit is contained in:
Noralf Trønnes 2022-11-30 20:26:51 +01:00
parent f531d19882
commit 754a6ca85c

View File

@ -333,15 +333,49 @@ void gud_clear_damage(struct gud_device *gdrm)
gdrm->damage.y2 = 0;
}
static void gud_flush_damage(struct gud_device *gdrm, struct drm_framebuffer *fb,
struct drm_rect *damage)
{
const struct drm_format_info *format;
unsigned int i, lines;
size_t pitch;
int ret;
format = fb->format;
if (format->format == DRM_FORMAT_XRGB8888 && gdrm->xrgb8888_emulation_format)
format = gdrm->xrgb8888_emulation_format;
/* Split update if it's too big */
pitch = drm_format_info_min_pitch(format, 0, drm_rect_width(damage));
lines = drm_rect_height(damage);
if (gdrm->bulk_len < lines * pitch)
lines = gdrm->bulk_len / pitch;
for (i = 0; i < DIV_ROUND_UP(drm_rect_height(damage), lines); i++) {
struct drm_rect rect = *damage;
rect.y1 += i * lines;
rect.y2 = min_t(u32, rect.y1 + lines, damage->y2);
ret = gud_flush_rect(gdrm, fb, format, &rect);
if (ret) {
if (ret != -ENODEV && ret != -ECONNRESET &&
ret != -ESHUTDOWN && ret != -EPROTO)
dev_err_ratelimited(fb->dev->dev,
"Failed to flush framebuffer: error=%d\n", ret);
gdrm->prev_flush_failed = true;
break;
}
}
}
void gud_flush_work(struct work_struct *work)
{
struct gud_device *gdrm = container_of(work, struct gud_device, work);
const struct drm_format_info *format;
struct drm_framebuffer *fb;
struct drm_rect damage;
unsigned int i, lines;
int idx, ret = 0;
size_t pitch;
int idx;
if (!drm_dev_enter(&gdrm->drm, &idx))
return;
@ -356,35 +390,7 @@ void gud_flush_work(struct work_struct *work)
if (!fb)
goto out;
format = fb->format;
if (format->format == DRM_FORMAT_XRGB8888 && gdrm->xrgb8888_emulation_format)
format = gdrm->xrgb8888_emulation_format;
/* Split update if it's too big */
pitch = drm_format_info_min_pitch(format, 0, drm_rect_width(&damage));
lines = drm_rect_height(&damage);
if (gdrm->bulk_len < lines * pitch)
lines = gdrm->bulk_len / pitch;
for (i = 0; i < DIV_ROUND_UP(drm_rect_height(&damage), lines); i++) {
struct drm_rect rect = damage;
rect.y1 += i * lines;
rect.y2 = min_t(u32, rect.y1 + lines, damage.y2);
ret = gud_flush_rect(gdrm, fb, format, &rect);
if (ret) {
if (ret != -ENODEV && ret != -ECONNRESET &&
ret != -ESHUTDOWN && ret != -EPROTO)
dev_err_ratelimited(fb->dev->dev,
"Failed to flush framebuffer: error=%d\n", ret);
gdrm->prev_flush_failed = true;
break;
}
gdrm->prev_flush_failed = false;
}
gud_flush_damage(gdrm, fb, &damage);
drm_framebuffer_put(fb);
out: