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