Code drop from //branches/cupcake/...@124589
diff --git a/libpixelflinger/Android.mk b/libpixelflinger/Android.mk
index a8e5ee4..6edc56f 100644
--- a/libpixelflinger/Android.mk
+++ b/libpixelflinger/Android.mk
@@ -85,3 +85,6 @@
 LOCAL_WHOLE_STATIC_LIBRARIES := libpixelflinger_armv6
 endif
 include $(BUILD_STATIC_LIBRARY)
+
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/libpixelflinger/codeflinger/GGLAssembler.cpp b/libpixelflinger/codeflinger/GGLAssembler.cpp
index 90c275e..1cd189c 100644
--- a/libpixelflinger/codeflinger/GGLAssembler.cpp
+++ b/libpixelflinger/codeflinger/GGLAssembler.cpp
@@ -151,6 +151,7 @@
         // Destination is zero (beware of logic ops)
     }
     
+    int fbComponents = 0;
     const int masking = GGL_READ_NEEDS(MASK_ARGB, needs.n);
     for (int i=0 ; i<4 ; i++) {
         const int mask = 1<<i;
@@ -176,9 +177,14 @@
 
         mBlending |= (info.blend ? mask : 0);
         mMasking |= (mCbFormat.c[i].h && info.masked) ? mask : 0;
+        fbComponents |= mCbFormat.c[i].h ? mask : 0;
     }
 
-
+    mAllMasked = (mMasking == fbComponents);
+    if (mAllMasked) {
+        mDithering = 0;
+    }
+    
     fragment_parts_t parts;
 
     // ------------------------------------------------------------------------
@@ -226,8 +232,10 @@
             build_textures(parts, regs);
         }        
 
-        if ((blending & (FACTOR_DST|BLEND_DST)) || mMasking ||
-                (mLogicOp & LOGIC_OP_DST)) {
+        if ((blending & (FACTOR_DST|BLEND_DST)) || 
+                (mMasking && !mAllMasked) ||
+                (mLogicOp & LOGIC_OP_DST)) 
+        {
             // blending / logic_op / masking need the framebuffer
             mDstPixel.setTo(regs.obtain(), &mCbFormat);
 
@@ -284,14 +292,16 @@
             pixel = mDstPixel;
         }
         
-        // logic operation
-        build_logic_op(pixel, regs);
-
-        // masking
-        build_masking(pixel, regs); 
-
-        comment("store");
-        store(parts.cbPtr, pixel, WRITE_BACK);
+        if (!mAllMasked) {
+            // logic operation
+            build_logic_op(pixel, regs);
+    
+            // masking
+            build_masking(pixel, regs); 
+    
+            comment("store");
+            store(parts.cbPtr, pixel, WRITE_BACK);
+        }
     }
 
     if (registerFile().status())
@@ -322,7 +332,9 @@
         build_smooth_shade(parts);
         build_iterate_z(parts);
         build_iterate_f(parts);
-        ADD(AL, 0, parts.cbPtr.reg, parts.cbPtr.reg, imm(parts.cbPtr.size>>3));
+        if (!mAllMasked) {
+            ADD(AL, 0, parts.cbPtr.reg, parts.cbPtr.reg, imm(parts.cbPtr.size>>3));
+        }
         SUB(AL, S, parts.count.reg, parts.count.reg, imm(1<<16));
         B(PL, "fragment_loop");
         epilog(registerFile().touched());
@@ -370,16 +382,18 @@
         MOV(AL, 0, parts.count.reg, reg_imm(parts.count.reg, LSL, 16));
     }
 
