floor_lut_value = (__u16 *)&lut->base[drm_fixp2int(lut_index)]; if (drm_fixp2int(lut_index) == (lut->lut_length - 1)) /* We're at the end of the LUT array, use same value for ceil and floor */
ceil_lut_value = floor_lut_value; else
ceil_lut_value = (__u16 *)&lut->base[drm_fixp2int_ceil(lut_index)];
if (x == 1 && y == 0) return READ_LEFT_TO_RIGHT; elseif (x == -1 && y == 0) return READ_RIGHT_TO_LEFT; elseif (y == 1 && x == 0) return READ_TOP_TO_BOTTOM; elseif (y == -1 && x == 0) return READ_BOTTOM_TO_TOP;
WARN_ONCE(true, "The inverse of the rotation gives an incorrect direction."); return READ_LEFT_TO_RIGHT;
}
/** *clamp_line_coordinates()-Computeandclampthecoordinatetoreadandwriteduringtheblend *process. * *@direction:directionofthereading *@current_plane:currentplaneblended *@src_line:sourcelineofthereading.Onlythetop-leftcoordinateisused.Thisrectangle *mustberotatedandhaveashapeof1*pixel_countif@directionisverticalandashapeof *pixel_count*1if@directionishorizontal. *@src_x_start:xstartcoordinateforthelinereading *@src_y_start:ystartcoordinateforthelinereading *@dst_x_start:xcoordinatetoblendthereadline *@pixel_count:numberofpixelstoblend * *Thisfunctionismainlyasafetynettoavoidreadingoutsidethesourcebuffer.Asthe *userspaceshouldneverasktoreadoutsidethesourceplane,allthecasescoveredhereshould *bedeadcode.
*/ staticvoid clamp_line_coordinates(enum pixel_read_direction direction, conststruct vkms_plane_state *current_plane, conststruct drm_rect *src_line, int *src_x_start, int *src_y_start, int *dst_x_start, int *pixel_count)
{ /* By default the start points are correct */
*src_x_start = src_line->x1;
*src_y_start = src_line->y1;
*dst_x_start = current_plane->frame_info->dst.x1;
/* Get the correct number of pixel to blend, it depends of the direction */ switch (direction) { case READ_LEFT_TO_RIGHT: case READ_RIGHT_TO_LEFT:
*pixel_count = drm_rect_width(src_line); break; case READ_BOTTOM_TO_TOP: case READ_TOP_TO_BOTTOM:
*pixel_count = drm_rect_height(src_line); break;
}
/* *Clampthecoordinatestoavoidreadingoutsidethebuffer * *Thisismainlyasecuritychecktoavoidreadingoutsidethebuffer,theuserspace *shouldneverrequesttoreadoutsidethesourcebuffer.
*/ switch (direction) { case READ_LEFT_TO_RIGHT: case READ_RIGHT_TO_LEFT: if (*src_x_start < 0) {
*pixel_count += *src_x_start;
*dst_x_start -= *src_x_start;
*src_x_start = 0;
} if (*src_x_start + *pixel_count > current_plane->frame_info->fb->width)
*pixel_count = max(0, (int)current_plane->frame_info->fb->width -
*src_x_start); break; case READ_BOTTOM_TO_TOP: case READ_TOP_TO_BOTTOM: if (*src_y_start < 0) {
*pixel_count += *src_y_start;
*dst_x_start -= *src_y_start;
*src_y_start = 0;
} if (*src_y_start + *pixel_count > current_plane->frame_info->fb->height)
*pixel_count = max(0, (int)current_plane->frame_info->fb->height -
*src_y_start); break;
}
}
/** *blend_line()-Blendalinefromaplanetotheoutputbuffer * *@current_plane:currentplanetoworkon *@y:linetowriteintheoutputbuffer *@crtc_x_limit:widthoftheoutputbuffer *@stage_buffer:temporarybuffertoconvertthepixellinefromthesourcebuffer *@output_buffer:buffertoblendthereadlineinto.
*/ staticvoid blend_line(struct vkms_plane_state *current_plane, int y, int crtc_x_limit, struct line_buffer *stage_buffer, struct line_buffer *output_buffer)
{ int src_x_start, src_y_start, dst_x_start, pixel_count; struct drm_rect dst_line, tmp_src, src_line;
/* Avoid rendering useless lines */ if (y < current_plane->frame_info->dst.y1 ||
y >= current_plane->frame_info->dst.y2) return;
/* Get the correct reading direction in the source buffer. */
enum pixel_read_direction direction =
direction_for_rotation(current_plane->frame_info->rotation);
/* [2]: Compute and clamp the number of pixel to read */
clamp_line_coordinates(direction, current_plane, &src_line, &src_x_start, &src_y_start,
&dst_x_start, &pixel_count);
if (pixel_count <= 0) { /* Nothing to read, so avoid multiple function calls */ return;
}
/* *Modifythestartingpointtotakeinaccounttherotation * *src_lineisthetop-leftcorner,sowhenreadingREAD_RIGHT_TO_LEFTor *READ_BOTTOM_TO_TOP,itmustbechangedtothetop-right/bottom-left *corner.
*/ if (direction == READ_RIGHT_TO_LEFT) { // src_x_start is now the right point
src_x_start += pixel_count - 1;
} elseif (direction == READ_BOTTOM_TO_TOP) { // src_y_start is now the bottom point
src_y_start += pixel_count - 1;
}
int crtc_y_limit = crtc_state->base.mode.vdisplay; int crtc_x_limit = crtc_state->base.mode.hdisplay;
/* *Theplanesarecomposedline-by-linetoavoidheavymemoryusage.Itisanecessary *complexitytoavoidpoorblendingperformance. * *Thefunctionpixel_read_linecallbackisusedtoreadaline,usinganefficient *algorithmforaspecificformat,intothestagingbuffer.
*/ for (int y = 0; y < crtc_y_limit; y++) {
fill_background(&background_color, output_buffer);
/* The active planes are composed associatively in z-order. */ for (size_t i = 0; i < n_active_planes; i++) {
blend_line(plane[i], y, crtc_x_limit, stage_buffer, output_buffer);
}
stage_buffer.pixels = kvmalloc(line_width * pixel_size, GFP_KERNEL); if (!stage_buffer.pixels) {
DRM_ERROR("Cannot allocate memory for the output line buffer"); return -ENOMEM;
}
output_buffer.pixels = kvmalloc(line_width * pixel_size, GFP_KERNEL); if (!output_buffer.pixels) {
DRM_ERROR("Cannot allocate memory for intermediate line buffer");
ret = -ENOMEM; goto free_stage_buffer;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Hier finden Sie eine Liste der Produkte des Unternehmens