summaryrefslogtreecommitdiffstats
path: root/libs/ui
diff options
context:
space:
mode:
Diffstat (limited to 'libs/ui')
-rw-r--r--libs/ui/Fence.cpp40
-rw-r--r--libs/ui/GraphicBuffer.cpp37
-rw-r--r--libs/ui/PixelFormat.cpp137
-rw-r--r--libs/ui/Rect.cpp85
-rw-r--r--libs/ui/Region.cpp9
-rw-r--r--libs/ui/tests/Android.mk5
-rw-r--r--libs/ui/tests/mat_test.cpp139
-rw-r--r--libs/ui/tests/vec_test.cpp256
8 files changed, 528 insertions, 180 deletions
diff --git a/libs/ui/Fence.cpp b/libs/ui/Fence.cpp
index 464ee86..93ec0ce 100644
--- a/libs/ui/Fence.cpp
+++ b/libs/ui/Fence.cpp
@@ -127,37 +127,49 @@ nsecs_t Fence::getSignalTime() const {
}
size_t Fence::getFlattenedSize() const {
- return 0;
+ return 1;
}
size_t Fence::getFdCount() const {
return isValid() ? 1 : 0;
}
-status_t Fence::flatten(void* buffer, size_t size, int fds[],
- size_t count) const {
- if (size != getFlattenedSize() || count != getFdCount()) {
- return BAD_VALUE;
+status_t Fence::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const {
+ if (size < getFlattenedSize() || count < getFdCount()) {
+ return NO_MEMORY;
}
-
+ FlattenableUtils::write(buffer, size, getFdCount());
if (isValid()) {
- fds[0] = mFenceFd;
+ *fds++ = mFenceFd;
+ count--;
}
return NO_ERROR;
}
-status_t Fence::unflatten(void const* buffer, size_t size, int fds[],
- size_t count) {
- if (size != 0 || (count != 0 && count != 1)) {
- return BAD_VALUE;
- }
+status_t Fence::unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count) {
if (mFenceFd != -1) {
// Don't unflatten if we already have a valid fd.
return INVALID_OPERATION;
}
- if (count == 1) {
- mFenceFd = fds[0];
+ if (size < 1) {
+ return NO_MEMORY;
+ }
+
+ size_t numFds;
+ FlattenableUtils::read(buffer, size, numFds);
+
+ if (numFds > 1) {
+ return BAD_VALUE;
+ }
+
+ if (count < numFds) {
+ return NO_MEMORY;
+ }
+
+ if (numFds) {
+ mFenceFd = *fds++;
+ count--;
}
return NO_ERROR;
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 46a5a1d..8c325fd 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -36,8 +36,7 @@ namespace android {
GraphicBuffer::GraphicBuffer()
: BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
- mInitCheck(NO_ERROR), mIndex(-1)
-{
+ mInitCheck(NO_ERROR) {
width =
height =
stride =
@@ -49,7 +48,7 @@ GraphicBuffer::GraphicBuffer()
GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h,
PixelFormat reqFormat, uint32_t reqUsage)
: BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
- mInitCheck(NO_ERROR), mIndex(-1)
+ mInitCheck(NO_ERROR)
{
width =
height =
@@ -65,7 +64,7 @@ GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h,
uint32_t inStride, native_handle_t* inHandle, bool keepOwnership)
: BASE(), mOwner(keepOwnership ? ownHandle : ownNone),
mBufferMapper(GraphicBufferMapper::get()),
- mInitCheck(NO_ERROR), mIndex(-1)
+ mInitCheck(NO_ERROR)
{
width = w;
height = h;
@@ -78,7 +77,7 @@ GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h,
GraphicBuffer::GraphicBuffer(ANativeWindowBuffer* buffer, bool keepOwnership)
: BASE(), mOwner(keepOwnership ? ownHandle : ownNone),
mBufferMapper(GraphicBufferMapper::get()),
- mInitCheck(NO_ERROR), mIndex(-1), mWrappedBuffer(buffer)
+ mInitCheck(NO_ERROR), mWrappedBuffer(buffer)
{
width = buffer->width;
height = buffer->height;
@@ -209,9 +208,7 @@ size_t GraphicBuffer::getFdCount() const {
return handle ? handle->numFds : 0;
}
-status_t GraphicBuffer::flatten(void* buffer, size_t size,
- int fds[], size_t count) const
-{
+status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const {
size_t sizeNeeded = GraphicBuffer::getFlattenedSize();
if (size < sizeNeeded) return NO_MEMORY;
@@ -236,12 +233,16 @@ status_t GraphicBuffer::flatten(void* buffer, size_t size,
memcpy(&buf[8], h->data + h->numFds, h->numInts*sizeof(int));
}
+ buffer = reinterpret_cast<void*>(static_cast<int*>(buffer) + sizeNeeded);
+ size -= sizeNeeded;
+ fds += handle->numFds;
+ count -= handle->numFds;
+
return NO_ERROR;
}
-status_t GraphicBuffer::unflatten(void const* buffer, size_t size,
- int fds[], size_t count)
-{
+status_t GraphicBuffer::unflatten(
+ void const*& buffer, size_t& size, int const*& fds, size_t& count) {
if (size < 8*sizeof(int)) return NO_MEMORY;
int const* buf = static_cast<int const*>(buffer);
@@ -306,16 +307,12 @@ status_t GraphicBuffer::unflatten(void const* buffer, size_t size,
}
}
- return NO_ERROR;
-}
-
+ buffer = reinterpret_cast<void const*>(static_cast<int const*>(buffer) + sizeNeeded);
+ size -= sizeNeeded;
+ fds += numFds;
+ count -= numFds;
-void GraphicBuffer::setIndex(int index) {
- mIndex = index;
-}
-
-int GraphicBuffer::getIndex() const {
- return mIndex;
+ return NO_ERROR;
}
// ---------------------------------------------------------------------------
diff --git a/libs/ui/PixelFormat.cpp b/libs/ui/PixelFormat.cpp
index 3ced41d..d2d103a 100644
--- a/libs/ui/PixelFormat.cpp
+++ b/libs/ui/PixelFormat.cpp
@@ -21,123 +21,36 @@
namespace android {
// ----------------------------------------------------------------------------
-static const int COMPONENT_YUV = 0xFF;
-
-struct Info {
- size_t size;
- size_t bitsPerPixel;
- struct {
- uint8_t ah;
- uint8_t al;
- uint8_t rh;
- uint8_t rl;
- uint8_t gh;
- uint8_t gl;
- uint8_t bh;
- uint8_t bl;
- };
- uint8_t components;
-};
-
-static Info const sPixelFormatInfos[] = {
- { 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
- { 4, 32, {32,24, 8, 0, 16, 8, 24,16 }, PixelFormatInfo::RGBA },
- { 4, 24, { 0, 0, 8, 0, 16, 8, 24,16 }, PixelFormatInfo::RGB },
- { 3, 24, { 0, 0, 8, 0, 16, 8, 24,16 }, PixelFormatInfo::RGB },
- { 2, 16, { 0, 0, 16,11, 11, 5, 5, 0 }, PixelFormatInfo::RGB },
- { 4, 32, {32,24, 24,16, 16, 8, 8, 0 }, PixelFormatInfo::RGBA },
- { 2, 16, { 1, 0, 16,11, 11, 6, 6, 1 }, PixelFormatInfo::RGBA },
- { 2, 16, { 4, 0, 16,12, 12, 8, 8, 4 }, PixelFormatInfo::RGBA },
- { 1, 8, { 8, 0, 0, 0, 0, 0, 0, 0 }, PixelFormatInfo::ALPHA},
- { 1, 8, { 0, 0, 8, 0, 8, 0, 8, 0 }, PixelFormatInfo::L },
- { 2, 16, {16, 8, 8, 0, 8, 0, 8, 0 }, PixelFormatInfo::LA },
- { 1, 8, { 0, 0, 8, 5, 5, 2, 2, 0 }, PixelFormatInfo::RGB },
-};
-
-static const Info* gGetPixelFormatTable(size_t* numEntries) {
- if (numEntries) {
- *numEntries = sizeof(sPixelFormatInfos)/sizeof(Info);
- }
- return sPixelFormatInfos;
-}
-
-// ----------------------------------------------------------------------------
-
-size_t PixelFormatInfo::getScanlineSize(unsigned int width) const
-{
- size_t size;
- if (components == COMPONENT_YUV) {
- // YCbCr formats are different.
- size = (width * bitsPerPixel)>>3;
- } else {
- size = width * bytesPerPixel;
+ssize_t bytesPerPixel(PixelFormat format) {
+ switch (format) {
+ case PIXEL_FORMAT_RGBA_8888:
+ case PIXEL_FORMAT_RGBX_8888:
+ case PIXEL_FORMAT_BGRA_8888:
+ return 4;
+ case PIXEL_FORMAT_RGB_888:
+ return 3;
+ case PIXEL_FORMAT_RGB_565:
+ case PIXEL_FORMAT_RGBA_5551:
+ case PIXEL_FORMAT_RGBA_4444:
+ return 2;
}
- return size;
+ return BAD_VALUE;
}
-ssize_t bytesPerPixel(PixelFormat format)
-{
- PixelFormatInfo info;
- status_t err = getPixelFormatInfo(format, &info);
- return (err < 0) ? err : info.bytesPerPixel;
-}
-
-ssize_t bitsPerPixel(PixelFormat format)
-{
- PixelFormatInfo info;
- status_t err = getPixelFormatInfo(format, &info);
- return (err < 0) ? err : info.bitsPerPixel;
-}
-
-status_t getPixelFormatInfo(PixelFormat format, PixelFormatInfo* info)
-{
- if (format <= 0)
- return BAD_VALUE;
-
- if (info->version != sizeof(PixelFormatInfo))
- return INVALID_OPERATION;
-
- // YUV format from the HAL are handled here
+ssize_t bitsPerPixel(PixelFormat format) {
switch (format) {
- case HAL_PIXEL_FORMAT_YCbCr_422_SP:
- case HAL_PIXEL_FORMAT_YCbCr_422_I:
- info->bitsPerPixel = 16;
- goto done;
- case HAL_PIXEL_FORMAT_YCrCb_420_SP:
- case HAL_PIXEL_FORMAT_YV12:
- info->bitsPerPixel = 12;
- done:
- info->format = format;
- info->components = COMPONENT_YUV;
- info->bytesPerPixel = 1;
- info->h_alpha = 0;
- info->l_alpha = 0;
- info->h_red = info->h_green = info->h_blue = 8;
- info->l_red = info->l_green = info->l_blue = 0;
- return NO_ERROR;
+ case PIXEL_FORMAT_RGBA_8888:
+ case PIXEL_FORMAT_RGBX_8888:
+ case PIXEL_FORMAT_BGRA_8888:
+ return 32;
+ case PIXEL_FORMAT_RGB_888:
+ return 24;
+ case PIXEL_FORMAT_RGB_565:
+ case PIXEL_FORMAT_RGBA_5551:
+ case PIXEL_FORMAT_RGBA_4444:
+ return 16;
}
-
- size_t numEntries;
- const Info *i = gGetPixelFormatTable(&numEntries) + format;
- bool valid = uint32_t(format) < numEntries;
- if (!valid) {
- return BAD_INDEX;
- }
-
- info->format = format;
- info->bytesPerPixel = i->size;
- info->bitsPerPixel = i->bitsPerPixel;
- info->h_alpha = i->ah;
- info->l_alpha = i->al;
- info->h_red = i->rh;
- info->l_red = i->rl;
- info->h_green = i->gh;
- info->l_green = i->gl;
- info->h_blue = i->bh;
- info->l_blue = i->bl;
- info->components = i->components;
-
- return NO_ERROR;
+ return BAD_VALUE;
}
// ----------------------------------------------------------------------------
diff --git a/libs/ui/Rect.cpp b/libs/ui/Rect.cpp
index c4dd55b..b480f3a 100644
--- a/libs/ui/Rect.cpp
+++ b/libs/ui/Rect.cpp
@@ -20,11 +20,11 @@
namespace android {
static inline int32_t min(int32_t a, int32_t b) {
- return (a<b) ? a : b;
+ return (a < b) ? a : b;
}
static inline int32_t max(int32_t a, int32_t b) {
- return (a>b) ? a : b;
+ return (a > b) ? a : b;
}
void Rect::makeInvalid() {
@@ -34,18 +34,17 @@ void Rect::makeInvalid() {
bottom = -1;
}
-bool Rect::operator < (const Rect& rhs) const
-{
- if (top<rhs.top) {
+bool Rect::operator <(const Rect& rhs) const {
+ if (top < rhs.top) {
return true;
} else if (top == rhs.top) {
if (left < rhs.left) {
return true;
} else if (left == rhs.left) {
- if (bottom<rhs.bottom) {
+ if (bottom < rhs.bottom) {
return true;
} else if (bottom == rhs.bottom) {
- if (right<rhs.right) {
+ if (right < rhs.right) {
return true;
}
}
@@ -54,8 +53,7 @@ bool Rect::operator < (const Rect& rhs) const
return false;
}
-Rect& Rect::offsetTo(int32_t x, int32_t y)
-{
+Rect& Rect::offsetTo(int32_t x, int32_t y) {
right -= left - x;
bottom -= top - y;
left = x;
@@ -63,45 +61,41 @@ Rect& Rect::offsetTo(int32_t x, int32_t y)
return *this;
}
-Rect& Rect::offsetBy(int32_t x, int32_t y)
-{
+Rect& Rect::offsetBy(int32_t x, int32_t y) {
left += x;
- top += y;
- right+= x;
- bottom+=y;
+ top += y;
+ right += x;
+ bottom += y;
return *this;
}
-const Rect Rect::operator + (const Point& rhs) const
-{
- const Rect result(left+rhs.x, top+rhs.y, right+rhs.x, bottom+rhs.y);
+const Rect Rect::operator +(const Point& rhs) const {
+ const Rect result(left + rhs.x, top + rhs.y, right + rhs.x, bottom + rhs.y);
return result;
}
-const Rect Rect::operator - (const Point& rhs) const
-{
- const Rect result(left-rhs.x, top-rhs.y, right-rhs.x, bottom-rhs.y);
+const Rect Rect::operator -(const Point& rhs) const {
+ const Rect result(left - rhs.x, top - rhs.y, right - rhs.x, bottom - rhs.y);
return result;
}
-bool Rect::intersect(const Rect& with, Rect* result) const
-{
- result->left = max(left, with.left);
- result->top = max(top, with.top);
- result->right = min(right, with.right);
- result->bottom = min(bottom, with.bottom);
+bool Rect::intersect(const Rect& with, Rect* result) const {
+ result->left = max(left, with.left);
+ result->top = max(top, with.top);
+ result->right = min(right, with.right);
+ result->bottom = min(bottom, with.bottom);
return !(result->isEmpty());
}
Rect Rect::transform(uint32_t xform, int32_t width, int32_t height) const {
Rect result(*this);
if (xform & HAL_TRANSFORM_FLIP_H) {
- result = Rect(width - result.right, result.top,
- width - result.left, result.bottom);
+ result = Rect(width - result.right, result.top, width - result.left,
+ result.bottom);
}
if (xform & HAL_TRANSFORM_FLIP_V) {
- result = Rect(result.left, height - result.bottom,
- result.right, height - result.top);
+ result = Rect(result.left, height - result.bottom, result.right,
+ height - result.top);
}
if (xform & HAL_TRANSFORM_ROT_90) {
int left = height - result.bottom;
@@ -113,4 +107,35 @@ Rect Rect::transform(uint32_t xform, int32_t width, int32_t height) const {
return result;
}
+Rect Rect::reduce(const Rect& exclude) const {
+ Rect result;
+
+ uint32_t mask = 0;
+ mask |= (exclude.left > left) ? 1 : 0;
+ mask |= (exclude.top > top) ? 2 : 0;
+ mask |= (exclude.right < right) ? 4 : 0;
+ mask |= (exclude.bottom < bottom) ? 8 : 0;
+
+ if (mask == 0) {
+ // crop entirely covers us
+ result.clear();
+ } else {
+ result = *this;
+ if (!(mask & (mask - 1))) {
+ // power-of-2, i.e.: just one bit is set
+ if (mask & 1) {
+ result.right = exclude.left;
+ } else if (mask & 2) {
+ result.bottom = exclude.top;
+ } else if (mask & 4) {
+ result.left = exclude.right;
+ } else if (mask & 8) {
+ result.top = exclude.bottom;
+ }
+ }
+ }
+
+ return result;
+}
+
}; // namespace android
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index bf01488..e5abcf5 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -697,7 +697,7 @@ void Region::translate(Region& reg, int dx, int dy)
size_t count = reg.mStorage.size();
Rect* rects = reg.mStorage.editArray();
while (count) {
- rects->translate(dx, dy);
+ rects->offsetBy(dx, dy);
rects++;
count--;
}
@@ -715,14 +715,17 @@ void Region::translate(Region& dst, const Region& reg, int dx, int dy)
// ----------------------------------------------------------------------------
-size_t Region::getSize() const {
+size_t Region::getFlattenedSize() const {
return mStorage.size() * sizeof(Rect);
}
-status_t Region::flatten(void* buffer) const {
+status_t Region::flatten(void* buffer, size_t size) const {
#if VALIDATE_REGIONS
validate(*this, "Region::flatten");
#endif
+ if (size < mStorage.size() * sizeof(Rect)) {
+ return NO_MEMORY;
+ }
Rect* rects = reinterpret_cast<Rect*>(buffer);
memcpy(rects, mStorage.array(), mStorage.size() * sizeof(Rect));
return NO_ERROR;
diff --git a/libs/ui/tests/Android.mk b/libs/ui/tests/Android.mk
index 8b8e1d8..6f62a55 100644
--- a/libs/ui/tests/Android.mk
+++ b/libs/ui/tests/Android.mk
@@ -4,9 +4,12 @@ include $(CLEAR_VARS)
# Build the unit tests.
test_src_files := \
- Region_test.cpp
+ Region_test.cpp \
+ vec_test.cpp \
+ mat_test.cpp
shared_libraries := \
+ libutils \
libui
static_libraries := \
diff --git a/libs/ui/tests/mat_test.cpp b/libs/ui/tests/mat_test.cpp
new file mode 100644
index 0000000..a2c63ac
--- /dev/null
+++ b/libs/ui/tests/mat_test.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2013 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.
+ */
+
+#define LOG_TAG "RegionTest"
+
+#include <stdlib.h>
+#include <ui/Region.h>
+#include <ui/Rect.h>
+#include <gtest/gtest.h>
+
+#include <ui/mat4.h>
+
+namespace android {
+
+class MatTest : public testing::Test {
+protected:
+};
+
+TEST_F(MatTest, Basics) {
+ mat4 m0;
+ EXPECT_EQ(sizeof(mat4), sizeof(float)*16);
+}
+
+TEST_F(MatTest, ComparisonOps) {
+ mat4 m0;
+ mat4 m1(2);
+
+ EXPECT_TRUE(m0 == m0);
+ EXPECT_TRUE(m0 != m1);
+ EXPECT_FALSE(m0 != m0);
+ EXPECT_FALSE(m0 == m1);
+}
+
+TEST_F(MatTest, Constructors) {
+ mat4 m0;
+ ASSERT_EQ(m0[0].x, 1);
+ ASSERT_EQ(m0[0].y, 0);
+ ASSERT_EQ(m0[0].z, 0);
+ ASSERT_EQ(m0[0].w, 0);
+ ASSERT_EQ(m0[1].x, 0);
+ ASSERT_EQ(m0[1].y, 1);
+ ASSERT_EQ(m0[1].z, 0);
+ ASSERT_EQ(m0[1].w, 0);
+ ASSERT_EQ(m0[2].x, 0);
+ ASSERT_EQ(m0[2].y, 0);
+ ASSERT_EQ(m0[2].z, 1);
+ ASSERT_EQ(m0[2].w, 0);
+ ASSERT_EQ(m0[3].x, 0);
+ ASSERT_EQ(m0[3].y, 0);
+ ASSERT_EQ(m0[3].z, 0);
+ ASSERT_EQ(m0[3].w, 1);
+
+ mat4 m1(2);
+ mat4 m2(vec4(2));
+ mat4 m3(m2);
+
+ EXPECT_EQ(m1, m2);
+ EXPECT_EQ(m2, m3);
+ EXPECT_EQ(m3, m1);
+
+ mat4 m4(vec4(1), vec4(2), vec4(3), vec4(4));
+}
+
+TEST_F(MatTest, ArithmeticOps) {
+ mat4 m0;
+ mat4 m1(2);
+ mat4 m2(vec4(2));
+
+ m1 += m2;
+ EXPECT_EQ(mat4(4), m1);
+
+ m2 -= m1;
+ EXPECT_EQ(mat4(-2), m2);
+
+ m1 *= 2;
+ EXPECT_EQ(mat4(8), m1);
+
+ m1 /= 2;
+ EXPECT_EQ(mat4(4), m1);
+
+ m0 = -m0;
+ EXPECT_EQ(mat4(-1), m0);
+}
+
+TEST_F(MatTest, UnaryOps) {
+ const mat4 identity;
+ mat4 m0;
+
+ ++m0;
+ EXPECT_EQ(mat4( vec4(2,1,1,1), vec4(1,2,1,1), vec4(1,1,2,1), vec4(1,1,1,2) ), m0);
+ EXPECT_EQ(mat4( -vec4(2,1,1,1), -vec4(1,2,1,1), -vec4(1,1,2,1), -vec4(1,1,1,2) ), -m0);
+
+ --m0;
+ EXPECT_EQ(identity, m0);
+}
+
+TEST_F(MatTest, MiscOps) {
+ const mat4 identity;
+ mat4 m0;
+ EXPECT_EQ(4, trace(m0));
+
+ mat4 m1(vec4(1,2,3,4), vec4(5,6,7,8), vec4(9,10,11,12), vec4(13,14,15,16));
+ mat4 m2(vec4(1,5,9,13), vec4(2,6,10,14), vec4(3,7,11,15), vec4(4,8,12,16));
+ EXPECT_EQ(m1, transpose(m2));
+ EXPECT_EQ(m2, transpose(m1));
+ EXPECT_EQ(vec4(1,6,11,16), diag(m1));
+
+ EXPECT_EQ(identity, inverse(identity));
+
+ mat4 m3(vec4(4,3,0,0), vec4(3,2,0,0), vec4(0,0,1,0), vec4(0,0,0,1));
+ mat4 m3i(inverse(m3));
+ EXPECT_FLOAT_EQ(-2, m3i[0][0]);
+ EXPECT_FLOAT_EQ( 3, m3i[0][1]);
+ EXPECT_FLOAT_EQ( 3, m3i[1][0]);
+ EXPECT_FLOAT_EQ(-4, m3i[1][1]);
+
+ mat4 m3ii(inverse(m3i));
+ EXPECT_FLOAT_EQ(m3[0][0], m3ii[0][0]);
+ EXPECT_FLOAT_EQ(m3[0][1], m3ii[0][1]);
+ EXPECT_FLOAT_EQ(m3[1][0], m3ii[1][0]);
+ EXPECT_FLOAT_EQ(m3[1][1], m3ii[1][1]);
+
+ EXPECT_EQ(m1, m1*identity);
+}
+
+}; // namespace android
diff --git a/libs/ui/tests/vec_test.cpp b/libs/ui/tests/vec_test.cpp
new file mode 100644
index 0000000..00f737e
--- /dev/null
+++ b/libs/ui/tests/vec_test.cpp
@@ -0,0 +1,256 @@
+/*
+ * Copyright 2013 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.
+ */
+
+#define LOG_TAG "RegionTest"
+
+#include <stdlib.h>
+#include <ui/Region.h>
+#include <ui/Rect.h>
+#include <gtest/gtest.h>
+
+#include <ui/vec4.h>
+
+namespace android {
+
+class VecTest : public testing::Test {
+protected:
+};
+
+TEST_F(VecTest, Basics) {
+ vec4 v4;
+ vec3& v3(v4.xyz);
+
+ EXPECT_EQ(sizeof(vec4), sizeof(float)*4);
+ EXPECT_EQ(sizeof(vec3), sizeof(float)*3);
+ EXPECT_EQ(sizeof(vec2), sizeof(float)*2);
+ EXPECT_EQ((void*)&v3, (void*)&v4);
+}
+
+TEST_F(VecTest, Constructors) {
+ vec4 v0;
+ EXPECT_EQ(v0.x, 0);
+ EXPECT_EQ(v0.y, 0);
+ EXPECT_EQ(v0.z, 0);
+ EXPECT_EQ(v0.w, 0);
+
+ vec4 v1(1);
+ EXPECT_EQ(v1.x, 1);
+ EXPECT_EQ(v1.y, 1);
+ EXPECT_EQ(v1.z, 1);
+ EXPECT_EQ(v1.w, 1);
+
+ vec4 v2(1,2,3,4);
+ EXPECT_EQ(v2.x, 1);
+ EXPECT_EQ(v2.y, 2);
+ EXPECT_EQ(v2.z, 3);
+ EXPECT_EQ(v2.w, 4);
+
+ vec4 v3(v2);
+ EXPECT_EQ(v3.x, 1);
+ EXPECT_EQ(v3.y, 2);
+ EXPECT_EQ(v3.z, 3);
+ EXPECT_EQ(v3.w, 4);
+
+ vec4 v4(v3.xyz, 42);
+ EXPECT_EQ(v4.x, 1);
+ EXPECT_EQ(v4.y, 2);
+ EXPECT_EQ(v4.z, 3);
+ EXPECT_EQ(v4.w, 42);
+
+ vec4 v5(vec3(v2.xy, 42), 24);
+ EXPECT_EQ(v5.x, 1);
+ EXPECT_EQ(v5.y, 2);
+ EXPECT_EQ(v5.z, 42);
+ EXPECT_EQ(v5.w, 24);
+
+ tvec4<double> vd(2);
+ EXPECT_EQ(vd.x, 2);
+ EXPECT_EQ(vd.y, 2);
+ EXPECT_EQ(vd.z, 2);
+ EXPECT_EQ(vd.w, 2);
+}
+
+TEST_F(VecTest, Access) {
+ vec4 v0(1,2,3,4);
+ v0.x = 10;
+ v0.y = 20;
+ v0.z = 30;
+ v0.w = 40;
+ EXPECT_EQ(v0.x, 10);
+ EXPECT_EQ(v0.y, 20);
+ EXPECT_EQ(v0.z, 30);
+ EXPECT_EQ(v0.w, 40);
+
+ v0[0] = 100;
+ v0[1] = 200;
+ v0[2] = 300;
+ v0[3] = 400;
+ EXPECT_EQ(v0.x, 100);
+ EXPECT_EQ(v0.y, 200);
+ EXPECT_EQ(v0.z, 300);
+ EXPECT_EQ(v0.w, 400);
+
+ v0.xyz = vec3(1,2,3);
+ EXPECT_EQ(v0.x, 1);
+ EXPECT_EQ(v0.y, 2);
+ EXPECT_EQ(v0.z, 3);
+ EXPECT_EQ(v0.w, 400);
+}
+
+TEST_F(VecTest, UnaryOps) {
+ vec4 v0(1,2,3,4);
+
+ v0 += 1;
+ EXPECT_EQ(v0.x, 2);
+ EXPECT_EQ(v0.y, 3);
+ EXPECT_EQ(v0.z, 4);
+ EXPECT_EQ(v0.w, 5);
+
+ v0 -= 1;
+ EXPECT_EQ(v0.x, 1);
+ EXPECT_EQ(v0.y, 2);
+ EXPECT_EQ(v0.z, 3);
+ EXPECT_EQ(v0.w, 4);
+
+ v0 *= 2;
+ EXPECT_EQ(v0.x, 2);
+ EXPECT_EQ(v0.y, 4);
+ EXPECT_EQ(v0.z, 6);
+ EXPECT_EQ(v0.w, 8);
+
+ v0 /= 2;
+ EXPECT_EQ(v0.x, 1);
+ EXPECT_EQ(v0.y, 2);
+ EXPECT_EQ(v0.z, 3);
+ EXPECT_EQ(v0.w, 4);
+
+ vec4 v1(10, 20, 30, 40);
+
+ v0 += v1;
+ EXPECT_EQ(v0.x, 11);
+ EXPECT_EQ(v0.y, 22);
+ EXPECT_EQ(v0.z, 33);
+ EXPECT_EQ(v0.w, 44);
+
+ v0 -= v1;
+ EXPECT_EQ(v0.x, 1);
+ EXPECT_EQ(v0.y, 2);
+ EXPECT_EQ(v0.z, 3);
+ EXPECT_EQ(v0.w, 4);
+
+ v0 *= v1;
+ EXPECT_EQ(v0.x, 10);
+ EXPECT_EQ(v0.y, 40);
+ EXPECT_EQ(v0.z, 90);
+ EXPECT_EQ(v0.w, 160);
+
+ v0 /= v1;
+ EXPECT_EQ(v0.x, 1);
+ EXPECT_EQ(v0.y, 2);
+ EXPECT_EQ(v0.z, 3);
+ EXPECT_EQ(v0.w, 4);
+
+ ++v0;
+ EXPECT_EQ(v0.x, 2);
+ EXPECT_EQ(v0.y, 3);
+ EXPECT_EQ(v0.z, 4);
+ EXPECT_EQ(v0.w, 5);
+
+ ++++v0;
+ EXPECT_EQ(v0.x, 4);
+ EXPECT_EQ(v0.y, 5);
+ EXPECT_EQ(v0.z, 6);
+ EXPECT_EQ(v0.w, 7);
+
+ --v1;
+ EXPECT_EQ(v1.x, 9);
+ EXPECT_EQ(v1.y, 19);
+ EXPECT_EQ(v1.z, 29);
+ EXPECT_EQ(v1.w, 39);
+
+ v1 = -v1;
+ EXPECT_EQ(v1.x, -9);
+ EXPECT_EQ(v1.y, -19);
+ EXPECT_EQ(v1.z, -29);
+ EXPECT_EQ(v1.w, -39);
+
+ tvec4<double> dv(1,2,3,4);
+ v1 += dv;
+ EXPECT_EQ(v1.x, -8);
+ EXPECT_EQ(v1.y, -17);
+ EXPECT_EQ(v1.z, -26);
+ EXPECT_EQ(v1.w, -35);
+}
+
+TEST_F(VecTest, ComparisonOps) {
+ vec4 v0(1,2,3,4);
+ vec4 v1(10,20,30,40);
+
+ EXPECT_TRUE(v0 == v0);
+ EXPECT_TRUE(v0 != v1);
+ EXPECT_FALSE(v0 != v0);
+ EXPECT_FALSE(v0 == v1);
+}
+
+TEST_F(VecTest, ArithmeticOps) {
+ vec4 v0(1,2,3,4);
+ vec4 v1(10,20,30,40);
+
+ vec4 v2(v0 + v1);
+ EXPECT_EQ(v2.x, 11);
+ EXPECT_EQ(v2.y, 22);
+ EXPECT_EQ(v2.z, 33);
+ EXPECT_EQ(v2.w, 44);
+
+ v0 = v1 * 2;
+ EXPECT_EQ(v0.x, 20);
+ EXPECT_EQ(v0.y, 40);
+ EXPECT_EQ(v0.z, 60);
+ EXPECT_EQ(v0.w, 80);
+
+ v0 = 2 * v1;
+ EXPECT_EQ(v0.x, 20);
+ EXPECT_EQ(v0.y, 40);
+ EXPECT_EQ(v0.z, 60);
+ EXPECT_EQ(v0.w, 80);
+
+ tvec4<double> vd(2);
+ v0 = v1 * vd;
+ EXPECT_EQ(v0.x, 20);
+ EXPECT_EQ(v0.y, 40);
+ EXPECT_EQ(v0.z, 60);
+ EXPECT_EQ(v0.w, 80);
+}
+
+TEST_F(VecTest, ArithmeticFunc) {
+ vec3 east(1, 0, 0);
+ vec3 north(0, 1, 0);
+ vec3 up( cross(east, north) );
+ EXPECT_EQ(up, vec3(0,0,1));
+ EXPECT_EQ(dot(east, north), 0);
+ EXPECT_EQ(length(east), 1);
+ EXPECT_EQ(distance(east, north), sqrtf(2));
+
+ vec3 v0(1,2,3);
+ vec3 vn(normalize(v0));
+ EXPECT_FLOAT_EQ(1, length(vn));
+ EXPECT_FLOAT_EQ(length(v0), dot(v0, vn));
+
+ tvec3<double> vd(east);
+ EXPECT_EQ(length(vd), 1);
+}
+
+}; // namespace android