1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* libs/pixelflinger/codeflinger/texturing.cpp
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** Copyright 2006, The Android Open Source Project
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** you may not use this file except in compliance with the License.
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** You may obtain a copy of the License at
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**     http://www.apache.org/licenses/LICENSE-2.0
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** Unless required by applicable law or agreed to in writing, software
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS,
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** See the License for the specific language governing permissions and
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** limitations under the License.
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project*/
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <assert.h>
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdint.h>
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h>
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h>
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/types.h>
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/log.h>
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "codeflinger/GGLAssembler.h"
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectnamespace android {
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ---------------------------------------------------------------------------
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// iterators are initialized like this:
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// (intToFixedCenter(x) * dx)>>16 + x0
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ((x<<16 + 0x8000) * dx)>>16 + x0
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ((x<<16)*dx + (0x8000*dx))>>16 + x0
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ( (x*dx) + dx>>1 ) + x0
38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// (x*dx) + (dx>>1 + x0)
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid GGLAssembler::init_iterated_color(fragment_parts_t& parts, const reg_t& x)
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    context_t const* c = mBuilderContext.c;
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const needs_t& needs = mBuilderContext.needs;
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (mSmooth) {
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // NOTE: we could take this case in the mDithering + !mSmooth case,
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // but this would use up to 4 more registers for the color components
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // for only a little added quality.
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // Currently, this causes the system to run out of registers in
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // some case (see issue #719496)
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        comment("compute initial iterated color (smooth and/or dither case)");
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        parts.iterated_packed = 0;
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        parts.packed = 0;
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // 0x1: color component
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // 0x2: iterators
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const int optReload = mOptLevel >> 1;
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (optReload >= 3)         parts.reload = 0; // reload nothing
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        else if (optReload == 2)    parts.reload = 2; // reload iterators
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        else if (optReload == 1)    parts.reload = 1; // reload colors
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        else if (optReload <= 0)    parts.reload = 3; // reload both
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!mSmooth) {
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // we're not smoothing (just dithering), we never have to
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // reload the iterators
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            parts.reload &= ~2;
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        Scratch scratches(registerFile());
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const int t0 = (parts.reload & 1) ? scratches.obtain() : 0;
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const int t1 = (parts.reload & 2) ? scratches.obtain() : 0;
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        for (int i=0 ; i<4 ; i++) {
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (!mInfo[i].iterated)
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                continue;
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // this component exists in the destination and is not replaced
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // by a texture unit.
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            const int c = (parts.reload & 1) ? t0 : obtainReg();
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (i==0) CONTEXT_LOAD(c, iterators.ydady);
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (i==1) CONTEXT_LOAD(c, iterators.ydrdy);
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (i==2) CONTEXT_LOAD(c, iterators.ydgdy);
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (i==3) CONTEXT_LOAD(c, iterators.ydbdy);
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            parts.argb[i].reg = c;
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (mInfo[i].smooth) {
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                parts.argb_dx[i].reg = (parts.reload & 2) ? t1 : obtainReg();
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                const int dvdx = parts.argb_dx[i].reg;
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                CONTEXT_LOAD(dvdx, generated_vars.argb[i].dx);
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                MLA(AL, 0, c, x.reg, dvdx, c);
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // adjust the color iterator to make sure it won't overflow
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (!mAA) {
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    // this is not needed when we're using anti-aliasing
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    // because we will (have to) clamp the components
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    // anyway.
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    int end = scratches.obtain();
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    MOV(AL, 0, end, reg_imm(parts.count.reg, LSR, 16));
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    MLA(AL, 1, end, dvdx, end, c);
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    SUB(MI, 0, c, c, end);
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    BIC(AL, 0, c, c, reg_imm(c, ASR, 31));
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    scratches.recycle(end);
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (parts.reload & 1) {
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                CONTEXT_STORE(c, generated_vars.argb[i].c);
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // We're not smoothed, so we can
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // just use a packed version of the color and extract the
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // components as needed (or not at all if we don't blend)
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // figure out if we need the iterated color
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int load = 0;
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        for (int i=0 ; i<4 ; i++) {
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            component_info_t& info = mInfo[i];
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if ((info.inDest || info.needed) && !info.replaced)
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                load |= 1;
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        parts.iterated_packed = 1;
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        parts.packed = (!mTextureMachine.mask && !mBlending
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                && !mFog && !mDithering);
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        parts.reload = 0;
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (load || parts.packed) {
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (mBlending || mDithering || mInfo[GGLFormat::ALPHA].needed) {
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                comment("load initial iterated color (8888 packed)");
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                parts.iterated.setTo(obtainReg(),
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        &(c->formats[GGL_PIXEL_FORMAT_RGBA_8888]));
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                CONTEXT_LOAD(parts.iterated.reg, packed8888);
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else {
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                comment("load initial iterated color (dest format packed)");
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                parts.iterated.setTo(obtainReg(), &mCbFormat);
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // pre-mask the iterated color
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                const int bits = parts.iterated.size();
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                const uint32_t size = ((bits>=32) ? 0 : (1LU << bits)) - 1;
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                uint32_t mask = 0;
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (mMasking) {
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    for (int i=0 ; i<4 ; i++) {
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        const int component_mask = 1<<i;
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        const int h = parts.iterated.format.c[i].h;
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        const int l = parts.iterated.format.c[i].l;
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        if (h && (!(mMasking & component_mask))) {
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                            mask |= ((1<<(h-l))-1) << l;
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        }
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    }
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (mMasking && ((mask & size)==0)) {
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    // none of the components are present in the mask
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                } else {
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    CONTEXT_LOAD(parts.iterated.reg, packed);
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    if (mCbFormat.size == 1) {
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        AND(AL, 0, parts.iterated.reg,
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                parts.iterated.reg, imm(0xFF));
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    } else if (mCbFormat.size == 2) {
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        MOV(AL, 0, parts.iterated.reg,
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                reg_imm(parts.iterated.reg, LSR, 16));
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    }
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // pre-mask the iterated color
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (mMasking) {
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    build_and_immediate(parts.iterated.reg, parts.iterated.reg,
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                            mask, bits);
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid GGLAssembler::build_iterated_color(
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        component_t& fragment,
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const fragment_parts_t& parts,
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int component,
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        Scratch& regs)
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fragment.setTo( regs.obtain(), 0, 32, CORRUPTIBLE);
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!mInfo[component].iterated)
186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return;
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (parts.iterated_packed) {
189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // iterated colors are packed, extract the one we need
190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        extract(fragment, parts.iterated, component);
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fragment.h = GGL_COLOR_BITS;
193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fragment.l = GGL_COLOR_BITS - 8;
194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fragment.flags |= CLEAR_LO;
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // iterated colors are held in their own register,
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // (smooth and/or dithering case)
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (parts.reload==3) {
198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // this implies mSmooth
199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            Scratch scratches(registerFile());
200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int dx = scratches.obtain();
201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            CONTEXT_LOAD(fragment.reg, generated_vars.argb[component].c);
202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            CONTEXT_LOAD(dx, generated_vars.argb[component].dx);
203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ADD(AL, 0, dx, fragment.reg, dx);
204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            CONTEXT_STORE(dx, generated_vars.argb[component].c);
205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if (parts.reload & 1) {
206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            CONTEXT_LOAD(fragment.reg, generated_vars.argb[component].c);
207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // we don't reload, so simply rename the register and mark as
209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // non CORRUPTIBLE so that the texture env or blending code
210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // won't modify this (renamed) register
211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            regs.recycle(fragment.reg);
212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fragment.reg = parts.argb[component].reg;
213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fragment.flags &= ~CORRUPTIBLE;
214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (mInfo[component].smooth && mAA) {
216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // when using smooth shading AND anti-aliasing, we need to clamp
217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // the iterators because there is always an extra pixel on the
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // edges, which most of the time will cause an overflow
219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // (since technically its outside of the domain).
220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            BIC(AL, 0, fragment.reg, fragment.reg,
221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    reg_imm(fragment.reg, ASR, 31));
222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            component_sat(fragment);
223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ---------------------------------------------------------------------------
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid GGLAssembler::decodeLogicOpNeeds(const needs_t& needs)
230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // gather some informations about the components we need to process...
232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int opcode = GGL_READ_NEEDS(LOGIC_OP, needs.n) | GGL_CLEAR;
233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    switch(opcode) {
234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_COPY:
235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        mLogicOp = 0;
236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_CLEAR:
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_SET:
239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        mLogicOp = LOGIC_OP;
240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_AND:
242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_AND_REVERSE:
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_AND_INVERTED:
244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_XOR:
245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_OR:
246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_NOR:
247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_EQUIV:
248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_OR_REVERSE:
249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_OR_INVERTED:
250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_NAND:
251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        mLogicOp = LOGIC_OP|LOGIC_OP_SRC|LOGIC_OP_DST;
252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_NOOP:
254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_INVERT:
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        mLogicOp = LOGIC_OP|LOGIC_OP_DST;
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_COPY_INVERTED:
258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        mLogicOp = LOGIC_OP|LOGIC_OP_SRC;
259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    };
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid GGLAssembler::decodeTMUNeeds(const needs_t& needs, context_t const* c)
264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    uint8_t replaced=0;
266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    mTextureMachine.mask = 0;
267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    mTextureMachine.activeUnits = 0;
268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (int i=GGL_TEXTURE_UNIT_COUNT-1 ; i>=0 ; i--) {
269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        texture_unit_t& tmu = mTextureMachine.tmu[i];
270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (replaced == 0xF) {
271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // all components are replaced, skip this TMU.
272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            tmu.format_idx = 0;
273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            tmu.mask = 0;
274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            tmu.replaced = replaced;
275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            continue;
276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        tmu.format_idx = GGL_READ_NEEDS(T_FORMAT, needs.t[i]);
278dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        tmu.format = c->formats[tmu.format_idx];
279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        tmu.bits = tmu.format.size*8;
280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        tmu.swrap = GGL_READ_NEEDS(T_S_WRAP, needs.t[i]);
281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        tmu.twrap = GGL_READ_NEEDS(T_T_WRAP, needs.t[i]);
282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        tmu.env = ggl_needs_to_env(GGL_READ_NEEDS(T_ENV, needs.t[i]));
283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        tmu.pot = GGL_READ_NEEDS(T_POT, needs.t[i]);
284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        tmu.linear = GGL_READ_NEEDS(T_LINEAR, needs.t[i])
285dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                && tmu.format.size!=3; // XXX: only 8, 16 and 32 modes for now
286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // 5551 linear filtering is not supported
288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (tmu.format_idx == GGL_PIXEL_FORMAT_RGBA_5551)
289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            tmu.linear = 0;
290dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
291dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        tmu.mask = 0;
292dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        tmu.replaced = replaced;
293dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
294dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (tmu.format_idx) {
295dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            mTextureMachine.activeUnits++;
296dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (tmu.format.c[0].h)    tmu.mask |= 0x1;
297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (tmu.format.c[1].h)    tmu.mask |= 0x2;
298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (tmu.format.c[2].h)    tmu.mask |= 0x4;
299dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (tmu.format.c[3].h)    tmu.mask |= 0x8;
300dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (tmu.env == GGL_REPLACE) {
301dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                replaced |= tmu.mask;
302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else if (tmu.env == GGL_DECAL) {
303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (!tmu.format.c[GGLFormat::ALPHA].h) {
304dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    // if we don't have alpha, decal does nothing
305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    tmu.mask = 0;
306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                } else {
307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    // decal always ignores At
308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    tmu.mask &= ~(1<<GGLFormat::ALPHA);
309dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
311dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
312dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        mTextureMachine.mask |= tmu.mask;
313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //printf("%d: mask=%08lx, replaced=%08lx\n",
314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //    i, int(tmu.mask), int(tmu.replaced));
315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
316dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    mTextureMachine.replaced = replaced;
317dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    mTextureMachine.directTexture = 0;
318dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    //printf("replaced=%08lx\n", mTextureMachine.replaced);
319dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
320dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
321dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
322dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid GGLAssembler::init_textures(
323dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        tex_coord_t* coords,
324dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const reg_t& x, const reg_t& y)
325dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
326dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    context_t const* c = mBuilderContext.c;
327dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const needs_t& needs = mBuilderContext.needs;
328dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int Rctx = mBuilderContext.Rctx;
329dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int Rx = x.reg;
330dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int Ry = y.reg;
331dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
332dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (mTextureMachine.mask) {
333dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        comment("compute texture coordinates");
334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
335dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
336dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // init texture coordinates for each tmu
337dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int cb_format_idx = GGL_READ_NEEDS(CB_FORMAT, needs.n);
338dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const bool multiTexture = mTextureMachine.activeUnits > 1;
339dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT; i++) {
340dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const texture_unit_t& tmu = mTextureMachine.tmu[i];
341dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (tmu.format_idx == 0)
342dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            continue;
343dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if ((tmu.swrap == GGL_NEEDS_WRAP_11) &&
344dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            (tmu.twrap == GGL_NEEDS_WRAP_11))
345dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        {
346dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // 1:1 texture
347dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            pointer_t& txPtr = coords[i].ptr;
348dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            txPtr.setTo(obtainReg(), tmu.bits);
349dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            CONTEXT_LOAD(txPtr.reg, state.texture[i].iterators.ydsdy);
350dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ADD(AL, 0, Rx, Rx, reg_imm(txPtr.reg, ASR, 16));    // x += (s>>16)
351dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            CONTEXT_LOAD(txPtr.reg, state.texture[i].iterators.ydtdy);
352dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ADD(AL, 0, Ry, Ry, reg_imm(txPtr.reg, ASR, 16));    // y += (t>>16)
353dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // merge base & offset
354dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            CONTEXT_LOAD(txPtr.reg, generated_vars.texture[i].stride);
355dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            SMLABB(AL, Rx, Ry, txPtr.reg, Rx);               // x+y*stride
356dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            CONTEXT_LOAD(txPtr.reg, generated_vars.texture[i].data);
357dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            base_offset(txPtr, txPtr, Rx);
358dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
359dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            Scratch scratches(registerFile());
360dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            reg_t& s = coords[i].s;
361dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            reg_t& t = coords[i].t;
362dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // s = (x * dsdx)>>16 + ydsdy
363dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // s = (x * dsdx)>>16 + (y*dsdy)>>16 + s0
364dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // t = (x * dtdx)>>16 + ydtdy
365dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // t = (x * dtdx)>>16 + (y*dtdy)>>16 + t0
366dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            s.setTo(obtainReg());
367dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            t.setTo(obtainReg());
368dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            const int need_w = GGL_READ_NEEDS(W, needs.n);
369dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (need_w) {
370dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                CONTEXT_LOAD(s.reg, state.texture[i].iterators.ydsdy);
371dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                CONTEXT_LOAD(t.reg, state.texture[i].iterators.ydtdy);
372dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else {
373dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                int ydsdy = scratches.obtain();
374dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                int ydtdy = scratches.obtain();
375dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                CONTEXT_LOAD(s.reg, generated_vars.texture[i].dsdx);
376dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                CONTEXT_LOAD(ydsdy, state.texture[i].iterators.ydsdy);
377dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                CONTEXT_LOAD(t.reg, generated_vars.texture[i].dtdx);
378dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                CONTEXT_LOAD(ydtdy, state.texture[i].iterators.ydtdy);
379dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                MLA(AL, 0, s.reg, Rx, s.reg, ydsdy);
380dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                MLA(AL, 0, t.reg, Rx, t.reg, ydtdy);
381dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
382dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
383dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if ((mOptLevel&1)==0) {
384dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                CONTEXT_STORE(s.reg, generated_vars.texture[i].spill[0]);
385dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                CONTEXT_STORE(t.reg, generated_vars.texture[i].spill[1]);
386dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                recycleReg(s.reg);
387dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                recycleReg(t.reg);
388dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
389dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
390dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
391dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // direct texture?
392dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!multiTexture && !mBlending && !mDithering && !mFog &&
393dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            cb_format_idx == tmu.format_idx && !tmu.linear &&
394dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            mTextureMachine.replaced == tmu.mask)
395dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        {
396dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                mTextureMachine.directTexture = i + 1;
397dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
398dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
399dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
400dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
401dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid GGLAssembler::build_textures(  fragment_parts_t& parts,
402dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                    Scratch& regs)
403dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
404dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    context_t const* c = mBuilderContext.c;
405dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const needs_t& needs = mBuilderContext.needs;
406dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int Rctx = mBuilderContext.Rctx;
407dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
408dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // We don't have a way to spill registers automatically
409dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // spill depth and AA regs, when we know we may have to.
410dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // build the spill list...
411dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    uint32_t spill_list = 0;
412dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT; i++) {
413dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const texture_unit_t& tmu = mTextureMachine.tmu[i];
414dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (tmu.format_idx == 0)
415dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            continue;
416dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (tmu.linear) {
417dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // we may run out of register if we have linear filtering
418dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // at 1 or 4 bytes / pixel on any texture unit.
419dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (tmu.format.size == 1) {
420dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // if depth and AA enabled, we'll run out of 1 register
421dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (parts.z.reg > 0 && parts.covPtr.reg > 0)
422dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    spill_list |= 1<<parts.covPtr.reg;
423dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
424dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (tmu.format.size == 4) {
425dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // if depth or AA enabled, we'll run out of 1 or 2 registers
426dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (parts.z.reg > 0)
427dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    spill_list |= 1<<parts.z.reg;
428dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (parts.covPtr.reg > 0)
429dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    spill_list |= 1<<parts.covPtr.reg;
430dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
431dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
432dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
433dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
434dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    Spill spill(registerFile(), *this, spill_list);
435dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
436dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const bool multiTexture = mTextureMachine.activeUnits > 1;
437dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT; i++) {
438dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const texture_unit_t& tmu = mTextureMachine.tmu[i];
439dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (tmu.format_idx == 0)
440dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            continue;
441dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
442dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        pointer_t& txPtr = parts.coords[i].ptr;
443dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        pixel_t& texel = parts.texel[i];
444dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
445dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // repeat...
446dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if ((tmu.swrap == GGL_NEEDS_WRAP_11) &&
447dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            (tmu.twrap == GGL_NEEDS_WRAP_11))
448dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        { // 1:1 textures
449dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            comment("fetch texel");
450dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            texel.setTo(regs.obtain(), &tmu.format);
451dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            load(txPtr, texel, WRITE_BACK);
452dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
453dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            Scratch scratches(registerFile());
454dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            reg_t& s = parts.coords[i].s;
455dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            reg_t& t = parts.coords[i].t;
456dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if ((mOptLevel&1)==0) {
457dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                comment("reload s/t (multitexture or linear filtering)");
458dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                s.reg = scratches.obtain();
459dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                t.reg = scratches.obtain();
460dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                CONTEXT_LOAD(s.reg, generated_vars.texture[i].spill[0]);
461dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                CONTEXT_LOAD(t.reg, generated_vars.texture[i].spill[1]);
462dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
463dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
464dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            comment("compute repeat/clamp");
465dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int u       = scratches.obtain();
466dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int v       = scratches.obtain();
467dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int width   = scratches.obtain();
468dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int height  = scratches.obtain();
469dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int U = 0;
470dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int V = 0;
471dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
472dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            CONTEXT_LOAD(width,  generated_vars.texture[i].width);
473dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            CONTEXT_LOAD(height, generated_vars.texture[i].height);
474dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
475dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int FRAC_BITS = 0;
476dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (tmu.linear) {
477dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // linear interpolation
478dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (tmu.format.size == 1) {
479dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    // for 8-bits textures, we can afford
480dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    // 7 bits of fractional precision at no
481dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    // additional cost (we can't do 8 bits
482dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    // because filter8 uses signed 16 bits muls)
483dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    FRAC_BITS = 7;
484dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                } else if (tmu.format.size == 2) {
485dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    // filter16() is internally limited to 4 bits, so:
486dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    // FRAC_BITS=2 generates less instructions,
487dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    // FRAC_BITS=3,4,5 creates unpleasant artifacts,
488dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    // FRAC_BITS=6+ looks good
489dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    FRAC_BITS = 6;
490dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                } else if (tmu.format.size == 4) {
491dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    // filter32() is internally limited to 8 bits, so:
492dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    // FRAC_BITS=4 looks good
493dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    // FRAC_BITS=5+ looks better, but generates 3 extra ipp
494dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    FRAC_BITS = 6;
495dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                } else {
496dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    // for all other cases we use 4 bits.
497dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    FRAC_BITS = 4;
498dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
499dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
500dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            wrapping(u, s.reg, width,  tmu.swrap, FRAC_BITS);
501dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            wrapping(v, t.reg, height, tmu.twrap, FRAC_BITS);
502dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
503dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (tmu.linear) {
504dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                comment("compute linear filtering offsets");
505dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // pixel size scale
506dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                const int shift = 31 - gglClz(tmu.format.size);
507dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                U = scratches.obtain();
508dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                V = scratches.obtain();
509dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
510dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // sample the texel center
511dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                SUB(AL, 0, u, u, imm(1<<(FRAC_BITS-1)));
512dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                SUB(AL, 0, v, v, imm(1<<(FRAC_BITS-1)));
513dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
514dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // get the fractionnal part of U,V
515dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                AND(AL, 0, U, u, imm((1<<FRAC_BITS)-1));
516dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                AND(AL, 0, V, v, imm((1<<FRAC_BITS)-1));
517dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
518dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // compute width-1 and height-1
519dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                SUB(AL, 0, width,  width,  imm(1));
520dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                SUB(AL, 0, height, height, imm(1));
521dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
522dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // get the integer part of U,V and clamp/wrap
523dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // and compute offset to the next texel
524dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (tmu.swrap == GGL_NEEDS_WRAP_REPEAT) {
525dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    // u has already been REPEATed
526dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    MOV(AL, 1, u, reg_imm(u, ASR, FRAC_BITS));
527dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    MOV(MI, 0, u, width);
528dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    CMP(AL, u, width);
529dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    MOV(LT, 0, width, imm(1 << shift));
530dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    if (shift)
531dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        MOV(GE, 0, width, reg_imm(width, LSL, shift));
532dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    RSB(GE, 0, width, width, imm(0));
533dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                } else {
534dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    // u has not been CLAMPed yet
535dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    // algorithm:
536dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    // if ((u>>4) >= width)
537dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    //      u = width<<4
538dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    //      width = 0
539dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    // else
540dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    //      width = 1<<shift
541dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    // u = u>>4; // get integer part
542dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    // if (u<0)
543dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    //      u = 0
544dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    //      width = 0
545dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    // generated_vars.rt = width
546dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
547dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    CMP(AL, width, reg_imm(u, ASR, FRAC_BITS));
548dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    MOV(LE, 0, u, reg_imm(width, LSL, FRAC_BITS));
549dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    MOV(LE, 0, width, imm(0));
550dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    MOV(GT, 0, width, imm(1 << shift));
551dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    MOV(AL, 1, u, reg_imm(u, ASR, FRAC_BITS));
552dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    MOV(MI, 0, u, imm(0));
553dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    MOV(MI, 0, width, imm(0));
554dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
555dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                CONTEXT_STORE(width, generated_vars.rt);
556dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
557dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                const int stride = width;
558dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                CONTEXT_LOAD(stride, generated_vars.texture[i].stride);
559dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (tmu.twrap == GGL_NEEDS_WRAP_REPEAT) {
560dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    // v has already been REPEATed
561dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    MOV(AL, 1, v, reg_imm(v, ASR, FRAC_BITS));
562dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    MOV(MI, 0, v, height);
563dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    CMP(AL, v, height);
564dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    MOV(LT, 0, height, imm(1 << shift));
565dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    if (shift)
566dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        MOV(GE, 0, height, reg_imm(height, LSL, shift));
567dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    RSB(GE, 0, height, height, imm(0));
568dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    MUL(AL, 0, height, stride, height);
569dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                } else {
570dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    // u has not been CLAMPed yet
571dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    CMP(AL, height, reg_imm(v, ASR, FRAC_BITS));
572dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    MOV(LE, 0, v, reg_imm(height, LSL, FRAC_BITS));
573dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    MOV(LE, 0, height, imm(0));
574dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    if (shift) {
575dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        MOV(GT, 0, height, reg_imm(stride, LSL, shift));
576dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    } else {
577dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        MOV(GT, 0, height, stride);
578dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    }
579dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    MOV(AL, 1, v, reg_imm(v, ASR, FRAC_BITS));
580dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    MOV(MI, 0, v, imm(0));
581dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    MOV(MI, 0, height, imm(0));
582dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
583dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                CONTEXT_STORE(height, generated_vars.lb);
584dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
585dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
586dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            scratches.recycle(width);
587dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            scratches.recycle(height);
588dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
589dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // iterate texture coordinates...
590dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            comment("iterate s,t");
591dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int dsdx = scratches.obtain();
592dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int dtdx = scratches.obtain();
593dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            CONTEXT_LOAD(dsdx, generated_vars.texture[i].dsdx);
594dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            CONTEXT_LOAD(dtdx, generated_vars.texture[i].dtdx);
595dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ADD(AL, 0, s.reg, s.reg, dsdx);
596dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ADD(AL, 0, t.reg, t.reg, dtdx);
597dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if ((mOptLevel&1)==0) {
598dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                CONTEXT_STORE(s.reg, generated_vars.texture[i].spill[0]);
599dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                CONTEXT_STORE(t.reg, generated_vars.texture[i].spill[1]);
600dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                scratches.recycle(s.reg);
601dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                scratches.recycle(t.reg);
602dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
603dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            scratches.recycle(dsdx);
604dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            scratches.recycle(dtdx);
605dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
606dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // merge base & offset...
607dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            comment("merge base & offset");
608dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            texel.setTo(regs.obtain(), &tmu.format);
609dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            txPtr.setTo(texel.reg, tmu.bits);
610dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int stride = scratches.obtain();
611dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            CONTEXT_LOAD(stride,    generated_vars.texture[i].stride);
612dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            CONTEXT_LOAD(txPtr.reg, generated_vars.texture[i].data);
613dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            SMLABB(AL, u, v, stride, u);    // u+v*stride
614dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            base_offset(txPtr, txPtr, u);
615dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
616dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // load texel
617dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (!tmu.linear) {
618dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                comment("fetch texel");
619dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                load(txPtr, texel, 0);
620dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else {
621dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // recycle registers we don't need anymore
622dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                scratches.recycle(u);
623dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                scratches.recycle(v);
624dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                scratches.recycle(stride);
625dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
626dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                comment("fetch texel, bilinear");
627dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                switch (tmu.format.size) {
628dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                case 1:  filter8(parts, texel, tmu, U, V, txPtr, FRAC_BITS); break;
629dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                case 2: filter16(parts, texel, tmu, U, V, txPtr, FRAC_BITS); break;
630dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                case 3: filter24(parts, texel, tmu, U, V, txPtr, FRAC_BITS); break;
631dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                case 4: filter32(parts, texel, tmu, U, V, txPtr, FRAC_BITS); break;
632dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
633dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
634dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
635dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
636dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
637dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
638dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid GGLAssembler::build_iterate_texture_coordinates(
639dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const fragment_parts_t& parts)
640dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
641dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const bool multiTexture = mTextureMachine.activeUnits > 1;
642dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT; i++) {
643dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const texture_unit_t& tmu = mTextureMachine.tmu[i];
644dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (tmu.format_idx == 0)
645dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            continue;
646dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
647dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if ((tmu.swrap == GGL_NEEDS_WRAP_11) &&
648dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            (tmu.twrap == GGL_NEEDS_WRAP_11))
649dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        { // 1:1 textures
650dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            const pointer_t& txPtr = parts.coords[i].ptr;
651dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ADD(AL, 0, txPtr.reg, txPtr.reg, imm(txPtr.size>>3));
652dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
653dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            Scratch scratches(registerFile());
654dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int s = parts.coords[i].s.reg;
655dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int t = parts.coords[i].t.reg;
656dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if ((mOptLevel&1)==0) {
657dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                s = scratches.obtain();
658dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                t = scratches.obtain();
659dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                CONTEXT_LOAD(s, generated_vars.texture[i].spill[0]);
660dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                CONTEXT_LOAD(t, generated_vars.texture[i].spill[1]);
661dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
662dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int dsdx = scratches.obtain();
663dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int dtdx = scratches.obtain();
664dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            CONTEXT_LOAD(dsdx, generated_vars.texture[i].dsdx);
665dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            CONTEXT_LOAD(dtdx, generated_vars.texture[i].dtdx);
666dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ADD(AL, 0, s, s, dsdx);
667dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ADD(AL, 0, t, t, dtdx);
668dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if ((mOptLevel&1)==0) {
669dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                CONTEXT_STORE(s, generated_vars.texture[i].spill[0]);
670dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                CONTEXT_STORE(t, generated_vars.texture[i].spill[1]);
671dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
672dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
673dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
674dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
675dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
676dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid GGLAssembler::filter8(
677dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const fragment_parts_t& parts,
678dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        pixel_t& texel, const texture_unit_t& tmu,
679dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int U, int V, pointer_t& txPtr,
680dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int FRAC_BITS)
681dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
682dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (tmu.format.components != GGL_ALPHA &&
683dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        tmu.format.components != GGL_LUMINANCE)
684dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    {
685dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // this is a packed format, and we don't support
686dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // linear filtering (it's probably RGB 332)
687dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // Should not happen with OpenGL|ES
688dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        LDRB(AL, texel.reg, txPtr.reg);
689dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return;
690dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
691dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
692dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // ------------------------
693dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // about ~22 cycles / pixel
694dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    Scratch scratches(registerFile());
695dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
696dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int pixel= scratches.obtain();
697dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int d    = scratches.obtain();
698dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int u    = scratches.obtain();
699dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int k    = scratches.obtain();
700dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int rt   = scratches.obtain();
701dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int lb   = scratches.obtain();
702dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
703dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // RB -> U * V
704dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
705dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    CONTEXT_LOAD(rt, generated_vars.rt);
706dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    CONTEXT_LOAD(lb, generated_vars.lb);
707dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
708dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int offset = pixel;
709dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ADD(AL, 0, offset, lb, rt);
710dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    LDRB(AL, pixel, txPtr.reg, reg_scale_pre(offset));
711dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SMULBB(AL, u, U, V);
712dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SMULBB(AL, d, pixel, u);
713dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    RSB(AL, 0, k, u, imm(1<<(FRAC_BITS*2)));
714dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
715dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // LB -> (1-U) * V
716dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    RSB(AL, 0, U, U, imm(1<<FRAC_BITS));
717dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    LDRB(AL, pixel, txPtr.reg, reg_scale_pre(lb));
718dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SMULBB(AL, u, U, V);
719dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SMLABB(AL, d, pixel, u, d);
720dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SUB(AL, 0, k, k, u);
721dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
722dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // LT -> (1-U)*(1-V)
723dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    RSB(AL, 0, V, V, imm(1<<FRAC_BITS));
724dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    LDRB(AL, pixel, txPtr.reg);
725dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SMULBB(AL, u, U, V);
726dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SMLABB(AL, d, pixel, u, d);
727dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
728dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // RT -> U*(1-V)
729dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    LDRB(AL, pixel, txPtr.reg, reg_scale_pre(rt));
730dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SUB(AL, 0, u, k, u);
731dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SMLABB(AL, texel.reg, pixel, u, d);
732dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
733dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (int i=0 ; i<4 ; i++) {
734dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!texel.format.c[i].h) continue;
735dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        texel.format.c[i].h = FRAC_BITS*2+8;
736dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        texel.format.c[i].l = FRAC_BITS*2; // keeping 8 bits in enough
737dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
738dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    texel.format.size = 4;
739dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    texel.format.bitsPerPixel = 32;
740dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    texel.flags |= CLEAR_LO;
741dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
742dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
743dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid GGLAssembler::filter16(
744dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const fragment_parts_t& parts,
745dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        pixel_t& texel, const texture_unit_t& tmu,
746dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int U, int V, pointer_t& txPtr,
747dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int FRAC_BITS)
748dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
749dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // compute the mask
750dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // XXX: it would be nice if the mask below could be computed
751dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // automatically.
752dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    uint32_t mask = 0;
753dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int shift = 0;
754dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int prec = 0;
755dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    switch (tmu.format_idx) {
756dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case GGL_PIXEL_FORMAT_RGB_565:
757dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // source: 00000ggg.ggg00000 | rrrrr000.000bbbbb
758dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // result: gggggggg.gggrrrrr | rrrrr0bb.bbbbbbbb
759dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            mask = 0x07E0F81F;
760dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            shift = 16;
761dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            prec = 5;
762dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
763dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case GGL_PIXEL_FORMAT_RGBA_4444:
764dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // 0000,1111,0000,1111 | 0000,1111,0000,1111
765dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            mask = 0x0F0F0F0F;
766dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            shift = 12;
767dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            prec = 4;
768dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
769dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case GGL_PIXEL_FORMAT_LA_88:
770dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // 0000,0000,1111,1111 | 0000,0000,1111,1111
771dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // AALL -> 00AA | 00LL
772dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            mask = 0x00FF00FF;
773dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            shift = 8;
774dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            prec = 8;
775dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
776dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        default:
777dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // unsupported format, do something sensical...
778dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            LOGE("Unsupported 16-bits texture format (%d)", tmu.format_idx);
779dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            LDRH(AL, texel.reg, txPtr.reg);
780dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return;
781dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
782dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
783dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int adjust = FRAC_BITS*2 - prec;
784dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int round  = 0;
785dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
786dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // update the texel format
787dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    texel.format.size = 4;
788dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    texel.format.bitsPerPixel = 32;
789dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    texel.flags |= CLEAR_HI|CLEAR_LO;
790dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (int i=0 ; i<4 ; i++) {
791dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!texel.format.c[i].h) continue;
792dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const uint32_t offset = (mask & tmu.format.mask(i)) ? 0 : shift;
793dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        texel.format.c[i].h = tmu.format.c[i].h + offset + prec;
794dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        texel.format.c[i].l = texel.format.c[i].h - (tmu.format.bits(i) + prec);
795dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
796dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
797dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // ------------------------
798dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // about ~40 cycles / pixel
799dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    Scratch scratches(registerFile());
800dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
801dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int pixel= scratches.obtain();
802dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int d    = scratches.obtain();
803dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int u    = scratches.obtain();
804dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int k    = scratches.obtain();
805dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
806dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // RB -> U * V
807dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int offset = pixel;
808dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    CONTEXT_LOAD(offset, generated_vars.rt);
809dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    CONTEXT_LOAD(u, generated_vars.lb);
810dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ADD(AL, 0, offset, offset, u);
811dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
812dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    LDRH(AL, pixel, txPtr.reg, reg_pre(offset));
813dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SMULBB(AL, u, U, V);
814dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ORR(AL, 0, pixel, pixel, reg_imm(pixel, LSL, shift));
815dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    build_and_immediate(pixel, pixel, mask, 32);
816dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (adjust) {
817dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (round)
818dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ADD(AL, 0, u, u, imm(1<<(adjust-1)));
819dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        MOV(AL, 0, u, reg_imm(u, LSR, adjust));
820dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
821dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    MUL(AL, 0, d, pixel, u);
822dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    RSB(AL, 0, k, u, imm(1<<prec));
823dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
824dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // LB -> (1-U) * V
825dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    CONTEXT_LOAD(offset, generated_vars.lb);
826dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    RSB(AL, 0, U, U, imm(1<<FRAC_BITS));
827dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    LDRH(AL, pixel, txPtr.reg, reg_pre(offset));
828dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SMULBB(AL, u, U, V);
829dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ORR(AL, 0, pixel, pixel, reg_imm(pixel, LSL, shift));
830dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    build_and_immediate(pixel, pixel, mask, 32);
831dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (adjust) {
832dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (round)
833dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ADD(AL, 0, u, u, imm(1<<(adjust-1)));
834dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        MOV(AL, 0, u, reg_imm(u, LSR, adjust));
835dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
836dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    MLA(AL, 0, d, pixel, u, d);
837dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SUB(AL, 0, k, k, u);
838dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
839dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // LT -> (1-U)*(1-V)
840dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    RSB(AL, 0, V, V, imm(1<<FRAC_BITS));
841dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    LDRH(AL, pixel, txPtr.reg);
842dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SMULBB(AL, u, U, V);
843dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ORR(AL, 0, pixel, pixel, reg_imm(pixel, LSL, shift));
844dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    build_and_immediate(pixel, pixel, mask, 32);
845dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (adjust) {
846dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (round)
847dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ADD(AL, 0, u, u, imm(1<<(adjust-1)));
848dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        MOV(AL, 0, u, reg_imm(u, LSR, adjust));
849dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
850dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    MLA(AL, 0, d, pixel, u, d);
851dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
852dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // RT -> U*(1-V)
853dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    CONTEXT_LOAD(offset, generated_vars.rt);
854dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    LDRH(AL, pixel, txPtr.reg, reg_pre(offset));
855dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SUB(AL, 0, u, k, u);
856dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ORR(AL, 0, pixel, pixel, reg_imm(pixel, LSL, shift));
857dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    build_and_immediate(pixel, pixel, mask, 32);
858dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    MLA(AL, 0, texel.reg, pixel, u, d);
859dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
860dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
861dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid GGLAssembler::filter24(
862dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const fragment_parts_t& parts,
863dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        pixel_t& texel, const texture_unit_t& tmu,
864dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int U, int V, pointer_t& txPtr,
865dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int FRAC_BITS)
866dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
867dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // not supported yet (currently disabled)
868dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    load(txPtr, texel, 0);
869dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
870dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
871dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid GGLAssembler::filter32(
872dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const fragment_parts_t& parts,
873dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        pixel_t& texel, const texture_unit_t& tmu,
874dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int U, int V, pointer_t& txPtr,
875dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int FRAC_BITS)
876dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
877dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int adjust = FRAC_BITS*2 - 8;
878dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int round  = 0;
879dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
880dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // ------------------------
881dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // about ~38 cycles / pixel
882dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    Scratch scratches(registerFile());
883dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
884dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int pixel= scratches.obtain();
885dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int dh   = scratches.obtain();
886dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int u    = scratches.obtain();
887dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int k    = scratches.obtain();
888dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
889dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int temp = scratches.obtain();
890dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int dl   = scratches.obtain();
891dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int mask = scratches.obtain();
892dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
893dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    MOV(AL, 0, mask, imm(0xFF));
894dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ORR(AL, 0, mask, mask, imm(0xFF0000));
895dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
896dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // RB -> U * V
897dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int offset = pixel;
898dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    CONTEXT_LOAD(offset, generated_vars.rt);
899dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    CONTEXT_LOAD(u, generated_vars.lb);
900dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ADD(AL, 0, offset, offset, u);
901dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
902dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    LDR(AL, pixel, txPtr.reg, reg_scale_pre(offset));
903dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SMULBB(AL, u, U, V);
904dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    AND(AL, 0, temp, mask, pixel);
905dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (adjust) {
906dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (round)
907dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ADD(AL, 0, u, u, imm(1<<(adjust-1)));
908dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        MOV(AL, 0, u, reg_imm(u, LSR, adjust));
909dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
910dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    MUL(AL, 0, dh, temp, u);
911dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    AND(AL, 0, temp, mask, reg_imm(pixel, LSR, 8));
912dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    MUL(AL, 0, dl, temp, u);
913dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    RSB(AL, 0, k, u, imm(0x100));
914dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
915dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // LB -> (1-U) * V
916dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    CONTEXT_LOAD(offset, generated_vars.lb);
917dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    RSB(AL, 0, U, U, imm(1<<FRAC_BITS));
918dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    LDR(AL, pixel, txPtr.reg, reg_scale_pre(offset));
919dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SMULBB(AL, u, U, V);
920dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    AND(AL, 0, temp, mask, pixel);
921dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (adjust) {
922dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (round)
923dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ADD(AL, 0, u, u, imm(1<<(adjust-1)));
924dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        MOV(AL, 0, u, reg_imm(u, LSR, adjust));
925dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
926dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    MLA(AL, 0, dh, temp, u, dh);
927dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    AND(AL, 0, temp, mask, reg_imm(pixel, LSR, 8));
928dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    MLA(AL, 0, dl, temp, u, dl);
929dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SUB(AL, 0, k, k, u);
930dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
931dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // LT -> (1-U)*(1-V)
932dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    RSB(AL, 0, V, V, imm(1<<FRAC_BITS));
933dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    LDR(AL, pixel, txPtr.reg);
934dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SMULBB(AL, u, U, V);
935dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    AND(AL, 0, temp, mask, pixel);
936dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (adjust) {
937dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (round)
938dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ADD(AL, 0, u, u, imm(1<<(adjust-1)));
939dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        MOV(AL, 0, u, reg_imm(u, LSR, adjust));
940dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
941dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    MLA(AL, 0, dh, temp, u, dh);
942dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    AND(AL, 0, temp, mask, reg_imm(pixel, LSR, 8));
943dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    MLA(AL, 0, dl, temp, u, dl);
944dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
945dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // RT -> U*(1-V)
946dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    CONTEXT_LOAD(offset, generated_vars.rt);
947dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    LDR(AL, pixel, txPtr.reg, reg_scale_pre(offset));
948dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SUB(AL, 0, u, k, u);
949dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    AND(AL, 0, temp, mask, pixel);
950dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    MLA(AL, 0, dh, temp, u, dh);
951dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    AND(AL, 0, temp, mask, reg_imm(pixel, LSR, 8));
952dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    MLA(AL, 0, dl, temp, u, dl);
953dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
954dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    AND(AL, 0, dh, mask, reg_imm(dh, LSR, 8));
955dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    AND(AL, 0, dl, dl, reg_imm(mask, LSL, 8));
956dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ORR(AL, 0, texel.reg, dh, dl);
957dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
958dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
959dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid GGLAssembler::build_texture_environment(
960dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        component_t& fragment,
961dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const fragment_parts_t& parts,
962dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int component,
963dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        Scratch& regs)
964dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
965dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const uint32_t component_mask = 1<<component;
966dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const bool multiTexture = mTextureMachine.activeUnits > 1;
967dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
968dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        texture_unit_t& tmu = mTextureMachine.tmu[i];
969dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
970dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (tmu.mask & component_mask) {
971dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // replace or modulate with this texture
972dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if ((tmu.replaced & component_mask) == 0) {
973dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // not replaced by a later tmu...
974dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
975dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                Scratch scratches(registerFile());
976dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                pixel_t texel(parts.texel[i]);
977dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (multiTexture &&
978dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    tmu.swrap == GGL_NEEDS_WRAP_11 &&
979dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    tmu.twrap == GGL_NEEDS_WRAP_11)
980dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                {
981dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    texel.reg = scratches.obtain();
982dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    texel.flags |= CORRUPTIBLE;
983dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    comment("fetch texel (multitexture 1:1)");
984dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    load(parts.coords[i].ptr, texel, WRITE_BACK);
985dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                 }
986dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
987dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                component_t incoming(fragment);
988dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                modify(fragment, regs);
989dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
990dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                switch (tmu.env) {
991dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                case GGL_REPLACE:
992dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    extract(fragment, texel, component);
993dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    break;
994dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                case GGL_MODULATE:
995dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    modulate(fragment, incoming, texel, component);
996dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    break;
997dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                case GGL_DECAL:
998dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    decal(fragment, incoming, texel, component);
999dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    break;
1000dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                case GGL_BLEND:
1001dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    blend(fragment, incoming, texel, component, i);
1002dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    break;
1003dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                case GGL_ADD:
1004dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    add(fragment, incoming, texel, component);
1005dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    break;
1006dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
1007dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
1008dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
1009dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
1010dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1011dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1012dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ---------------------------------------------------------------------------
1013dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1014dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid GGLAssembler::wrapping(
1015dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int d,
1016dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int coord, int size,
1017dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int tx_wrap, int tx_linear)
1018dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
1019dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // notes:
1020dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // if tx_linear is set, we need 4 extra bits of precision on the result
1021dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // SMULL/UMULL is 3 cycles
1022dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    Scratch scratches(registerFile());
1023dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int c = coord;
1024dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (tx_wrap == GGL_NEEDS_WRAP_REPEAT) {
1025dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // UMULL takes 4 cycles (interlocked), and we can get away with
1026dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // 2 cycles using SMULWB, but we're loosing 16 bits of precision
1027dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // out of 32 (this is not a problem because the iterator keeps
1028dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // its full precision)
1029dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // UMULL(AL, 0, size, d, c, size);
1030dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // note: we can't use SMULTB because it's signed.
1031dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        MOV(AL, 0, d, reg_imm(c, LSR, 16-tx_linear));
1032dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        SMULWB(AL, d, d, size);
1033dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if (tx_wrap == GGL_NEEDS_WRAP_CLAMP_TO_EDGE) {
1034dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (tx_linear) {
1035dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // 1 cycle
1036dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            MOV(AL, 0, d, reg_imm(coord, ASR, 16-tx_linear));
1037dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
1038dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // 4 cycles (common case)
1039dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            MOV(AL, 0, d, reg_imm(coord, ASR, 16));
1040dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            BIC(AL, 0, d, d, reg_imm(d, ASR, 31));
1041dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            CMP(AL, d, size);
1042dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            SUB(GE, 0, d, size, imm(1));
1043dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
1044dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
1045dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1046dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1047dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ---------------------------------------------------------------------------
1048dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1049dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid GGLAssembler::modulate(
1050dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        component_t& dest,
1051dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const component_t& incoming,
1052dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const pixel_t& incomingTexel, int component)
1053dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
1054dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    Scratch locals(registerFile());
1055dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    integer_t texel(locals.obtain(), 32, CORRUPTIBLE);
1056dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    extract(texel, incomingTexel, component);
1057dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1058dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int Nt = texel.size();
1059dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // Nt should always be less than 10 bits because it comes
1060dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // from the TMU.
1061dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1062dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int Ni = incoming.size();
1063dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // Ni could be big because it comes from previous MODULATEs
1064dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1065dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (Nt == 1) {
1066dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // texel acts as a bit-mask
1067dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // dest = incoming & ((texel << incoming.h)-texel)
1068dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        RSB(AL, 0, dest.reg, texel.reg, reg_imm(texel.reg, LSL, incoming.h));
1069dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        AND(AL, 0, dest.reg, dest.reg, incoming.reg);
1070dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        dest.l = incoming.l;
1071dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        dest.h = incoming.h;
1072dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        dest.flags |= (incoming.flags & CLEAR_LO);
1073dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if (Ni == 1) {
1074dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        MOV(AL, 0, dest.reg, reg_imm(incoming.reg, LSL, 31-incoming.h));
1075dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        AND(AL, 0, dest.reg, texel.reg, reg_imm(dest.reg, ASR, 31));
1076dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        dest.l = 0;
1077dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        dest.h = Nt;
1078dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
1079dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int inReg = incoming.reg;
1080dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int shift = incoming.l;
1081dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if ((Nt + Ni) > 32) {
1082dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // we will overflow, reduce the precision of Ni to 8 bits
1083dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // (Note Nt cannot be more than 10 bits which happens with
1084dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // 565 textures and GGL_LINEAR)
1085dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            shift += Ni-8;
1086dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            Ni = 8;
1087dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
1088dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1089dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // modulate by the component with the lowest precision
1090dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (Nt >= Ni) {
1091dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (shift) {
1092dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // XXX: we should be able to avoid this shift
1093dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // when shift==16 && Nt<16 && Ni<16, in which
1094dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // we could use SMULBT below.
1095dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                MOV(AL, 0, dest.reg, reg_imm(inReg, LSR, shift));
1096dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                inReg = dest.reg;
1097dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                shift = 0;
1098dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
1099dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // operation:           (Cf*Ct)/((1<<Ni)-1)
1100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // approximated with:   Cf*(Ct + Ct>>(Ni-1))>>Ni
1101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // this operation doesn't change texel's size
1102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ADD(AL, 0, dest.reg, inReg, reg_imm(inReg, LSR, Ni-1));
1103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (Nt<16 && Ni<16) SMULBB(AL, dest.reg, texel.reg, dest.reg);
1104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            else                MUL(AL, 0, dest.reg, texel.reg, dest.reg);
1105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            dest.l = Ni;
1106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            dest.h = Nt + Ni;
1107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
1108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (shift && (shift != 16)) {
1109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // if shift==16, we can use 16-bits mul instructions later
1110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                MOV(AL, 0, dest.reg, reg_imm(inReg, LSR, shift));
1111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                inReg = dest.reg;
1112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                shift = 0;
1113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
1114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // operation:           (Cf*Ct)/((1<<Nt)-1)
1115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // approximated with:   Ct*(Cf + Cf>>(Nt-1))>>Nt
1116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // this operation doesn't change incoming's size
1117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            Scratch scratches(registerFile());
1118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int t = (texel.flags & CORRUPTIBLE) ? texel.reg : dest.reg;
1119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (t == inReg)
1120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                t = scratches.obtain();
1121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ADD(AL, 0, t, texel.reg, reg_imm(texel.reg, LSR, Nt-1));
1122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (Nt<16 && Ni<16) {
1123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (shift==16)  SMULBT(AL, dest.reg, t, inReg);
1124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                else            SMULBB(AL, dest.reg, t, inReg);
1125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else              MUL(AL, 0, dest.reg, t, inReg);
1126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            dest.l = Nt;
1127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            dest.h = Nt + Ni;
1128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
1129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // low bits are not valid
1131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        dest.flags |= CLEAR_LO;
1132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // no need to keep more than 8 bits/component
1134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (dest.size() > 8)
1135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            dest.l = dest.h-8;
1136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
1137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid GGLAssembler::decal(
1140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        component_t& dest,
1141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const component_t& incoming,
1142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const pixel_t& incomingTexel, int component)
1143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
1144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // RGBA:
1145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // Cv = Cf*(1 - At) + Ct*At = Cf + (Ct - Cf)*At
1146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // Av = Af
1147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    Scratch locals(registerFile());
1148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    integer_t texel(locals.obtain(), 32, CORRUPTIBLE);
1149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    integer_t factor(locals.obtain(), 32, CORRUPTIBLE);
1150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    extract(texel, incomingTexel, component);
1151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    extract(factor, incomingTexel, GGLFormat::ALPHA);
1152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // no need to keep more than 8-bits for decal
1154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int Ni = incoming.size();
1155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int shift = incoming.l;
1156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (Ni > 8) {
1157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        shift += Ni-8;
1158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        Ni = 8;
1159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
1160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    integer_t incomingNorm(incoming.reg, Ni, incoming.flags);
1161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (shift) {
1162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        MOV(AL, 0, dest.reg, reg_imm(incomingNorm.reg, LSR, shift));
1163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        incomingNorm.reg = dest.reg;
1164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        incomingNorm.flags |= CORRUPTIBLE;
1165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
1166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ADD(AL, 0, factor.reg, factor.reg, reg_imm(factor.reg, LSR, factor.s-1));
1167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    build_blendOneMinusFF(dest, factor, incomingNorm, texel);
1168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid GGLAssembler::blend(
1171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        component_t& dest,
1172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const component_t& incoming,
1173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const pixel_t& incomingTexel, int component, int tmu)
1174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
1175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // RGBA:
1176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // Cv = (1 - Ct)*Cf + Ct*Cc = Cf + (Cc - Cf)*Ct
1177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // Av = At*Af
1178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (component == GGLFormat::ALPHA) {
1180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        modulate(dest, incoming, incomingTexel, component);
1181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return;
1182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
1183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    Scratch locals(registerFile());
1185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    integer_t color(locals.obtain(), 8, CORRUPTIBLE);
1186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    integer_t factor(locals.obtain(), 32, CORRUPTIBLE);
1187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    LDRB(AL, color.reg, mBuilderContext.Rctx,
1188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            immed12_pre(GGL_OFFSETOF(state.texture[tmu].env_color[component])));
1189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    extract(factor, incomingTexel, component);
1190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // no need to keep more than 8-bits for blend
1192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int Ni = incoming.size();
1193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int shift = incoming.l;
1194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (Ni > 8) {
1195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        shift += Ni-8;
1196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        Ni = 8;
1197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
1198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    integer_t incomingNorm(incoming.reg, Ni, incoming.flags);
1199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (shift) {
1200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        MOV(AL, 0, dest.reg, reg_imm(incomingNorm.reg, LSR, shift));
1201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        incomingNorm.reg = dest.reg;
1202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        incomingNorm.flags |= CORRUPTIBLE;
1203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
1204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ADD(AL, 0, factor.reg, factor.reg, reg_imm(factor.reg, LSR, factor.s-1));
1205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    build_blendOneMinusFF(dest, factor, incomingNorm, color);
1206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid GGLAssembler::add(
1209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        component_t& dest,
1210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const component_t& incoming,
1211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const pixel_t& incomingTexel, int component)
1212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
1213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // RGBA:
1214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // Cv = Cf + Ct;
1215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    Scratch locals(registerFile());
1216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    component_t incomingTemp(incoming);
1218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // use "dest" as a temporary for extracting the texel, unless "dest"
1220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // overlaps "incoming".
1221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    integer_t texel(dest.reg, 32, CORRUPTIBLE);
1222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (dest.reg == incomingTemp.reg)
1223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        texel.reg = locals.obtain();
1224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    extract(texel, incomingTexel, component);
1225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (texel.s < incomingTemp.size()) {
1227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        expand(texel, texel, incomingTemp.size());
1228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if (texel.s > incomingTemp.size()) {
1229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (incomingTemp.flags & CORRUPTIBLE) {
1230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            expand(incomingTemp, incomingTemp, texel.s);
1231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
1232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            incomingTemp.reg = locals.obtain();
1233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            expand(incomingTemp, incoming, texel.s);
1234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
1235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
1236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (incomingTemp.l) {
1238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ADD(AL, 0, dest.reg, texel.reg,
1239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                reg_imm(incomingTemp.reg, LSR, incomingTemp.l));
1240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
1241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ADD(AL, 0, dest.reg, texel.reg, incomingTemp.reg);
1242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
1243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    dest.l = 0;
1244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    dest.h = texel.size();
1245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    component_sat(dest);
1246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ----------------------------------------------------------------------------
1249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}; // namespace android
1251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1252