diff --git a/src/gl/textures/gl_hqresize.cpp b/src/gl/textures/gl_hqresize.cpp index fe523c79d8..253d91f4b3 100644 --- a/src/gl/textures/gl_hqresize.cpp +++ b/src/gl/textures/gl_hqresize.cpp @@ -46,6 +46,17 @@ #include "gl/xbr/xbrz.h" #include "gl/xbr/xbrz_old.h" +#ifdef __APPLE__ +# include +# if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 +# define GZ_USE_LIBDISPATCH +# endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 +#endif // __APPLE__ + +#ifdef GZ_USE_LIBDISPATCH +# include +#endif // GZ_USE_LIBDISPATCH + CUSTOM_CVAR(Int, gl_texture_hqresize, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) { if (self < 0 || self > 16) @@ -76,6 +87,22 @@ CVAR (Flag, gl_texture_hqresize_textures, gl_texture_hqresize_targets, 1); CVAR (Flag, gl_texture_hqresize_sprites, gl_texture_hqresize_targets, 2); CVAR (Flag, gl_texture_hqresize_fonts, gl_texture_hqresize_targets, 4); +#ifdef GZ_USE_LIBDISPATCH +CVAR(Bool, gl_texture_hqresize_multithread, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); + +CUSTOM_CVAR(Int, gl_texture_hqresize_mt_width, 16, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (self < 2) self = 2; + if (self > 1024) self = 1024; +} + +CUSTOM_CVAR(Int, gl_texture_hqresize_mt_height, 4, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (self < 2) self = 2; + if (self > 1024) self = 1024; +} +#endif // GZ_USE_LIBDISPATCH + static void scale2x ( uint32* inputBuffer, uint32* outputBuffer, int inWidth, int inHeight ) { @@ -261,26 +288,38 @@ static unsigned char *xbrzHelper( void (*xbrzFunction) ( size_t, const uint32_t* outHeight = N *inHeight; unsigned char * newBuffer = new unsigned char[outWidth*outHeight*4]; - xbrzFunction(N, reinterpret_cast(inputBuffer), reinterpret_cast(newBuffer), inWidth, inHeight, xbrz::ARGB, xbrz::ScalerCfg(), 0, std::numeric_limits::max()); + +#ifdef GZ_USE_LIBDISPATCH + const int thresholdWidth = gl_texture_hqresize_mt_width; + const int thresholdHeight = gl_texture_hqresize_mt_height; + + if (gl_texture_hqresize_multithread + && inWidth > thresholdWidth + && inHeight > thresholdHeight) + { + const dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + + dispatch_apply(inHeight / thresholdHeight + 1, queue, ^(size_t sliceY) + { + xbrzFunction(N, reinterpret_cast(inputBuffer), reinterpret_cast(newBuffer), + inWidth, inHeight, xbrz::ARGB, xbrz::ScalerCfg(), sliceY * thresholdHeight, (sliceY + 1) * thresholdHeight); + }); + } + else +#endif // GZ_USE_LIBDISPATCH + { + xbrzFunction(N, reinterpret_cast(inputBuffer), reinterpret_cast(newBuffer), + inWidth, inHeight, xbrz::ARGB, xbrz::ScalerCfg(), 0, std::numeric_limits::max()); + } + delete[] inputBuffer; return newBuffer; } -static unsigned char *xbrzoldHelper( void (*xbrzFunction) ( size_t factor, const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight, const xbrz_old::ScalerCfg& cfg, int yFirst, int yLast ), - const int N, - unsigned char *inputBuffer, - const int inWidth, - const int inHeight, - int &outWidth, - int &outHeight ) +static void xbrzOldScale(size_t factor, const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight, xbrz::ColorFormat colFmt, const xbrz::ScalerCfg& cfg, int yFirst, int yLast) { - outWidth = N * inWidth; - outHeight = N *inHeight; - - unsigned char * newBuffer = new unsigned char[outWidth*outHeight*4]; - xbrzFunction(N, reinterpret_cast(inputBuffer), reinterpret_cast(newBuffer), inWidth, inHeight, xbrz_old::ScalerCfg(), 0, std::numeric_limits::max()); - delete[] inputBuffer; - return newBuffer; + static_assert(sizeof(xbrz::ScalerCfg) == sizeof(xbrz_old::ScalerCfg), "ScalerCfg classes have different layout"); + xbrz_old::scale(factor, src, trg, srcWidth, srcHeight, reinterpret_cast(cfg), yFirst, yLast); } @@ -372,7 +411,7 @@ unsigned char *gl_CreateUpsampledTextureBuffer ( const FTexture *inputTexture, u case 13: case 14: case 15: - return xbrzoldHelper(xbrz_old::scale, type - 11, inputBuffer, inWidth, inHeight, outWidth, outHeight ); + return xbrzHelper(xbrzOldScale, type - 11, inputBuffer, inWidth, inHeight, outWidth, outHeight ); } }