-    // compute dst ptr
-    comment("compute color-buffer pointer");
-    const int cb_bits = mCbFormat.size*8;
-    int Rs = scratches.obtain();
-    parts.cbPtr.setTo(obtainReg(), cb_bits);
-    CONTEXT_LOAD(Rs, state.buffers.color.stride);
-    CONTEXT_LOAD(parts.cbPtr.reg, state.buffers.color.data);
-    SMLABB(AL, Rs, Ry, Rs, Rx);  // Rs = Rx + Ry*Rs
-    base_offset(parts.cbPtr, parts.cbPtr, Rs);
-    scratches.recycle(Rs);
+    if (!mAllMasked) {
+        // compute dst ptr
+        comment("compute color-buffer pointer");
+        const int cb_bits = mCbFormat.size*8;
+        int Rs = scratches.obtain();
+        parts.cbPtr.setTo(obtainReg(), cb_bits);
+        CONTEXT_LOAD(Rs, state.buffers.color.stride);
+        CONTEXT_LOAD(parts.cbPtr.reg, state.buffers.color.data);
+        SMLABB(AL, Rs, Ry, Rs, Rx);  // Rs = Rx + Ry*Rs
+        base_offset(parts.cbPtr, parts.cbPtr, Rs);
+        scratches.recycle(Rs);
+    }
     
     // init fog
     const int need_fog = GGL_READ_NEEDS(P_FOG, needs.p);
@@ -904,8 +918,9 @@
 
 void GGLAssembler::build_masking(pixel_t& pixel, Scratch& regs)
 {
-    if (!mMasking)
+    if (!mMasking || mAllMasked) {
         return;
+    }
 
     comment("color mask");
 
@@ -928,7 +943,7 @@
 
     // There is no need to clear the masked components of the source
     // (unless we applied a logic op), because they're already zeroed 
-    // by contruction (masked components are not computed)
+    // by construction (masked components are not computed)
 
     if (mLogicOp) {
         const needs_t& needs = mBuilderContext.needs;
diff --git a/libpixelflinger/codeflinger/GGLAssembler.h b/libpixelflinger/codeflinger/GGLAssembler.h
index ccaf43d..d1d29f0 100644
--- a/libpixelflinger/codeflinger/GGLAssembler.h
+++ b/libpixelflinger/codeflinger/GGLAssembler.h
@@ -363,6 +363,10 @@
                     const component_t& incoming,
                     const pixel_t& texel, int component, int tmu);
 
+    void    add(  component_t& dest,
+                    const component_t& incoming,
+                    const pixel_t& texel, int component);
+
     // load/store stuff
     void    store(const pointer_t& addr, const pixel_t& src, uint32_t flags=0);
     void    load(const pointer_t& addr, const pixel_t& dest, uint32_t flags=0);
@@ -517,6 +521,7 @@
     component_info_t    mInfo[4];
     int                 mBlending;
     int                 mMasking;
+    int                 mAllMasked;
     int                 mLogicOp;
     int                 mAlphaTest;
     int                 mAA;
diff --git a/libpixelflinger/codeflinger/blending.cpp b/libpixelflinger/codeflinger/blending.cpp
index 6d3b282..f10217b 100644
--- a/libpixelflinger/codeflinger/blending.cpp
+++ b/libpixelflinger/codeflinger/blending.cpp
@@ -50,6 +50,12 @@
         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);
     }
 }
diff --git a/libpixelflinger/codeflinger/load_store.cpp b/libpixelflinger/codeflinger/load_store.cpp
index 514ce07..93c5825 100644
--- a/libpixelflinger/codeflinger/load_store.cpp
+++ b/libpixelflinger/codeflinger/load_store.cpp
@@ -168,7 +168,7 @@
 void GGLAssembler::expand(component_t& d, const component_t& s, int dbits)
 {
     integer_t r(d.reg, 32, d.flags);
-    expand(r, d, dbits);
+    expand(r, s, dbits);
     d = component_t(r);
 }
 
diff --git a/libpixelflinger/codeflinger/texturing.cpp b/libpixelflinger/codeflinger/texturing.cpp
index 269b6c0..90e6584 100644
--- a/libpixelflinger/codeflinger/texturing.cpp
+++ b/libpixelflinger/codeflinger/texturing.cpp
@@ -1000,6 +1000,9 @@
                 case GGL_BLEND:
                     blend(fragment, incoming, texel, component, i);
                     break;
