Code drop from //branches/cupcake/...@124589
diff --git a/opengl/libagl/TextureObjectManager.cpp b/opengl/libagl/TextureObjectManager.cpp
index 12fae63..ce31854 100644
--- a/opengl/libagl/TextureObjectManager.cpp
+++ b/opengl/libagl/TextureObjectManager.cpp
@@ -129,7 +129,7 @@
     // so for now, we just loose it.
     memset(crop_rect, 0, sizeof(crop_rect));
 
-    // it would be nice id we could keep the generate_mipmap flag
+    // it would be nice if we could keep the generate_mipmap flag,
     // we would have to generate them right now though.
     generate_mipmap = GL_FALSE;
 
@@ -286,7 +286,7 @@
 
 void EGLSurfaceManager::deleteTextures(GLsizei n, const GLuint *tokens)
 {
-    // free all texures
+    // free all textures
     Mutex::Autolock _l(mLock);
     for (GLsizei i=0 ; i<n ; i++) {
         const GLuint t(*tokens++);
diff --git a/opengl/libagl/array.cpp b/opengl/libagl/array.cpp
index 1f6757d..8fa7566 100644
--- a/opengl/libagl/array.cpp
+++ b/opengl/libagl/array.cpp
@@ -1116,8 +1116,8 @@
     if (enables & GGL_ENABLE_TMUS) { // needs texture transforms
         want |= transform_state_t::TEXTURE;
     }
-    if (c->clipPlanes.enable) { // needs eye coords
-        want |= transform_state_t::MODELVIEW;
+    if (c->clipPlanes.enable || (enables & GGL_ENABLE_FOG)) { 
+        want |= transform_state_t::MODELVIEW; // needs eye coords
     }
     ogles_validate_transform(c, want);
 
diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp
index 854a49e..3e8dca9 100644
--- a/opengl/libagl/egl.cpp
+++ b/opengl/libagl/egl.cpp
@@ -36,6 +36,7 @@
 #include <GLES/egl.h>
 
 #include <pixelflinger/format.h>
+#include <pixelflinger/pixelflinger.h>
 
 #include "context.h"
 #include "state.h"
@@ -57,7 +58,7 @@
 #ifndef HAVE_ANDROID_OS
 namespace gl {
 pthread_key_t gGLKey = -1;
-}; // namspace gl
+}; // namespace gl
 #endif
 
 template<typename T>
@@ -156,7 +157,7 @@
 egl_surface_t::egl_surface_t(EGLDisplay dpy,
         EGLConfig config,
         int32_t depthFormat)
-    : magic(0x31415265), dpy(dpy), config(config), ctx(0)
+    : magic(MAGIC), dpy(dpy), config(config), ctx(0)
 {
     depth.version = sizeof(GGLSurface);
     depth.data = 0;
@@ -240,7 +241,7 @@
 {
     uint32_t flags = nativeWindow->swapBuffers(nativeWindow);
     if (flags & EGL_NATIVES_FLAG_SIZE_CHANGED) {
-        // TODO: we probaly should reset the swap rect here
+        // TODO: we probably should reset the swap rect here
         // if the window size has changed
         //    window->setSwapRectangle(Rect(info.w, info.h));
         if (depth.data) {
@@ -402,12 +403,13 @@
 {
     size_t size = w*h;
     switch (f) {
-    case GGL_PIXEL_FORMAT_RGB_565:      size *= 2; break;
-    case GGL_PIXEL_FORMAT_RGBA_8888:    size *= 4; break;
-    default:
-        LOGE("incompatible pixel format for pbuffer (format=%d)", f);
-        pbuffer.data = 0;
-        break;
+        case GGL_PIXEL_FORMAT_A_8:          size *= 1; break;
+        case GGL_PIXEL_FORMAT_RGB_565:      size *= 2; break;
+        case GGL_PIXEL_FORMAT_RGBA_8888:    size *= 4; break;
+        default:
+            LOGE("incompatible pixel format for pbuffer (format=%d)", f);
+            pbuffer.data = 0;
+            break;
     }
     pbuffer.version = sizeof(GGLSurface);
     pbuffer.width   = w;
@@ -488,28 +490,28 @@
 };
 
 static const extention_map_t gExtentionMap[] = {
-    { "eglSwapRectangleANDROID",            (void(*)())&eglSwapRectangleANDROID },
-    { "glDrawTexsOES",                      (void(*)())&glDrawTexsOES },
-    { "glDrawTexiOES",                      (void(*)())&glDrawTexiOES },
-    { "glDrawTexfOES",                      (void(*)())&glDrawTexfOES },
-    { "glDrawTexxOES",                      (void(*)())&glDrawTexxOES },
-    { "glDrawTexsvOES",                     (void(*)())&glDrawTexsvOES },
-    { "glDrawTexivOES",                     (void(*)())&glDrawTexivOES },
-    { "glDrawTexfvOES",                     (void(*)())&glDrawTexfvOES },
-    { "glDrawTexxvOES",                     (void(*)())&glDrawTexxvOES },
-    { "glQueryMatrixxOES",                  (void(*)())&glQueryMatrixxOES },
-    { "glClipPlanef",                       (void(*)())&glClipPlanef },
-    { "glClipPlanex",                       (void(*)())&glClipPlanex },
-    { "glBindBuffer",                       (void(*)())&glBindBuffer },
-    { "glBufferData",                       (void(*)())&glBufferData },
-    { "glBufferSubData",                    (void(*)())&glBufferSubData },
-    { "glDeleteBuffers",                    (void(*)())&glDeleteBuffers },
-    { "glGenBuffers",                       (void(*)())&glGenBuffers },
+    { "eglSwapRectangleANDROID",    (void(*)())&eglSwapRectangleANDROID },
+    { "glDrawTexsOES",              (void(*)())&glDrawTexsOES },
+    { "glDrawTexiOES",              (void(*)())&glDrawTexiOES },
+    { "glDrawTexfOES",              (void(*)())&glDrawTexfOES },
+    { "glDrawTexxOES",              (void(*)())&glDrawTexxOES },
+    { "glDrawTexsvOES",             (void(*)())&glDrawTexsvOES },
+    { "glDrawTexivOES",             (void(*)())&glDrawTexivOES },
+    { "glDrawTexfvOES",             (void(*)())&glDrawTexfvOES },
+    { "glDrawTexxvOES",             (void(*)())&glDrawTexxvOES },
+    { "glQueryMatrixxOES",          (void(*)())&glQueryMatrixxOES },
+    { "glClipPlanef",               (void(*)())&glClipPlanef },
+    { "glClipPlanex",               (void(*)())&glClipPlanex },
+    { "glBindBuffer",               (void(*)())&glBindBuffer },
+    { "glBufferData",               (void(*)())&glBufferData },
+    { "glBufferSubData",            (void(*)())&glBufferSubData },
+    { "glDeleteBuffers",            (void(*)())&glDeleteBuffers },
+    { "glGenBuffers",               (void(*)())&glGenBuffers },
 };
 
 /* 
  * In the lists below, attributes names MUST be sorted.
- * Additinnaly, all configs must be sorted according to
+ * Additionally, all configs must be sorted according to
  * the EGL specification.
  */
 
@@ -517,9 +519,10 @@
         { EGL_STENCIL_SIZE,               0                                 },
         { EGL_CONFIG_CAVEAT,              EGL_SLOW_CONFIG                   },
         { EGL_LEVEL,                      0                                 },
-        { EGL_MAX_PBUFFER_HEIGHT,         0                                 },
-        { EGL_MAX_PBUFFER_PIXELS,         0                                 },
-        { EGL_MAX_PBUFFER_WIDTH,          0                                 },
+        { EGL_MAX_PBUFFER_HEIGHT,         GGL_MAX_VIEWPORT_DIMS             },
+        { EGL_MAX_PBUFFER_PIXELS,         
+                GGL_MAX_VIEWPORT_DIMS*GGL_MAX_VIEWPORT_DIMS                 },
+        { EGL_MAX_PBUFFER_WIDTH,          GGL_MAX_VIEWPORT_DIMS             },
         { EGL_NATIVE_RENDERABLE,          EGL_TRUE                          },
         { EGL_NATIVE_VISUAL_ID,           0                                 },
         { EGL_NATIVE_VISUAL_TYPE,         GGL_PIXEL_FORMAT_RGB_565          },
@@ -536,49 +539,72 @@
 };
 
 // These configs can override the base attribute list
+// NOTE: when adding a config here, don't forget to update eglCreate*Surface()
 
 static config_pair_t const config_0_attribute_list[] = {
-        { EGL_BUFFER_SIZE,        16 },
-        { EGL_ALPHA_SIZE,          0 },
-        { EGL_BLUE_SIZE,           5 },
-        { EGL_GREEN_SIZE,          6 },
-        { EGL_RED_SIZE,            5 },
-        { EGL_DEPTH_SIZE,          0 },
-        { EGL_CONFIG_ID,           0 },
-        { EGL_SURFACE_TYPE,        EGL_WINDOW_BIT | EGL_PIXMAP_BIT },
+        { EGL_BUFFER_SIZE,     16 },
+        { EGL_ALPHA_SIZE,       0 },
+        { EGL_BLUE_SIZE,        5 },
+        { EGL_GREEN_SIZE,       6 },
+        { EGL_RED_SIZE,         5 },
+        { EGL_DEPTH_SIZE,       0 },
+        { EGL_CONFIG_ID,        0 },
+        { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
 };
 
 static config_pair_t const config_1_attribute_list[] = {
-        { EGL_BUFFER_SIZE,        16 },
-        { EGL_ALPHA_SIZE,          0 },
-        { EGL_BLUE_SIZE,           5 },
-        { EGL_GREEN_SIZE,          6 },
-        { EGL_RED_SIZE,            5 },
-        { EGL_DEPTH_SIZE,         16 },
-        { EGL_CONFIG_ID,           1 },
-        { EGL_SURFACE_TYPE,        EGL_WINDOW_BIT | EGL_PIXMAP_BIT },
+        { EGL_BUFFER_SIZE,     16 },
+        { EGL_ALPHA_SIZE,       0 },
+        { EGL_BLUE_SIZE,        5 },
+        { EGL_GREEN_SIZE,       6 },
+        { EGL_RED_SIZE,         5 },
+        { EGL_DEPTH_SIZE,      16 },
+        { EGL_CONFIG_ID,        1 },
+        { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
 };
 
 static config_pair_t const config_2_attribute_list[] = {
-        { EGL_BUFFER_SIZE,        32 },
-        { EGL_ALPHA_SIZE,          8 },
-        { EGL_BLUE_SIZE,           8 },
-        { EGL_GREEN_SIZE,          8 },
-        { EGL_RED_SIZE,            8 },
-        { EGL_DEPTH_SIZE,          0 },
-        { EGL_CONFIG_ID,           2 },
-        { EGL_SURFACE_TYPE,        EGL_WINDOW_BIT | EGL_PIXMAP_BIT },
+        { EGL_BUFFER_SIZE,     32 },
+        { EGL_ALPHA_SIZE,       8 },
+        { EGL_BLUE_SIZE,        8 },
+        { EGL_GREEN_SIZE,       8 },
+        { EGL_RED_SIZE,         8 },
+        { EGL_DEPTH_SIZE,       0 },
+        { EGL_CONFIG_ID,        2 },
+        { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
 };
 
 static config_pair_t const config_3_attribute_list[] = {
-        { EGL_BUFFER_SIZE,        32 },
-        { EGL_ALPHA_SIZE,          8 },
-        { EGL_BLUE_SIZE,           8 },
-        { EGL_GREEN_SIZE,          8 },
-        { EGL_RED_SIZE,            8 },
-        { EGL_DEPTH_SIZE,         16 },
-        { EGL_CONFIG_ID,           3 },
-        { EGL_SURFACE_TYPE,        EGL_WINDOW_BIT | EGL_PIXMAP_BIT },
+        { EGL_BUFFER_SIZE,     32 },
+        { EGL_ALPHA_SIZE,       8 },
+        { EGL_BLUE_SIZE,        8 },
+        { EGL_GREEN_SIZE,       8 },
+        { EGL_RED_SIZE,         8 },
+        { EGL_DEPTH_SIZE,      16 },
+        { EGL_CONFIG_ID,        3 },
+        { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
+};
+
+static config_pair_t const config_4_attribute_list[] = {
+        { EGL_BUFFER_SIZE,      8 },
+        { EGL_ALPHA_SIZE,       8 },
+        { EGL_BLUE_SIZE,        0 },
+        { EGL_GREEN_SIZE,       0 },
+        { EGL_RED_SIZE,         0 },
+        { EGL_DEPTH_SIZE,       0 },
+        { EGL_CONFIG_ID,        4 },
+        { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
+};
+
+static config_pair_t const config_5_attribute_list[] = {
+        { EGL_BUFFER_SIZE,      8 },
+        { EGL_ALPHA_SIZE,       8 },
+        { EGL_BLUE_SIZE,        0 },
+        { EGL_GREEN_SIZE,       0 },
+        { EGL_RED_SIZE,         0 },
+        { EGL_DEPTH_SIZE,      16 },
+        { EGL_CONFIG_ID,        5 },
+        { EGL_SURFACE_TYPE,     EGL_WINDOW_BIT|EGL_PBUFFER_BIT|EGL_PIXMAP_BIT },
 };
 
 static configs_t const gConfigs[] = {
@@ -586,6 +612,8 @@
         { config_1_attribute_list, NELEM(config_1_attribute_list) },
         { config_2_attribute_list, NELEM(config_2_attribute_list) },
         { config_3_attribute_list, NELEM(config_3_attribute_list) },
+        { config_4_attribute_list, NELEM(config_4_attribute_list) },
+        { config_5_attribute_list, NELEM(config_5_attribute_list) },
 };
 
 static config_management_t const gConfigManagement[] = {
@@ -669,7 +697,7 @@
                 return 1;
             }
         } else {
-            // attribute nont found. this should NEVER happen.
+            // attribute not found. this should NEVER happen.
         }
     } else {
         // error, this attribute doesn't exist
@@ -779,11 +807,19 @@
         pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; 
         depthFormat = GGL_PIXEL_FORMAT_Z_16;
         break;
+    case 4:
+        pixelFormat = GGL_PIXEL_FORMAT_A_8; 
+        depthFormat = 0;
+        break;
+    case 5:
+        pixelFormat = GGL_PIXEL_FORMAT_A_8; 
+        depthFormat = GGL_PIXEL_FORMAT_Z_16;
+        break;
     default:
         return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
     }
 
-    // XXX: we don't have access to the pixelFormat here just yet.
+    // FIXME: we don't have access to the pixelFormat here just yet.
     // (it's possible that the surface is not fully initialized)
     // maybe this should be done after the page-flip
     //if (EGLint(info.format) != pixelFormat)
@@ -840,6 +876,14 @@
         pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; 
         depthFormat = GGL_PIXEL_FORMAT_Z_16;
         break;
+    case 4:
+        pixelFormat = GGL_PIXEL_FORMAT_A_8; 
+        depthFormat = 0;
+        break;
+    case 5:
+        pixelFormat = GGL_PIXEL_FORMAT_A_8; 
+        depthFormat = GGL_PIXEL_FORMAT_Z_16;
+        break;
     default:
         return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
     }
@@ -896,6 +940,14 @@
         pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; 
         depthFormat = GGL_PIXEL_FORMAT_Z_16;
         break;
+    case 4:
+        pixelFormat = GGL_PIXEL_FORMAT_A_8; 
+        depthFormat = 0;
+        break;
+    case 5:
+        pixelFormat = GGL_PIXEL_FORMAT_A_8; 
+        depthFormat = GGL_PIXEL_FORMAT_Z_16;
+        break;
     default:
         return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
     }
@@ -979,7 +1031,7 @@
     EGLBoolean res = EGL_TRUE;
     egl_display_t& d = egl_display_t::get_display(dpy);
     if (android_atomic_dec(&d.initialized) == 1) {
-        // TODO: destroy all resources (surfaces, contextes, etc...)
+        // TODO: destroy all resources (surfaces, contexts, etc...)
         //pthread_mutex_lock(&gInitMutex);
         //pthread_mutex_unlock(&gInitMutex);
     }
@@ -1105,11 +1157,7 @@
 EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
                                     const EGLint *attrib_list)
 {
-    // none of our configs support pbuffers
-    // (in fact it's working but since we can't use them as 
-    // textures yet, it's not useful at all)
-    //createPbufferSurface(dpy, config, attrib_list);
-    return EGL_NO_SURFACE;
+    return createPbufferSurface(dpy, config, attrib_list);
 }
                                     
 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface)
@@ -1231,6 +1279,13 @@
     }
 
     EGLContext current_ctx = EGL_NO_CONTEXT;
+    
+    if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
+        return setError(EGL_BAD_MATCH, EGL_FALSE);
+
+    if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT))
+        return setError(EGL_BAD_MATCH, EGL_FALSE);
+
     if (ctx == EGL_NO_CONTEXT) {
         // if we're detaching, we need the current context
         current_ctx = (EGLContext)getGlThreadSpecific();
@@ -1486,7 +1541,7 @@
 }
 
 // ----------------------------------------------------------------------------
-// Android extentions
+// Android extensions
 // ----------------------------------------------------------------------------
 
 void (*eglGetProcAddress (const char *procname))()
diff --git a/opengl/libagl/light.cpp b/opengl/libagl/light.cpp
index 87725cb..25c41d0 100644
--- a/opengl/libagl/light.cpp
+++ b/opengl/libagl/light.cpp
@@ -117,11 +117,11 @@
 }
 
 static GLfixed fog_linear(ogles_context_t* c, GLfixed z) {
-    return clampF(gglMulx((c->fog.end - z), c->fog.invEndMinusStart));
+    return clampF(gglMulx((c->fog.end - ((z<0)?-z:z)), c->fog.invEndMinusStart));
 }
 
 static GLfixed fog_exp(ogles_context_t* c, GLfixed z) {
-    const float e = fixedToFloat(gglMulx(c->fog.density, z));
+    const float e = fixedToFloat(gglMulx(c->fog.density, ((z<0)?-z:z)));
     return clampF(gglFloatToFixed(fastexpf(-e)));
 }
 
