12f083884Ss.makeev_local // The MIT License (MIT) 22f083884Ss.makeev_local // 32f083884Ss.makeev_local // Copyright (c) 2015 Sergey Makeev, Vadim Slyusarev 42f083884Ss.makeev_local // 52f083884Ss.makeev_local // Permission is hereby granted, free of charge, to any person obtaining a copy 62f083884Ss.makeev_local // of this software and associated documentation files (the "Software"), to deal 72f083884Ss.makeev_local // in the Software without restriction, including without limitation the rights 82f083884Ss.makeev_local // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 92f083884Ss.makeev_local // copies of the Software, and to permit persons to whom the Software is 102f083884Ss.makeev_local // furnished to do so, subject to the following conditions: 112f083884Ss.makeev_local // 122f083884Ss.makeev_local // The above copyright notice and this permission notice shall be included in 132f083884Ss.makeev_local // all copies or substantial portions of the Software. 142f083884Ss.makeev_local // 152f083884Ss.makeev_local // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 162f083884Ss.makeev_local // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 172f083884Ss.makeev_local // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 182f083884Ss.makeev_local // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 192f083884Ss.makeev_local // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 202f083884Ss.makeev_local // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 212f083884Ss.makeev_local // THE SOFTWARE. 222f083884Ss.makeev_local 232f083884Ss.makeev_local #include "Tests.h" 242f083884Ss.makeev_local #include <UnitTest++.h> 252f083884Ss.makeev_local #include <MTScheduler.h> 262f083884Ss.makeev_local 272f083884Ss.makeev_local #include <squish.h> 282f083884Ss.makeev_local #include <string.h> 29*faa6c6e5Ss.makeev_local #include <math.h> 302f083884Ss.makeev_local 312f083884Ss.makeev_local /* 322f083884Ss.makeev_local #ifdef _WIN32 332f083884Ss.makeev_local 342f083884Ss.makeev_local #include <conio.h> 352f083884Ss.makeev_local 362f083884Ss.makeev_local #else 372f083884Ss.makeev_local 382f083884Ss.makeev_local #include <stdio.h> 392f083884Ss.makeev_local #include <termios.h> 402f083884Ss.makeev_local #include <unistd.h> 412f083884Ss.makeev_local #include <fcntl.h> 422f083884Ss.makeev_local 432f083884Ss.makeev_local int _kbhit(void) 442f083884Ss.makeev_local { 452f083884Ss.makeev_local struct termios oldt, newt; 462f083884Ss.makeev_local int ch; 472f083884Ss.makeev_local int oldf; 482f083884Ss.makeev_local 492f083884Ss.makeev_local tcgetattr(STDIN_FILENO, &oldt); 502f083884Ss.makeev_local newt = oldt; 512f083884Ss.makeev_local newt.c_lflag &= ~(ICANON | ECHO); 522f083884Ss.makeev_local tcsetattr(STDIN_FILENO, TCSANOW, &newt); 532f083884Ss.makeev_local oldf = fcntl(STDIN_FILENO, F_GETFL, 0); 542f083884Ss.makeev_local fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK); 552f083884Ss.makeev_local 562f083884Ss.makeev_local ch = getchar(); 572f083884Ss.makeev_local 582f083884Ss.makeev_local tcsetattr(STDIN_FILENO, TCSANOW, &oldt); 592f083884Ss.makeev_local fcntl(STDIN_FILENO, F_SETFL, oldf); 602f083884Ss.makeev_local 612f083884Ss.makeev_local if(ch != EOF) 622f083884Ss.makeev_local { 632f083884Ss.makeev_local ungetc(ch, stdin); 642f083884Ss.makeev_local return 1; 652f083884Ss.makeev_local } 662f083884Ss.makeev_local 672f083884Ss.makeev_local return 0; 682f083884Ss.makeev_local } 692f083884Ss.makeev_local #endif 702f083884Ss.makeev_local */ 712f083884Ss.makeev_local 722f083884Ss.makeev_local #ifdef MT_INSTRUMENTED_BUILD 732f083884Ss.makeev_local 742f083884Ss.makeev_local class Microprofile : public MT::IProfilerEventListener 752f083884Ss.makeev_local { 762f083884Ss.makeev_local void OnThreadCreated(uint32 workerIndex) 772f083884Ss.makeev_local { 782f083884Ss.makeev_local MT_UNUSED(workerIndex); 792f083884Ss.makeev_local } 802f083884Ss.makeev_local 812f083884Ss.makeev_local void OnThreadStarted(uint32 workerIndex) 822f083884Ss.makeev_local { 832f083884Ss.makeev_local MT_UNUSED(workerIndex); 842f083884Ss.makeev_local } 852f083884Ss.makeev_local 862f083884Ss.makeev_local void OnThreadStoped(uint32 workerIndex) 872f083884Ss.makeev_local { 882f083884Ss.makeev_local MT_UNUSED(workerIndex); 892f083884Ss.makeev_local } 902f083884Ss.makeev_local 912f083884Ss.makeev_local void OnThreadIdleBegin(uint32 workerIndex) 922f083884Ss.makeev_local { 932f083884Ss.makeev_local MT_UNUSED(workerIndex); 942f083884Ss.makeev_local } 952f083884Ss.makeev_local 962f083884Ss.makeev_local void OnThreadIdleEnd(uint32 workerIndex) 972f083884Ss.makeev_local { 982f083884Ss.makeev_local MT_UNUSED(workerIndex); 992f083884Ss.makeev_local } 1002f083884Ss.makeev_local 1012f083884Ss.makeev_local void OnTaskFinished(MT::Color::Type debugColor, const mt_char* debugID) 1022f083884Ss.makeev_local { 1032f083884Ss.makeev_local MT_UNUSED(debugColor); 1042f083884Ss.makeev_local MT_UNUSED(debugID); 1052f083884Ss.makeev_local } 1062f083884Ss.makeev_local 1072f083884Ss.makeev_local void OnTaskResumed(MT::Color::Type debugColor, const mt_char* debugID) 1082f083884Ss.makeev_local { 1092f083884Ss.makeev_local MT_UNUSED(debugColor); 1102f083884Ss.makeev_local MT_UNUSED(debugID); 1112f083884Ss.makeev_local } 1122f083884Ss.makeev_local 1132f083884Ss.makeev_local void OnTaskYielded(MT::Color::Type debugColor, const mt_char* debugID) 1142f083884Ss.makeev_local { 1152f083884Ss.makeev_local MT_UNUSED(debugColor); 1162f083884Ss.makeev_local MT_UNUSED(debugID); 1172f083884Ss.makeev_local } 1182f083884Ss.makeev_local 1192f083884Ss.makeev_local }; 1202f083884Ss.makeev_local 1212f083884Ss.makeev_local 1222f083884Ss.makeev_local #endif 1232f083884Ss.makeev_local 1242f083884Ss.makeev_local 1252f083884Ss.makeev_local 1262f083884Ss.makeev_local 1272f083884Ss.makeev_local 1282f083884Ss.makeev_local namespace EmbeddedImage 1292f083884Ss.makeev_local { 1302f083884Ss.makeev_local #include "LenaDxt/LenaColor.h" 1312f083884Ss.makeev_local #include "LenaDxt/HeaderDDS.h" 1322f083884Ss.makeev_local } 1332f083884Ss.makeev_local 1342f083884Ss.makeev_local 1352f083884Ss.makeev_local bool CompareImagesPSNR(uint8 * img1, uint8 * img2, uint32 bytesCount, double psnrThreshold) 1362f083884Ss.makeev_local { 1372f083884Ss.makeev_local double mse = 0.0; 1382f083884Ss.makeev_local 1392f083884Ss.makeev_local for (uint32 i = 0; i < bytesCount; i++) 1402f083884Ss.makeev_local { 1412f083884Ss.makeev_local double error = (double)img1[0] - (double)img2[1]; 1422f083884Ss.makeev_local mse += (error * error); 1432f083884Ss.makeev_local } 1442f083884Ss.makeev_local 1452f083884Ss.makeev_local mse = mse / (double)bytesCount; 1462f083884Ss.makeev_local 1472f083884Ss.makeev_local if (mse > 0.0) 1482f083884Ss.makeev_local { 1492f083884Ss.makeev_local double psnr = 10.0 * log10(255.0*255.0/mse); 1502f083884Ss.makeev_local if (psnr < psnrThreshold) 1512f083884Ss.makeev_local { 1522f083884Ss.makeev_local return false; 1532f083884Ss.makeev_local } 1542f083884Ss.makeev_local } 1552f083884Ss.makeev_local 1562f083884Ss.makeev_local return true; 1572f083884Ss.makeev_local } 1582f083884Ss.makeev_local 1592f083884Ss.makeev_local 1602f083884Ss.makeev_local 1612f083884Ss.makeev_local SUITE(DxtTests) 1622f083884Ss.makeev_local { 1632f083884Ss.makeev_local //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 1642f083884Ss.makeev_local struct CompressDxtBlock 1652f083884Ss.makeev_local { 1662f083884Ss.makeev_local MT_DECLARE_TASK(CompressDxtBlock, MT::StackRequirements::STANDARD, MT::Color::Blue); 1672f083884Ss.makeev_local 1682f083884Ss.makeev_local MT::ArrayView<uint8> srcPixels; 1692f083884Ss.makeev_local MT::ArrayView<uint8> dstBlocks; 1702f083884Ss.makeev_local 1712f083884Ss.makeev_local int srcX; 1722f083884Ss.makeev_local int srcY; 1732f083884Ss.makeev_local 1742f083884Ss.makeev_local int stride; 1752f083884Ss.makeev_local int dstBlockOffset; 1762f083884Ss.makeev_local 1772f083884Ss.makeev_local CompressDxtBlock(int _srcX, int _srcY, int _stride, const MT::ArrayView<uint8> & _srcPixels, const MT::ArrayView<uint8> & _dstBlocks, int _dstBlockOffset) 1782f083884Ss.makeev_local : srcPixels(_srcPixels) 1792f083884Ss.makeev_local , dstBlocks(_dstBlocks) 1802f083884Ss.makeev_local { 1812f083884Ss.makeev_local srcX = _srcX; 1822f083884Ss.makeev_local srcY = _srcY; 1832f083884Ss.makeev_local stride = _stride; 1842f083884Ss.makeev_local dstBlockOffset = _dstBlockOffset; 1852f083884Ss.makeev_local } 1862f083884Ss.makeev_local 1872f083884Ss.makeev_local CompressDxtBlock(CompressDxtBlock&& other) 1882f083884Ss.makeev_local : srcPixels(other.srcPixels) 1892f083884Ss.makeev_local , dstBlocks(other.dstBlocks) 1902f083884Ss.makeev_local , srcX(other.srcX) 1912f083884Ss.makeev_local , srcY(other.srcY) 1922f083884Ss.makeev_local , stride(other.stride) 1932f083884Ss.makeev_local , dstBlockOffset(other.dstBlockOffset) 1942f083884Ss.makeev_local { 1952f083884Ss.makeev_local other.srcX = -1; 1962f083884Ss.makeev_local other.srcY = -1; 1972f083884Ss.makeev_local other.stride = -1; 1982f083884Ss.makeev_local other.dstBlockOffset = -1; 1992f083884Ss.makeev_local } 2002f083884Ss.makeev_local 2012f083884Ss.makeev_local ~CompressDxtBlock() 2022f083884Ss.makeev_local { 2032f083884Ss.makeev_local srcX = -1; 2042f083884Ss.makeev_local srcY = -1; 2052f083884Ss.makeev_local stride = -1; 2062f083884Ss.makeev_local dstBlockOffset = -1; 2072f083884Ss.makeev_local } 2082f083884Ss.makeev_local 2092f083884Ss.makeev_local void Do(MT::FiberContext&) 2102f083884Ss.makeev_local { 2112f083884Ss.makeev_local // 16 pixels of input 2122f083884Ss.makeev_local uint32 pixels[4*4]; 2132f083884Ss.makeev_local 2142f083884Ss.makeev_local // copy dxt1 block from image 2152f083884Ss.makeev_local for (int y = 0; y < 4; y++) 2162f083884Ss.makeev_local { 2172f083884Ss.makeev_local for (int x = 0; x < 4; x++) 2182f083884Ss.makeev_local { 2192f083884Ss.makeev_local int posX = srcX + x; 2202f083884Ss.makeev_local int posY = srcY + y; 2212f083884Ss.makeev_local 2222f083884Ss.makeev_local int index = posY * stride + (posX * 3); 2232f083884Ss.makeev_local 2242f083884Ss.makeev_local MT_ASSERT(index >= 0 && ((size_t)(index + 2) < MT_ARRAY_SIZE(EmbeddedImage::lenaColor)), "Invalid index"); 2252f083884Ss.makeev_local 2262f083884Ss.makeev_local uint8 r = srcPixels[index + 0]; 2272f083884Ss.makeev_local uint8 g = srcPixels[index + 1]; 2282f083884Ss.makeev_local uint8 b = srcPixels[index + 2]; 2292f083884Ss.makeev_local 2302f083884Ss.makeev_local uint32 color = 0xFF000000 | ((b << 16) | (g << 8) | (r)); 2312f083884Ss.makeev_local 2322f083884Ss.makeev_local pixels[y * 4 + x] = color; 2332f083884Ss.makeev_local } 2342f083884Ss.makeev_local } 2352f083884Ss.makeev_local 2362f083884Ss.makeev_local // compress the 4x4 block using DXT1 compression 2372f083884Ss.makeev_local squish::Compress( (squish::u8 *)&pixels[0], &dstBlocks[dstBlockOffset], squish::kDxt1 ); 2382f083884Ss.makeev_local } 2392f083884Ss.makeev_local }; 2402f083884Ss.makeev_local 2412f083884Ss.makeev_local 2422f083884Ss.makeev_local //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 2432f083884Ss.makeev_local struct CompressDxt 2442f083884Ss.makeev_local { 2452f083884Ss.makeev_local MT_DECLARE_TASK(CompressDxt, MT::StackRequirements::EXTENDED, MT::Color::Aqua); 2462f083884Ss.makeev_local 2472f083884Ss.makeev_local uint32 width; 2482f083884Ss.makeev_local uint32 height; 2492f083884Ss.makeev_local uint32 stride; 2502f083884Ss.makeev_local 2512f083884Ss.makeev_local uint32 blkWidth; 2522f083884Ss.makeev_local uint32 blkHeight; 2532f083884Ss.makeev_local 2542f083884Ss.makeev_local MT::ArrayView<uint8> srcPixels; 2552f083884Ss.makeev_local MT::ArrayView<uint8> dxtBlocks; 2562f083884Ss.makeev_local 2572f083884Ss.makeev_local CompressDxt(uint32 _width, uint32 _height, uint32 _stride, const MT::ArrayView<uint8> & _srcPixels ) 2582f083884Ss.makeev_local : srcPixels(_srcPixels) 2592f083884Ss.makeev_local { 2602f083884Ss.makeev_local width = _width; 2612f083884Ss.makeev_local height = _height; 2622f083884Ss.makeev_local stride = _stride; 2632f083884Ss.makeev_local 2642f083884Ss.makeev_local blkWidth = width >> 2; 2652f083884Ss.makeev_local blkHeight = height >> 2; 2662f083884Ss.makeev_local 2672f083884Ss.makeev_local int dxtBlocksTotalSizeInBytes = blkWidth * blkHeight * 8; // 8 bytes = 64 bits per block (dxt1) 2682f083884Ss.makeev_local dxtBlocks = MT::ArrayView<uint8>( malloc( dxtBlocksTotalSizeInBytes ), dxtBlocksTotalSizeInBytes); 2692f083884Ss.makeev_local } 2702f083884Ss.makeev_local 2712f083884Ss.makeev_local ~CompressDxt() 2722f083884Ss.makeev_local { 2732f083884Ss.makeev_local void* pDxtBlocks = dxtBlocks.GetRawData(); 2742f083884Ss.makeev_local if (pDxtBlocks) 2752f083884Ss.makeev_local { 2762f083884Ss.makeev_local free(pDxtBlocks); 2772f083884Ss.makeev_local } 2782f083884Ss.makeev_local } 2792f083884Ss.makeev_local 2802f083884Ss.makeev_local 2812f083884Ss.makeev_local void Do(MT::FiberContext& context) 2822f083884Ss.makeev_local { 2832f083884Ss.makeev_local // use stack_array as subtask container. beware stack overflow! 2842f083884Ss.makeev_local MT::StackArray<CompressDxtBlock, 1024> subTasks; 2852f083884Ss.makeev_local 2862f083884Ss.makeev_local for (uint32 blkY = 0; blkY < blkHeight; blkY++) 2872f083884Ss.makeev_local { 2882f083884Ss.makeev_local for (uint32 blkX = 0; blkX < blkWidth; blkX++) 2892f083884Ss.makeev_local { 2902f083884Ss.makeev_local uint32 blockIndex = blkY * blkWidth + blkX; 2912f083884Ss.makeev_local subTasks.PushBack( CompressDxtBlock(blkX * 4, blkY * 4, stride, srcPixels, dxtBlocks, blockIndex * 8) ); 2922f083884Ss.makeev_local } 2932f083884Ss.makeev_local } 2942f083884Ss.makeev_local 2952f083884Ss.makeev_local context.RunSubtasksAndYield(MT::TaskGroup::Default(), &subTasks[0], subTasks.Size()); 2962f083884Ss.makeev_local } 2972f083884Ss.makeev_local }; 2982f083884Ss.makeev_local 2992f083884Ss.makeev_local 3002f083884Ss.makeev_local 3012f083884Ss.makeev_local //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 3022f083884Ss.makeev_local struct DecompressDxtBlock 3032f083884Ss.makeev_local { 3042f083884Ss.makeev_local MT_DECLARE_TASK(DecompressDxtBlock, MT::StackRequirements::STANDARD, MT::Color::Red); 3052f083884Ss.makeev_local 3062f083884Ss.makeev_local MT::ArrayView<uint8> srcBlocks; 3072f083884Ss.makeev_local MT::ArrayView<uint8> dstPixels; 3082f083884Ss.makeev_local 3092f083884Ss.makeev_local int dstX; 3102f083884Ss.makeev_local int dstY; 3112f083884Ss.makeev_local 3122f083884Ss.makeev_local int stride; 3132f083884Ss.makeev_local int srcBlockOffset; 3142f083884Ss.makeev_local 3152f083884Ss.makeev_local DecompressDxtBlock(int _dstX, int _dstY, int _stride, const MT::ArrayView<uint8> & _dstPixels, const MT::ArrayView<uint8> & _srcBlocks, int _srcBlockOffset) 3162f083884Ss.makeev_local : srcBlocks(_srcBlocks) 3172f083884Ss.makeev_local , dstPixels(_dstPixels) 3182f083884Ss.makeev_local { 3192f083884Ss.makeev_local dstX = _dstX; 3202f083884Ss.makeev_local dstY = _dstY; 3212f083884Ss.makeev_local stride = _stride; 3222f083884Ss.makeev_local srcBlockOffset = _srcBlockOffset; 3232f083884Ss.makeev_local } 3242f083884Ss.makeev_local 3252f083884Ss.makeev_local DecompressDxtBlock(DecompressDxtBlock&& other) 3262f083884Ss.makeev_local : srcBlocks(other.srcBlocks) 3272f083884Ss.makeev_local , dstPixels(other.dstPixels) 3282f083884Ss.makeev_local , dstX(other.dstX) 3292f083884Ss.makeev_local , dstY(other.dstY) 3302f083884Ss.makeev_local , stride(other.stride) 3312f083884Ss.makeev_local , srcBlockOffset(other.srcBlockOffset) 3322f083884Ss.makeev_local { 3332f083884Ss.makeev_local other.dstX = -1; 3342f083884Ss.makeev_local other.dstY = -1; 3352f083884Ss.makeev_local other.stride = -1; 3362f083884Ss.makeev_local other.srcBlockOffset = -1; 3372f083884Ss.makeev_local } 3382f083884Ss.makeev_local 3392f083884Ss.makeev_local ~DecompressDxtBlock() 3402f083884Ss.makeev_local { 3412f083884Ss.makeev_local dstX = -1; 3422f083884Ss.makeev_local dstY = -1; 3432f083884Ss.makeev_local stride = -1; 3442f083884Ss.makeev_local srcBlockOffset = -1; 3452f083884Ss.makeev_local } 3462f083884Ss.makeev_local 3472f083884Ss.makeev_local 3482f083884Ss.makeev_local void Do(MT::FiberContext&) 3492f083884Ss.makeev_local { 3502f083884Ss.makeev_local // 16 pixels of output 3512f083884Ss.makeev_local uint32 pixels[4*4]; 3522f083884Ss.makeev_local 3532f083884Ss.makeev_local // copy dxt1 block from image 3542f083884Ss.makeev_local for (int y = 0; y < 4; y++) 3552f083884Ss.makeev_local { 3562f083884Ss.makeev_local for (int x = 0; x < 4; x++) 3572f083884Ss.makeev_local { 3582f083884Ss.makeev_local squish::Decompress((squish::u8 *)&pixels[0], &srcBlocks[srcBlockOffset], squish::kDxt1); 3592f083884Ss.makeev_local 3602f083884Ss.makeev_local int posX = dstX + x; 3612f083884Ss.makeev_local int posY = dstY + y; 3622f083884Ss.makeev_local 3632f083884Ss.makeev_local int index = posY * stride + (posX * 3); 3642f083884Ss.makeev_local 3652f083884Ss.makeev_local uint32 pixel = pixels[y * 4 + x]; 3662f083884Ss.makeev_local 3672f083884Ss.makeev_local MT_ASSERT(index >= 0 && ((size_t)(index + 2) < MT_ARRAY_SIZE(EmbeddedImage::lenaColor)), "Invalid index"); 3682f083884Ss.makeev_local 3692f083884Ss.makeev_local dstPixels[index + 0] = (pixel & 0xFF); 3702f083884Ss.makeev_local dstPixels[index + 1] = (pixel >> 8 & 0xFF); 3712f083884Ss.makeev_local dstPixels[index + 2] = (pixel >> 16 & 0xFF); 3722f083884Ss.makeev_local } 3732f083884Ss.makeev_local } 3742f083884Ss.makeev_local 3752f083884Ss.makeev_local } 3762f083884Ss.makeev_local }; 3772f083884Ss.makeev_local 3782f083884Ss.makeev_local //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 3792f083884Ss.makeev_local struct DecompressDxt 3802f083884Ss.makeev_local { 3812f083884Ss.makeev_local MT_DECLARE_TASK(DecompressDxt, MT::StackRequirements::EXTENDED, MT::Color::Yellow); 3822f083884Ss.makeev_local 3832f083884Ss.makeev_local MT::ArrayView<uint8> dxtBlocks; 3842f083884Ss.makeev_local MT::ArrayView<uint8> decompressedImage; 3852f083884Ss.makeev_local 3862f083884Ss.makeev_local uint32 blkWidth; 3872f083884Ss.makeev_local uint32 blkHeight; 3882f083884Ss.makeev_local 3892f083884Ss.makeev_local 3902f083884Ss.makeev_local DecompressDxt(const MT::ArrayView<uint8> & _dxtBlocks, uint32 dxtBlocksCountWidth, uint32 dxtBlocksCountHeight) 3912f083884Ss.makeev_local : dxtBlocks(_dxtBlocks) 3922f083884Ss.makeev_local { 3932f083884Ss.makeev_local blkWidth = dxtBlocksCountWidth; 3942f083884Ss.makeev_local blkHeight = dxtBlocksCountHeight; 3952f083884Ss.makeev_local 3962f083884Ss.makeev_local // dxt1 block = 16 rgb pixels = 48 bytes 3972f083884Ss.makeev_local uint32 bytesCount = blkWidth * blkHeight * 48; 3982f083884Ss.makeev_local decompressedImage = MT::ArrayView<uint8>( malloc(bytesCount), bytesCount); 3992f083884Ss.makeev_local } 4002f083884Ss.makeev_local 4012f083884Ss.makeev_local ~DecompressDxt() 4022f083884Ss.makeev_local { 4032f083884Ss.makeev_local void* pDxtBlocks = dxtBlocks.GetRawData(); 4042f083884Ss.makeev_local if (pDxtBlocks) 4052f083884Ss.makeev_local { 4062f083884Ss.makeev_local free(pDxtBlocks); 4072f083884Ss.makeev_local } 4082f083884Ss.makeev_local 4092f083884Ss.makeev_local void* pDecompressedImage = decompressedImage.GetRawData(); 4102f083884Ss.makeev_local if (pDecompressedImage) 4112f083884Ss.makeev_local { 4122f083884Ss.makeev_local free(pDecompressedImage); 4132f083884Ss.makeev_local } 4142f083884Ss.makeev_local 4152f083884Ss.makeev_local } 4162f083884Ss.makeev_local 4172f083884Ss.makeev_local void Do(MT::FiberContext& context) 4182f083884Ss.makeev_local { 4192f083884Ss.makeev_local // use stack_array as subtask container. beware stack overflow! 4202f083884Ss.makeev_local MT::StackArray<DecompressDxtBlock, 1024> subTasks; 4212f083884Ss.makeev_local 4222f083884Ss.makeev_local int stride = blkWidth * 4 * 3; 4232f083884Ss.makeev_local 4242f083884Ss.makeev_local for (uint32 blkY = 0; blkY < blkHeight; blkY++) 4252f083884Ss.makeev_local { 4262f083884Ss.makeev_local for (uint32 blkX = 0; blkX < blkWidth; blkX++) 4272f083884Ss.makeev_local { 4282f083884Ss.makeev_local uint32 blockIndex = blkY * blkWidth + blkX; 4292f083884Ss.makeev_local subTasks.PushBack( DecompressDxtBlock(blkX * 4, blkY * 4, stride, decompressedImage, dxtBlocks, blockIndex * 8) ); 4302f083884Ss.makeev_local } 4312f083884Ss.makeev_local } 4322f083884Ss.makeev_local 4332f083884Ss.makeev_local context.RunSubtasksAndYield(MT::TaskGroup::Default(), &subTasks[0], subTasks.Size()); 4342f083884Ss.makeev_local } 4352f083884Ss.makeev_local 4362f083884Ss.makeev_local }; 4372f083884Ss.makeev_local 4382f083884Ss.makeev_local 4392f083884Ss.makeev_local //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4402f083884Ss.makeev_local void Wait(MT::TaskScheduler & scheduler) 4412f083884Ss.makeev_local { 4422f083884Ss.makeev_local //emulate game loop 4432f083884Ss.makeev_local for(;;) 4442f083884Ss.makeev_local { 4452f083884Ss.makeev_local bool waitDone = scheduler.WaitAll(33); 4462f083884Ss.makeev_local if (waitDone) 4472f083884Ss.makeev_local { 4482f083884Ss.makeev_local break; 4492f083884Ss.makeev_local } 4502f083884Ss.makeev_local } 4512f083884Ss.makeev_local } 4522f083884Ss.makeev_local 4532f083884Ss.makeev_local 4542f083884Ss.makeev_local // dxt compressor complex test 4552f083884Ss.makeev_local //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 4562f083884Ss.makeev_local TEST(RunComplexDxtTest) 4572f083884Ss.makeev_local { 4582f083884Ss.makeev_local static_assert(MT_ARRAY_SIZE(EmbeddedImage::lenaColor) == 49152, "Image size is invalid"); 4592f083884Ss.makeev_local 4602f083884Ss.makeev_local int stride = 384; 4612f083884Ss.makeev_local 4622f083884Ss.makeev_local MT::ArrayView<uint8> srcImage((void*)&EmbeddedImage::lenaColor[0], MT_ARRAY_SIZE(EmbeddedImage::lenaColor)); 4632f083884Ss.makeev_local 4642f083884Ss.makeev_local CompressDxt compressTask(128, 128, stride, srcImage); 4652f083884Ss.makeev_local MT_ASSERT ((compressTask.width & 3) == 0 && (compressTask.height & 3) == 0, "Image size must be a multiple of 4"); 4662f083884Ss.makeev_local 4672f083884Ss.makeev_local #ifdef MT_INSTRUMENTED_BUILD 4682f083884Ss.makeev_local Microprofile profiler; 4692f083884Ss.makeev_local MT::TaskScheduler scheduler(0, &profiler); 4702f083884Ss.makeev_local #else 4712f083884Ss.makeev_local MT::TaskScheduler scheduler; 4722f083884Ss.makeev_local #endif 4732f083884Ss.makeev_local 4742f083884Ss.makeev_local int workersCount = (int)scheduler.GetWorkersCount(); 4752f083884Ss.makeev_local printf("Scheduler started, %d workers\n", workersCount); 4762f083884Ss.makeev_local 4772f083884Ss.makeev_local printf("Compress image\n"); 4782f083884Ss.makeev_local scheduler.RunAsync(MT::TaskGroup::Default(), &compressTask, 1); 4792f083884Ss.makeev_local 4802f083884Ss.makeev_local Wait(scheduler); 4812f083884Ss.makeev_local 4822f083884Ss.makeev_local DecompressDxt decompressTask(compressTask.dxtBlocks, compressTask.blkWidth, compressTask.blkHeight); 4832f083884Ss.makeev_local compressTask.dxtBlocks = MT::ArrayView<uint8>(); //transfer memory ownership to Decompress task 4842f083884Ss.makeev_local 4852f083884Ss.makeev_local printf("Decompress image\n"); 4862f083884Ss.makeev_local scheduler.RunAsync(MT::TaskGroup::Default(), &decompressTask, 1); 4872f083884Ss.makeev_local 4882f083884Ss.makeev_local Wait(scheduler); 4892f083884Ss.makeev_local 4902f083884Ss.makeev_local /* 4912f083884Ss.makeev_local //save compressed image 4922f083884Ss.makeev_local { 4932f083884Ss.makeev_local FILE * file = fopen("lena_dxt1.dds", "w+b"); 4942f083884Ss.makeev_local fwrite(&EmbeddedImage::ddsHeader[0], MT_ARRAY_SIZE(EmbeddedImage::ddsHeader), 1, file); 4952f083884Ss.makeev_local fwrite(decompressTask.dxtBlocks, decompressTask.blkWidth * decompressTask.blkHeight * 8, 1, file); 4962f083884Ss.makeev_local fclose(file); 4972f083884Ss.makeev_local } 4982f083884Ss.makeev_local 4992f083884Ss.makeev_local //save uncompressed image 5002f083884Ss.makeev_local { 5012f083884Ss.makeev_local FILE * file = fopen("lena_rgb.raw", "w+b"); 5022f083884Ss.makeev_local fwrite(decompressTask.decompressedImage, decompressTask.blkWidth * decompressTask.blkHeight * 48, 1, file); 5032f083884Ss.makeev_local fclose(file); 5042f083884Ss.makeev_local } 5052f083884Ss.makeev_local */ 5062f083884Ss.makeev_local 5072f083884Ss.makeev_local printf("Compare images\n"); 5082f083884Ss.makeev_local bool imagesEqual = CompareImagesPSNR(&srcImage[0], &decompressTask.decompressedImage[0], MT_ARRAY_SIZE(EmbeddedImage::lenaColor), 8.0); 5092f083884Ss.makeev_local CHECK_EQUAL(true, imagesEqual); 5102f083884Ss.makeev_local 5112f083884Ss.makeev_local /* 5122f083884Ss.makeev_local #ifdef MT_INSTRUMENTED_BUILD 5132f083884Ss.makeev_local // waiting for profiler attach 5142f083884Ss.makeev_local printf("Press any key to continue\n"); 5152f083884Ss.makeev_local while(true) 5162f083884Ss.makeev_local { 5172f083884Ss.makeev_local if (_kbhit() != 0) 5182f083884Ss.makeev_local { 5192f083884Ss.makeev_local break; 5202f083884Ss.makeev_local } 5212f083884Ss.makeev_local } 5222f083884Ss.makeev_local #endif 5232f083884Ss.makeev_local */ 5242f083884Ss.makeev_local } 5252f083884Ss.makeev_local 5262f083884Ss.makeev_local 5272f083884Ss.makeev_local } 528