/* libs/pixelflinger/codeflinger/blending.cpp
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License"); 
** you may not use this file except in compliance with the License. 
** You may obtain a copy of the License at 
**
**     http://www.apache.org/licenses/LICENSE-2.0 
**
** Unless required by applicable law or agreed to in writing, software 
** distributed under the License is distributed on an "AS IS" BASIS, 
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
** See the License for the specific language governing permissions and 
** limitations under the License.
*/

#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>

#include <cutils/log.h>

#include "codeflinger/GGLAssembler.h"


namespace android {

void GGLAssembler::build_fog(
                        component_t& temp,      // incomming fragment / output
                        int component,
                        Scratch& regs)
{
   if (mInfo[component].fog) {
        Scratch scratches(registerFile());
        comment("fog");

        integer_t fragment(temp.reg, temp.h, temp.flags);
        if (!(temp.flags & CORRUPTIBLE)) {
            temp.reg = regs.obtain();
            temp.flags |= CORRUPTIBLE;
        }

        integer_t fogColor(scratches.obtain(), 8, CORRUPTIBLE); 
        LDRB(AL, fogColor.reg, mBuilderContext.Rctx,
                immed12_pre(GGL_OFFSETOF(state.fog.color[component])));

        integer_t factor(scratches.obtain(), 16, CORRUPTIBLE);
        CONTEXT_LOAD(factor.reg, generated_vars.f);

        // clamp fog factor (TODO: see if there is a way to guarantee
        // we won't overflow, when setting the iterators)
        BIC(AL, 0, factor.reg, factor.reg, reg_imm(factor.reg, ASR, 31));
        CMP(AL, factor.reg, imm( 0x10000 ));
        MOV(HS, 0, factor.reg, imm( 0x10000 ));

        build_blendFOneMinusF(temp, factor, fragment, fogColor);
    }
}

void GGLAssembler::build_blending(
                        component_t& temp,      // incomming fragment / output
                        const pixel_t& pixel,   // framebuffer
                        int component,
                        Scratch& regs)
{
   if (!mInfo[component].blend)
        return;
        
    int fs = component==GGLFormat::ALPHA ? mBlendSrcA : mBlendSrc;
    int fd = component==GGLFormat::ALPHA ? mBlendDstA : mBlendDst;
    if (fs==GGL_SRC_ALPHA_SATURATE && component==GGLFormat::ALPHA)
        fs = GGL_ONE;
    const int blending = blending_codes(fs, fd);
    if (!temp.size()) {
        // here, blending will produce something which doesn't depend on
        // that component (eg: GL_ZERO:GL_*), so the register has not been
        // allocated yet. Will never be used as a source.
        temp = component_t(regs.obtain(), CORRUPTIBLE);
    }

    // we are doing real blending...
    // fb:          extracted dst
    // fragment:    extracted src
    // temp:        component_t(fragment) and result

    // scoped register allocator
    Scratch scratches(registerFile());
    comment("blending");

    // we can optimize these cases a bit...
    // (1) saturation is not needed
    // (2) we can use only one multiply instead of 2
    // (3) we can reduce the register pressure
    //      R = S*f + D*(1-f) = (S-D)*f + D
    //      R = S*(1-f) + D*f = (D-S)*f + S

    const bool same_factor_opt1 =
        (fs==GGL_DST_COLOR && fd==GGL_ONE_MINUS_DST_COLOR) ||
        (fs==GGL_SRC_COLOR && fd==GGL_ONE_MINUS_SRC_COLOR) ||
        (fs==GGL_DST_ALPHA && fd==GGL_ONE_MINUS_DST_ALPHA) ||
        (fs==GGL_SRC_ALPHA && fd==GGL_ONE_MINUS_SRC_ALPHA);

    const bool same_factor_opt2 =
        (fs==GGL_ONE_MINUS_DST_COLOR && fd==GGL_DST_COLOR) ||
        (fs==GGL_ONE_MINUS_SRC_COLOR && fd==GGL_SRC_COLOR) || 
        (fs==GGL_ONE_MINUS_DST_ALPHA && fd==GGL_DST_ALPHA) ||
        (fs==GGL_ONE_MINUS_SRC_ALPHA && fd==GGL_SRC_ALPHA);


    // XXX: we could also optimize these cases:
    // R = S*f + D*f = (S+D)*f
    // R = S*(1-f) + D*(1-f) = (S+D)*(1-f)
    // R = S*D + D*S = 2*S*D


    // see if we need to extract 'component' from the destination (fb)
    integer_t fb;
    if (blending & (BLEND_DST|FACTOR_DST)) { 
        fb.setTo(scratches.obtain(), 32); 
        extract(fb, pixel, component);
        if (mDithering) {
            // XXX: maybe what we should do instead, is simply
            // expand fb -or- fragment to the larger of the two
            if (fb.size() < temp.size()) {
                // for now we expand 'fb' to min(fragment, 8)
                int new_size = temp.size() < 8 ? temp.size() : 8;
                expand(fb, fb, new_size);
            }
        }
    }


    // convert input fragment to integer_t
    if (temp.l && (temp.flags & CORRUPTIBLE)) {
        MOV(AL, 0, temp.reg, reg_imm(temp.reg, LSR, temp.l));
        temp.h -= temp.l;
        temp.l = 0;
    }
    integer_t fragment(temp.reg, temp.size(), temp.flags);

    // if not done yet, convert input fragment to integer_t
    if (temp.l) {
        // here we know temp is not CORRUPTIBLE
        fragment.reg = scratches.obtain();
        MOV(AL, 0, fragment.reg, reg_imm(temp.reg, LSR, temp.l));
        fragment.flags |= CORRUPTIBLE;
    }

    if (!(temp.flags & CORRUPTIBLE)) {
        // temp is not corruptible, but since it's the destination it
        // will be modified, so we need to allocate a new register.
        temp.reg = regs.obtain();
        temp.flags &= ~CORRUPTIBLE;
        fragment.flags &= ~CORRUPTIBLE;
    }

    if ((blending & BLEND_SRC) && !same_factor_opt1) {
        // source (fragment) is needed for the blending stage
        // so it's not CORRUPTIBLE (unless we're doing same_factor_opt1)
        fragment.flags &= ~CORRUPTIBLE;
    }


    if (same_factor_opt1) {
        //  R = S*f + D*(1-f) = (S-D)*f + D
        integer_t factor;
        build_blend_factor(factor, fs, 
                component, pixel, fragment, fb, scratches);
        // fb is always corruptible from this point
        fb.flags |= CORRUPTIBLE;
        build_blendFOneMinusF(temp, factor, fragment, fb);
    } else if (same_factor_opt2) {
        //  R = S*(1-f) + D*f = (D-S)*f + S
        integer_t factor;
        // fb is always corrruptible here
        fb.flags |= CORRUPTIBLE;
        build_blend_factor(factor, fd,
                component, pixel, fragment, fb, scratches);
        build_blendOneMinusFF(temp, factor, fragment, fb);
    } else {
        integer_t src_factor;
        integer_t dst_factor;

        // if destination (fb) is not needed for the blending stage, 
        // then it can be marked as CORRUPTIBLE
        if (!(blending & BLEND_DST)) {
            fb.flags |= CORRUPTIBLE;
        }

        // XXX: try to mark some registers as CORRUPTIBLE
        // in most case we could make those corruptible
        // when we're processing the last component
        // but not always, for instance
        //    when fragment is constant and not reloaded
        //    when fb is needed for logic-ops or masking
        //    when a register is aliased (for instance with mAlphaSource)

        // blend away...
        if (fs==GGL_ZERO) {
            if (fd==GGL_ZERO) {         // R = 0
                // already taken care of
            } else if (fd==GGL_ONE) {   // R = D
                // already taken care of
            } else {                    // R = D*fd
                // compute fd
                build_blend_factor(dst_factor, fd,
                        component, pixel, fragment, fb, scratches);
                mul_factor(temp, fb, dst_factor);
            }
        } else if (fs==GGL_ONE) {
            if (fd==GGL_ZERO) {         // R = S
                // NOP, taken care of
            } else if (fd==GGL_ONE) {   // R = S + D
                component_add(temp, fb, fragment); // args order matters
                component_sat(temp);
            } else {                    // R = S + D*fd
                // compute fd
                build_blend_factor(dst_factor, fd,
                        component, pixel, fragment, fb, scratches);
                mul_factor_add(temp, fb, dst_factor, component_t(fragment));
                if (fd==GGL_ONE_MINUS_SRC_ALPHA) {
                    // XXX: in theory this is not correct, we should
                    // saturate here. However, this mode is often
                    // used for displaying alpha-premultiplied graphics,
                    // in which case, saturation is not necessary.
                    // unfortunatelly, we have no way to know.
                    // This is a case, where we sacrifice correctness for
                    // performance. we should probably have some heuristics.
                } else {
                    component_sat(temp);
                }
            }
        } else {
            // compute fs
            build_blend_factor(src_factor, fs, 
                    component, pixel, fragment, fb, scratches);
            if (fd==GGL_ZERO) {         // R = S*fs
                mul_factor(temp, fragment, src_factor);
            } else if (fd==GGL_ONE) {   // R = S*fs + D
                mul_factor_add(temp, fragment, src_factor, component_t(fb));
                component_sat(temp);
            } else {                    // R = S*fs + D*fd
                mul_factor(temp, fragment, src_factor);
                if (scratches.isUsed(src_factor.reg))
                    scratches.recycle(src_factor.reg);
                // compute fd
                build_blend_factor(dst_factor, fd,
                        component, pixel, fragment, fb, scratches);
                mul_factor_add(temp, fb, dst_factor, temp);
                if (!same_factor_opt1 && !same_factor_opt2) {
                    component_sat(temp);
                }
            }
        }
    }

    // now we can be corrupted (it's the dest)
    temp.flags |= CORRUPTIBLE;
}

void GGLAssembler::build_blend_factor(
        integer_t& factor, int f, int component,
        const pixel_t& dst_pixel,
        integer_t& fragment,
        integer_t& fb,
        Scratch& scratches)
{
    integer_t src_alpha(fragment);

    // src_factor/dst_factor won't be used after blending,
    // so it's fine to mark them as CORRUPTIBLE (if not aliased)
    factor.flags |= CORRUPTIBLE;

    switch(f) {
    case GGL_ONE_MINUS_SRC_ALPHA:
    case GGL_SRC_ALPHA:
        if (component==GGLFormat::ALPHA && !isAlphaSourceNeeded()) {
            // we're processing alpha, so we already have
            // src-alpha in fragment, and we need src-alpha just this time.
        } else {
           // alpha-src will be needed for other components
            if (!mBlendFactorCached || mBlendFactorCached==f) {
                src_alpha = mAlphaSource;
                factor = mAlphaSource;
                factor.flags &= ~CORRUPTIBLE;           
                // we already computed the blend factor before, nothing to do.
                if (mBlendFactorCached)
                    return;
                // this is the first time, make sure to compute the blend
                // factor properly.
                mBlendFactorCached = f;
                break;
            } else {
                // we have a cached alpha blend factor, but we want another one,
                // this should really not happen because by construction,
                // we cannot have BOTH source and destination
                // blend factors use ALPHA *and* ONE_MINUS_ALPHA (because
                // the blending stage uses the f/(1-f) optimization
                
                // for completeness, we handle this case though. Since there
                // are only 2 choices, this meens we want "the other one"
                // (1-factor)
                factor = mAlphaSource;
                factor.flags &= ~CORRUPTIBLE;           
                RSB(AL, 0, factor.reg, factor.reg, imm((1<<factor.s)));
                mBlendFactorCached = f;
                return;
            }                
        }
        // fall-through...
    case GGL_ONE_MINUS_DST_COLOR:
    case GGL_DST_COLOR:
    case GGL_ONE_MINUS_SRC_COLOR:
    case GGL_SRC_COLOR:
    case GGL_ONE_MINUS_DST_ALPHA:
    case GGL_DST_ALPHA:
    case GGL_SRC_ALPHA_SATURATE:
        // help us find out what register we can use for the blend-factor
        // CORRUPTIBLE registers are chosen first, or a new one is allocated.
        if (fragment.flags & CORRUPTIBLE) {
            factor.setTo(fragment.reg, 32, CORRUPTIBLE);
            fragment.flags &= ~CORRUPTIBLE;
        } else if (fb.flags & CORRUPTIBLE) {
            factor.setTo(fb.reg, 32, CORRUPTIBLE);
            fb.flags &= ~CORRUPTIBLE;
        } else {
            factor.setTo(scratches.obtain(), 32, CORRUPTIBLE);
        } 
        break;
    }

    // XXX: doesn't work if size==1

    switch(f) {
    case GGL_ONE_MINUS_DST_COLOR:
    case GGL_DST_COLOR:
        factor.s = fb.s;
        ADD(AL, 0, factor.reg, fb.reg, reg_imm(fb.reg, LSR, fb.s-1));
        break;
    case GGL_ONE_MINUS_SRC_COLOR:
    case GGL_SRC_COLOR:
        factor.s = fragment.s;
        ADD(AL, 0, factor.reg, fragment.reg,
            reg_imm(fragment.reg, LSR, fragment.s-1));
        break;
    case GGL_ONE_MINUS_SRC_ALPHA:
    case GGL_SRC_ALPHA:
        factor.s = src_alpha.s;
        ADD(AL, 0, factor.reg, src_alpha.reg,
                reg_imm(src_alpha.reg, LSR, src_alpha.s-1));
        break;
    case GGL_ONE_MINUS_DST_ALPHA:
    case GGL_DST_ALPHA:
        // XXX: should be precomputed
        extract(factor, dst_pixel, GGLFormat::ALPHA);
        ADD(AL, 0, factor.reg, factor.reg,
                reg_imm(factor.reg, LSR, factor.s-1));
        break;
    case GGL_SRC_ALPHA_SATURATE:
        // XXX: should be precomputed
        // XXX: f = min(As, 1-Ad)
        // btw, we're guaranteed that Ad's size is <= 8, because
        // it's extracted from the framebuffer
        break;
    }

    switch(f) {
    case GGL_ONE_MINUS_DST_COLOR:
    case GGL_ONE_MINUS_SRC_COLOR:
    case GGL_ONE_MINUS_DST_ALPHA:
    case GGL_ONE_MINUS_SRC_ALPHA:
        RSB(AL, 0, factor.reg, factor.reg, imm((1<<factor.s)));
    }
    
    // don't need more than 8-bits for the blend factor
    // and this will prevent overflows in the multiplies later
    if (factor.s > 8) {
        MOV(AL, 0, factor.reg, reg_imm(factor.reg, LSR, factor.s-8));
        factor.s = 8;
    }
}

int GGLAssembler::blending_codes(int fs, int fd)
{
    int blending = 0;
    switch(fs) {
    case GGL_ONE:
        blending |= BLEND_SRC;
        break;

    case GGL_ONE_MINUS_DST_COLOR:
    case GGL_DST_COLOR:
        blending |= FACTOR_DST|BLEND_SRC;
        break;
    case GGL_ONE_MINUS_DST_ALPHA:
    case GGL_DST_ALPHA:
        // no need to extract 'component' from the destination
        // for the blend factor, because we need ALPHA only.
        blending |= BLEND_SRC;
        break;

    case GGL_ONE_MINUS_SRC_COLOR:
    case GGL_SRC_COLOR:    
        blending |= FACTOR_SRC|BLEND_SRC;
        break;
    case GGL_ONE_MINUS_SRC_ALPHA:
    case GGL_SRC_ALPHA:
    case GGL_SRC_ALPHA_SATURATE:
        blending |= FACTOR_SRC|BLEND_SRC;
        break;
    }
    switch(fd) {
    case GGL_ONE:
        blending |= BLEND_DST;
        break;

    case GGL_ONE_MINUS_DST_COLOR:
    case GGL_DST_COLOR:
        blending |= FACTOR_DST|BLEND_DST;
        break;
    case GGL_ONE_MINUS_DST_ALPHA:
    case GGL_DST_ALPHA:
        blending |= FACTOR_DST|BLEND_DST;
        break;

    case GGL_ONE_MINUS_SRC_COLOR:
    case GGL_SRC_COLOR:    
        blending |= FACTOR_SRC|BLEND_DST;
        break;
    case GGL_ONE_MINUS_SRC_ALPHA:
    case GGL_SRC_ALPHA:
        // no need to extract 'component' from the source
        // for the blend factor, because we need ALPHA only.
        blending |= BLEND_DST;
        break;
    }
    return blending;
}

// ---------------------------------------------------------------------------

void GGLAssembler::build_blendFOneMinusF(
        component_t& temp,
        const integer_t& factor, 
        const integer_t& fragment,
        const integer_t& fb)
{
    //  R = S*f + D*(1-f) = (S-D)*f + D
    Scratch scratches(registerFile());
    // compute S-D
    integer_t diff(fragment.flags & CORRUPTIBLE ?
            fragment.reg : scratches.obtain(), fb.size(), CORRUPTIBLE);
    const int shift = fragment.size() - fb.size();
    if (shift>0)        RSB(AL, 0, diff.reg, fb.reg, reg_imm(fragment.reg, LSR, shift));
    else if (shift<0)   RSB(AL, 0, diff.reg, fb.reg, reg_imm(fragment.reg, LSL,-shift));
    else                RSB(AL, 0, diff.reg, fb.reg, fragment.reg);
    mul_factor_add(temp, diff, factor, component_t(fb));
}

void GGLAssembler::build_blendOneMinusFF(
        component_t& temp,
        const integer_t& factor, 
        const integer_t& fragment,
        const integer_t& fb)
{
    //  R = S*f + D*(1-f) = (S-D)*f + D
    Scratch scratches(registerFile());
    // compute D-S
    integer_t diff(fb.flags & CORRUPTIBLE ?
            fb.reg : scratches.obtain(), fb.size(), CORRUPTIBLE);
    const int shift = fragment.size() - fb.size();
    if (shift>0)        SUB(AL, 0, diff.reg, fb.reg, reg_imm(fragment.reg, LSR, shift));
    else if (shift<0)   SUB(AL, 0, diff.reg, fb.reg, reg_imm(fragment.reg, LSL,-shift));
    else                SUB(AL, 0, diff.reg, fb.reg, fragment.reg);
    mul_factor_add(temp, diff, factor, component_t(fragment));
}

// ---------------------------------------------------------------------------

void GGLAssembler::mul_factor(  component_t& d,
                                const integer_t& v,
                                const integer_t& f)
{
    int vs = v.size();
    int fs = f.size();
    int ms = vs+fs;

    // XXX: we could have special cases for 1 bit mul

    // all this code below to use the best multiply instruction
    // wrt the parameters size. We take advantage of the fact
    // that the 16-bits multiplies allow a 16-bit shift
    // The trick is that we just make sure that we have at least 8-bits
    // per component (which is enough for a 8 bits display).

    int xy;
    int vshift = 0;
    int fshift = 0;
    int smulw = 0;

    if (vs<16) {
        if (fs<16) {
            xy = xyBB;
        } else if (GGL_BETWEEN(fs, 24, 31)) {
            ms -= 16;
            xy = xyTB;
        } else {
            // eg: 15 * 18  ->  15 * 15
            fshift = fs - 15;
            ms -= fshift;
            xy = xyBB;
        }
    } else if (GGL_BETWEEN(vs, 24, 31)) {
        if (fs<16) {
            ms -= 16;
            xy = xyTB;
        } else if (GGL_BETWEEN(fs, 24, 31)) {
            ms -= 32;
            xy = xyTT;
        } else {
            // eg: 24 * 18  ->  8 * 18
            fshift = fs - 15;
            ms -= 16 + fshift;
            xy = xyTB;
        }
    } else {
        if (fs<16) {
            // eg: 18 * 15  ->  15 * 15
            vshift = vs - 15;
            ms -= vshift;
            xy = xyBB;
        } else if (GGL_BETWEEN(fs, 24, 31)) {
            // eg: 18 * 24  ->  15 * 8
            vshift = vs - 15;
            ms -= 16 + vshift;
            xy = xyBT;
        } else {
            // eg: 18 * 18  ->  (15 * 18)>>16
            fshift = fs - 15;
            ms -= 16 + fshift;
            xy = yB;    //XXX SMULWB
            smulw = 1;
        }
    }

    LOGE_IF(ms>=32, "mul_factor overflow vs=%d, fs=%d", vs, fs);

    int vreg = v.reg;
    int freg = f.reg;
    if (vshift) {
        MOV(AL, 0, d.reg, reg_imm(vreg, LSR, vshift));
        vreg = d.reg;
    }
    if (fshift) {
        MOV(AL, 0, d.reg, reg_imm(vreg, LSR, fshift));
        freg = d.reg;
    }
    if (smulw)  SMULW(AL, xy, d.reg, vreg, freg);
    else        SMUL(AL, xy, d.reg, vreg, freg);


    d.h = ms;
    if (mDithering) {
        d.l = 0; 
    } else {
        d.l = fs; 
        d.flags |= CLEAR_LO;
    }
}

void GGLAssembler::mul_factor_add(  component_t& d,
                                    const integer_t& v,
                                    const integer_t& f,
                                    const component_t& a)
{
    // XXX: we could have special cases for 1 bit mul
    Scratch scratches(registerFile());

    int vs = v.size();
    int fs = f.size();
    int as = a.h;
    int ms = vs+fs;

    LOGE_IF(ms>=32, "mul_factor_add overflow vs=%d, fs=%d, as=%d", vs, fs, as);

    integer_t add(a.reg, a.h, a.flags);

    // 'a' is a component_t but it is guaranteed to have
    // its high bits set to 0. However in the dithering case,
    // we can't get away with truncating the potentially bad bits
    // so extraction is needed.

   if ((mDithering) && (a.size() < ms)) {
        // we need to expand a
        if (!(a.flags & CORRUPTIBLE)) {
            // ... but it's not corruptible, so we need to pick a
            // temporary register.
            // Try to uses the destination register first (it's likely
            // to be usable, unless it aliases an input).
            if (d.reg!=a.reg && d.reg!=v.reg && d.reg!=f.reg) {
                add.reg = d.reg;
            } else {
                add.reg = scratches.obtain();
            }
        }
        expand(add, a, ms); // extracts and expands
        as = ms;
    }

    if (ms == as) {
        if (vs<16 && fs<16) SMLABB(AL, d.reg, v.reg, f.reg, add.reg);
        else                MLA(AL, 0, d.reg, v.reg, f.reg, add.reg);
    } else {
        int temp = d.reg;
        if (temp == add.reg) {
            // the mul will modify add.reg, we need an intermediary reg
            if (v.flags & CORRUPTIBLE)      temp = v.reg;
            else if (f.flags & CORRUPTIBLE) temp = f.reg;
            else                            temp = scratches.obtain();
        }

        if (vs<16 && fs<16) SMULBB(AL, temp, v.reg, f.reg);
        else                MUL(AL, 0, temp, v.reg, f.reg);

        if (ms>as) {
            ADD(AL, 0, d.reg, temp, reg_imm(add.reg, LSL, ms-as));
        } else if (ms<as) {
            // not sure if we should expand the mul instead?
            ADD(AL, 0, d.reg, temp, reg_imm(add.reg, LSR, as-ms));
        }
    }

    d.h = ms;
    if (mDithering) {
        d.l = a.l; 
    } else {
        d.l = fs>a.l ? fs : a.l;
        d.flags |= CLEAR_LO;
    }
}

void GGLAssembler::component_add(component_t& d,
        const integer_t& dst, const integer_t& src)
{
    // here we're guaranteed that fragment.size() >= fb.size()
    const int shift = src.size() - dst.size();
    if (!shift) {
        ADD(AL, 0, d.reg, src.reg, dst.reg);
    } else {
        ADD(AL, 0, d.reg, src.reg, reg_imm(dst.reg, LSL, shift));
    }

    d.h = src.size();
    if (mDithering) {
        d.l = 0;
    } else {
        d.l = shift;
        d.flags |= CLEAR_LO;
    }
}

void GGLAssembler::component_sat(const component_t& v)
{
    const int one = ((1<<v.size())-1)<<v.l;
    CMP(AL, v.reg, imm( 1<<v.h ));
    if (isValidImmediate(one)) {
        MOV(HS, 0, v.reg, imm( one ));
    } else if (isValidImmediate(~one)) {
        MVN(HS, 0, v.reg, imm( ~one ));
    } else {
        MOV(HS, 0, v.reg, imm( 1<<v.h ));
        SUB(HS, 0, v.reg, v.reg, imm( 1<<v.l ));
    }
}

// ----------------------------------------------------------------------------

}; // namespace android

