1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* libs/pixelflinger/codeflinger/blending.cpp
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** Copyright 2006, The Android Open Source Project
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** you may not use this file except in compliance with the License.
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** You may obtain a copy of the License at
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**     http://www.apache.org/licenses/LICENSE-2.0
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** Unless required by applicable law or agreed to in writing, software
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS,
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** See the License for the specific language governing permissions and
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** limitations under the License.
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project*/
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <assert.h>
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdint.h>
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h>
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h>
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/types.h>
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/log.h>
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "codeflinger/GGLAssembler.h"
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectnamespace android {
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid GGLAssembler::build_fog(
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        component_t& temp,      // incomming fragment / output
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        int component,
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        Scratch& regs)
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   if (mInfo[component].fog) {
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        Scratch scratches(registerFile());
38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        comment("fog");
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        integer_t fragment(temp.reg, temp.h, temp.flags);
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!(temp.flags & CORRUPTIBLE)) {
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            temp.reg = regs.obtain();
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            temp.flags |= CORRUPTIBLE;
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        integer_t fogColor(scratches.obtain(), 8, CORRUPTIBLE);
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        LDRB(AL, fogColor.reg, mBuilderContext.Rctx,
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                immed12_pre(GGL_OFFSETOF(state.fog.color[component])));
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        integer_t factor(scratches.obtain(), 16, CORRUPTIBLE);
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        CONTEXT_LOAD(factor.reg, generated_vars.f);
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // clamp fog factor (TODO: see if there is a way to guarantee
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // we won't overflow, when setting the iterators)
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        BIC(AL, 0, factor.reg, factor.reg, reg_imm(factor.reg, ASR, 31));
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        CMP(AL, factor.reg, imm( 0x10000 ));
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        MOV(HS, 0, factor.reg, imm( 0x10000 ));
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        build_blendFOneMinusF(temp, factor, fragment, fogColor);
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid GGLAssembler::build_blending(
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        component_t& temp,      // incomming fragment / output
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        const pixel_t& pixel,   // framebuffer
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        int component,
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        Scratch& regs)
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   if (!mInfo[component].blend)
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return;
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int fs = component==GGLFormat::ALPHA ? mBlendSrcA : mBlendSrc;
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int fd = component==GGLFormat::ALPHA ? mBlendDstA : mBlendDst;
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (fs==GGL_SRC_ALPHA_SATURATE && component==GGLFormat::ALPHA)
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fs = GGL_ONE;
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int blending = blending_codes(fs, fd);
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!temp.size()) {
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // here, blending will produce something which doesn't depend on
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // that component (eg: GL_ZERO:GL_*), so the register has not been
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // allocated yet. Will never be used as a source.
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        temp = component_t(regs.obtain(), CORRUPTIBLE);
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // we are doing real blending...
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // fb:          extracted dst
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // fragment:    extracted src
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // temp:        component_t(fragment) and result
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // scoped register allocator
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    Scratch scratches(registerFile());
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    comment("blending");
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // we can optimize these cases a bit...
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // (1) saturation is not needed
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // (2) we can use only one multiply instead of 2
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // (3) we can reduce the register pressure
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    //      R = S*f + D*(1-f) = (S-D)*f + D
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    //      R = S*(1-f) + D*f = (D-S)*f + S
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const bool same_factor_opt1 =
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        (fs==GGL_DST_COLOR && fd==GGL_ONE_MINUS_DST_COLOR) ||
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        (fs==GGL_SRC_COLOR && fd==GGL_ONE_MINUS_SRC_COLOR) ||
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        (fs==GGL_DST_ALPHA && fd==GGL_ONE_MINUS_DST_ALPHA) ||
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        (fs==GGL_SRC_ALPHA && fd==GGL_ONE_MINUS_SRC_ALPHA);
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const bool same_factor_opt2 =
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        (fs==GGL_ONE_MINUS_DST_COLOR && fd==GGL_DST_COLOR) ||
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        (fs==GGL_ONE_MINUS_SRC_COLOR && fd==GGL_SRC_COLOR) ||
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        (fs==GGL_ONE_MINUS_DST_ALPHA && fd==GGL_DST_ALPHA) ||
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        (fs==GGL_ONE_MINUS_SRC_ALPHA && fd==GGL_SRC_ALPHA);
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // XXX: we could also optimize these cases:
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // R = S*f + D*f = (S+D)*f
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // R = S*(1-f) + D*(1-f) = (S+D)*(1-f)
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // R = S*D + D*S = 2*S*D
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // see if we need to extract 'component' from the destination (fb)
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    integer_t fb;
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (blending & (BLEND_DST|FACTOR_DST)) {
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fb.setTo(scratches.obtain(), 32);
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        extract(fb, pixel, component);
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (mDithering) {
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // XXX: maybe what we should do instead, is simply
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // expand fb -or- fragment to the larger of the two
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (fb.size() < temp.size()) {
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // for now we expand 'fb' to min(fragment, 8)
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                int new_size = temp.size() < 8 ? temp.size() : 8;
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                expand(fb, fb, new_size);
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // convert input fragment to integer_t
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (temp.l && (temp.flags & CORRUPTIBLE)) {
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        MOV(AL, 0, temp.reg, reg_imm(temp.reg, LSR, temp.l));
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        temp.h -= temp.l;
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        temp.l = 0;
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    integer_t fragment(temp.reg, temp.size(), temp.flags);
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // if not done yet, convert input fragment to integer_t
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (temp.l) {
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // here we know temp is not CORRUPTIBLE
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fragment.reg = scratches.obtain();
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        MOV(AL, 0, fragment.reg, reg_imm(temp.reg, LSR, temp.l));
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fragment.flags |= CORRUPTIBLE;
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!(temp.flags & CORRUPTIBLE)) {
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // temp is not corruptible, but since it's the destination it
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // will be modified, so we need to allocate a new register.
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        temp.reg = regs.obtain();
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        temp.flags &= ~CORRUPTIBLE;
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fragment.flags &= ~CORRUPTIBLE;
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if ((blending & BLEND_SRC) && !same_factor_opt1) {
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // source (fragment) is needed for the blending stage
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // so it's not CORRUPTIBLE (unless we're doing same_factor_opt1)
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fragment.flags &= ~CORRUPTIBLE;
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (same_factor_opt1) {
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //  R = S*f + D*(1-f) = (S-D)*f + D
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        integer_t factor;
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        build_blend_factor(factor, fs,
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                component, pixel, fragment, fb, scratches);
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // fb is always corruptible from this point
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fb.flags |= CORRUPTIBLE;
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        build_blendFOneMinusF(temp, factor, fragment, fb);
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if (same_factor_opt2) {
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //  R = S*(1-f) + D*f = (D-S)*f + S
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        integer_t factor;
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // fb is always corrruptible here
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fb.flags |= CORRUPTIBLE;
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        build_blend_factor(factor, fd,
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                component, pixel, fragment, fb, scratches);
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        build_blendOneMinusFF(temp, factor, fragment, fb);
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        integer_t src_factor;
185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        integer_t dst_factor;
186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // if destination (fb) is not needed for the blending stage,
188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // then it can be marked as CORRUPTIBLE
189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!(blending & BLEND_DST)) {
190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fb.flags |= CORRUPTIBLE;
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // XXX: try to mark some registers as CORRUPTIBLE
194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // in most case we could make those corruptible
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // when we're processing the last component
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // but not always, for instance
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //    when fragment is constant and not reloaded
198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //    when fb is needed for logic-ops or masking
199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //    when a register is aliased (for instance with mAlphaSource)
200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // blend away...
202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (fs==GGL_ZERO) {
203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (fd==GGL_ZERO) {         // R = 0
204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // already taken care of
205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else if (fd==GGL_ONE) {   // R = D
206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // already taken care of
207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else {                    // R = D*fd
208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // compute fd
209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                build_blend_factor(dst_factor, fd,
210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        component, pixel, fragment, fb, scratches);
211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                mul_factor(temp, fb, dst_factor);
212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if (fs==GGL_ONE) {
214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (fd==GGL_ZERO) {         // R = S
215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // NOP, taken care of
216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else if (fd==GGL_ONE) {   // R = S + D
217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                component_add(temp, fb, fragment); // args order matters
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                component_sat(temp);
219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else {                    // R = S + D*fd
220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // compute fd
221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                build_blend_factor(dst_factor, fd,
222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        component, pixel, fragment, fb, scratches);
223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                mul_factor_add(temp, fb, dst_factor, component_t(fragment));
224665a2227e5212c6a7452f080d87f377b8471a8b0Mathias Agopian                component_sat(temp);
225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // compute fs
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            build_blend_factor(src_factor, fs,
229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    component, pixel, fragment, fb, scratches);
230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (fd==GGL_ZERO) {         // R = S*fs
231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                mul_factor(temp, fragment, src_factor);
232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else if (fd==GGL_ONE) {   // R = S*fs + D
233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                mul_factor_add(temp, fragment, src_factor, component_t(fb));
234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                component_sat(temp);
235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else {                    // R = S*fs + D*fd
236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                mul_factor(temp, fragment, src_factor);
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (scratches.isUsed(src_factor.reg))
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    scratches.recycle(src_factor.reg);
239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // compute fd
240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                build_blend_factor(dst_factor, fd,
241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        component, pixel, fragment, fb, scratches);
242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                mul_factor_add(temp, fb, dst_factor, temp);
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (!same_factor_opt1 && !same_factor_opt2) {
244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    component_sat(temp);
245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // now we can be corrupted (it's the dest)
251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    temp.flags |= CORRUPTIBLE;
252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid GGLAssembler::build_blend_factor(
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        integer_t& factor, int f, int component,
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const pixel_t& dst_pixel,
257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        integer_t& fragment,
258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        integer_t& fb,
259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        Scratch& scratches)
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    integer_t src_alpha(fragment);
262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // src_factor/dst_factor won't be used after blending,
264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // so it's fine to mark them as CORRUPTIBLE (if not aliased)
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    factor.flags |= CORRUPTIBLE;
266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    switch(f) {
268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_ONE_MINUS_SRC_ALPHA:
269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_SRC_ALPHA:
270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (component==GGLFormat::ALPHA && !isAlphaSourceNeeded()) {
271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // we're processing alpha, so we already have
272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // src-alpha in fragment, and we need src-alpha just this time.
273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           // alpha-src will be needed for other components
275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (!mBlendFactorCached || mBlendFactorCached==f) {
276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                src_alpha = mAlphaSource;
277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                factor = mAlphaSource;
278dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                factor.flags &= ~CORRUPTIBLE;
279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // we already computed the blend factor before, nothing to do.
280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (mBlendFactorCached)
281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    return;
282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // this is the first time, make sure to compute the blend
283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // factor properly.
284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                mBlendFactorCached = f;
285dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                break;
286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else {
287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // we have a cached alpha blend factor, but we want another one,
288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // this should really not happen because by construction,
289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // we cannot have BOTH source and destination
290dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // blend factors use ALPHA *and* ONE_MINUS_ALPHA (because
291dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // the blending stage uses the f/(1-f) optimization
292dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
293dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // for completeness, we handle this case though. Since there
294dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // are only 2 choices, this meens we want "the other one"
295dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // (1-factor)
296dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                factor = mAlphaSource;
297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                factor.flags &= ~CORRUPTIBLE;
298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                RSB(AL, 0, factor.reg, factor.reg, imm((1<<factor.s)));
299dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                mBlendFactorCached = f;
300dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                return;
301dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // fall-through...
304dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_ONE_MINUS_DST_COLOR:
305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_DST_COLOR:
306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_ONE_MINUS_SRC_COLOR:
307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_SRC_COLOR:
308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_ONE_MINUS_DST_ALPHA:
309dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_DST_ALPHA:
310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_SRC_ALPHA_SATURATE:
311dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // help us find out what register we can use for the blend-factor
312dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // CORRUPTIBLE registers are chosen first, or a new one is allocated.
313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (fragment.flags & CORRUPTIBLE) {
314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            factor.setTo(fragment.reg, 32, CORRUPTIBLE);
315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fragment.flags &= ~CORRUPTIBLE;
316dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if (fb.flags & CORRUPTIBLE) {
317dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            factor.setTo(fb.reg, 32, CORRUPTIBLE);
318dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fb.flags &= ~CORRUPTIBLE;
319dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
320dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            factor.setTo(scratches.obtain(), 32, CORRUPTIBLE);
321dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
322dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
323dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
324dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
325dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // XXX: doesn't work if size==1
326dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
327dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    switch(f) {
328dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_ONE_MINUS_DST_COLOR:
329dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_DST_COLOR:
330dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        factor.s = fb.s;
331dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ADD(AL, 0, factor.reg, fb.reg, reg_imm(fb.reg, LSR, fb.s-1));
332dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
333dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_ONE_MINUS_SRC_COLOR:
334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_SRC_COLOR:
335dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        factor.s = fragment.s;
336dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ADD(AL, 0, factor.reg, fragment.reg,
337dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            reg_imm(fragment.reg, LSR, fragment.s-1));
338dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
339dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_ONE_MINUS_SRC_ALPHA:
340dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_SRC_ALPHA:
341dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        factor.s = src_alpha.s;
342dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ADD(AL, 0, factor.reg, src_alpha.reg,
343dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                reg_imm(src_alpha.reg, LSR, src_alpha.s-1));
344dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
345dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_ONE_MINUS_DST_ALPHA:
346dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_DST_ALPHA:
347dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // XXX: should be precomputed
348dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        extract(factor, dst_pixel, GGLFormat::ALPHA);
349dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ADD(AL, 0, factor.reg, factor.reg,
350dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                reg_imm(factor.reg, LSR, factor.s-1));
351dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
352dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_SRC_ALPHA_SATURATE:
353dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // XXX: should be precomputed
354dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // XXX: f = min(As, 1-Ad)
355dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // btw, we're guaranteed that Ad's size is <= 8, because
356dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // it's extracted from the framebuffer
357dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
358dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
359dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
360dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    switch(f) {
361dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_ONE_MINUS_DST_COLOR:
362dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_ONE_MINUS_SRC_COLOR:
363dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_ONE_MINUS_DST_ALPHA:
364dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_ONE_MINUS_SRC_ALPHA:
365dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        RSB(AL, 0, factor.reg, factor.reg, imm((1<<factor.s)));
366dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
367dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
368dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // don't need more than 8-bits for the blend factor
369dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // and this will prevent overflows in the multiplies later
370dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (factor.s > 8) {
371dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        MOV(AL, 0, factor.reg, reg_imm(factor.reg, LSR, factor.s-8));
372dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        factor.s = 8;
373dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
374dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
375dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
376dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint GGLAssembler::blending_codes(int fs, int fd)
377dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
378dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int blending = 0;
379dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    switch(fs) {
380dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_ONE:
381dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        blending |= BLEND_SRC;
382dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
383dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
384dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_ONE_MINUS_DST_COLOR:
385dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_DST_COLOR:
386dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        blending |= FACTOR_DST|BLEND_SRC;
387dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
388dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_ONE_MINUS_DST_ALPHA:
389dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_DST_ALPHA:
390dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // no need to extract 'component' from the destination
391dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // for the blend factor, because we need ALPHA only.
392dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        blending |= BLEND_SRC;
393dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
394dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
395dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_ONE_MINUS_SRC_COLOR:
396dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_SRC_COLOR:
397dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        blending |= FACTOR_SRC|BLEND_SRC;
398dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
399dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_ONE_MINUS_SRC_ALPHA:
400dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_SRC_ALPHA:
401dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_SRC_ALPHA_SATURATE:
402dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        blending |= FACTOR_SRC|BLEND_SRC;
403dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
404dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
405dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    switch(fd) {
406dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_ONE:
407dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        blending |= BLEND_DST;
408dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
409dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
410dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_ONE_MINUS_DST_COLOR:
411dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_DST_COLOR:
412dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        blending |= FACTOR_DST|BLEND_DST;
413dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
414dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_ONE_MINUS_DST_ALPHA:
415dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_DST_ALPHA:
416dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        blending |= FACTOR_DST|BLEND_DST;
417dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
418dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
419dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_ONE_MINUS_SRC_COLOR:
420dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_SRC_COLOR:
421dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        blending |= FACTOR_SRC|BLEND_DST;
422dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
423dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_ONE_MINUS_SRC_ALPHA:
424dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case GGL_SRC_ALPHA:
425dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // no need to extract 'component' from the source
426dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // for the blend factor, because we need ALPHA only.
427dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        blending |= BLEND_DST;
428dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
429dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
430dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return blending;
431dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
432dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
433dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ---------------------------------------------------------------------------
434dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
435dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid GGLAssembler::build_blendFOneMinusF(
436dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        component_t& temp,
437dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const integer_t& factor,
438dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const integer_t& fragment,
439dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const integer_t& fb)
440dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
441dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    //  R = S*f + D*(1-f) = (S-D)*f + D
442dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    Scratch scratches(registerFile());
443dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // compute S-D
444dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    integer_t diff(fragment.flags & CORRUPTIBLE ?
445dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fragment.reg : scratches.obtain(), fb.size(), CORRUPTIBLE);
446dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int shift = fragment.size() - fb.size();
447dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (shift>0)        RSB(AL, 0, diff.reg, fb.reg, reg_imm(fragment.reg, LSR, shift));
448dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    else if (shift<0)   RSB(AL, 0, diff.reg, fb.reg, reg_imm(fragment.reg, LSL,-shift));
449dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    else                RSB(AL, 0, diff.reg, fb.reg, fragment.reg);
450dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    mul_factor_add(temp, diff, factor, component_t(fb));
451dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
452dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
453dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid GGLAssembler::build_blendOneMinusFF(
454dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        component_t& temp,
455dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const integer_t& factor,
456dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const integer_t& fragment,
457dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const integer_t& fb)
458dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
459dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    //  R = S*f + D*(1-f) = (S-D)*f + D
460dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    Scratch scratches(registerFile());
461dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // compute D-S
462dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    integer_t diff(fb.flags & CORRUPTIBLE ?
463dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fb.reg : scratches.obtain(), fb.size(), CORRUPTIBLE);
464dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int shift = fragment.size() - fb.size();
465dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (shift>0)        SUB(AL, 0, diff.reg, fb.reg, reg_imm(fragment.reg, LSR, shift));
466dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    else if (shift<0)   SUB(AL, 0, diff.reg, fb.reg, reg_imm(fragment.reg, LSL,-shift));
467dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    else                SUB(AL, 0, diff.reg, fb.reg, fragment.reg);
468dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    mul_factor_add(temp, diff, factor, component_t(fragment));
469dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
470dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
471dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ---------------------------------------------------------------------------
472dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
473dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid GGLAssembler::mul_factor(  component_t& d,
474dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                const integer_t& v,
475dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                const integer_t& f)
476dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
477dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int vs = v.size();
478dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int fs = f.size();
479dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int ms = vs+fs;
480dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
481dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // XXX: we could have special cases for 1 bit mul
482dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
483dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // all this code below to use the best multiply instruction
484dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // wrt the parameters size. We take advantage of the fact
485dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // that the 16-bits multiplies allow a 16-bit shift
486dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // The trick is that we just make sure that we have at least 8-bits
487dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // per component (which is enough for a 8 bits display).
488dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
489dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int xy;
490dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int vshift = 0;
491dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int fshift = 0;
492dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int smulw = 0;
493dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
494dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (vs<16) {
495dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (fs<16) {
496dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            xy = xyBB;
497dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if (GGL_BETWEEN(fs, 24, 31)) {
498dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ms -= 16;
499dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            xy = xyTB;
500dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
501dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // eg: 15 * 18  ->  15 * 15
502dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fshift = fs - 15;
503dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ms -= fshift;
504dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            xy = xyBB;
505dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
506dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if (GGL_BETWEEN(vs, 24, 31)) {
507dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (fs<16) {
508dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ms -= 16;
509dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            xy = xyTB;
510dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if (GGL_BETWEEN(fs, 24, 31)) {
511dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ms -= 32;
512dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            xy = xyTT;
513dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
514dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // eg: 24 * 18  ->  8 * 18
515dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fshift = fs - 15;
516dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ms -= 16 + fshift;
517dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            xy = xyTB;
518dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
519dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
520dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (fs<16) {
521dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // eg: 18 * 15  ->  15 * 15
522dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            vshift = vs - 15;
523dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ms -= vshift;
524dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            xy = xyBB;
525dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if (GGL_BETWEEN(fs, 24, 31)) {
526dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // eg: 18 * 24  ->  15 * 8
527dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            vshift = vs - 15;
528dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ms -= 16 + vshift;
529dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            xy = xyBT;
530dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
531dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // eg: 18 * 18  ->  (15 * 18)>>16
532dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fshift = fs - 15;
533dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ms -= 16 + fshift;
534dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            xy = yB;    //XXX SMULWB
535dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            smulw = 1;
536dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
537dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
538dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
53901dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block    ALOGE_IF(ms>=32, "mul_factor overflow vs=%d, fs=%d", vs, fs);
540dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
541dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int vreg = v.reg;
542dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int freg = f.reg;
543dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (vshift) {
544dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        MOV(AL, 0, d.reg, reg_imm(vreg, LSR, vshift));
545dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        vreg = d.reg;
546dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
547dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (fshift) {
548dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        MOV(AL, 0, d.reg, reg_imm(vreg, LSR, fshift));
549dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        freg = d.reg;
550dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
551dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (smulw)  SMULW(AL, xy, d.reg, vreg, freg);
552dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    else        SMUL(AL, xy, d.reg, vreg, freg);
553dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
554dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
555dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    d.h = ms;
556dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (mDithering) {
557dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        d.l = 0;
558dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
559dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        d.l = fs;
560dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        d.flags |= CLEAR_LO;
561dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
562dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
563dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
564dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid GGLAssembler::mul_factor_add(  component_t& d,
565dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                    const integer_t& v,
566dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                    const integer_t& f,
567dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                    const component_t& a)
568dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
569dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // XXX: we could have special cases for 1 bit mul
570dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    Scratch scratches(registerFile());
571dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
572dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int vs = v.size();
573dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int fs = f.size();
574dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int as = a.h;
575dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int ms = vs+fs;
576dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
57701dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block    ALOGE_IF(ms>=32, "mul_factor_add overflow vs=%d, fs=%d, as=%d", vs, fs, as);
578dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
579dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    integer_t add(a.reg, a.h, a.flags);
580dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
581dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // 'a' is a component_t but it is guaranteed to have
582dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // its high bits set to 0. However in the dithering case,
583dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // we can't get away with truncating the potentially bad bits
584dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // so extraction is needed.
585dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
586dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project   if ((mDithering) && (a.size() < ms)) {
587dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // we need to expand a
588dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!(a.flags & CORRUPTIBLE)) {
589dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // ... but it's not corruptible, so we need to pick a
590dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // temporary register.
591dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // Try to uses the destination register first (it's likely
592dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // to be usable, unless it aliases an input).
593dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (d.reg!=a.reg && d.reg!=v.reg && d.reg!=f.reg) {
594dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                add.reg = d.reg;
595dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else {
596dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                add.reg = scratches.obtain();
597dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
598dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
599dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        expand(add, a, ms); // extracts and expands
600dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        as = ms;
601dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
602dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
603dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (ms == as) {
604dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (vs<16 && fs<16) SMLABB(AL, d.reg, v.reg, f.reg, add.reg);
605dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        else                MLA(AL, 0, d.reg, v.reg, f.reg, add.reg);
606dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
607dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int temp = d.reg;
608dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (temp == add.reg) {
609dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // the mul will modify add.reg, we need an intermediary reg
610dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (v.flags & CORRUPTIBLE)      temp = v.reg;
611dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            else if (f.flags & CORRUPTIBLE) temp = f.reg;
612dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            else                            temp = scratches.obtain();
613dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
614dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
615dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (vs<16 && fs<16) SMULBB(AL, temp, v.reg, f.reg);
616dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        else                MUL(AL, 0, temp, v.reg, f.reg);
617dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
618dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (ms>as) {
619dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ADD(AL, 0, d.reg, temp, reg_imm(add.reg, LSL, ms-as));
620dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if (ms<as) {
621dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // not sure if we should expand the mul instead?
622dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ADD(AL, 0, d.reg, temp, reg_imm(add.reg, LSR, as-ms));
623dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
624dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
625dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
626dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    d.h = ms;
627dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (mDithering) {
628dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        d.l = a.l;
629dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
630dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        d.l = fs>a.l ? fs : a.l;
631dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        d.flags |= CLEAR_LO;
632dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
633dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
634dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
635dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid GGLAssembler::component_add(component_t& d,
636dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const integer_t& dst, const integer_t& src)
637dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
638dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // here we're guaranteed that fragment.size() >= fb.size()
639dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int shift = src.size() - dst.size();
640dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!shift) {
641dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ADD(AL, 0, d.reg, src.reg, dst.reg);
642dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
643dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ADD(AL, 0, d.reg, src.reg, reg_imm(dst.reg, LSL, shift));
644dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
645dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
646dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    d.h = src.size();
647dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (mDithering) {
648dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        d.l = 0;
649dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
650dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        d.l = shift;
651dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        d.flags |= CLEAR_LO;
652dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
653dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
654dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
655dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid GGLAssembler::component_sat(const component_t& v)
656dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
657dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int one = ((1<<v.size())-1)<<v.l;
658dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    CMP(AL, v.reg, imm( 1<<v.h ));
659dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (isValidImmediate(one)) {
660dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        MOV(HS, 0, v.reg, imm( one ));
661dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if (isValidImmediate(~one)) {
662dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        MVN(HS, 0, v.reg, imm( ~one ));
663dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
664dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        MOV(HS, 0, v.reg, imm( 1<<v.h ));
665dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        SUB(HS, 0, v.reg, v.reg, imm( 1<<v.l ));
666dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
667dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
668dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
669dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ----------------------------------------------------------------------------
670dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
671dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}; // namespace android
672dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
673