All of lore.kernel.org
 help / color / mirror / Atom feed
From: "José Expósito" <jose.exposito89@gmail.com>
To: airlied@gmail.com, arthurgrillo@riseup.net, corbet@lwn.net,
	dri-devel@lists.freedesktop.org, hamohammed.sa@gmail.com,
	helen.koike@collabora.com, jeremie.dautheribes@bootlin.com,
	linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
	maarten.lankhorst@linux.intel.com, mairacanal@riseup.net,
	marcheu@google.com, melissa.srw@gmail.com,
	miquel.raynal@bootlin.com, mripard@kernel.org,
	nicolejadeyee@google.com, pekka.paalanen@haloniitty.fi,
	rdunlap@infradead.org, rodrigosiqueiramelo@gmail.com,
	seanpaul@google.com, simona.vetter@ffwll.ch, simona@ffwll.ch,
	thomas.petazzoni@bootlin.com, tzimmermann@suse.de
Subject: Re: [PATCH v13 5/9] drm/vkms: Update pixels accessor to support packed and multi-plane formats.
Date: Mon, 18 Nov 2024 18:24:14 +0100	[thread overview]
Message-ID: <Zzt4PiTRqwmikMnm@fedora> (raw)
In-Reply-To: <Zzt2l0hZpKp4mniY@louis-chauvet-laptop>

