Precache glyphs at final raster size

The deferred display lists model now allows us to precache glyphs
at their exact size on screen.

This change also removes debug markers when the renderer defers
and reorders display lists. It also adds a flush event marker.

Change-Id: I66ec5216dc12b93ecfdad52a7146b1cfb31fbeb4
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 5befb95..a1cc2e8 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -50,9 +50,9 @@
 Caches::Caches(): Singleton<Caches>(), mExtensions(Extensions::getInstance()), mInitialized(false) {
     init();
     initFont();
-    initExtensions();
     initConstraints();
     initProperties();
+    initExtensions();
 
     mDebugLevel = readDebugLevel();
     ALOGD("Enabling debug mode %d", mDebugLevel);
@@ -103,15 +103,21 @@
 void Caches::initExtensions() {
     if (mExtensions.hasDebugMarker()) {
         eventMark = glInsertEventMarkerEXT;
-        startMark = glPushGroupMarkerEXT;
-        endMark = glPopGroupMarkerEXT;
+        if ((drawDeferDisabled || drawReorderDisabled)) {
+            startMark = glPushGroupMarkerEXT;
+            endMark = glPopGroupMarkerEXT;
+        } else {
+            startMark = startMarkNull;
+            endMark = endMarkNull;
+        }
+
     } else {
         eventMark = eventMarkNull;
         startMark = startMarkNull;
         endMark = endMarkNull;
     }
 
-    if (mExtensions.hasDebugLabel()) {
+    if (mExtensions.hasDebugLabel() && (drawDeferDisabled || drawReorderDisabled)) {
         setLabel = glLabelObjectEXT;
         getLabel = glGetObjectLabelEXT;
     } else {
@@ -164,6 +170,20 @@
         debugStencilClip = kStencilHide;
     }
 
+    if (property_get(PROPERTY_DISABLE_DRAW_DEFER, property, "false")) {
+        drawDeferDisabled = !strcasecmp(property, "true");
+        INIT_LOGD("  Draw defer %s", drawDeferDisabled ? "disabled" : "enabled");
+    } else {
+        INIT_LOGD("  Draw defer enabled");
+    }
+
+    if (property_get(PROPERTY_DISABLE_DRAW_REORDER, property, "false")) {
+        drawReorderDisabled = !strcasecmp(property, "true");
+        INIT_LOGD("  Draw reorder %s", drawReorderDisabled ? "disabled" : "enabled");
+    } else {
+        INIT_LOGD("  Draw reorder enabled");
+    }
+
     return (prevDebugLayersUpdates != debugLayersUpdates) ||
             (prevDebugOverdraw != debugOverdraw) ||
             (prevDebugStencilClip != debugStencilClip);
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index c35ad88..ca699d5 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -240,6 +240,9 @@
     Program* currentProgram;
     bool scissorEnabled;
 
+    bool drawDeferDisabled;
+    bool drawReorderDisabled;
+
     // VBO to draw with
     GLuint meshBuffer;
 
diff --git a/libs/hwui/DeferredDisplayList.cpp b/libs/hwui/DeferredDisplayList.cpp
index 8962964..a4e9950 100644
--- a/libs/hwui/DeferredDisplayList.cpp
+++ b/libs/hwui/DeferredDisplayList.cpp
@@ -146,6 +146,8 @@
     if (isEmpty()) return status; // nothing to flush
 
     DEFER_LOGD("--flushing");
+    renderer.eventMark("Flush");
+
     DrawModifiers restoreDrawModifiers = renderer.getDrawModifiers();
     int restoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
     int opCount = 0;
@@ -166,6 +168,7 @@
     }
 
     DEFER_LOGD("--flushed, drew %d batches (total %d ops)", mBatches.size(), opCount);
+
     renderer.restoreToCount(restoreTo);
     renderer.setDrawModifiers(restoreDrawModifiers);
     clear();
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 9ecfb5a..4a72477 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -147,7 +147,8 @@
 
         if (!renderer.storeDisplayState(state)) {
             // op wasn't quick-rejected, so defer
-            deferredList->add(this, renderer.disallowReorder());
+            deferredList->add(this, renderer.getCaches().drawReorderDisabled);
+            onDrawOpDeferred(renderer);
         }
 
         return DrawGlInfo::kStatusDone;
@@ -156,6 +157,9 @@
     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
             bool caching, int multipliedAlpha) = 0;
 
+    virtual void onDrawOpDeferred(OpenGLRenderer& renderer) {
+    }
+
     // returns true if bounds exist
     virtual bool getLocalBounds(Rect& localBounds) { return false; }
 
@@ -1081,6 +1085,12 @@
         OP_LOG("Draw some text, %d bytes", mBytesCount);
     }
 
