blob: 48aec87ae765889875246ba038952dfa07d71d5e [file] [log] [blame]
// Copyright (C) 2016 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package builder
import (
"bytes"
"fmt"
"io"
"android.googlesource.com/platform/tools/gpu/framework/binary"
"android.googlesource.com/platform/tools/gpu/framework/binary/endian"
"android.googlesource.com/platform/tools/gpu/framework/device"
"android.googlesource.com/platform/tools/gpu/framework/id"
"android.googlesource.com/platform/tools/gpu/framework/log"
"android.googlesource.com/platform/tools/gpu/gapid/database"
)
// IndexLimits holds the results of CalculateIndexLimits.
type IndexLimits struct {
binary.Generate
Min uint32 // Smallest index found in the index buffer.
Max uint32 // Largest index found in the index buffer.
}
// CalcIndexLimits returns the lowest and highest index contained in the index
// buffer with identifier id. The buffer holds count elements, each of size
// bytes.
func CalcIndexLimits(ctx log.Context, id id.ID, count int, size int, littleEndian bool, d database.Database) (IndexLimits, error) {
c := &calcIndexLimits{
indexSize: size,
count: count,
littleEndian: littleEndian,
data: id,
}
r, err := database.Build(ctx, c, d)
if err != nil {
return IndexLimits{}, fmt.Errorf("Could not calculate index limits: %v", err)
}
return *r.(*IndexLimits), nil
}
type calcIndexLimits struct {
binary.Generate
indexSize int
count int
littleEndian bool
data id.ID
}
func (c calcIndexLimits) WriteForHash(w io.Writer) error {
u := endian.Writer(w, device.LittleEndian)
u.Int32(int32(c.indexSize))
u.Int32(int32(c.count))
u.Bool(c.littleEndian)
u.Data(c.data[:20])
return u.Error()
}
func (c calcIndexLimits) BuildLazy(ctx log.Context, _ interface{}, d database.Database) (interface{}, error) {
min, max := ^uint32(0), uint32(0)
data, err := d.Resolve(ctx, c.data)
if err != nil {
return nil, err
}
byteOrder := device.LittleEndian
if !c.littleEndian {
byteOrder = device.BigEndian
}
r := endian.Reader(bytes.NewReader(data.([]byte)), byteOrder)
var decode func() uint32
switch c.indexSize {
case 1:
decode = func() uint32 { return uint32(r.Uint8()) }
case 2:
decode = func() uint32 { return uint32(r.Uint16()) }
case 4:
decode = r.Uint32
default:
return nil, fmt.Errorf("Unsupported index size %v", c.indexSize)
}
for i := 0; i < c.count; i++ {
v := decode()
if r.Error() != nil {
return nil, r.Error()
}
if min > v {
min = v
}
if max < v {
max = v
}
}
return &IndexLimits{Min: min, Max: max}, nil
}