@@ -556,11 +556,11 @@
         ogles_error(c, GL_INVALID_VALUE);
         break;
     case GL_FOG_START:
-        c->fog.start = gglClampx(param);
+        c->fog.start = param;
         c->fog.invEndMinusStart = gglRecip(c->fog.end - c->fog.start);
         break;
     case GL_FOG_END:
-        c->fog.end = gglClampx(param);
+        c->fog.end = param;
         c->fog.invEndMinusStart = gglRecip(c->fog.end - c->fog.start);
         break;
     case GL_FOG_MODE:
diff --git a/opengl/libagl/matrix.cpp b/opengl/libagl/matrix.cpp
index 441da38..f175cda 100644
--- a/opengl/libagl/matrix.cpp
+++ b/opengl/libagl/matrix.cpp
@@ -98,8 +98,9 @@
     c->arrays.perspective = (c->clipPlanes.enable) ?
         ogles_vertex_clipAllPerspective3D : ogles_vertex_perspective3D;
     if (enables & (GGL_ENABLE_DEPTH_TEST|GGL_ENABLE_FOG)) {
-        c->arrays.perspective = (c->clipPlanes.enable) ?
-            ogles_vertex_clipAllPerspective3DZ : ogles_vertex_perspective3DZ;
+        c->arrays.perspective = ogles_vertex_perspective3DZ;
+        if (c->clipPlanes.enable || (enables&GGL_ENABLE_FOG))
+            c->arrays.perspective = ogles_vertex_clipAllPerspective3DZ;
     }
     if ((c->arrays.vertex.size != 4) &&
         (c->transforms.mvp4.flags & transform_t::FLAGS_2D_PROJECTION)) {
diff --git a/opengl/libagl/primitives.cpp b/opengl/libagl/primitives.cpp
index 20e8d37..f164c02 100644
--- a/opengl/libagl/primitives.cpp
+++ b/opengl/libagl/primitives.cpp
@@ -133,7 +133,7 @@
 {
     if (!(v->flags & vertex_t::LIT)) {
         v->flags |= vertex_t::LIT;
-        v->fog = c->fog.fog(c, v->window.z);
+        v->fog = c->fog.fog(c, v->eye.z);
         const GLvoid* cp = c->arrays.color.element(
                 v->index & vertex_cache_t::INDEX_MASK);
         c->arrays.color.fetch(c, v->color.v, cp);
@@ -144,14 +144,14 @@
 {
     if (!(v->flags & vertex_t::LIT)) {
         v->flags |= vertex_t::LIT;
-        v->fog = c->fog.fog(c, v->window.z);
+        v->fog = c->fog.fog(c, v->eye.z);
     }
 }
 static inline
 void lightVertexSmoothFog(ogles_context_t* c, vertex_t* v)
 {
     if (!(v->flags & vertex_t::LIT)) {
-        v->fog = c->fog.fog(c, v->window.z);
+        v->fog = c->fog.fog(c, v->eye.z);
         c->lighting.lightVertex(c, v);
     }
 }
@@ -243,12 +243,20 @@
     m_area = m_dx01*m_dy02 + (-m_dy10)*m_dx20;
 }
 
+void compute_iterators_t::initLine(
+        vertex_t const* v0, vertex_t const* v1)
+{
+    m_dx01 = m_dy02 = v1->window.x - v0->window.x;
+    m_dy10 = m_dx20 = v0->window.y - v1->window.y;
+    m_area = m_dx01*m_dy02 + (-m_dy10)*m_dx20;
+}
+
 void compute_iterators_t::initLerp(vertex_t const* v0, uint32_t enables)
 {
     m_x0 = v0->window.x;
     m_y0 = v0->window.y;
     const GGLcoord area = (m_area + TRI_HALF) >> TRI_FRACTION_BITS;
-    const GGLcoord minArea = 2; // cannot be inversed
+    const GGLcoord minArea = 2; // cannot be inverted
     // triangles with an area smaller than 1.0 are not smooth-shaded
 
     int q=0, s=0, d=0;
@@ -336,6 +344,20 @@
     it[2] = dcdy;
 }
 
+void compute_iterators_t::iterators0032(int64_t* it,
+        int32_t c0, int32_t c1, int32_t c2) const
+{
+    const int s = m_area_scale - 16;
+    int32_t dc01 = (c1 - c0)>>s;
+    int32_t dc02 = (c2 - c0)>>s;
+    // 16.16 x 16.16 == 32.32
+    int64_t dcdx = gglMulii(dc01, m_dy02) + gglMulii(dc02, m_dy10);
+    int64_t dcdy = gglMulii(dc02, m_dx01) + gglMulii(dc01, m_dx20);
+    it[ 0] = (c0<<16) - ((dcdx*m_x0 + dcdy*m_y0)>>4);
+    it[ 1] = dcdx;
+    it[ 2] = dcdy;
+}
+
 #if defined(__arm__) && !defined(__thumb__)
 inline void compute_iterators_t::iterators0032(int32_t* it,
         int32_t c0, int32_t c1, int32_t c2) const
@@ -346,16 +368,11 @@
 void compute_iterators_t::iterators0032(int32_t* it,
         int32_t c0, int32_t c1, int32_t c2) const
 {
-    const int s = m_area_scale - 16;
-    int32_t dc01 = (c1 - c0)>>s;
-    int32_t dc02 = (c2 - c0)>>s;
-    // 16.16 x 16.16 == 32.32
-    int64_t dcdx = gglMulii(dc01, m_dy02) + gglMulii(dc02, m_dy10);
-    int64_t dcdy = gglMulii(dc02, m_dx01) + gglMulii(dc01, m_dx20);
-    int32_t c = (c0<<16) - ((dcdx*m_x0 + dcdy*m_y0)>>4);
-    it[ 0] = c;
-    it[ 1] = dcdx;
-    it[ 2] = dcdy;
+    int64_t it64[3];
+    iterators0032(it, c0, c1, c2);
+    it[0] = it64[0];
+    it[1] = it64[1];
+    it[2] = it64[2];
 }
 #endif
 
@@ -454,7 +471,7 @@
             c->arrays.color.fetch(c, v->color.v, cp);
         }
         if (enables & GGL_ENABLE_FOG) {
-            v->fog = c->fog.fog(c, v->window.z);
+            v->fog = c->fog.fog(c, v->eye.z);
         }
     }
 
