diff mbox series

[v2,1/2] libv4lconvert: Port supported_src_formats to bit-ops

Message ID 20190417114135.5987-1-ricardo@ribalda.com (mailing list archive)
State New, archived
Headers show
Series [v2,1/2] libv4lconvert: Port supported_src_formats to bit-ops | expand

Commit Message

Ricardo Ribalda Delgado April 17, 2019, 11:41 a.m. UTC
We have passed the barrier of 64 supported formats, therefore a int64_t
is not enough for holding the bitfield.

Instead use bit-ops ala kernel.

Signed-off-by: Ricardo Ribalda Delgado <ricardo@ribalda.com>
Suggested-by: Hans de Goede <hdegoede@redhat.com>
---
 lib/libv4lconvert/libv4lconvert-priv.h |  3 +-
 lib/libv4lconvert/libv4lconvert.c      | 40 ++++++++++++++++++++++----
 2 files changed, 37 insertions(+), 6 deletions(-)

Comments

Hans de Goede April 18, 2019, 11:21 a.m. UTC | #1
Hi,

On 17-04-19 13:41, Ricardo Ribalda Delgado wrote:
> We have passed the barrier of 64 supported formats, therefore a int64_t
> is not enough for holding the bitfield.
> 
> Instead use bit-ops ala kernel.
> 
> Signed-off-by: Ricardo Ribalda Delgado <ricardo@ribalda.com>
> Suggested-by: Hans de Goede <hdegoede@redhat.com>

Thank you.

I've dropped the unnecessary __prefix from the bitop functions and
I've pushed both patches to the upstream master branch now.

Regards,

Hans