+                case GGL_ADD:
+                    add(fragment, incoming, texel, component);
+                    break;
                 }
             }
         }
@@ -1202,6 +1205,46 @@
     build_blendOneMinusFF(dest, factor, incomingNorm, color);
 }
 
+void GGLAssembler::add(
+        component_t& dest, 
+        const component_t& incoming,
+        const pixel_t& incomingTexel, int component)
+{
+    // RGBA:
+    // Cv = Cf + Ct;
+    Scratch locals(registerFile());
+    
+    component_t incomingTemp(incoming);
+
+    // use "dest" as a temporary for extracting the texel, unless "dest"
+    // overlaps "incoming".
+    integer_t texel(dest.reg, 32, CORRUPTIBLE);
+    if (dest.reg == incomingTemp.reg)
+        texel.reg = locals.obtain();
+    extract(texel, incomingTexel, component);
+
+    if (texel.s < incomingTemp.size()) {
+        expand(texel, texel, incomingTemp.size());
+    } else if (texel.s > incomingTemp.size()) {
+        if (incomingTemp.flags & CORRUPTIBLE) {
+            expand(incomingTemp, incomingTemp, texel.s);
+        } else {
+            incomingTemp.reg = locals.obtain();
+            expand(incomingTemp, incoming, texel.s);
+        }
+    }
+
+    if (incomingTemp.l) {
+        ADD(AL, 0, dest.reg, texel.reg,
+                reg_imm(incomingTemp.reg, LSR, incomingTemp.l));
+    } else {
+        ADD(AL, 0, dest.reg, texel.reg, incomingTemp.reg);
+    }
+    dest.l = 0;
+    dest.h = texel.size();
+    component_sat(dest);
+}
+
 // ----------------------------------------------------------------------------
 
 }; // namespace android
