Example #1
0
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;
    }
}