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