blob: 5ae831483899a81e0b03171dcac9aa50ba2d3dcd [file] [log] [blame]
// Copyright (C) 2015 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 image
import "android.googlesource.com/platform/tools/gpu/binary"
type fmtETC1_RGB8_OES struct{ binary.Generate }
func (*fmtETC1_RGB8_OES) String() string { return "ETC1_RGB8_OES" }
func (*fmtETC1_RGB8_OES) Check(d []byte, w, h int) error {
return checkSize(d, max(w, 4), max(h, 4), 4)
}
// ETC1_RGB8_OES returns a format representing the texture compression format
// with the same name.
func ETC1_RGB8_OES() Format { return &fmtETC1_RGB8_OES{} }
func init() {
RegisterConverter(ETC1_RGB8_OES(), RGBA(), func(src []byte, width, height int) ([]byte, error) {
dst := make([]byte, width*height*4)
block_width := max(width/4, 1)
block_height := max(height/4, 1)
c := [2][3]int32{}
codes := [2][4]int32{}
modTbl := [8][4]int32{
{2, 8, -2, -8},
{5, 17, -5, -17},
{9, 29, -9, -29},
{13, 42, -13, -42},
{18, 60, -18, -60},
{24, 80, -24, -80},
{33, 106, -33, -106},
{47, 183, -47, -183},
}
diffTbl := [8]int32{0, 1, 2, 3, -4, -3, -2, -1}
flipTbl := [2][16]int32{
{0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1},
{0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1},
}
for by := 0; by < block_height; by++ {
for bx := 0; bx < block_width; bx++ {
u64 := uint64(src[0])
u64 = (u64 << 8) | uint64(src[1])
u64 = (u64 << 8) | uint64(src[2])
u64 = (u64 << 8) | uint64(src[3])
u64 = (u64 << 8) | uint64(src[4])
u64 = (u64 << 8) | uint64(src[5])
u64 = (u64 << 8) | uint64(src[6])
u64 = (u64 << 8) | uint64(src[7])
src = src[8:]
flip := (u64 >> 32) & 1
diff := (u64 >> 33) & 1
codes[0] = modTbl[(u64>>37)&7]
codes[1] = modTbl[(u64>>34)&7]
for i := uint(0); i < 3; i++ {
if diff == 0 {
a := (u64 >> (44 + i*8)) & 15
b := (u64 >> (40 + i*8)) & 15
c[0][i] = int32((a << 4) | a)
c[1][i] = int32((b << 4) | b)
} else {
a := (u64 >> (43 + i*8)) & 31
b := (u64 >> (40 + i*8)) & 7
d := int32(int32(a) + diffTbl[b])
c[0][i] = int32((a << 3) | (a >> 2))
c[1][i] = int32((d << 3) | (d >> 2))
}
}
blockTbl := flipTbl[flip]
i := uint(0)
for x := bx * 4; x < (bx+1)*4; x++ {
for y := by * 4; y < (by+1)*4; y++ {
if x < width && y < height {
block := blockTbl[i]
base := c[block]
k := 4 * (y*width + x)
idx := ((u64 >> i) & 1) | ((u64 >> (15 + i)) & 2)
shift := codes[block][idx]
dst[k+0] = toByte(base[2] + shift)
dst[k+1] = toByte(base[1] + shift)
dst[k+2] = toByte(base[0] + shift)
dst[k+3] = 255
i++
}
}
}
}
}
return dst, nil
})
}