12b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski/* 22b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski * Copyright 2014 Google Inc. 32b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski * 42b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski * Use of this source code is governed by a BSD-style license that can be 52b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski * found in the LICENSE file. 62b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski */ 72b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski 82b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski#include "SkBitmap.h" 92b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski#include "SkData.h" 102b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski#include "SkEndian.h" 112b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski#include "SkImageInfo.h" 122b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski#include "SkTextureCompressor.h" 132b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski#include "Test.h" 142b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski 152b310e46eb28bbbe375369e47068accbdfeff3a7krajcevskistatic const int kLATCBlockDimension = 4; 162b310e46eb28bbbe375369e47068accbdfeff3a7krajcevskistatic const int kLATCEncodedBlockSize = 8; 172b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski 182b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski/** 192b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski * Make sure that we properly fail when we don't have multiple of four image dimensions. 202b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski */ 212b310e46eb28bbbe375369e47068accbdfeff3a7krajcevskiDEF_TEST(CompressLATCFailDimensions, reporter) { 222b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski SkBitmap bitmap; 232b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski static const int kWidth = 63; 242b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski static const int kHeight = 63; 252b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski SkImageInfo info = SkImageInfo::MakeA8(kWidth, kHeight); 262b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski REPORTER_ASSERT(reporter, kWidth % kLATCBlockDimension != 0); 272b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski REPORTER_ASSERT(reporter, kHeight % kLATCBlockDimension != 0); 282b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski 292b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski bool setInfoSuccess = bitmap.setInfo(info); 302b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski REPORTER_ASSERT(reporter, setInfoSuccess); 312b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski 322b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski bool allocPixelsSuccess = bitmap.allocPixels(info); 332b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski REPORTER_ASSERT(reporter, allocPixelsSuccess); 342b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski bitmap.unlockPixels(); 352b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski 362b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski const SkTextureCompressor::Format kLATCFormat = SkTextureCompressor::kLATC_Format; 372b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski SkAutoDataUnref latcData(SkTextureCompressor::CompressBitmapToFormat(bitmap, kLATCFormat)); 382b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski REPORTER_ASSERT(reporter, NULL == latcData); 392b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski} 402b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski 412b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski/** 422b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski * Make sure that we properly fail when we don't have the correct bitmap type. 432b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski * LATC compressed textures can only be created from A8 bitmaps. 442b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski */ 452b310e46eb28bbbe375369e47068accbdfeff3a7krajcevskiDEF_TEST(CompressLATCFailColorType, reporter) { 462b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski SkBitmap bitmap; 472b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski static const int kWidth = 64; 482b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski static const int kHeight = 64; 492b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski SkImageInfo info = SkImageInfo::MakeN32Premul(kWidth, kHeight); 502b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski REPORTER_ASSERT(reporter, kWidth % kLATCBlockDimension == 0); 512b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski REPORTER_ASSERT(reporter, kHeight % kLATCBlockDimension == 0); 522b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski 532b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski bool setInfoSuccess = bitmap.setInfo(info); 542b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski REPORTER_ASSERT(reporter, setInfoSuccess); 552b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski 562b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski bool allocPixelsSuccess = bitmap.allocPixels(info); 572b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski REPORTER_ASSERT(reporter, allocPixelsSuccess); 582b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski bitmap.unlockPixels(); 592b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski 602b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski const SkTextureCompressor::Format kLATCFormat = SkTextureCompressor::kLATC_Format; 612b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski SkAutoDataUnref latcData(SkTextureCompressor::CompressBitmapToFormat(bitmap, kLATCFormat)); 622b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski REPORTER_ASSERT(reporter, NULL == latcData); 632b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski} 642b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski 652b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski/** 662b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski * Make sure that if we pass in a solid color bitmap that we get the appropriate results 672b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski */ 682b310e46eb28bbbe375369e47068accbdfeff3a7krajcevskiDEF_TEST(CompressLATC, reporter) { 692b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski SkBitmap bitmap; 702b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski static const int kWidth = 8; 712b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski static const int kHeight = 8; 722b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski SkImageInfo info = SkImageInfo::MakeA8(kWidth, kHeight); 732b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski 742b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski bool setInfoSuccess = bitmap.setInfo(info); 752b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski REPORTER_ASSERT(reporter, setInfoSuccess); 762b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski 772b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski bool allocPixelsSuccess = bitmap.allocPixels(info); 782b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski REPORTER_ASSERT(reporter, allocPixelsSuccess); 792b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski bitmap.unlockPixels(); 802b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski 812b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski REPORTER_ASSERT(reporter, kWidth % kLATCBlockDimension == 0); 822b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski REPORTER_ASSERT(reporter, kHeight % kLATCBlockDimension == 0); 832b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski const int numBlocks = (kWidth / kLATCBlockDimension) * (kHeight / kLATCBlockDimension); 842b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski const size_t kSizeToBe = static_cast<size_t>(kLATCEncodedBlockSize * numBlocks); 852b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski 862b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski for (int lum = 0; lum < 256; ++lum) { 872b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski bitmap.lockPixels(); 882b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski uint8_t* pixels = reinterpret_cast<uint8_t*>(bitmap.getPixels()); 892b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski REPORTER_ASSERT(reporter, NULL != pixels); 902b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski 912b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski for (int i = 0; i < kWidth*kHeight; ++i) { 922b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski pixels[i] = lum; 932b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski } 942b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski bitmap.unlockPixels(); 952b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski 962b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski const SkTextureCompressor::Format kLATCFormat = SkTextureCompressor::kLATC_Format; 972b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski SkAutoDataUnref latcData( 982b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski SkTextureCompressor::CompressBitmapToFormat(bitmap, kLATCFormat)); 992b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski REPORTER_ASSERT(reporter, NULL != latcData); 1002b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski REPORTER_ASSERT(reporter, kSizeToBe == latcData->size()); 1012b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski 1022b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski // Make sure that it all matches a given block encoding. If the entire bitmap 1032b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski // is a single value, then the lower two bytes of the encoded data should be that 1042b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski // value. The remaining indices can be any value, and since we try to match the pixels 1052b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski // in the chosen palette in increasing index order, each one should be zero. Hence, 1062b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski // the correct encoding should be just the two luminance values in the bottom two 1072b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski // bytes of the block encoding. 1082b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski const uint64_t kConstColorEncoding = SkEndian_SwapLE64(lum | (lum << 8)); 1092b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski const uint64_t* blockPtr = reinterpret_cast<const uint64_t*>(latcData->data()); 1102b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski for (int i = 0; i < numBlocks; ++i) { 1112b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski REPORTER_ASSERT(reporter, blockPtr[i] == kConstColorEncoding); 1122b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski } 1132b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski } 1142b310e46eb28bbbe375369e47068accbdfeff3a7krajcevski} 115