@@ -514,22 +531,12 @@
 
 void primitive_line(ogles_context_t* c, vertex_t* v0, vertex_t* v1)
 {
-    // This is a cheezy implementation of line drawing that
-    // uses 2 triangles per line. 
-    // That said, how often line drawing is used?
-
     // get texture coordinates
     fetch_texcoord(c, v0, v1, v1);
 
     // light/shade the vertices first (they're copied below)
     c->lighting.lightTriangle(c, v0, v1, v1);
 
-    vertex_t v[4];
-    v[0] = *v0;
-    v[1] = *v1;
-    v0 = &v[0];
-    v1 = &v[1];
-
     // clip the line if needed
     if (ggl_unlikely((v0->flags | v1->flags) & vertex_t::CLIP_ALL)) {
         unsigned int count = clip_line(c, v0, v1);
@@ -546,8 +553,8 @@
                             GGL_ENABLE_DEPTH_TEST;
 
     if (ggl_unlikely(enables & mask)) {
-        c->lerp.initTriangle(v0, v1, v1);
-        lerp_triangle(c, v0, v1, v1);
+        c->lerp.initLine(v0, v1);
+        lerp_triangle(c, v0, v1, v0);
     }
 
     // render our line
@@ -654,17 +661,26 @@
         const int32_t v0z = clampZ(v0->window.z);
         const int32_t v1z = clampZ(v1->window.z);
         const int32_t v2z = clampZ(v2->window.z);
-        lerp.iterators0032(itz, v0z, v1z, v2z);
         if (ggl_unlikely(c->polygonOffset.enable)) {
+            const int32_t units = (c->polygonOffset.units << 16);
             const GLfixed factor = c->polygonOffset.factor;
-            const GLfixed units = c->polygonOffset.units;
-            int32_t maxDepthSlope = max(abs(itz[1]), abs(itz[2]));
-            int32_t offset = (int64_t(maxDepthSlope)*factor +
-                    (int64_t(units) << 16)) >> 16;
-            itz[0] += offset; // XXX: this can cause overflows
+            if (factor) {
+                int64_t itz64[3];
+                lerp.iterators0032(itz64, v0z, v1z, v2z);
+                int64_t maxDepthSlope = max(itz64[1], itz64[2]);
+                itz[0] = uint32_t(itz64[0]) 
+                        + uint32_t((maxDepthSlope*factor)>>16) + units;
+                itz[1] = uint32_t(itz64[1]);
+                itz[2] = uint32_t(itz64[2]);
+            } else {
+                lerp.iterators0032(itz, v0z, v1z, v2z);
+                itz[0] += units; 
+            }
+        } else {
+            lerp.iterators0032(itz, v0z, v1z, v2z);
         }
         c->rasterizer.procs.zGrad3xv(c, itz);
-    }
+    }    
 
     if (ggl_unlikely(enables & GGL_ENABLE_FOG)) {
         GLfixed itf[3];
@@ -880,11 +896,11 @@
                 vertex_t** output = ovl;
                 unsigned int oc = 0;
                 unsigned int sentinel = 0;
-                // previous vertice, compute distance to the plane
+                // previous vertex, compute distance to the plane
                 vertex_t* s = ivl[ic-1];
                 const vec4_t& equation = c->clipPlanes.plane[plane].equation;
                 GLfixed sd = dot4(equation.v, s->eye.v);
-                // clip each vertice against this plane...
+                // clip each vertex against this plane...
                 for (unsigned int i=0 ; i<ic ; i++) {            
                     vertex_t* p = ivl[i];
                     const GLfixed pd = dot4(equation.v, p->eye.v);
@@ -946,10 +962,10 @@
                 vertex_t** output = ovl;
                 unsigned int oc = 0;
                 unsigned int sentinel = 0;
-                // previous vertice, compute distance to the plane
+                // previous vertex, compute distance to the plane
                 vertex_t* s = ivl[ic-1];
                 GLfixed sd = frustumPlaneDist(plane, s->clip);
-                // clip each vertice against this plane...
+                // clip each vertex against this plane...
                 for (unsigned int i=0 ; i<ic ; i++) {            
                     vertex_t* p = ivl[i];
                     const GLfixed pd = frustumPlaneDist(plane, p->clip);
diff --git a/opengl/libagl/vertex.cpp b/opengl/libagl/vertex.cpp
index 5bcc9dc..dad04d6 100644
--- a/opengl/libagl/vertex.cpp
+++ b/opengl/libagl/vertex.cpp
@@ -99,7 +99,7 @@
     c->arrays.cull &= clip;
 
     if (ggl_likely(!clip)) {
-        // if the vertice is clipped, we don't do the perspective
+        // if the vertex is clipped, we don't do the perspective
         // divide, since we don't need its window coordinates.
         perspective(c, v, enables);
     }