diff --git a/libpixelflinger/format.cpp b/libpixelflinger/format.cpp
index c77eada..cbbd91a 100644
--- a/libpixelflinger/format.cpp
+++ b/libpixelflinger/format.cpp
@@ -21,13 +21,13 @@
 namespace android {
 
 static GGLFormat const gPixelFormatInfos[] =
-{
+{   //          Alpha    Red     Green   Blue
     {  0,  0, {{ 0, 0,   0, 0,   0, 0,   0, 0 }},        0 },   // PIXEL_FORMAT_NONE
     {  4, 32, {{32,24,   8, 0,  16, 8,  24,16 }}, GGL_RGBA },   // PIXEL_FORMAT_RGBA_8888
     {  4, 24, {{ 0, 0,   8, 0,  16, 8,  24,16 }}, GGL_RGB  },   // PIXEL_FORMAT_RGBX_8888
     {  3, 24, {{ 0, 0,   8, 0,  16, 8,  24,16 }}, GGL_RGB  },   // PIXEL_FORMAT_RGB_888
     {  2, 16, {{ 0, 0,  16,11,  11, 5,   5, 0 }}, GGL_RGB  },   // PIXEL_FORMAT_RGB_565
-    {  0,  0, {{ 0, 0,   0, 0,   0, 0,   0, 0 }},        0 },   // PIXEL_FORMAT_NONE
+    {  4, 32, {{32,24,  24,16,  16, 8,   8, 0 }}, GGL_RGBA },   // PIXEL_FORMAT_BGRA_8888
     {  2, 16, {{ 1, 0,  16,11,  11, 6,   6, 1 }}, GGL_RGBA },   // PIXEL_FORMAT_RGBA_5551
     {  2, 16, {{ 4, 0,  16,12,  12, 8,   8, 4 }}, GGL_RGBA },   // PIXEL_FORMAT_RGBA_4444
     {  1,  8, {{ 8, 0,   0, 0,   0, 0,   0, 0 }}, GGL_ALPHA},   // PIXEL_FORMAT_A8
diff --git a/libpixelflinger/scanline.cpp b/libpixelflinger/scanline.cpp
index d24c988..75b668d 100644
--- a/libpixelflinger/scanline.cpp
+++ b/libpixelflinger/scanline.cpp
@@ -55,9 +55,11 @@
 #   define ANDROID_ARM_CODEGEN  0
 #endif
 
-
 #define DEBUG__CODEGEN_ONLY     0
 
+
+#define ASSEMBLY_SCRATCH_SIZE   2048
+
 // ----------------------------------------------------------------------------
 namespace android {
 // ----------------------------------------------------------------------------
@@ -247,7 +249,8 @@
     sp<Assembly> assembly = gCodeCache.lookup(key);
     if (assembly == 0) {
         // create a new assembly region
-        sp<ScanlineAssembly> a = new ScanlineAssembly(c->state.needs, 1024);
+        sp<ScanlineAssembly> a = new ScanlineAssembly(c->state.needs, 
+                ASSEMBLY_SCRATCH_SIZE);
         // initialize our assembler
         GGLAssembler assembler( new ARMAssembler(a) );
         //GGLAssembler assembler(
@@ -676,6 +679,12 @@
                             Cf = ((((1<<st) - factor) * Cf) + Ct*Cc)>>st;
                         }
                         break;
+                    case GGL_ADD:
+                        if (st) {
+                            rescale(Cf, sf, Ct, st);
+                            Cf += Ct;
+                        }
+                        break;
                     }
                 }
             }
@@ -1473,7 +1482,7 @@
     needs.p = p;
     needs.t[0] = t0;
     needs.t[1] = t1;
-    sp<ScanlineAssembly> a(new ScanlineAssembly(needs, 1024));
+    sp<ScanlineAssembly> a(new ScanlineAssembly(needs, ASSEMBLY_SCRATCH_SIZE));
     GGLAssembler assembler( new ARMAssembler(a) );
     int err = assembler.scanline(needs, (context_t*)c);
     if (err != 0) {
diff --git a/libpixelflinger/tests/Android.mk b/libpixelflinger/tests/Android.mk
new file mode 100644
index 0000000..6571161
--- /dev/null
+++ b/libpixelflinger/tests/Android.mk
@@ -0,0 +1 @@
+include $(all-subdir-makefiles)
diff --git a/libpixelflinger/tests/codegen/Android.mk b/libpixelflinger/tests/codegen/Android.mk
new file mode 100644
index 0000000..1bc4214
--- /dev/null
+++ b/libpixelflinger/tests/codegen/Android.mk
@@ -0,0 +1,15 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	codegen.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils \
+    libpixelflinger
+
+LOCAL_MODULE:= test-opengl-codegen
+
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_EXECUTABLE)
diff --git a/libpixelflinger/tests/codegen/codegen.cpp b/libpixelflinger/tests/codegen/codegen.cpp
new file mode 100644
index 0000000..1865888
--- /dev/null
+++ b/libpixelflinger/tests/codegen/codegen.cpp
@@ -0,0 +1,21 @@
+#include <stdio.h>
+#include <stdint.h>
+
+extern "C" void ggl_test_codegen(
+        uint32_t n, uint32_t p, uint32_t t0, uint32_t t1);
+
+
+int main(int argc, char** argv)
+{
+    if (argc != 2) {
+        printf("usage: %s 00000117:03454504_00001501_00000000\n", argv[0]);
+        return 0;
+    }
+    uint32_t n;
+    uint32_t p;
+    uint32_t t0;
+    uint32_t t1;
+    sscanf(argv[1], "%08x:%08x_%08x_%08x", &p, &n, &t0, &t1);
+    ggl_test_codegen(n, p,  t0, t1);
+    return 0;
+}