DisplayList.h revision bb615a6ffbc8a051007163916f1ed085d10b5327
1/* 2 * Copyright (C) 2013 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#ifndef ANDROID_HWUI_DISPLAY_LIST_H 18#define ANDROID_HWUI_DISPLAY_LIST_H 19 20#ifndef LOG_TAG 21 #define LOG_TAG "OpenGLRenderer" 22#endif 23 24#include <SkCamera.h> 25#include <SkMatrix.h> 26 27#include <private/hwui/DrawGlInfo.h> 28 29#include <utils/KeyedVector.h> 30#include <utils/LinearAllocator.h> 31#include <utils/RefBase.h> 32#include <utils/SortedVector.h> 33#include <utils/String8.h> 34#include <utils/Vector.h> 35 36#include <cutils/compiler.h> 37 38#include <androidfw/ResourceTypes.h> 39 40#include "Debug.h" 41#include "Matrix.h" 42#include "DeferredDisplayList.h" 43 44#define TRANSLATION 0x0001 45#define ROTATION 0x0002 46#define ROTATION_3D 0x0004 47#define SCALE 0x0008 48#define PIVOT 0x0010 49 50class SkBitmap; 51class SkPaint; 52class SkPath; 53class SkRegion; 54 55namespace android { 56namespace uirenderer { 57 58class DeferredDisplayList; 59class DisplayListOp; 60class DisplayListRenderer; 61class OpenGLRenderer; 62class Rect; 63class Layer; 64class SkiaColorFilter; 65class SkiaShader; 66 67class ClipRectOp; 68class SaveLayerOp; 69class SaveOp; 70class RestoreToCountOp; 71class DrawDisplayListOp; 72 73/** 74 * Holds data used in the playback a tree of DisplayLists. 75 */ 76class PlaybackStateStruct { 77protected: 78 PlaybackStateStruct(OpenGLRenderer& renderer, int replayFlags, LinearAllocator* allocator) 79 : mRenderer(renderer), mReplayFlags(replayFlags), mAllocator(allocator), mRoot(NULL) {} 80 81public: 82 OpenGLRenderer& mRenderer; 83 const int mReplayFlags; 84 85 // Allocator with the lifetime of a single frame. 86 // replay uses an Allocator owned by the struct, while defer shares the DeferredDisplayList's Allocator 87 LinearAllocator * const mAllocator; 88 const DisplayList* mRoot; // TEMPORARY, for debug logging only 89}; 90 91class DeferStateStruct : public PlaybackStateStruct { 92public: 93 DeferStateStruct(DeferredDisplayList& deferredList, OpenGLRenderer& renderer, int replayFlags) 94 : PlaybackStateStruct(renderer, replayFlags, &(deferredList.mAllocator)), 95 mDeferredList(deferredList) {} 96 97 DeferredDisplayList& mDeferredList; 98}; 99 100class ReplayStateStruct : public PlaybackStateStruct { 101public: 102 ReplayStateStruct(OpenGLRenderer& renderer, Rect& dirty, int replayFlags) 103 : PlaybackStateStruct(renderer, replayFlags, &mReplayAllocator), 104 mDirty(dirty), mDrawGlStatus(DrawGlInfo::kStatusDone) {} 105 106 Rect& mDirty; 107 status_t mDrawGlStatus; 108 LinearAllocator mReplayAllocator; 109}; 110 111/** 112 * Refcounted structure that holds the list of commands used in display list stream. 113 */ 114class DisplayListData : public LightRefBase<DisplayListData> { 115public: 116 DisplayListData() : projectionIndex(-1) {} 117 // allocator into which all ops were allocated 118 LinearAllocator allocator; 119 120 // pointers to all ops within display list, pointing into allocator data 121 Vector<DisplayListOp*> displayListOps; 122 123 // list of children display lists for quick, non-drawing traversal 124 Vector<DrawDisplayListOp*> children; 125 126 // index of DisplayListOp restore, after which projected descendents should be drawn 127 int projectionIndex; 128 Matrix4 projectionTransform; 129}; 130 131/** 132 * Primary class for storing recorded canvas commands, as well as per-View/ViewGroup display properties. 133 * 134 * Recording of canvas commands is somewhat similar to SkPicture, except the canvas-recording 135 * functionality is split between DisplayListRenderer (which manages the recording), DisplayListData 136 * (which holds the actual data), and DisplayList (which holds properties and performs playback onto 137 * a renderer). 138 * 139 * Note that DisplayListData is swapped out from beneath an individual DisplayList when a view's 140 * recorded stream of canvas operations is refreshed. The DisplayList (and its properties) stay 141 * attached. 142 */ 143class DisplayList { 144public: 145 DisplayList(const DisplayListRenderer& recorder); 146 ANDROID_API ~DisplayList(); 147 148 // See flags defined in DisplayList.java 149 enum ReplayFlag { 150 kReplayFlag_ClipChildren = 0x1 151 }; 152 153 ANDROID_API size_t getSize(); 154 ANDROID_API static void destroyDisplayListDeferred(DisplayList* displayList); 155 ANDROID_API static void outputLogBuffer(int fd); 156 157 void initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing = false); 158 159 void computeOrdering(); 160 void defer(DeferStateStruct& deferStruct, const int level); 161 void replay(ReplayStateStruct& replayStruct, const int level); 162 163 ANDROID_API void output(uint32_t level = 1); 164 165 ANDROID_API void reset(); 166 167 void setRenderable(bool renderable) { 168 mIsRenderable = renderable; 169 } 170 171 bool isRenderable() const { 172 return mIsRenderable; 173 } 174 175 void setName(const char* name) { 176 if (name) { 177 char* lastPeriod = strrchr(name, '.'); 178 if (lastPeriod) { 179 mName.setTo(lastPeriod + 1); 180 } else { 181 mName.setTo(name); 182 } 183 } 184 } 185 186 const char* getName() const { 187 return mName.string(); 188 } 189 190 void setClipToBounds(bool clipToBounds) { 191 mClipToBounds = clipToBounds; 192 } 193 194 void setIsContainedVolume(bool isContainedVolume) { 195 mIsContainedVolume = isContainedVolume; 196 } 197 198 void setProjectToContainedVolume(bool shouldProject) { 199 if (!mProjectToContainedVolume && shouldProject) { 200 ALOGD("DL %s(%p) marked for projection", getName(), this); 201 } 202 mProjectToContainedVolume = shouldProject; 203 } 204 205 void setStaticMatrix(SkMatrix* matrix) { 206 delete mStaticMatrix; 207 mStaticMatrix = new SkMatrix(*matrix); 208 } 209 210 // Can return NULL 211 SkMatrix* getStaticMatrix() { 212 return mStaticMatrix; 213 } 214 215 void setAnimationMatrix(SkMatrix* matrix) { 216 delete mAnimationMatrix; 217 if (matrix) { 218 mAnimationMatrix = new SkMatrix(*matrix); 219 } else { 220 mAnimationMatrix = NULL; 221 } 222 } 223 224 void setAlpha(float alpha) { 225 alpha = fminf(1.0f, fmaxf(0.0f, alpha)); 226 if (alpha != mAlpha) { 227 mAlpha = alpha; 228 } 229 } 230 231 float getAlpha() const { 232 return mAlpha; 233 } 234 235 void setHasOverlappingRendering(bool hasOverlappingRendering) { 236 mHasOverlappingRendering = hasOverlappingRendering; 237 } 238 239 bool hasOverlappingRendering() const { 240 return mHasOverlappingRendering; 241 } 242 243 void setTranslationX(float translationX) { 244 if (translationX != mTranslationX) { 245 mTranslationX = translationX; 246 onTranslationUpdate(); 247 } 248 } 249 250 float getTranslationX() const { 251 return mTranslationX; 252 } 253 254 void setTranslationY(float translationY) { 255 if (translationY != mTranslationY) { 256 mTranslationY = translationY; 257 onTranslationUpdate(); 258 } 259 } 260 261 float getTranslationY() const { 262 return mTranslationY; 263 } 264 265 void setTranslationZ(float translationZ) { 266 if (translationZ != mTranslationZ) { 267 if (mTranslationZ == 0.0f) { 268 ALOGD("DL %s(%p) marked for 3d compositing", getName(), this); 269 } 270 mTranslationZ = translationZ; 271 onTranslationUpdate(); 272 } 273 } 274 275 float getTranslationZ() const { 276 return mTranslationZ; 277 } 278 279 void setRotation(float rotation) { 280 if (rotation != mRotation) { 281 mRotation = rotation; 282 mMatrixDirty = true; 283 if (mRotation == 0.0f) { 284 mMatrixFlags &= ~ROTATION; 285 } else { 286 mMatrixFlags |= ROTATION; 287 } 288 } 289 } 290 291 float getRotation() const { 292 return mRotation; 293 } 294 295 void setRotationX(float rotationX) { 296 if (rotationX != mRotationX) { 297 mRotationX = rotationX; 298 mMatrixDirty = true; 299 if (mRotationX == 0.0f && mRotationY == 0.0f) { 300 mMatrixFlags &= ~ROTATION_3D; 301 } else { 302 mMatrixFlags |= ROTATION_3D; 303 } 304 } 305 } 306 307 float getRotationX() const { 308 return mRotationX; 309 } 310 311 void setRotationY(float rotationY) { 312 if (rotationY != mRotationY) { 313 mRotationY = rotationY; 314 mMatrixDirty = true; 315 if (mRotationX == 0.0f && mRotationY == 0.0f) { 316 mMatrixFlags &= ~ROTATION_3D; 317 } else { 318 mMatrixFlags |= ROTATION_3D; 319 } 320 } 321 } 322 323 float getRotationY() const { 324 return mRotationY; 325 } 326 327 void setScaleX(float scaleX) { 328 if (scaleX != mScaleX) { 329 mScaleX = scaleX; 330 mMatrixDirty = true; 331 if (mScaleX == 1.0f && mScaleY == 1.0f) { 332 mMatrixFlags &= ~SCALE; 333 } else { 334 mMatrixFlags |= SCALE; 335 } 336 } 337 } 338 339 float getScaleX() const { 340 return mScaleX; 341 } 342 343 void setScaleY(float scaleY) { 344 if (scaleY != mScaleY) { 345 mScaleY = scaleY; 346 mMatrixDirty = true; 347 if (mScaleX == 1.0f && mScaleY == 1.0f) { 348 mMatrixFlags &= ~SCALE; 349 } else { 350 mMatrixFlags |= SCALE; 351 } 352 } 353 } 354 355 float getScaleY() const { 356 return mScaleY; 357 } 358 359 void setPivotX(float pivotX) { 360 mPivotX = pivotX; 361 mMatrixDirty = true; 362 if (mPivotX == 0.0f && mPivotY == 0.0f) { 363 mMatrixFlags &= ~PIVOT; 364 } else { 365 mMatrixFlags |= PIVOT; 366 } 367 mPivotExplicitlySet = true; 368 } 369 370 ANDROID_API float getPivotX(); 371 372 void setPivotY(float pivotY) { 373 mPivotY = pivotY; 374 mMatrixDirty = true; 375 if (mPivotX == 0.0f && mPivotY == 0.0f) { 376 mMatrixFlags &= ~PIVOT; 377 } else { 378 mMatrixFlags |= PIVOT; 379 } 380 mPivotExplicitlySet = true; 381 } 382 383 ANDROID_API float getPivotY(); 384 385 void setCameraDistance(float distance) { 386 if (distance != mCameraDistance) { 387 mCameraDistance = distance; 388 mMatrixDirty = true; 389 if (!mTransformCamera) { 390 mTransformCamera = new Sk3DView(); 391 mTransformMatrix3D = new SkMatrix(); 392 } 393 mTransformCamera->setCameraLocation(0, 0, distance); 394 } 395 } 396 397 float getCameraDistance() const { 398 return mCameraDistance; 399 } 400 401 void setLeft(int left) { 402 if (left != mLeft) { 403 mLeft = left; 404 mWidth = mRight - mLeft; 405 if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) { 406 mMatrixDirty = true; 407 } 408 } 409 } 410 411 float getLeft() const { 412 return mLeft; 413 } 414 415 void setTop(int top) { 416 if (top != mTop) { 417 mTop = top; 418 mHeight = mBottom - mTop; 419 if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) { 420 mMatrixDirty = true; 421 } 422 } 423 } 424 425 float getTop() const { 426 return mTop; 427 } 428 429 void setRight(int right) { 430 if (right != mRight) { 431 mRight = right; 432 mWidth = mRight - mLeft; 433 if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) { 434 mMatrixDirty = true; 435 } 436 } 437 } 438 439 float getRight() const { 440 return mRight; 441 } 442 443 void setBottom(int bottom) { 444 if (bottom != mBottom) { 445 mBottom = bottom; 446 mHeight = mBottom - mTop; 447 if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) { 448 mMatrixDirty = true; 449 } 450 } 451 } 452 453 float getBottom() const { 454 return mBottom; 455 } 456 457 void setLeftTop(int left, int top) { 458 if (left != mLeft || top != mTop) { 459 mLeft = left; 460 mTop = top; 461 mWidth = mRight - mLeft; 462 mHeight = mBottom - mTop; 463 if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) { 464 mMatrixDirty = true; 465 } 466 } 467 } 468 469 void setLeftTopRightBottom(int left, int top, int right, int bottom) { 470 if (left != mLeft || top != mTop || right != mRight || bottom != mBottom) { 471 mLeft = left; 472 mTop = top; 473 mRight = right; 474 mBottom = bottom; 475 mWidth = mRight - mLeft; 476 mHeight = mBottom - mTop; 477 if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) { 478 mMatrixDirty = true; 479 } 480 } 481 } 482 483 void offsetLeftRight(float offset) { 484 if (offset != 0) { 485 mLeft += offset; 486 mRight += offset; 487 if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) { 488 mMatrixDirty = true; 489 } 490 } 491 } 492 493 void offsetTopBottom(float offset) { 494 if (offset != 0) { 495 mTop += offset; 496 mBottom += offset; 497 if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) { 498 mMatrixDirty = true; 499 } 500 } 501 } 502 503 void setCaching(bool caching) { 504 mCaching = caching; 505 } 506 507 int getWidth() { 508 return mWidth; 509 } 510 511 int getHeight() { 512 return mHeight; 513 } 514 515private: 516 typedef key_value_pair_t<float, DrawDisplayListOp*> ZDrawDisplayListOpPair; 517 518 enum ChildrenSelectMode { 519 kNegativeZChildren, 520 kPositiveZChildren 521 }; 522 523 void onTranslationUpdate() { 524 mMatrixDirty = true; 525 if (mTranslationX == 0.0f && mTranslationY == 0.0f && mTranslationZ == 0.0f) { 526 mMatrixFlags &= ~TRANSLATION; 527 } else { 528 mMatrixFlags |= TRANSLATION; 529 } 530 } 531 532 void outputViewProperties(const int level); 533 534 void applyViewPropertyTransforms(mat4& matrix); 535 536 void computeOrderingImpl(DrawDisplayListOp* opState, 537 Vector<ZDrawDisplayListOpPair>* compositedChildrenOf3dRoot, 538 const mat4* transformFrom3dRoot, 539 Vector<DrawDisplayListOp*>* compositedChildrenOfProjectionSurface, 540 const mat4* transformFromProjectionSurface, 541 const void* rootDisplayList, const int orderingId); 542 543 template <class T> 544 inline void setViewProperties(OpenGLRenderer& renderer, T& handler, const int level); 545 546 template <class T> 547 inline void iterate3dChildren(ChildrenSelectMode mode, OpenGLRenderer& renderer, 548 T& handler, const int level); 549 550 template <class T> 551 inline void iterateProjectedChildren(OpenGLRenderer& renderer, T& handler, const int level); 552 553 template <class T> 554 inline void iterate(OpenGLRenderer& renderer, T& handler, const int level); 555 556 void init(); 557 558 void clearResources(); 559 560 void updateMatrix(); 561 562 class TextContainer { 563 public: 564 size_t length() const { 565 return mByteLength; 566 } 567 568 const char* text() const { 569 return (const char*) mText; 570 } 571 572 size_t mByteLength; 573 const char* mText; 574 }; 575 576 Vector<const SkBitmap*> mBitmapResources; 577 Vector<const SkBitmap*> mOwnedBitmapResources; 578 Vector<SkiaColorFilter*> mFilterResources; 579 Vector<const Res_png_9patch*> mPatchResources; 580 581 Vector<const SkPaint*> mPaints; 582 Vector<const SkPath*> mPaths; 583 SortedVector<const SkPath*> mSourcePaths; 584 Vector<const SkRegion*> mRegions; 585 Vector<const SkMatrix*> mMatrices; 586 Vector<SkiaShader*> mShaders; 587 Vector<Layer*> mLayers; 588 589 sp<DisplayListData> mDisplayListData; 590 591 size_t mSize; 592 593 bool mIsRenderable; 594 uint32_t mFunctorCount; 595 596 String8 mName; 597 bool mDestroyed; // used for debugging crash, TODO: remove once invalid state crash fixed 598 599 // Rendering properties 600 bool mClipToBounds; 601 bool mIsContainedVolume; 602 bool mProjectToContainedVolume; 603 float mAlpha; 604 bool mHasOverlappingRendering; 605 float mTranslationX, mTranslationY, mTranslationZ; 606 float mRotation, mRotationX, mRotationY; 607 float mScaleX, mScaleY; 608 float mPivotX, mPivotY; 609 float mCameraDistance; 610 int mLeft, mTop, mRight, mBottom; 611 int mWidth, mHeight; 612 int mPrevWidth, mPrevHeight; 613 bool mPivotExplicitlySet; 614 bool mMatrixDirty; 615 bool mMatrixIsIdentity; 616 uint32_t mMatrixFlags; 617 SkMatrix* mTransformMatrix; 618 Sk3DView* mTransformCamera; 619 SkMatrix* mTransformMatrix3D; 620 SkMatrix* mStaticMatrix; 621 SkMatrix* mAnimationMatrix; 622 Matrix4 mTransform; 623 bool mCaching; 624 625 /** 626 * Draw time state - these properties are only set and used during rendering 627 */ 628 629 // for 3d roots, contains a z sorted list of all children items 630 Vector<ZDrawDisplayListOpPair> m3dNodes; 631 632 // for projection surfaces, contains a list of all children items 633 Vector<DrawDisplayListOp*> mProjectedNodes; 634 635 // TEMPORARY, for debug logging only 636 const void* mRootDisplayList; 637 int mOrderingId; 638}; // class DisplayList 639 640}; // namespace uirenderer 641}; // namespace android 642 643#endif // ANDROID_HWUI_OPENGL_RENDERER_H 644