diff --git a/src/render/SDL_yuv_sw.c b/src/render/SDL_yuv_sw.c index 96ca1bec63..4750bdec7f 100644 --- a/src/render/SDL_yuv_sw.c +++ b/src/render/SDL_yuv_sw.c @@ -73,12 +73,13 @@ SDL_SW_YUVTexture *SDL_SW_CreateYUVTexture(SDL_PixelFormat format, SDL_Colorspac } // Find the pitch and offset values for the texture + const int bpp = SDL_BYTESPERPIXEL(format); switch (format) { case SDL_PIXELFORMAT_YV12: case SDL_PIXELFORMAT_IYUV: case SDL_PIXELFORMAT_I0FL: - swdata->pitches[0] = w * SDL_BYTESPERPIXEL(format); - swdata->pitches[1] = ((w + 1) / 2) * SDL_BYTESPERPIXEL(format); + swdata->pitches[0] = w * bpp; + swdata->pitches[1] = (((swdata->pitches[0] / bpp) + 1) / 2) * bpp; swdata->pitches[2] = swdata->pitches[1]; swdata->planes[0] = swdata->pixels; swdata->planes[1] = swdata->planes[0] + swdata->pitches[0] * h; @@ -86,7 +87,7 @@ SDL_SW_YUVTexture *SDL_SW_CreateYUVTexture(SDL_PixelFormat format, SDL_Colorspac break; case SDL_PIXELFORMAT_I444: case SDL_PIXELFORMAT_I4FL: - swdata->pitches[0] = w * SDL_BYTESPERPIXEL(format); + swdata->pitches[0] = w * bpp; swdata->pitches[1] = swdata->pitches[0]; swdata->pitches[2] = swdata->pitches[1]; swdata->planes[0] = swdata->pixels; @@ -127,6 +128,8 @@ bool SDL_SW_QueryYUVTexturePixels(SDL_SW_YUVTexture *swdata, void **pixels, bool SDL_SW_UpdateYUVTexture(SDL_SW_YUVTexture *swdata, const SDL_Rect *rect, const void *pixels, int pitch) { + const int bpp = SDL_BYTESPERPIXEL(swdata->format); + switch (swdata->format) { case SDL_PIXELFORMAT_YV12: case SDL_PIXELFORMAT_IYUV: @@ -134,17 +137,16 @@ bool SDL_SW_UpdateYUVTexture(SDL_SW_YUVTexture *swdata, const SDL_Rect *rect, if (rect->x == 0 && rect->y == 0 && rect->w == swdata->w && rect->h == swdata->h && pitch == swdata->pitches[0]) { SDL_memcpy(swdata->pixels, pixels, - (size_t)(swdata->h * swdata->w) + 2 * ((swdata->h + 1) / 2) * ((swdata->w + 1) / 2)); + (size_t)(swdata->h * swdata->w * bpp) + 2 * ((swdata->h + 1) / 2) * ((swdata->w + 1) / 2) * bpp); } else { Uint8 *src, *dst; int row; size_t length; - const int bpp = SDL_BYTESPERPIXEL(swdata->format); const int UVpitch = ((pitch / bpp + 1) / 2) * bpp; // Copy the Y plane src = (Uint8 *)pixels; - dst = swdata->pixels + rect->y * swdata->w + rect->x; + dst = swdata->pixels + rect->y * swdata->w * bpp + rect->x * bpp; length = rect->w * bpp; for (row = 0; row < rect->h; ++row) { SDL_memcpy(dst, src, length); @@ -154,8 +156,8 @@ bool SDL_SW_UpdateYUVTexture(SDL_SW_YUVTexture *swdata, const SDL_Rect *rect, // Copy the next plane src = (Uint8 *)pixels + rect->h * pitch; - dst = swdata->pixels + swdata->h * swdata->w; - dst += rect->y / 2 * ((swdata->w + 1) / 2) + rect->x / 2; + dst = swdata->pixels + swdata->h * swdata->pitches[0]; + dst += (rect->y / 2) * swdata->pitches[1] + (rect->x / 2) * bpp; length = ((rect->w + 1) / 2) * bpp; for (row = 0; row < (rect->h + 1) / 2; ++row) { SDL_memcpy(dst, src, length); @@ -165,9 +167,8 @@ bool SDL_SW_UpdateYUVTexture(SDL_SW_YUVTexture *swdata, const SDL_Rect *rect, // Copy the next plane src = (Uint8 *)pixels + rect->h * pitch + ((rect->h + 1) / 2) * UVpitch; - dst = swdata->pixels + swdata->h * swdata->w + - ((swdata->h + 1) / 2) * ((swdata->w + 1) / 2); - dst += rect->y / 2 * ((swdata->w + 1) / 2) + rect->x / 2; + dst = swdata->pixels + swdata->h * swdata->pitches[0] + ((rect->h + 1) / 2) * swdata->pitches[1]; + dst += (rect->y / 2) * swdata->pitches[2] + (rect->x / 2) * bpp; length = ((rect->w + 1) / 2) * bpp; for (row = 0; row < (rect->h + 1) / 2; ++row) { SDL_memcpy(dst, src, length); @@ -185,12 +186,11 @@ bool SDL_SW_UpdateYUVTexture(SDL_SW_YUVTexture *swdata, const SDL_Rect *rect, Uint8 *src, *dst; int row; size_t length; - const int bpp = SDL_BYTESPERPIXEL(swdata->format); // Copy the Y plane src = (Uint8 *)pixels; dst = swdata->pixels; - dst += rect->y * swdata->pitches[0] + rect->x *bpp; + dst += rect->y * swdata->pitches[0] + rect->x * bpp; length = rect->w * bpp; for (row = 0; row < rect->h; ++row) { SDL_memcpy(dst, src, length); @@ -403,7 +403,7 @@ bool SDL_SW_LockYUVTexture(SDL_SW_YUVTexture *swdata, const SDL_Rect *rect, } break; default: - return SDL_SetError("Unsupported YUV format"); + break; } if (rect) { diff --git a/src/render/vulkan/SDL_render_vulkan.c b/src/render/vulkan/SDL_render_vulkan.c index 03b344a67a..9be5117116 100644 --- a/src/render/vulkan/SDL_render_vulkan.c +++ b/src/render/vulkan/SDL_render_vulkan.c @@ -37,6 +37,7 @@ #include "../SDL_sysrender.h" #include "../SDL_d3dmath.h" #include "../../video/SDL_pixels_c.h" +#include "../../video/SDL_yuv_c.h" #include "SDL_shaders_vulkan.h" #define SET_ERROR_CODE(message, rc) \ @@ -267,6 +268,8 @@ typedef struct // Pipeline layout with immutable sampler descriptor set layout VkPipelineLayout pipelineLayoutYcbcr; + Uint8 *pixels; + int pitch; } VULKAN_TextureData; // Pipeline State Object data @@ -2872,6 +2875,7 @@ static void VULKAN_DestroyTexture(SDL_Renderer *renderer, } } + SDL_free(textureData->pixels); SDL_free(textureData); texture->internal = NULL; } @@ -3105,6 +3109,28 @@ static bool VULKAN_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, return SDL_SetError("texture is already locked"); } + bool yuv = (textureData->descriptorSetLayoutYcbcr != VK_NULL_HANDLE); + if (yuv) { + // It's more efficient to upload directly... + if (!textureData->pixels) { + size_t size, calculated_pitch; + if (!SDL_CalculateYUVSize(texture->format, texture->w, texture->h, &size, &calculated_pitch)) { + return false; + } + textureData->pitch = (int)calculated_pitch; + textureData->pixels = (Uint8 *)SDL_malloc(size); + if (!textureData->pixels) { + return false; + } + } + textureData->lockedRect = *rect; + *pixels = + (void *)(textureData->pixels + rect->y * textureData->pitch + + rect->x * SDL_BYTESPERPIXEL(texture->format)); + *pitch = textureData->pitch; + return true; + } + VkDeviceSize pixelSize = VULKAN_GetBytesPerPixel(textureData->mainImage.format, 0); VkDeviceSize length = rect->w * pixelSize; VkDeviceSize stagingBufferSize = length * rect->h; @@ -3142,6 +3168,15 @@ static void VULKAN_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture) return; } + bool yuv = (textureData->descriptorSetLayoutYcbcr != VK_NULL_HANDLE); + if (yuv) { + const SDL_Rect *rect = &textureData->lockedRect; + const Uint8 *pixels = textureData->pixels + rect->y * textureData->pitch + rect->x * SDL_BYTESPERPIXEL(texture->format); + + VULKAN_UpdateTexture(renderer, texture, rect, pixels, textureData->pitch); + return; + } + VULKAN_EnsureCommandBuffer(rendererData); // Make sure the destination is in the correct resource state diff --git a/test/testyuv.c b/test/testyuv.c index 1b1dc1070a..0c6ee60c6f 100644 --- a/test/testyuv.c +++ b/test/testyuv.c @@ -373,7 +373,266 @@ done: return result; } -static bool create_textures(SDL_Renderer *renderer, SDL_Surface *original, SDL_PixelFormat yuv_format, SDL_PixelFormat rgb_format, bool planar, bool monochrome, int luminance, SDL_Texture *output[3]) +// Copied from SDL_yuv_sw.c to verify functionality + +struct SW_YUVTexture +{ + SDL_PixelFormat format; + int w, h; + Uint8 *pixels; + int pitches[3]; + Uint8 *planes[3]; +}; + +typedef struct SW_YUVTexture SW_YUVTexture; + +static SW_YUVTexture *SW_CreateYUVTexture(SDL_PixelFormat format, int w, int h, void *pixels, int pitch) +{ + SW_YUVTexture *swdata; + + switch (format) { + case SDL_PIXELFORMAT_YV12: + case SDL_PIXELFORMAT_IYUV: + case SDL_PIXELFORMAT_I444: + case SDL_PIXELFORMAT_I0FL: + case SDL_PIXELFORMAT_I4FL: + case SDL_PIXELFORMAT_YUY2: + case SDL_PIXELFORMAT_UYVY: + case SDL_PIXELFORMAT_YVYU: + case SDL_PIXELFORMAT_NV12: + case SDL_PIXELFORMAT_NV21: + break; + default: + SDL_SetError("Unsupported YUV format"); + return NULL; + } + + swdata = (SW_YUVTexture *)SDL_calloc(1, sizeof(*swdata)); + if (!swdata) { + return NULL; + } + + swdata->format = format; + swdata->w = w; + swdata->h = h; + swdata->pixels = (Uint8 *)pixels; + + // Find the pitch and offset values for the texture + const int bpp = SDL_BYTESPERPIXEL(format); + switch (format) { + case SDL_PIXELFORMAT_YV12: + case SDL_PIXELFORMAT_IYUV: + case SDL_PIXELFORMAT_I0FL: + swdata->pitches[0] = pitch; + swdata->pitches[1] = (((swdata->pitches[0] / bpp) + 1) / 2) * bpp; + swdata->pitches[2] = swdata->pitches[1]; + swdata->planes[0] = swdata->pixels; + swdata->planes[1] = swdata->planes[0] + swdata->pitches[0] * h; + swdata->planes[2] = swdata->planes[1] + swdata->pitches[1] * ((h + 1) / 2); + break; + case SDL_PIXELFORMAT_I444: + case SDL_PIXELFORMAT_I4FL: + swdata->pitches[0] = w * bpp; + swdata->pitches[1] = swdata->pitches[0]; + swdata->pitches[2] = swdata->pitches[1]; + swdata->planes[0] = swdata->pixels; + swdata->planes[1] = swdata->planes[0] + swdata->pitches[0] * h; + swdata->planes[2] = swdata->planes[1] + swdata->pitches[1] * h; + break; + case SDL_PIXELFORMAT_YUY2: + case SDL_PIXELFORMAT_UYVY: + case SDL_PIXELFORMAT_YVYU: + swdata->pitches[0] = ((w + 1) / 2) * 4; + swdata->planes[0] = swdata->pixels; + break; + case SDL_PIXELFORMAT_NV12: + case SDL_PIXELFORMAT_NV21: + swdata->pitches[0] = w; + swdata->pitches[1] = 2 * ((swdata->pitches[0] + 1) / 2); + swdata->planes[0] = swdata->pixels; + swdata->planes[1] = swdata->planes[0] + swdata->pitches[0] * h; + break; + + default: + SDL_assert(!"We should never get here (caught above)"); + break; + } + + // We're all done.. + return swdata; +} + +static bool SW_UpdateYUVTexture(SW_YUVTexture *swdata, const SDL_Rect *rect, const void *pixels, int pitch) +{ + const int bpp = SDL_BYTESPERPIXEL(swdata->format); + + switch (swdata->format) { + case SDL_PIXELFORMAT_YV12: + case SDL_PIXELFORMAT_IYUV: + case SDL_PIXELFORMAT_I0FL: + if (rect->x == 0 && rect->y == 0 && + rect->w == swdata->w && rect->h == swdata->h && pitch == swdata->pitches[0]) { + SDL_memcpy(swdata->pixels, pixels, + (size_t)(swdata->h * swdata->w * bpp) + 2 * ((swdata->h + 1) / 2) * ((swdata->w + 1) / 2) * bpp); + } else { + Uint8 *src, *dst; + int row; + size_t length; + const int UVpitch = ((pitch / bpp + 1) / 2) * bpp; + + // Copy the Y plane + src = (Uint8 *)pixels; + dst = swdata->pixels + rect->y * swdata->w * bpp + rect->x * bpp; + length = rect->w * bpp; + for (row = 0; row < rect->h; ++row) { + SDL_memcpy(dst, src, length); + src += pitch; + dst += swdata->pitches[0]; + } + + // Copy the next plane + src = (Uint8 *)pixels + rect->h * pitch; + dst = swdata->pixels + swdata->h * swdata->pitches[0]; + dst += (rect->y / 2) * swdata->pitches[1] + (rect->x / 2) * bpp; + length = ((rect->w + 1) / 2) * bpp; + for (row = 0; row < (rect->h + 1) / 2; ++row) { + SDL_memcpy(dst, src, length); + src += UVpitch; + dst += swdata->pitches[1]; + } + + // Copy the next plane + src = (Uint8 *)pixels + rect->h * pitch + ((rect->h + 1) / 2) * UVpitch; + dst = swdata->pixels + swdata->h * swdata->pitches[0] + ((rect->h + 1) / 2) * swdata->pitches[1]; + dst += (rect->y / 2) * swdata->pitches[2] + (rect->x / 2) * bpp; + length = ((rect->w + 1) / 2) * bpp; + for (row = 0; row < (rect->h + 1) / 2; ++row) { + SDL_memcpy(dst, src, length); + src += UVpitch; + dst += swdata->pitches[2]; + } + } + break; + case SDL_PIXELFORMAT_I444: + case SDL_PIXELFORMAT_I4FL: + if (rect->x == 0 && rect->y == 0 && + rect->w == swdata->w && rect->h == swdata->h && pitch == swdata->pitches[0]) { + SDL_memcpy(swdata->pixels, pixels, (size_t)(swdata->h * pitch * 3)); + } else { + Uint8 *src, *dst; + int row; + size_t length; + + // Copy the Y plane + src = (Uint8 *)pixels; + dst = swdata->pixels; + dst += rect->y * swdata->pitches[0] + rect->x * bpp; + length = rect->w * bpp; + for (row = 0; row < rect->h; ++row) { + SDL_memcpy(dst, src, length); + src += pitch; + dst += swdata->pitches[0]; + } + + // Copy the next plane + dst = swdata->pixels + swdata->h * swdata->pitches[0]; + dst += rect->y * swdata->pitches[1] + rect->x * bpp; + for (row = 0; row < rect->h; ++row) { + SDL_memcpy(dst, src, length); + src += pitch; + dst += swdata->pitches[1]; + } + + // Copy the next plane + dst = swdata->pixels + swdata->h * swdata->pitches[0] + swdata->h * swdata->pitches[1]; + dst += rect->y * swdata->pitches[2] + rect->x * bpp; + for (row = 0; row < rect->h; ++row) { + SDL_memcpy(dst, src, length); + src += pitch; + dst += swdata->pitches[2]; + } + } + break; + case SDL_PIXELFORMAT_YUY2: + case SDL_PIXELFORMAT_UYVY: + case SDL_PIXELFORMAT_YVYU: + { + Uint8 *src, *dst; + int row; + size_t length; + + src = (Uint8 *)pixels; + dst = + swdata->planes[0] + rect->y * swdata->pitches[0] + + rect->x * 2; + length = 4 * (((size_t)rect->w + 1) / 2); + for (row = 0; row < rect->h; ++row) { + SDL_memcpy(dst, src, length); + src += pitch; + dst += swdata->pitches[0]; + } + } break; + case SDL_PIXELFORMAT_NV12: + case SDL_PIXELFORMAT_NV21: + { + if (rect->x == 0 && rect->y == 0 && rect->w == swdata->w && rect->h == swdata->h) { + SDL_memcpy(swdata->pixels, pixels, + (size_t)(swdata->h * swdata->w) + 2 * ((swdata->h + 1) / 2) * ((swdata->w + 1) / 2)); + } else { + + Uint8 *src, *dst; + int row; + size_t length; + + // Copy the Y plane + src = (Uint8 *)pixels; + dst = swdata->pixels + rect->y * swdata->w + rect->x; + length = rect->w; + for (row = 0; row < rect->h; ++row) { + SDL_memcpy(dst, src, length); + src += pitch; + dst += swdata->w; + } + + // Copy the next plane + src = (Uint8 *)pixels + rect->h * pitch; + dst = swdata->pixels + swdata->h * swdata->w; + dst += 2 * ((rect->y + 1) / 2) * ((swdata->w + 1) / 2) + 2 * (rect->x / 2); + length = 2 * (((size_t)rect->w + 1) / 2); + for (row = 0; row < (rect->h + 1) / 2; ++row) { + SDL_memcpy(dst, src, length); + src += 2 * ((pitch + 1) / 2); + dst += 2 * ((swdata->w + 1) / 2); + } + } + } break; + default: + return SDL_SetError("Unsupported YUV format"); + } + return true; +} + +static void SW_DestroyYUVTexture(SW_YUVTexture *swdata) +{ + if (swdata) { + SDL_free(swdata); + } +} + +static bool update_locked_texture(SDL_PixelFormat format, int w, int h, const void *pixels, int pitch, void *output_pixels, int output_pitch) +{ + SW_YUVTexture *swdata = SW_CreateYUVTexture(format, w, h, output_pixels, output_pitch); + if (!swdata) { + return false; + } + + SDL_Rect rect = { 0, 0, w, h }; + bool result = SW_UpdateYUVTexture(swdata, &rect, pixels, pitch); + SW_DestroyYUVTexture(swdata); + return result; +} + +static bool create_textures(SDL_Renderer *renderer, SDL_Surface *original, SDL_PixelFormat yuv_format, SDL_PixelFormat rgb_format, bool planar, bool lock, bool monochrome, int luminance, SDL_Texture *output[3]) { SDL_Colorspace rgb_colorspace = SDL_COLORSPACE_SRGB; SDL_Colorspace yuv_colorspace; @@ -556,6 +815,19 @@ static bool create_textures(SDL_Renderer *renderer, SDL_Surface *original, SDL_P SDL_UpdateNVTexture(output[2], NULL, plane0, Ypitch, plane1, UVpitch); SDL_free(plane0); SDL_free(plane1); + } else if (lock) { + void *dst; + int dst_pitch; + if (!SDL_LockTexture(output[2], NULL, &dst, &dst_pitch)) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't lock YUV texture: %s", SDL_GetError()); + goto done; + } + bool updated = update_locked_texture(yuv_format, original->w, original->h, raw_yuv, pitch, dst, dst_pitch); + SDL_UnlockTexture(output[2]); + if (!updated) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't update YUV texture: %s", SDL_GetError()); + goto done; + } } else { SDL_UpdateTexture(output[2], NULL, raw_yuv, pitch); } @@ -610,12 +882,12 @@ static bool check_output(SDL_Renderer *renderer, SDL_Surface *original, SDL_Text return result; } -static bool run_single_format_test(SDL_Renderer *renderer, SDL_Surface *original, SDL_PixelFormat yuv_format, SDL_PixelFormat rgb_format, bool planar) +static bool run_single_format_test(SDL_Renderer *renderer, SDL_Surface *original, SDL_PixelFormat yuv_format, SDL_PixelFormat rgb_format, bool planar, bool lock) { SDL_Texture *output[3]; bool result = true; - if (!create_textures(renderer, original, yuv_format, rgb_format, planar, false, 100, output)) { + if (!create_textures(renderer, original, yuv_format, rgb_format, planar, lock, false, 100, output)) { return false; } @@ -668,7 +940,7 @@ static bool run_all_format_test(SDL_Window *window, const char *requested_render { YUV_CONVERSION_JPEG, "JPEG" }, { YUV_CONVERSION_BT601, "BT601" }, { YUV_CONVERSION_BT709, "BT709" }, - { YUV_CONVERSION_BT2020, "BT2020" } + //{ YUV_CONVERSION_BT2020, "BT2020" } }; bool quit = false; bool result = true; @@ -700,10 +972,13 @@ static bool run_all_format_test(SDL_Window *window, const char *requested_render SDL_PixelFormat rgb_format = rgb_formats[n]; SDL_Log("Testing: %s %s %s %s (planar)", renderer_name, colorspaces[j].name, SDL_GetPixelFormatName(yuv_format), SDL_GetPixelFormatName(rgb_format)); - result &= run_single_format_test(renderer, original, yuv_format, rgb_format, true); + result &= run_single_format_test(renderer, original, yuv_format, rgb_format, true, false); SDL_Log("Testing: %s %s %s %s (packed)", renderer_name, colorspaces[j].name, SDL_GetPixelFormatName(yuv_format), SDL_GetPixelFormatName(rgb_format)); - result &= run_single_format_test(renderer, original, yuv_format, rgb_format, false); + result &= run_single_format_test(renderer, original, yuv_format, rgb_format, false, false); + + SDL_Log("Testing: %s %s %s %s (locked)", renderer_name, colorspaces[j].name, SDL_GetPixelFormatName(yuv_format), SDL_GetPixelFormatName(rgb_format)); + result &= run_single_format_test(renderer, original, yuv_format, rgb_format, false, true); SDL_Event event; while (SDL_PollEvent(&event)) { @@ -720,7 +995,7 @@ static bool run_all_format_test(SDL_Window *window, const char *requested_render return result; } -static bool run_interactive(SDL_Window *window, const char *renderer_name, SDL_Surface *original, SDL_PixelFormat yuv_format, SDL_PixelFormat rgb_format, bool planar, bool monochrome, int luminance) +static bool run_interactive(SDL_Window *window, const char *renderer_name, SDL_Surface *original, SDL_PixelFormat yuv_format, SDL_PixelFormat rgb_format, bool planar, bool lock, bool monochrome, int luminance) { const char *titles[3] = { "ORIGINAL", "SOFTWARE", "HARDWARE" }; char title[128]; @@ -739,7 +1014,7 @@ static bool run_interactive(SDL_Window *window, const char *renderer_name, SDL_S renderer_name = SDL_GetRendererName(renderer); SDL_Texture *output[3]; - if (!create_textures(renderer, original, yuv_format, rgb_format, planar, monochrome, luminance, output)) { + if (!create_textures(renderer, original, yuv_format, rgb_format, planar, lock, monochrome, luminance, output)) { goto done; } @@ -865,6 +1140,7 @@ int main(int argc, char **argv) Uint32 yuv_format = SDL_PIXELFORMAT_YV12; Uint32 rgb_format = SDL_PIXELFORMAT_RGBX8888; bool planar = false; + bool lock = false; bool monochrome = false; int luminance = 100; int i; @@ -964,6 +1240,9 @@ int main(int argc, char **argv) } else if (SDL_strcmp(argv[i], "--planar") == 0) { planar = true; consumed = 1; + } else if (SDL_strcmp(argv[i], "--lock") == 0) { + lock = true; + consumed = 1; } else if (SDL_strcmp(argv[i], "--monochrome") == 0) { monochrome = true; consumed = 1; @@ -989,7 +1268,7 @@ int main(int argc, char **argv) "[--jpeg|--bt601|--bt709|--auto]", "[--yv12|--iyuv|--i444|--yuy2|--uyvy|--yvyu|--nv12|--nv21|--p010|--i4fl]", "[--rgb555|--rgb565|--rgb24|--argb|--abgr|--rgba|--bgra]", - "[--monochrome] [--luminance N%] [--planar]", + "[--monochrome] [--luminance N%] [--planar] [--lock]", "[--automated] [--colorspace-test] [--renderer NAME]", "[sample.png]", NULL, @@ -1047,7 +1326,7 @@ int main(int argc, char **argv) result = 5; } } else { - if (!run_interactive(window, renderer_name, original, yuv_format, rgb_format, planar, monochrome, luminance)) { + if (!run_interactive(window, renderer_name, original, yuv_format, rgb_format, planar, lock, monochrome, luminance)) { result = 5; } }