1 // 2 // Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 // IndexRangeCache.cpp: Defines the rx::IndexRangeCache class which stores information about 8 // ranges of indices. 9 10 #include "libGLESv2/renderer/IndexRangeCache.h" 11 #include "libGLESv2/formatutils.h" 12 13 #include "common/debug.h" 14 15 #include <tuple> 16 17 namespace rx 18 { 19 20 template <class IndexType> 21 static RangeUI ComputeTypedRange(const IndexType *indices, GLsizei count) 22 { 23 unsigned int minIndex = indices[0]; 24 unsigned int maxIndex = indices[0]; 25 26 for (GLsizei i = 1; i < count; i++) 27 { 28 if (minIndex > indices[i]) minIndex = indices[i]; 29 if (maxIndex < indices[i]) maxIndex = indices[i]; 30 } 31 32 return RangeUI(minIndex, maxIndex); 33 } 34 35 RangeUI IndexRangeCache::ComputeRange(GLenum type, const GLvoid *indices, GLsizei count) 36 { 37 switch (type) 38 { 39 case GL_UNSIGNED_BYTE: 40 return ComputeTypedRange(static_cast<const GLubyte*>(indices), count); 41 case GL_UNSIGNED_INT: 42 return ComputeTypedRange(static_cast<const GLuint*>(indices), count); 43 case GL_UNSIGNED_SHORT: 44 return ComputeTypedRange(static_cast<const GLushort*>(indices), count); 45 default: 46 UNREACHABLE(); 47 return RangeUI(); 48 } 49 } 50 51 void IndexRangeCache::addRange(GLenum type, unsigned int offset, GLsizei count, const RangeUI &range, 52 unsigned int streamOffset) 53 { 54 mIndexRangeCache[IndexRange(type, offset, count)] = IndexBounds(range, streamOffset); 55 } 56 57 void IndexRangeCache::invalidateRange(unsigned int offset, unsigned int size) 58 { 59 unsigned int invalidateStart = offset; 60 unsigned int invalidateEnd = offset + size; 61 62 IndexRangeMap::iterator i = mIndexRangeCache.begin(); 63 while (i != mIndexRangeCache.end()) 64 { 65 unsigned int rangeStart = i->second.streamOffset; 66 unsigned int rangeEnd = i->second.streamOffset + (gl::GetTypeInfo(i->first.type).bytes * i->first.count); 67 68 if (invalidateEnd < rangeStart || invalidateStart > rangeEnd) 69 { 70 ++i; 71 } 72 else 73 { 74 i = mIndexRangeCache.erase(i); 75 } 76 } 77 } 78 79 bool IndexRangeCache::findRange(GLenum type, unsigned int offset, GLsizei count, 80 RangeUI *outRange, unsigned int *outStreamOffset) const 81 { 82 IndexRangeMap::const_iterator i = mIndexRangeCache.find(IndexRange(type, offset, count)); 83 if (i != mIndexRangeCache.end()) 84 { 85 if (outRange) *outRange = i->second.range; 86 if (outStreamOffset) *outStreamOffset = i->second.streamOffset; 87 return true; 88 } 89 else 90 { 91 if (outRange) *outRange = RangeUI(0, 0); 92 if (outStreamOffset) *outStreamOffset = 0; 93 return false; 94 } 95 } 96 97 void IndexRangeCache::clear() 98 { 99 mIndexRangeCache.clear(); 100 } 101 102 IndexRangeCache::IndexRange::IndexRange() 103 : type(GL_NONE), offset(0), count(0) 104 { 105 } 106 107 IndexRangeCache::IndexRange::IndexRange(GLenum typ, intptr_t off, GLsizei c) 108 : type(typ), offset(off), count(c) 109 { 110 } 111 112 bool IndexRangeCache::IndexRange::operator<(const IndexRange& rhs) const 113 { 114 return std::make_tuple(type, offset, count) < std::make_tuple(rhs.type, rhs.offset, rhs.count); 115 } 116 117 IndexRangeCache::IndexBounds::IndexBounds() 118 : range(0, 0), 119 streamOffset(0) 120 { 121 } 122 123 IndexRangeCache::IndexBounds::IndexBounds(const RangeUI &rangeIn, unsigned int offset) 124 : range(rangeIn), streamOffset(offset) 125 { 126 } 127 128 } 129