+    virtual void onDrawOpDeferred(OpenGLRenderer& renderer) {
+        SkPaint* paint = getPaint(renderer);
+        FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint);
+        fontRenderer.precache(paint, mText, mCount, mat4::identity());
+    }
+
     virtual DeferredDisplayList::OpBatchId getBatchId() {
         return mPaint->getColor() == 0xff000000 ?
                 DeferredDisplayList::kOpBatch_Text :
@@ -1156,6 +1166,19 @@
         mLocalBounds.set(x, mY + metrics.fTop, x + length, mY + metrics.fBottom);
     }
 
+    /*
+     * When this method is invoked the state field  is initialized to have the
+     * final rendering state. We can thus use it to process data as it will be
+     * used at draw time.
+     */
+    virtual void onDrawOpDeferred(OpenGLRenderer& renderer) {
+        SkPaint* paint = getPaint(renderer);
+        FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint);
+        const bool pureTranslate = state.mMatrix.isPureTranslate();
+        fontRenderer.precache(paint, mText, mCount,
+                pureTranslate ? mat4::identity() : state.mMatrix);
+    }
+
     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
             bool caching, int multipliedAlpha) {
         return renderer.drawText(mText, mBytesCount, mCount, mX, mY,
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 16218fa..b011443 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -403,11 +403,7 @@
 
     DrawOp* op = new (alloc()) DrawTextOnPathOp(text, bytesCount, count, path,
             hOffset, vOffset, paint);
-    if (addDrawOp(op)) {
-        // precache if draw operation is visible
-        FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
-        fontRenderer.precache(paint, text, count, mat4::identity());
-    }
+    addDrawOp(op);
     return DrawGlInfo::kStatusDone;
 }
 
@@ -420,11 +416,7 @@
     paint = refPaint(paint);
 
     DrawOp* op = new (alloc()) DrawPosTextOp(text, bytesCount, count, positions, paint);
-    if (addDrawOp(op)) {
-        // precache if draw operation is visible
-        FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
-        fontRenderer.precache(paint, text, count, mat4::identity());
-    }
+    addDrawOp(op);
     return DrawGlInfo::kStatusDone;
 }
 
@@ -439,13 +431,7 @@
     paint = refPaint(paint);
 
     DrawOp* op = new (alloc()) DrawTextOp(text, bytesCount, count, x, y, positions, paint, length);
-    if (addDrawOp(op)) {
-        // precache if draw operation is visible
-        FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
-        const bool pureTranslate = mSnapshot->transform->isPureTranslate();
-        fontRenderer.precache(paint, text, count,
-                pureTranslate ? mat4::identity() : *mSnapshot->transform);
-    }
+    addDrawOp(op);
     return DrawGlInfo::kStatusDone;
 }
 
@@ -515,17 +501,15 @@
     addOpInternal(op);
 }
 
