texturing.cpp revision 9b6c850d24df82451862b81f059361b586f5ef0b
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
289b6c850d24df82451862b81f059361b586f5ef0bJean-Baptiste Queru#ifdef __arm__
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
4674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            comment("compute repeat/clamp");
4684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int u       = scratches.obtain();
4694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int v       = scratches.obtain();
4704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int width   = scratches.obtain();
4714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int height  = scratches.obtain();
4724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int U = 0;
4734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int V = 0;
4744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(width,  generated_vars.texture[i].width);
4764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(height, generated_vars.texture[i].height);
4774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int FRAC_BITS = 0;
4794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (tmu.linear) {
4804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // linear interpolation
4814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (tmu.format.size == 1) {
4824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // for 8-bits textures, we can afford
4834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // 7 bits of fractional precision at no
4844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // additional cost (we can't do 8 bits
4854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // because filter8 uses signed 16 bits muls)
4864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    FRAC_BITS = 7;
4874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                } else if (tmu.format.size == 2) {
4884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // filter16() is internally limited to 4 bits, so:
4894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // FRAC_BITS=2 generates less instructions,
4904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // FRAC_BITS=3,4,5 creates unpleasant artifacts,
4914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // FRAC_BITS=6+ looks good
4924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    FRAC_BITS = 6;
4934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                } else if (tmu.format.size == 4) {
4944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // filter32() is internally limited to 8 bits, so:
4954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // FRAC_BITS=4 looks good
4964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // FRAC_BITS=5+ looks better, but generates 3 extra ipp
4974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    FRAC_BITS = 6;
4984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                } else {
4994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // for all other cases we use 4 bits.
5004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    FRAC_BITS = 4;
5014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                }
5024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
5034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            wrapping(u, s.reg, width,  tmu.swrap, FRAC_BITS);
5044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            wrapping(v, t.reg, height, tmu.twrap, FRAC_BITS);
5054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (tmu.linear) {
5074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                comment("compute linear filtering offsets");
5084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // pixel size scale
5094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                const int shift = 31 - gglClz(tmu.format.size);
5104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                U = scratches.obtain();
5114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                V = scratches.obtain();
5124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // sample the texel center
5144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                SUB(AL, 0, u, u, imm(1<<(FRAC_BITS-1)));
5154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                SUB(AL, 0, v, v, imm(1<<(FRAC_BITS-1)));
5164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // get the fractionnal part of U,V
5184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                AND(AL, 0, U, u, imm((1<<FRAC_BITS)-1));
5194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                AND(AL, 0, V, v, imm((1<<FRAC_BITS)-1));
5204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // compute width-1 and height-1
5224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                SUB(AL, 0, width,  width,  imm(1));
5234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                SUB(AL, 0, height, height, imm(1));
5244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // get the integer part of U,V and clamp/wrap
5264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // and compute offset to the next texel
5274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (tmu.swrap == GGL_NEEDS_WRAP_REPEAT) {
5284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // u has already been REPEATed
5294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(AL, 1, u, reg_imm(u, ASR, FRAC_BITS));
5304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(MI, 0, u, width);
5314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    CMP(AL, u, width);
5324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(LT, 0, width, imm(1 << shift));
5334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    if (shift)
5344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                        MOV(GE, 0, width, reg_imm(width, LSL, shift));
5354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    RSB(GE, 0, width, width, imm(0));
5364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                } else {
5374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // u has not been CLAMPed yet
5384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // algorithm:
5394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // if ((u>>4) >= width)
5404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    //      u = width<<4
5414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    //      width = 0
5424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // else
5434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    //      width = 1<<shift
5444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // u = u>>4; // get integer part
5454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // if (u<0)
5464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    //      u = 0
5474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    //      width = 0
5484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // generated_vars.rt = width
5494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    CMP(AL, width, reg_imm(u, ASR, FRAC_BITS));
5514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(LE, 0, u, reg_imm(width, LSL, FRAC_BITS));
5524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(LE, 0, width, imm(0));
5534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(GT, 0, width, imm(1 << shift));
5544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(AL, 1, u, reg_imm(u, ASR, FRAC_BITS));
5554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(MI, 0, u, imm(0));
5564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(MI, 0, width, imm(0));
5574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                }
5584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_STORE(width, generated_vars.rt);
5594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                const int stride = width;
5614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_LOAD(stride, generated_vars.texture[i].stride);
5624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (tmu.twrap == GGL_NEEDS_WRAP_REPEAT) {
5634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // v has already been REPEATed
5644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(AL, 1, v, reg_imm(v, ASR, FRAC_BITS));
5654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(MI, 0, v, height);
5664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    CMP(AL, v, height);
5674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(LT, 0, height, imm(1 << shift));
5684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    if (shift)
5694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                        MOV(GE, 0, height, reg_imm(height, LSL, shift));
5704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    RSB(GE, 0, height, height, imm(0));
5714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MUL(AL, 0, height, stride, height);
5724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                } else {
57396dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell                    // v has not been CLAMPed yet
5744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    CMP(AL, height, reg_imm(v, ASR, FRAC_BITS));
5754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(LE, 0, v, reg_imm(height, LSL, FRAC_BITS));
5764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(LE, 0, height, imm(0));
5774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    if (shift) {
5784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                        MOV(GT, 0, height, reg_imm(stride, LSL, shift));
5794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    } else {
5804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                        MOV(GT, 0, height, stride);
5814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    }
5824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(AL, 1, v, reg_imm(v, ASR, FRAC_BITS));
5834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(MI, 0, v, imm(0));
5844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(MI, 0, height, imm(0));
5854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                }
5864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_STORE(height, generated_vars.lb);
5874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
5884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            scratches.recycle(width);
5904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            scratches.recycle(height);
5914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // iterate texture coordinates...
5934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            comment("iterate s,t");
5944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int dsdx = scratches.obtain();
5954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int dtdx = scratches.obtain();
5964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(dsdx, generated_vars.texture[i].dsdx);
5974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(dtdx, generated_vars.texture[i].dtdx);
5984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, s.reg, s.reg, dsdx);
5994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, t.reg, t.reg, dtdx);
6004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if ((mOptLevel&1)==0) {
6014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_STORE(s.reg, generated_vars.texture[i].spill[0]);
6024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_STORE(t.reg, generated_vars.texture[i].spill[1]);
6034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                scratches.recycle(s.reg);
6044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                scratches.recycle(t.reg);
6054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
6064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            scratches.recycle(dsdx);
6074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            scratches.recycle(dtdx);
6084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // merge base & offset...
6104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            comment("merge base & offset");
6114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            texel.setTo(regs.obtain(), &tmu.format);
6124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            txPtr.setTo(texel.reg, tmu.bits);
6134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int stride = scratches.obtain();
6144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(stride,    generated_vars.texture[i].stride);
6154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(txPtr.reg, generated_vars.texture[i].data);
6164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            SMLABB(AL, u, v, stride, u);    // u+v*stride
6174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            base_offset(txPtr, txPtr, u);
6184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // load texel
6204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (!tmu.linear) {
6214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                comment("fetch texel");
6224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                load(txPtr, texel, 0);
6234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            } else {
6244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // recycle registers we don't need anymore
6254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                scratches.recycle(u);
6264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                scratches.recycle(v);
6274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                scratches.recycle(stride);
6284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                comment("fetch texel, bilinear");
6304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                switch (tmu.format.size) {
6314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                case 1:  filter8(parts, texel, tmu, U, V, txPtr, FRAC_BITS); break;
6324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                case 2: filter16(parts, texel, tmu, U, V, txPtr, FRAC_BITS); break;
6334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                case 3: filter24(parts, texel, tmu, U, V, txPtr, FRAC_BITS); break;
6344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                case 4: filter32(parts, texel, tmu, U, V, txPtr, FRAC_BITS); break;
6354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                }
6364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
6374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
6384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
6394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
6404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::build_iterate_texture_coordinates(
6424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const fragment_parts_t& parts)
6434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
6444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const bool multiTexture = mTextureMachine.activeUnits > 1;
6454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT; i++) {
6464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const texture_unit_t& tmu = mTextureMachine.tmu[i];
6474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (tmu.format_idx == 0)
6484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            continue;
6494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if ((tmu.swrap == GGL_NEEDS_WRAP_11) &&
6514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            (tmu.twrap == GGL_NEEDS_WRAP_11))
6524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        { // 1:1 textures
6534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            const pointer_t& txPtr = parts.coords[i].ptr;
6544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, txPtr.reg, txPtr.reg, imm(txPtr.size>>3));
6554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else {
6564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            Scratch scratches(registerFile());
6574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int s = parts.coords[i].s.reg;
6584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int t = parts.coords[i].t.reg;
6594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if ((mOptLevel&1)==0) {
6604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                s = scratches.obtain();
6614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                t = scratches.obtain();
6624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_LOAD(s, generated_vars.texture[i].spill[0]);
6634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_LOAD(t, generated_vars.texture[i].spill[1]);
6644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
6654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int dsdx = scratches.obtain();
6664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int dtdx = scratches.obtain();
6674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(dsdx, generated_vars.texture[i].dsdx);
6684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(dtdx, generated_vars.texture[i].dtdx);
6694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, s, s, dsdx);
6704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, t, t, dtdx);
6714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if ((mOptLevel&1)==0) {
6724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_STORE(s, generated_vars.texture[i].spill[0]);
6734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_STORE(t, generated_vars.texture[i].spill[1]);
6744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
6754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
6764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
6774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
6784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::filter8(
6804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const fragment_parts_t& parts,
6814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        pixel_t& texel, const texture_unit_t& tmu,
6824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int U, int V, pointer_t& txPtr,
6834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int FRAC_BITS)
6844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
6854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (tmu.format.components != GGL_ALPHA &&
6864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        tmu.format.components != GGL_LUMINANCE)
6874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    {
6884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // this is a packed format, and we don't support
6894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // linear filtering (it's probably RGB 332)
6904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // Should not happen with OpenGL|ES
6914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        LDRB(AL, texel.reg, txPtr.reg);
6924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
6934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
6944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // ------------------------
6964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // about ~22 cycles / pixel
6974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    Scratch scratches(registerFile());
6984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int pixel= scratches.obtain();
7004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int d    = scratches.obtain();
7014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int u    = scratches.obtain();
7024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int k    = scratches.obtain();
7034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int rt   = scratches.obtain();
7044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int lb   = scratches.obtain();
7054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // RB -> U * V
7074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    CONTEXT_LOAD(rt, generated_vars.rt);
7094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    CONTEXT_LOAD(lb, generated_vars.lb);
7104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int offset = pixel;
7124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ADD(AL, 0, offset, lb, rt);
7134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDRB(AL, pixel, txPtr.reg, reg_scale_pre(offset));
7144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMULBB(AL, u, U, V);
7154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMULBB(AL, d, pixel, u);
7164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    RSB(AL, 0, k, u, imm(1<<(FRAC_BITS*2)));
7174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // LB -> (1-U) * V
7194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    RSB(AL, 0, U, U, imm(1<<FRAC_BITS));
7204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDRB(AL, pixel, txPtr.reg, reg_scale_pre(lb));
7214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMULBB(AL, u, U, V);
7224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMLABB(AL, d, pixel, u, d);
7234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SUB(AL, 0, k, k, u);
7244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // LT -> (1-U)*(1-V)
7264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    RSB(AL, 0, V, V, imm(1<<FRAC_BITS));
7274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDRB(AL, pixel, txPtr.reg);
7284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMULBB(AL, u, U, V);
7294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMLABB(AL, d, pixel, u, d);
7304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // RT -> U*(1-V)
7324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDRB(AL, pixel, txPtr.reg, reg_scale_pre(rt));
7334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SUB(AL, 0, u, k, u);
7344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMLABB(AL, texel.reg, pixel, u, d);
7354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for (int i=0 ; i<4 ; i++) {
7374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (!texel.format.c[i].h) continue;
7384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        texel.format.c[i].h = FRAC_BITS*2+8;
7394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        texel.format.c[i].l = FRAC_BITS*2; // keeping 8 bits in enough
7404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
7414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    texel.format.size = 4;
7424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    texel.format.bitsPerPixel = 32;
7434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    texel.flags |= CLEAR_LO;
7444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
7454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::filter16(
7474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const fragment_parts_t& parts,
7484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        pixel_t& texel, const texture_unit_t& tmu,
7494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int U, int V, pointer_t& txPtr,
7504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int FRAC_BITS)
7514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
7524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // compute the mask
7534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // XXX: it would be nice if the mask below could be computed
7544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // automatically.
7554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    uint32_t mask = 0;
7564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int shift = 0;
7574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int prec = 0;
7584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    switch (tmu.format_idx) {
7594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        case GGL_PIXEL_FORMAT_RGB_565:
7604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // source: 00000ggg.ggg00000 | rrrrr000.000bbbbb
7614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // result: gggggggg.gggrrrrr | rrrrr0bb.bbbbbbbb
7624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            mask = 0x07E0F81F;
7634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            shift = 16;
7644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            prec = 5;
7654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            break;
7664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        case GGL_PIXEL_FORMAT_RGBA_4444:
7674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // 0000,1111,0000,1111 | 0000,1111,0000,1111
7684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            mask = 0x0F0F0F0F;
7694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            shift = 12;
7704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            prec = 4;
7714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            break;
7724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        case GGL_PIXEL_FORMAT_LA_88:
7734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // 0000,0000,1111,1111 | 0000,0000,1111,1111
7744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // AALL -> 00AA | 00LL
7754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            mask = 0x00FF00FF;
7764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            shift = 8;
7774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            prec = 8;
7784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            break;
7794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        default:
7804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // unsupported format, do something sensical...
7814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            LOGE("Unsupported 16-bits texture format (%d)", tmu.format_idx);
7824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            LDRH(AL, texel.reg, txPtr.reg);
7834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            return;
7844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
7854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const int adjust = FRAC_BITS*2 - prec;
7874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const int round  = 0;
7884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // update the texel format
7904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    texel.format.size = 4;
7914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    texel.format.bitsPerPixel = 32;
7924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    texel.flags |= CLEAR_HI|CLEAR_LO;
7934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for (int i=0 ; i<4 ; i++) {
7944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (!texel.format.c[i].h) continue;
7954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const uint32_t offset = (mask & tmu.format.mask(i)) ? 0 : shift;
7964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        texel.format.c[i].h = tmu.format.c[i].h + offset + prec;
7974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        texel.format.c[i].l = texel.format.c[i].h - (tmu.format.bits(i) + prec);
7984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
7994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // ------------------------
8014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // about ~40 cycles / pixel
8024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    Scratch scratches(registerFile());
8034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int pixel= scratches.obtain();
8054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int d    = scratches.obtain();
8064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int u    = scratches.obtain();
8074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int k    = scratches.obtain();
8084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // RB -> U * V
8104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int offset = pixel;
8114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    CONTEXT_LOAD(offset, generated_vars.rt);
8124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    CONTEXT_LOAD(u, generated_vars.lb);
8134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ADD(AL, 0, offset, offset, u);
8144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDRH(AL, pixel, txPtr.reg, reg_pre(offset));
8164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMULBB(AL, u, U, V);
8174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ORR(AL, 0, pixel, pixel, reg_imm(pixel, LSL, shift));
8184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    build_and_immediate(pixel, pixel, mask, 32);
8194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (adjust) {
8204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (round)
8214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, u, u, imm(1<<(adjust-1)));
8224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        MOV(AL, 0, u, reg_imm(u, LSR, adjust));
8234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
8244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MUL(AL, 0, d, pixel, u);
8254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    RSB(AL, 0, k, u, imm(1<<prec));
8264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // LB -> (1-U) * V
8284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    CONTEXT_LOAD(offset, generated_vars.lb);
8294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    RSB(AL, 0, U, U, imm(1<<FRAC_BITS));
8304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDRH(AL, pixel, txPtr.reg, reg_pre(offset));
8314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMULBB(AL, u, U, V);
8324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ORR(AL, 0, pixel, pixel, reg_imm(pixel, LSL, shift));
8334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    build_and_immediate(pixel, pixel, mask, 32);
8344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (adjust) {
8354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (round)
8364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, u, u, imm(1<<(adjust-1)));
8374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        MOV(AL, 0, u, reg_imm(u, LSR, adjust));
8384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
8394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MLA(AL, 0, d, pixel, u, d);
8404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SUB(AL, 0, k, k, u);
8414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // LT -> (1-U)*(1-V)
8434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    RSB(AL, 0, V, V, imm(1<<FRAC_BITS));
8444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDRH(AL, pixel, txPtr.reg);
8454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMULBB(AL, u, U, V);
8464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ORR(AL, 0, pixel, pixel, reg_imm(pixel, LSL, shift));
8474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    build_and_immediate(pixel, pixel, mask, 32);
8484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (adjust) {
8494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (round)
8504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, u, u, imm(1<<(adjust-1)));
8514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        MOV(AL, 0, u, reg_imm(u, LSR, adjust));
8524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
8534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MLA(AL, 0, d, pixel, u, d);
8544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // RT -> U*(1-V)
8564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    CONTEXT_LOAD(offset, generated_vars.rt);
8574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDRH(AL, pixel, txPtr.reg, reg_pre(offset));
8584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SUB(AL, 0, u, k, u);
8594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ORR(AL, 0, pixel, pixel, reg_imm(pixel, LSL, shift));
8604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    build_and_immediate(pixel, pixel, mask, 32);
8614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MLA(AL, 0, texel.reg, pixel, u, d);
8624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
8634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::filter24(
8654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const fragment_parts_t& parts,
8664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        pixel_t& texel, const texture_unit_t& tmu,
8674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int U, int V, pointer_t& txPtr,
8684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int FRAC_BITS)
8694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
8704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // not supported yet (currently disabled)
8714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    load(txPtr, texel, 0);
8724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
8734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
87496dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell#if __ARM_ARCH__ >= 6
87596dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell// ARMv6 version, using UXTB16, and scheduled for Cortex-A8 pipeline
87696dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewellvoid GGLAssembler::filter32(
87796dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        const fragment_parts_t& parts,
87896dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        pixel_t& texel, const texture_unit_t& tmu,
87996dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        int U, int V, pointer_t& txPtr,
88096dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        int FRAC_BITS)
88196dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell{
88296dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    const int adjust = FRAC_BITS*2 - 8;
88396dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    const int round  = 0;
88496dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    const int prescale = 16 - adjust;
88596dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell
88696dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    Scratch scratches(registerFile());
88796dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell
88896dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    int pixel= scratches.obtain();
88996dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    int dh   = scratches.obtain();
89096dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    int u    = scratches.obtain();
89196dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    int k    = scratches.obtain();
89296dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell
89396dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    int temp = scratches.obtain();
89496dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    int dl   = scratches.obtain();
89596dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell
89696dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    int offsetrt = scratches.obtain();
89796dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    int offsetlb = scratches.obtain();
89896dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell
89996dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    int pixellb = offsetlb;
90096dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell
90196dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    // RB -> U * V
90296dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    CONTEXT_LOAD(offsetrt, generated_vars.rt);
90396dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    CONTEXT_LOAD(offsetlb, generated_vars.lb);
90496dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    if(!round) {
90596dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        MOV(AL, 0, U, reg_imm(U, LSL, prescale));
90696dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    }
90796dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    ADD(AL, 0, u, offsetrt, offsetlb);
90896dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell
90996dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    LDR(AL, pixel, txPtr.reg, reg_scale_pre(u));
91096dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    if (round) {
91196dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        SMULBB(AL, u, U, V);
91296dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        RSB(AL, 0, U, U, imm(1<<FRAC_BITS));
91396dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    } else {
91496dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        SMULWB(AL, u, U, V);
91596dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        RSB(AL, 0, U, U, imm(1<<(FRAC_BITS+prescale)));
91696dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    }
91796dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    UXTB16(AL, temp, pixel, 0);
91896dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    if (round) {
91996dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        ADD(AL, 0, u, u, imm(1<<(adjust-1)));
92096dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        MOV(AL, 0, u, reg_imm(u, LSR, adjust));
92196dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    }
92296dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    LDR(AL, pixellb, txPtr.reg, reg_scale_pre(offsetlb));
92396dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    MUL(AL, 0, dh, temp, u);
92496dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    UXTB16(AL, temp, pixel, 8);
92596dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    MUL(AL, 0, dl, temp, u);
92696dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    RSB(AL, 0, k, u, imm(0x100));
92796dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell
92896dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    // LB -> (1-U) * V
92996dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    if (round) {
93096dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        SMULBB(AL, u, U, V);
93196dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    } else {
93296dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        SMULWB(AL, u, U, V);
93396dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    }
93496dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    UXTB16(AL, temp, pixellb, 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    MLA(AL, 0, dh, temp, u, dh);
94096dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    UXTB16(AL, temp, pixellb, 8);
94196dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    MLA(AL, 0, dl, temp, u, dl);
94296dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    SUB(AL, 0, k, k, u);
94396dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell
94496dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    // LT -> (1-U)*(1-V)
94596dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    RSB(AL, 0, V, V, imm(1<<FRAC_BITS));
94696dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    LDR(AL, pixel, txPtr.reg);
94796dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    if (round) {
94896dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        SMULBB(AL, u, U, V);
94996dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    } else {
95096dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        SMULWB(AL, u, U, V);
95196dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    }
95296dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    UXTB16(AL, temp, pixel, 0);
95396dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    if (round) {
95496dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        ADD(AL, 0, u, u, imm(1<<(adjust-1)));
95596dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell        MOV(AL, 0, u, reg_imm(u, LSR, adjust));
95696dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    }
95796dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    MLA(AL, 0, dh, temp, u, dh);
95896dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    UXTB16(AL, temp, pixel, 8);
95996dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    MLA(AL, 0, dl, temp, u, dl);
96096dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell
96196dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    // RT -> U*(1-V)
96296dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    LDR(AL, pixel, txPtr.reg, reg_scale_pre(offsetrt));
96396dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    SUB(AL, 0, u, k, u);
96496dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    UXTB16(AL, temp, pixel, 0);
96596dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    MLA(AL, 0, dh, temp, u, dh);
96696dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    UXTB16(AL, temp, pixel, 8);
96796dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    MLA(AL, 0, dl, temp, u, dl);
96896dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell
96996dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    UXTB16(AL, dh, dh, 8);
97096dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    UXTB16(AL, dl, dl, 8);
97196dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell    ORR(AL, 0, texel.reg, dh, reg_imm(dl, LSL, 8));
97296dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell}
97396dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell#else
9744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::filter32(
9754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const fragment_parts_t& parts,
9764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        pixel_t& texel, const texture_unit_t& tmu,
9774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int U, int V, pointer_t& txPtr,
9784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int FRAC_BITS)
9794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
9804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const int adjust = FRAC_BITS*2 - 8;
9814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const int round  = 0;
9824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // ------------------------
9844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // about ~38 cycles / pixel
9854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    Scratch scratches(registerFile());
9864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int pixel= scratches.obtain();
9884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int dh   = scratches.obtain();
9894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int u    = scratches.obtain();
9904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int k    = scratches.obtain();
9914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int temp = scratches.obtain();
9934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int dl   = scratches.obtain();
9944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int mask = scratches.obtain();
9954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MOV(AL, 0, mask, imm(0xFF));
9974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ORR(AL, 0, mask, mask, imm(0xFF0000));
9984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // RB -> U * V
10004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int offset = pixel;
10014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    CONTEXT_LOAD(offset, generated_vars.rt);
10024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    CONTEXT_LOAD(u, generated_vars.lb);
10034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ADD(AL, 0, offset, offset, u);
10044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDR(AL, pixel, txPtr.reg, reg_scale_pre(offset));
10064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMULBB(AL, u, U, V);
10074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AND(AL, 0, temp, mask, pixel);
10084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (adjust) {
10094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (round)
10104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, u, u, imm(1<<(adjust-1)));
10114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        MOV(AL, 0, u, reg_imm(u, LSR, adjust));
10124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
10134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MUL(AL, 0, dh, temp, u);
10144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AND(AL, 0, temp, mask, reg_imm(pixel, LSR, 8));
10154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MUL(AL, 0, dl, temp, u);
10164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    RSB(AL, 0, k, u, imm(0x100));
10174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // LB -> (1-U) * V
10194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    CONTEXT_LOAD(offset, generated_vars.lb);
10204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    RSB(AL, 0, U, U, imm(1<<FRAC_BITS));
10214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDR(AL, pixel, txPtr.reg, reg_scale_pre(offset));
10224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMULBB(AL, u, U, V);
10234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AND(AL, 0, temp, mask, pixel);
10244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (adjust) {
10254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (round)
10264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, u, u, imm(1<<(adjust-1)));
10274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        MOV(AL, 0, u, reg_imm(u, LSR, adjust));
10284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
10294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MLA(AL, 0, dh, temp, u, dh);
10304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AND(AL, 0, temp, mask, reg_imm(pixel, LSR, 8));
10314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MLA(AL, 0, dl, temp, u, dl);
10324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SUB(AL, 0, k, k, u);
10334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // LT -> (1-U)*(1-V)
10354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    RSB(AL, 0, V, V, imm(1<<FRAC_BITS));
10364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDR(AL, pixel, txPtr.reg);
10374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMULBB(AL, u, U, V);
10384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AND(AL, 0, temp, mask, pixel);
10394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (adjust) {
10404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (round)
10414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, u, u, imm(1<<(adjust-1)));
10424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        MOV(AL, 0, u, reg_imm(u, LSR, adjust));
10434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
10444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MLA(AL, 0, dh, temp, u, dh);
10454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AND(AL, 0, temp, mask, reg_imm(pixel, LSR, 8));
10464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MLA(AL, 0, dl, temp, u, dl);
10474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // RT -> U*(1-V)
10494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    CONTEXT_LOAD(offset, generated_vars.rt);
10504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDR(AL, pixel, txPtr.reg, reg_scale_pre(offset));
10514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SUB(AL, 0, u, k, u);
10524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AND(AL, 0, temp, mask, pixel);
10534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MLA(AL, 0, dh, temp, u, dh);
10544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AND(AL, 0, temp, mask, reg_imm(pixel, LSR, 8));
10554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MLA(AL, 0, dl, temp, u, dl);
10564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AND(AL, 0, dh, mask, reg_imm(dh, LSR, 8));
10584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AND(AL, 0, dl, dl, reg_imm(mask, LSL, 8));
10594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ORR(AL, 0, texel.reg, dh, dl);
10604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
106196dbb4fc58fe2dcf4390e073dbb42cc77ef2f0b5Martyn Capewell#endif
10624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::build_texture_environment(
10644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        component_t& fragment,
10654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const fragment_parts_t& parts,
10664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int component,
10674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        Scratch& regs)
10684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
10694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const uint32_t component_mask = 1<<component;
10704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const bool multiTexture = mTextureMachine.activeUnits > 1;
10714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
10724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        texture_unit_t& tmu = mTextureMachine.tmu[i];
10734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (tmu.mask & component_mask) {
10754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // replace or modulate with this texture
10764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if ((tmu.replaced & component_mask) == 0) {
10774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // not replaced by a later tmu...
10784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                Scratch scratches(registerFile());
10804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                pixel_t texel(parts.texel[i]);
10814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (multiTexture &&
10824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    tmu.swrap == GGL_NEEDS_WRAP_11 &&
10834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    tmu.twrap == GGL_NEEDS_WRAP_11)
10844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                {
10854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    texel.reg = scratches.obtain();
10864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    texel.flags |= CORRUPTIBLE;
10874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    comment("fetch texel (multitexture 1:1)");
10884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    load(parts.coords[i].ptr, texel, WRITE_BACK);
10894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                 }
10904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                component_t incoming(fragment);
10924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                modify(fragment, regs);
10934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                switch (tmu.env) {
10954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                case GGL_REPLACE:
10964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    extract(fragment, texel, component);
10974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    break;
10984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                case GGL_MODULATE:
10994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    modulate(fragment, incoming, texel, component);
11004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    break;
11014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                case GGL_DECAL:
11024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    decal(fragment, incoming, texel, component);
11034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    break;
11044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                case GGL_BLEND:
11054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    blend(fragment, incoming, texel, component, i);
11064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    break;
110735237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project                case GGL_ADD:
110835237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project                    add(fragment, incoming, texel, component);
110935237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project                    break;
11104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                }
11114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
11124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
11134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
11144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
11154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
11164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project// ---------------------------------------------------------------------------
11174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
11184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::wrapping(
11194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int d,
11204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int coord, int size,
11214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int tx_wrap, int tx_linear)
11224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
11234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // notes:
11244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // if tx_linear is set, we need 4 extra bits of precision on the result
11254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // SMULL/UMULL is 3 cycles
11264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    Scratch scratches(registerFile());
11274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int c = coord;
11284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (tx_wrap == GGL_NEEDS_WRAP_REPEAT) {
11294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // UMULL takes 4 cycles (interlocked), and we can get away with
11304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // 2 cycles using SMULWB, but we're loosing 16 bits of precision
11314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // out of 32 (this is not a problem because the iterator keeps
11324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // its full precision)
11334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // UMULL(AL, 0, size, d, c, size);
11344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // note: we can't use SMULTB because it's signed.
11354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        MOV(AL, 0, d, reg_imm(c, LSR, 16-tx_linear));
11364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SMULWB(AL, d, d, size);
11374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else if (tx_wrap == GGL_NEEDS_WRAP_CLAMP_TO_EDGE) {
11384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (tx_linear) {
11394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // 1 cycle
11404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            MOV(AL, 0, d, reg_imm(coord, ASR, 16-tx_linear));
11414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else {
11424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // 4 cycles (common case)
11434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            MOV(AL, 0, d, reg_imm(coord, ASR, 16));
11444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            BIC(AL, 0, d, d, reg_imm(d, ASR, 31));
11454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CMP(AL, d, size);
11464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            SUB(GE, 0, d, size, imm(1));
11474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
11484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
11494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
11504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
11514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project// ---------------------------------------------------------------------------
11524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
11534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::modulate(
11544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        component_t& dest,
11554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const component_t& incoming,
11564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const pixel_t& incomingTexel, int component)
11574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
11584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    Scratch locals(registerFile());
11594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    integer_t texel(locals.obtain(), 32, CORRUPTIBLE);
11604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    extract(texel, incomingTexel, component);
11614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
11624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const int Nt = texel.size();
11634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // Nt should always be less than 10 bits because it comes
11644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // from the TMU.
11654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
11664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int Ni = incoming.size();
11674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // Ni could be big because it comes from previous MODULATEs
11684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
11694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (Nt == 1) {
11704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // texel acts as a bit-mask
11714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // dest = incoming & ((texel << incoming.h)-texel)
11724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        RSB(AL, 0, dest.reg, texel.reg, reg_imm(texel.reg, LSL, incoming.h));
11734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        AND(AL, 0, dest.reg, dest.reg, incoming.reg);
11744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        dest.l = incoming.l;
11754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        dest.h = incoming.h;
11764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        dest.flags |= (incoming.flags & CLEAR_LO);
11774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else if (Ni == 1) {
11784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        MOV(AL, 0, dest.reg, reg_imm(incoming.reg, LSL, 31-incoming.h));
11794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        AND(AL, 0, dest.reg, texel.reg, reg_imm(dest.reg, ASR, 31));
11804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        dest.l = 0;
11814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        dest.h = Nt;
11824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
11834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int inReg = incoming.reg;
11844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int shift = incoming.l;
11854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if ((Nt + Ni) > 32) {
11864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // we will overflow, reduce the precision of Ni to 8 bits
11874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // (Note Nt cannot be more than 10 bits which happens with
11884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // 565 textures and GGL_LINEAR)
11894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            shift += Ni-8;
11904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            Ni = 8;
11914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
11924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
11934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // modulate by the component with the lowest precision
11944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (Nt >= Ni) {
11954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (shift) {
11964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // XXX: we should be able to avoid this shift
11974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // when shift==16 && Nt<16 && Ni<16, in which
11984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // we could use SMULBT below.
11994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                MOV(AL, 0, dest.reg, reg_imm(inReg, LSR, shift));
12004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                inReg = dest.reg;
12014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                shift = 0;
12024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
12034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // operation:           (Cf*Ct)/((1<<Ni)-1)
12044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // approximated with:   Cf*(Ct + Ct>>(Ni-1))>>Ni
12054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // this operation doesn't change texel's size
12064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, dest.reg, inReg, reg_imm(inReg, LSR, Ni-1));
12074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (Nt<16 && Ni<16) SMULBB(AL, dest.reg, texel.reg, dest.reg);
12084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            else                MUL(AL, 0, dest.reg, texel.reg, dest.reg);
12094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            dest.l = Ni;
12104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            dest.h = Nt + Ni;
12114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else {
12124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (shift && (shift != 16)) {
12134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // if shift==16, we can use 16-bits mul instructions later
12144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                MOV(AL, 0, dest.reg, reg_imm(inReg, LSR, shift));
12154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                inReg = dest.reg;
12164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                shift = 0;
12174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
12184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // operation:           (Cf*Ct)/((1<<Nt)-1)
12194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // approximated with:   Ct*(Cf + Cf>>(Nt-1))>>Nt
12204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // this operation doesn't change incoming's size
12214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            Scratch scratches(registerFile());
12224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int t = (texel.flags & CORRUPTIBLE) ? texel.reg : dest.reg;
12234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (t == inReg)
12244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                t = scratches.obtain();
12254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, t, texel.reg, reg_imm(texel.reg, LSR, Nt-1));
12264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (Nt<16 && Ni<16) {
12274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (shift==16)  SMULBT(AL, dest.reg, t, inReg);
12284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                else            SMULBB(AL, dest.reg, t, inReg);
12294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            } else              MUL(AL, 0, dest.reg, t, inReg);
12304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            dest.l = Nt;
12314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            dest.h = Nt + Ni;
12324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
12334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
12344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // low bits are not valid
12354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        dest.flags |= CLEAR_LO;
12364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
12374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // no need to keep more than 8 bits/component
12384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (dest.size() > 8)
12394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            dest.l = dest.h-8;
12404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
12414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
12424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
12434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::decal(
12444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        component_t& dest,
12454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const component_t& incoming,
12464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const pixel_t& incomingTexel, int component)
12474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
12484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // RGBA:
12494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // Cv = Cf*(1 - At) + Ct*At = Cf + (Ct - Cf)*At
12504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // Av = Af
12514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    Scratch locals(registerFile());
12524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    integer_t texel(locals.obtain(), 32, CORRUPTIBLE);
12534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    integer_t factor(locals.obtain(), 32, CORRUPTIBLE);
12544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    extract(texel, incomingTexel, component);
12554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    extract(factor, incomingTexel, GGLFormat::ALPHA);
12564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
12574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // no need to keep more than 8-bits for decal
12584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int Ni = incoming.size();
12594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int shift = incoming.l;
12604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (Ni > 8) {
12614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        shift += Ni-8;
12624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        Ni = 8;
12634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
12644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    integer_t incomingNorm(incoming.reg, Ni, incoming.flags);
12654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (shift) {
12664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        MOV(AL, 0, dest.reg, reg_imm(incomingNorm.reg, LSR, shift));
12674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        incomingNorm.reg = dest.reg;
12684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        incomingNorm.flags |= CORRUPTIBLE;
12694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
12704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ADD(AL, 0, factor.reg, factor.reg, reg_imm(factor.reg, LSR, factor.s-1));
12714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    build_blendOneMinusFF(dest, factor, incomingNorm, texel);
12724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
12734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
12744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::blend(
12754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        component_t& dest,
12764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const component_t& incoming,
12774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const pixel_t& incomingTexel, int component, int tmu)
12784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
12794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // RGBA:
12804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // Cv = (1 - Ct)*Cf + Ct*Cc = Cf + (Cc - Cf)*Ct
12814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // Av = At*Af
12824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
12834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (component == GGLFormat::ALPHA) {
12844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        modulate(dest, incoming, incomingTexel, component);
12854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
12864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
12874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
12884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    Scratch locals(registerFile());
12894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    integer_t color(locals.obtain(), 8, CORRUPTIBLE);
12904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    integer_t factor(locals.obtain(), 32, CORRUPTIBLE);
12914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDRB(AL, color.reg, mBuilderContext.Rctx,
12924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            immed12_pre(GGL_OFFSETOF(state.texture[tmu].env_color[component])));
12934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    extract(factor, incomingTexel, component);
12944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
12954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // no need to keep more than 8-bits for blend
12964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int Ni = incoming.size();
12974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int shift = incoming.l;
12984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (Ni > 8) {
12994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        shift += Ni-8;
13004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        Ni = 8;
13014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
13024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    integer_t incomingNorm(incoming.reg, Ni, incoming.flags);
13034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (shift) {
13044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        MOV(AL, 0, dest.reg, reg_imm(incomingNorm.reg, LSR, shift));
13054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        incomingNorm.reg = dest.reg;
13064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        incomingNorm.flags |= CORRUPTIBLE;
13074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
13084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ADD(AL, 0, factor.reg, factor.reg, reg_imm(factor.reg, LSR, factor.s-1));
13094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    build_blendOneMinusFF(dest, factor, incomingNorm, color);
13104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
13114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
131235237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Projectvoid GGLAssembler::add(
131335237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        component_t& dest,
131435237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        const component_t& incoming,
131535237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        const pixel_t& incomingTexel, int component)
131635237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project{
131735237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    // RGBA:
131835237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    // Cv = Cf + Ct;
131935237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    Scratch locals(registerFile());
132035237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project
132135237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    component_t incomingTemp(incoming);
132235237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project
132335237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    // use "dest" as a temporary for extracting the texel, unless "dest"
132435237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    // overlaps "incoming".
132535237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    integer_t texel(dest.reg, 32, CORRUPTIBLE);
132635237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    if (dest.reg == incomingTemp.reg)
132735237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        texel.reg = locals.obtain();
132835237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    extract(texel, incomingTexel, component);
132935237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project
133035237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    if (texel.s < incomingTemp.size()) {
133135237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        expand(texel, texel, incomingTemp.size());
133235237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    } else if (texel.s > incomingTemp.size()) {
133335237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        if (incomingTemp.flags & CORRUPTIBLE) {
133435237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project            expand(incomingTemp, incomingTemp, texel.s);
133535237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        } else {
133635237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project            incomingTemp.reg = locals.obtain();
133735237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project            expand(incomingTemp, incoming, texel.s);
133835237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        }
133935237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    }
134035237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project
134135237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    if (incomingTemp.l) {
134235237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        ADD(AL, 0, dest.reg, texel.reg,
134335237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project                reg_imm(incomingTemp.reg, LSR, incomingTemp.l));
134435237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    } else {
134535237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        ADD(AL, 0, dest.reg, texel.reg, incomingTemp.reg);
134635237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    }
134735237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    dest.l = 0;
134835237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    dest.h = texel.size();
134935237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    component_sat(dest);
135035237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project}
135135237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project
13524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project// ----------------------------------------------------------------------------
13534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
13544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}; // namespace android
13554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1356