vkms_formats.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971
  1. // SPDX-License-Identifier: GPL-2.0+
  2. #include <linux/kernel.h>
  3. #include <linux/minmax.h>
  4. #include <drm/drm_blend.h>
  5. #include <drm/drm_rect.h>
  6. #include <drm/drm_fixed.h>
  7. #include <kunit/visibility.h>
  8. #include "vkms_formats.h"
  9. /**
  10. * packed_pixels_offset() - Get the offset of the block containing the pixel at coordinates x/y
  11. *
  12. * @frame_info: Buffer metadata
  13. * @x: The x coordinate of the wanted pixel in the buffer
  14. * @y: The y coordinate of the wanted pixel in the buffer
  15. * @plane_index: The index of the plane to use
  16. * @offset: The returned offset inside the buffer of the block
  17. * @rem_x: The returned X coordinate of the requested pixel in the block
  18. * @rem_y: The returned Y coordinate of the requested pixel in the block
  19. *
  20. * As some pixel formats store multiple pixels in a block (DRM_FORMAT_R* for example), some
  21. * pixels are not individually addressable. This function return 3 values: the offset of the
  22. * whole block, and the coordinate of the requested pixel inside this block.
  23. * For example, if the format is DRM_FORMAT_R1 and the requested coordinate is 13,5, the offset
  24. * will point to the byte 5*pitches + 13/8 (second byte of the 5th line), and the rem_x/rem_y
  25. * coordinates will be (13 % 8, 5 % 1) = (5, 0)
  26. *
  27. * With this function, the caller just have to extract the correct pixel from the block.
  28. */
  29. static void packed_pixels_offset(const struct vkms_frame_info *frame_info, int x, int y,
  30. int plane_index, int *offset, int *rem_x, int *rem_y)
  31. {
  32. struct drm_framebuffer *fb = frame_info->fb;
  33. const struct drm_format_info *format = frame_info->fb->format;
  34. /* Directly using x and y to multiply pitches and format->ccp is not sufficient because
  35. * in some formats a block can represent multiple pixels.
  36. *
  37. * Dividing x and y by the block size allows to extract the correct offset of the block
  38. * containing the pixel.
  39. */
  40. int block_x = x / drm_format_info_block_width(format, plane_index);
  41. int block_y = y / drm_format_info_block_height(format, plane_index);
  42. int block_pitch = fb->pitches[plane_index] * drm_format_info_block_height(format,
  43. plane_index);
  44. *rem_x = x % drm_format_info_block_width(format, plane_index);
  45. *rem_y = y % drm_format_info_block_height(format, plane_index);
  46. *offset = fb->offsets[plane_index] +
  47. block_y * block_pitch +
  48. block_x * format->char_per_block[plane_index];
  49. }
  50. /**
  51. * packed_pixels_addr() - Get the pointer to the block containing the pixel at the given
  52. * coordinates
  53. *
  54. * @frame_info: Buffer metadata
  55. * @x: The x (width) coordinate inside the plane
  56. * @y: The y (height) coordinate inside the plane
  57. * @plane_index: The index of the plane
  58. * @addr: The returned pointer
  59. * @rem_x: The returned X coordinate of the requested pixel in the block
  60. * @rem_y: The returned Y coordinate of the requested pixel in the block
  61. *
  62. * Takes the information stored in the frame_info, a pair of coordinates, and returns the address
  63. * of the block containing this pixel and the pixel position inside this block.
  64. *
  65. * See @packed_pixels_offset for details about rem_x/rem_y behavior.
  66. */
  67. static void packed_pixels_addr(const struct vkms_frame_info *frame_info,
  68. int x, int y, int plane_index, u8 **addr, int *rem_x,
  69. int *rem_y)
  70. {
  71. int offset;
  72. packed_pixels_offset(frame_info, x, y, plane_index, &offset, rem_x, rem_y);
  73. *addr = (u8 *)frame_info->map[0].vaddr + offset;
  74. }
  75. /**
  76. * get_block_step_bytes() - Common helper to compute the correct step value between each pixel block
  77. * to read in a certain direction.
  78. *
  79. * @fb: Framebuffer to iter on
  80. * @direction: Direction of the reading
  81. * @plane_index: Plane to get the step from
  82. *
  83. * As the returned count is the number of bytes between two consecutive blocks in a direction,
  84. * the caller may have to read multiple pixels before using the next one (for example, to read from
  85. * left to right in a DRM_FORMAT_R1 plane, each block contains 8 pixels, so the step must be used
  86. * only every 8 pixels).
  87. */
  88. static int get_block_step_bytes(struct drm_framebuffer *fb, enum pixel_read_direction direction,
  89. int plane_index)
  90. {
  91. switch (direction) {
  92. case READ_LEFT_TO_RIGHT:
  93. return fb->format->char_per_block[plane_index];
  94. case READ_RIGHT_TO_LEFT:
  95. return -fb->format->char_per_block[plane_index];
  96. case READ_TOP_TO_BOTTOM:
  97. return (int)fb->pitches[plane_index] * drm_format_info_block_width(fb->format,
  98. plane_index);
  99. case READ_BOTTOM_TO_TOP:
  100. return -(int)fb->pitches[plane_index] * drm_format_info_block_width(fb->format,
  101. plane_index);
  102. }
  103. return 0;
  104. }
  105. /**
  106. * packed_pixels_addr_1x1() - Get the pointer to the block containing the pixel at the given
  107. * coordinates
  108. *
  109. * @frame_info: Buffer metadata
  110. * @x: The x (width) coordinate inside the plane
  111. * @y: The y (height) coordinate inside the plane
  112. * @plane_index: The index of the plane
  113. * @addr: The returned pointer
  114. *
  115. * This function can only be used with format where block_h == block_w == 1.
  116. */
  117. static void packed_pixels_addr_1x1(const struct vkms_frame_info *frame_info,
  118. int x, int y, int plane_index, u8 **addr)
  119. {
  120. int offset, rem_x, rem_y;
  121. WARN_ONCE(drm_format_info_block_width(frame_info->fb->format,
  122. plane_index) != 1,
  123. "%s() only support formats with block_w == 1", __func__);
  124. WARN_ONCE(drm_format_info_block_height(frame_info->fb->format,
  125. plane_index) != 1,
  126. "%s() only support formats with block_h == 1", __func__);
  127. packed_pixels_offset(frame_info, x, y, plane_index, &offset, &rem_x,
  128. &rem_y);
  129. *addr = (u8 *)frame_info->map[0].vaddr + offset;
  130. }
  131. /**
  132. * get_subsampling() - Get the subsampling divisor value on a specific direction
  133. *
  134. * @format: format to extarct the subsampling from
  135. * @direction: direction of the subsampling requested
  136. */
  137. static int get_subsampling(const struct drm_format_info *format,
  138. enum pixel_read_direction direction)
  139. {
  140. switch (direction) {
  141. case READ_BOTTOM_TO_TOP:
  142. case READ_TOP_TO_BOTTOM:
  143. return format->vsub;
  144. case READ_RIGHT_TO_LEFT:
  145. case READ_LEFT_TO_RIGHT:
  146. return format->hsub;
  147. }
  148. WARN_ONCE(true, "Invalid direction for pixel reading: %d\n", direction);
  149. return 1;
  150. }
  151. /**
  152. * get_subsampling_offset() - An offset for keeping the chroma siting consistent regardless of
  153. * x_start and y_start values
  154. *
  155. * @direction: direction of the reading to properly compute this offset
  156. * @x_start: x coordinate of the starting point of the readed line
  157. * @y_start: y coordinate of the starting point of the readed line
  158. */
  159. static int get_subsampling_offset(enum pixel_read_direction direction, int x_start, int y_start)
  160. {
  161. switch (direction) {
  162. case READ_BOTTOM_TO_TOP:
  163. return -y_start - 1;
  164. case READ_TOP_TO_BOTTOM:
  165. return y_start;
  166. case READ_RIGHT_TO_LEFT:
  167. return -x_start - 1;
  168. case READ_LEFT_TO_RIGHT:
  169. return x_start;
  170. }
  171. WARN_ONCE(true, "Invalid direction for pixel reading: %d\n", direction);
  172. return 0;
  173. }
  174. /*
  175. * The following functions take pixel data (a, r, g, b, pixel, ...) and convert them to
  176. * &struct pixel_argb_u16
  177. *
  178. * They are used in the `read_line`s functions to avoid duplicate work for some pixel formats.
  179. */
  180. static struct pixel_argb_u16 argb_u16_from_u8888(u8 a, u8 r, u8 g, u8 b)
  181. {
  182. struct pixel_argb_u16 out_pixel;
  183. /*
  184. * The 257 is the "conversion ratio". This number is obtained by the
  185. * (2^16 - 1) / (2^8 - 1) division. Which, in this case, tries to get
  186. * the best color value in a pixel format with more possibilities.
  187. * A similar idea applies to others RGB color conversions.
  188. */
  189. out_pixel.a = (u16)a * 257;
  190. out_pixel.r = (u16)r * 257;
  191. out_pixel.g = (u16)g * 257;
  192. out_pixel.b = (u16)b * 257;
  193. return out_pixel;
  194. }
  195. static struct pixel_argb_u16 argb_u16_from_u16161616(u16 a, u16 r, u16 g, u16 b)
  196. {
  197. struct pixel_argb_u16 out_pixel;
  198. out_pixel.a = a;
  199. out_pixel.r = r;
  200. out_pixel.g = g;
  201. out_pixel.b = b;
  202. return out_pixel;
  203. }
  204. static struct pixel_argb_u16 argb_u16_from_le16161616(__le16 a, __le16 r, __le16 g, __le16 b)
  205. {
  206. return argb_u16_from_u16161616(le16_to_cpu(a), le16_to_cpu(r), le16_to_cpu(g),
  207. le16_to_cpu(b));
  208. }
  209. static struct pixel_argb_u16 argb_u16_from_RGB565(const __le16 *pixel)
  210. {
  211. struct pixel_argb_u16 out_pixel;
  212. s64 fp_rb_ratio = drm_fixp_div(drm_int2fixp(65535), drm_int2fixp(31));
  213. s64 fp_g_ratio = drm_fixp_div(drm_int2fixp(65535), drm_int2fixp(63));
  214. u16 rgb_565 = le16_to_cpu(*pixel);
  215. s64 fp_r = drm_int2fixp((rgb_565 >> 11) & 0x1f);
  216. s64 fp_g = drm_int2fixp((rgb_565 >> 5) & 0x3f);
  217. s64 fp_b = drm_int2fixp(rgb_565 & 0x1f);
  218. out_pixel.a = (u16)0xffff;
  219. out_pixel.r = drm_fixp2int_round(drm_fixp_mul(fp_r, fp_rb_ratio));
  220. out_pixel.g = drm_fixp2int_round(drm_fixp_mul(fp_g, fp_g_ratio));
  221. out_pixel.b = drm_fixp2int_round(drm_fixp_mul(fp_b, fp_rb_ratio));
  222. return out_pixel;
  223. }
  224. static struct pixel_argb_u16 argb_u16_from_gray8(u8 gray)
  225. {
  226. return argb_u16_from_u8888(255, gray, gray, gray);
  227. }
  228. static struct pixel_argb_u16 argb_u16_from_grayu16(u16 gray)
  229. {
  230. return argb_u16_from_u16161616(0xFFFF, gray, gray, gray);
  231. }
  232. static struct pixel_argb_u16 argb_u16_from_BGR565(const __le16 *pixel)
  233. {
  234. struct pixel_argb_u16 out_pixel;
  235. out_pixel = argb_u16_from_RGB565(pixel);
  236. swap(out_pixel.r, out_pixel.b);
  237. return out_pixel;
  238. }
  239. VISIBLE_IF_KUNIT
  240. struct pixel_argb_u16 argb_u16_from_yuv161616(const struct conversion_matrix *matrix,
  241. u16 y, u16 channel_1, u16 channel_2)
  242. {
  243. u16 r, g, b;
  244. s64 fp_y, fp_channel_1, fp_channel_2;
  245. s64 fp_r, fp_g, fp_b;
  246. fp_y = drm_int2fixp((int)y - matrix->y_offset * 257);
  247. fp_channel_1 = drm_int2fixp((int)channel_1 - 128 * 257);
  248. fp_channel_2 = drm_int2fixp((int)channel_2 - 128 * 257);
  249. fp_r = drm_fixp_mul(matrix->matrix[0][0], fp_y) +
  250. drm_fixp_mul(matrix->matrix[0][1], fp_channel_1) +
  251. drm_fixp_mul(matrix->matrix[0][2], fp_channel_2);
  252. fp_g = drm_fixp_mul(matrix->matrix[1][0], fp_y) +
  253. drm_fixp_mul(matrix->matrix[1][1], fp_channel_1) +
  254. drm_fixp_mul(matrix->matrix[1][2], fp_channel_2);
  255. fp_b = drm_fixp_mul(matrix->matrix[2][0], fp_y) +
  256. drm_fixp_mul(matrix->matrix[2][1], fp_channel_1) +
  257. drm_fixp_mul(matrix->matrix[2][2], fp_channel_2);
  258. fp_r = drm_fixp2int_round(fp_r);
  259. fp_g = drm_fixp2int_round(fp_g);
  260. fp_b = drm_fixp2int_round(fp_b);
  261. r = clamp(fp_r, 0, 0xffff);
  262. g = clamp(fp_g, 0, 0xffff);
  263. b = clamp(fp_b, 0, 0xffff);
  264. return argb_u16_from_u16161616(0xffff, r, g, b);
  265. }
  266. EXPORT_SYMBOL_IF_KUNIT(argb_u16_from_yuv161616);
  267. /**
  268. * READ_LINE() - Generic generator for a read_line function which can be used for format with one
  269. * plane and a block_h == block_w == 1.
  270. *
  271. * @function_name: Function name to generate
  272. * @pixel_name: Temporary pixel name used in the @__VA_ARGS__ parameters
  273. * @pixel_type: Used to specify the type you want to cast the pixel pointer
  274. * @callback: Callback to call for each pixels. This fonction should take @__VA_ARGS__ as parameter
  275. * and return a pixel_argb_u16
  276. * __VA_ARGS__: Argument to pass inside the callback. You can use @pixel_name to access current
  277. * pixel.
  278. */
  279. #define READ_LINE(function_name, pixel_name, pixel_type, callback, ...) \
  280. static void function_name(const struct vkms_plane_state *plane, int x_start, \
  281. int y_start, enum pixel_read_direction direction, int count, \
  282. struct pixel_argb_u16 out_pixel[]) \
  283. { \
  284. struct pixel_argb_u16 *end = out_pixel + count; \
  285. int step = get_block_step_bytes(plane->frame_info->fb, direction, 0); \
  286. u8 *src_pixels; \
  287. \
  288. packed_pixels_addr_1x1(plane->frame_info, x_start, y_start, 0, &src_pixels); \
  289. \
  290. while (out_pixel < end) { \
  291. pixel_type *(pixel_name) = (pixel_type *)src_pixels; \
  292. *out_pixel = (callback)(__VA_ARGS__); \
  293. out_pixel += 1; \
  294. src_pixels += step; \
  295. } \
  296. }
  297. /**
  298. * READ_LINE_ARGB8888() - Generic generator for ARGB8888 formats.
  299. * The pixel type used is u8, so pixel_name[0]..pixel_name[n] are the n components of the pixel.
  300. *
  301. * @function_name: Function name to generate
  302. * @pixel_name: temporary pixel to use in @a, @r, @g and @b parameters
  303. * @a: alpha value
  304. * @r: red value
  305. * @g: green value
  306. * @b: blue value
  307. */
  308. #define READ_LINE_ARGB8888(function_name, pixel_name, a, r, g, b) \
  309. READ_LINE(function_name, pixel_name, u8, argb_u16_from_u8888, a, r, g, b)
  310. /**
  311. * READ_LINE_le16161616() - Generic generator for ARGB16161616 formats.
  312. * The pixel type used is u16, so pixel_name[0]..pixel_name[n] are the n components of the pixel.
  313. *
  314. * @function_name: Function name to generate
  315. * @pixel_name: temporary pixel to use in @a, @r, @g and @b parameters
  316. * @a: alpha value
  317. * @r: red value
  318. * @g: green value
  319. * @b: blue value
  320. */
  321. #define READ_LINE_le16161616(function_name, pixel_name, a, r, g, b) \
  322. READ_LINE(function_name, pixel_name, __le16, argb_u16_from_le16161616, a, r, g, b)
  323. /*
  324. * The following functions are read_line function for each pixel format supported by VKMS.
  325. *
  326. * They read a line starting at the point @x_start,@y_start following the @direction. The result
  327. * is stored in @out_pixel and in a 64 bits format, see struct pixel_argb_u16.
  328. *
  329. * These functions are very repetitive, but the innermost pixel loops must be kept inside these
  330. * functions for performance reasons. Some benchmarking was done in [1] where having the innermost
  331. * loop factored out of these functions showed a slowdown by a factor of three.
  332. *
  333. * [1]: https://lore.kernel.org/dri-devel/d258c8dc-78e9-4509-9037-a98f7f33b3a3@riseup.net/
  334. */
  335. static void Rx_read_line(const struct vkms_plane_state *plane, int x_start,
  336. int y_start, enum pixel_read_direction direction, int count,
  337. struct pixel_argb_u16 out_pixel[])
  338. {
  339. struct pixel_argb_u16 *end = out_pixel + count;
  340. int bits_per_pixel = drm_format_info_bpp(plane->frame_info->fb->format, 0);
  341. u8 *src_pixels;
  342. int rem_x, rem_y;
  343. WARN_ONCE(drm_format_info_block_height(plane->frame_info->fb->format, 0) != 1,
  344. "%s() only support formats with block_h == 1", __func__);
  345. packed_pixels_addr(plane->frame_info, x_start, y_start, 0, &src_pixels, &rem_x, &rem_y);
  346. int bit_offset = (8 - bits_per_pixel) - rem_x * bits_per_pixel;
  347. int step = get_block_step_bytes(plane->frame_info->fb, direction, 0);
  348. int mask = (0x1 << bits_per_pixel) - 1;
  349. int lum_per_level = 0xFFFF / mask;
  350. if (direction == READ_LEFT_TO_RIGHT || direction == READ_RIGHT_TO_LEFT) {
  351. int restart_bit_offset;
  352. int step_bit_offset;
  353. if (direction == READ_LEFT_TO_RIGHT) {
  354. restart_bit_offset = 8 - bits_per_pixel;
  355. step_bit_offset = -bits_per_pixel;
  356. } else {
  357. restart_bit_offset = 0;
  358. step_bit_offset = bits_per_pixel;
  359. }
  360. while (out_pixel < end) {
  361. u8 val = ((*src_pixels) >> bit_offset) & mask;
  362. *out_pixel = argb_u16_from_grayu16((int)val * lum_per_level);
  363. bit_offset += step_bit_offset;
  364. if (bit_offset < 0 || 8 <= bit_offset) {
  365. bit_offset = restart_bit_offset;
  366. src_pixels += step;
  367. }
  368. out_pixel += 1;
  369. }
  370. } else if (direction == READ_TOP_TO_BOTTOM || direction == READ_BOTTOM_TO_TOP) {
  371. while (out_pixel < end) {
  372. u8 val = (*src_pixels >> bit_offset) & mask;
  373. *out_pixel = argb_u16_from_grayu16((int)val * lum_per_level);
  374. src_pixels += step;
  375. out_pixel += 1;
  376. }
  377. }
  378. }
  379. static void R1_read_line(const struct vkms_plane_state *plane, int x_start,
  380. int y_start, enum pixel_read_direction direction, int count,
  381. struct pixel_argb_u16 out_pixel[])
  382. {
  383. Rx_read_line(plane, x_start, y_start, direction, count, out_pixel);
  384. }
  385. static void R2_read_line(const struct vkms_plane_state *plane, int x_start,
  386. int y_start, enum pixel_read_direction direction, int count,
  387. struct pixel_argb_u16 out_pixel[])
  388. {
  389. Rx_read_line(plane, x_start, y_start, direction, count, out_pixel);
  390. }
  391. static void R4_read_line(const struct vkms_plane_state *plane, int x_start,
  392. int y_start, enum pixel_read_direction direction, int count,
  393. struct pixel_argb_u16 out_pixel[])
  394. {
  395. Rx_read_line(plane, x_start, y_start, direction, count, out_pixel);
  396. }
  397. READ_LINE_ARGB8888(XRGB8888_read_line, px, 0xFF, px[2], px[1], px[0])
  398. READ_LINE_ARGB8888(XBGR8888_read_line, px, 0xFF, px[0], px[1], px[2])
  399. READ_LINE_ARGB8888(ARGB8888_read_line, px, px[3], px[2], px[1], px[0])
  400. READ_LINE_ARGB8888(ABGR8888_read_line, px, px[3], px[0], px[1], px[2])
  401. READ_LINE_ARGB8888(RGBA8888_read_line, px, px[0], px[3], px[2], px[1])
  402. READ_LINE_ARGB8888(BGRA8888_read_line, px, px[0], px[1], px[2], px[3])
  403. READ_LINE_ARGB8888(RGB888_read_line, px, 0xFF, px[2], px[1], px[0])
  404. READ_LINE_ARGB8888(BGR888_read_line, px, 0xFF, px[0], px[1], px[2])
  405. READ_LINE_le16161616(ARGB16161616_read_line, px, px[3], px[2], px[1], px[0])
  406. READ_LINE_le16161616(ABGR16161616_read_line, px, px[3], px[0], px[1], px[2])
  407. READ_LINE_le16161616(XRGB16161616_read_line, px, cpu_to_le16(0xFFFF), px[2], px[1], px[0])
  408. READ_LINE_le16161616(XBGR16161616_read_line, px, cpu_to_le16(0xFFFF), px[0], px[1], px[2])
  409. READ_LINE(RGB565_read_line, px, __le16, argb_u16_from_RGB565, px)
  410. READ_LINE(BGR565_read_line, px, __le16, argb_u16_from_BGR565, px)
  411. READ_LINE(R8_read_line, px, u8, argb_u16_from_gray8, *px)
  412. /*
  413. * This callback can be used for YUV formats where U and V values are
  414. * stored in the same plane (often called semi-planar formats). It will
  415. * correctly handle subsampling as described in the drm_format_info of the plane.
  416. *
  417. * The conversion matrix stored in the @plane is used to:
  418. * - Apply the correct color range and encoding
  419. * - Convert YUV and YVU with the same function (a column swap is needed when setting up
  420. * plane->conversion_matrix)
  421. */
  422. /**
  423. * READ_LINE_YUV_SEMIPLANAR() - Generic generator for a read_line function which can be used for yuv
  424. * formats with two planes and block_w == block_h == 1.
  425. *
  426. * @function_name: Function name to generate
  427. * @pixel_1_name: temporary pixel name for the first plane used in the @__VA_ARGS__ parameters
  428. * @pixel_2_name: temporary pixel name for the second plane used in the @__VA_ARGS__ parameters
  429. * @pixel_1_type: Used to specify the type you want to cast the pixel pointer on the plane 1
  430. * @pixel_2_type: Used to specify the type you want to cast the pixel pointer on the plane 2
  431. * @callback: Callback to call for each pixels. This function should take
  432. * (struct conversion_matrix*, @__VA_ARGS__) as parameter and return a pixel_argb_u16
  433. * __VA_ARGS__: Argument to pass inside the callback. You can use @pixel_1_name and @pixel_2_name
  434. * to access current pixel values
  435. */
  436. #define READ_LINE_YUV_SEMIPLANAR(function_name, pixel_1_name, pixel_2_name, pixel_1_type, \
  437. pixel_2_type, callback, ...) \
  438. static void function_name(const struct vkms_plane_state *plane, int x_start, \
  439. int y_start, enum pixel_read_direction direction, int count, \
  440. struct pixel_argb_u16 out_pixel[]) \
  441. { \
  442. u8 *plane_1; \
  443. u8 *plane_2; \
  444. \
  445. packed_pixels_addr_1x1(plane->frame_info, x_start, y_start, 0, \
  446. &plane_1); \
  447. packed_pixels_addr_1x1(plane->frame_info, \
  448. x_start / plane->frame_info->fb->format->hsub, \
  449. y_start / plane->frame_info->fb->format->vsub, 1, \
  450. &plane_2); \
  451. int step_1 = get_block_step_bytes(plane->frame_info->fb, direction, 0); \
  452. int step_2 = get_block_step_bytes(plane->frame_info->fb, direction, 1); \
  453. int subsampling = get_subsampling(plane->frame_info->fb->format, direction); \
  454. int subsampling_offset = get_subsampling_offset(direction, x_start, y_start); \
  455. const struct conversion_matrix *conversion_matrix = &plane->conversion_matrix; \
  456. \
  457. for (int i = 0; i < count; i++) { \
  458. pixel_1_type *(pixel_1_name) = (pixel_1_type *)plane_1; \
  459. pixel_2_type *(pixel_2_name) = (pixel_2_type *)plane_2; \
  460. *out_pixel = (callback)(conversion_matrix, __VA_ARGS__); \
  461. out_pixel += 1; \
  462. plane_1 += step_1; \
  463. if ((i + subsampling_offset + 1) % subsampling == 0) \
  464. plane_2 += step_2; \
  465. } \
  466. }
  467. READ_LINE_YUV_SEMIPLANAR(YUV888_semiplanar_read_line, y, uv, u8, u8, argb_u16_from_yuv161616,
  468. y[0] * 257, uv[0] * 257, uv[1] * 257)
  469. READ_LINE_YUV_SEMIPLANAR(YUV161616_semiplanar_read_line, y, uv, u16, u16, argb_u16_from_yuv161616,
  470. y[0], uv[0], uv[1])
  471. /*
  472. * This callback can be used for YUV format where each color component is
  473. * stored in a different plane (often called planar formats). It will
  474. * correctly handle subsampling as described in the drm_format_info of the plane.
  475. *
  476. * The conversion matrix stored in the @plane is used to:
  477. * - Apply the correct color range and encoding
  478. * - Convert YUV and YVU with the same function (a column swap is needed when setting up
  479. * plane->conversion_matrix)
  480. */
  481. static void planar_yuv_read_line(const struct vkms_plane_state *plane, int x_start,
  482. int y_start, enum pixel_read_direction direction, int count,
  483. struct pixel_argb_u16 out_pixel[])
  484. {
  485. u8 *y_plane;
  486. u8 *channel_1_plane;
  487. u8 *channel_2_plane;
  488. packed_pixels_addr_1x1(plane->frame_info, x_start, y_start, 0,
  489. &y_plane);
  490. packed_pixels_addr_1x1(plane->frame_info,
  491. x_start / plane->frame_info->fb->format->hsub,
  492. y_start / plane->frame_info->fb->format->vsub, 1,
  493. &channel_1_plane);
  494. packed_pixels_addr_1x1(plane->frame_info,
  495. x_start / plane->frame_info->fb->format->hsub,
  496. y_start / plane->frame_info->fb->format->vsub, 2,
  497. &channel_2_plane);
  498. int step_y = get_block_step_bytes(plane->frame_info->fb, direction, 0);
  499. int step_channel_1 = get_block_step_bytes(plane->frame_info->fb, direction, 1);
  500. int step_channel_2 = get_block_step_bytes(plane->frame_info->fb, direction, 2);
  501. int subsampling = get_subsampling(plane->frame_info->fb->format, direction);
  502. int subsampling_offset = get_subsampling_offset(direction, x_start, y_start);
  503. const struct conversion_matrix *conversion_matrix = &plane->conversion_matrix;
  504. for (int i = 0; i < count; i++) {
  505. *out_pixel = argb_u16_from_yuv161616(conversion_matrix,
  506. *y_plane * 257, *channel_1_plane * 257,
  507. *channel_2_plane * 257);
  508. out_pixel += 1;
  509. y_plane += step_y;
  510. if ((i + subsampling_offset + 1) % subsampling == 0) {
  511. channel_1_plane += step_channel_1;
  512. channel_2_plane += step_channel_2;
  513. }
  514. }
  515. }
  516. /*
  517. * The following functions take one &struct pixel_argb_u16 and convert it to a specific format.
  518. * The result is stored in @out_pixel.
  519. *
  520. * They are used in vkms_writeback_row() to convert and store a pixel from the src_buffer to
  521. * the writeback buffer.
  522. */
  523. static void argb_u16_to_ARGB8888(u8 *out_pixel, const struct pixel_argb_u16 *in_pixel)
  524. {
  525. /*
  526. * This sequence below is important because the format's byte order is
  527. * in little-endian. In the case of the ARGB8888 the memory is
  528. * organized this way:
  529. *
  530. * | Addr | = blue channel
  531. * | Addr + 1 | = green channel
  532. * | Addr + 2 | = Red channel
  533. * | Addr + 3 | = Alpha channel
  534. */
  535. out_pixel[3] = DIV_ROUND_CLOSEST(in_pixel->a, 257);
  536. out_pixel[2] = DIV_ROUND_CLOSEST(in_pixel->r, 257);
  537. out_pixel[1] = DIV_ROUND_CLOSEST(in_pixel->g, 257);
  538. out_pixel[0] = DIV_ROUND_CLOSEST(in_pixel->b, 257);
  539. }
  540. static void argb_u16_to_XRGB8888(u8 *out_pixel, const struct pixel_argb_u16 *in_pixel)
  541. {
  542. out_pixel[3] = 0xff;
  543. out_pixel[2] = DIV_ROUND_CLOSEST(in_pixel->r, 257);
  544. out_pixel[1] = DIV_ROUND_CLOSEST(in_pixel->g, 257);
  545. out_pixel[0] = DIV_ROUND_CLOSEST(in_pixel->b, 257);
  546. }
  547. static void argb_u16_to_ABGR8888(u8 *out_pixel, const struct pixel_argb_u16 *in_pixel)
  548. {
  549. out_pixel[3] = DIV_ROUND_CLOSEST(in_pixel->a, 257);
  550. out_pixel[2] = DIV_ROUND_CLOSEST(in_pixel->b, 257);
  551. out_pixel[1] = DIV_ROUND_CLOSEST(in_pixel->g, 257);
  552. out_pixel[0] = DIV_ROUND_CLOSEST(in_pixel->r, 257);
  553. }
  554. static void argb_u16_to_ARGB16161616(u8 *out_pixel, const struct pixel_argb_u16 *in_pixel)
  555. {
  556. __le16 *pixel = (__le16 *)out_pixel;
  557. pixel[3] = cpu_to_le16(in_pixel->a);
  558. pixel[2] = cpu_to_le16(in_pixel->r);
  559. pixel[1] = cpu_to_le16(in_pixel->g);
  560. pixel[0] = cpu_to_le16(in_pixel->b);
  561. }
  562. static void argb_u16_to_XRGB16161616(u8 *out_pixel, const struct pixel_argb_u16 *in_pixel)
  563. {
  564. __le16 *pixel = (__le16 *)out_pixel;
  565. pixel[3] = cpu_to_le16(0xffff);
  566. pixel[2] = cpu_to_le16(in_pixel->r);
  567. pixel[1] = cpu_to_le16(in_pixel->g);
  568. pixel[0] = cpu_to_le16(in_pixel->b);
  569. }
  570. static void argb_u16_to_RGB565(u8 *out_pixel, const struct pixel_argb_u16 *in_pixel)
  571. {
  572. __le16 *pixel = (__le16 *)out_pixel;
  573. s64 fp_rb_ratio = drm_fixp_div(drm_int2fixp(65535), drm_int2fixp(31));
  574. s64 fp_g_ratio = drm_fixp_div(drm_int2fixp(65535), drm_int2fixp(63));
  575. s64 fp_r = drm_int2fixp(in_pixel->r);
  576. s64 fp_g = drm_int2fixp(in_pixel->g);
  577. s64 fp_b = drm_int2fixp(in_pixel->b);
  578. u16 r = drm_fixp2int(drm_fixp_div(fp_r, fp_rb_ratio));
  579. u16 g = drm_fixp2int(drm_fixp_div(fp_g, fp_g_ratio));
  580. u16 b = drm_fixp2int(drm_fixp_div(fp_b, fp_rb_ratio));
  581. *pixel = cpu_to_le16(r << 11 | g << 5 | b);
  582. }
  583. /**
  584. * vkms_writeback_row() - Generic loop for all supported writeback format. It is executed just
  585. * after the blending to write a line in the writeback buffer.
  586. *
  587. * @wb: Job where to insert the final image
  588. * @src_buffer: Line to write
  589. * @y: Row to write in the writeback buffer
  590. */
  591. void vkms_writeback_row(struct vkms_writeback_job *wb,
  592. const struct line_buffer *src_buffer, int y)
  593. {
  594. struct vkms_frame_info *frame_info = &wb->wb_frame_info;
  595. int x_dst = frame_info->dst.x1;
  596. u8 *dst_pixels;
  597. int rem_x, rem_y;
  598. packed_pixels_addr(frame_info, x_dst, y, 0, &dst_pixels, &rem_x, &rem_y);
  599. struct pixel_argb_u16 *in_pixels = src_buffer->pixels;
  600. int x_limit = min_t(size_t, drm_rect_width(&frame_info->dst), src_buffer->n_pixels);
  601. for (size_t x = 0; x < x_limit; x++, dst_pixels += frame_info->fb->format->cpp[0])
  602. wb->pixel_write(dst_pixels, &in_pixels[x]);
  603. }
  604. /**
  605. * get_pixel_read_line_function() - Retrieve the correct read_line function for a specific
  606. * format. The returned pointer is NULL for unsupported pixel formats. The caller must ensure that
  607. * the pointer is valid before using it in a vkms_plane_state.
  608. *
  609. * @format: DRM_FORMAT_* value for which to obtain a conversion function (see [drm_fourcc.h])
  610. */
  611. pixel_read_line_t get_pixel_read_line_function(u32 format)
  612. {
  613. switch (format) {
  614. case DRM_FORMAT_ARGB8888:
  615. return &ARGB8888_read_line;
  616. case DRM_FORMAT_ABGR8888:
  617. return &ABGR8888_read_line;
  618. case DRM_FORMAT_BGRA8888:
  619. return &BGRA8888_read_line;
  620. case DRM_FORMAT_RGBA8888:
  621. return &RGBA8888_read_line;
  622. case DRM_FORMAT_XRGB8888:
  623. return &XRGB8888_read_line;
  624. case DRM_FORMAT_XBGR8888:
  625. return &XBGR8888_read_line;
  626. case DRM_FORMAT_RGB888:
  627. return &RGB888_read_line;
  628. case DRM_FORMAT_BGR888:
  629. return &BGR888_read_line;
  630. case DRM_FORMAT_ARGB16161616:
  631. return &ARGB16161616_read_line;
  632. case DRM_FORMAT_ABGR16161616:
  633. return &ABGR16161616_read_line;
  634. case DRM_FORMAT_XRGB16161616:
  635. return &XRGB16161616_read_line;
  636. case DRM_FORMAT_XBGR16161616:
  637. return &XBGR16161616_read_line;
  638. case DRM_FORMAT_RGB565:
  639. return &RGB565_read_line;
  640. case DRM_FORMAT_BGR565:
  641. return &BGR565_read_line;
  642. case DRM_FORMAT_NV12:
  643. case DRM_FORMAT_NV16:
  644. case DRM_FORMAT_NV24:
  645. case DRM_FORMAT_NV21:
  646. case DRM_FORMAT_NV61:
  647. case DRM_FORMAT_NV42:
  648. return &YUV888_semiplanar_read_line;
  649. case DRM_FORMAT_P010:
  650. case DRM_FORMAT_P012:
  651. case DRM_FORMAT_P016:
  652. return &YUV161616_semiplanar_read_line;
  653. case DRM_FORMAT_YUV420:
  654. case DRM_FORMAT_YUV422:
  655. case DRM_FORMAT_YUV444:
  656. case DRM_FORMAT_YVU420:
  657. case DRM_FORMAT_YVU422:
  658. case DRM_FORMAT_YVU444:
  659. return &planar_yuv_read_line;
  660. case DRM_FORMAT_R1:
  661. return &R1_read_line;
  662. case DRM_FORMAT_R2:
  663. return &R2_read_line;
  664. case DRM_FORMAT_R4:
  665. return &R4_read_line;
  666. case DRM_FORMAT_R8:
  667. return &R8_read_line;
  668. default:
  669. /*
  670. * This is a bug in vkms_plane_atomic_check(). All the supported
  671. * format must:
  672. * - Be listed in vkms_formats in vkms_plane.c
  673. * - Have a pixel_read callback defined here
  674. */
  675. pr_err("Pixel format %p4cc is not supported by VKMS planes. This is a kernel bug, atomic check must forbid this configuration.\n",
  676. &format);
  677. BUG();
  678. }
  679. }
  680. /*
  681. * Those matrices were generated using the colour python framework
  682. *
  683. * Below are the function calls used to generate each matrix, go to
  684. * https://colour.readthedocs.io/en/develop/generated/colour.matrix_YCbCr.html
  685. * for more info:
  686. *
  687. * numpy.around(colour.matrix_YCbCr(K=colour.WEIGHTS_YCBCR["ITU-R BT.601"],
  688. * is_legal = False,
  689. * bits = 8) * 2**32).astype(int)
  690. */
  691. static const struct conversion_matrix no_operation = {
  692. .matrix = {
  693. { 4294967296, 0, 0, },
  694. { 0, 4294967296, 0, },
  695. { 0, 0, 4294967296, },
  696. },
  697. .y_offset = 0,
  698. };
  699. static const struct conversion_matrix yuv_bt601_full = {
  700. .matrix = {
  701. { 4294967296, 0, 6021544149 },
  702. { 4294967296, -1478054095, -3067191994 },
  703. { 4294967296, 7610682049, 0 },
  704. },
  705. .y_offset = 0,
  706. };
  707. /*
  708. * numpy.around(colour.matrix_YCbCr(K=colour.WEIGHTS_YCBCR["ITU-R BT.601"],
  709. * is_legal = True,
  710. * bits = 8) * 2**32).astype(int)
  711. */
  712. static const struct conversion_matrix yuv_bt601_limited = {
  713. .matrix = {
  714. { 5020601039, 0, 6881764740 },
  715. { 5020601039, -1689204679, -3505362278 },
  716. { 5020601039, 8697922339, 0 },
  717. },
  718. .y_offset = 16,
  719. };
  720. /*
  721. * numpy.around(colour.matrix_YCbCr(K=colour.WEIGHTS_YCBCR["ITU-R BT.709"],
  722. * is_legal = False,
  723. * bits = 8) * 2**32).astype(int)
  724. */
  725. static const struct conversion_matrix yuv_bt709_full = {
  726. .matrix = {
  727. { 4294967296, 0, 6763714498 },
  728. { 4294967296, -804551626, -2010578443 },
  729. { 4294967296, 7969741314, 0 },
  730. },
  731. .y_offset = 0,
  732. };
  733. /*
  734. * numpy.around(colour.matrix_YCbCr(K=colour.WEIGHTS_YCBCR["ITU-R BT.709"],
  735. * is_legal = True,
  736. * bits = 8) * 2**32).astype(int)
  737. */
  738. static const struct conversion_matrix yuv_bt709_limited = {
  739. .matrix = {
  740. { 5020601039, 0, 7729959424 },
  741. { 5020601039, -919487572, -2297803934 },
  742. { 5020601039, 9108275786, 0 },
  743. },
  744. .y_offset = 16,
  745. };
  746. /*
  747. * numpy.around(colour.matrix_YCbCr(K=colour.WEIGHTS_YCBCR["ITU-R BT.2020"],
  748. * is_legal = False,
  749. * bits = 8) * 2**32).astype(int)
  750. */
  751. static const struct conversion_matrix yuv_bt2020_full = {
  752. .matrix = {
  753. { 4294967296, 0, 6333358775 },
  754. { 4294967296, -706750298, -2453942994 },
  755. { 4294967296, 8080551471, 0 },
  756. },
  757. .y_offset = 0,
  758. };
  759. /*
  760. * numpy.around(colour.matrix_YCbCr(K=colour.WEIGHTS_YCBCR["ITU-R BT.2020"],
  761. * is_legal = True,
  762. * bits = 8) * 2**32).astype(int)
  763. */
  764. static const struct conversion_matrix yuv_bt2020_limited = {
  765. .matrix = {
  766. { 5020601039, 0, 7238124312 },
  767. { 5020601039, -807714626, -2804506279 },
  768. { 5020601039, 9234915964, 0 },
  769. },
  770. .y_offset = 16,
  771. };
  772. /**
  773. * swap_uv_columns() - Swap u and v column of a given matrix
  774. *
  775. * @matrix: Matrix in which column are swapped
  776. */
  777. static void swap_uv_columns(struct conversion_matrix *matrix)
  778. {
  779. swap(matrix->matrix[0][2], matrix->matrix[0][1]);
  780. swap(matrix->matrix[1][2], matrix->matrix[1][1]);
  781. swap(matrix->matrix[2][2], matrix->matrix[2][1]);
  782. }
  783. /**
  784. * get_conversion_matrix_to_argb_u16() - Retrieve the correct yuv to rgb conversion matrix for a
  785. * given encoding and range.
  786. *
  787. * @format: DRM_FORMAT_* value for which to obtain a conversion function (see [drm_fourcc.h])
  788. * @encoding: DRM_COLOR_* value for which to obtain a conversion matrix
  789. * @range: DRM_COLOR_*_RANGE value for which to obtain a conversion matrix
  790. * @matrix: Pointer to store the value into
  791. */
  792. void get_conversion_matrix_to_argb_u16(u32 format,
  793. enum drm_color_encoding encoding,
  794. enum drm_color_range range,
  795. struct conversion_matrix *matrix)
  796. {
  797. const struct conversion_matrix *matrix_to_copy;
  798. bool limited_range;
  799. switch (range) {
  800. case DRM_COLOR_YCBCR_LIMITED_RANGE:
  801. limited_range = true;
  802. break;
  803. case DRM_COLOR_YCBCR_FULL_RANGE:
  804. limited_range = false;
  805. break;
  806. case DRM_COLOR_RANGE_MAX:
  807. limited_range = false;
  808. WARN_ONCE(true, "The requested range is not supported.");
  809. break;
  810. }
  811. switch (encoding) {
  812. case DRM_COLOR_YCBCR_BT601:
  813. matrix_to_copy = limited_range ? &yuv_bt601_limited :
  814. &yuv_bt601_full;
  815. break;
  816. case DRM_COLOR_YCBCR_BT709:
  817. matrix_to_copy = limited_range ? &yuv_bt709_limited :
  818. &yuv_bt709_full;
  819. break;
  820. case DRM_COLOR_YCBCR_BT2020:
  821. matrix_to_copy = limited_range ? &yuv_bt2020_limited :
  822. &yuv_bt2020_full;
  823. break;
  824. case DRM_COLOR_ENCODING_MAX:
  825. matrix_to_copy = &no_operation;
  826. WARN_ONCE(true, "The requested encoding is not supported.");
  827. break;
  828. }
  829. memcpy(matrix, matrix_to_copy, sizeof(*matrix_to_copy));
  830. switch (format) {
  831. case DRM_FORMAT_YVU420:
  832. case DRM_FORMAT_YVU422:
  833. case DRM_FORMAT_YVU444:
  834. case DRM_FORMAT_NV21:
  835. case DRM_FORMAT_NV61:
  836. case DRM_FORMAT_NV42:
  837. swap_uv_columns(matrix);
  838. break;
  839. default:
  840. break;
  841. }
  842. }
  843. EXPORT_SYMBOL(get_conversion_matrix_to_argb_u16);
  844. /**
  845. * get_pixel_write_function() - Retrieve the correct write_pixel function for a specific format.
  846. * The returned pointer is NULL for unsupported pixel formats. The caller must ensure that the
  847. * pointer is valid before using it in a vkms_writeback_job.
  848. *
  849. * @format: DRM_FORMAT_* value for which to obtain a conversion function (see [drm_fourcc.h])
  850. */
  851. pixel_write_t get_pixel_write_function(u32 format)
  852. {
  853. switch (format) {
  854. case DRM_FORMAT_ARGB8888:
  855. return &argb_u16_to_ARGB8888;
  856. case DRM_FORMAT_XRGB8888:
  857. return &argb_u16_to_XRGB8888;
  858. case DRM_FORMAT_ABGR8888:
  859. return &argb_u16_to_ABGR8888;
  860. case DRM_FORMAT_ARGB16161616:
  861. return &argb_u16_to_ARGB16161616;
  862. case DRM_FORMAT_XRGB16161616:
  863. return &argb_u16_to_XRGB16161616;
  864. case DRM_FORMAT_RGB565:
  865. return &argb_u16_to_RGB565;
  866. default:
  867. /*
  868. * This is a bug in vkms_writeback_atomic_check. All the supported
  869. * format must:
  870. * - Be listed in vkms_wb_formats in vkms_writeback.c
  871. * - Have a pixel_write callback defined here
  872. */
  873. pr_err("Pixel format %p4cc is not supported by VKMS writeback. This is a kernel bug, atomic check must forbid this configuration.\n",
  874. &format);
  875. BUG();
  876. }
  877. }