Skip to content

Commit cd3afe8

Browse files
committed
Basic support for 3-way buffer blitting
Fast-paths haven't been implemented yet, and there are probably some bugs in there, and the linear-stretching impl isn't done yet, either. But semantically speaking, the impl is there.
1 parent 24d8b60 commit cd3afe8

File tree

20 files changed

+3128
-1357
lines changed

20 files changed

+3128
-1357
lines changed

kos/cpp.hint

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2868,3 +2868,7 @@
28682868
#define DEFINE_PIXEL64_IO_WRAPPERS(...)
28692869
#define DEFINE_PIXEL64_IO_WRAPPERS__WITH_PREFIX(...)
28702870
#define DEFINE_PIXEL64_IO_WRAPPERS__WITH_SUFFIX(...)
2871+
#define DECLARE_libvideo_swblitter3__blend_FOO(n,...) \
2872+
video_color_t libvideo_swblitter3__blend_##n(struct video_blitter3 const*__restrict self,video_color_t dst,video_color_t src);
2873+
#define DEFINE_libvideo_swblitter3__blend_FOO(n,...) \
2874+
video_color_t libvideo_swblitter3__blend_##n(struct video_blitter3 const*__restrict self,video_color_t dst,video_color_t src){}

kos/include/libvideo/gfx/gfx.h

Lines changed: 179 additions & 17 deletions
Large diffs are not rendered by default.

