14f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project/* libs/pixelflinger/codeflinger/texturing.cpp
24f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project**
34f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project** Copyright 2006, The Android Open Source Project
44f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project**
54f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");
64f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project** you may not use this file except in compliance with the License.
74f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project** You may obtain a copy of the License at
84f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project**
94f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project**     http://www.apache.org/licenses/LICENSE-2.0
104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project**
114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project** Unless required by applicable law or agreed to in writing, software
124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS,
134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project** See the License for the specific language governing permissions and
154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project** limitations under the License.
164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project*/
174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <assert.h>
194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <stdint.h>
204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <stdlib.h>
214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <stdio.h>
224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <sys/types.h>
234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <cutils/log.h>
254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include "codeflinger/GGLAssembler.h"
274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
282bef93cc20155c3a59cdbb22c564c4b385b2c160Bruce Beare#ifdef __ARM_ARCH__
2996dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell#include <machine/cpu-features.h>
309b6c850d24df82451862b81f059361b586f5ef0bJean-Baptiste Queru#endif
314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectnamespace android {
334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project// ---------------------------------------------------------------------------
354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project// iterators are initialized like this:
374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project// (intToFixedCenter(x) * dx)>>16 + x0
384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project// ((x<<16 + 0x8000) * dx)>>16 + x0
394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project// ((x<<16)*dx + (0x8000*dx))>>16 + x0
404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project// ( (x*dx) + dx>>1 ) + x0
414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project// (x*dx) + (dx>>1 + x0)
424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::init_iterated_color(fragment_parts_t& parts, const reg_t& x)
444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    context_t const* c = mBuilderContext.c;
464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const needs_t& needs = mBuilderContext.needs;
474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (mSmooth) {
494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // NOTE: we could take this case in the mDithering + !mSmooth case,
504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // but this would use up to 4 more registers for the color components
514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // for only a little added quality.
524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // Currently, this causes the system to run out of registers in
534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // some case (see issue #719496)
544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        comment("compute initial iterated color (smooth and/or dither case)");
564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        parts.iterated_packed = 0;
584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        parts.packed = 0;
594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // 0x1: color component
614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // 0x2: iterators
624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const int optReload = mOptLevel >> 1;
634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (optReload >= 3)         parts.reload = 0; // reload nothing
644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        else if (optReload == 2)    parts.reload = 2; // reload iterators
654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        else if (optReload == 1)    parts.reload = 1; // reload colors
664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        else if (optReload <= 0)    parts.reload = 3; // reload both
674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (!mSmooth) {
694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // we're not smoothing (just dithering), we never have to
704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // reload the iterators
714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            parts.reload &= ~2;
724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        Scratch scratches(registerFile());
754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const int t0 = (parts.reload & 1) ? scratches.obtain() : 0;
764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const int t1 = (parts.reload & 2) ? scratches.obtain() : 0;
774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        for (int i=0 ; i<4 ; i++) {
784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (!mInfo[i].iterated)
794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                continue;
804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // this component exists in the destination and is not replaced
824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // by a texture unit.
834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            const int c = (parts.reload & 1) ? t0 : obtainReg();
844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (i==0) CONTEXT_LOAD(c, iterators.ydady);
854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (i==1) CONTEXT_LOAD(c, iterators.ydrdy);
864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (i==2) CONTEXT_LOAD(c, iterators.ydgdy);
874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (i==3) CONTEXT_LOAD(c, iterators.ydbdy);
884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            parts.argb[i].reg = c;
894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (mInfo[i].smooth) {
914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                parts.argb_dx[i].reg = (parts.reload & 2) ? t1 : obtainReg();
924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                const int dvdx = parts.argb_dx[i].reg;
934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_LOAD(dvdx, generated_vars.argb[i].dx);
944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                MLA(AL, 0, c, x.reg, dvdx, c);
954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // adjust the color iterator to make sure it won't overflow
974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (!mAA) {
984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // this is not needed when we're using anti-aliasing
994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // because we will (have to) clamp the components
1004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // anyway.
1014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    int end = scratches.obtain();
1024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(AL, 0, end, reg_imm(parts.count.reg, LSR, 16));
1034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MLA(AL, 1, end, dvdx, end, c);
1044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    SUB(MI, 0, c, c, end);
1054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    BIC(AL, 0, c, c, reg_imm(c, ASR, 31));
1064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    scratches.recycle(end);
1074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                }
1084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
1094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (parts.reload & 1) {
1114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_STORE(c, generated_vars.argb[i].c);
1124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
1134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
1144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
1154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // We're not smoothed, so we can
1164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // just use a packed version of the color and extract the
1174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // components as needed (or not at all if we don't blend)
1184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // figure out if we need the iterated color
1204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int load = 0;
1214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        for (int i=0 ; i<4 ; i++) {
1224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            component_info_t& info = mInfo[i];
1234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if ((info.inDest || info.needed) && !info.replaced)
1244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                load |= 1;
1254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
1264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        parts.iterated_packed = 1;
1284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        parts.packed = (!mTextureMachine.mask && !mBlending
1294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                && !mFog && !mDithering);
1304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        parts.reload = 0;
1314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (load || parts.packed) {
1324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (mBlending || mDithering || mInfo[GGLFormat::ALPHA].needed) {
1334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                comment("load initial iterated color (8888 packed)");
1344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                parts.iterated.setTo(obtainReg(),
1354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                        &(c->formats[GGL_PIXEL_FORMAT_RGBA_8888]));
1364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_LOAD(parts.iterated.reg, packed8888);
1374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            } else {
1384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                comment("load initial iterated color (dest format packed)");
1394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                parts.iterated.setTo(obtainReg(), &mCbFormat);
1414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // pre-mask the iterated color
1434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                const int bits = parts.iterated.size();
1444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                const uint32_t size = ((bits>=32) ? 0 : (1LU << bits)) - 1;
1454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                uint32_t mask = 0;
1464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (mMasking) {
1474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    for (int i=0 ; i<4 ; i++) {
1484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                        const int component_mask = 1<<i;
1494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                        const int h = parts.iterated.format.c[i].h;
1504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                        const int l = parts.iterated.format.c[i].l;
1514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                        if (h && (!(mMasking & component_mask))) {
1524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                            mask |= ((1<<(h-l))-1) << l;
1534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                        }
1544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    }
1554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                }
1564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (mMasking && ((mask & size)==0)) {
1584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // none of the components are present in the mask
1594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                } else {
1604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    CONTEXT_LOAD(parts.iterated.reg, packed);
1614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    if (mCbFormat.size == 1) {
1624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                        AND(AL, 0, parts.iterated.reg,
1634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                parts.iterated.reg, imm(0xFF));
1644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    } else if (mCbFormat.size == 2) {
1654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                        MOV(AL, 0, parts.iterated.reg,
1664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                reg_imm(parts.iterated.reg, LSR, 16));
1674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    }
1684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                }
1694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // pre-mask the iterated color
1714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (mMasking) {
1724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    build_and_immediate(parts.iterated.reg, parts.iterated.reg,
1734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                            mask, bits);
1744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                }
1754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
1764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
1774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
1794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::build_iterated_color(
1814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        component_t& fragment,
1824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const fragment_parts_t& parts,
1834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int component,
1844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        Scratch& regs)
1854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
1864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    fragment.setTo( regs.obtain(), 0, 32, CORRUPTIBLE);
1874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (!mInfo[component].iterated)
1894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
1904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (parts.iterated_packed) {
1924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // iterated colors are packed, extract the one we need
1934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        extract(fragment, parts.iterated, component);
1944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
1954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fragment.h = GGL_COLOR_BITS;
1964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fragment.l = GGL_COLOR_BITS - 8;
1974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fragment.flags |= CLEAR_LO;
1984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // iterated colors are held in their own register,
1994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // (smooth and/or dithering case)
2004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (parts.reload==3) {
2014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // this implies mSmooth
2024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            Scratch scratches(registerFile());
2034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int dx = scratches.obtain();
2044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(fragment.reg, generated_vars.argb[component].c);
2054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(dx, generated_vars.argb[component].dx);
2064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, dx, fragment.reg, dx);
2074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_STORE(dx, generated_vars.argb[component].c);
2084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (parts.reload & 1) {
2094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(fragment.reg, generated_vars.argb[component].c);
2104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else {
2114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // we don't reload, so simply rename the register and mark as
2124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // non CORRUPTIBLE so that the texture env or blending code
2134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // won't modify this (renamed) register
2144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            regs.recycle(fragment.reg);
2154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            fragment.reg = parts.argb[component].reg;
2164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            fragment.flags &= ~CORRUPTIBLE;
2174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (mInfo[component].smooth && mAA) {
2194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // when using smooth shading AND anti-aliasing, we need to clamp
2204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // the iterators because there is always an extra pixel on the
2214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // edges, which most of the time will cause an overflow
2224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // (since technically its outside of the domain).
2234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            BIC(AL, 0, fragment.reg, fragment.reg,
2244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    reg_imm(fragment.reg, ASR, 31));
2254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            component_sat(fragment);
2264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
2284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
2294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project// ---------------------------------------------------------------------------
2314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::decodeLogicOpNeeds(const needs_t& needs)
2334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
2344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // gather some informations about the components we need to process...
2354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const int opcode = GGL_READ_NEEDS(LOGIC_OP, needs.n) | GGL_CLEAR;
2364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    switch(opcode) {
2374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case GGL_COPY:
2384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        mLogicOp = 0;
2394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        break;
2404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case GGL_CLEAR:
2414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case GGL_SET:
2424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        mLogicOp = LOGIC_OP;
2434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        break;
2444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case GGL_AND:
2454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case GGL_AND_REVERSE:
2464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case GGL_AND_INVERTED:
2474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case GGL_XOR:
2484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case GGL_OR:
2494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case GGL_NOR:
2504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case GGL_EQUIV:
2514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case GGL_OR_REVERSE:
2524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case GGL_OR_INVERTED:
2534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case GGL_NAND:
2544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        mLogicOp = LOGIC_OP|LOGIC_OP_SRC|LOGIC_OP_DST;
2554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        break;
2564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case GGL_NOOP:
2574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case GGL_INVERT:
2584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        mLogicOp = LOGIC_OP|LOGIC_OP_DST;
2594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        break;
2604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case GGL_COPY_INVERTED:
2614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        mLogicOp = LOGIC_OP|LOGIC_OP_SRC;
2624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        break;
2634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    };
2644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
2654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::decodeTMUNeeds(const needs_t& needs, context_t const* c)
2674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
2684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    uint8_t replaced=0;
2694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mTextureMachine.mask = 0;
2704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mTextureMachine.activeUnits = 0;
2714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for (int i=GGL_TEXTURE_UNIT_COUNT-1 ; i>=0 ; i--) {
2724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        texture_unit_t& tmu = mTextureMachine.tmu[i];
2734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (replaced == 0xF) {
2744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // all components are replaced, skip this TMU.
2754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            tmu.format_idx = 0;
2764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            tmu.mask = 0;
2774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            tmu.replaced = replaced;
2784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            continue;
2794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        tmu.format_idx = GGL_READ_NEEDS(T_FORMAT, needs.t[i]);
2814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        tmu.format = c->formats[tmu.format_idx];
2824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        tmu.bits = tmu.format.size*8;
2834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        tmu.swrap = GGL_READ_NEEDS(T_S_WRAP, needs.t[i]);
2844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        tmu.twrap = GGL_READ_NEEDS(T_T_WRAP, needs.t[i]);
2854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        tmu.env = ggl_needs_to_env(GGL_READ_NEEDS(T_ENV, needs.t[i]));
2864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        tmu.pot = GGL_READ_NEEDS(T_POT, needs.t[i]);
2874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        tmu.linear = GGL_READ_NEEDS(T_LINEAR, needs.t[i])
2884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                && tmu.format.size!=3; // XXX: only 8, 16 and 32 modes for now
2894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // 5551 linear filtering is not supported
2914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (tmu.format_idx == GGL_PIXEL_FORMAT_RGBA_5551)
2924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            tmu.linear = 0;
2934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        tmu.mask = 0;
2954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        tmu.replaced = replaced;
2964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (tmu.format_idx) {
2984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            mTextureMachine.activeUnits++;
2994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (tmu.format.c[0].h)    tmu.mask |= 0x1;
3004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (tmu.format.c[1].h)    tmu.mask |= 0x2;
3014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (tmu.format.c[2].h)    tmu.mask |= 0x4;
3024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (tmu.format.c[3].h)    tmu.mask |= 0x8;
3034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (tmu.env == GGL_REPLACE) {
3044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                replaced |= tmu.mask;
3054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            } else if (tmu.env == GGL_DECAL) {
3064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (!tmu.format.c[GGLFormat::ALPHA].h) {
3074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // if we don't have alpha, decal does nothing
3084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    tmu.mask = 0;
3094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                } else {
3104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // decal always ignores At
3114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    tmu.mask &= ~(1<<GGLFormat::ALPHA);
3124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                }
3134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
3144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
3154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        mTextureMachine.mask |= tmu.mask;
3164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        //printf("%d: mask=%08lx, replaced=%08lx\n",
3174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        //    i, int(tmu.mask), int(tmu.replaced));
3184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mTextureMachine.replaced = replaced;
3204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mTextureMachine.directTexture = 0;
3214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    //printf("replaced=%08lx\n", mTextureMachine.replaced);
3224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
3234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::init_textures(
3264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        tex_coord_t* coords,
3274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const reg_t& x, const reg_t& y)
3284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
3294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    context_t const* c = mBuilderContext.c;
3304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const needs_t& needs = mBuilderContext.needs;
3314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int Rctx = mBuilderContext.Rctx;
3324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int Rx = x.reg;
3334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int Ry = y.reg;
3344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (mTextureMachine.mask) {
3364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        comment("compute texture coordinates");
3374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // init texture coordinates for each tmu
3404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const int cb_format_idx = GGL_READ_NEEDS(CB_FORMAT, needs.n);
3414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const bool multiTexture = mTextureMachine.activeUnits > 1;
3424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT; i++) {
3434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const texture_unit_t& tmu = mTextureMachine.tmu[i];
3444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (tmu.format_idx == 0)
3454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            continue;
3464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if ((tmu.swrap == GGL_NEEDS_WRAP_11) &&
3474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            (tmu.twrap == GGL_NEEDS_WRAP_11))
3484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        {
3494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // 1:1 texture
3504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            pointer_t& txPtr = coords[i].ptr;
3514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            txPtr.setTo(obtainReg(), tmu.bits);
3524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(txPtr.reg, state.texture[i].iterators.ydsdy);
3534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, Rx, Rx, reg_imm(txPtr.reg, ASR, 16));    // x += (s>>16)
3544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(txPtr.reg, state.texture[i].iterators.ydtdy);
3554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, Ry, Ry, reg_imm(txPtr.reg, ASR, 16));    // y += (t>>16)
3564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // merge base & offset
3574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(txPtr.reg, generated_vars.texture[i].stride);
3584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            SMLABB(AL, Rx, Ry, txPtr.reg, Rx);               // x+y*stride
3594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(txPtr.reg, generated_vars.texture[i].data);
3604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            base_offset(txPtr, txPtr, Rx);
3614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else {
3624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            Scratch scratches(registerFile());
3634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            reg_t& s = coords[i].s;
3644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            reg_t& t = coords[i].t;
3654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // s = (x * dsdx)>>16 + ydsdy
3664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // s = (x * dsdx)>>16 + (y*dsdy)>>16 + s0
3674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // t = (x * dtdx)>>16 + ydtdy
3684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // t = (x * dtdx)>>16 + (y*dtdy)>>16 + t0
3694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            s.setTo(obtainReg());
3704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            t.setTo(obtainReg());
3714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            const int need_w = GGL_READ_NEEDS(W, needs.n);
3724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (need_w) {
3734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_LOAD(s.reg, state.texture[i].iterators.ydsdy);
3744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_LOAD(t.reg, state.texture[i].iterators.ydtdy);
3754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            } else {
3764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                int ydsdy = scratches.obtain();
3774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                int ydtdy = scratches.obtain();
3784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_LOAD(s.reg, generated_vars.texture[i].dsdx);
3794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_LOAD(ydsdy, state.texture[i].iterators.ydsdy);
3804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_LOAD(t.reg, generated_vars.texture[i].dtdx);
3814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_LOAD(ydtdy, state.texture[i].iterators.ydtdy);
3824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                MLA(AL, 0, s.reg, Rx, s.reg, ydsdy);
3834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                MLA(AL, 0, t.reg, Rx, t.reg, ydtdy);
3844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
3854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if ((mOptLevel&1)==0) {
3874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_STORE(s.reg, generated_vars.texture[i].spill[0]);
3884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_STORE(t.reg, generated_vars.texture[i].spill[1]);
3894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                recycleReg(s.reg);
3904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                recycleReg(t.reg);
3914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
3924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
3934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // direct texture?
3954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (!multiTexture && !mBlending && !mDithering && !mFog &&
3964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            cb_format_idx == tmu.format_idx && !tmu.linear &&
3974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            mTextureMachine.replaced == tmu.mask)
3984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        {
3994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                mTextureMachine.directTexture = i + 1;
4004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
4014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
4024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
4034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::build_textures(  fragment_parts_t& parts,
4054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                    Scratch& regs)
4064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
4074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    context_t const* c = mBuilderContext.c;
4084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const needs_t& needs = mBuilderContext.needs;
4094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int Rctx = mBuilderContext.Rctx;
4104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // We don't have a way to spill registers automatically
4124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // spill depth and AA regs, when we know we may have to.
4134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // build the spill list...
4144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    uint32_t spill_list = 0;
4154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT; i++) {
4164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const texture_unit_t& tmu = mTextureMachine.tmu[i];
4174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (tmu.format_idx == 0)
4184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            continue;
4194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (tmu.linear) {
4204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // we may run out of register if we have linear filtering
4214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // at 1 or 4 bytes / pixel on any texture unit.
4224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (tmu.format.size == 1) {
4234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // if depth and AA enabled, we'll run out of 1 register
4244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (parts.z.reg > 0 && parts.covPtr.reg > 0)
4254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    spill_list |= 1<<parts.covPtr.reg;
4264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
4274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (tmu.format.size == 4) {
4284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // if depth or AA enabled, we'll run out of 1 or 2 registers
4294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (parts.z.reg > 0)
4304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    spill_list |= 1<<parts.z.reg;
4314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (parts.covPtr.reg > 0)
4324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    spill_list |= 1<<parts.covPtr.reg;
4334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
4344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
4354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
4364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    Spill spill(registerFile(), *this, spill_list);
4384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const bool multiTexture = mTextureMachine.activeUnits > 1;
4404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT; i++) {
4414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const texture_unit_t& tmu = mTextureMachine.tmu[i];
4424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (tmu.format_idx == 0)
4434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            continue;
4444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        pointer_t& txPtr = parts.coords[i].ptr;
4464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        pixel_t& texel = parts.texel[i];
4474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // repeat...
4494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if ((tmu.swrap == GGL_NEEDS_WRAP_11) &&
4504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            (tmu.twrap == GGL_NEEDS_WRAP_11))
4514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        { // 1:1 textures
4524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            comment("fetch texel");
4534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            texel.setTo(regs.obtain(), &tmu.format);
4544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            load(txPtr, texel, WRITE_BACK);
4554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else {
4564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            Scratch scratches(registerFile());
4574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            reg_t& s = parts.coords[i].s;
4584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            reg_t& t = parts.coords[i].t;
4594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if ((mOptLevel&1)==0) {
4604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                comment("reload s/t (multitexture or linear filtering)");
4614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                s.reg = scratches.obtain();
4624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                t.reg = scratches.obtain();
4634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_LOAD(s.reg, generated_vars.texture[i].spill[0]);
4644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_LOAD(t.reg, generated_vars.texture[i].spill[1]);
4654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
4664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4672bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            if (registerFile().status() & RegisterFile::OUT_OF_REGISTERS)
4682bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                return;
4692bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
4704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            comment("compute repeat/clamp");
4714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int u       = scratches.obtain();
4724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int v       = scratches.obtain();
4734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int width   = scratches.obtain();
4744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int height  = scratches.obtain();
4754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int U = 0;
4764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int V = 0;
4774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4782bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            if (registerFile().status() & RegisterFile::OUT_OF_REGISTERS)
4792bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                return;
4802bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
4814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(width,  generated_vars.texture[i].width);
4824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(height, generated_vars.texture[i].height);
4834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int FRAC_BITS = 0;
4854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (tmu.linear) {
4864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // linear interpolation
4874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (tmu.format.size == 1) {
4884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // for 8-bits textures, we can afford
4894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // 7 bits of fractional precision at no
4904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // additional cost (we can't do 8 bits
4914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // because filter8 uses signed 16 bits muls)
4924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    FRAC_BITS = 7;
4934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                } else if (tmu.format.size == 2) {
4944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // filter16() is internally limited to 4 bits, so:
4954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // FRAC_BITS=2 generates less instructions,
4964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // FRAC_BITS=3,4,5 creates unpleasant artifacts,
4974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // FRAC_BITS=6+ looks good
4984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    FRAC_BITS = 6;
4994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                } else if (tmu.format.size == 4) {
5004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // filter32() is internally limited to 8 bits, so:
5014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // FRAC_BITS=4 looks good
5024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // FRAC_BITS=5+ looks better, but generates 3 extra ipp
5034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    FRAC_BITS = 6;
5044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                } else {
5054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // for all other cases we use 4 bits.
5064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    FRAC_BITS = 4;
5074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                }
5084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
5094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            wrapping(u, s.reg, width,  tmu.swrap, FRAC_BITS);
5104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            wrapping(v, t.reg, height, tmu.twrap, FRAC_BITS);
5114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (tmu.linear) {
5134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                comment("compute linear filtering offsets");
5144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // pixel size scale
5154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                const int shift = 31 - gglClz(tmu.format.size);
5164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                U = scratches.obtain();
5174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                V = scratches.obtain();
5184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5192bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                if (registerFile().status() & RegisterFile::OUT_OF_REGISTERS)
5202bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                    return;
5212bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
5224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // sample the texel center
5234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                SUB(AL, 0, u, u, imm(1<<(FRAC_BITS-1)));
5244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                SUB(AL, 0, v, v, imm(1<<(FRAC_BITS-1)));
5254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // get the fractionnal part of U,V
5274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                AND(AL, 0, U, u, imm((1<<FRAC_BITS)-1));
5284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                AND(AL, 0, V, v, imm((1<<FRAC_BITS)-1));
5294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // compute width-1 and height-1
5314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                SUB(AL, 0, width,  width,  imm(1));
5324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                SUB(AL, 0, height, height, imm(1));
5334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // get the integer part of U,V and clamp/wrap
5354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // and compute offset to the next texel
5364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (tmu.swrap == GGL_NEEDS_WRAP_REPEAT) {
5374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // u has already been REPEATed
5384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(AL, 1, u, reg_imm(u, ASR, FRAC_BITS));
5394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(MI, 0, u, width);
5404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    CMP(AL, u, width);
5414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(LT, 0, width, imm(1 << shift));
5424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    if (shift)
5434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                        MOV(GE, 0, width, reg_imm(width, LSL, shift));
5444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    RSB(GE, 0, width, width, imm(0));
5454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                } else {
5464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // u has not been CLAMPed yet
5474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // algorithm:
5484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // if ((u>>4) >= width)
5494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    //      u = width<<4
5504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    //      width = 0
5514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // else
5524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    //      width = 1<<shift
5534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // u = u>>4; // get integer part
5544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // if (u<0)
5554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    //      u = 0
5564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    //      width = 0
5574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // generated_vars.rt = width
5584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    CMP(AL, width, reg_imm(u, ASR, FRAC_BITS));
5604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(LE, 0, u, reg_imm(width, LSL, FRAC_BITS));
5614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(LE, 0, width, imm(0));
5624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(GT, 0, width, imm(1 << shift));
5634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(AL, 1, u, reg_imm(u, ASR, FRAC_BITS));
5644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(MI, 0, u, imm(0));
5654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(MI, 0, width, imm(0));
5664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                }
5674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_STORE(width, generated_vars.rt);
5684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                const int stride = width;
5704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_LOAD(stride, generated_vars.texture[i].stride);
5714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (tmu.twrap == GGL_NEEDS_WRAP_REPEAT) {
5724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // v has already been REPEATed
5734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(AL, 1, v, reg_imm(v, ASR, FRAC_BITS));
5744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(MI, 0, v, height);
5754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    CMP(AL, v, height);
5764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(LT, 0, height, imm(1 << shift));
5774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    if (shift)
5784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                        MOV(GE, 0, height, reg_imm(height, LSL, shift));
5794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    RSB(GE, 0, height, height, imm(0));
5804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MUL(AL, 0, height, stride, height);
5814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                } else {
58296dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell                    // v has not been CLAMPed yet
5834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    CMP(AL, height, reg_imm(v, ASR, FRAC_BITS));
5844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(LE, 0, v, reg_imm(height, LSL, FRAC_BITS));
5854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(LE, 0, height, imm(0));
5864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    if (shift) {
5874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                        MOV(GT, 0, height, reg_imm(stride, LSL, shift));
5884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    } else {
5894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                        MOV(GT, 0, height, stride);
5904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    }
5914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(AL, 1, v, reg_imm(v, ASR, FRAC_BITS));
5924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(MI, 0, v, imm(0));
5934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(MI, 0, height, imm(0));
5944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                }
5954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_STORE(height, generated_vars.lb);
5964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
5974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            scratches.recycle(width);
5994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            scratches.recycle(height);
6004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // iterate texture coordinates...
6024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            comment("iterate s,t");
6034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int dsdx = scratches.obtain();
6044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int dtdx = scratches.obtain();
6052bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
6062bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            if (registerFile().status() & RegisterFile::OUT_OF_REGISTERS)
6072bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                return;
6082bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
6094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(dsdx, generated_vars.texture[i].dsdx);
6104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(dtdx, generated_vars.texture[i].dtdx);
6114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, s.reg, s.reg, dsdx);
6124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, t.reg, t.reg, dtdx);
6134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if ((mOptLevel&1)==0) {
6144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_STORE(s.reg, generated_vars.texture[i].spill[0]);
6154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_STORE(t.reg, generated_vars.texture[i].spill[1]);
6164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                scratches.recycle(s.reg);
6174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                scratches.recycle(t.reg);
6184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
6194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            scratches.recycle(dsdx);
6204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            scratches.recycle(dtdx);
6214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // merge base & offset...
6234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            comment("merge base & offset");
6244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            texel.setTo(regs.obtain(), &tmu.format);
6254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            txPtr.setTo(texel.reg, tmu.bits);
6264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int stride = scratches.obtain();
6272bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
6282bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind            if (registerFile().status() & RegisterFile::OUT_OF_REGISTERS)
6292bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind                return;
6302bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
6314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(stride,    generated_vars.texture[i].stride);
6324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(txPtr.reg, generated_vars.texture[i].data);
6334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            SMLABB(AL, u, v, stride, u);    // u+v*stride
6344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            base_offset(txPtr, txPtr, u);
6354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // load texel
6374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (!tmu.linear) {
6384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                comment("fetch texel");
6394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                load(txPtr, texel, 0);
6404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            } else {
6414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // recycle registers we don't need anymore
6424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                scratches.recycle(u);
6434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                scratches.recycle(v);
6444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                scratches.recycle(stride);
6454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                comment("fetch texel, bilinear");
6474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                switch (tmu.format.size) {
6484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                case 1:  filter8(parts, texel, tmu, U, V, txPtr, FRAC_BITS); break;
6494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                case 2: filter16(parts, texel, tmu, U, V, txPtr, FRAC_BITS); break;
6504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                case 3: filter24(parts, texel, tmu, U, V, txPtr, FRAC_BITS); break;
6514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                case 4: filter32(parts, texel, tmu, U, V, txPtr, FRAC_BITS); break;
6524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                }
6534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
6544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
6554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
6564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
6574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::build_iterate_texture_coordinates(
6594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const fragment_parts_t& parts)
6604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
6614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const bool multiTexture = mTextureMachine.activeUnits > 1;
6624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT; i++) {
6634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const texture_unit_t& tmu = mTextureMachine.tmu[i];
6644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (tmu.format_idx == 0)
6654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            continue;
6664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if ((tmu.swrap == GGL_NEEDS_WRAP_11) &&
6684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            (tmu.twrap == GGL_NEEDS_WRAP_11))
6694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        { // 1:1 textures
6704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            const pointer_t& txPtr = parts.coords[i].ptr;
6714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, txPtr.reg, txPtr.reg, imm(txPtr.size>>3));
6724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else {
6734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            Scratch scratches(registerFile());
6744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int s = parts.coords[i].s.reg;
6754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int t = parts.coords[i].t.reg;
6764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if ((mOptLevel&1)==0) {
6774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                s = scratches.obtain();
6784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                t = scratches.obtain();
6794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_LOAD(s, generated_vars.texture[i].spill[0]);
6804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_LOAD(t, generated_vars.texture[i].spill[1]);
6814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
6824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int dsdx = scratches.obtain();
6834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int dtdx = scratches.obtain();
6844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(dsdx, generated_vars.texture[i].dsdx);
6854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(dtdx, generated_vars.texture[i].dtdx);
6864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, s, s, dsdx);
6874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, t, t, dtdx);
6884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if ((mOptLevel&1)==0) {
6894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_STORE(s, generated_vars.texture[i].spill[0]);
6904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_STORE(t, generated_vars.texture[i].spill[1]);
6914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
6924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
6934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
6944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
6954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::filter8(
6974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const fragment_parts_t& parts,
6984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        pixel_t& texel, const texture_unit_t& tmu,
6994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int U, int V, pointer_t& txPtr,
7004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int FRAC_BITS)
7014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
7024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (tmu.format.components != GGL_ALPHA &&
7034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        tmu.format.components != GGL_LUMINANCE)
7044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    {
7054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // this is a packed format, and we don't support
7064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // linear filtering (it's probably RGB 332)
7074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // Should not happen with OpenGL|ES
7084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        LDRB(AL, texel.reg, txPtr.reg);
7094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
7104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
7114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // ------------------------
7134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // about ~22 cycles / pixel
7144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    Scratch scratches(registerFile());
7154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int pixel= scratches.obtain();
7174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int d    = scratches.obtain();
7184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int u    = scratches.obtain();
7194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int k    = scratches.obtain();
7204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int rt   = scratches.obtain();
7214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int lb   = scratches.obtain();
7224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // RB -> U * V
7244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    CONTEXT_LOAD(rt, generated_vars.rt);
7264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    CONTEXT_LOAD(lb, generated_vars.lb);
7274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int offset = pixel;
7294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ADD(AL, 0, offset, lb, rt);
7304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDRB(AL, pixel, txPtr.reg, reg_scale_pre(offset));
7314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMULBB(AL, u, U, V);
7324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMULBB(AL, d, pixel, u);
7334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    RSB(AL, 0, k, u, imm(1<<(FRAC_BITS*2)));
7344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // LB -> (1-U) * V
7364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    RSB(AL, 0, U, U, imm(1<<FRAC_BITS));
7374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDRB(AL, pixel, txPtr.reg, reg_scale_pre(lb));
7384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMULBB(AL, u, U, V);
7394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMLABB(AL, d, pixel, u, d);
7404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SUB(AL, 0, k, k, u);
7414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // LT -> (1-U)*(1-V)
7434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    RSB(AL, 0, V, V, imm(1<<FRAC_BITS));
7444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDRB(AL, pixel, txPtr.reg);
7454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMULBB(AL, u, U, V);
7464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMLABB(AL, d, pixel, u, d);
7474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // RT -> U*(1-V)
7494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDRB(AL, pixel, txPtr.reg, reg_scale_pre(rt));
7504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SUB(AL, 0, u, k, u);
7514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMLABB(AL, texel.reg, pixel, u, d);
7524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for (int i=0 ; i<4 ; i++) {
7544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (!texel.format.c[i].h) continue;
7554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        texel.format.c[i].h = FRAC_BITS*2+8;
7564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        texel.format.c[i].l = FRAC_BITS*2; // keeping 8 bits in enough
7574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
7584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    texel.format.size = 4;
7594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    texel.format.bitsPerPixel = 32;
7604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    texel.flags |= CLEAR_LO;
7614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
7624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::filter16(
7644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const fragment_parts_t& parts,
7654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        pixel_t& texel, const texture_unit_t& tmu,
7664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int U, int V, pointer_t& txPtr,
7674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int FRAC_BITS)
7684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
7694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // compute the mask
7704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // XXX: it would be nice if the mask below could be computed
7714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // automatically.
7724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    uint32_t mask = 0;
7734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int shift = 0;
7744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int prec = 0;
7754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    switch (tmu.format_idx) {
7764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        case GGL_PIXEL_FORMAT_RGB_565:
7774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // source: 00000ggg.ggg00000 | rrrrr000.000bbbbb
7784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // result: gggggggg.gggrrrrr | rrrrr0bb.bbbbbbbb
7794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            mask = 0x07E0F81F;
7804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            shift = 16;
7814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            prec = 5;
7824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            break;
7834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        case GGL_PIXEL_FORMAT_RGBA_4444:
7844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // 0000,1111,0000,1111 | 0000,1111,0000,1111
7854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            mask = 0x0F0F0F0F;
7864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            shift = 12;
7874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            prec = 4;
7884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            break;
7894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        case GGL_PIXEL_FORMAT_LA_88:
7904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // 0000,0000,1111,1111 | 0000,0000,1111,1111
7914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // AALL -> 00AA | 00LL
7924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            mask = 0x00FF00FF;
7934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            shift = 8;
7944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            prec = 8;
7954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            break;
7964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        default:
7974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // unsupported format, do something sensical...
79801dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block            ALOGE("Unsupported 16-bits texture format (%d)", tmu.format_idx);
7994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            LDRH(AL, texel.reg, txPtr.reg);
8004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            return;
8014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
8024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const int adjust = FRAC_BITS*2 - prec;
8044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const int round  = 0;
8054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // update the texel format
8074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    texel.format.size = 4;
8084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    texel.format.bitsPerPixel = 32;
8094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    texel.flags |= CLEAR_HI|CLEAR_LO;
8104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for (int i=0 ; i<4 ; i++) {
8114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (!texel.format.c[i].h) continue;
8124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const uint32_t offset = (mask & tmu.format.mask(i)) ? 0 : shift;
8134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        texel.format.c[i].h = tmu.format.c[i].h + offset + prec;
8144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        texel.format.c[i].l = texel.format.c[i].h - (tmu.format.bits(i) + prec);
8154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
8164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // ------------------------
8184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // about ~40 cycles / pixel
8194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    Scratch scratches(registerFile());
8204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int pixel= scratches.obtain();
8224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int d    = scratches.obtain();
8234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int u    = scratches.obtain();
8244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int k    = scratches.obtain();
8254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // RB -> U * V
8274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int offset = pixel;
8284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    CONTEXT_LOAD(offset, generated_vars.rt);
8294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    CONTEXT_LOAD(u, generated_vars.lb);
8304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ADD(AL, 0, offset, offset, u);
8314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDRH(AL, pixel, txPtr.reg, reg_pre(offset));
8334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMULBB(AL, u, U, V);
8344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ORR(AL, 0, pixel, pixel, reg_imm(pixel, LSL, shift));
8354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    build_and_immediate(pixel, pixel, mask, 32);
8364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (adjust) {
8374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (round)
8384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, u, u, imm(1<<(adjust-1)));
8394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        MOV(AL, 0, u, reg_imm(u, LSR, adjust));
8404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
8414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MUL(AL, 0, d, pixel, u);
8424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    RSB(AL, 0, k, u, imm(1<<prec));
8434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // LB -> (1-U) * V
8454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    CONTEXT_LOAD(offset, generated_vars.lb);
8464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    RSB(AL, 0, U, U, imm(1<<FRAC_BITS));
8474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDRH(AL, pixel, txPtr.reg, reg_pre(offset));
8484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMULBB(AL, u, U, V);
8494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ORR(AL, 0, pixel, pixel, reg_imm(pixel, LSL, shift));
8504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    build_and_immediate(pixel, pixel, mask, 32);
8514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (adjust) {
8524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (round)
8534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, u, u, imm(1<<(adjust-1)));
8544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        MOV(AL, 0, u, reg_imm(u, LSR, adjust));
8554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
8564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MLA(AL, 0, d, pixel, u, d);
8574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SUB(AL, 0, k, k, u);
8584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // LT -> (1-U)*(1-V)
8604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    RSB(AL, 0, V, V, imm(1<<FRAC_BITS));
8614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDRH(AL, pixel, txPtr.reg);
8624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMULBB(AL, u, U, V);
8634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ORR(AL, 0, pixel, pixel, reg_imm(pixel, LSL, shift));
8644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    build_and_immediate(pixel, pixel, mask, 32);
8654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (adjust) {
8664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (round)
8674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, u, u, imm(1<<(adjust-1)));
8684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        MOV(AL, 0, u, reg_imm(u, LSR, adjust));
8694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
8704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MLA(AL, 0, d, pixel, u, d);
8714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // RT -> U*(1-V)
8734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    CONTEXT_LOAD(offset, generated_vars.rt);
8744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDRH(AL, pixel, txPtr.reg, reg_pre(offset));
8754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SUB(AL, 0, u, k, u);
8764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ORR(AL, 0, pixel, pixel, reg_imm(pixel, LSL, shift));
8774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    build_and_immediate(pixel, pixel, mask, 32);
8784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MLA(AL, 0, texel.reg, pixel, u, d);
8794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
8804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::filter24(
8824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const fragment_parts_t& parts,
8834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        pixel_t& texel, const texture_unit_t& tmu,
8844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int U, int V, pointer_t& txPtr,
8854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int FRAC_BITS)
8864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
8874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // not supported yet (currently disabled)
8884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    load(txPtr, texel, 0);
8894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
8904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
89196dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell#if __ARM_ARCH__ >= 6
89296dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell// ARMv6 version, using UXTB16, and scheduled for Cortex-A8 pipeline
89396dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewellvoid GGLAssembler::filter32(
89496dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        const fragment_parts_t& parts,
89596dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        pixel_t& texel, const texture_unit_t& tmu,
89696dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        int U, int V, pointer_t& txPtr,
89796dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        int FRAC_BITS)
89896dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell{
89996dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    const int adjust = FRAC_BITS*2 - 8;
90096dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    const int round  = 0;
90196dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    const int prescale = 16 - adjust;
90296dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell
90396dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    Scratch scratches(registerFile());
90496dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell
90596dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    int pixel= scratches.obtain();
90696dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    int dh   = scratches.obtain();
90796dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    int u    = scratches.obtain();
90896dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    int k    = scratches.obtain();
90996dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell
91096dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    int temp = scratches.obtain();
91196dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    int dl   = scratches.obtain();
91296dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell
91396dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    int offsetrt = scratches.obtain();
91496dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    int offsetlb = scratches.obtain();
91596dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell
91696dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    int pixellb = offsetlb;
91796dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell
91896dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    // RB -> U * V
91996dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    CONTEXT_LOAD(offsetrt, generated_vars.rt);
92096dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    CONTEXT_LOAD(offsetlb, generated_vars.lb);
92196dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    if(!round) {
92296dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        MOV(AL, 0, U, reg_imm(U, LSL, prescale));
92396dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    }
92496dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    ADD(AL, 0, u, offsetrt, offsetlb);
92596dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell
92696dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    LDR(AL, pixel, txPtr.reg, reg_scale_pre(u));
92796dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    if (round) {
92896dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        SMULBB(AL, u, U, V);
92996dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        RSB(AL, 0, U, U, imm(1<<FRAC_BITS));
93096dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    } else {
93196dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        SMULWB(AL, u, U, V);
93296dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        RSB(AL, 0, U, U, imm(1<<(FRAC_BITS+prescale)));
93396dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    }
93496dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    UXTB16(AL, temp, pixel, 0);
93596dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    if (round) {
93696dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        ADD(AL, 0, u, u, imm(1<<(adjust-1)));
93796dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        MOV(AL, 0, u, reg_imm(u, LSR, adjust));
93896dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    }
93996dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    LDR(AL, pixellb, txPtr.reg, reg_scale_pre(offsetlb));
94096dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    MUL(AL, 0, dh, temp, u);
94196dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    UXTB16(AL, temp, pixel, 8);
94296dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    MUL(AL, 0, dl, temp, u);
94396dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    RSB(AL, 0, k, u, imm(0x100));
94496dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell
94596dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    // LB -> (1-U) * V
94696dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    if (round) {
94796dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        SMULBB(AL, u, U, V);
94896dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    } else {
94996dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        SMULWB(AL, u, U, V);
95096dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    }
95196dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    UXTB16(AL, temp, pixellb, 0);
95296dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    if (round) {
95396dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        ADD(AL, 0, u, u, imm(1<<(adjust-1)));
95496dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        MOV(AL, 0, u, reg_imm(u, LSR, adjust));
95596dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    }
95696dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    MLA(AL, 0, dh, temp, u, dh);
95796dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    UXTB16(AL, temp, pixellb, 8);
95896dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    MLA(AL, 0, dl, temp, u, dl);
95996dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    SUB(AL, 0, k, k, u);
96096dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell
96196dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    // LT -> (1-U)*(1-V)
96296dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    RSB(AL, 0, V, V, imm(1<<FRAC_BITS));
96396dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    LDR(AL, pixel, txPtr.reg);
96496dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    if (round) {
96596dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        SMULBB(AL, u, U, V);
96696dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    } else {
96796dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        SMULWB(AL, u, U, V);
96896dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    }
96996dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    UXTB16(AL, temp, pixel, 0);
97096dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    if (round) {
97196dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        ADD(AL, 0, u, u, imm(1<<(adjust-1)));
97296dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        MOV(AL, 0, u, reg_imm(u, LSR, adjust));
97396dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    }
97496dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    MLA(AL, 0, dh, temp, u, dh);
97596dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    UXTB16(AL, temp, pixel, 8);
97696dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    MLA(AL, 0, dl, temp, u, dl);
97796dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell
97896dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    // RT -> U*(1-V)
97996dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    LDR(AL, pixel, txPtr.reg, reg_scale_pre(offsetrt));
98096dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    SUB(AL, 0, u, k, u);
98196dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    UXTB16(AL, temp, pixel, 0);
98296dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    MLA(AL, 0, dh, temp, u, dh);
98396dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    UXTB16(AL, temp, pixel, 8);
98496dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    MLA(AL, 0, dl, temp, u, dl);
98596dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell
98696dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    UXTB16(AL, dh, dh, 8);
98796dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    UXTB16(AL, dl, dl, 8);
98896dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    ORR(AL, 0, texel.reg, dh, reg_imm(dl, LSL, 8));
98996dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell}
99096dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell#else
9914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::filter32(
9924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const fragment_parts_t& parts,
9934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        pixel_t& texel, const texture_unit_t& tmu,
9944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int U, int V, pointer_t& txPtr,
9954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int FRAC_BITS)
9964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
9974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const int adjust = FRAC_BITS*2 - 8;
9984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const int round  = 0;
9994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // ------------------------
10014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // about ~38 cycles / pixel
10024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    Scratch scratches(registerFile());
10034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int pixel= scratches.obtain();
10054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int dh   = scratches.obtain();
10064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int u    = scratches.obtain();
10074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int k    = scratches.obtain();
10084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int temp = scratches.obtain();
10104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int dl   = scratches.obtain();
10114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int mask = scratches.obtain();
10124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MOV(AL, 0, mask, imm(0xFF));
10144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ORR(AL, 0, mask, mask, imm(0xFF0000));
10154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // RB -> U * V
10174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int offset = pixel;
10184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    CONTEXT_LOAD(offset, generated_vars.rt);
10194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    CONTEXT_LOAD(u, generated_vars.lb);
10204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ADD(AL, 0, offset, offset, u);
10214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDR(AL, pixel, txPtr.reg, reg_scale_pre(offset));
10234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMULBB(AL, u, U, V);
10244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AND(AL, 0, temp, mask, pixel);
10254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (adjust) {
10264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (round)
10274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, u, u, imm(1<<(adjust-1)));
10284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        MOV(AL, 0, u, reg_imm(u, LSR, adjust));
10294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
10304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MUL(AL, 0, dh, temp, u);
10314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AND(AL, 0, temp, mask, reg_imm(pixel, LSR, 8));
10324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MUL(AL, 0, dl, temp, u);
10334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    RSB(AL, 0, k, u, imm(0x100));
10344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // LB -> (1-U) * V
10364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    CONTEXT_LOAD(offset, generated_vars.lb);
10374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    RSB(AL, 0, U, U, imm(1<<FRAC_BITS));
10384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDR(AL, pixel, txPtr.reg, reg_scale_pre(offset));
10394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMULBB(AL, u, U, V);
10404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AND(AL, 0, temp, mask, pixel);
10414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (adjust) {
10424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (round)
10434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, u, u, imm(1<<(adjust-1)));
10444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        MOV(AL, 0, u, reg_imm(u, LSR, adjust));
10454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
10464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MLA(AL, 0, dh, temp, u, dh);
10474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AND(AL, 0, temp, mask, reg_imm(pixel, LSR, 8));
10484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MLA(AL, 0, dl, temp, u, dl);
10494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SUB(AL, 0, k, k, u);
10504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // LT -> (1-U)*(1-V)
10524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    RSB(AL, 0, V, V, imm(1<<FRAC_BITS));
10534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDR(AL, pixel, txPtr.reg);
10544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMULBB(AL, u, U, V);
10554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AND(AL, 0, temp, mask, pixel);
10564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (adjust) {
10574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (round)
10584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, u, u, imm(1<<(adjust-1)));
10594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        MOV(AL, 0, u, reg_imm(u, LSR, adjust));
10604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
10614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MLA(AL, 0, dh, temp, u, dh);
10624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AND(AL, 0, temp, mask, reg_imm(pixel, LSR, 8));
10634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MLA(AL, 0, dl, temp, u, dl);
10644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // RT -> U*(1-V)
10664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    CONTEXT_LOAD(offset, generated_vars.rt);
10674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDR(AL, pixel, txPtr.reg, reg_scale_pre(offset));
10684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SUB(AL, 0, u, k, u);
10694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AND(AL, 0, temp, mask, pixel);
10704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MLA(AL, 0, dh, temp, u, dh);
10714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AND(AL, 0, temp, mask, reg_imm(pixel, LSR, 8));
10724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MLA(AL, 0, dl, temp, u, dl);
10734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AND(AL, 0, dh, mask, reg_imm(dh, LSR, 8));
10754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AND(AL, 0, dl, dl, reg_imm(mask, LSL, 8));
10764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ORR(AL, 0, texel.reg, dh, dl);
10774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
107896dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell#endif
10794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::build_texture_environment(
10814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        component_t& fragment,
10824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const fragment_parts_t& parts,
10834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int component,
10844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        Scratch& regs)
10854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
10864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const uint32_t component_mask = 1<<component;
10874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const bool multiTexture = mTextureMachine.activeUnits > 1;
10884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
10894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        texture_unit_t& tmu = mTextureMachine.tmu[i];
10904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (tmu.mask & component_mask) {
10924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // replace or modulate with this texture
10934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if ((tmu.replaced & component_mask) == 0) {
10944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // not replaced by a later tmu...
10954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                Scratch scratches(registerFile());
10974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                pixel_t texel(parts.texel[i]);
10982bc2b792782b304b15d8c48b54916a9b3fa3a7acPaul Lind
10994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (multiTexture &&
11004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    tmu.swrap == GGL_NEEDS_WRAP_11 &&
11014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    tmu.twrap == GGL_NEEDS_WRAP_11)
11024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                {
11034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    texel.reg = scratches.obtain();
11044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    texel.flags |= CORRUPTIBLE;
11054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    comment("fetch texel (multitexture 1:1)");
11064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    load(parts.coords[i].ptr, texel, WRITE_BACK);
11074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                 }
11084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
11094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                component_t incoming(fragment);
11104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                modify(fragment, regs);
11114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
11124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                switch (tmu.env) {
11134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                case GGL_REPLACE:
11144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    extract(fragment, texel, component);
11154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    break;
11164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                case GGL_MODULATE:
11174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    modulate(fragment, incoming, texel, component);
11184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    break;
11194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                case GGL_DECAL:
11204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    decal(fragment, incoming, texel, component);
11214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    break;
11224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                case GGL_BLEND:
11234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    blend(fragment, incoming, texel, component, i);
11244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    break;
112535237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project                case GGL_ADD:
112635237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project                    add(fragment, incoming, texel, component);
112735237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project                    break;
11284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                }
11294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
11304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
11314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
11324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
11334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
11344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project// ---------------------------------------------------------------------------
11354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
11364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::wrapping(
11374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int d,
11384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int coord, int size,
11394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int tx_wrap, int tx_linear)
11404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
11414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // notes:
11424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // if tx_linear is set, we need 4 extra bits of precision on the result
11434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // SMULL/UMULL is 3 cycles
11444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    Scratch scratches(registerFile());
11454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int c = coord;
11464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (tx_wrap == GGL_NEEDS_WRAP_REPEAT) {
11474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // UMULL takes 4 cycles (interlocked), and we can get away with
11484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // 2 cycles using SMULWB, but we're loosing 16 bits of precision
11494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // out of 32 (this is not a problem because the iterator keeps
11504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // its full precision)
11514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // UMULL(AL, 0, size, d, c, size);
11524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // note: we can't use SMULTB because it's signed.
11534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        MOV(AL, 0, d, reg_imm(c, LSR, 16-tx_linear));
11544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SMULWB(AL, d, d, size);
11554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else if (tx_wrap == GGL_NEEDS_WRAP_CLAMP_TO_EDGE) {
11564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (tx_linear) {
11574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // 1 cycle
11584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            MOV(AL, 0, d, reg_imm(coord, ASR, 16-tx_linear));
11594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else {
11604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // 4 cycles (common case)
11614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            MOV(AL, 0, d, reg_imm(coord, ASR, 16));
11624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            BIC(AL, 0, d, d, reg_imm(d, ASR, 31));
11634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CMP(AL, d, size);
11644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            SUB(GE, 0, d, size, imm(1));
11654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
11664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
11674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
11684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
11694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project// ---------------------------------------------------------------------------
11704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
11714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::modulate(
11724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        component_t& dest,
11734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const component_t& incoming,
11744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const pixel_t& incomingTexel, int component)
11754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
11764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    Scratch locals(registerFile());
11774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    integer_t texel(locals.obtain(), 32, CORRUPTIBLE);
11784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    extract(texel, incomingTexel, component);
11794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
11804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const int Nt = texel.size();
11814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // Nt should always be less than 10 bits because it comes
11824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // from the TMU.
11834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
11844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int Ni = incoming.size();
11854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // Ni could be big because it comes from previous MODULATEs
11864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
11874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (Nt == 1) {
11884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // texel acts as a bit-mask
11894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // dest = incoming & ((texel << incoming.h)-texel)
11904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        RSB(AL, 0, dest.reg, texel.reg, reg_imm(texel.reg, LSL, incoming.h));
11914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        AND(AL, 0, dest.reg, dest.reg, incoming.reg);
11924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        dest.l = incoming.l;
11934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        dest.h = incoming.h;
11944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        dest.flags |= (incoming.flags & CLEAR_LO);
11954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else if (Ni == 1) {
11964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        MOV(AL, 0, dest.reg, reg_imm(incoming.reg, LSL, 31-incoming.h));
11974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        AND(AL, 0, dest.reg, texel.reg, reg_imm(dest.reg, ASR, 31));
11984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        dest.l = 0;
11994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        dest.h = Nt;
12004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
12014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int inReg = incoming.reg;
12024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int shift = incoming.l;
12034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if ((Nt + Ni) > 32) {
12044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // we will overflow, reduce the precision of Ni to 8 bits
12054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // (Note Nt cannot be more than 10 bits which happens with
12064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // 565 textures and GGL_LINEAR)
12074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            shift += Ni-8;
12084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            Ni = 8;
12094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
12104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
12114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // modulate by the component with the lowest precision
12124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (Nt >= Ni) {
12134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (shift) {
12144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // XXX: we should be able to avoid this shift
12154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // when shift==16 && Nt<16 && Ni<16, in which
12164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // we could use SMULBT below.
12174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                MOV(AL, 0, dest.reg, reg_imm(inReg, LSR, shift));
12184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                inReg = dest.reg;
12194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                shift = 0;
12204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
12214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // operation:           (Cf*Ct)/((1<<Ni)-1)
12224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // approximated with:   Cf*(Ct + Ct>>(Ni-1))>>Ni
12234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // this operation doesn't change texel's size
12244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, dest.reg, inReg, reg_imm(inReg, LSR, Ni-1));
12254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (Nt<16 && Ni<16) SMULBB(AL, dest.reg, texel.reg, dest.reg);
12264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            else                MUL(AL, 0, dest.reg, texel.reg, dest.reg);
12274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            dest.l = Ni;
12284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            dest.h = Nt + Ni;
12294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else {
12304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (shift && (shift != 16)) {
12314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // if shift==16, we can use 16-bits mul instructions later
12324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                MOV(AL, 0, dest.reg, reg_imm(inReg, LSR, shift));
12334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                inReg = dest.reg;
12344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                shift = 0;
12354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
12364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // operation:           (Cf*Ct)/((1<<Nt)-1)
12374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // approximated with:   Ct*(Cf + Cf>>(Nt-1))>>Nt
12384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // this operation doesn't change incoming's size
12394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            Scratch scratches(registerFile());
12404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int t = (texel.flags & CORRUPTIBLE) ? texel.reg : dest.reg;
12414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (t == inReg)
12424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                t = scratches.obtain();
12434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, t, texel.reg, reg_imm(texel.reg, LSR, Nt-1));
12444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (Nt<16 && Ni<16) {
12454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (shift==16)  SMULBT(AL, dest.reg, t, inReg);
12464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                else            SMULBB(AL, dest.reg, t, inReg);
12474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            } else              MUL(AL, 0, dest.reg, t, inReg);
12484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            dest.l = Nt;
12494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            dest.h = Nt + Ni;
12504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
12514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
12524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // low bits are not valid
12534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        dest.flags |= CLEAR_LO;
12544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
12554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // no need to keep more than 8 bits/component
12564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (dest.size() > 8)
12574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            dest.l = dest.h-8;
12584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
12594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
12604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
12614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::decal(
12624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        component_t& dest,
12634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const component_t& incoming,
12644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const pixel_t& incomingTexel, int component)
12654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
12664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // RGBA:
12674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // Cv = Cf*(1 - At) + Ct*At = Cf + (Ct - Cf)*At
12684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // Av = Af
12694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    Scratch locals(registerFile());
12704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    integer_t texel(locals.obtain(), 32, CORRUPTIBLE);
12714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    integer_t factor(locals.obtain(), 32, CORRUPTIBLE);
12724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    extract(texel, incomingTexel, component);
12734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    extract(factor, incomingTexel, GGLFormat::ALPHA);
12744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
12754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // no need to keep more than 8-bits for decal
12764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int Ni = incoming.size();
12774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int shift = incoming.l;
12784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (Ni > 8) {
12794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        shift += Ni-8;
12804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        Ni = 8;
12814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
12824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    integer_t incomingNorm(incoming.reg, Ni, incoming.flags);
12834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (shift) {
12844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        MOV(AL, 0, dest.reg, reg_imm(incomingNorm.reg, LSR, shift));
12854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        incomingNorm.reg = dest.reg;
12864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        incomingNorm.flags |= CORRUPTIBLE;
12874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
12884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ADD(AL, 0, factor.reg, factor.reg, reg_imm(factor.reg, LSR, factor.s-1));
12894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    build_blendOneMinusFF(dest, factor, incomingNorm, texel);
12904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
12914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
12924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::blend(
12934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        component_t& dest,
12944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const component_t& incoming,
12954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const pixel_t& incomingTexel, int component, int tmu)
12964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
12974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // RGBA:
12984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // Cv = (1 - Ct)*Cf + Ct*Cc = Cf + (Cc - Cf)*Ct
12994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // Av = At*Af
13004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
13014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (component == GGLFormat::ALPHA) {
13024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        modulate(dest, incoming, incomingTexel, component);
13034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
13044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
13054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
13064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    Scratch locals(registerFile());
13074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    integer_t color(locals.obtain(), 8, CORRUPTIBLE);
13084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    integer_t factor(locals.obtain(), 32, CORRUPTIBLE);
13094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDRB(AL, color.reg, mBuilderContext.Rctx,
13104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            immed12_pre(GGL_OFFSETOF(state.texture[tmu].env_color[component])));
13114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    extract(factor, incomingTexel, component);
13124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
13134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // no need to keep more than 8-bits for blend
13144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int Ni = incoming.size();
13154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int shift = incoming.l;
13164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (Ni > 8) {
13174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        shift += Ni-8;
13184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        Ni = 8;
13194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
13204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    integer_t incomingNorm(incoming.reg, Ni, incoming.flags);
13214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (shift) {
13224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        MOV(AL, 0, dest.reg, reg_imm(incomingNorm.reg, LSR, shift));
13234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        incomingNorm.reg = dest.reg;
13244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        incomingNorm.flags |= CORRUPTIBLE;
13254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
13264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ADD(AL, 0, factor.reg, factor.reg, reg_imm(factor.reg, LSR, factor.s-1));
13274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    build_blendOneMinusFF(dest, factor, incomingNorm, color);
13284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
13294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
133035237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Projectvoid GGLAssembler::add(
133135237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        component_t& dest,
133235237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        const component_t& incoming,
133335237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        const pixel_t& incomingTexel, int component)
133435237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project{
133535237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    // RGBA:
133635237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    // Cv = Cf + Ct;
133735237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    Scratch locals(registerFile());
133835237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project
133935237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    component_t incomingTemp(incoming);
134035237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project
134135237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    // use "dest" as a temporary for extracting the texel, unless "dest"
134235237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    // overlaps "incoming".
134335237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    integer_t texel(dest.reg, 32, CORRUPTIBLE);
134435237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    if (dest.reg == incomingTemp.reg)
134535237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        texel.reg = locals.obtain();
134635237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    extract(texel, incomingTexel, component);
134735237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project
134835237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    if (texel.s < incomingTemp.size()) {
134935237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        expand(texel, texel, incomingTemp.size());
135035237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    } else if (texel.s > incomingTemp.size()) {
135135237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        if (incomingTemp.flags & CORRUPTIBLE) {
135235237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project            expand(incomingTemp, incomingTemp, texel.s);
135335237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        } else {
135435237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project            incomingTemp.reg = locals.obtain();
135535237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project            expand(incomingTemp, incoming, texel.s);
135635237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        }
135735237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    }
135835237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project
135935237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    if (incomingTemp.l) {
136035237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        ADD(AL, 0, dest.reg, texel.reg,
136135237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project                reg_imm(incomingTemp.reg, LSR, incomingTemp.l));
136235237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    } else {
136335237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        ADD(AL, 0, dest.reg, texel.reg, incomingTemp.reg);
136435237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    }
136535237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    dest.l = 0;
136635237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    dest.h = texel.size();
136735237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    component_sat(dest);
136835237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project}
136935237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project
13704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project// ----------------------------------------------------------------------------
13714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
13724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}; // namespace android
13734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1374