crimild::Bool encode( std::string key, containers::Array< T, U > &a ) { crimild::Size N = a.size(); encodeArrayBegin( key, N ); a.each( [ this, key ]( T &elem, crimild::Size i ) { auto itemKey = beginEncodingArrayElement( key, i ); encode( itemKey, elem ); endEncodingArrayElement( key, i ); }); encodeArrayEnd( key ); return true; }
void BufferGLTest::mapRangeExplicitFlush() { #ifndef MAGNUM_TARGET_GLES2 if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::map_buffer_range>()) CORRADE_SKIP(Extensions::GL::ARB::map_buffer_range::string() + std::string(" is not supported")); #else if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::map_buffer_range>()) CORRADE_SKIP(Extensions::GL::EXT::map_buffer_range::string() + std::string(" is not supported")); #endif constexpr char data[] = {2, 7, 5, 13, 25}; Buffer buffer; buffer.setData(data, Buffer::Usage::StaticDraw); /* Map, set byte, don't flush and unmap */ char* contents = reinterpret_cast<char*>(buffer.map(1, 4, Buffer::MapFlag::Write|Buffer::MapFlag::FlushExplicit)); CORRADE_VERIFY(contents); contents[2] = 99; CORRADE_VERIFY(buffer.unmap()); MAGNUM_VERIFY_NO_ERROR(); /* Unflushed range _might_ not be changed, thus nothing to test */ /* Map, set byte, flush and unmap */ contents = reinterpret_cast<char*>(buffer.map(1, 4, Buffer::MapFlag::Write|Buffer::MapFlag::FlushExplicit)); CORRADE_VERIFY(contents); contents[3] = 107; buffer.flushMappedRange(3, 1); MAGNUM_VERIFY_NO_ERROR(); CORRADE_VERIFY(buffer.unmap()); MAGNUM_VERIFY_NO_ERROR(); /* Flushed range should be changed */ /** @todo How to verify the contents in ES? */ #ifndef MAGNUM_TARGET_GLES Containers::Array<char> changedContents = buffer.data<char>(); CORRADE_COMPARE(changedContents.size(), 5); CORRADE_COMPARE(changedContents[4], 107); #endif }
void CompressIndicesTest::compressShort() { std::size_t indexCount; Mesh::IndexType indexType; Containers::Array<char> data; std::tie(indexCount, indexType, data) = MeshTools::compressIndices( std::vector<UnsignedInt>{1, 256, 0, 5}); CORRADE_COMPARE(indexCount, 4); CORRADE_VERIFY(indexType == Mesh::IndexType::UnsignedShort); if(!Utility::Endianness::isBigEndian()) { CORRADE_COMPARE(std::vector<char>(data.begin(), data.end()), (std::vector<char>{ 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x05, 0x00 })); } else { CORRADE_COMPARE(std::vector<char>(data.begin(), data.end()), (std::vector<char>{ 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05 })); } }
void ArrayTest::access() { Array a(7); for(std::size_t i = 0; i != 7; ++i) a[i] = i; CORRADE_COMPARE(a.data(), static_cast<int*>(a)); CORRADE_COMPARE(*(a.begin()+2), 2); CORRADE_COMPARE(a[4], 4); CORRADE_COMPARE(a.end()-a.begin(), a.size()); const auto b = Array::from(7, 3, 5, 4); CORRADE_COMPARE(b.data(), static_cast<const int*>(b)); CORRADE_COMPARE(b[2], 5); }
void BufferGLTest::copy() { Buffer buffer1; constexpr char data[] = {2, 7, 5, 13, 25}; buffer1.setData(data, BufferUsage::StaticCopy); Buffer buffer2; buffer2.setData({nullptr, 5}, BufferUsage::StaticRead); Buffer::copy(buffer1, buffer2, 1, 2, 3); MAGNUM_VERIFY_NO_ERROR(); /** @todo How to verify the contents in ES? */ #ifndef MAGNUM_TARGET_GLES const Containers::Array<char> subContents = buffer2.subData<char>(2, 3); CORRADE_COMPARE(subContents.size(), 3); CORRADE_COMPARE(subContents[0], 7); CORRADE_COMPARE(subContents[1], 5); CORRADE_COMPARE(subContents[2], 13); #endif }
std::optional<ImageData2D> JpegImporter::doImage2D(UnsignedInt) { /* Initialize structures */ jpeg_decompress_struct file; Containers::Array<JSAMPROW> rows; Containers::Array<char> data; /* Fugly error handling stuff */ /** @todo Get rid of this crap */ struct ErrorManager { jpeg_error_mgr jpegErrorManager; std::jmp_buf setjmpBuffer; } errorManager; file.err = jpeg_std_error(&errorManager.jpegErrorManager); errorManager.jpegErrorManager.error_exit = [](j_common_ptr info) { info->err->output_message(info); std::longjmp(reinterpret_cast<ErrorManager*>(info->err)->setjmpBuffer, 1); }; if(setjmp(errorManager.setjmpBuffer)) { Error() << "Trade::JpegImporter::image2D(): error while reading JPEG file"; jpeg_destroy_decompress(&file); return std::nullopt; } /* Open file */ jpeg_create_decompress(&file); jpeg_mem_src(&file, _in.begin(), _in.size()); /* Read file header, start decompression */ jpeg_read_header(&file, true); jpeg_start_decompress(&file); /* Image size and type */ const Vector2i size(file.output_width, file.output_height); static_assert(BITS_IN_JSAMPLE == 8, "Only 8-bit JPEG is supported"); constexpr PixelType type = PixelType::UnsignedByte; /* Image format */ PixelFormat format = {}; switch(file.out_color_space) { case JCS_GRAYSCALE: CORRADE_INTERNAL_ASSERT(file.out_color_components == 1); #ifdef MAGNUM_TARGET_GLES2 format = Context::hasCurrent() && Context::current().isExtensionSupported<Extensions::GL::EXT::texture_rg>() ? PixelFormat::Red : PixelFormat::Luminance; #else format = PixelFormat::Red; #endif break; case JCS_RGB: CORRADE_INTERNAL_ASSERT(file.out_color_components == 3); format = PixelFormat::RGB; break; /** @todo RGBA (only in libjpeg-turbo and probably ignored) */ default: Error() << "Trade::JpegImporter::image2D(): unsupported color space" << file.out_color_space; return std::nullopt; } /* Initialize data array, align rows to four bytes */ const std::size_t stride = ((size.x()*file.out_color_components*BITS_IN_JSAMPLE/8 + 3)/4)*4; data = Containers::Array<char>{stride*std::size_t(size.y())}; /* Read image row by row */ rows = Containers::Array<JSAMPROW>{std::size_t(size.y())}; for(Int i = 0; i != size.y(); ++i) rows[i] = reinterpret_cast<JSAMPROW>(data.data()) + (size.y() - i - 1)*stride; while(file.output_scanline < file.output_height) jpeg_read_scanlines(&file, rows + file.output_scanline, file.output_height - file.output_scanline); /* Cleanup */ jpeg_finish_decompress(&file); jpeg_destroy_decompress(&file); /* Always using the default 4-byte alignment */ return Trade::ImageData2D{format, type, size, std::move(data)}; }
namespace Magnum { namespace Test { struct BufferGLTest: AbstractOpenGLTester { explicit BufferGLTest(); void construct(); void constructCopy(); void constructMove(); void wrap(); void label(); #ifndef MAGNUM_TARGET_GLES2 void bindBase(); void bindRange(); #endif void data(); void map(); #ifdef CORRADE_TARGET_NACL void mapSub(); #endif void mapRange(); void mapRangeExplicitFlush(); #ifndef MAGNUM_TARGET_GLES2 void copy(); #endif void invalidate(); }; BufferGLTest::BufferGLTest() { addTests({&BufferGLTest::construct, &BufferGLTest::constructCopy, &BufferGLTest::constructMove, &BufferGLTest::wrap, &BufferGLTest::label, #ifndef MAGNUM_TARGET_GLES2 &BufferGLTest::bindBase, &BufferGLTest::bindRange, #endif &BufferGLTest::data, &BufferGLTest::map, #ifdef CORRADE_TARGET_NACL &BufferGLTest::mapSub, #endif &BufferGLTest::mapRange, &BufferGLTest::mapRangeExplicitFlush, #ifndef MAGNUM_TARGET_GLES2 &BufferGLTest::copy, #endif &BufferGLTest::invalidate}); } void BufferGLTest::construct() { { Buffer buffer; MAGNUM_VERIFY_NO_ERROR(); CORRADE_VERIFY(buffer.id() > 0); CORRADE_COMPARE(buffer.targetHint(), Buffer::TargetHint::Array); CORRADE_COMPARE(buffer.size(), 0); } MAGNUM_VERIFY_NO_ERROR(); } void BufferGLTest::constructCopy() { CORRADE_VERIFY(!(std::is_constructible<Buffer, const Buffer&>{})); CORRADE_VERIFY(!(std::is_assignable<Buffer, const Buffer&>{})); } void BufferGLTest::constructMove() { Buffer a; const Int id = a.id(); MAGNUM_VERIFY_NO_ERROR(); CORRADE_VERIFY(id > 0); Buffer b(std::move(a)); CORRADE_COMPARE(a.id(), 0); CORRADE_COMPARE(b.id(), id); Buffer c; const Int cId = c.id(); c = std::move(b); MAGNUM_VERIFY_NO_ERROR(); CORRADE_VERIFY(cId > 0); CORRADE_COMPARE(b.id(), cId); CORRADE_COMPARE(c.id(), id); } void BufferGLTest::wrap() { GLuint id; glGenBuffers(1, &id); /* Releasing won't delete anything */ { auto buffer = Buffer::wrap(id, ObjectFlag::DeleteOnDestruction); CORRADE_COMPARE(buffer.release(), id); } /* ...so we can wrap it again */ Buffer::wrap(id); glDeleteBuffers(1, &id); } void BufferGLTest::label() { /* No-Op version is tested in AbstractObjectGLTest */ if(!Context::current()->isExtensionSupported<Extensions::GL::KHR::debug>() && !Context::current()->isExtensionSupported<Extensions::GL::EXT::debug_label>()) CORRADE_SKIP("Required extension is not available"); Buffer buffer; CORRADE_COMPARE(buffer.label(), ""); MAGNUM_VERIFY_NO_ERROR(); buffer.setLabel("MyBuffer"); MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(buffer.label(), "MyBuffer"); } #ifndef MAGNUM_TARGET_GLES2 void BufferGLTest::bindBase() { #ifndef MAGNUM_TARGET_GLES if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::uniform_buffer_object>()) CORRADE_SKIP(Extensions::GL::ARB::uniform_buffer_object::string() + std::string{" is not supported."}); #endif Buffer buffer; buffer.bind(Buffer::Target::Uniform, 15); MAGNUM_VERIFY_NO_ERROR(); Buffer::unbind(Buffer::Target::Uniform, 15); MAGNUM_VERIFY_NO_ERROR(); Buffer::bind(Buffer::Target::Uniform, 7, {&buffer, nullptr, &buffer}); MAGNUM_VERIFY_NO_ERROR(); Buffer::unbind(Buffer::Target::Uniform, 7, 3); MAGNUM_VERIFY_NO_ERROR(); } void BufferGLTest::bindRange() { #ifndef MAGNUM_TARGET_GLES if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::uniform_buffer_object>()) CORRADE_SKIP(Extensions::GL::ARB::uniform_buffer_object::string() + std::string{" is not supported."}); #endif /* Check that we have correct offset alignment */ CORRADE_INTERNAL_ASSERT(256 % Buffer::uniformOffsetAlignment() == 0); Buffer buffer; buffer.setData({nullptr, 1024}, BufferUsage::StaticDraw) .bind(Buffer::Target::Uniform, 15, 256, 13); MAGNUM_VERIFY_NO_ERROR(); /** @todo C++14: get rid of std::make_tuple */ Buffer::bind(Buffer::Target::Uniform, 7, { std::make_tuple(&buffer, 256, 13), {}, std::make_tuple(&buffer, 768, 64)}); MAGNUM_VERIFY_NO_ERROR(); } #endif void BufferGLTest::data() { Buffer buffer; /* Plain array */ constexpr Int data[] = {2, 7, 5, 13, 25}; buffer.setData({data, 5}, BufferUsage::StaticDraw); MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(buffer.size(), 5*4); /* STL vector */ std::vector<Int> data2{2, 7, 5, 13, 25}; buffer.setData(data2, BufferUsage::StaticDraw); MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(buffer.size(), 5*4); /* STL array */ std::array<Int, 5> data3{{2, 7, 5, 13, 25}}; buffer.setData(data3, BufferUsage::StaticDraw); MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(buffer.size(), 5*4); /** @todo How to verify the contents in ES? */ #ifndef MAGNUM_TARGET_GLES const Containers::Array<Int> contents = buffer.data<Int>(); MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(contents.size(), 5); CORRADE_COMPARE(contents[0], 2); CORRADE_COMPARE(contents[1], 7); CORRADE_COMPARE(contents[2], 5); CORRADE_COMPARE(contents[3], 13); CORRADE_COMPARE(contents[4], 25); #endif /* Plain array */ constexpr Int subData[] = {125, 3, 15}; buffer.setSubData(4, {subData, 3}); MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(buffer.size(), 5*4); /* STL vector */ std::vector<Int> subData2{125, 3, 15}; buffer.setSubData(4, subData2); MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(buffer.size(), 5*4); /* STL array */ std::array<Int, 3> subData3{{125, 3, 15}}; buffer.setSubData(4, subData3); MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(buffer.size(), 5*4); /** @todo How to verify the contents in ES? */ #ifndef MAGNUM_TARGET_GLES const Containers::Array<Int> subContents = buffer.subData<Int>(4, 3); MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(subContents.size(), 3); CORRADE_COMPARE(subContents[0], 125); CORRADE_COMPARE(subContents[1], 3); CORRADE_COMPARE(subContents[2], 15); #endif } void BufferGLTest::map() { #ifdef MAGNUM_TARGET_GLES if(!Context::current()->isExtensionSupported<Extensions::GL::OES::mapbuffer>()) CORRADE_SKIP(Extensions::GL::OES::mapbuffer::string() + std::string(" is not supported")); #endif Buffer buffer; constexpr char data[] = {2, 7, 5, 13, 25}; buffer.setData(data, BufferUsage::StaticDraw); #ifndef MAGNUM_TARGET_GLES char* contents = buffer.map<char>(Buffer::MapAccess::ReadWrite); #else char* contents = buffer.map<char>(Buffer::MapAccess::WriteOnly); #endif MAGNUM_VERIFY_NO_ERROR(); CORRADE_VERIFY(contents); #ifndef MAGNUM_TARGET_GLES2 CORRADE_COMPARE(contents[2], 5); #endif contents[3] = 107; CORRADE_VERIFY(buffer.unmap()); MAGNUM_VERIFY_NO_ERROR(); /** @todo How to verify the contents in ES? */ #ifndef MAGNUM_TARGET_GLES Containers::Array<char> changedContents = buffer.data<char>(); CORRADE_COMPARE(changedContents.size(), 5); CORRADE_COMPARE(changedContents[3], 107); #endif } #ifdef CORRADE_TARGET_NACL void BufferGLTest::mapSub() { if(!Context::current()->isExtensionSupported<Extensions::GL::CHROMIUM::map_sub>()) CORRADE_SKIP(Extensions::GL::CHROMIUM::map_sub::string() + std::string(" is not supported")); Buffer buffer; constexpr char data[] = {2, 7, 5, 13, 25}; buffer.setData(data, BufferUsage::StaticDraw); char* contents = buffer.mapSub<char>(1, 4, Buffer::MapAccess::WriteOnly); MAGNUM_VERIFY_NO_ERROR(); CORRADE_VERIFY(contents); contents[3] = 107; buffer.unmapSub(); MAGNUM_VERIFY_NO_ERROR(); /** @todo How to verify the contents in ES? */ } #endif void BufferGLTest::mapRange() { #ifndef MAGNUM_TARGET_GLES if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::map_buffer_range>()) CORRADE_SKIP(Extensions::GL::ARB::map_buffer_range::string() + std::string(" is not supported")); #elif defined(MAGNUM_TARGET_GLES2) if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::map_buffer_range>()) CORRADE_SKIP(Extensions::GL::EXT::map_buffer_range::string() + std::string(" is not supported")); #endif constexpr char data[] = {2, 7, 5, 13, 25}; Buffer buffer; buffer.setData(data, BufferUsage::StaticDraw); char* contents = buffer.map<char>(1, 4, Buffer::MapFlag::Read|Buffer::MapFlag::Write); MAGNUM_VERIFY_NO_ERROR(); CORRADE_VERIFY(contents); CORRADE_COMPARE(contents[2], 13); contents[3] = 107; CORRADE_VERIFY(buffer.unmap()); MAGNUM_VERIFY_NO_ERROR(); /** @todo How to verify the contents in ES? */ #ifndef MAGNUM_TARGET_GLES Containers::Array<char> changedContents = buffer.data<char>(); CORRADE_COMPARE(changedContents.size(), 5); CORRADE_COMPARE(changedContents[4], 107); #endif } void BufferGLTest::mapRangeExplicitFlush() { #ifndef MAGNUM_TARGET_GLES if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::map_buffer_range>()) CORRADE_SKIP(Extensions::GL::ARB::map_buffer_range::string() + std::string(" is not supported")); #elif defined(MAGNUM_TARGET_GLES2) if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::map_buffer_range>()) CORRADE_SKIP(Extensions::GL::EXT::map_buffer_range::string() + std::string(" is not supported")); #endif constexpr char data[] = {2, 7, 5, 13, 25}; Buffer buffer; buffer.setData(data, BufferUsage::StaticDraw); /* Map, set byte, don't flush and unmap */ char* contents = buffer.map<char>(1, 4, Buffer::MapFlag::Write|Buffer::MapFlag::FlushExplicit); CORRADE_VERIFY(contents); contents[2] = 99; CORRADE_VERIFY(buffer.unmap()); MAGNUM_VERIFY_NO_ERROR(); /* Unflushed range _might_ not be changed, thus nothing to test */ /* Map, set byte, flush and unmap */ contents = buffer.map<char>(1, 4, Buffer::MapFlag::Write|Buffer::MapFlag::FlushExplicit); CORRADE_VERIFY(contents); contents[3] = 107; buffer.flushMappedRange(3, 1); MAGNUM_VERIFY_NO_ERROR(); CORRADE_VERIFY(buffer.unmap()); MAGNUM_VERIFY_NO_ERROR(); /* Flushed range should be changed */ /** @todo How to verify the contents in ES? */ #ifndef MAGNUM_TARGET_GLES Containers::Array<char> changedContents = buffer.data<char>(); CORRADE_COMPARE(changedContents.size(), 5); CORRADE_COMPARE(changedContents[4], 107); #endif } #ifndef MAGNUM_TARGET_GLES2 void BufferGLTest::copy() { Buffer buffer1; constexpr char data[] = {2, 7, 5, 13, 25}; buffer1.setData(data, BufferUsage::StaticCopy); Buffer buffer2; buffer2.setData({nullptr, 5}, BufferUsage::StaticRead); Buffer::copy(buffer1, buffer2, 1, 2, 3); MAGNUM_VERIFY_NO_ERROR(); /** @todo How to verify the contents in ES? */ #ifndef MAGNUM_TARGET_GLES const Containers::Array<char> subContents = buffer2.subData<char>(2, 3); CORRADE_COMPARE(subContents.size(), 3); CORRADE_COMPARE(subContents[0], 7); CORRADE_COMPARE(subContents[1], 5); CORRADE_COMPARE(subContents[2], 13); #endif } #endif void BufferGLTest::invalidate() { Buffer buffer; constexpr char data[] = {2, 7, 5, 13, 25}; buffer.setData(data, BufferUsage::StaticDraw); /* Just test that no errors are emitted */ buffer.invalidateSubData(3, 2); MAGNUM_VERIFY_NO_ERROR(); buffer.invalidateData(); MAGNUM_VERIFY_NO_ERROR(); } }}
void BufferGLTest::data() { Buffer buffer; /* Plain array */ constexpr Int data[] = {2, 7, 5, 13, 25}; buffer.setData({data, 5}, BufferUsage::StaticDraw); MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(buffer.size(), 5*4); /* STL vector */ std::vector<Int> data2{2, 7, 5, 13, 25}; buffer.setData(data2, BufferUsage::StaticDraw); MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(buffer.size(), 5*4); /* STL array */ std::array<Int, 5> data3{{2, 7, 5, 13, 25}}; buffer.setData(data3, BufferUsage::StaticDraw); MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(buffer.size(), 5*4); /** @todo How to verify the contents in ES? */ #ifndef MAGNUM_TARGET_GLES const Containers::Array<Int> contents = buffer.data<Int>(); MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(contents.size(), 5); CORRADE_COMPARE(contents[0], 2); CORRADE_COMPARE(contents[1], 7); CORRADE_COMPARE(contents[2], 5); CORRADE_COMPARE(contents[3], 13); CORRADE_COMPARE(contents[4], 25); #endif /* Plain array */ constexpr Int subData[] = {125, 3, 15}; buffer.setSubData(4, {subData, 3}); MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(buffer.size(), 5*4); /* STL vector */ std::vector<Int> subData2{125, 3, 15}; buffer.setSubData(4, subData2); MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(buffer.size(), 5*4); /* STL array */ std::array<Int, 3> subData3{{125, 3, 15}}; buffer.setSubData(4, subData3); MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(buffer.size(), 5*4); /** @todo How to verify the contents in ES? */ #ifndef MAGNUM_TARGET_GLES const Containers::Array<Int> subContents = buffer.subData<Int>(4, 3); MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(subContents.size(), 3); CORRADE_COMPARE(subContents[0], 125); CORRADE_COMPARE(subContents[1], 3); CORRADE_COMPARE(subContents[2], 15); #endif }
Containers::Optional<ImageData2D> JpegImporter::doImage2D(UnsignedInt) { /* Initialize structures */ jpeg_decompress_struct file; Containers::Array<char> data; /* Fugly error handling stuff */ /** @todo Get rid of this crap */ struct ErrorManager { jpeg_error_mgr jpegErrorManager; std::jmp_buf setjmpBuffer; char message[JMSG_LENGTH_MAX]{}; } errorManager; file.err = jpeg_std_error(&errorManager.jpegErrorManager); errorManager.jpegErrorManager.error_exit = [](j_common_ptr info) { auto& errorManager = *reinterpret_cast<ErrorManager*>(info->err); info->err->format_message(info, errorManager.message); std::longjmp(errorManager.setjmpBuffer, 1); }; if(setjmp(errorManager.setjmpBuffer)) { Error() << "Trade::JpegImporter::image2D(): error:" << errorManager.message; jpeg_destroy_decompress(&file); return Containers::NullOpt; } /* Open file */ jpeg_create_decompress(&file); jpeg_mem_src(&file, _in.begin(), _in.size()); /* Read file header, start decompression. On macOS (Travis, with Xcode 7.3) the compilation fails because "no known conversion from 'bool' to 'boolean' for 2nd argument" (boolean is an enum instead of a typedef to int there) so doing the conversion implicitly. */ jpeg_read_header(&file, boolean(true)); jpeg_start_decompress(&file); /* Image size and type */ const Vector2i size(file.output_width, file.output_height); static_assert(BITS_IN_JSAMPLE == 8, "Only 8-bit JPEG is supported"); /* Image format */ PixelFormat format; switch(file.out_color_space) { case JCS_GRAYSCALE: CORRADE_INTERNAL_ASSERT(file.out_color_components == 1); format = PixelFormat::R8Unorm; break; case JCS_RGB: CORRADE_INTERNAL_ASSERT(file.out_color_components == 3); format = PixelFormat::RGB8Unorm; break; /** @todo RGBA (only in libjpeg-turbo and probably ignored) */ default: Error() << "Trade::JpegImporter::image2D(): unsupported color space" << file.out_color_space; return Containers::NullOpt; } /* Initialize data array, align rows to four bytes */ const std::size_t stride = ((size.x()*file.out_color_components*BITS_IN_JSAMPLE/8 + 3)/4)*4; data = Containers::Array<char>{stride*std::size_t(size.y())}; /* Read image row by row */ while(file.output_scanline < file.output_height) { JSAMPROW row = reinterpret_cast<JSAMPROW>(data.data() + (size.y() - file.output_scanline - 1)*stride); jpeg_read_scanlines(&file, &row, 1); } /* Cleanup */ jpeg_finish_decompress(&file); jpeg_destroy_decompress(&file); /* Always using the default 4-byte alignment */ return Trade::ImageData2D{format, size, std::move(data)}; }
namespace Corrade { namespace Containers { namespace Test { struct ArrayTest: TestSuite::Tester { explicit ArrayTest(); void constructEmpty(); void constructNullptr(); void constructDefaultInit(); void constructValueInit(); void constructNoInit(); void constructDirectInit(); void construct(); void constructFromExisting(); void constructZeroSize(); void constructMove(); void constructFrom(); void constructFromChar(); void boolConversion(); void pointerConversion(); void emptyCheck(); void access(); void rvalueArrayAccess(); void rangeBasedFor(); void slice(); void sliceToStatic(); void release(); void customDeleter(); void customDeleterType(); }; typedef Containers::Array<int> Array; ArrayTest::ArrayTest() { addTests({&ArrayTest::constructEmpty, &ArrayTest::constructNullptr, &ArrayTest::constructDefaultInit, &ArrayTest::constructValueInit, &ArrayTest::constructNoInit, &ArrayTest::constructDirectInit, &ArrayTest::construct, &ArrayTest::constructFromExisting, &ArrayTest::constructZeroSize, &ArrayTest::constructMove, &ArrayTest::constructFrom, &ArrayTest::constructFromChar, &ArrayTest::boolConversion, &ArrayTest::pointerConversion, &ArrayTest::emptyCheck, &ArrayTest::access, &ArrayTest::rvalueArrayAccess, &ArrayTest::rangeBasedFor, &ArrayTest::slice, &ArrayTest::sliceToStatic, &ArrayTest::release, &ArrayTest::customDeleter, &ArrayTest::customDeleterType}); } void ArrayTest::constructEmpty() { const Array a; CORRADE_VERIFY(a == nullptr); CORRADE_COMPARE(a.size(), 0); /* Zero-length should not call new */ const std::size_t size = 0; const Array b(size); CORRADE_VERIFY(b == nullptr); CORRADE_COMPARE(b.size(), 0); } void ArrayTest::constructNullptr() { const Array c(nullptr); CORRADE_VERIFY(c == nullptr); CORRADE_COMPARE(c.size(), 0); /* Implicit construction from nullptr should be allowed */ CORRADE_VERIFY((std::is_convertible<std::nullptr_t, Array>::value)); } void ArrayTest::construct() { const Array a(5); CORRADE_VERIFY(a != nullptr); CORRADE_COMPARE(a.size(), 5); /* Implicit construction from std::size_t is not allowed */ CORRADE_VERIFY(!(std::is_convertible<std::size_t, Array>::value)); } void ArrayTest::constructFromExisting() { int* a = new int[25]; Array b{a, 25}; CORRADE_VERIFY(b == a); CORRADE_COMPARE(b.size(), 25); } void ArrayTest::constructDefaultInit() { const Array a{DefaultInit, 5}; CORRADE_VERIFY(a); CORRADE_COMPARE(a.size(), 5); } void ArrayTest::constructValueInit() { const Array a{ValueInit, 2}; CORRADE_VERIFY(a); CORRADE_COMPARE(a.size(), 2); CORRADE_COMPARE(a[0], 0); CORRADE_COMPARE(a[1], 0); } namespace { struct Foo { static int constructorCallCount; Foo() { ++constructorCallCount; } }; int Foo::constructorCallCount = 0; } void ArrayTest::constructNoInit() { const Containers::Array<Foo> a{NoInit, 5}; CORRADE_VERIFY(a); CORRADE_COMPARE(a.size(), 5); CORRADE_COMPARE(Foo::constructorCallCount, 0); const Containers::Array<Foo> b{DefaultInit, 7}; CORRADE_COMPARE(Foo::constructorCallCount, 7); } void ArrayTest::constructDirectInit() { const Array a{DirectInit, 2, -37}; CORRADE_VERIFY(a); CORRADE_COMPARE(a.size(), 2); CORRADE_COMPARE(a[0], -37); CORRADE_COMPARE(a[1], -37); } void ArrayTest::constructZeroSize() { const Array a(0); CORRADE_VERIFY(a == nullptr); CORRADE_COMPARE(a.size(), 0); } void ArrayTest::constructMove() { Array a(5); CORRADE_VERIFY(a); const int* const ptr = a; Array b(std::move(a)); CORRADE_VERIFY(a == nullptr); CORRADE_VERIFY(b == ptr); CORRADE_COMPARE(a.size(), 0); CORRADE_COMPARE(b.size(), 5); Array c; c = std::move(b); CORRADE_VERIFY(b == nullptr); CORRADE_VERIFY(c == ptr); CORRADE_COMPARE(b.size(), 0); CORRADE_COMPARE(c.size(), 5); } void ArrayTest::constructFrom() { Array a = Array::from(1, 3, 127, -48); CORRADE_VERIFY(a); CORRADE_COMPARE(a.size(), 4); CORRADE_COMPARE(a[0], 1); CORRADE_COMPARE(a[1], 3); CORRADE_COMPARE(a[2], 127); CORRADE_COMPARE(a[3], -48); Array b = Array::from(); CORRADE_VERIFY(!b); } void ArrayTest::constructFromChar() { /* Verify that this compiles without "narrowing from int to char" errors */ const auto a = Containers::Array<char>::from(0x11, 0x22, 0x33); CORRADE_VERIFY(a); CORRADE_COMPARE(a[1], 0x22); } void ArrayTest::boolConversion() { CORRADE_VERIFY(Array(2)); CORRADE_VERIFY(!Array()); CORRADE_VERIFY(!(std::is_convertible<Array, int>::value)); } void ArrayTest::pointerConversion() { Array a(2); int* b = a; CORRADE_COMPARE(b, a.begin()); const Array c(3); const int* d = c; CORRADE_COMPARE(d, c.begin()); /* Pointer arithmetic */ const Array e(3); const int* f = e + 2; CORRADE_COMPARE(f, &e[2]); /* Verify that we can't convert rvalues */ CORRADE_VERIFY((std::is_convertible<Array&, int*>::value)); CORRADE_VERIFY((std::is_convertible<const Array&, const int*>::value)); { #ifdef CORRADE_GCC47_COMPATIBILITY CORRADE_EXPECT_FAIL("Rvalue references for *this are not supported in GCC < 4.8.1."); #endif CORRADE_VERIFY(!(std::is_convertible<Array, int*>::value)); CORRADE_VERIFY(!(std::is_convertible<Array&&, int*>::value)); } /* Deleting const&& overload and leaving only const& one will not, in fact, disable conversion of const Array&& to pointer, but rather make the conversion ambiguous, which is not what we want, as it breaks e.g. rvalueArrayAccess() test. */ { CORRADE_EXPECT_FAIL("I don't know how to properly disable conversion of const Array&& to pointer."); CORRADE_VERIFY(!(std::is_convertible<const Array, const int*>::value)); CORRADE_VERIFY(!(std::is_convertible<const Array&&, const int*>::value)); } } void ArrayTest::emptyCheck() { Array a; CORRADE_VERIFY(!a); CORRADE_VERIFY(a.empty()); Array b(5); CORRADE_VERIFY(b); CORRADE_VERIFY(!b.empty()); } void ArrayTest::access() { Array a(7); for(std::size_t i = 0; i != 7; ++i) a[i] = i; CORRADE_COMPARE(a.data(), static_cast<int*>(a)); CORRADE_COMPARE(*(a.begin()+2), 2); CORRADE_COMPARE(a[4], 4); CORRADE_COMPARE(a.end()-a.begin(), a.size()); const auto b = Array::from(7, 3, 5, 4); CORRADE_COMPARE(b.data(), static_cast<const int*>(b)); CORRADE_COMPARE(b[2], 5); } void ArrayTest::rvalueArrayAccess() { CORRADE_COMPARE(Array::from(1, 2, 3, 4)[2], 3); } void ArrayTest::rangeBasedFor() { Array a(5); for(auto& i: a) i = 3; CORRADE_COMPARE(a[0], 3); CORRADE_COMPARE(a[1], 3); CORRADE_COMPARE(a[2], 3); CORRADE_COMPARE(a[3], 3); CORRADE_COMPARE(a[4], 3); } void ArrayTest::slice() { Array a = Array::from(1, 2, 3, 4, 5); const Array ac = Array::from(1, 2, 3, 4, 5); ArrayView<int> b = a.slice(1, 4); CORRADE_COMPARE(b.size(), 3); CORRADE_COMPARE(b[0], 2); CORRADE_COMPARE(b[1], 3); CORRADE_COMPARE(b[2], 4); ArrayView<const int> bc = ac.slice(1, 4); CORRADE_COMPARE(bc.size(), 3); CORRADE_COMPARE(bc[0], 2); CORRADE_COMPARE(bc[1], 3); CORRADE_COMPARE(bc[2], 4); ArrayView<int> c = a.prefix(3); CORRADE_COMPARE(c.size(), 3); CORRADE_COMPARE(c[0], 1); CORRADE_COMPARE(c[1], 2); CORRADE_COMPARE(c[2], 3); ArrayView<const int> cc = ac.prefix(3); CORRADE_COMPARE(cc.size(), 3); CORRADE_COMPARE(cc[0], 1); CORRADE_COMPARE(cc[1], 2); CORRADE_COMPARE(cc[2], 3); ArrayView<int> d = a.suffix(2); CORRADE_COMPARE(d.size(), 3); CORRADE_COMPARE(d[0], 3); CORRADE_COMPARE(d[1], 4); CORRADE_COMPARE(d[2], 5); ArrayView<const int> dc = ac.suffix(2); CORRADE_COMPARE(dc.size(), 3); CORRADE_COMPARE(dc[0], 3); CORRADE_COMPARE(dc[1], 4); CORRADE_COMPARE(dc[2], 5); } void ArrayTest::sliceToStatic() { Array a = Array::from(1, 2, 3, 4, 5); const Array ac = Array::from(1, 2, 3, 4, 5); StaticArrayView<3, int> b = a.slice<3>(1); CORRADE_COMPARE(b[0], 2); CORRADE_COMPARE(b[1], 3); CORRADE_COMPARE(b[2], 4); StaticArrayView<3, const int> bc = ac.slice<3>(1); CORRADE_COMPARE(bc[0], 2); CORRADE_COMPARE(bc[1], 3); CORRADE_COMPARE(bc[2], 4); } void ArrayTest::release() { Array a(5); int* const data = a; int* const released = a.release(); delete[] released; CORRADE_COMPARE(data, released); CORRADE_COMPARE(a.begin(), nullptr); CORRADE_COMPARE(a.size(), 0); } namespace { int CustomDeleterDeletedCount = 0; } void ArrayTest::customDeleter() { int data[25]{}; { Array a{data, 25, [](int*, std::size_t size) { CustomDeleterDeletedCount = size; }}; CORRADE_VERIFY(a == data); CORRADE_COMPARE(a.size(), 25); CORRADE_COMPARE(CustomDeleterDeletedCount, 0); } CORRADE_COMPARE(CustomDeleterDeletedCount, 25); } namespace { struct CustomDeleter { CustomDeleter(int& deletedCountOutput): deletedCount{deletedCountOutput} {} void operator()(int*, std::size_t size) { deletedCount = size; } int& deletedCount; }; } void ArrayTest::customDeleterType() { int data[25]{}; int deletedCount = 0; { Containers::Array<int, CustomDeleter> a{data, 25, CustomDeleter{deletedCount}}; CORRADE_VERIFY(a == data); CORRADE_COMPARE(a.size(), 25); CORRADE_COMPARE(deletedCount, 0); } CORRADE_COMPARE(deletedCount, 25); } }}}
namespace Magnum { namespace Test { class BufferGLTest: public AbstractOpenGLTester { public: explicit BufferGLTest(); void construct(); void data(); void map(); #ifdef MAGNUM_TARGET_GLES2 void mapSub(); #endif void mapRange(); void mapRangeExplicitFlush(); #ifndef MAGNUM_TARGET_GLES2 void copy(); #endif #ifndef MAGNUM_TARGET_GLES2 void invalidate(); #endif }; BufferGLTest::BufferGLTest() { addTests({&BufferGLTest::construct, &BufferGLTest::data, &BufferGLTest::map, #ifdef MAGNUM_TARGET_GLES2 &BufferGLTest::mapSub, #endif &BufferGLTest::mapRange, &BufferGLTest::mapRangeExplicitFlush, #ifndef MAGNUM_TARGET_GLES2 &BufferGLTest::copy, #endif #ifndef MAGNUM_TARGET_GLES &BufferGLTest::invalidate #endif }); } void BufferGLTest::construct() { Buffer buffer; MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(buffer.targetHint(), Buffer::Target::Array); CORRADE_COMPARE(buffer.size(), 0); MAGNUM_VERIFY_NO_ERROR(); } void BufferGLTest::data() { Buffer buffer; /* Plain array */ constexpr Int data[] = {2, 7, 5, 13, 25}; buffer.setData({data, 5}, Buffer::Usage::StaticDraw); MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(buffer.size(), 5*4); /* STL vector */ std::vector<Int> data2{2, 7, 5, 13, 25}; buffer.setData(data2, Buffer::Usage::StaticDraw); MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(buffer.size(), 5*4); /* STL array */ std::array<Int, 5> data3{{2, 7, 5, 13, 25}}; buffer.setData(data3, Buffer::Usage::StaticDraw); MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(buffer.size(), 5*4); /** @todo How to verify the contents in ES? */ #ifndef MAGNUM_TARGET_GLES const Containers::Array<Int> contents = buffer.data<Int>(); MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(contents.size(), 5); CORRADE_COMPARE(contents[0], 2); CORRADE_COMPARE(contents[1], 7); CORRADE_COMPARE(contents[2], 5); CORRADE_COMPARE(contents[3], 13); CORRADE_COMPARE(contents[4], 25); #endif /* Plain array */ constexpr Int subData[] = {125, 3, 15}; buffer.setSubData(4, {subData, 3}); MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(buffer.size(), 5*4); /* STL vector */ std::vector<Int> subData2{125, 3, 15}; buffer.setSubData(4, subData2); MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(buffer.size(), 5*4); /* STL array */ std::array<Int, 3> subData3{{125, 3, 15}}; buffer.setSubData(4, subData3); MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(buffer.size(), 5*4); /** @todo How to verify the contents in ES? */ #ifndef MAGNUM_TARGET_GLES const Containers::Array<Int> subContents = buffer.subData<Int>(4, 3); MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(subContents.size(), 3); CORRADE_COMPARE(subContents[0], 125); CORRADE_COMPARE(subContents[1], 3); CORRADE_COMPARE(subContents[2], 15); #endif } #ifndef MAGNUM_TARGET_GLES3 void BufferGLTest::map() { #ifdef MAGNUM_TARGET_GLES2 if(!Context::current()->isExtensionSupported<Extensions::GL::OES::mapbuffer>()) CORRADE_SKIP(Extensions::GL::OES::mapbuffer::string() + std::string(" is not supported")); #endif Buffer buffer; constexpr char data[] = {2, 7, 5, 13, 25}; buffer.setData(data, Buffer::Usage::StaticDraw); #ifndef MAGNUM_TARGET_GLES2 char* contents = reinterpret_cast<char*>(buffer.map(Buffer::MapAccess::ReadWrite)); #else char* contents = reinterpret_cast<char*>(buffer.map(Buffer::MapAccess::WriteOnly)); #endif MAGNUM_VERIFY_NO_ERROR(); CORRADE_VERIFY(contents); #ifndef MAGNUM_TARGET_GLES2 CORRADE_COMPARE(contents[2], 5); #endif contents[3] = 107; CORRADE_VERIFY(buffer.unmap()); MAGNUM_VERIFY_NO_ERROR(); /** @todo How to verify the contents in ES? */ #ifndef MAGNUM_TARGET_GLES Containers::Array<char> changedContents = buffer.data<char>(); CORRADE_COMPARE(changedContents.size(), 5); CORRADE_COMPARE(changedContents[3], 107); #endif } #endif #ifdef MAGNUM_TARGET_GLES2 void BufferGLTest::mapSub() { if(!Context::current()->isExtensionSupported<Extensions::GL::CHROMIUM::map_sub>()) CORRADE_SKIP(Extensions::GL::CHROMIUM::map_sub::string() + std::string(" is not supported")); Buffer buffer; constexpr char data[] = {2, 7, 5, 13, 25}; buffer.setData(data, Buffer::Usage::StaticDraw); char* contents = reinterpret_cast<char*>(buffer.mapSub(1, 4, Buffer::MapAccess::WriteOnly)); MAGNUM_VERIFY_NO_ERROR(); CORRADE_VERIFY(contents); contents[3] = 107; buffer.unmapSub(); MAGNUM_VERIFY_NO_ERROR(); /** @todo How to verify the contents in ES? */ } #endif void BufferGLTest::mapRange() { #ifndef MAGNUM_TARGET_GLES2 if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::map_buffer_range>()) CORRADE_SKIP(Extensions::GL::ARB::map_buffer_range::string() + std::string(" is not supported")); #else if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::map_buffer_range>()) CORRADE_SKIP(Extensions::GL::EXT::map_buffer_range::string() + std::string(" is not supported")); #endif constexpr char data[] = {2, 7, 5, 13, 25}; Buffer buffer; buffer.setData(data, Buffer::Usage::StaticDraw); char* contents = reinterpret_cast<char*>(buffer.map(1, 4, Buffer::MapFlag::Read|Buffer::MapFlag::Write)); MAGNUM_VERIFY_NO_ERROR(); CORRADE_VERIFY(contents); CORRADE_COMPARE(contents[2], 13); contents[3] = 107; CORRADE_VERIFY(buffer.unmap()); MAGNUM_VERIFY_NO_ERROR(); /** @todo How to verify the contents in ES? */ #ifndef MAGNUM_TARGET_GLES Containers::Array<char> changedContents = buffer.data<char>(); CORRADE_COMPARE(changedContents.size(), 5); CORRADE_COMPARE(changedContents[4], 107); #endif } void BufferGLTest::mapRangeExplicitFlush() { #ifndef MAGNUM_TARGET_GLES2 if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::map_buffer_range>()) CORRADE_SKIP(Extensions::GL::ARB::map_buffer_range::string() + std::string(" is not supported")); #else if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::map_buffer_range>()) CORRADE_SKIP(Extensions::GL::EXT::map_buffer_range::string() + std::string(" is not supported")); #endif constexpr char data[] = {2, 7, 5, 13, 25}; Buffer buffer; buffer.setData(data, Buffer::Usage::StaticDraw); /* Map, set byte, don't flush and unmap */ char* contents = reinterpret_cast<char*>(buffer.map(1, 4, Buffer::MapFlag::Write|Buffer::MapFlag::FlushExplicit)); CORRADE_VERIFY(contents); contents[2] = 99; CORRADE_VERIFY(buffer.unmap()); MAGNUM_VERIFY_NO_ERROR(); /* Unflushed range _might_ not be changed, thus nothing to test */ /* Map, set byte, flush and unmap */ contents = reinterpret_cast<char*>(buffer.map(1, 4, Buffer::MapFlag::Write|Buffer::MapFlag::FlushExplicit)); CORRADE_VERIFY(contents); contents[3] = 107; buffer.flushMappedRange(3, 1); MAGNUM_VERIFY_NO_ERROR(); CORRADE_VERIFY(buffer.unmap()); MAGNUM_VERIFY_NO_ERROR(); /* Flushed range should be changed */ /** @todo How to verify the contents in ES? */ #ifndef MAGNUM_TARGET_GLES Containers::Array<char> changedContents = buffer.data<char>(); CORRADE_COMPARE(changedContents.size(), 5); CORRADE_COMPARE(changedContents[4], 107); #endif } #ifndef MAGNUM_TARGET_GLES2 void BufferGLTest::copy() { Buffer buffer1; constexpr char data[] = {2, 7, 5, 13, 25}; buffer1.setData(data, Buffer::Usage::StaticDraw); Buffer buffer2; buffer2.setData({nullptr, 5}, Buffer::Usage::StaticDraw); Buffer::copy(buffer1, buffer2, 1, 2, 3); MAGNUM_VERIFY_NO_ERROR(); /** @todo How to verify the contents in ES? */ #ifndef MAGNUM_TARGET_GLES const Containers::Array<char> subContents = buffer2.subData<char>(2, 3); CORRADE_COMPARE(subContents.size(), 3); CORRADE_COMPARE(subContents[0], 7); CORRADE_COMPARE(subContents[1], 5); CORRADE_COMPARE(subContents[2], 13); #endif } #endif #ifndef MAGNUM_TARGET_GLES void BufferGLTest::invalidate() { if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::invalidate_subdata>()) CORRADE_SKIP(Extensions::GL::ARB::invalidate_subdata::string() + std::string(" is not supported")); Buffer buffer; constexpr char data[] = {2, 7, 5, 13, 25}; buffer.setData(data, Buffer::Usage::StaticDraw); /* Just test that no errors are emitted */ buffer.invalidateSubData(3, 2); MAGNUM_VERIFY_NO_ERROR(); buffer.invalidateData(); MAGNUM_VERIFY_NO_ERROR(); } #endif }}