> ---
>   lib/libv4lconvert/libv4lconvert-priv.h |  3 +-
>   lib/libv4lconvert/libv4lconvert.c      | 40 ++++++++++++++++++++++----
>   2 files changed, 37 insertions(+), 6 deletions(-)
> 
> diff --git a/lib/libv4lconvert/libv4lconvert-priv.h b/lib/libv4lconvert/libv4lconvert-priv.h
> index a8046ce2..5286a9b1 100644
> --- a/lib/libv4lconvert/libv4lconvert-priv.h
> +++ b/lib/libv4lconvert/libv4lconvert-priv.h
> @@ -38,6 +38,7 @@
>   #include "tinyjpeg.h"
>   
>   #define ARRAY_SIZE(x) ((int)sizeof(x)/(int)sizeof((x)[0]))
> +#define BITS_PER_LONG (8 * sizeof(long))
>   
>   #define V4LCONVERT_ERROR_MSG_SIZE 256
>   #define V4LCONVERT_MAX_FRAMESIZES 256
> @@ -55,7 +56,7 @@ struct v4lconvert_data {
>   	int flags; /* bitfield */
>   	int control_flags; /* bitfield */
>   	unsigned int no_formats;
> -	int64_t supported_src_formats; /* bitfield */
> +	unsigned long supported_src_formats[128 / BITS_PER_LONG];
>   	char error_msg[V4LCONVERT_ERROR_MSG_SIZE];
>   	struct jdec_private *tinyjpeg;
>   #ifdef HAVE_JPEG
> diff --git a/lib/libv4lconvert/libv4lconvert.c b/lib/libv4lconvert/libv4lconvert.c
> index 78fb3432..0607cc8b 100644
> --- a/lib/libv4lconvert/libv4lconvert.c
> +++ b/lib/libv4lconvert/libv4lconvert.c
> @@ -32,6 +32,29 @@
>   #include "libv4lsyscall-priv.h"
>   
>   #define MIN(a, b) (((a) < (b)) ? (a) : (b))
> +#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
> +#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
> +
> +static inline void __set_bit(int nr, volatile unsigned long *addr)
> +{
> +	unsigned long mask = BIT_MASK(nr);
> +	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
> +
> +	*p  |= mask;
> +}
> +
> +static inline void __clear_bit(int nr, volatile unsigned long *addr)
> +{
> +	unsigned long mask = BIT_MASK(nr);
> +	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
> +
> +	*p &= ~mask;
> +}
> +
> +static inline int __test_bit(int nr, const volatile unsigned long *addr)
> +{
> +	return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
> +}
>   
>   static void *dev_init(int fd)
>   {
> @@ -231,7 +254,7 @@ struct v4lconvert_data *v4lconvert_create_with_dev_ops(int fd, void *dev_ops_pri
>   				break;
>   
>   		if (j < ARRAY_SIZE(supported_src_pixfmts)) {
> -			data->supported_src_formats |= 1ULL << j;
> +			__set_bit(j, data->supported_src_formats);
>   			v4lconvert_get_framesizes(data, fmt.pixelformat, j);
>   			if (!supported_src_pixfmts[j].needs_conversion)
>   				always_needs_conversion = 0;
> @@ -316,8 +339,15 @@ int v4lconvert_supported_dst_format(unsigned int pixelformat)
>   
>   int v4lconvert_supported_dst_fmt_only(struct v4lconvert_data *data)
>   {
> -	return v4lcontrol_needs_conversion(data->control) &&
> -		data->supported_src_formats;
> +	int i;
> +
> +	for (i = 0 ; i < ARRAY_SIZE(data->supported_src_formats); i++)
> +		if (data->supported_src_formats[i])
> +			break;
> +	if (i == ARRAY_SIZE(data->supported_src_formats))
> +		return 0;
> +
> +	return v4lcontrol_needs_conversion(data->control);
>   }
>   
>   /* See libv4lconvert.h for description of in / out parameters */
> @@ -334,7 +364,7 @@ int v4lconvert_enum_fmt(struct v4lconvert_data *data, struct v4l2_fmtdesc *fmt)
>   
>   	for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++)
>   		if (v4lconvert_supported_dst_fmt_only(data) ||
> -				!(data->supported_src_formats & (1ULL << i))) {
> +		    !__test_bit(i, data->supported_src_formats)) {
>   			faked_fmts[no_faked_fmts] = supported_dst_pixfmts[i].fmt;
>   			no_faked_fmts++;
>   		}
> @@ -490,7 +520,7 @@ static int v4lconvert_do_try_format(struct v4lconvert_data *data,
>   
>   	for (i = 0; i < ARRAY_SIZE(supported_src_pixfmts); i++) {
>   		/* is this format supported? */
> -		if (!(data->supported_src_formats & (1ULL << i)))
> +		if (!__test_bit(i, data->supported_src_formats))
>   			continue;
>   
>   		try_fmt = *dest_fmt;
>
diff mbox series

Patch

diff --git a/lib/libv4lconvert/libv4lconvert-priv.h b/lib/libv4lconvert/libv4lconvert-priv.h
index a8046ce2..5286a9b1 100644
--- a/lib/libv4lconvert/libv4lconvert-priv.h
+++ b/lib/libv4lconvert/libv4lconvert-priv.h
@@ -38,6 +38,7 @@ 
 #include "tinyjpeg.h"
 
 #define ARRAY_SIZE(x) ((int)sizeof(x)/(int)sizeof((x)[0]))
+#define BITS_PER_LONG (8 * sizeof(long))
 
 #define V4LCONVERT_ERROR_MSG_SIZE 256
 #define V4LCONVERT_MAX_FRAMESIZES 256
@@ -55,7 +56,7 @@  struct v4lconvert_data {
 	int flags; /* bitfield */
 	int control_flags; /* bitfield */
 	unsigned int no_formats;
-	int64_t supported_src_formats; /* bitfield */
+	unsigned long supported_src_formats[128 / BITS_PER_LONG];
 	char error_msg[V4LCONVERT_ERROR_MSG_SIZE];
 	struct jdec_private *tinyjpeg;
 #ifdef HAVE_JPEG
diff --git a/lib/libv4lconvert/libv4lconvert.c b/lib/libv4lconvert/libv4lconvert.c
index 78fb3432..0607cc8b 100644
--- a/lib/libv4lconvert/libv4lconvert.c
+++ b/lib/libv4lconvert/libv4lconvert.c
@@ -32,6 +32,29 @@ 
 #include "libv4lsyscall-priv.h"
 
 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
+#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
+
+static inline void __set_bit(int nr, volatile unsigned long *addr)
+{
+	unsigned long mask = BIT_MASK(nr);
+	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
+
+	*p  |= mask;
+}
+
+static inline void __clear_bit(int nr, volatile unsigned long *addr)
+{
+	unsigned long mask = BIT_MASK(nr);
+	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
+
+	*p &= ~mask;
+}
+
+static inline int __test_bit(int nr, const volatile unsigned long *addr)
+{
+	return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
+}
 
 static void *dev_init(int fd)
 {
@@ -231,7 +254,7 @@  struct v4lconvert_data *v4lconvert_create_with_dev_ops(int fd, void *dev_ops_pri
 				break;
 
 		if (j < ARRAY_SIZE(supported_src_pixfmts)) {
-			data->supported_src_formats |= 1ULL << j;
+			__set_bit(j, data->supported_src_formats);
 			v4lconvert_get_framesizes(data, fmt.pixelformat, j);
 			if (!supported_src_pixfmts[j].needs_conversion)
 				always_needs_conversion = 0;
@@ -316,8 +339,15 @@  int v4lconvert_supported_dst_format(unsigned int pixelformat)
 
 int v4lconvert_supported_dst_fmt_only(struct v4lconvert_data *data)
 {
-	return v4lcontrol_needs_conversion(data->control) &&
-		data->supported_src_formats;
+	int i;
+
+	for (i = 0 ; i < ARRAY_SIZE(data->supported_src_formats); i++)
+		if (data->supported_src_formats[i])
+			break;
+	if (i == ARRAY_SIZE(data->supported_src_formats))
+		return 0;
+
+	return v4lcontrol_needs_conversion(data->control);
 }
 
 /* See libv4lconvert.h for description of in / out parameters */
@@ -334,7 +364,7 @@  int v4lconvert_enum_fmt(struct v4lconvert_data *data, struct v4l2_fmtdesc *fmt)
 
 	for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++)
 		if (v4lconvert_supported_dst_fmt_only(data) ||
-				!(data->supported_src_formats & (1ULL << i))) {
+		    !__test_bit(i, data->supported_src_formats)) {
 			faked_fmts[no_faked_fmts] = supported_dst_pixfmts[i].fmt;
 			no_faked_fmts++;
 		}
@@ -490,7 +520,7 @@  static int v4lconvert_do_try_format(struct v4lconvert_data *data,
 
 	for (i = 0; i < ARRAY_SIZE(supported_src_pixfmts); i++) {
 		/* is this format supported? */
-		if (!(data->supported_src_formats & (1ULL << i)))
+		if (!__test_bit(i, data->supported_src_formats))
 			continue;
 
 		try_fmt = *dest_fmt;