static int copy_pixels(struct evdi_framebuffer *ufb, char __user *buffer, int buf_byte_stride, int num_rects, struct drm_clip_rect *rects, int const max_x, int const max_y, struct evdi_cursor *cursor_copy) { struct drm_framebuffer *fb = &ufb->base; struct drm_clip_rect *r; EVDI_CHECKPT(); for (r = rects; r != rects + num_rects; ++r) { const int byte_offset = r->x1 * 4; const int byte_span = (r->x2 - r->x1) * 4; const int src_offset = fb->pitches[0] * r->y1 + byte_offset; const char *src = (char *)ufb->obj->vmapping + src_offset; const int dst_offset = buf_byte_stride * r->y1 + byte_offset; char __user *dst = buffer + dst_offset; int y = r->y2 - r->y1; /* rect size may correspond to previous resolution */ if (max_x < r->x2 || max_y < r->y2) { EVDI_WARN("Rect size beyond expected dimensions\n"); return -EFAULT; } EVDI_VERBOSE("copy rect %d,%d-%d,%d\n", r->x1, r->y1, r->x2, r->y2); for (; y > 0; --y) { if (copy_to_user(dst, src, byte_span)) return -EFAULT; src += fb->pitches[0]; dst += buf_byte_stride; } } return evdi_cursor_composing_and_copy(cursor_copy, ufb, buffer, buf_byte_stride, max_x, max_y); }
int evdi_handle_damage(struct evdi_framebuffer *fb, int x, int y, int width, int height) { struct drm_device *dev = fb->base.dev; struct evdi_device *evdi = dev->dev_private; EVDI_CHECKPT(); if (!fb->obj->vmapping) { if (evdi_gem_vmap(fb->obj) == -ENOMEM) { DRM_ERROR("failed to vmap fb\n"); return 0; } if (!fb->obj->vmapping) { DRM_ERROR("failed to vmapping\n"); return 0; } } { const int line_offset = fb->base.pitches[0] * y; const int byte_offset = line_offset + (x * 4); //RG24 const char* pix = (char*)fb->obj->vmapping + byte_offset; EVDI_VERBOSE("%p %d,%d-%dx%d %02x%02x%02x%02x%02x%02x%02x%02x\n", fb, x, y, width, height, ((int)(pix[0])&0xff), ((int)(pix[1])&0xff), ((int)(pix[2])&0xff), ((int)(pix[3])&0xff), ((int)(pix[4])&0xff), ((int)(pix[5])&0xff), ((int)(pix[6])&0xff), ((int)(pix[7])&0xff)); } { struct drm_clip_rect rect = { x, y, x + width, y + height }; evdi_painter_mark_dirty(evdi, fb, &rect); } return 0; }
void evdi_painter_mark_dirty(struct evdi_device *evdi, const struct drm_clip_rect *dirty_rect) { struct drm_clip_rect rect; struct evdi_framebuffer *efb = NULL; struct evdi_painter *painter = evdi->painter; painter_lock(evdi->painter); efb = evdi->painter->scanout_fb; if (!efb) { EVDI_WARN("Skip clip rect. Scanout buffer not set.\n"); goto unlock; } rect = evdi_framebuffer_sanitize_rect(efb, dirty_rect); EVDI_VERBOSE("(dev=%d) %d,%d-%d,%d\n", evdi->dev_index, rect.x1, rect.y1, rect.x2, rect.y2); if (painter->num_dirts == MAX_DIRTS) merge_dirty_rects(&painter->dirty_rects[0], &painter->num_dirts); if (painter->num_dirts == MAX_DIRTS) collapse_dirty_rects(&painter->dirty_rects[0], &painter->num_dirts); memcpy(&painter->dirty_rects[painter->num_dirts], &rect, sizeof(rect)); painter->num_dirts++; if (painter->was_update_requested) { evdi_painter_send_update_ready(painter); painter->was_update_requested = false; } unlock: painter_unlock(evdi->painter); }