-bool DisplayListRenderer::addDrawOp(DrawOp* op) {
-    bool rejected = false;
+void DisplayListRenderer::addDrawOp(DrawOp* op) {
     Rect localBounds;
     if (op->getLocalBounds(localBounds)) {
-        rejected = quickRejectNoScissor(localBounds.left, localBounds.top,
+        bool rejected = quickRejectNoScissor(localBounds.left, localBounds.top,
                 localBounds.right, localBounds.bottom);
         op->setQuickRejected(rejected);
     }
     mHasDrawOps = true;
     addOpInternal(op);
-    return !rejected;
 }
 
 }; // namespace uirenderer
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index bff3b97..38619bf 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -195,7 +195,7 @@
 
     LinearAllocator& alloc() { return mDisplayListData->allocator; }
     void addStateOp(StateOp* op);
-    bool addDrawOp(DrawOp* op); // returns true if op not rejected
+    void addDrawOp(DrawOp* op);
     void addOpInternal(DisplayListOp* op) {
         insertRestoreToCount();
         insertTranslate();
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 7e9734f..ff6f332 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -122,8 +122,6 @@
     mFirstSnapshot = new Snapshot;
 
     mScissorOptimizationDisabled = false;
-    mDrawDeferDisabled = false;
-    mDrawReorderDisabled = false;
 }
 
 OpenGLRenderer::~OpenGLRenderer() {
@@ -140,20 +138,6 @@
     } else {
         INIT_LOGD("  Scissor optimization enabled");
     }
-
-    if (property_get(PROPERTY_DISABLE_DRAW_DEFER, property, "false")) {
-        mDrawDeferDisabled = !strcasecmp(property, "true");
-        INIT_LOGD("  Draw defer %s", mDrawDeferDisabled ? "disabled" : "enabled");
-    } else {
-        INIT_LOGD("  Draw defer enabled");
-    }
-
-    if (property_get(PROPERTY_DISABLE_DRAW_REORDER, property, "false")) {
-        mDrawReorderDisabled = !strcasecmp(property, "true");
-        INIT_LOGD("  Draw reorder %s", mDrawReorderDisabled ? "disabled" : "enabled");
-    } else {
-        INIT_LOGD("  Draw reorder enabled");
-    }
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -462,6 +446,10 @@
 // Debug
 ///////////////////////////////////////////////////////////////////////////////
 
+void OpenGLRenderer::eventMark(const char* name) const {
+    mCaches.eventMark(0, name);
+}
+
 void OpenGLRenderer::startMark(const char* name) const {
     mCaches.startMark(0, name);
 }
@@ -1815,7 +1803,7 @@
     // All the usual checks and setup operations (quickReject, setupDraw, etc.)
     // will be performed by the display list itself
     if (displayList && displayList->isRenderable()) {
-        if (CC_UNLIKELY(mDrawDeferDisabled)) {
+        if (CC_UNLIKELY(mCaches.drawDeferDisabled)) {
             return displayList->replay(*this, dirty, flags, 0);
         }
 
@@ -2710,7 +2698,7 @@
     setupDrawShaderUniforms(!isPerspective);
     setupDrawTextGammaUniforms();
 
-    const Rect* clip = mSnapshot->hasPerspectiveTransform() ? NULL : mSnapshot->clipRect;
+    const Rect* clip = isPerspective ? NULL : mSnapshot->clipRect;
     Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);
 
     const bool hasActiveLayer = hasLayer();
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index cfad593..1bfd3c0 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -270,8 +270,6 @@
                 (mSnapshot->flags & Snapshot::kFlagFboTarget); // ensure we're not in a layer
     }
 
-    bool disallowReorder() { return mDrawReorderDisabled; }
-
     bool storeDisplayState(DeferredDisplayState& state);
     void restoreDisplayState(const DeferredDisplayState& state);
 
@@ -282,6 +280,10 @@
         return mSnapshot->transform->isSimple();
     }
 
+    Caches& getCaches() {
+        return mCaches;
+    }
+
     /**
      * Sets the alpha on the current snapshot. This alpha value will be modulated
      * with other alpha values when drawing primitives.
@@ -291,6 +293,11 @@
     }
 
     /**
+     * Inserts a named event marker in the stream of GL commands.
+     */
+    void eventMark(const char* name) const;
+
+    /**
      * Inserts a named group marker in the stream of GL commands. This marker
      * can be used by tools to group commands into logical groups. A call to
      * this method must always be followed later on by a call to endMark().
@@ -439,10 +446,6 @@
         return false;
     }
 
-    Caches& getCaches() {
-        return mCaches;
-    }
-
 private:
     /**
      * Discards the content of the framebuffer if supported by the driver.
@@ -957,8 +960,6 @@
     // See PROPERTY_DISABLE_SCISSOR_OPTIMIZATION in
     // Properties.h
     bool mScissorOptimizationDisabled;
-    bool mDrawDeferDisabled;
-    bool mDrawReorderDisabled;
 
     // No-ops start/endTiling when set
     bool mSuppressTiling;
diff --git a/libs/hwui/font/Font.cpp b/libs/hwui/font/Font.cpp
index d48b612..e804644 100644
--- a/libs/hwui/font/Font.cpp
+++ b/libs/hwui/font/Font.cpp
@@ -284,7 +284,8 @@
 
         // Is the glyph still in texture cache?
         if (!cachedGlyph->mIsValid) {
-            const SkGlyph& skiaGlyph = GET_METRICS(paint, textUnit, &mDescription.mLookupTransform);
+            const SkGlyph& skiaGlyph = GET_METRICS(paint, textUnit,
+                    &mDescription.mLookupTransform);
             updateGlyphCache(paint, skiaGlyph, cachedGlyph, precaching);
         }
     } else {