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 "DisplayList.h"
     25 #include "DeferredDisplayList.h"
     26 #include "DisplayListLogBuffer.h"
     27 #include "DisplayListOp.h"
     28 #include "DisplayListRenderer.h"
     29 #include "Caches.h"
     30 
     31 namespace android {
     32 namespace uirenderer {
     33 
     34 DisplayListRenderer::DisplayListRenderer():
     35         mCaches(Caches::getInstance()), mDisplayListData(new DisplayListData),
     36         mTranslateX(0.0f), mTranslateY(0.0f), mHasTranslate(false),
     37         mHasDrawOps(false), mFunctorCount(0) {
     38 }
     39 
     40 DisplayListRenderer::~DisplayListRenderer() {
     41     reset();
     42 }
     43 
     44 void DisplayListRenderer::reset() {
     45     mDisplayListData = new DisplayListData();
     46     mCaches.resourceCache.lock();
     47 
     48     for (size_t i = 0; i < mBitmapResources.size(); i++) {
     49         mCaches.resourceCache.decrementRefcountLocked(mBitmapResources.itemAt(i));
     50     }
     51 
     52     for (size_t i = 0; i < mOwnedBitmapResources.size(); i++) {
     53         mCaches.resourceCache.decrementRefcountLocked(mOwnedBitmapResources.itemAt(i));
     54     }
     55 
     56     for (size_t i = 0; i < mFilterResources.size(); i++) {
     57         mCaches.resourceCache.decrementRefcountLocked(mFilterResources.itemAt(i));
     58     }
     59 
     60     for (size_t i = 0; i < mPatchResources.size(); i++) {
     61         mCaches.resourceCache.decrementRefcountLocked(mPatchResources.itemAt(i));
     62     }
     63 
     64     for (size_t i = 0; i < mShaders.size(); i++) {
     65         mCaches.resourceCache.decrementRefcountLocked(mShaders.itemAt(i));
     66     }
     67 
     68     for (size_t i = 0; i < mSourcePaths.size(); i++) {
     69         mCaches.resourceCache.decrementRefcountLocked(mSourcePaths.itemAt(i));
     70     }
     71 
     72     for (size_t i = 0; i < mLayers.size(); i++) {
     73         mCaches.resourceCache.decrementRefcountLocked(mLayers.itemAt(i));
     74     }
     75 
     76     mCaches.resourceCache.unlock();
     77 
     78     mBitmapResources.clear();
     79     mOwnedBitmapResources.clear();
     80     mFilterResources.clear();
     81     mPatchResources.clear();
     82     mSourcePaths.clear();
     83 
     84     mShaders.clear();
     85     mShaderMap.clear();
     86 
     87     mPaints.clear();
     88     mPaintMap.clear();
     89 
     90     mRegions.clear();
     91     mRegionMap.clear();
     92 
     93     mPaths.clear();
     94     mPathMap.clear();
     95 
     96     mMatrices.clear();
     97 
     98     mLayers.clear();
     99 
    100     mHasDrawOps = false;
    101     mFunctorCount = 0;
    102 }
    103 
    104 ///////////////////////////////////////////////////////////////////////////////
    105 // Operations
    106 ///////////////////////////////////////////////////////////////////////////////
    107 
    108 DisplayList* DisplayListRenderer::getDisplayList(DisplayList* displayList) {
    109     if (!displayList) {
    110         displayList = new DisplayList(*this);
    111     } else {
    112         displayList->initFromDisplayListRenderer(*this, true);
    113     }
    114     displayList->setRenderable(mHasDrawOps);
    115     return displayList;
    116 }
    117 
    118 bool DisplayListRenderer::isDeferred() {
    119     return true;
    120 }
    121 
    122 void DisplayListRenderer::setViewport(int width, int height) {
    123     mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1);
    124 
    125     mWidth = width;
    126     mHeight = height;
    127 }
    128 
    129 status_t DisplayListRenderer::prepareDirty(float left, float top,
    130         float right, float bottom, bool opaque) {
    131     mSnapshot = new Snapshot(mFirstSnapshot,
    132             SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
    133     mSaveCount = 1;
    134 
    135     mSnapshot->setClip(0.0f, 0.0f, mWidth, mHeight);
    136     mDirtyClip = opaque;
    137 
    138     mRestoreSaveCount = -1;
    139 
    140     return DrawGlInfo::kStatusDone; // No invalidate needed at record-time
    141 }
    142 
    143 void DisplayListRenderer::finish() {
    144     insertRestoreToCount();
    145     insertTranslate();
    146 }
    147 
    148 void DisplayListRenderer::interrupt() {
    149 }
    150 
    151 void DisplayListRenderer::resume() {
    152 }
    153 
    154 status_t DisplayListRenderer::callDrawGLFunction(Functor *functor, Rect& dirty) {
    155     // Ignore dirty during recording, it matters only when we replay
    156     addDrawOp(new (alloc()) DrawFunctorOp(functor));
    157     mFunctorCount++;
    158     return DrawGlInfo::kStatusDone; // No invalidate needed at record-time
    159 }
    160 
    161 int DisplayListRenderer::save(int flags) {
    162     addStateOp(new (alloc()) SaveOp(flags));
    163     return OpenGLRenderer::save(flags);
    164 }
    165 
    166 void DisplayListRenderer::restore() {
    167     if (mRestoreSaveCount < 0) {
    168         restoreToCount(getSaveCount() - 1);
    169         return;
    170     }
    171 
    172     mRestoreSaveCount--;
    173     insertTranslate();
    174     OpenGLRenderer::restore();
    175 }
    176 
    177 void DisplayListRenderer::restoreToCount(int saveCount) {
    178     mRestoreSaveCount = saveCount;
    179     insertTranslate();
    180     OpenGLRenderer::restoreToCount(saveCount);
    181 }
    182 
    183 int DisplayListRenderer::saveLayer(float left, float top, float right, float bottom,
    184         int alpha, SkXfermode::Mode mode, int flags) {
    185     addStateOp(new (alloc()) SaveLayerOp(left, top, right, bottom, alpha, mode, flags));
    186     return OpenGLRenderer::save(flags);
    187 }
    188 
    189 void DisplayListRenderer::translate(float dx, float dy) {
    190     mHasTranslate = true;
    191     mTranslateX += dx;
    192     mTranslateY += dy;
    193     insertRestoreToCount();
    194     OpenGLRenderer::translate(dx, dy);
    195 }
    196 
    197 void DisplayListRenderer::rotate(float degrees) {
    198     addStateOp(new (alloc()) RotateOp(degrees));
    199     OpenGLRenderer::rotate(degrees);
    200 }
    201 
    202 void DisplayListRenderer::scale(float sx, float sy) {
    203     addStateOp(new (alloc()) ScaleOp(sx, sy));
    204     OpenGLRenderer::scale(sx, sy);
    205 }
    206 
    207 void DisplayListRenderer::skew(float sx, float sy) {
    208     addStateOp(new (alloc()) SkewOp(sx, sy));
    209     OpenGLRenderer::skew(sx, sy);
    210 }
    211 
    212 void DisplayListRenderer::setMatrix(SkMatrix* matrix) {
    213     matrix = refMatrix(matrix);
    214     addStateOp(new (alloc()) SetMatrixOp(matrix));
    215     OpenGLRenderer::setMatrix(matrix);
    216 }
    217 
    218 void DisplayListRenderer::concatMatrix(SkMatrix* matrix) {
    219     matrix = refMatrix(matrix);
    220     addStateOp(new (alloc()) ConcatMatrixOp(matrix));
    221     OpenGLRenderer::concatMatrix(matrix);
    222 }
    223 
    224 bool DisplayListRenderer::clipRect(float left, float top, float right, float bottom,
    225         SkRegion::Op op) {
    226     addStateOp(new (alloc()) ClipRectOp(left, top, right, bottom, op));
    227     return OpenGLRenderer::clipRect(left, top, right, bottom, op);
    228 }
    229 
    230 bool DisplayListRenderer::clipPath(SkPath* path, SkRegion::Op op) {
    231     path = refPath(path);
    232     addStateOp(new (alloc()) ClipPathOp(path, op));
    233     return OpenGLRenderer::clipPath(path, op);
    234 }
    235 
    236 bool DisplayListRenderer::clipRegion(SkRegion* region, SkRegion::Op op) {
    237     region = refRegion(region);
    238     addStateOp(new (alloc()) ClipRegionOp(region, op));
    239     return OpenGLRenderer::clipRegion(region, op);
    240 }
    241 
    242 status_t DisplayListRenderer::drawDisplayList(DisplayList* displayList,
    243         Rect& dirty, int32_t flags) {
    244     // dirty is an out parameter and should not be recorded,
    245     // it matters only when replaying the display list
    246 
    247     // TODO: To be safe, the display list should be ref-counted in the
    248     //       resources cache, but we rely on the caller (UI toolkit) to
    249     //       do the right thing for now
    250 
    251     addDrawOp(new (alloc()) DrawDisplayListOp(displayList, flags));
    252     return DrawGlInfo::kStatusDone;
    253 }
    254 
    255 status_t DisplayListRenderer::drawLayer(Layer* layer, float x, float y) {
    256     layer = refLayer(layer);
    257     addDrawOp(new (alloc()) DrawLayerOp(layer, x, y));
    258     return DrawGlInfo::kStatusDone;
    259 }
    260 
    261 status_t DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint) {
    262     bitmap = refBitmap(bitmap);
    263     paint = refPaint(paint);
    264 
    265     addDrawOp(new (alloc()) DrawBitmapOp(bitmap, left, top, paint));
    266     return DrawGlInfo::kStatusDone;
    267 }
    268 
    269 status_t DisplayListRenderer::drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint) {
    270     bitmap = refBitmap(bitmap);
    271     matrix = refMatrix(matrix);
    272     paint = refPaint(paint);
    273 
    274     addDrawOp(new (alloc()) DrawBitmapMatrixOp(bitmap, matrix, paint));
    275     return DrawGlInfo::kStatusDone;
    276 }
    277 
    278 status_t DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
    279         float srcRight, float srcBottom, float dstLeft, float dstTop,
    280         float dstRight, float dstBottom, SkPaint* paint) {
    281     bitmap = refBitmap(bitmap);
    282     paint = refPaint(paint);
    283 
    284     if (srcLeft == 0 && srcTop == 0 &&
    285             srcRight == bitmap->width() && srcBottom == bitmap->height() &&
    286             (srcBottom - srcTop == dstBottom - dstTop) &&
    287             (srcRight - srcLeft == dstRight - dstLeft)) {
    288         // transform simple rect to rect drawing case into position bitmap ops, since they merge
    289         addDrawOp(new (alloc()) DrawBitmapOp(bitmap, dstLeft, dstTop, paint));
    290         return DrawGlInfo::kStatusDone;
    291     }
    292 
    293     addDrawOp(new (alloc()) DrawBitmapRectOp(bitmap,
    294                     srcLeft, srcTop, srcRight, srcBottom,
    295                     dstLeft, dstTop, dstRight, dstBottom, paint));
    296     return DrawGlInfo::kStatusDone;
    297 }
    298 
    299 status_t DisplayListRenderer::drawBitmapData(SkBitmap* bitmap, float left, float top,
    300         SkPaint* paint) {
    301     bitmap = refBitmapData(bitmap);
    302     paint = refPaint(paint);
    303 
    304     addDrawOp(new (alloc()) DrawBitmapDataOp(bitmap, left, top, paint));
    305     return DrawGlInfo::kStatusDone;
    306 }
    307 
    308 status_t DisplayListRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int meshHeight,
    309         float* vertices, int* colors, SkPaint* paint) {
    310     int count = (meshWidth + 1) * (meshHeight + 1) * 2;
    311     bitmap = refBitmap(bitmap);
    312     vertices = refBuffer<float>(vertices, count);
    313     paint = refPaint(paint);
    314     colors = refBuffer<int>(colors, count);
    315 
    316     addDrawOp(new (alloc()) DrawBitmapMeshOp(bitmap, meshWidth, meshHeight,
    317                     vertices, colors, paint));
    318     return DrawGlInfo::kStatusDone;
    319 }
    320 
    321 status_t DisplayListRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch,
    322         float left, float top, float right, float bottom, SkPaint* paint) {
    323     bitmap = refBitmap(bitmap);
    324     patch = refPatch(patch);
    325     paint = refPaint(paint);
    326 
    327     addDrawOp(new (alloc()) DrawPatchOp(bitmap, patch, left, top, right, bottom, paint));
    328     return DrawGlInfo::kStatusDone;
    329 }
    330 
    331 status_t DisplayListRenderer::drawColor(int color, SkXfermode::Mode mode) {
    332     addDrawOp(new (alloc()) DrawColorOp(color, mode));
    333     return DrawGlInfo::kStatusDone;
    334 }
    335 
    336 status_t DisplayListRenderer::drawRect(float left, float top, float right, float bottom,
    337         SkPaint* paint) {
    338     paint = refPaint(paint);
    339     addDrawOp(new (alloc()) DrawRectOp(left, top, right, bottom, paint));
    340     return DrawGlInfo::kStatusDone;
    341 }
    342 
    343 status_t DisplayListRenderer::drawRoundRect(float left, float top, float right, float bottom,
    344         float rx, float ry, SkPaint* paint) {
    345     paint = refPaint(paint);
    346     addDrawOp(new (alloc()) DrawRoundRectOp(left, top, right, bottom, rx, ry, paint));
    347     return DrawGlInfo::kStatusDone;
    348 }
    349 
    350 status_t DisplayListRenderer::drawCircle(float x, float y, float radius, SkPaint* paint) {
    351     paint = refPaint(paint);
    352     addDrawOp(new (alloc()) DrawCircleOp(x, y, radius, paint));
    353     return DrawGlInfo::kStatusDone;
    354 }
    355 
    356 status_t DisplayListRenderer::drawOval(float left, float top, float right, float bottom,
    357         SkPaint* paint) {
    358     paint = refPaint(paint);
    359     addDrawOp(new (alloc()) DrawOvalOp(left, top, right, bottom, paint));
    360     return DrawGlInfo::kStatusDone;
    361 }
    362 
    363 status_t DisplayListRenderer::drawArc(float left, float top, float right, float bottom,
    364         float startAngle, float sweepAngle, bool useCenter, SkPaint* paint) {
    365     paint = refPaint(paint);
    366     addDrawOp(new (alloc()) DrawArcOp(left, top, right, bottom,
    367                     startAngle, sweepAngle, useCenter, paint));
    368     return DrawGlInfo::kStatusDone;
    369 }
    370 
    371 status_t DisplayListRenderer::drawPath(SkPath* path, SkPaint* paint) {
    372     path = refPath(path);
    373     paint = refPaint(paint);
    374 
    375     addDrawOp(new (alloc()) DrawPathOp(path, paint));
    376     return DrawGlInfo::kStatusDone;
    377 }
    378 
    379 status_t DisplayListRenderer::drawLines(float* points, int count, SkPaint* paint) {
    380     points = refBuffer<float>(points, count);
    381     paint = refPaint(paint);
    382 
    383     addDrawOp(new (alloc()) DrawLinesOp(points, count, paint));
    384     return DrawGlInfo::kStatusDone;
    385 }
    386 
    387 status_t DisplayListRenderer::drawPoints(float* points, int count, SkPaint* paint) {
    388     points = refBuffer<float>(points, count);
    389     paint = refPaint(paint);
    390 
    391     addDrawOp(new (alloc()) DrawPointsOp(points, count, paint));
    392     return DrawGlInfo::kStatusDone;
    393 }
    394 
    395 status_t DisplayListRenderer::drawTextOnPath(const char* text, int bytesCount, int count,
    396         SkPath* path, float hOffset, float vOffset, SkPaint* paint) {
    397     if (!text || count <= 0) return DrawGlInfo::kStatusDone;
    398 
    399     text = refText(text, bytesCount);
    400     path = refPath(path);
    401     paint = refPaint(paint);
    402 
    403     DrawOp* op = new (alloc()) DrawTextOnPathOp(text, bytesCount, count, path,
    404             hOffset, vOffset, paint);
    405     addDrawOp(op);
    406     return DrawGlInfo::kStatusDone;
    407 }
    408 
    409 status_t DisplayListRenderer::drawPosText(const char* text, int bytesCount, int count,
    410         const float* positions, SkPaint* paint) {
    411     if (!text || count <= 0) return DrawGlInfo::kStatusDone;
    412 
    413     text = refText(text, bytesCount);
    414     positions = refBuffer<float>(positions, count * 2);
    415     paint = refPaint(paint);
    416 
    417     DrawOp* op = new (alloc()) DrawPosTextOp(text, bytesCount, count, positions, paint);
    418     addDrawOp(op);
    419     return DrawGlInfo::kStatusDone;
    420 }
    421 
    422 status_t DisplayListRenderer::drawText(const char* text, int bytesCount, int count,
    423         float x, float y, const float* positions, SkPaint* paint,
    424         float totalAdvance, const Rect& bounds, DrawOpMode drawOpMode) {
    425 
    426     if (!text || count <= 0) return DrawGlInfo::kStatusDone;
    427 
    428     text = refText(text, bytesCount);
    429     positions = refBuffer<float>(positions, count * 2);
    430     paint = refPaint(paint);
    431 
    432     DrawOp* op = new (alloc()) DrawTextOp(text, bytesCount, count,
    433             x, y, positions, paint, totalAdvance, bounds);
    434     addDrawOp(op);
    435     return DrawGlInfo::kStatusDone;
    436 }
    437 
    438 status_t DisplayListRenderer::drawRects(const float* rects, int count, SkPaint* paint) {
    439     if (count <= 0) return DrawGlInfo::kStatusDone;
    440 
    441     rects = refBuffer<float>(rects, count);
    442     paint = refPaint(paint);
    443     addDrawOp(new (alloc()) DrawRectsOp(rects, count, paint));
    444     return DrawGlInfo::kStatusDone;
    445 }
    446 
    447 void DisplayListRenderer::resetShader() {
    448     addStateOp(new (alloc()) ResetShaderOp());
    449 }
    450 
    451 void DisplayListRenderer::setupShader(SkiaShader* shader) {
    452     shader = refShader(shader);
    453     addStateOp(new (alloc()) SetupShaderOp(shader));
    454 }
    455 
    456 void DisplayListRenderer::resetColorFilter() {
    457     addStateOp(new (alloc()) ResetColorFilterOp());
    458 }
    459 
    460 void DisplayListRenderer::setupColorFilter(SkiaColorFilter* filter) {
    461     filter = refColorFilter(filter);
    462     addStateOp(new (alloc()) SetupColorFilterOp(filter));
    463 }
    464 
    465 void DisplayListRenderer::resetShadow() {
    466     addStateOp(new (alloc()) ResetShadowOp());
    467     OpenGLRenderer::resetShadow();
    468 }
    469 
    470 void DisplayListRenderer::setupShadow(float radius, float dx, float dy, int color) {
    471     addStateOp(new (alloc()) SetupShadowOp(radius, dx, dy, color));
    472     OpenGLRenderer::setupShadow(radius, dx, dy, color);
    473 }
    474 
    475 void DisplayListRenderer::resetPaintFilter() {
    476     addStateOp(new (alloc()) ResetPaintFilterOp());
    477 }
    478 
    479 void DisplayListRenderer::setupPaintFilter(int clearBits, int setBits) {
    480     addStateOp(new (alloc()) SetupPaintFilterOp(clearBits, setBits));
    481 }
    482 
    483 void DisplayListRenderer::insertRestoreToCount() {
    484     if (mRestoreSaveCount >= 0) {
    485         DisplayListOp* op = new (alloc()) RestoreToCountOp(mRestoreSaveCount);
    486         mDisplayListData->displayListOps.add(op);
    487         mRestoreSaveCount = -1;
    488     }
    489 }
    490 
    491 void DisplayListRenderer::insertTranslate() {
    492     if (mHasTranslate) {
    493         if (mTranslateX != 0.0f || mTranslateY != 0.0f) {
    494             DisplayListOp* op = new (alloc()) TranslateOp(mTranslateX, mTranslateY);
    495             mDisplayListData->displayListOps.add(op);
    496             mTranslateX = mTranslateY = 0.0f;
    497         }
    498         mHasTranslate = false;
    499     }
    500 }
    501 
    502 void DisplayListRenderer::addStateOp(StateOp* op) {
    503     addOpInternal(op);
    504 }
    505 
    506 void DisplayListRenderer::addDrawOp(DrawOp* op) {
    507     Rect localBounds;
    508     if (op->getLocalBounds(mDrawModifiers, localBounds)) {
    509         bool rejected = quickRejectNoScissor(localBounds.left, localBounds.top,
    510                 localBounds.right, localBounds.bottom);
    511         op->setQuickRejected(rejected);
    512     }
    513 
    514     mHasDrawOps = true;
    515     addOpInternal(op);
    516 }
    517 
    518 }; // namespace uirenderer
    519 }; // namespace android
    520