kos/src/apps/showpic/main.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,11 +337,23 @@ do_showpic(struct screen_buffer *screen,
337337
#endif
338338

339339
/* Display the image */
340-
#if 1
340+
#if 0
341341
video_gfx_stretch(&screen_gfx, blit_x, blit_y, blit_w, blit_h,
342342
&image_gfx, 0, 0,
343343
video_gfx_getclipw(&image_gfx),
344344
video_gfx_getcliph(&image_gfx));
345+
#elif 1
346+
{
347+
struct video_gfx flipgfx = image_gfx;
348+
video_gfx_hmirror(&flipgfx);
349+
video_gfx_setblend(&flipgfx, GFX_BLENDMODE_ALPHA_OVERRIDE(240));
350+
video_gfx_stretch3(&screen_gfx, blit_x, blit_y,
351+
&flipgfx, 0, 0,
352+
blit_w, blit_h,
353+
&image_gfx, 0, 0,
354+
video_gfx_getclipw(&image_gfx),
355+
video_gfx_getcliph(&image_gfx));
356+
}
345357
#elif 0
346358
{
347359
int offset = 10;

kos/src/libvideo/gfx/gfx-empty.c

Lines changed: 80 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,13 @@ DECL_BEGIN
5151
/* Empty GFX operators */
5252
INTERN ATTR_RETNONNULL ATTR_INOUT(1) struct video_blitter *FCC
5353
libvideo_emptygfx_blitfrom(struct video_blitter *__restrict ctx) {
54-
ctx->vbt_ops = &libvideo_blit_empty_ops;
54+
ctx->vbt_ops = &libvideo_emptyblitter_ops;
55+
return ctx;
56+
}
57+
58+
INTERN ATTR_RETNONNULL ATTR_INOUT(1) struct video_blitter3 *FCC
59+
libvideo_emptygfx_blitfrom3(struct video_blitter3 *__restrict ctx) {
60+
ctx->vbt3_ops = &libvideo_emptyblitter3_ops;
5561
return ctx;
5662
}
5763

@@ -70,8 +76,6 @@ libvideo_emptygfx_clip(struct video_gfx *__restrict self,
7076
return self;
7177
}
7278

73-
#define libvideo_emptygfx_coord2offset \
74-
(*(bool (CC *)(struct video_gfx const *__restrict, video_coord_t, video_coord_t, video_offset_t[2]))&libvideo_emptygfx_offset2coord)
7579
INTERN WUNUSED ATTR_IN(1) ATTR_OUT(4) bool CC
7680
libvideo_emptygfx_offset2coord(struct video_gfx const *__restrict self,
7781
video_offset_t x, video_offset_t y,
@@ -161,19 +165,42 @@ libvideo_emptygfx_fillstretchmask(struct video_gfx const *__restrict UNUSED(self
161165
}
162166

163167
INTERN ATTR_IN(1) ATTR_IN(4) void CC
164-
libvideo_emptygfx_bitblit(struct video_gfx const *__restrict UNUSED(dst),
168+
libvideo_emptygfx_bitblit(struct video_gfx const *UNUSED(dst),
165169
video_offset_t UNUSED(dst_x), video_offset_t UNUSED(dst_y),
166-
struct video_gfx const *__restrict UNUSED(src),
170+
struct video_gfx const *UNUSED(src),
167171
video_offset_t UNUSED(src_x), video_offset_t UNUSED(src_y),
168172
video_dim_t UNUSED(size_x), video_dim_t UNUSED(size_y)) {
169173
COMPILER_IMPURE();
170174
}
171175

172176
INTERN ATTR_IN(1) ATTR_IN(6) void CC
173-
libvideo_emptygfx_stretch(struct video_gfx const *__restrict UNUSED(dst),
177+
libvideo_emptygfx_stretch(struct video_gfx const *UNUSED(dst),
174178
video_offset_t UNUSED(dst_x), video_offset_t UNUSED(dst_y),
175179
video_dim_t UNUSED(dst_size_x), video_dim_t UNUSED(dst_size_y),
176-
struct video_gfx const *__restrict UNUSED(src),
180+
struct video_gfx const *UNUSED(src),
181+
video_offset_t UNUSED(src_x), video_offset_t UNUSED(src_y),
182+
video_dim_t UNUSED(src_size_x), video_dim_t UNUSED(src_size_y)) {
183+
COMPILER_IMPURE();
184+
}
185+
186+
INTERN ATTR_IN(1) ATTR_IN(4) ATTR_IN(7) void CC
187+
libvideo_emptygfx_bitblit3(struct video_gfx const *UNUSED(wrdst),
188+
video_offset_t UNUSED(wrdst_x), video_offset_t UNUSED(wrdst_y),
189+
struct video_gfx const *UNUSED(rddst),
190+
video_offset_t UNUSED(rddst_x), video_offset_t UNUSED(rddst_y),
191+
struct video_gfx const *UNUSED(src),
192+
video_offset_t UNUSED(src_x), video_offset_t UNUSED(src_y),
193+
video_dim_t UNUSED(size_x), video_dim_t UNUSED(size_y)) {
194+
COMPILER_IMPURE();
195+
}
196+
197+
INTERN ATTR_IN(1) ATTR_IN(4) ATTR_IN(9) void CC
198+
libvideo_emptygfx_stretch3(struct video_gfx const *UNUSED(wrdst),
199+
video_offset_t UNUSED(wrdst_x), video_offset_t UNUSED(wrdst_y),
200+
struct video_gfx const *UNUSED(rddst),
201+
video_offset_t UNUSED(rddst_x), video_offset_t UNUSED(rddst_y),
202+
video_dim_t UNUSED(dst_size_x), video_dim_t UNUSED(dst_size_y),
203+
struct video_gfx const *UNUSED(src),
177204
video_offset_t UNUSED(src_x), video_offset_t UNUSED(src_y),
178205
video_dim_t UNUSED(src_size_x), video_dim_t UNUSED(src_size_y)) {
179206
COMPILER_IMPURE();
@@ -185,11 +212,14 @@ PRIVATE struct video_gfx_ops libvideo_emptygfx_ops = {};
185212
INTERN ATTR_RETNONNULL WUNUSED struct video_gfx_ops const *CC _libvideo_emptygfx_ops(void) {
186213
if unlikely(!libvideo_emptygfx_ops.vgfo_getcolor) {
187214
libvideo_emptygfx_ops.vgfo_blitfrom = &libvideo_emptygfx_blitfrom;
215+
libvideo_emptygfx_ops.vgfo_blitfrom3 = &libvideo_emptygfx_blitfrom3;
188216
libvideo_emptygfx_ops.vgfo_clip = &libvideo_emptygfx_clip;
189217
libvideo_emptygfx_ops.vgfo_coord2offset = &libvideo_emptygfx_coord2offset;
190218
libvideo_emptygfx_ops.vgfo_offset2coord = &libvideo_emptygfx_offset2coord;
191219
libvideo_emptygfx_ops.vgfo_bitblit = &libvideo_emptygfx_bitblit;
192220
libvideo_emptygfx_ops.vgfo_stretch = &libvideo_emptygfx_stretch;
221+
libvideo_emptygfx_ops.vgfo_bitblit3 = &libvideo_emptygfx_bitblit3;
222+
libvideo_emptygfx_ops.vgfo_stretch3 = &libvideo_emptygfx_stretch3;
193223
libvideo_emptygfx_ops.vgfo_vgradient = &libvideo_emptygfx_vgradient;
194224
libvideo_emptygfx_ops.vgfo_hgradient = &libvideo_emptygfx_hgradient;
195225
libvideo_emptygfx_ops.vgfo_gradient = &libvideo_emptygfx_gradient;
@@ -227,18 +257,53 @@ libvideo_emptyblitter_stretch(struct video_blitter const *__restrict UNUSED(self
227257
COMPILER_IMPURE();
228258
}
229259

230-
#undef libvideo_blit_empty_ops
231-
PRIVATE struct video_blitter_ops libvideo_blit_empty_ops = {};
232-
INTERN ATTR_RETNONNULL WUNUSED struct video_blitter_ops const *CC _libvideo_blit_empty_ops(void) {
233-
if unlikely(!libvideo_blit_empty_ops.vbto_bitblit) {
234-
libvideo_blit_empty_ops.vbto_stretch = &libvideo_emptyblitter_stretch;
260+
#undef libvideo_emptyblitter_ops
261+
PRIVATE struct video_blitter_ops libvideo_emptyblitter_ops = {};
262+
INTERN ATTR_RETNONNULL WUNUSED struct video_blitter_ops const *CC _libvideo_emptyblitter_ops(void) {
263+
if unlikely(!libvideo_emptyblitter_ops.vbto_bitblit) {
264+
libvideo_emptyblitter_ops.vbto_stretch = &libvideo_emptyblitter_stretch;
265+
COMPILER_WRITE_BARRIER();
266+
libvideo_emptyblitter_ops.vbto_bitblit = &libvideo_emptyblitter_blit;
267+
COMPILER_WRITE_BARRIER();
268+
}
269+
return &libvideo_emptyblitter_ops;
270+
}
271+
#define libvideo_emptyblitter_ops (*_libvideo_emptyblitter_ops())
272+
273+
274+
275+
/* Empty blit3 operators */
276+
INTERN ATTR_IN(1) void CC
277+
libvideo_emptyblitter3_blit(struct video_blitter3 const *__restrict UNUSED(self),
278+
video_offset_t UNUSED(wrdst_x), video_offset_t UNUSED(wrdst_y),
279+
video_offset_t UNUSED(rddst_x), video_offset_t UNUSED(rddst_y),
280+
video_offset_t UNUSED(src_x), video_offset_t UNUSED(src_y),
281+
video_dim_t UNUSED(size_x), video_dim_t UNUSED(size_y)) {
282+
COMPILER_IMPURE();
283+
}
284+
285+
INTERN ATTR_IN(1) void CC
286+
libvideo_emptyblitter3_stretch(struct video_blitter3 const *__restrict UNUSED(self),
287+
video_offset_t UNUSED(wrdst_x), video_offset_t UNUSED(wrdst_y),
288+
video_offset_t UNUSED(rddst_x), video_offset_t UNUSED(rddst_y),
289+
video_dim_t UNUSED(dst_size_x), video_dim_t UNUSED(dst_size_y),
290+
video_offset_t UNUSED(src_x), video_offset_t UNUSED(src_y),
291+
video_dim_t UNUSED(src_size_x), video_dim_t UNUSED(src_size_y)) {
292+
COMPILER_IMPURE();
293+
}
294+
295+
#undef libvideo_emptyblitter3_ops
296+
PRIVATE struct video_blitter3_ops libvideo_emptyblitter3_ops = {};
297+
INTERN ATTR_RETNONNULL WUNUSED struct video_blitter3_ops const *CC _libvideo_emptyblitter3_ops(void) {
298+
if unlikely(!libvideo_emptyblitter3_ops.vbt3o_bitblit) {
299+
libvideo_emptyblitter3_ops.vbt3o_stretch = &libvideo_emptyblitter3_stretch;
235300
COMPILER_WRITE_BARRIER();
236-
libvideo_blit_empty_ops.vbto_bitblit = &libvideo_emptyblitter_blit;
301+
libvideo_emptyblitter3_ops.vbt3o_bitblit = &libvideo_emptyblitter3_blit;
237302
COMPILER_WRITE_BARRIER();
238303
}
239-
return &libvideo_blit_empty_ops;
304+
return &libvideo_emptyblitter3_ops;
240305
}
241-
#define libvideo_blit_empty_ops (*_libvideo_blit_empty_ops())
306+
#define libvideo_emptyblitter3_ops (*_libvideo_emptyblitter3_ops())
242307

243308

244309

kos/src/libvideo/gfx/gfx-empty.h

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ DECL_BEGIN
3030

3131
/* Empty GFX operators */
3232
INTDEF ATTR_RETNONNULL ATTR_INOUT(1) struct video_blitter *FCC libvideo_emptygfx_blitfrom(struct video_blitter *__restrict ctx);
33+
INTDEF ATTR_RETNONNULL ATTR_INOUT(1) struct video_blitter3 *FCC libvideo_emptygfx_blitfrom3(struct video_blitter3 *__restrict ctx);
34+
INTDEF ATTR_RETNONNULL ATTR_INOUT(1) struct video_gfx *CC libvideo_emptygfx_clip(struct video_gfx *__restrict self, video_offset_t clip_x, video_offset_t clip_y, video_dim_t size_x, video_dim_t size_y);
35+
INTDEF WUNUSED ATTR_IN(1) ATTR_OUT(4) bool CC libvideo_emptygfx_coord2offset(struct video_gfx const *__restrict self, video_coord_t x, video_coord_t y, video_offset_t coords[2]) ASMNAME("libvideo_emptygfx_offset2coord");
36+
INTDEF WUNUSED ATTR_IN(1) ATTR_OUT(4) bool CC libvideo_emptygfx_offset2coord(struct video_gfx const *__restrict self, video_offset_t x, video_offset_t y, video_coord_t coords[2]);
3337
INTDEF ATTR_IN(1) video_color_t CC libvideo_emptygfx_getcolor(struct video_gfx const *__restrict self, video_offset_t x, video_offset_t y);
3438
INTDEF ATTR_IN(1) void CC libvideo_emptygfx_putcolor(struct video_gfx const *__restrict self, video_offset_t x, video_offset_t y, video_color_t color);
3539
INTDEF ATTR_IN(1) void CC libvideo_emptygfx_line(struct video_gfx const *__restrict self, video_offset_t x1, video_offset_t y1, video_offset_t x2, video_offset_t y2, video_color_t color);
@@ -42,16 +46,24 @@ INTDEF ATTR_IN(1) void CC libvideo_emptygfx_hgradient(struct video_gfx const *__
4246
INTDEF ATTR_IN(1) void CC libvideo_emptygfx_vgradient(struct video_gfx const *__restrict self, video_offset_t x, video_offset_t y, video_dim_t size_x, video_dim_t size_y, video_color_t locolor, video_color_t hicolor);
4347
INTDEF ATTR_IN(1) ATTR_IN(6) ATTR_IN(7) void CC libvideo_emptygfx_fillmask(struct video_gfx const *__restrict self, video_offset_t dst_x, video_offset_t dst_y, video_dim_t size_x, video_dim_t size_y, video_color_t const bg_fg_colors[2], struct video_bitmask const *__restrict bm);
4448
INTDEF ATTR_IN(1) ATTR_IN(6) ATTR_IN(9) void CC libvideo_emptygfx_fillstretchmask(struct video_gfx const *__restrict self, video_offset_t dst_x, video_offset_t dst_y, video_dim_t dst_size_x, video_dim_t dst_size_y, video_color_t const bg_fg_colors[2], video_dim_t src_size_x, video_dim_t src_size_y, struct video_bitmask const *__restrict bm);
45-
INTDEF ATTR_IN(1) ATTR_IN(4) void CC libvideo_emptygfx_bitblit(struct video_gfx const *__restrict dst, video_offset_t dst_x, video_offset_t dst_y, struct video_gfx const *__restrict src, video_offset_t src_x, video_offset_t src_y, video_dim_t size_x, video_dim_t size_y);
46-
INTDEF ATTR_IN(1) ATTR_IN(6) void CC libvideo_emptygfx_stretch(struct video_gfx const *__restrict dst, video_offset_t dst_x, video_offset_t dst_y, video_dim_t dst_size_x, video_dim_t dst_size_y, struct video_gfx const *__restrict src, video_offset_t src_x, video_offset_t src_y, video_dim_t src_size_x, video_dim_t src_size_y);
49+
INTDEF ATTR_IN(1) ATTR_IN(4) void CC libvideo_emptygfx_bitblit(struct video_gfx const *dst, video_offset_t dst_x, video_offset_t dst_y, struct video_gfx const *src, video_offset_t src_x, video_offset_t src_y, video_dim_t size_x, video_dim_t size_y);
50+
INTDEF ATTR_IN(1) ATTR_IN(6) void CC libvideo_emptygfx_stretch(struct video_gfx const *dst, video_offset_t dst_x, video_offset_t dst_y, video_dim_t dst_size_x, video_dim_t dst_size_y, struct video_gfx const *src, video_offset_t src_x, video_offset_t src_y, video_dim_t src_size_x, video_dim_t src_size_y);
51+
INTDEF ATTR_IN(1) ATTR_IN(4) ATTR_IN(7) void CC libvideo_emptygfx_bitblit3(struct video_gfx const *wrdst, video_offset_t wrdst_x, video_offset_t wrdst_y, struct video_gfx const *rddst, video_offset_t rddst_x, video_offset_t rddst_y, struct video_gfx const *src, video_offset_t src_x, video_offset_t src_y, video_dim_t size_x, video_dim_t size_y);
52+
INTDEF ATTR_IN(1) ATTR_IN(4) ATTR_IN(9) void CC libvideo_emptygfx_stretch3(struct video_gfx const *wrdst, video_offset_t wrdst_x, video_offset_t wrdst_y, struct video_gfx const *rddst, video_offset_t rddst_x, video_offset_t rddst_y, video_dim_t dst_size_x, video_dim_t dst_size_y, struct video_gfx const *src, video_offset_t src_x, video_offset_t src_y, video_dim_t src_size_x, video_dim_t src_size_y);
4753
INTDEF ATTR_RETNONNULL WUNUSED struct video_gfx_ops const *CC _libvideo_emptygfx_ops(void);
4854
#define libvideo_emptygfx_ops (*_libvideo_emptygfx_ops())
4955

5056
/* Empty blit operators */
5157
INTDEF ATTR_IN(1) void CC libvideo_emptyblitter_blit(struct video_blitter const *__restrict self, video_offset_t dst_x, video_offset_t dst_y, video_offset_t src_x, video_offset_t src_y, video_dim_t size_x, video_dim_t size_y);
5258
INTDEF ATTR_IN(1) void CC libvideo_emptyblitter_stretch(struct video_blitter const *__restrict self, video_offset_t dst_x, video_offset_t dst_y, video_dim_t dst_size_x, video_dim_t dst_size_y, video_offset_t src_x, video_offset_t src_y, video_dim_t src_size_x, video_dim_t src_size_y);
53-
INTDEF ATTR_RETNONNULL WUNUSED struct video_blitter_ops const *CC _libvideo_blit_empty_ops(void);
54-
#define libvideo_blit_empty_ops (*_libvideo_blit_empty_ops())
59+
INTDEF ATTR_RETNONNULL WUNUSED struct video_blitter_ops const *CC _libvideo_emptyblitter_ops(void);
60+
#define libvideo_emptyblitter_ops (*_libvideo_emptyblitter_ops())
61+
62+
/* Empty blit3 operators */
63+
INTDEF ATTR_IN(1) void CC libvideo_emptyblitter3_blit(struct video_blitter3 const *__restrict self, video_offset_t wrdst_x, video_offset_t wrdst_y, video_offset_t rddst_x, video_offset_t rddst_y, video_offset_t src_x, video_offset_t src_y, video_dim_t size_x, video_dim_t size_y);
64+
INTDEF ATTR_IN(1) void CC libvideo_emptyblitter3_stretch(struct video_blitter3 const *__restrict self, video_offset_t wrdst_x, video_offset_t wrdst_y, video_offset_t rddst_x, video_offset_t rddst_y, video_dim_t dst_size_x, video_dim_t dst_size_y, video_offset_t src_x, video_offset_t src_y, video_dim_t src_size_x, video_dim_t src_size_y);
65+
INTDEF ATTR_RETNONNULL WUNUSED struct video_blitter3_ops const *CC _libvideo_emptyblitter3_ops(void);
66+
#define libvideo_emptyblitter3_ops (*_libvideo_emptyblitter3_ops())
5567

5668
/* Empty video buffer. */
5769
INTDEF WUNUSED ATTR_INOUT(1) ATTR_OUT(2) int FCC libvideo_emptybuffer_lock(struct video_buffer *__restrict self, struct video_lock *__restrict lock);

kos/src/libvideo/gfx/gfx-utils.h

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,62 @@ interpolate_2d(video_color_t c_y0_x0, video_color_t c_y0_x1,
516516
} while (iter_size_x); \
517517
} while (size_y)
518518

519+
520+
/* Invoke:
521+
* >> cb(video_coord_t out_x, video_coord_t out_y,
522+
* >> video_coord_t dst_x, video_coord_t dst_y,
523+
* >> video_coord_t src_x, video_coord_t src_y);
524+
* for every pixel within the destination region */
525+
#define GFX_BLIT_FOREACH3(out_x, out_y, dst_x, dst_y, src_x, src_y, size_x, size_y, cb) \
526+
do { \
527+
video_coord_t used_out_x = out_x; \
528+
video_coord_t used_dst_x = dst_x; \
529+
video_coord_t used_src_x = src_x; \
530+
video_dim_t iter_size_x = size_x; \
531+
do { \
532+
cb(used_out_x, out_y, used_dst_x, dst_y, used_src_x, src_y); \
533+
++used_out_x; \
534+
++used_dst_x; \
535+
++used_src_x; \
536+
} while (--iter_size_x); \
537+
++out_y; \
538+
++dst_y; \
539+
++src_y; \
540+
} while (--size_y)
541+
542+
/* Invoke:
543+
* >> cb(video_coord_t out_x, video_coord_t out_y,
544+
* >> video_coord_t dst_x, video_coord_t dst_y,
545+
* >> video_coord_t src_x, video_coord_t src_y);
546+
* for every pixel within the destination region, applying
547+
* transformation as per "dst_matrix" and "src_matrix"
548+
*
549+
* Allowed to clobber all given arguments. */
550+
#define GFX_BLIT_FOREACH3_IMATRIX(out_x, out_y, dst_x, dst_y, dst_matrix, \
551+
src_x, src_y, size_x, size_y, src_matrix, cb) \
552+
do { \
553+
video_coord_t used_out_x = out_x; \
554+
video_coord_t used_dst_x = dst_x; \
555+
video_coord_t used_dst_y = dst_y; \
556+
video_coord_t used_src_x = src_x; \
557+
video_coord_t used_src_y = src_y; \
558+
video_dim_t iter_size_x = size_x; \
559+
do { \
560+
cb(used_out_x, out_y, used_dst_x, used_dst_y, used_src_x, used_src_y); \
561+
used_src_x += video_imatrix2d_get(&src_matrix, 0, 0); \
562+
used_src_y += video_imatrix2d_get(&src_matrix, 1, 0); \
563+
used_dst_x += video_imatrix2d_get(&dst_matrix, 0, 0); \
564+
used_dst_y += video_imatrix2d_get(&dst_matrix, 1, 0); \
565+
++used_out_x; \
566+
} while (--iter_size_x); \
567+
src_x += video_imatrix2d_get(&src_matrix, 0, 1); \
568+
src_y += video_imatrix2d_get(&src_matrix, 1, 1); \
569+
dst_x += video_imatrix2d_get(&dst_matrix, 0, 1); \
570+
dst_y += video_imatrix2d_get(&dst_matrix, 1, 1); \
571+
++out_y; \
572+
} while (--size_y)
573+
574+
519575
/* Invoke:
520576
* >> cb(size_t sizeof_dst_pixel, size_t sizeof_src_pixel);
521577
* (where "sizeof_dst_pixel" and "sizeof_src_pixel" are preprocessor

0 commit comments

Comments
 (0)