On Mon, Nov 18, 2024 at 06:17:11PM +0100, Louis Chauvet wrote:
> On 18/11/24 - 18:10, José Expósito wrote:
> > > Introduce the usage of block_h/block_w to compute the offset and the
> > > pointer of a pixel. The previous implementation was specialized for
> > > planes with block_h == block_w == 1. To avoid confusion and allow easier
> > > implementation of tiled formats. It also remove the usage of the
> > > deprecated format field `cpp`.
> > > 
> > > Introduce the plane_index parameter to get an offset/pointer on a
> > > different plane.
> > > 
> > > Acked-by: Maíra Canal <mairacanal@riseup.net>
> > > Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
> > > ---
> > >  drivers/gpu/drm/vkms/vkms_formats.c | 114 ++++++++++++++++++++++++++++--------
> > >  1 file changed, 91 insertions(+), 23 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/vkms/vkms_formats.c b/drivers/gpu/drm/vkms/vkms_formats.c
> > > index 06aef5162529..7f932d42394d 100644
> > > --- a/drivers/gpu/drm/vkms/vkms_formats.c
> > > +++ b/drivers/gpu/drm/vkms/vkms_formats.c
> > > @@ -10,22 +10,46 @@
> > >  #include "vkms_formats.h"
> > >  
> > >  /**
> > > - * pixel_offset() - Get the offset of the pixel at coordinates x/y in the first plane
> > > + * packed_pixels_offset() - Get the offset of the block containing the pixel at coordinates x/y
> > >   *
> > >   * @frame_info: Buffer metadata
> > >   * @x: The x coordinate of the wanted pixel in the buffer
> > >   * @y: The y coordinate of the wanted pixel in the buffer
> > > + * @plane_index: The index of the plane to use
> > > + * @offset: The returned offset inside the buffer of the block
> > 
> > The previous function (pixel_offset) returned a size_t for the offset rather
> > than an int. Do you know if we are safe using an int in this case?
> 
> I think I used int everywhere because it may avoid strange issues with 
> implicit casting and negative number. I don't remember exactly where, but 
> Pekka suggested it.

Ah! Good to know. For the record, I ran locally the IGT tests and
perform some manual testing and I found no issues.

> > > + * @rem_x: The returned X coordinate of the requested pixel in the block
> > > + * @rem_y: The returned Y coordinate of the requested pixel in the block
> > >   *
> > > - * The caller must ensure that the framebuffer associated with this request uses a pixel format
> > > - * where block_h == block_w == 1.
> > > - * If this requirement is not fulfilled, the resulting offset can point to an other pixel or
> > > - * outside of the buffer.
> > > + * As some pixel formats store multiple pixels in a block (DRM_FORMAT_R* for example), some
> > > + * pixels are not individually addressable. This function return 3 values: the offset of the
> > > + * whole block, and the coordinate of the requested pixel inside this block.
> > > + * For example, if the format is DRM_FORMAT_R1 and the requested coordinate is 13,5, the offset
> > > + * will point to the byte 5*pitches + 13/8 (second byte of the 5th line), and the rem_x/rem_y
> > > + * coordinates will be (13 % 8, 5 % 1) = (5, 0)
> > > + *
> > > + * With this function, the caller just have to extract the correct pixel from the block.
> > >   */
> > > -static size_t pixel_offset(const struct vkms_frame_info *frame_info, int x, int y)
> > > +static void packed_pixels_offset(const struct vkms_frame_info *frame_info, int x, int y,
> > > +				 int plane_index, int *offset, int *rem_x, int *rem_y)
> > >  {
> > >  	struct drm_framebuffer *fb = frame_info->fb;
> > > +	const struct drm_format_info *format = frame_info->fb->format;
> > > +	/* Directly using x and y to multiply pitches and format->ccp is not sufficient because
> > > +	 * in some formats a block can represent multiple pixels.
> > > +	 *
> > > +	 * Dividing x and y by the block size allows to extract the correct offset of the block
> > > +	 * containing the pixel.
> > > +	 */
> > >  
> > > -	return fb->offsets[0] + (y * fb->pitches[0]) + (x * fb->format->cpp[0]);
> > > +	int block_x = x / drm_format_info_block_width(format, plane_index);
> > > +	int block_y = y / drm_format_info_block_height(format, plane_index);
> > > +	int block_pitch = fb->pitches[plane_index] * drm_format_info_block_height(format,
> > > +										  plane_index);
> > > +	*rem_x = x % drm_format_info_block_width(format, plane_index);
> > > +	*rem_y = y % drm_format_info_block_height(format, plane_index);
> > > +	*offset = fb->offsets[plane_index] +
> > > +		  block_y * block_pitch +
> > > +		  block_x * format->char_per_block[plane_index];
> > >  }
> > >  
> > >  /**
> > > @@ -35,30 +59,71 @@ static size_t pixel_offset(const struct vkms_frame_info *frame_info, int x, int
> > >   * @frame_info: Buffer metadata
> > >   * @x: The x (width) coordinate inside the plane
> > >   * @y: The y (height) coordinate inside the plane
> > > + * @plane_index: The index of the plane
> > > + * @addr: The returned pointer
> > > + * @rem_x: The returned X coordinate of the requested pixel in the block
> > > + * @rem_y: The returned Y coordinate of the requested pixel in the block
> > >   *
> > > - * Takes the information stored in the frame_info, a pair of coordinates, and
> > > - * returns the address of the first color channel.
> > > - * This function assumes the channels are packed together, i.e. a color channel
> > > - * comes immediately after another in the memory. And therefore, this function
> > > - * doesn't work for YUV with chroma subsampling (e.g. YUV420 and NV21).
> > > + * Takes the information stored in the frame_info, a pair of coordinates, and returns the address
> > > + * of the block containing this pixel and the pixel position inside this block.
> > >   *
> > > - * The caller must ensure that the framebuffer associated with this request uses a pixel format
> > > - * where block_h == block_w == 1, otherwise the returned pointer can be outside the buffer.
> > > + * See @packed_pixel_offset for details about rem_x/rem_y behavior.
> > 
> > Missing "s" in the name of the function. Should read "@packed_pixels_offset".
> 
> Thanks!
> 
> > >   */
> > > -static void *packed_pixels_addr(const struct vkms_frame_info *frame_info,
> > > -				int x, int y)
> > > +static void packed_pixels_addr(const struct vkms_frame_info *frame_info,
> > > +			       int x, int y, int plane_index, u8 **addr, int *rem_x,
> > > +			       int *rem_y)
> > >  {
> > > -	size_t offset = pixel_offset(frame_info, x, y);
> > > +	int offset;
> > >  
> > > -	return (u8 *)frame_info->map[0].vaddr + offset;
> > > +	packed_pixels_offset(frame_info, x, y, plane_index, &offset, rem_x, rem_y);
> > > +	*addr = (u8 *)frame_info->map[0].vaddr + offset;
> > >  }
> > >  
> > > -static void *get_packed_src_addr(const struct vkms_frame_info *frame_info, int y)
> > > +/**
> > > + * packed_pixels_addr_1x1() - Get the pointer to the block containing the pixel at the given
> > > + * coordinates
> > > + *
> > > + * @frame_info: Buffer metadata
> > > + * @x: The x (width) coordinate inside the plane
> > > + * @y: The y (height) coordinate inside the plane
> > > + * @plane_index: The index of the plane
> > > + * @addr: The returned pointer
> > > + *
> > > + * This function can only be used with format where block_h == block_w == 1.
> > > + */
> > > +static void packed_pixels_addr_1x1(const struct vkms_frame_info *frame_info,
> > > +				   int x, int y, int plane_index, u8 **addr)
> > > +{
> > > +	int offset, rem_x, rem_y;
> > 
> > Nitpick, but it'd be nice if packed_pixels_offset() could take NULLs in
> > the output values so we avoid declaring unused variables here and when
> > calling packed_pixels_addr().
> 
> It is not a trivial change, and as I want this series to be merged I will 
> send the v14 without it. But if I have the time I will send a new 
> patch/series with this cleanup, thanks for the suggestion.

That works for me, we can always fix it in a follow up... Specially since
2 other series depend on this one :)

