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