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 17namespace rx 18{ 19 20template <class IndexType> 21static 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 35RangeUI 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 51void 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 57void 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 79bool 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 97void IndexRangeCache::clear() 98{ 99 mIndexRangeCache.clear(); 100} 101 102IndexRangeCache::IndexRange::IndexRange() 103 : type(GL_NONE), offset(0), count(0) 104{ 105} 106 107IndexRangeCache::IndexRange::IndexRange(GLenum typ, intptr_t off, GLsizei c) 108 : type(typ), offset(off), count(c) 109{ 110} 111 112bool 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 117IndexRangeCache::IndexBounds::IndexBounds() 118 : range(0, 0), 119 streamOffset(0) 120{ 121} 122 123IndexRangeCache::IndexBounds::IndexBounds(const RangeUI &rangeIn, unsigned int offset) 124 : range(rangeIn), streamOffset(offset) 125{ 126} 127 128} 129