/*-------------------------------------------------------------------------
* drawElements C++ Base Library
* -----------------------------
*
* Copyright 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*//*!
* \file
* \brief Array buffer
*//*--------------------------------------------------------------------*/
#include "deArrayBuffer.hpp"
#if defined(DE_VALGRIND_BUILD) && defined(HAVE_VALGRIND_MEMCHECK_H)
# include <valgrind/memcheck.h>
#endif
namespace de
{
namespace detail
{
void* ArrayBuffer_AlignedMalloc (size_t numBytes, size_t alignment)
{
const int sizeAsInt = (int)numBytes;
void* ptr;
// int overflow
if (sizeAsInt < 0 || numBytes != (size_t)sizeAsInt)
throw std::bad_alloc();
// alloc
ptr = deAlignedMalloc(sizeAsInt, (int)alignment);
if (!ptr)
throw std::bad_alloc();
// mark area as undefined for valgrind
#if defined(DE_VALGRIND_BUILD) && defined(HAVE_VALGRIND_MEMCHECK_H)
if (RUNNING_ON_VALGRIND)
{
VALGRIND_MAKE_MEM_UNDEFINED(ptr, numBytes);
}
#endif
return ptr;
}
void ArrayBuffer_AlignedFree (void* ptr)
{
deAlignedFree(ptr);
}
} // detail
void ArrayBuffer_selfTest (void)
{
// default constructor
{
de::ArrayBuffer<int> buf;
DE_TEST_ASSERT(buf.size() == 0);
DE_TEST_ASSERT(buf.getPtr() == DE_NULL);
}
// sized constructor
{
de::ArrayBuffer<int> buf(4);
DE_TEST_ASSERT(buf.size() == 4);
DE_TEST_ASSERT(buf.getPtr() != DE_NULL);
}
// copy constructor
{
de::ArrayBuffer<int> originalBuf(4);
*originalBuf.getElementPtr(0) = 1;
*originalBuf.getElementPtr(1) = 2;
*originalBuf.getElementPtr(2) = 3;
*originalBuf.getElementPtr(3) = 4;
de::ArrayBuffer<int> targetBuf(originalBuf);
DE_TEST_ASSERT(*originalBuf.getElementPtr(0) == 1);
DE_TEST_ASSERT(*originalBuf.getElementPtr(1) == 2);
DE_TEST_ASSERT(*originalBuf.getElementPtr(2) == 3);
DE_TEST_ASSERT(*originalBuf.getElementPtr(3) == 4);
DE_TEST_ASSERT(*targetBuf.getElementPtr(0) == 1);
DE_TEST_ASSERT(*targetBuf.getElementPtr(1) == 2);
DE_TEST_ASSERT(*targetBuf.getElementPtr(2) == 3);
DE_TEST_ASSERT(*targetBuf.getElementPtr(3) == 4);
}
// assignment
{
de::ArrayBuffer<int> originalBuf(4);
*originalBuf.getElementPtr(0) = 1;
*originalBuf.getElementPtr(1) = 2;
*originalBuf.getElementPtr(2) = 3;
*originalBuf.getElementPtr(3) = 4;
de::ArrayBuffer<int> targetBuf(1);
targetBuf = originalBuf;
DE_TEST_ASSERT(*originalBuf.getElementPtr(0) == 1);
DE_TEST_ASSERT(*originalBuf.getElementPtr(1) == 2);
DE_TEST_ASSERT(*originalBuf.getElementPtr(2) == 3);
DE_TEST_ASSERT(*originalBuf.getElementPtr(3) == 4);
DE_TEST_ASSERT(*targetBuf.getElementPtr(0) == 1);
DE_TEST_ASSERT(*targetBuf.getElementPtr(1) == 2);
DE_TEST_ASSERT(*targetBuf.getElementPtr(2) == 3);
DE_TEST_ASSERT(*targetBuf.getElementPtr(3) == 4);
}
// clear
{
de::ArrayBuffer<int> buf(4);
buf.clear();
DE_TEST_ASSERT(buf.size() == 0);
DE_TEST_ASSERT(buf.getPtr() == DE_NULL);
}
// setStorage
{
de::ArrayBuffer<int> buf(4);
buf.setStorage(12);
DE_TEST_ASSERT(buf.size() == 12);
DE_TEST_ASSERT(buf.getPtr() != DE_NULL);
}
// setStorage, too large
{
de::ArrayBuffer<int> buf(4);
*buf.getElementPtr(0) = 1;
*buf.getElementPtr(1) = 2;
*buf.getElementPtr(2) = 3;
*buf.getElementPtr(3) = 4;
try
{
buf.setStorage((size_t)-1);
// setStorage succeeded, all ok
}
catch (std::bad_alloc&)
{
// alloc failed, check storage not changed
DE_TEST_ASSERT(buf.size() == 4);
DE_TEST_ASSERT(*buf.getElementPtr(0) == 1);
DE_TEST_ASSERT(*buf.getElementPtr(1) == 2);
DE_TEST_ASSERT(*buf.getElementPtr(2) == 3);
DE_TEST_ASSERT(*buf.getElementPtr(3) == 4);
}
}
// swap
{
de::ArrayBuffer<int> buf;
de::ArrayBuffer<int> source(4);
*source.getElementPtr(0) = 1;
*source.getElementPtr(1) = 2;
*source.getElementPtr(2) = 3;
*source.getElementPtr(3) = 4;
buf.swap(source);
DE_TEST_ASSERT(source.size() == 0);
DE_TEST_ASSERT(buf.size() == 4);
DE_TEST_ASSERT(*buf.getElementPtr(0) == 1);
DE_TEST_ASSERT(*buf.getElementPtr(1) == 2);
DE_TEST_ASSERT(*buf.getElementPtr(2) == 3);
DE_TEST_ASSERT(*buf.getElementPtr(3) == 4);
}
// default
{
de::ArrayBuffer<int> source(4);
int dst;
*source.getElementPtr(1) = 2;
deMemcpy(&dst, (int*)source.getPtr() + 1, sizeof(int));
DE_TEST_ASSERT(dst == 2);
}
// Aligned
{
de::ArrayBuffer<int, 64, sizeof(int)> source(4);
int dst;
*source.getElementPtr(1) = 2;
deMemcpy(&dst, (int*)source.getPtr() + 1, sizeof(int));
DE_TEST_ASSERT(dst == 2);
}
// Strided
{
de::ArrayBuffer<int, 4, 64> source(4);
int dst;
*source.getElementPtr(1) = 2;
deMemcpy(&dst, (deUint8*)source.getPtr() + 64, sizeof(int));
DE_TEST_ASSERT(dst == 2);
}
// Aligned, Strided
{
de::ArrayBuffer<int, 32, 64> source(4);
int dst;
*source.getElementPtr(1) = 2;
deMemcpy(&dst, (deUint8*)source.getPtr() + 64, sizeof(int));
DE_TEST_ASSERT(dst == 2);
}
}
} // de