content/canvas/compiledtest/TestWebGLElementArrayCache.cpp

branch
TOR_BUG_9701
changeset 11
deefc01c0e14
equal deleted inserted replaced
-1:000000000000 0:7004d9315718
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
4 * You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #include "mozilla/Assertions.h"
7
8 #include "WebGLElementArrayCache.cpp"
9
10 #include <cstdlib>
11 #include <iostream>
12 #include "nscore.h"
13 #include "nsTArray.h"
14
15 using namespace mozilla;
16
17 int gTestsPassed = 0;
18
19 void VerifyImplFunction(bool condition, const char* file, int line)
20 {
21 if (condition) {
22 gTestsPassed++;
23 } else {
24 std::cerr << "Test failed at " << file << ":" << line << std::endl;
25 abort();
26 }
27 }
28
29 #define VERIFY(condition) \
30 VerifyImplFunction((condition), __FILE__, __LINE__)
31
32 void MakeRandomVector(nsTArray<uint8_t>& a, size_t size) {
33 a.SetLength(size);
34 // only the most-significant bits of rand() are reasonably random.
35 // RAND_MAX can be as low as 0x7fff, and we need 8 bits for the result, so we can only
36 // ignore the 7 least significant bits.
37 for (size_t i = 0; i < size; i++)
38 a[i] = static_cast<uint8_t>((unsigned int)(rand()) >> 7);
39 }
40
41 template<typename T>
42 T RandomInteger(T a, T b)
43 {
44 T result(a + rand() % (b - a + 1));
45 return result;
46 }
47
48 template<typename T>
49 GLenum GLType()
50 {
51 switch (sizeof(T))
52 {
53 case 4: return LOCAL_GL_UNSIGNED_INT;
54 case 2: return LOCAL_GL_UNSIGNED_SHORT;
55 case 1: return LOCAL_GL_UNSIGNED_BYTE;
56 default:
57 VERIFY(false);
58 return 0;
59 }
60 }
61
62 template<typename T>
63 void CheckValidateOneType(WebGLElementArrayCache& c, size_t firstByte, size_t countBytes)
64 {
65 size_t first = firstByte / sizeof(T);
66 size_t count = countBytes / sizeof(T);
67
68 GLenum type = GLType<T>();
69
70 T max = 0;
71 for (size_t i = 0; i < count; i++)
72 if (c.Element<T>(first + i) > max)
73 max = c.Element<T>(first + i);
74
75 VERIFY(c.Validate(type, max, first, count));
76 VERIFY(c.Validate(type, T(-1), first, count));
77 if (T(max + 1)) VERIFY(c.Validate(type, T(max + 1), first, count));
78 if (max > 0) {
79 VERIFY(!c.Validate(type, max - 1, first, count));
80 VERIFY(!c.Validate(type, 0, first, count));
81 }
82 }
83
84 void CheckValidate(WebGLElementArrayCache& c, size_t firstByte, size_t countBytes)
85 {
86 CheckValidateOneType<uint8_t>(c, firstByte, countBytes);
87 CheckValidateOneType<uint16_t>(c, firstByte, countBytes);
88 CheckValidateOneType<uint32_t>(c, firstByte, countBytes);
89 }
90
91 template<typename T>
92 void CheckSanity()
93 {
94 const size_t numElems = 64; // should be significantly larger than tree leaf size to
95 // ensure we exercise some nontrivial tree-walking
96 T data[numElems] = {1,0,3,1,2,6,5,4}; // intentionally specify only 8 elements for now
97 size_t numBytes = numElems * sizeof(T);
98 MOZ_ASSERT(numBytes == sizeof(data));
99
100 GLenum type = GLType<T>();
101
102 WebGLElementArrayCache c;
103 c.BufferData(data, numBytes);
104 VERIFY( c.Validate(type, 6, 0, 8));
105 VERIFY(!c.Validate(type, 5, 0, 8));
106 VERIFY( c.Validate(type, 3, 0, 3));
107 VERIFY(!c.Validate(type, 2, 0, 3));
108 VERIFY( c.Validate(type, 6, 2, 4));
109 VERIFY(!c.Validate(type, 5, 2, 4));
110
111 c.BufferSubData(5*sizeof(T), data, sizeof(T));
112 VERIFY( c.Validate(type, 5, 0, 8));
113 VERIFY(!c.Validate(type, 4, 0, 8));
114
115 // now test a somewhat larger size to ensure we exceed the size of a tree leaf
116 for(size_t i = 0; i < numElems; i++)
117 data[i] = numElems - i;
118 c.BufferData(data, numBytes);
119 VERIFY( c.Validate(type, numElems, 0, numElems));
120 VERIFY(!c.Validate(type, numElems - 1, 0, numElems));
121
122 MOZ_ASSERT(numElems > 10);
123 VERIFY( c.Validate(type, numElems - 10, 10, numElems - 10));
124 VERIFY(!c.Validate(type, numElems - 11, 10, numElems - 10));
125 }
126
127 template<typename T>
128 void CheckUintOverflow()
129 {
130 // This test is only for integer types smaller than uint32_t
131 static_assert(sizeof(T) < sizeof(uint32_t), "This test is only for integer types \
132 smaller than uint32_t");
133
134 const size_t numElems = 64; // should be significantly larger than tree leaf size to
135 // ensure we exercise some nontrivial tree-walking
136 T data[numElems];
137 size_t numBytes = numElems * sizeof(T);
138 MOZ_ASSERT(numBytes == sizeof(data));
139
140 GLenum type = GLType<T>();
141
142 WebGLElementArrayCache c;
143
144 for(size_t i = 0; i < numElems; i++)
145 data[i] = numElems - i;
146 c.BufferData(data, numBytes);
147
148 // bug 825205
149 uint32_t bigValWrappingToZero = uint32_t(T(-1)) + 1;
150 VERIFY( c.Validate(type, bigValWrappingToZero, 0, numElems));
151 VERIFY( c.Validate(type, bigValWrappingToZero - 1, 0, numElems));
152 VERIFY(!c.Validate(type, 0, 0, numElems));
153 }
154
155 int main(int argc, char *argv[])
156 {
157 srand(0); // do not want a random seed here.
158
159 CheckSanity<uint8_t>();
160 CheckSanity<uint16_t>();
161 CheckSanity<uint32_t>();
162
163 CheckUintOverflow<uint8_t>();
164 CheckUintOverflow<uint16_t>();
165
166 nsTArray<uint8_t> v, vsub;
167 WebGLElementArrayCache b;
168
169 for (int maxBufferSize = 1; maxBufferSize <= 4096; maxBufferSize *= 2) {
170 // See bug 800612. We originally had | repeat = min(maxBufferSize, 20) |
171 // and a real bug was only caught on Windows and not on Linux due to rand()
172 // producing different values. In that case, the minimum value by which to replace
173 // this 20 to reproduce the bug on Linux, was 25. Replacing it with 64 should give
174 // us some comfort margin.
175 int repeat = std::min(maxBufferSize, 64);
176 for (int i = 0; i < repeat; i++) {
177 size_t size = RandomInteger<size_t>(1, maxBufferSize);
178 MakeRandomVector(v, size);
179 b.BufferData(v.Elements(), size);
180 CheckValidate(b, 0, size);
181
182 for (int j = 0; j < 16; j++) {
183 for (int bufferSubDataCalls = 1; bufferSubDataCalls <= 8; bufferSubDataCalls *= 2) {
184 for (int validateCalls = 1; validateCalls <= 8; validateCalls *= 2) {
185
186 size_t offset = 0, subsize = 0;
187
188 for (int k = 0; k < bufferSubDataCalls; k++) {
189 offset = RandomInteger<size_t>(0, size);
190 subsize = RandomInteger<size_t>(0, size - offset);
191 MakeRandomVector(vsub, subsize);
192 b.BufferSubData(offset, vsub.Elements(), subsize);
193 }
194
195 for (int k = 0; k < validateCalls; k++) {
196 offset = RandomInteger<size_t>(0, size);
197 subsize = RandomInteger<size_t>(0, size - offset);
198 CheckValidate(b, offset, subsize);
199 }
200 } // validateCalls
201 } // bufferSubDataCalls
202 } // j
203 } // i
204 } // maxBufferSize
205
206 std::cerr << argv[0] << ": all " << gTestsPassed << " tests passed" << std::endl;
207 return 0;
208 }

mercurial