Jose
 
> > > +
> > > +	WARN_ONCE(drm_format_info_block_width(frame_info->fb->format,
> > > +					      plane_index) != 1,
> > > +		"%s() only support formats with block_w == 1", __func__);
> > > +	WARN_ONCE(drm_format_info_block_height(frame_info->fb->format,
> > > +					       plane_index) != 1,
> > > +		"%s() only support formats with block_h == 1", __func__);
> > > +
> > > +	packed_pixels_offset(frame_info, x, y, plane_index, &offset, &rem_x,
> > > +			     &rem_y);
> > > +	*addr = (u8 *)frame_info->map[0].vaddr + offset;
> > > +}
> > > +
> > > +static void *get_packed_src_addr(const struct vkms_frame_info *frame_info, int y,
> > > +				 int plane_index)
> > >  {
> > >  	int x_src = frame_info->src.x1 >> 16;
> > >  	int y_src = y - frame_info->rotated.y1 + (frame_info->src.y1 >> 16);
> > > +	u8 *addr;
> > > +	int rem_x, rem_y;
> > > +
> > > +	WARN_ONCE(drm_format_info_block_width(frame_info->fb->format, plane_index) != 1,
> > > +		  "%s() only support formats with block_w == 1", __func__);
> > > +	WARN_ONCE(drm_format_info_block_height(frame_info->fb->format, plane_index) != 1,
> > > +		  "%s() only support formats with block_h == 1", __func__);
> > >  
> > > -	return packed_pixels_addr(frame_info, x_src, y_src);
> > > +	packed_pixels_addr(frame_info, x_src, y_src, plane_index, &addr, &rem_x, &rem_y);
> > > +
> > > +	return addr;
> > >  }
> > >  
> > >  static int get_x_position(const struct vkms_frame_info *frame_info, int limit, int x)
> > > @@ -152,14 +217,14 @@ void vkms_compose_row(struct line_buffer *stage_buffer, struct vkms_plane_state
> > >  {
> > >  	struct pixel_argb_u16 *out_pixels = stage_buffer->pixels;
> > >  	struct vkms_frame_info *frame_info = plane->frame_info;
> > > -	u8 *src_pixels = get_packed_src_addr(frame_info, y);
> > > +	u8 *src_pixels = get_packed_src_addr(frame_info, y, 0);
> > >  	int limit = min_t(size_t, drm_rect_width(&frame_info->dst), stage_buffer->n_pixels);
> > >  
> > >  	for (size_t x = 0; x < limit; x++, src_pixels += frame_info->fb->format->cpp[0]) {
> > >  		int x_pos = get_x_position(frame_info, limit, x);
> > >  
> > >  		if (drm_rotation_90_or_270(frame_info->rotation))
> > > -			src_pixels = get_packed_src_addr(frame_info, x + frame_info->rotated.y1)
> > > +			src_pixels = get_packed_src_addr(frame_info, x + frame_info->rotated.y1, 0)
> > >  				+ frame_info->fb->format->cpp[0] * y;
> > >  
> > >  		plane->pixel_read(src_pixels, &out_pixels[x_pos]);
> > > @@ -250,7 +315,10 @@ void vkms_writeback_row(struct vkms_writeback_job *wb,
> > >  {
> > >  	struct vkms_frame_info *frame_info = &wb->wb_frame_info;
> > >  	int x_dst = frame_info->dst.x1;
> > > -	u8 *dst_pixels = packed_pixels_addr(frame_info, x_dst, y);
> > > +	u8 *dst_pixels;
> > > +	int rem_x, rem_y;
> > > +
> > > +	packed_pixels_addr(frame_info, x_dst, y, 0, &dst_pixels, &rem_x, &rem_y);
> > >  	struct pixel_argb_u16 *in_pixels = src_buffer->pixels;
> > >  	int x_limit = min_t(size_t, drm_rect_width(&frame_info->dst), src_buffer->n_pixels);
> > >  
> > > 

  reply	other threads:[~2024-11-18 17:24 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-10-31 17:53 [PATCH v13 0/9] drm/vkms: Reimplement line-per-line pixel conversion for plane reading Louis Chauvet
2024-10-31 17:53 ` [PATCH v13 1/9] drm/vkms: Code formatting Louis Chauvet
2024-10-31 17:53 ` [PATCH v13 2/9] drm/vkms: Use drm_frame directly Louis Chauvet
2024-10-31 17:53 ` [PATCH v13 3/9] drm/vkms: Add typedef and documentation for pixel_read and pixel_write functions Louis Chauvet
2024-10-31 17:53 ` [PATCH v13 4/9] drm/vkms: Use const for input pointers in pixel_read an " Louis Chauvet
2024-10-31 17:53 ` [PATCH v13 5/9] drm/vkms: Update pixels accessor to support packed and multi-plane formats Louis Chauvet
2024-11-18 17:10   ` José Expósito
2024-11-18 17:17     ` Louis Chauvet
2024-11-18 17:24       ` José Expósito [this message]
2024-11-18 17:35         ` Louis Chauvet
2024-11-19 14:58           ` José Expósito
2024-10-31 17:53 ` [PATCH v13 6/9] drm/vkms: Avoid computing blending limits inside pre_mul_alpha_blend Louis Chauvet
2024-10-31 17:53 ` [PATCH v13 7/9] drm/vkms: Introduce pixel_read_direction enum Louis Chauvet
2024-11-18 17:10   ` José Expósito
2024-10-31 17:53 ` [PATCH v13 8/9] drm/vkms: Re-introduce line-per-line composition algorithm Louis Chauvet
2024-11-18 17:10   ` José Expósito
2024-11-18 17:19     ` Louis Chauvet
2024-10-31 17:53 ` [PATCH v13 9/9] drm/vkms: Remove useless drm_rotation_simplify Louis Chauvet
2024-11-18 17:10 ` [PATCH v13 0/9] drm/vkms: Reimplement line-per-line pixel conversion for plane reading José Expósito
2024-11-18 17:13   ` Louis Chauvet

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Zzt4PiTRqwmikMnm@fedora \
    --to=jose.exposito89@gmail.com \
    --cc=airlied@gmail.com \
    --cc=arthurgrillo@riseup.net \
    --cc=corbet@lwn.net \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=hamohammed.sa@gmail.com \
    --cc=helen.koike@collabora.com \
    --cc=jeremie.dautheribes@bootlin.com \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=maarten.lankhorst@linux.intel.com \
    --cc=mairacanal@riseup.net \
    --cc=marcheu@google.com \
    --cc=melissa.srw@gmail.com \
    --cc=miquel.raynal@bootlin.com \
    --cc=mripard@kernel.org \
    --cc=nicolejadeyee@google.com \
    --cc=pekka.paalanen@haloniitty.fi \
    --cc=rdunlap@infradead.org \
    --cc=rodrigosiqueiramelo@gmail.com \
    --cc=seanpaul@google.com \
    --cc=simona.vetter@ffwll.ch \
    --cc=simona@ffwll.ch \
    --cc=thomas.petazzoni@bootlin.com \
    --cc=tzimmermann@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.