content/canvas/compiledtest/TestWebGLElementArrayCache.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/content/canvas/compiledtest/TestWebGLElementArrayCache.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,208 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     1.7 + * You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include "mozilla/Assertions.h"
    1.10 +
    1.11 +#include "WebGLElementArrayCache.cpp"
    1.12 +
    1.13 +#include <cstdlib>
    1.14 +#include <iostream>
    1.15 +#include "nscore.h"
    1.16 +#include "nsTArray.h"
    1.17 +
    1.18 +using namespace mozilla;
    1.19 +
    1.20 +int gTestsPassed = 0;
    1.21 +
    1.22 +void VerifyImplFunction(bool condition, const char* file, int line)
    1.23 +{
    1.24 +  if (condition) {
    1.25 +    gTestsPassed++;
    1.26 +  } else {
    1.27 +    std::cerr << "Test failed at " << file << ":" << line << std::endl;
    1.28 +    abort();
    1.29 +  }
    1.30 +}
    1.31 +
    1.32 +#define VERIFY(condition) \
    1.33 +    VerifyImplFunction((condition), __FILE__, __LINE__)
    1.34 +
    1.35 +void MakeRandomVector(nsTArray<uint8_t>& a, size_t size) {
    1.36 +  a.SetLength(size);
    1.37 +  // only the most-significant bits of rand() are reasonably random.
    1.38 +  // RAND_MAX can be as low as 0x7fff, and we need 8 bits for the result, so we can only
    1.39 +  // ignore the 7 least significant bits.
    1.40 +  for (size_t i = 0; i < size; i++)
    1.41 +    a[i] = static_cast<uint8_t>((unsigned int)(rand()) >> 7);
    1.42 +}
    1.43 +
    1.44 +template<typename T>
    1.45 +T RandomInteger(T a, T b)
    1.46 +{
    1.47 +  T result(a + rand() % (b - a + 1));
    1.48 +  return result;
    1.49 +}
    1.50 +
    1.51 +template<typename T>
    1.52 +GLenum GLType()
    1.53 +{
    1.54 +  switch (sizeof(T))
    1.55 +  {
    1.56 +    case 4:  return LOCAL_GL_UNSIGNED_INT;
    1.57 +    case 2:  return LOCAL_GL_UNSIGNED_SHORT;
    1.58 +    case 1:  return LOCAL_GL_UNSIGNED_BYTE;
    1.59 +    default:
    1.60 +      VERIFY(false);
    1.61 +      return 0;
    1.62 +  }
    1.63 +}
    1.64 +
    1.65 +template<typename T>
    1.66 +void CheckValidateOneType(WebGLElementArrayCache& c, size_t firstByte, size_t countBytes)
    1.67 +{
    1.68 +  size_t first = firstByte / sizeof(T);
    1.69 +  size_t count = countBytes / sizeof(T);
    1.70 +
    1.71 +  GLenum type = GLType<T>();
    1.72 +
    1.73 +  T max = 0;
    1.74 +  for (size_t i = 0; i < count; i++)
    1.75 +    if (c.Element<T>(first + i) > max)
    1.76 +      max = c.Element<T>(first + i);
    1.77 +
    1.78 +  VERIFY(c.Validate(type, max, first, count));
    1.79 +  VERIFY(c.Validate(type, T(-1), first, count));
    1.80 +  if (T(max + 1)) VERIFY(c.Validate(type, T(max + 1), first, count));
    1.81 +  if (max > 0) {
    1.82 +    VERIFY(!c.Validate(type, max - 1, first, count));
    1.83 +    VERIFY(!c.Validate(type, 0, first, count));
    1.84 +  }
    1.85 +}
    1.86 +
    1.87 +void CheckValidate(WebGLElementArrayCache& c, size_t firstByte, size_t countBytes)
    1.88 +{
    1.89 +  CheckValidateOneType<uint8_t>(c, firstByte, countBytes);
    1.90 +  CheckValidateOneType<uint16_t>(c, firstByte, countBytes);
    1.91 +  CheckValidateOneType<uint32_t>(c, firstByte, countBytes);
    1.92 +}
    1.93 +
    1.94 +template<typename T>
    1.95 +void CheckSanity()
    1.96 +{
    1.97 +  const size_t numElems = 64; // should be significantly larger than tree leaf size to
    1.98 +                        // ensure we exercise some nontrivial tree-walking
    1.99 +  T data[numElems] = {1,0,3,1,2,6,5,4}; // intentionally specify only 8 elements for now
   1.100 +  size_t numBytes = numElems * sizeof(T);
   1.101 +  MOZ_ASSERT(numBytes == sizeof(data));
   1.102 +
   1.103 +  GLenum type = GLType<T>();
   1.104 +
   1.105 +  WebGLElementArrayCache c;
   1.106 +  c.BufferData(data, numBytes);
   1.107 +  VERIFY( c.Validate(type, 6, 0, 8));
   1.108 +  VERIFY(!c.Validate(type, 5, 0, 8));
   1.109 +  VERIFY( c.Validate(type, 3, 0, 3));
   1.110 +  VERIFY(!c.Validate(type, 2, 0, 3));
   1.111 +  VERIFY( c.Validate(type, 6, 2, 4));
   1.112 +  VERIFY(!c.Validate(type, 5, 2, 4));
   1.113 +
   1.114 +  c.BufferSubData(5*sizeof(T), data, sizeof(T));
   1.115 +  VERIFY( c.Validate(type, 5, 0, 8));
   1.116 +  VERIFY(!c.Validate(type, 4, 0, 8));
   1.117 +
   1.118 +  // now test a somewhat larger size to ensure we exceed the size of a tree leaf
   1.119 +  for(size_t i = 0; i < numElems; i++)
   1.120 +    data[i] = numElems - i;
   1.121 +  c.BufferData(data, numBytes);
   1.122 +  VERIFY( c.Validate(type, numElems,     0, numElems));
   1.123 +  VERIFY(!c.Validate(type, numElems - 1, 0, numElems));
   1.124 +
   1.125 +  MOZ_ASSERT(numElems > 10);
   1.126 +  VERIFY( c.Validate(type, numElems - 10, 10, numElems - 10));
   1.127 +  VERIFY(!c.Validate(type, numElems - 11, 10, numElems - 10));
   1.128 +}
   1.129 +
   1.130 +template<typename T>
   1.131 +void CheckUintOverflow()
   1.132 +{
   1.133 +  // This test is only for integer types smaller than uint32_t
   1.134 +  static_assert(sizeof(T) < sizeof(uint32_t), "This test is only for integer types \
   1.135 +                smaller than uint32_t");
   1.136 +
   1.137 +  const size_t numElems = 64; // should be significantly larger than tree leaf size to
   1.138 +                              // ensure we exercise some nontrivial tree-walking
   1.139 +  T data[numElems];
   1.140 +  size_t numBytes = numElems * sizeof(T);
   1.141 +  MOZ_ASSERT(numBytes == sizeof(data));
   1.142 +
   1.143 +  GLenum type = GLType<T>();
   1.144 +
   1.145 +  WebGLElementArrayCache c;
   1.146 +
   1.147 +  for(size_t i = 0; i < numElems; i++)
   1.148 +    data[i] = numElems - i;
   1.149 +  c.BufferData(data, numBytes);
   1.150 +
   1.151 +  // bug 825205
   1.152 +  uint32_t bigValWrappingToZero = uint32_t(T(-1)) + 1;
   1.153 +  VERIFY( c.Validate(type, bigValWrappingToZero,     0, numElems));
   1.154 +  VERIFY( c.Validate(type, bigValWrappingToZero - 1, 0, numElems));
   1.155 +  VERIFY(!c.Validate(type,                        0, 0, numElems));
   1.156 +}
   1.157 +
   1.158 +int main(int argc, char *argv[])
   1.159 +{
   1.160 +  srand(0); // do not want a random seed here.
   1.161 +
   1.162 +  CheckSanity<uint8_t>();
   1.163 +  CheckSanity<uint16_t>();
   1.164 +  CheckSanity<uint32_t>();
   1.165 +
   1.166 +  CheckUintOverflow<uint8_t>();
   1.167 +  CheckUintOverflow<uint16_t>();
   1.168 +
   1.169 +  nsTArray<uint8_t> v, vsub;
   1.170 +  WebGLElementArrayCache b;
   1.171 +
   1.172 +  for (int maxBufferSize = 1; maxBufferSize <= 4096; maxBufferSize *= 2) {
   1.173 +    // See bug 800612. We originally had | repeat = min(maxBufferSize, 20) |
   1.174 +    // and a real bug was only caught on Windows and not on Linux due to rand()
   1.175 +    // producing different values. In that case, the minimum value by which to replace
   1.176 +    // this 20 to reproduce the bug on Linux, was 25. Replacing it with 64 should give
   1.177 +    // us some comfort margin.
   1.178 +    int repeat = std::min(maxBufferSize, 64);
   1.179 +    for (int i = 0; i < repeat; i++) {
   1.180 +      size_t size = RandomInteger<size_t>(1, maxBufferSize);
   1.181 +      MakeRandomVector(v, size);
   1.182 +      b.BufferData(v.Elements(), size);
   1.183 +      CheckValidate(b, 0, size);
   1.184 +
   1.185 +      for (int j = 0; j < 16; j++) {
   1.186 +        for (int bufferSubDataCalls = 1; bufferSubDataCalls <= 8; bufferSubDataCalls *= 2) {
   1.187 +          for (int validateCalls = 1; validateCalls <= 8; validateCalls *= 2) {
   1.188 +
   1.189 +            size_t offset = 0, subsize = 0;
   1.190 +
   1.191 +            for (int k = 0; k < bufferSubDataCalls; k++) {
   1.192 +              offset = RandomInteger<size_t>(0, size);
   1.193 +              subsize = RandomInteger<size_t>(0, size - offset);
   1.194 +              MakeRandomVector(vsub, subsize);
   1.195 +              b.BufferSubData(offset, vsub.Elements(), subsize);
   1.196 +            }
   1.197 +
   1.198 +            for (int k = 0; k < validateCalls; k++) {
   1.199 +              offset = RandomInteger<size_t>(0, size);
   1.200 +              subsize = RandomInteger<size_t>(0, size - offset);
   1.201 +              CheckValidate(b, offset, subsize);
   1.202 +            }
   1.203 +          } // validateCalls
   1.204 +        } // bufferSubDataCalls
   1.205 +      } // j
   1.206 +    } // i
   1.207 +  } // maxBufferSize
   1.208 +
   1.209 +  std::cerr << argv[0] << ": all " << gTestsPassed << " tests passed" << std::endl;
   1.210 +  return 0;
   1.211 +}

mercurial