texturing.cpp revision 35237d135807af84bf9b0e5b8d7f8633e58db6f5
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
284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectnamespace android {
304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project// ---------------------------------------------------------------------------
324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project// iterators are initialized like this:
344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project// (intToFixedCenter(x) * dx)>>16 + x0
354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project// ((x<<16 + 0x8000) * dx)>>16 + x0
364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project// ((x<<16)*dx + (0x8000*dx))>>16 + x0
374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project// ( (x*dx) + dx>>1 ) + x0
384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project// (x*dx) + (dx>>1 + x0)
394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::init_iterated_color(fragment_parts_t& parts, const reg_t& x)
414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    context_t const* c = mBuilderContext.c;
434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const needs_t& needs = mBuilderContext.needs;
444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (mSmooth) {
464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // NOTE: we could take this case in the mDithering + !mSmooth case,
474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // but this would use up to 4 more registers for the color components
484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // for only a little added quality.
494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // Currently, this causes the system to run out of registers in
504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // some case (see issue #719496)
514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        comment("compute initial iterated color (smooth and/or dither case)");
534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        parts.iterated_packed = 0;
554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        parts.packed = 0;
564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // 0x1: color component
584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // 0x2: iterators
594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const int optReload = mOptLevel >> 1;
604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (optReload >= 3)         parts.reload = 0; // reload nothing
614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        else if (optReload == 2)    parts.reload = 2; // reload iterators
624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        else if (optReload == 1)    parts.reload = 1; // reload colors
634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        else if (optReload <= 0)    parts.reload = 3; // reload both
644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (!mSmooth) {
664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // we're not smoothing (just dithering), we never have to
674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // reload the iterators
684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            parts.reload &= ~2;
694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        Scratch scratches(registerFile());
724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const int t0 = (parts.reload & 1) ? scratches.obtain() : 0;
734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const int t1 = (parts.reload & 2) ? scratches.obtain() : 0;
744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        for (int i=0 ; i<4 ; i++) {
754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (!mInfo[i].iterated)
764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                continue;
774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // this component exists in the destination and is not replaced
794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // by a texture unit.
804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            const int c = (parts.reload & 1) ? t0 : obtainReg();
814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (i==0) CONTEXT_LOAD(c, iterators.ydady);
824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (i==1) CONTEXT_LOAD(c, iterators.ydrdy);
834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (i==2) CONTEXT_LOAD(c, iterators.ydgdy);
844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (i==3) CONTEXT_LOAD(c, iterators.ydbdy);
854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            parts.argb[i].reg = c;
864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (mInfo[i].smooth) {
884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                parts.argb_dx[i].reg = (parts.reload & 2) ? t1 : obtainReg();
894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                const int dvdx = parts.argb_dx[i].reg;
904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_LOAD(dvdx, generated_vars.argb[i].dx);
914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                MLA(AL, 0, c, x.reg, dvdx, c);
924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // adjust the color iterator to make sure it won't overflow
944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (!mAA) {
954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // this is not needed when we're using anti-aliasing
964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // because we will (have to) clamp the components
974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // anyway.
984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    int end = scratches.obtain();
994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(AL, 0, end, reg_imm(parts.count.reg, LSR, 16));
1004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MLA(AL, 1, end, dvdx, end, c);
1014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    SUB(MI, 0, c, c, end);
1024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    BIC(AL, 0, c, c, reg_imm(c, ASR, 31));
1034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    scratches.recycle(end);
1044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                }
1054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
1064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (parts.reload & 1) {
1084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_STORE(c, generated_vars.argb[i].c);
1094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
1104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
1114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
1124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // We're not smoothed, so we can
1134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // just use a packed version of the color and extract the
1144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // components as needed (or not at all if we don't blend)
1154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // figure out if we need the iterated color
1174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int load = 0;
1184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        for (int i=0 ; i<4 ; i++) {
1194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            component_info_t& info = mInfo[i];
1204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if ((info.inDest || info.needed) && !info.replaced)
1214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                load |= 1;
1224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
1234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        parts.iterated_packed = 1;
1254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        parts.packed = (!mTextureMachine.mask && !mBlending
1264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                && !mFog && !mDithering);
1274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        parts.reload = 0;
1284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (load || parts.packed) {
1294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (mBlending || mDithering || mInfo[GGLFormat::ALPHA].needed) {
1304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                comment("load initial iterated color (8888 packed)");
1314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                parts.iterated.setTo(obtainReg(),
1324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                        &(c->formats[GGL_PIXEL_FORMAT_RGBA_8888]));
1334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_LOAD(parts.iterated.reg, packed8888);
1344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            } else {
1354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                comment("load initial iterated color (dest format packed)");
1364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                parts.iterated.setTo(obtainReg(), &mCbFormat);
1384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // pre-mask the iterated color
1404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                const int bits = parts.iterated.size();
1414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                const uint32_t size = ((bits>=32) ? 0 : (1LU << bits)) - 1;
1424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                uint32_t mask = 0;
1434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (mMasking) {
1444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    for (int i=0 ; i<4 ; i++) {
1454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                        const int component_mask = 1<<i;
1464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                        const int h = parts.iterated.format.c[i].h;
1474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                        const int l = parts.iterated.format.c[i].l;
1484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                        if (h && (!(mMasking & component_mask))) {
1494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                            mask |= ((1<<(h-l))-1) << l;
1504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                        }
1514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    }
1524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                }
1534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (mMasking && ((mask & size)==0)) {
1554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // none of the components are present in the mask
1564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                } else {
1574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    CONTEXT_LOAD(parts.iterated.reg, packed);
1584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    if (mCbFormat.size == 1) {
1594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                        AND(AL, 0, parts.iterated.reg,
1604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                parts.iterated.reg, imm(0xFF));
1614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    } else if (mCbFormat.size == 2) {
1624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                        MOV(AL, 0, parts.iterated.reg,
1634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                reg_imm(parts.iterated.reg, LSR, 16));
1644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    }
1654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                }
1664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // pre-mask the iterated color
1684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (mMasking) {
1694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    build_and_immediate(parts.iterated.reg, parts.iterated.reg,
1704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                            mask, bits);
1714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                }
1724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
1734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
1744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
1764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::build_iterated_color(
1784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        component_t& fragment,
1794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const fragment_parts_t& parts,
1804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int component,
1814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        Scratch& regs)
1824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
1834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    fragment.setTo( regs.obtain(), 0, 32, CORRUPTIBLE);
1844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (!mInfo[component].iterated)
1864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
1874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (parts.iterated_packed) {
1894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // iterated colors are packed, extract the one we need
1904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        extract(fragment, parts.iterated, component);
1914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
1924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fragment.h = GGL_COLOR_BITS;
1934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fragment.l = GGL_COLOR_BITS - 8;
1944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fragment.flags |= CLEAR_LO;
1954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // iterated colors are held in their own register,
1964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // (smooth and/or dithering case)
1974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (parts.reload==3) {
1984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // this implies mSmooth
1994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            Scratch scratches(registerFile());
2004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int dx = scratches.obtain();
2014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(fragment.reg, generated_vars.argb[component].c);
2024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(dx, generated_vars.argb[component].dx);
2034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, dx, fragment.reg, dx);
2044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_STORE(dx, generated_vars.argb[component].c);
2054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (parts.reload & 1) {
2064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(fragment.reg, generated_vars.argb[component].c);
2074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else {
2084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // we don't reload, so simply rename the register and mark as
2094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // non CORRUPTIBLE so that the texture env or blending code
2104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // won't modify this (renamed) register
2114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            regs.recycle(fragment.reg);
2124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            fragment.reg = parts.argb[component].reg;
2134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            fragment.flags &= ~CORRUPTIBLE;
2144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (mInfo[component].smooth && mAA) {
2164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // when using smooth shading AND anti-aliasing, we need to clamp
2174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // the iterators because there is always an extra pixel on the
2184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // edges, which most of the time will cause an overflow
2194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // (since technically its outside of the domain).
2204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            BIC(AL, 0, fragment.reg, fragment.reg,
2214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    reg_imm(fragment.reg, ASR, 31));
2224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            component_sat(fragment);
2234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
2254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
2264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project// ---------------------------------------------------------------------------
2284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::decodeLogicOpNeeds(const needs_t& needs)
2304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
2314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // gather some informations about the components we need to process...
2324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const int opcode = GGL_READ_NEEDS(LOGIC_OP, needs.n) | GGL_CLEAR;
2334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    switch(opcode) {
2344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case GGL_COPY:
2354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        mLogicOp = 0;
2364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        break;
2374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case GGL_CLEAR:
2384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case GGL_SET:
2394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        mLogicOp = LOGIC_OP;
2404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        break;
2414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case GGL_AND:
2424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case GGL_AND_REVERSE:
2434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case GGL_AND_INVERTED:
2444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case GGL_XOR:
2454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case GGL_OR:
2464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case GGL_NOR:
2474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case GGL_EQUIV:
2484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case GGL_OR_REVERSE:
2494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case GGL_OR_INVERTED:
2504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case GGL_NAND:
2514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        mLogicOp = LOGIC_OP|LOGIC_OP_SRC|LOGIC_OP_DST;
2524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        break;
2534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case GGL_NOOP:
2544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case GGL_INVERT:
2554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        mLogicOp = LOGIC_OP|LOGIC_OP_DST;
2564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        break;
2574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    case GGL_COPY_INVERTED:
2584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        mLogicOp = LOGIC_OP|LOGIC_OP_SRC;
2594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        break;
2604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    };
2614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
2624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::decodeTMUNeeds(const needs_t& needs, context_t const* c)
2644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
2654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    uint8_t replaced=0;
2664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mTextureMachine.mask = 0;
2674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mTextureMachine.activeUnits = 0;
2684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for (int i=GGL_TEXTURE_UNIT_COUNT-1 ; i>=0 ; i--) {
2694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        texture_unit_t& tmu = mTextureMachine.tmu[i];
2704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (replaced == 0xF) {
2714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // all components are replaced, skip this TMU.
2724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            tmu.format_idx = 0;
2734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            tmu.mask = 0;
2744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            tmu.replaced = replaced;
2754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            continue;
2764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        tmu.format_idx = GGL_READ_NEEDS(T_FORMAT, needs.t[i]);
2784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        tmu.format = c->formats[tmu.format_idx];
2794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        tmu.bits = tmu.format.size*8;
2804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        tmu.swrap = GGL_READ_NEEDS(T_S_WRAP, needs.t[i]);
2814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        tmu.twrap = GGL_READ_NEEDS(T_T_WRAP, needs.t[i]);
2824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        tmu.env = ggl_needs_to_env(GGL_READ_NEEDS(T_ENV, needs.t[i]));
2834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        tmu.pot = GGL_READ_NEEDS(T_POT, needs.t[i]);
2844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        tmu.linear = GGL_READ_NEEDS(T_LINEAR, needs.t[i])
2854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                && tmu.format.size!=3; // XXX: only 8, 16 and 32 modes for now
2864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // 5551 linear filtering is not supported
2884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (tmu.format_idx == GGL_PIXEL_FORMAT_RGBA_5551)
2894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            tmu.linear = 0;
2904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        tmu.mask = 0;
2924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        tmu.replaced = replaced;
2934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (tmu.format_idx) {
2954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            mTextureMachine.activeUnits++;
2964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (tmu.format.c[0].h)    tmu.mask |= 0x1;
2974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (tmu.format.c[1].h)    tmu.mask |= 0x2;
2984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (tmu.format.c[2].h)    tmu.mask |= 0x4;
2994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (tmu.format.c[3].h)    tmu.mask |= 0x8;
3004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (tmu.env == GGL_REPLACE) {
3014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                replaced |= tmu.mask;
3024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            } else if (tmu.env == GGL_DECAL) {
3034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (!tmu.format.c[GGLFormat::ALPHA].h) {
3044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // if we don't have alpha, decal does nothing
3054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    tmu.mask = 0;
3064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                } else {
3074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // decal always ignores At
3084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    tmu.mask &= ~(1<<GGLFormat::ALPHA);
3094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                }
3104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
3114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
3124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        mTextureMachine.mask |= tmu.mask;
3134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        //printf("%d: mask=%08lx, replaced=%08lx\n",
3144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        //    i, int(tmu.mask), int(tmu.replaced));
3154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mTextureMachine.replaced = replaced;
3174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mTextureMachine.directTexture = 0;
3184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    //printf("replaced=%08lx\n", mTextureMachine.replaced);
3194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
3204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::init_textures(
3234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        tex_coord_t* coords,
3244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const reg_t& x, const reg_t& y)
3254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
3264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    context_t const* c = mBuilderContext.c;
3274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const needs_t& needs = mBuilderContext.needs;
3284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int Rctx = mBuilderContext.Rctx;
3294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int Rx = x.reg;
3304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int Ry = y.reg;
3314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (mTextureMachine.mask) {
3334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        comment("compute texture coordinates");
3344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // init texture coordinates for each tmu
3374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const int cb_format_idx = GGL_READ_NEEDS(CB_FORMAT, needs.n);
3384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const bool multiTexture = mTextureMachine.activeUnits > 1;
3394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT; i++) {
3404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const texture_unit_t& tmu = mTextureMachine.tmu[i];
3414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (tmu.format_idx == 0)
3424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            continue;
3434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if ((tmu.swrap == GGL_NEEDS_WRAP_11) &&
3444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            (tmu.twrap == GGL_NEEDS_WRAP_11))
3454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        {
3464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // 1:1 texture
3474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            pointer_t& txPtr = coords[i].ptr;
3484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            txPtr.setTo(obtainReg(), tmu.bits);
3494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(txPtr.reg, state.texture[i].iterators.ydsdy);
3504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, Rx, Rx, reg_imm(txPtr.reg, ASR, 16));    // x += (s>>16)
3514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(txPtr.reg, state.texture[i].iterators.ydtdy);
3524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, Ry, Ry, reg_imm(txPtr.reg, ASR, 16));    // y += (t>>16)
3534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // merge base & offset
3544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(txPtr.reg, generated_vars.texture[i].stride);
3554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            SMLABB(AL, Rx, Ry, txPtr.reg, Rx);               // x+y*stride
3564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(txPtr.reg, generated_vars.texture[i].data);
3574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            base_offset(txPtr, txPtr, Rx);
3584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else {
3594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            Scratch scratches(registerFile());
3604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            reg_t& s = coords[i].s;
3614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            reg_t& t = coords[i].t;
3624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // s = (x * dsdx)>>16 + ydsdy
3634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // s = (x * dsdx)>>16 + (y*dsdy)>>16 + s0
3644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // t = (x * dtdx)>>16 + ydtdy
3654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // t = (x * dtdx)>>16 + (y*dtdy)>>16 + t0
3664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            s.setTo(obtainReg());
3674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            t.setTo(obtainReg());
3684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            const int need_w = GGL_READ_NEEDS(W, needs.n);
3694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (need_w) {
3704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_LOAD(s.reg, state.texture[i].iterators.ydsdy);
3714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_LOAD(t.reg, state.texture[i].iterators.ydtdy);
3724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            } else {
3734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                int ydsdy = scratches.obtain();
3744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                int ydtdy = scratches.obtain();
3754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_LOAD(s.reg, generated_vars.texture[i].dsdx);
3764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_LOAD(ydsdy, state.texture[i].iterators.ydsdy);
3774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_LOAD(t.reg, generated_vars.texture[i].dtdx);
3784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_LOAD(ydtdy, state.texture[i].iterators.ydtdy);
3794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                MLA(AL, 0, s.reg, Rx, s.reg, ydsdy);
3804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                MLA(AL, 0, t.reg, Rx, t.reg, ydtdy);
3814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
3824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if ((mOptLevel&1)==0) {
3844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_STORE(s.reg, generated_vars.texture[i].spill[0]);
3854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_STORE(t.reg, generated_vars.texture[i].spill[1]);
3864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                recycleReg(s.reg);
3874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                recycleReg(t.reg);
3884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
3894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
3904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // direct texture?
3924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (!multiTexture && !mBlending && !mDithering && !mFog &&
3934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            cb_format_idx == tmu.format_idx && !tmu.linear &&
3944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            mTextureMachine.replaced == tmu.mask)
3954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        {
3964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                mTextureMachine.directTexture = i + 1;
3974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
3984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
4004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::build_textures(  fragment_parts_t& parts,
4024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                    Scratch& regs)
4034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
4044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    context_t const* c = mBuilderContext.c;
4054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const needs_t& needs = mBuilderContext.needs;
4064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int Rctx = mBuilderContext.Rctx;
4074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // We don't have a way to spill registers automatically
4094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // spill depth and AA regs, when we know we may have to.
4104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // build the spill list...
4114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    uint32_t spill_list = 0;
4124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT; i++) {
4134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const texture_unit_t& tmu = mTextureMachine.tmu[i];
4144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (tmu.format_idx == 0)
4154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            continue;
4164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (tmu.linear) {
4174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // we may run out of register if we have linear filtering
4184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // at 1 or 4 bytes / pixel on any texture unit.
4194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (tmu.format.size == 1) {
4204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // if depth and AA enabled, we'll run out of 1 register
4214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (parts.z.reg > 0 && parts.covPtr.reg > 0)
4224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    spill_list |= 1<<parts.covPtr.reg;
4234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
4244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (tmu.format.size == 4) {
4254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // if depth or AA enabled, we'll run out of 1 or 2 registers
4264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (parts.z.reg > 0)
4274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    spill_list |= 1<<parts.z.reg;
4284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (parts.covPtr.reg > 0)
4294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    spill_list |= 1<<parts.covPtr.reg;
4304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
4314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
4324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
4334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    Spill spill(registerFile(), *this, spill_list);
4354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const bool multiTexture = mTextureMachine.activeUnits > 1;
4374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT; i++) {
4384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const texture_unit_t& tmu = mTextureMachine.tmu[i];
4394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (tmu.format_idx == 0)
4404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            continue;
4414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        pointer_t& txPtr = parts.coords[i].ptr;
4434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        pixel_t& texel = parts.texel[i];
4444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // repeat...
4464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if ((tmu.swrap == GGL_NEEDS_WRAP_11) &&
4474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            (tmu.twrap == GGL_NEEDS_WRAP_11))
4484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        { // 1:1 textures
4494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            comment("fetch texel");
4504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            texel.setTo(regs.obtain(), &tmu.format);
4514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            load(txPtr, texel, WRITE_BACK);
4524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else {
4534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            Scratch scratches(registerFile());
4544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            reg_t& s = parts.coords[i].s;
4554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            reg_t& t = parts.coords[i].t;
4564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if ((mOptLevel&1)==0) {
4574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                comment("reload s/t (multitexture or linear filtering)");
4584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                s.reg = scratches.obtain();
4594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                t.reg = scratches.obtain();
4604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_LOAD(s.reg, generated_vars.texture[i].spill[0]);
4614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_LOAD(t.reg, generated_vars.texture[i].spill[1]);
4624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
4634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            comment("compute repeat/clamp");
4654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int u       = scratches.obtain();
4664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int v       = scratches.obtain();
4674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int width   = scratches.obtain();
4684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int height  = scratches.obtain();
4694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int U = 0;
4704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int V = 0;
4714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(width,  generated_vars.texture[i].width);
4734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(height, generated_vars.texture[i].height);
4744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int FRAC_BITS = 0;
4764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (tmu.linear) {
4774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // linear interpolation
4784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (tmu.format.size == 1) {
4794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // for 8-bits textures, we can afford
4804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // 7 bits of fractional precision at no
4814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // additional cost (we can't do 8 bits
4824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // because filter8 uses signed 16 bits muls)
4834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    FRAC_BITS = 7;
4844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                } else if (tmu.format.size == 2) {
4854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // filter16() is internally limited to 4 bits, so:
4864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // FRAC_BITS=2 generates less instructions,
4874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // FRAC_BITS=3,4,5 creates unpleasant artifacts,
4884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // FRAC_BITS=6+ looks good
4894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    FRAC_BITS = 6;
4904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                } else if (tmu.format.size == 4) {
4914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // filter32() is internally limited to 8 bits, so:
4924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // FRAC_BITS=4 looks good
4934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // FRAC_BITS=5+ looks better, but generates 3 extra ipp
4944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    FRAC_BITS = 6;
4954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                } else {
4964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // for all other cases we use 4 bits.
4974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    FRAC_BITS = 4;
4984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                }
4994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
5004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            wrapping(u, s.reg, width,  tmu.swrap, FRAC_BITS);
5014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            wrapping(v, t.reg, height, tmu.twrap, FRAC_BITS);
5024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (tmu.linear) {
5044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                comment("compute linear filtering offsets");
5054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // pixel size scale
5064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                const int shift = 31 - gglClz(tmu.format.size);
5074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                U = scratches.obtain();
5084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                V = scratches.obtain();
5094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // sample the texel center
5114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                SUB(AL, 0, u, u, imm(1<<(FRAC_BITS-1)));
5124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                SUB(AL, 0, v, v, imm(1<<(FRAC_BITS-1)));
5134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // get the fractionnal part of U,V
5154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                AND(AL, 0, U, u, imm((1<<FRAC_BITS)-1));
5164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                AND(AL, 0, V, v, imm((1<<FRAC_BITS)-1));
5174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // compute width-1 and height-1
5194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                SUB(AL, 0, width,  width,  imm(1));
5204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                SUB(AL, 0, height, height, imm(1));
5214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // get the integer part of U,V and clamp/wrap
5234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // and compute offset to the next texel
5244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (tmu.swrap == GGL_NEEDS_WRAP_REPEAT) {
5254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // u has already been REPEATed
5264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(AL, 1, u, reg_imm(u, ASR, FRAC_BITS));
5274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(MI, 0, u, width);
5284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    CMP(AL, u, width);
5294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(LT, 0, width, imm(1 << shift));
5304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    if (shift)
5314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                        MOV(GE, 0, width, reg_imm(width, LSL, shift));
5324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    RSB(GE, 0, width, width, imm(0));
5334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                } else {
5344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // u has not been CLAMPed yet
5354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // algorithm:
5364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // if ((u>>4) >= width)
5374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    //      u = width<<4
5384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    //      width = 0
5394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // else
5404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    //      width = 1<<shift
5414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // u = u>>4; // get integer part
5424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // if (u<0)
5434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    //      u = 0
5444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    //      width = 0
5454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // generated_vars.rt = width
5464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    CMP(AL, width, reg_imm(u, ASR, FRAC_BITS));
5484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(LE, 0, u, reg_imm(width, LSL, FRAC_BITS));
5494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(LE, 0, width, imm(0));
5504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(GT, 0, width, imm(1 << shift));
5514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(AL, 1, u, reg_imm(u, ASR, FRAC_BITS));
5524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(MI, 0, u, imm(0));
5534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(MI, 0, width, imm(0));
5544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                }
5554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_STORE(width, generated_vars.rt);
5564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                const int stride = width;
5584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_LOAD(stride, generated_vars.texture[i].stride);
5594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (tmu.twrap == GGL_NEEDS_WRAP_REPEAT) {
5604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // v has already been REPEATed
5614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(AL, 1, v, reg_imm(v, ASR, FRAC_BITS));
5624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(MI, 0, v, height);
5634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    CMP(AL, v, height);
5644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(LT, 0, height, imm(1 << shift));
5654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    if (shift)
5664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                        MOV(GE, 0, height, reg_imm(height, LSL, shift));
5674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    RSB(GE, 0, height, height, imm(0));
5684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MUL(AL, 0, height, stride, height);
5694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                } else {
5704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    // u has not been CLAMPed yet
5714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    CMP(AL, height, reg_imm(v, ASR, FRAC_BITS));
5724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(LE, 0, v, reg_imm(height, LSL, FRAC_BITS));
5734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(LE, 0, height, imm(0));
5744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    if (shift) {
5754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                        MOV(GT, 0, height, reg_imm(stride, LSL, shift));
5764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    } else {
5774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                        MOV(GT, 0, height, stride);
5784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    }
5794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(AL, 1, v, reg_imm(v, ASR, FRAC_BITS));
5804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(MI, 0, v, imm(0));
5814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    MOV(MI, 0, height, imm(0));
5824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                }
5834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_STORE(height, generated_vars.lb);
5844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
5854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            scratches.recycle(width);
5874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            scratches.recycle(height);
5884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // iterate texture coordinates...
5904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            comment("iterate s,t");
5914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int dsdx = scratches.obtain();
5924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int dtdx = scratches.obtain();
5934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(dsdx, generated_vars.texture[i].dsdx);
5944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(dtdx, generated_vars.texture[i].dtdx);
5954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, s.reg, s.reg, dsdx);
5964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, t.reg, t.reg, dtdx);
5974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if ((mOptLevel&1)==0) {
5984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_STORE(s.reg, generated_vars.texture[i].spill[0]);
5994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_STORE(t.reg, generated_vars.texture[i].spill[1]);
6004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                scratches.recycle(s.reg);
6014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                scratches.recycle(t.reg);
6024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
6034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            scratches.recycle(dsdx);
6044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            scratches.recycle(dtdx);
6054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // merge base & offset...
6074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            comment("merge base & offset");
6084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            texel.setTo(regs.obtain(), &tmu.format);
6094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            txPtr.setTo(texel.reg, tmu.bits);
6104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int stride = scratches.obtain();
6114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(stride,    generated_vars.texture[i].stride);
6124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(txPtr.reg, generated_vars.texture[i].data);
6134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            SMLABB(AL, u, v, stride, u);    // u+v*stride
6144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            base_offset(txPtr, txPtr, u);
6154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // load texel
6174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (!tmu.linear) {
6184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                comment("fetch texel");
6194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                load(txPtr, texel, 0);
6204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            } else {
6214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // recycle registers we don't need anymore
6224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                scratches.recycle(u);
6234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                scratches.recycle(v);
6244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                scratches.recycle(stride);
6254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                comment("fetch texel, bilinear");
6274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                switch (tmu.format.size) {
6284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                case 1:  filter8(parts, texel, tmu, U, V, txPtr, FRAC_BITS); break;
6294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                case 2: filter16(parts, texel, tmu, U, V, txPtr, FRAC_BITS); break;
6304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                case 3: filter24(parts, texel, tmu, U, V, txPtr, FRAC_BITS); break;
6314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                case 4: filter32(parts, texel, tmu, U, V, txPtr, FRAC_BITS); break;
6324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                }
6334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
6344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
6354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
6364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
6374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::build_iterate_texture_coordinates(
6394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const fragment_parts_t& parts)
6404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
6414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const bool multiTexture = mTextureMachine.activeUnits > 1;
6424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT; i++) {
6434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const texture_unit_t& tmu = mTextureMachine.tmu[i];
6444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (tmu.format_idx == 0)
6454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            continue;
6464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if ((tmu.swrap == GGL_NEEDS_WRAP_11) &&
6484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            (tmu.twrap == GGL_NEEDS_WRAP_11))
6494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        { // 1:1 textures
6504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            const pointer_t& txPtr = parts.coords[i].ptr;
6514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, txPtr.reg, txPtr.reg, imm(txPtr.size>>3));
6524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else {
6534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            Scratch scratches(registerFile());
6544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int s = parts.coords[i].s.reg;
6554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int t = parts.coords[i].t.reg;
6564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if ((mOptLevel&1)==0) {
6574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                s = scratches.obtain();
6584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                t = scratches.obtain();
6594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_LOAD(s, generated_vars.texture[i].spill[0]);
6604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_LOAD(t, generated_vars.texture[i].spill[1]);
6614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
6624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int dsdx = scratches.obtain();
6634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int dtdx = scratches.obtain();
6644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(dsdx, generated_vars.texture[i].dsdx);
6654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CONTEXT_LOAD(dtdx, generated_vars.texture[i].dtdx);
6664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, s, s, dsdx);
6674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, t, t, dtdx);
6684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if ((mOptLevel&1)==0) {
6694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_STORE(s, generated_vars.texture[i].spill[0]);
6704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                CONTEXT_STORE(t, generated_vars.texture[i].spill[1]);
6714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
6724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
6734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
6744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
6754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::filter8(
6774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const fragment_parts_t& parts,
6784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        pixel_t& texel, const texture_unit_t& tmu,
6794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int U, int V, pointer_t& txPtr,
6804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int FRAC_BITS)
6814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
6824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (tmu.format.components != GGL_ALPHA &&
6834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        tmu.format.components != GGL_LUMINANCE)
6844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    {
6854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // this is a packed format, and we don't support
6864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // linear filtering (it's probably RGB 332)
6874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // Should not happen with OpenGL|ES
6884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        LDRB(AL, texel.reg, txPtr.reg);
6894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
6904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
6914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // ------------------------
6934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // about ~22 cycles / pixel
6944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    Scratch scratches(registerFile());
6954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int pixel= scratches.obtain();
6974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int d    = scratches.obtain();
6984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int u    = scratches.obtain();
6994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int k    = scratches.obtain();
7004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int rt   = scratches.obtain();
7014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int lb   = scratches.obtain();
7024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // RB -> U * V
7044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    CONTEXT_LOAD(rt, generated_vars.rt);
7064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    CONTEXT_LOAD(lb, generated_vars.lb);
7074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int offset = pixel;
7094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ADD(AL, 0, offset, lb, rt);
7104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDRB(AL, pixel, txPtr.reg, reg_scale_pre(offset));
7114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMULBB(AL, u, U, V);
7124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMULBB(AL, d, pixel, u);
7134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    RSB(AL, 0, k, u, imm(1<<(FRAC_BITS*2)));
7144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // LB -> (1-U) * V
7164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    RSB(AL, 0, U, U, imm(1<<FRAC_BITS));
7174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDRB(AL, pixel, txPtr.reg, reg_scale_pre(lb));
7184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMULBB(AL, u, U, V);
7194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMLABB(AL, d, pixel, u, d);
7204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SUB(AL, 0, k, k, u);
7214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // LT -> (1-U)*(1-V)
7234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    RSB(AL, 0, V, V, imm(1<<FRAC_BITS));
7244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDRB(AL, pixel, txPtr.reg);
7254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMULBB(AL, u, U, V);
7264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMLABB(AL, d, pixel, u, d);
7274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // RT -> U*(1-V)
7294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDRB(AL, pixel, txPtr.reg, reg_scale_pre(rt));
7304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SUB(AL, 0, u, k, u);
7314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMLABB(AL, texel.reg, pixel, u, d);
7324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for (int i=0 ; i<4 ; i++) {
7344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (!texel.format.c[i].h) continue;
7354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        texel.format.c[i].h = FRAC_BITS*2+8;
7364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        texel.format.c[i].l = FRAC_BITS*2; // keeping 8 bits in enough
7374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
7384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    texel.format.size = 4;
7394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    texel.format.bitsPerPixel = 32;
7404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    texel.flags |= CLEAR_LO;
7414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
7424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::filter16(
7444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const fragment_parts_t& parts,
7454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        pixel_t& texel, const texture_unit_t& tmu,
7464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int U, int V, pointer_t& txPtr,
7474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int FRAC_BITS)
7484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
7494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // compute the mask
7504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // XXX: it would be nice if the mask below could be computed
7514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // automatically.
7524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    uint32_t mask = 0;
7534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int shift = 0;
7544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int prec = 0;
7554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    switch (tmu.format_idx) {
7564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        case GGL_PIXEL_FORMAT_RGB_565:
7574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // source: 00000ggg.ggg00000 | rrrrr000.000bbbbb
7584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // result: gggggggg.gggrrrrr | rrrrr0bb.bbbbbbbb
7594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            mask = 0x07E0F81F;
7604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            shift = 16;
7614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            prec = 5;
7624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            break;
7634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        case GGL_PIXEL_FORMAT_RGBA_4444:
7644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // 0000,1111,0000,1111 | 0000,1111,0000,1111
7654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            mask = 0x0F0F0F0F;
7664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            shift = 12;
7674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            prec = 4;
7684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            break;
7694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        case GGL_PIXEL_FORMAT_LA_88:
7704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // 0000,0000,1111,1111 | 0000,0000,1111,1111
7714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // AALL -> 00AA | 00LL
7724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            mask = 0x00FF00FF;
7734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            shift = 8;
7744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            prec = 8;
7754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            break;
7764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        default:
7774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // unsupported format, do something sensical...
7784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            LOGE("Unsupported 16-bits texture format (%d)", tmu.format_idx);
7794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            LDRH(AL, texel.reg, txPtr.reg);
7804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            return;
7814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
7824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const int adjust = FRAC_BITS*2 - prec;
7844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const int round  = 0;
7854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // update the texel format
7874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    texel.format.size = 4;
7884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    texel.format.bitsPerPixel = 32;
7894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    texel.flags |= CLEAR_HI|CLEAR_LO;
7904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for (int i=0 ; i<4 ; i++) {
7914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (!texel.format.c[i].h) continue;
7924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const uint32_t offset = (mask & tmu.format.mask(i)) ? 0 : shift;
7934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        texel.format.c[i].h = tmu.format.c[i].h + offset + prec;
7944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        texel.format.c[i].l = texel.format.c[i].h - (tmu.format.bits(i) + prec);
7954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
7964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // ------------------------
7984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // about ~40 cycles / pixel
7994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    Scratch scratches(registerFile());
8004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int pixel= scratches.obtain();
8024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int d    = scratches.obtain();
8034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int u    = scratches.obtain();
8044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int k    = scratches.obtain();
8054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // RB -> U * V
8074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int offset = pixel;
8084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    CONTEXT_LOAD(offset, generated_vars.rt);
8094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    CONTEXT_LOAD(u, generated_vars.lb);
8104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ADD(AL, 0, offset, offset, u);
8114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDRH(AL, pixel, txPtr.reg, reg_pre(offset));
8134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMULBB(AL, u, U, V);
8144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ORR(AL, 0, pixel, pixel, reg_imm(pixel, LSL, shift));
8154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    build_and_immediate(pixel, pixel, mask, 32);
8164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (adjust) {
8174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (round)
8184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, u, u, imm(1<<(adjust-1)));
8194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        MOV(AL, 0, u, reg_imm(u, LSR, adjust));
8204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
8214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MUL(AL, 0, d, pixel, u);
8224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    RSB(AL, 0, k, u, imm(1<<prec));
8234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // LB -> (1-U) * V
8254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    CONTEXT_LOAD(offset, generated_vars.lb);
8264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    RSB(AL, 0, U, U, imm(1<<FRAC_BITS));
8274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDRH(AL, pixel, txPtr.reg, reg_pre(offset));
8284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMULBB(AL, u, U, V);
8294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ORR(AL, 0, pixel, pixel, reg_imm(pixel, LSL, shift));
8304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    build_and_immediate(pixel, pixel, mask, 32);
8314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (adjust) {
8324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (round)
8334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, u, u, imm(1<<(adjust-1)));
8344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        MOV(AL, 0, u, reg_imm(u, LSR, adjust));
8354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
8364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MLA(AL, 0, d, pixel, u, d);
8374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SUB(AL, 0, k, k, u);
8384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // LT -> (1-U)*(1-V)
8404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    RSB(AL, 0, V, V, imm(1<<FRAC_BITS));
8414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDRH(AL, pixel, txPtr.reg);
8424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMULBB(AL, u, U, V);
8434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ORR(AL, 0, pixel, pixel, reg_imm(pixel, LSL, shift));
8444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    build_and_immediate(pixel, pixel, mask, 32);
8454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (adjust) {
8464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (round)
8474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, u, u, imm(1<<(adjust-1)));
8484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        MOV(AL, 0, u, reg_imm(u, LSR, adjust));
8494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
8504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MLA(AL, 0, d, pixel, u, d);
8514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // RT -> U*(1-V)
8534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    CONTEXT_LOAD(offset, generated_vars.rt);
8544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDRH(AL, pixel, txPtr.reg, reg_pre(offset));
8554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SUB(AL, 0, u, k, u);
8564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ORR(AL, 0, pixel, pixel, reg_imm(pixel, LSL, shift));
8574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    build_and_immediate(pixel, pixel, mask, 32);
8584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MLA(AL, 0, texel.reg, pixel, u, d);
8594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
8604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::filter24(
8624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const fragment_parts_t& parts,
8634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        pixel_t& texel, const texture_unit_t& tmu,
8644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int U, int V, pointer_t& txPtr,
8654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int FRAC_BITS)
8664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
8674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // not supported yet (currently disabled)
8684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    load(txPtr, texel, 0);
8694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
8704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::filter32(
8724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const fragment_parts_t& parts,
8734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        pixel_t& texel, const texture_unit_t& tmu,
8744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int U, int V, pointer_t& txPtr,
8754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int FRAC_BITS)
8764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
8774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const int adjust = FRAC_BITS*2 - 8;
8784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const int round  = 0;
8794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // ------------------------
8814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // about ~38 cycles / pixel
8824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    Scratch scratches(registerFile());
8834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int pixel= scratches.obtain();
8854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int dh   = scratches.obtain();
8864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int u    = scratches.obtain();
8874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int k    = scratches.obtain();
8884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int temp = scratches.obtain();
8904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int dl   = scratches.obtain();
8914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int mask = scratches.obtain();
8924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MOV(AL, 0, mask, imm(0xFF));
8944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ORR(AL, 0, mask, mask, imm(0xFF0000));
8954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // RB -> U * V
8974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int offset = pixel;
8984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    CONTEXT_LOAD(offset, generated_vars.rt);
8994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    CONTEXT_LOAD(u, generated_vars.lb);
9004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ADD(AL, 0, offset, offset, u);
9014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDR(AL, pixel, txPtr.reg, reg_scale_pre(offset));
9034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMULBB(AL, u, U, V);
9044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AND(AL, 0, temp, mask, pixel);
9054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (adjust) {
9064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (round)
9074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, u, u, imm(1<<(adjust-1)));
9084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        MOV(AL, 0, u, reg_imm(u, LSR, adjust));
9094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
9104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MUL(AL, 0, dh, temp, u);
9114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AND(AL, 0, temp, mask, reg_imm(pixel, LSR, 8));
9124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MUL(AL, 0, dl, temp, u);
9134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    RSB(AL, 0, k, u, imm(0x100));
9144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // LB -> (1-U) * V
9164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    CONTEXT_LOAD(offset, generated_vars.lb);
9174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    RSB(AL, 0, U, U, imm(1<<FRAC_BITS));
9184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDR(AL, pixel, txPtr.reg, reg_scale_pre(offset));
9194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMULBB(AL, u, U, V);
9204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AND(AL, 0, temp, mask, pixel);
9214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (adjust) {
9224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (round)
9234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, u, u, imm(1<<(adjust-1)));
9244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        MOV(AL, 0, u, reg_imm(u, LSR, adjust));
9254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
9264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MLA(AL, 0, dh, temp, u, dh);
9274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AND(AL, 0, temp, mask, reg_imm(pixel, LSR, 8));
9284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MLA(AL, 0, dl, temp, u, dl);
9294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SUB(AL, 0, k, k, u);
9304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // LT -> (1-U)*(1-V)
9324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    RSB(AL, 0, V, V, imm(1<<FRAC_BITS));
9334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDR(AL, pixel, txPtr.reg);
9344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SMULBB(AL, u, U, V);
9354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AND(AL, 0, temp, mask, pixel);
9364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (adjust) {
9374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (round)
9384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, u, u, imm(1<<(adjust-1)));
9394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        MOV(AL, 0, u, reg_imm(u, LSR, adjust));
9404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
9414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MLA(AL, 0, dh, temp, u, dh);
9424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AND(AL, 0, temp, mask, reg_imm(pixel, LSR, 8));
9434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MLA(AL, 0, dl, temp, u, dl);
9444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // RT -> U*(1-V)
9464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    CONTEXT_LOAD(offset, generated_vars.rt);
9474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDR(AL, pixel, txPtr.reg, reg_scale_pre(offset));
9484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    SUB(AL, 0, u, k, u);
9494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AND(AL, 0, temp, mask, pixel);
9504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MLA(AL, 0, dh, temp, u, dh);
9514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AND(AL, 0, temp, mask, reg_imm(pixel, LSR, 8));
9524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    MLA(AL, 0, dl, temp, u, dl);
9534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AND(AL, 0, dh, mask, reg_imm(dh, LSR, 8));
9554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    AND(AL, 0, dl, dl, reg_imm(mask, LSL, 8));
9564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ORR(AL, 0, texel.reg, dh, dl);
9574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
9584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::build_texture_environment(
9604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        component_t& fragment,
9614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const fragment_parts_t& parts,
9624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int component,
9634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        Scratch& regs)
9644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
9654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const uint32_t component_mask = 1<<component;
9664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const bool multiTexture = mTextureMachine.activeUnits > 1;
9674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
9684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        texture_unit_t& tmu = mTextureMachine.tmu[i];
9694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (tmu.mask & component_mask) {
9714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // replace or modulate with this texture
9724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if ((tmu.replaced & component_mask) == 0) {
9734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // not replaced by a later tmu...
9744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                Scratch scratches(registerFile());
9764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                pixel_t texel(parts.texel[i]);
9774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (multiTexture &&
9784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    tmu.swrap == GGL_NEEDS_WRAP_11 &&
9794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    tmu.twrap == GGL_NEEDS_WRAP_11)
9804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                {
9814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    texel.reg = scratches.obtain();
9824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    texel.flags |= CORRUPTIBLE;
9834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    comment("fetch texel (multitexture 1:1)");
9844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    load(parts.coords[i].ptr, texel, WRITE_BACK);
9854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                 }
9864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                component_t incoming(fragment);
9884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                modify(fragment, regs);
9894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                switch (tmu.env) {
9914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                case GGL_REPLACE:
9924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    extract(fragment, texel, component);
9934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    break;
9944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                case GGL_MODULATE:
9954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    modulate(fragment, incoming, texel, component);
9964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    break;
9974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                case GGL_DECAL:
9984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    decal(fragment, incoming, texel, component);
9994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    break;
10004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                case GGL_BLEND:
10014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    blend(fragment, incoming, texel, component, i);
10024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                    break;
100335237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project                case GGL_ADD:
100435237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project                    add(fragment, incoming, texel, component);
100535237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project                    break;
10064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                }
10074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
10084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
10094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
10104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
10114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project// ---------------------------------------------------------------------------
10134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::wrapping(
10154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int d,
10164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int coord, int size,
10174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int tx_wrap, int tx_linear)
10184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
10194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // notes:
10204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // if tx_linear is set, we need 4 extra bits of precision on the result
10214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // SMULL/UMULL is 3 cycles
10224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    Scratch scratches(registerFile());
10234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int c = coord;
10244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (tx_wrap == GGL_NEEDS_WRAP_REPEAT) {
10254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // UMULL takes 4 cycles (interlocked), and we can get away with
10264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // 2 cycles using SMULWB, but we're loosing 16 bits of precision
10274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // out of 32 (this is not a problem because the iterator keeps
10284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // its full precision)
10294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // UMULL(AL, 0, size, d, c, size);
10304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // note: we can't use SMULTB because it's signed.
10314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        MOV(AL, 0, d, reg_imm(c, LSR, 16-tx_linear));
10324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        SMULWB(AL, d, d, size);
10334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else if (tx_wrap == GGL_NEEDS_WRAP_CLAMP_TO_EDGE) {
10344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (tx_linear) {
10354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // 1 cycle
10364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            MOV(AL, 0, d, reg_imm(coord, ASR, 16-tx_linear));
10374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else {
10384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // 4 cycles (common case)
10394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            MOV(AL, 0, d, reg_imm(coord, ASR, 16));
10404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            BIC(AL, 0, d, d, reg_imm(d, ASR, 31));
10414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            CMP(AL, d, size);
10424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            SUB(GE, 0, d, size, imm(1));
10434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
10444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
10454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
10464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project// ---------------------------------------------------------------------------
10484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::modulate(
10504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        component_t& dest,
10514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const component_t& incoming,
10524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const pixel_t& incomingTexel, int component)
10534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
10544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    Scratch locals(registerFile());
10554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    integer_t texel(locals.obtain(), 32, CORRUPTIBLE);
10564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    extract(texel, incomingTexel, component);
10574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    const int Nt = texel.size();
10594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // Nt should always be less than 10 bits because it comes
10604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // from the TMU.
10614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int Ni = incoming.size();
10634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // Ni could be big because it comes from previous MODULATEs
10644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (Nt == 1) {
10664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // texel acts as a bit-mask
10674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // dest = incoming & ((texel << incoming.h)-texel)
10684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        RSB(AL, 0, dest.reg, texel.reg, reg_imm(texel.reg, LSL, incoming.h));
10694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        AND(AL, 0, dest.reg, dest.reg, incoming.reg);
10704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        dest.l = incoming.l;
10714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        dest.h = incoming.h;
10724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        dest.flags |= (incoming.flags & CLEAR_LO);
10734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else if (Ni == 1) {
10744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        MOV(AL, 0, dest.reg, reg_imm(incoming.reg, LSL, 31-incoming.h));
10754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        AND(AL, 0, dest.reg, texel.reg, reg_imm(dest.reg, ASR, 31));
10764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        dest.l = 0;
10774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        dest.h = Nt;
10784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
10794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int inReg = incoming.reg;
10804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int shift = incoming.l;
10814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if ((Nt + Ni) > 32) {
10824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // we will overflow, reduce the precision of Ni to 8 bits
10834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // (Note Nt cannot be more than 10 bits which happens with
10844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // 565 textures and GGL_LINEAR)
10854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            shift += Ni-8;
10864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            Ni = 8;
10874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
10884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // modulate by the component with the lowest precision
10904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (Nt >= Ni) {
10914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (shift) {
10924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // XXX: we should be able to avoid this shift
10934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // when shift==16 && Nt<16 && Ni<16, in which
10944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // we could use SMULBT below.
10954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                MOV(AL, 0, dest.reg, reg_imm(inReg, LSR, shift));
10964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                inReg = dest.reg;
10974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                shift = 0;
10984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
10994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // operation:           (Cf*Ct)/((1<<Ni)-1)
11004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // approximated with:   Cf*(Ct + Ct>>(Ni-1))>>Ni
11014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // this operation doesn't change texel's size
11024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, dest.reg, inReg, reg_imm(inReg, LSR, Ni-1));
11034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (Nt<16 && Ni<16) SMULBB(AL, dest.reg, texel.reg, dest.reg);
11044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            else                MUL(AL, 0, dest.reg, texel.reg, dest.reg);
11054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            dest.l = Ni;
11064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            dest.h = Nt + Ni;
11074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else {
11084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (shift && (shift != 16)) {
11094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                // if shift==16, we can use 16-bits mul instructions later
11104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                MOV(AL, 0, dest.reg, reg_imm(inReg, LSR, shift));
11114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                inReg = dest.reg;
11124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                shift = 0;
11134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
11144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // operation:           (Cf*Ct)/((1<<Nt)-1)
11154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // approximated with:   Ct*(Cf + Cf>>(Nt-1))>>Nt
11164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            // this operation doesn't change incoming's size
11174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            Scratch scratches(registerFile());
11184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int t = (texel.flags & CORRUPTIBLE) ? texel.reg : dest.reg;
11194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (t == inReg)
11204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                t = scratches.obtain();
11214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ADD(AL, 0, t, texel.reg, reg_imm(texel.reg, LSR, Nt-1));
11224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (Nt<16 && Ni<16) {
11234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (shift==16)  SMULBT(AL, dest.reg, t, inReg);
11244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                else            SMULBB(AL, dest.reg, t, inReg);
11254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            } else              MUL(AL, 0, dest.reg, t, inReg);
11264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            dest.l = Nt;
11274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            dest.h = Nt + Ni;
11284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
11294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
11304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // low bits are not valid
11314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        dest.flags |= CLEAR_LO;
11324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
11334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        // no need to keep more than 8 bits/component
11344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (dest.size() > 8)
11354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            dest.l = dest.h-8;
11364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
11374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
11384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
11394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::decal(
11404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        component_t& dest,
11414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const component_t& incoming,
11424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const pixel_t& incomingTexel, int component)
11434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
11444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // RGBA:
11454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // Cv = Cf*(1 - At) + Ct*At = Cf + (Ct - Cf)*At
11464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // Av = Af
11474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    Scratch locals(registerFile());
11484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    integer_t texel(locals.obtain(), 32, CORRUPTIBLE);
11494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    integer_t factor(locals.obtain(), 32, CORRUPTIBLE);
11504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    extract(texel, incomingTexel, component);
11514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    extract(factor, incomingTexel, GGLFormat::ALPHA);
11524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
11534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // no need to keep more than 8-bits for decal
11544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int Ni = incoming.size();
11554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int shift = incoming.l;
11564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (Ni > 8) {
11574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        shift += Ni-8;
11584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        Ni = 8;
11594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
11604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    integer_t incomingNorm(incoming.reg, Ni, incoming.flags);
11614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (shift) {
11624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        MOV(AL, 0, dest.reg, reg_imm(incomingNorm.reg, LSR, shift));
11634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        incomingNorm.reg = dest.reg;
11644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        incomingNorm.flags |= CORRUPTIBLE;
11654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
11664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ADD(AL, 0, factor.reg, factor.reg, reg_imm(factor.reg, LSR, factor.s-1));
11674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    build_blendOneMinusFF(dest, factor, incomingNorm, texel);
11684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
11694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
11704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid GGLAssembler::blend(
11714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        component_t& dest,
11724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const component_t& incoming,
11734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        const pixel_t& incomingTexel, int component, int tmu)
11744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
11754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // RGBA:
11764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // Cv = (1 - Ct)*Cf + Ct*Cc = Cf + (Cc - Cf)*Ct
11774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // Av = At*Af
11784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
11794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (component == GGLFormat::ALPHA) {
11804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        modulate(dest, incoming, incomingTexel, component);
11814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
11824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
11834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
11844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    Scratch locals(registerFile());
11854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    integer_t color(locals.obtain(), 8, CORRUPTIBLE);
11864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    integer_t factor(locals.obtain(), 32, CORRUPTIBLE);
11874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    LDRB(AL, color.reg, mBuilderContext.Rctx,
11884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            immed12_pre(GGL_OFFSETOF(state.texture[tmu].env_color[component])));
11894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    extract(factor, incomingTexel, component);
11904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
11914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    // no need to keep more than 8-bits for blend
11924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int Ni = incoming.size();
11934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int shift = incoming.l;
11944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (Ni > 8) {
11954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        shift += Ni-8;
11964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        Ni = 8;
11974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
11984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    integer_t incomingNorm(incoming.reg, Ni, incoming.flags);
11994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (shift) {
12004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        MOV(AL, 0, dest.reg, reg_imm(incomingNorm.reg, LSR, shift));
12014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        incomingNorm.reg = dest.reg;
12024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        incomingNorm.flags |= CORRUPTIBLE;
12034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
12044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ADD(AL, 0, factor.reg, factor.reg, reg_imm(factor.reg, LSR, factor.s-1));
12054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    build_blendOneMinusFF(dest, factor, incomingNorm, color);
12064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
12074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
120835237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Projectvoid GGLAssembler::add(
120935237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        component_t& dest,
121035237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        const component_t& incoming,
121135237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        const pixel_t& incomingTexel, int component)
121235237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project{
121335237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    // RGBA:
121435237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    // Cv = Cf + Ct;
121535237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    Scratch locals(registerFile());
121635237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project
121735237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    component_t incomingTemp(incoming);
121835237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project
121935237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    // use "dest" as a temporary for extracting the texel, unless "dest"
122035237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    // overlaps "incoming".
122135237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    integer_t texel(dest.reg, 32, CORRUPTIBLE);
122235237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    if (dest.reg == incomingTemp.reg)
122335237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        texel.reg = locals.obtain();
122435237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    extract(texel, incomingTexel, component);
122535237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project
122635237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    if (texel.s < incomingTemp.size()) {
122735237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        expand(texel, texel, incomingTemp.size());
122835237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    } else if (texel.s > incomingTemp.size()) {
122935237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        if (incomingTemp.flags & CORRUPTIBLE) {
123035237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project            expand(incomingTemp, incomingTemp, texel.s);
123135237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        } else {
123235237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project            incomingTemp.reg = locals.obtain();
123335237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project            expand(incomingTemp, incoming, texel.s);
123435237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        }
123535237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    }
123635237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project
123735237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    if (incomingTemp.l) {
123835237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        ADD(AL, 0, dest.reg, texel.reg,
123935237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project                reg_imm(incomingTemp.reg, LSR, incomingTemp.l));
124035237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    } else {
124135237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        ADD(AL, 0, dest.reg, texel.reg, incomingTemp.reg);
124235237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    }
124335237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    dest.l = 0;
124435237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    dest.h = texel.size();
124535237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    component_sat(dest);
124635237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project}
124735237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project
12484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project// ----------------------------------------------------------------------------
12494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
12504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}; // namespace android
12514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1252