Home | History | Annotate | Download | only in hwui
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define LOG_TAG "OpenGLRenderer"
     18 
     19 #include <SkCamera.h>
     20 #include <SkCanvas.h>
     21 
     22 #include <private/hwui/DrawGlInfo.h>
     23 
     24 #include "ResourceCache.h"
     25 #include "DeferredDisplayList.h"
     26 #include "DeferredLayerUpdater.h"
     27 #include "DisplayListLogBuffer.h"
     28 #include "DisplayListOp.h"
     29 #include "DisplayListRenderer.h"
     30 #include "RenderNode.h"
     31 
     32 namespace android {
     33 namespace uirenderer {
     34 
     35 DisplayListRenderer::DisplayListRenderer()
     36     : mResourceCache(ResourceCache::getInstance())
     37     , mDisplayListData(NULL)
     38     , mTranslateX(0.0f)
     39     , mTranslateY(0.0f)
     40     , mDeferredBarrierType(kBarrier_None)
     41     , mHighContrastText(false)
     42     , mRestoreSaveCount(-1) {
     43 }
     44 
     45 DisplayListRenderer::~DisplayListRenderer() {
     46     LOG_ALWAYS_FATAL_IF(mDisplayListData,
     47             "Destroyed a DisplayListRenderer during a record!");
     48 }
     49 
     50 ///////////////////////////////////////////////////////////////////////////////
     51 // Operations
     52 ///////////////////////////////////////////////////////////////////////////////
     53 
     54 DisplayListData* DisplayListRenderer::finishRecording() {
     55     mPaintMap.clear();
     56     mRegionMap.clear();
     57     mPathMap.clear();
     58     DisplayListData* data = mDisplayListData;
     59     mDisplayListData = 0;
     60     return data;
     61 }
     62 
     63 status_t DisplayListRenderer::prepareDirty(float left, float top,
     64         float right, float bottom, bool opaque) {
     65 
     66     LOG_ALWAYS_FATAL_IF(mDisplayListData,
     67             "prepareDirty called a second time during a recording!");
     68     mDisplayListData = new DisplayListData();
     69 
     70     initializeSaveStack(0, 0, getWidth(), getHeight(), Vector3());
     71 
     72     mDeferredBarrierType = kBarrier_InOrder;
     73     mDirtyClip = opaque;
     74     mRestoreSaveCount = -1;
     75 
     76     return DrawGlInfo::kStatusDone; // No invalidate needed at record-time
     77 }
     78 
     79 void DisplayListRenderer::finish() {
     80     flushRestoreToCount();
     81     flushTranslate();
     82 }
     83 
     84 void DisplayListRenderer::interrupt() {
     85 }
     86 
     87 void DisplayListRenderer::resume() {
     88 }
     89 
     90 status_t DisplayListRenderer::callDrawGLFunction(Functor *functor, Rect& dirty) {
     91     // Ignore dirty during recording, it matters only when we replay
     92     addDrawOp(new (alloc()) DrawFunctorOp(functor));
     93     mDisplayListData->functors.add(functor);
     94     return DrawGlInfo::kStatusDone; // No invalidate needed at record-time
     95 }
     96 
     97 int DisplayListRenderer::save(int flags) {
     98     addStateOp(new (alloc()) SaveOp(flags));
     99     return StatefulBaseRenderer::save(flags);
    100 }
    101 
    102 void DisplayListRenderer::restore() {
    103     if (mRestoreSaveCount < 0) {
    104         restoreToCount(getSaveCount() - 1);
    105         return;
    106     }
    107 
    108     mRestoreSaveCount--;
    109     flushTranslate();
    110     StatefulBaseRenderer::restore();
    111 }
    112 
    113 void DisplayListRenderer::restoreToCount(int saveCount) {
    114     mRestoreSaveCount = saveCount;
    115     flushTranslate();
    116     StatefulBaseRenderer::restoreToCount(saveCount);
    117 }
    118 
    119 int DisplayListRenderer::saveLayer(float left, float top, float right, float bottom,
    120         const SkPaint* paint, int flags) {
    121     // force matrix/clip isolation for layer
    122     flags |= SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag;
    123 
    124     paint = refPaint(paint);
    125     addStateOp(new (alloc()) SaveLayerOp(left, top, right, bottom, paint, flags));
    126     return StatefulBaseRenderer::save(flags);
    127 }
    128 
    129 void DisplayListRenderer::translate(float dx, float dy, float dz) {
    130     // ignore dz, not used at defer time
    131     mHasDeferredTranslate = true;
    132     mTranslateX += dx;
    133     mTranslateY += dy;
    134     flushRestoreToCount();
    135     StatefulBaseRenderer::translate(dx, dy, dz);
    136 }
    137 
    138 void DisplayListRenderer::rotate(float degrees) {
    139     addStateOp(new (alloc()) RotateOp(degrees));
    140     StatefulBaseRenderer::rotate(degrees);
    141 }
    142 
    143 void DisplayListRenderer::scale(float sx, float sy) {
    144     addStateOp(new (alloc()) ScaleOp(sx, sy));
    145     StatefulBaseRenderer::scale(sx, sy);
    146 }
    147 
    148 void DisplayListRenderer::skew(float sx, float sy) {
    149     addStateOp(new (alloc()) SkewOp(sx, sy));
    150     StatefulBaseRenderer::skew(sx, sy);
    151 }
    152 
    153 void DisplayListRenderer::setMatrix(const SkMatrix& matrix) {
    154     addStateOp(new (alloc()) SetMatrixOp(matrix));
    155     StatefulBaseRenderer::setMatrix(matrix);
    156 }
    157 
    158 void DisplayListRenderer::concatMatrix(const SkMatrix& matrix) {
    159     addStateOp(new (alloc()) ConcatMatrixOp(matrix));
    160     StatefulBaseRenderer::concatMatrix(matrix);
    161 }
    162 
    163 bool DisplayListRenderer::clipRect(float left, float top, float right, float bottom,
    164         SkRegion::Op op) {
    165     addStateOp(new (alloc()) ClipRectOp(left, top, right, bottom, op));
    166     return StatefulBaseRenderer::clipRect(left, top, right, bottom, op);
    167 }
    168 
    169 bool DisplayListRenderer::clipPath(const SkPath* path, SkRegion::Op op) {
    170     path = refPath(path);
    171     addStateOp(new (alloc()) ClipPathOp(path, op));
    172     return StatefulBaseRenderer::clipPath(path, op);
    173 }
    174 
    175 bool DisplayListRenderer::clipRegion(const SkRegion* region, SkRegion::Op op) {
    176     region = refRegion(region);
    177     addStateOp(new (alloc()) ClipRegionOp(region, op));
    178     return StatefulBaseRenderer::clipRegion(region, op);
    179 }
    180 
    181 status_t DisplayListRenderer::drawRenderNode(RenderNode* renderNode, Rect& dirty, int32_t flags) {
    182     LOG_ALWAYS_FATAL_IF(!renderNode, "missing rendernode");
    183 
    184     // dirty is an out parameter and should not be recorded,
    185     // it matters only when replaying the display list
    186     DrawRenderNodeOp* op = new (alloc()) DrawRenderNodeOp(renderNode, flags, *currentTransform());
    187     addRenderNodeOp(op);
    188 
    189     return DrawGlInfo::kStatusDone;
    190 }
    191 
    192 status_t DisplayListRenderer::drawLayer(DeferredLayerUpdater* layerHandle, float x, float y) {
    193     // We ref the DeferredLayerUpdater due to its thread-safe ref-counting
    194     // semantics.
    195     mDisplayListData->ref(layerHandle);
    196     addDrawOp(new (alloc()) DrawLayerOp(layerHandle->backingLayer(), x, y));
    197     return DrawGlInfo::kStatusDone;
    198 }
    199 
    200 status_t DisplayListRenderer::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) {
    201     bitmap = refBitmap(bitmap);
    202     paint = refPaint(paint);
    203 
    204     addDrawOp(new (alloc()) DrawBitmapOp(bitmap, paint));
    205     return DrawGlInfo::kStatusDone;
    206 }
    207 
    208 status_t DisplayListRenderer::drawBitmap(const SkBitmap* bitmap, float srcLeft, float srcTop,
    209         float srcRight, float srcBottom, float dstLeft, float dstTop,
    210         float dstRight, float dstBottom, const SkPaint* paint) {
    211     if (srcLeft == 0 && srcTop == 0
    212             && srcRight == bitmap->width() && srcBottom == bitmap->height()
    213             && (srcBottom - srcTop == dstBottom - dstTop)
    214             && (srcRight - srcLeft == dstRight - dstLeft)) {
    215         // transform simple rect to rect drawing case into position bitmap ops, since they merge
    216         save(SkCanvas::kMatrix_SaveFlag);
    217         translate(dstLeft, dstTop);
    218         drawBitmap(bitmap, paint);
    219         restore();
    220     } else {
    221         bitmap = refBitmap(bitmap);
    222         paint = refPaint(paint);
    223 
    224         addDrawOp(new (alloc()) DrawBitmapRectOp(bitmap,
    225                 srcLeft, srcTop, srcRight, srcBottom,
    226                 dstLeft, dstTop, dstRight, dstBottom, paint));
    227     }
    228     return DrawGlInfo::kStatusDone;
    229 }
    230 
    231 status_t DisplayListRenderer::drawBitmapData(const SkBitmap* bitmap, const SkPaint* paint) {
    232     bitmap = refBitmapData(bitmap);
    233     paint = refPaint(paint);
    234 
    235     addDrawOp(new (alloc()) DrawBitmapDataOp(bitmap, paint));
    236     return DrawGlInfo::kStatusDone;
    237 }
    238 
    239 status_t DisplayListRenderer::drawBitmapMesh(const SkBitmap* bitmap, int meshWidth, int meshHeight,
    240         const float* vertices, const int* colors, const SkPaint* paint) {
    241     int vertexCount = (meshWidth + 1) * (meshHeight + 1);
    242     bitmap = refBitmap(bitmap);
    243     vertices = refBuffer<float>(vertices, vertexCount * 2); // 2 floats per vertex
    244     paint = refPaint(paint);
    245     colors = refBuffer<int>(colors, vertexCount); // 1 color per vertex
    246 
    247     addDrawOp(new (alloc()) DrawBitmapMeshOp(bitmap, meshWidth, meshHeight,
    248                     vertices, colors, paint));
    249     return DrawGlInfo::kStatusDone;
    250 }
    251 
    252 status_t DisplayListRenderer::drawPatch(const SkBitmap* bitmap, const Res_png_9patch* patch,
    253         float left, float top, float right, float bottom, const SkPaint* paint) {
    254     bitmap = refBitmap(bitmap);
    255     patch = refPatch(patch);
    256     paint = refPaint(paint);
    257 
    258     addDrawOp(new (alloc()) DrawPatchOp(bitmap, patch, left, top, right, bottom, paint));
    259     return DrawGlInfo::kStatusDone;
    260 }
    261 
    262 status_t DisplayListRenderer::drawColor(int color, SkXfermode::Mode mode) {
    263     addDrawOp(new (alloc()) DrawColorOp(color, mode));
    264     return DrawGlInfo::kStatusDone;
    265 }
    266 
    267 status_t DisplayListRenderer::drawRect(float left, float top, float right, float bottom,
    268         const SkPaint* paint) {
    269     paint = refPaint(paint);
    270     addDrawOp(new (alloc()) DrawRectOp(left, top, right, bottom, paint));
    271     return DrawGlInfo::kStatusDone;
    272 }
    273 
    274 status_t DisplayListRenderer::drawRoundRect(float left, float top, float right, float bottom,
    275         float rx, float ry, const SkPaint* paint) {
    276     paint = refPaint(paint);
    277     addDrawOp(new (alloc()) DrawRoundRectOp(left, top, right, bottom, rx, ry, paint));
    278     return DrawGlInfo::kStatusDone;
    279 }
    280 
    281 status_t DisplayListRenderer::drawRoundRect(
    282         CanvasPropertyPrimitive* left, CanvasPropertyPrimitive* top,
    283         CanvasPropertyPrimitive* right, CanvasPropertyPrimitive* bottom,
    284         CanvasPropertyPrimitive* rx, CanvasPropertyPrimitive* ry,
    285         CanvasPropertyPaint* paint) {
    286     mDisplayListData->ref(left);
    287     mDisplayListData->ref(top);
    288     mDisplayListData->ref(right);
    289     mDisplayListData->ref(bottom);
    290     mDisplayListData->ref(rx);
    291     mDisplayListData->ref(ry);
    292     mDisplayListData->ref(paint);
    293     addDrawOp(new (alloc()) DrawRoundRectPropsOp(&left->value, &top->value,
    294             &right->value, &bottom->value, &rx->value, &ry->value, &paint->value));
    295     return DrawGlInfo::kStatusDone;
    296 }
    297 
    298 status_t DisplayListRenderer::drawCircle(float x, float y, float radius, const SkPaint* paint) {
    299     paint = refPaint(paint);
    300     addDrawOp(new (alloc()) DrawCircleOp(x, y, radius, paint));
    301     return DrawGlInfo::kStatusDone;
    302 }
    303 
    304 status_t DisplayListRenderer::drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
    305         CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint) {
    306     mDisplayListData->ref(x);
    307     mDisplayListData->ref(y);
    308     mDisplayListData->ref(radius);
    309     mDisplayListData->ref(paint);
    310     addDrawOp(new (alloc()) DrawCirclePropsOp(&x->value, &y->value,
    311             &radius->value, &paint->value));
    312     return DrawGlInfo::kStatusDone;
    313 }
    314 
    315 status_t DisplayListRenderer::drawOval(float left, float top, float right, float bottom,
    316         const SkPaint* paint) {
    317     paint = refPaint(paint);
    318     addDrawOp(new (alloc()) DrawOvalOp(left, top, right, bottom, paint));
    319     return DrawGlInfo::kStatusDone;
    320 }
    321 
    322 status_t DisplayListRenderer::drawArc(float left, float top, float right, float bottom,
    323         float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint) {
    324     if (fabs(sweepAngle) >= 360.0f) {
    325         return drawOval(left, top, right, bottom, paint);
    326     }
    327 
    328     paint = refPaint(paint);
    329     addDrawOp(new (alloc()) DrawArcOp(left, top, right, bottom,
    330                     startAngle, sweepAngle, useCenter, paint));
    331     return DrawGlInfo::kStatusDone;
    332 }
    333 
    334 status_t DisplayListRenderer::drawPath(const SkPath* path, const SkPaint* paint) {
    335     path = refPath(path);
    336     paint = refPaint(paint);
    337 
    338     addDrawOp(new (alloc()) DrawPathOp(path, paint));
    339     return DrawGlInfo::kStatusDone;
    340 }
    341 
    342 status_t DisplayListRenderer::drawLines(const float* points, int count, const SkPaint* paint) {
    343     points = refBuffer<float>(points, count);
    344     paint = refPaint(paint);
    345 
    346     addDrawOp(new (alloc()) DrawLinesOp(points, count, paint));
    347     return DrawGlInfo::kStatusDone;
    348 }
    349 
    350 status_t DisplayListRenderer::drawPoints(const float* points, int count, const SkPaint* paint) {
    351     points = refBuffer<float>(points, count);
    352     paint = refPaint(paint);
    353 
    354     addDrawOp(new (alloc()) DrawPointsOp(points, count, paint));
    355     return DrawGlInfo::kStatusDone;
    356 }
    357 
    358 status_t DisplayListRenderer::drawTextOnPath(const char* text, int bytesCount, int count,
    359         const SkPath* path, float hOffset, float vOffset, const SkPaint* paint) {
    360     if (!text || count <= 0) return DrawGlInfo::kStatusDone;
    361 
    362     text = refText(text, bytesCount);
    363     path = refPath(path);
    364     paint = refPaint(paint);
    365 
    366     DrawOp* op = new (alloc()) DrawTextOnPathOp(text, bytesCount, count, path,
    367             hOffset, vOffset, paint);
    368     addDrawOp(op);
    369     return DrawGlInfo::kStatusDone;
    370 }
    371 
    372 status_t DisplayListRenderer::drawPosText(const char* text, int bytesCount, int count,
    373         const float* positions, const SkPaint* paint) {
    374     if (!text || count <= 0) return DrawGlInfo::kStatusDone;
    375 
    376     text = refText(text, bytesCount);
    377     positions = refBuffer<float>(positions, count * 2);
    378     paint = refPaint(paint);
    379 
    380     DrawOp* op = new (alloc()) DrawPosTextOp(text, bytesCount, count, positions, paint);
    381     addDrawOp(op);
    382     return DrawGlInfo::kStatusDone;
    383 }
    384 
    385 static void simplifyPaint(int color, SkPaint* paint) {
    386     paint->setColor(color);
    387     paint->setShader(NULL);
    388     paint->setColorFilter(NULL);
    389     paint->setLooper(NULL);
    390     paint->setStrokeWidth(4 + 0.04 * paint->getTextSize());
    391     paint->setStrokeJoin(SkPaint::kRound_Join);
    392     paint->setLooper(NULL);
    393 }
    394 
    395 status_t DisplayListRenderer::drawText(const char* text, int bytesCount, int count,
    396         float x, float y, const float* positions, const SkPaint* paint,
    397         float totalAdvance, const Rect& bounds, DrawOpMode drawOpMode) {
    398 
    399     if (!text || count <= 0 || paintWillNotDrawText(*paint)) return DrawGlInfo::kStatusDone;
    400 
    401     text = refText(text, bytesCount);
    402     positions = refBuffer<float>(positions, count * 2);
    403 
    404     if (CC_UNLIKELY(mHighContrastText)) {
    405         // high contrast draw path
    406         int color = paint->getColor();
    407         int channelSum = SkColorGetR(color) + SkColorGetG(color) + SkColorGetB(color);
    408         bool darken = channelSum < (128 * 3);
    409 
    410         // outline
    411         SkPaint* outlinePaint = copyPaint(paint);
    412         simplifyPaint(darken ? SK_ColorWHITE : SK_ColorBLACK, outlinePaint);
    413         outlinePaint->setStyle(SkPaint::kStrokeAndFill_Style);
    414         addDrawOp(new (alloc()) DrawTextOp(text, bytesCount, count,
    415                 x, y, positions, outlinePaint, totalAdvance, bounds)); // bounds?
    416 
    417         // inner
    418         SkPaint* innerPaint = copyPaint(paint);
    419         simplifyPaint(darken ? SK_ColorBLACK : SK_ColorWHITE, innerPaint);
    420         innerPaint->setStyle(SkPaint::kFill_Style);
    421         addDrawOp(new (alloc()) DrawTextOp(text, bytesCount, count,
    422                 x, y, positions, innerPaint, totalAdvance, bounds));
    423     } else {
    424         // standard draw path
    425         paint = refPaint(paint);
    426 
    427         DrawOp* op = new (alloc()) DrawTextOp(text, bytesCount, count,
    428                 x, y, positions, paint, totalAdvance, bounds);
    429         addDrawOp(op);
    430     }
    431     return DrawGlInfo::kStatusDone;
    432 }
    433 
    434 status_t DisplayListRenderer::drawRects(const float* rects, int count, const SkPaint* paint) {
    435     if (count <= 0) return DrawGlInfo::kStatusDone;
    436 
    437     rects = refBuffer<float>(rects, count);
    438     paint = refPaint(paint);
    439     addDrawOp(new (alloc()) DrawRectsOp(rects, count, paint));
    440     return DrawGlInfo::kStatusDone;
    441 }
    442 
    443 void DisplayListRenderer::resetPaintFilter() {
    444     addStateOp(new (alloc()) ResetPaintFilterOp());
    445 }
    446 
    447 void DisplayListRenderer::setupPaintFilter(int clearBits, int setBits) {
    448     addStateOp(new (alloc()) SetupPaintFilterOp(clearBits, setBits));
    449 }
    450 
    451 void DisplayListRenderer::insertReorderBarrier(bool enableReorder) {
    452     flushRestoreToCount();
    453     flushTranslate();
    454     mDeferredBarrierType = enableReorder ? kBarrier_OutOfOrder : kBarrier_InOrder;
    455 }
    456 
    457 void DisplayListRenderer::flushRestoreToCount() {
    458     if (mRestoreSaveCount >= 0) {
    459         addOpAndUpdateChunk(new (alloc()) RestoreToCountOp(mRestoreSaveCount));
    460         mRestoreSaveCount = -1;
    461     }
    462 }
    463 
    464 void DisplayListRenderer::flushTranslate() {
    465     if (mHasDeferredTranslate) {
    466         if (mTranslateX != 0.0f || mTranslateY != 0.0f) {
    467             addOpAndUpdateChunk(new (alloc()) TranslateOp(mTranslateX, mTranslateY));
    468             mTranslateX = mTranslateY = 0.0f;
    469         }
    470         mHasDeferredTranslate = false;
    471     }
    472 }
    473 
    474 size_t DisplayListRenderer::addOpAndUpdateChunk(DisplayListOp* op) {
    475     int insertIndex = mDisplayListData->displayListOps.add(op);
    476     if (mDeferredBarrierType != kBarrier_None) {
    477         // op is first in new chunk
    478         mDisplayListData->chunks.push();
    479         DisplayListData::Chunk& newChunk = mDisplayListData->chunks.editTop();
    480         newChunk.beginOpIndex = insertIndex;
    481         newChunk.endOpIndex = insertIndex + 1;
    482         newChunk.reorderChildren = (mDeferredBarrierType == kBarrier_OutOfOrder);
    483 
    484         int nextChildIndex = mDisplayListData->children().size();
    485         newChunk.beginChildIndex = newChunk.endChildIndex = nextChildIndex;
    486         mDeferredBarrierType = kBarrier_None;
    487     } else {
    488         // standard case - append to existing chunk
    489         mDisplayListData->chunks.editTop().endOpIndex = insertIndex + 1;
    490     }
    491     return insertIndex;
    492 }
    493 
    494 size_t DisplayListRenderer::flushAndAddOp(DisplayListOp* op) {
    495     flushRestoreToCount();
    496     flushTranslate();
    497     return addOpAndUpdateChunk(op);
    498 }
    499 
    500 size_t DisplayListRenderer::addStateOp(StateOp* op) {
    501     return flushAndAddOp(op);
    502 }
    503 
    504 size_t DisplayListRenderer::addDrawOp(DrawOp* op) {
    505     Rect localBounds;
    506     if (op->getLocalBounds(localBounds)) {
    507         bool rejected = quickRejectConservative(localBounds.left, localBounds.top,
    508                 localBounds.right, localBounds.bottom);
    509         op->setQuickRejected(rejected);
    510     }
    511 
    512     mDisplayListData->hasDrawOps = true;
    513     return flushAndAddOp(op);
    514 }
    515 
    516 size_t DisplayListRenderer::addRenderNodeOp(DrawRenderNodeOp* op) {
    517     int opIndex = addDrawOp(op);
    518     int childIndex = mDisplayListData->addChild(op);
    519 
    520     // update the chunk's child indices
    521     DisplayListData::Chunk& chunk = mDisplayListData->chunks.editTop();
    522     chunk.endChildIndex = childIndex + 1;
    523 
    524     if (op->renderNode()->stagingProperties().isProjectionReceiver()) {
    525         // use staging property, since recording on UI thread
    526         mDisplayListData->projectionReceiveIndex = opIndex;
    527     }
    528     return opIndex;
    529 }
    530 
    531 }; // namespace uirenderer
    532 }; // namespace android
    533