DisplayList.h revision e18264b079481a244b30e3f71012c53bbd861f92
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 SkiaShader; 65 66class ClipRectOp; 67class SaveLayerOp; 68class SaveOp; 69class RestoreToCountOp; 70class DrawDisplayListOp; 71 72/** 73 * Holds data used in the playback a tree of DisplayLists. 74 */ 75class PlaybackStateStruct { 76protected: 77 PlaybackStateStruct(OpenGLRenderer& renderer, int replayFlags, LinearAllocator* allocator) 78 : mRenderer(renderer), mReplayFlags(replayFlags), mAllocator(allocator){} 79 80public: 81 OpenGLRenderer& mRenderer; 82 const int mReplayFlags; 83 84 // Allocator with the lifetime of a single frame. 85 // replay uses an Allocator owned by the struct, while defer shares the DeferredDisplayList's Allocator 86 LinearAllocator * const mAllocator; 87}; 88 89class DeferStateStruct : public PlaybackStateStruct { 90public: 91 DeferStateStruct(DeferredDisplayList& deferredList, OpenGLRenderer& renderer, int replayFlags) 92 : PlaybackStateStruct(renderer, replayFlags, &(deferredList.mAllocator)), 93 mDeferredList(deferredList) {} 94 95 DeferredDisplayList& mDeferredList; 96}; 97 98class ReplayStateStruct : public PlaybackStateStruct { 99public: 100 ReplayStateStruct(OpenGLRenderer& renderer, Rect& dirty, int replayFlags) 101 : PlaybackStateStruct(renderer, replayFlags, &mReplayAllocator), 102 mDirty(dirty), mDrawGlStatus(DrawGlInfo::kStatusDone) {} 103 104 Rect& mDirty; 105 status_t mDrawGlStatus; 106 LinearAllocator mReplayAllocator; 107}; 108 109/** 110 * Data structure that holds the list of commands used in display list stream 111 */ 112class DisplayListData { 113public: 114 DisplayListData() : projectionReceiveIndex(-1), functorCount(0), hasDrawOps(false) {} 115 virtual ~DisplayListData() { cleanupResources(); } 116 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 projectionReceiveIndex; 128 129 Vector<const SkBitmap*> bitmapResources; 130 Vector<const SkBitmap*> ownedBitmapResources; 131 Vector<const Res_png_9patch*> patchResources; 132 133 Vector<const SkPaint*> paints; 134 Vector<const SkPath*> paths; 135 SortedVector<const SkPath*> sourcePaths; 136 Vector<const SkRegion*> regions; 137 Vector<const SkMatrix*> matrices; 138 Vector<SkiaShader*> shaders; 139 Vector<Layer*> layers; 140 uint32_t functorCount; 141 bool hasDrawOps; 142 143 bool isEmpty() { 144 return !displayListOps.size(); 145 } 146 147private: 148 void cleanupResources(); 149}; 150 151/** 152 * Primary class for storing recorded canvas commands, as well as per-View/ViewGroup display properties. 153 * 154 * Recording of canvas commands is somewhat similar to SkPicture, except the canvas-recording 155 * functionality is split between DisplayListRenderer (which manages the recording), DisplayListData 156 * (which holds the actual data), and DisplayList (which holds properties and performs playback onto 157 * a renderer). 158 * 159 * Note that DisplayListData is swapped out from beneath an individual DisplayList when a view's 160 * recorded stream of canvas operations is refreshed. The DisplayList (and its properties) stay 161 * attached. 162 */ 163class RenderNode { 164public: 165 ANDROID_API RenderNode(); 166 ANDROID_API ~RenderNode(); 167 168 // See flags defined in DisplayList.java 169 enum ReplayFlag { 170 kReplayFlag_ClipChildren = 0x1 171 }; 172 173 ANDROID_API static void destroyDisplayListDeferred(RenderNode* displayList); 174 ANDROID_API static void outputLogBuffer(int fd); 175 176 ANDROID_API void setData(DisplayListData* newData); 177 178 void computeOrdering(); 179 void defer(DeferStateStruct& deferStruct, const int level); 180 void replay(ReplayStateStruct& replayStruct, const int level); 181 182 ANDROID_API void output(uint32_t level = 1); 183 184 bool isRenderable() const { 185 return mDisplayListData && mDisplayListData->hasDrawOps; 186 } 187 188 void setName(const char* name) { 189 if (name) { 190 char* lastPeriod = strrchr(name, '.'); 191 if (lastPeriod) { 192 mName.setTo(lastPeriod + 1); 193 } else { 194 mName.setTo(name); 195 } 196 } 197 } 198 199 const char* getName() const { 200 return mName.string(); 201 } 202 203 void setClipToBounds(bool clipToBounds) { 204 mClipToBounds = clipToBounds; 205 } 206 207 void setIsolatedZVolume(bool shouldIsolate) { 208 mIsolatedZVolume = shouldIsolate; 209 } 210 211 void setCastsShadow(bool castsShadow) { 212 mCastsShadow = castsShadow; 213 } 214 215 void setUsesGlobalCamera(bool usesGlobalCamera) { 216 mUsesGlobalCamera = usesGlobalCamera; 217 } 218 219 void setProjectBackwards(bool shouldProject) { 220 mProjectBackwards = shouldProject; 221 } 222 223 void setProjectionReceiver(bool shouldRecieve) { 224 mProjectionReceiver = shouldRecieve; 225 } 226 227 bool isProjectionReceiver() { 228 return mProjectionReceiver; 229 } 230 231 void setOutline(const SkPath* outline) { 232 if (!outline) { 233 mOutline.reset(); 234 } else { 235 mOutline = *outline; 236 } 237 } 238 239 void setClipToOutline(bool clipToOutline) { 240 mClipToOutline = clipToOutline; 241 } 242 243 void setStaticMatrix(SkMatrix* matrix) { 244 delete mStaticMatrix; 245 mStaticMatrix = new SkMatrix(*matrix); 246 } 247 248 // Can return NULL 249 SkMatrix* getStaticMatrix() { 250 return mStaticMatrix; 251 } 252 253 void setAnimationMatrix(SkMatrix* matrix) { 254 delete mAnimationMatrix; 255 if (matrix) { 256 mAnimationMatrix = new SkMatrix(*matrix); 257 } else { 258 mAnimationMatrix = NULL; 259 } 260 } 261 262 void setAlpha(float alpha) { 263 alpha = fminf(1.0f, fmaxf(0.0f, alpha)); 264 if (alpha != mAlpha) { 265 mAlpha = alpha; 266 } 267 } 268 269 float getAlpha() const { 270 return mAlpha; 271 } 272 273 void setHasOverlappingRendering(bool hasOverlappingRendering) { 274 mHasOverlappingRendering = hasOverlappingRendering; 275 } 276 277 bool hasOverlappingRendering() const { 278 return mHasOverlappingRendering; 279 } 280 281 void setTranslationX(float translationX) { 282 if (translationX != mTranslationX) { 283 mTranslationX = translationX; 284 onTranslationUpdate(); 285 } 286 } 287 288 float getTranslationX() const { 289 return mTranslationX; 290 } 291 292 void setTranslationY(float translationY) { 293 if (translationY != mTranslationY) { 294 mTranslationY = translationY; 295 onTranslationUpdate(); 296 } 297 } 298 299 float getTranslationY() const { 300 return mTranslationY; 301 } 302 303 void setTranslationZ(float translationZ) { 304 if (translationZ != mTranslationZ) { 305 mTranslationZ = translationZ; 306 onTranslationUpdate(); 307 } 308 } 309 310 float getTranslationZ() const { 311 return mTranslationZ; 312 } 313 314 void setRotation(float rotation) { 315 if (rotation != mRotation) { 316 mRotation = rotation; 317 mMatrixDirty = true; 318 if (mRotation == 0.0f) { 319 mMatrixFlags &= ~ROTATION; 320 } else { 321 mMatrixFlags |= ROTATION; 322 } 323 } 324 } 325 326 float getRotation() const { 327 return mRotation; 328 } 329 330 void setRotationX(float rotationX) { 331 if (rotationX != mRotationX) { 332 mRotationX = rotationX; 333 mMatrixDirty = true; 334 if (mRotationX == 0.0f && mRotationY == 0.0f) { 335 mMatrixFlags &= ~ROTATION_3D; 336 } else { 337 mMatrixFlags |= ROTATION_3D; 338 } 339 } 340 } 341 342 float getRotationX() const { 343 return mRotationX; 344 } 345 346 void setRotationY(float rotationY) { 347 if (rotationY != mRotationY) { 348 mRotationY = rotationY; 349 mMatrixDirty = true; 350 if (mRotationX == 0.0f && mRotationY == 0.0f) { 351 mMatrixFlags &= ~ROTATION_3D; 352 } else { 353 mMatrixFlags |= ROTATION_3D; 354 } 355 } 356 } 357 358 float getRotationY() const { 359 return mRotationY; 360 } 361 362 void setScaleX(float scaleX) { 363 if (scaleX != mScaleX) { 364 mScaleX = scaleX; 365 mMatrixDirty = true; 366 if (mScaleX == 1.0f && mScaleY == 1.0f) { 367 mMatrixFlags &= ~SCALE; 368 } else { 369 mMatrixFlags |= SCALE; 370 } 371 } 372 } 373 374 float getScaleX() const { 375 return mScaleX; 376 } 377 378 void setScaleY(float scaleY) { 379 if (scaleY != mScaleY) { 380 mScaleY = scaleY; 381 mMatrixDirty = true; 382 if (mScaleX == 1.0f && mScaleY == 1.0f) { 383 mMatrixFlags &= ~SCALE; 384 } else { 385 mMatrixFlags |= SCALE; 386 } 387 } 388 } 389 390 float getScaleY() const { 391 return mScaleY; 392 } 393 394 void setPivotX(float pivotX) { 395 mPivotX = pivotX; 396 mMatrixDirty = true; 397 if (mPivotX == 0.0f && mPivotY == 0.0f) { 398 mMatrixFlags &= ~PIVOT; 399 } else { 400 mMatrixFlags |= PIVOT; 401 } 402 mPivotExplicitlySet = true; 403 } 404 405 ANDROID_API float getPivotX(); 406 407 void setPivotY(float pivotY) { 408 mPivotY = pivotY; 409 mMatrixDirty = true; 410 if (mPivotX == 0.0f && mPivotY == 0.0f) { 411 mMatrixFlags &= ~PIVOT; 412 } else { 413 mMatrixFlags |= PIVOT; 414 } 415 mPivotExplicitlySet = true; 416 } 417 418 ANDROID_API float getPivotY(); 419 420 void setCameraDistance(float distance) { 421 if (distance != mCameraDistance) { 422 mCameraDistance = distance; 423 mMatrixDirty = true; 424 if (!mTransformCamera) { 425 mTransformCamera = new Sk3DView(); 426 mTransformMatrix3D = new SkMatrix(); 427 } 428 mTransformCamera->setCameraLocation(0, 0, distance); 429 } 430 } 431 432 float getCameraDistance() const { 433 return mCameraDistance; 434 } 435 436 void setLeft(int left) { 437 if (left != mLeft) { 438 mLeft = left; 439 mWidth = mRight - mLeft; 440 if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) { 441 mMatrixDirty = true; 442 } 443 } 444 } 445 446 float getLeft() const { 447 return mLeft; 448 } 449 450 void setTop(int top) { 451 if (top != mTop) { 452 mTop = top; 453 mHeight = mBottom - mTop; 454 if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) { 455 mMatrixDirty = true; 456 } 457 } 458 } 459 460 float getTop() const { 461 return mTop; 462 } 463 464 void setRight(int right) { 465 if (right != mRight) { 466 mRight = right; 467 mWidth = mRight - mLeft; 468 if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) { 469 mMatrixDirty = true; 470 } 471 } 472 } 473 474 float getRight() const { 475 return mRight; 476 } 477 478 void setBottom(int bottom) { 479 if (bottom != mBottom) { 480 mBottom = bottom; 481 mHeight = mBottom - mTop; 482 if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) { 483 mMatrixDirty = true; 484 } 485 } 486 } 487 488 float getBottom() const { 489 return mBottom; 490 } 491 492 void setLeftTop(int left, int top) { 493 if (left != mLeft || top != mTop) { 494 mLeft = left; 495 mTop = top; 496 mWidth = mRight - mLeft; 497 mHeight = mBottom - mTop; 498 if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) { 499 mMatrixDirty = true; 500 } 501 } 502 } 503 504 void setLeftTopRightBottom(int left, int top, int right, int bottom) { 505 if (left != mLeft || top != mTop || right != mRight || bottom != mBottom) { 506 mLeft = left; 507 mTop = top; 508 mRight = right; 509 mBottom = bottom; 510 mWidth = mRight - mLeft; 511 mHeight = mBottom - mTop; 512 if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) { 513 mMatrixDirty = true; 514 } 515 } 516 } 517 518 void offsetLeftRight(float offset) { 519 if (offset != 0) { 520 mLeft += offset; 521 mRight += offset; 522 if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) { 523 mMatrixDirty = true; 524 } 525 } 526 } 527 528 void offsetTopBottom(float offset) { 529 if (offset != 0) { 530 mTop += offset; 531 mBottom += offset; 532 if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) { 533 mMatrixDirty = true; 534 } 535 } 536 } 537 538 void setCaching(bool caching) { 539 mCaching = caching; 540 } 541 542 int getWidth() { 543 return mWidth; 544 } 545 546 int getHeight() { 547 return mHeight; 548 } 549 550private: 551 typedef key_value_pair_t<float, DrawDisplayListOp*> ZDrawDisplayListOpPair; 552 553 static size_t findNonNegativeIndex(const Vector<ZDrawDisplayListOpPair>& nodes) { 554 for (size_t i = 0; i < nodes.size(); i++) { 555 if (nodes[i].key >= 0.0f) return i; 556 } 557 return nodes.size(); 558 } 559 560 enum ChildrenSelectMode { 561 kNegativeZChildren, 562 kPositiveZChildren 563 }; 564 565 void onTranslationUpdate() { 566 mMatrixDirty = true; 567 if (mTranslationX == 0.0f && mTranslationY == 0.0f && mTranslationZ == 0.0f) { 568 mMatrixFlags &= ~TRANSLATION; 569 } else { 570 mMatrixFlags |= TRANSLATION; 571 } 572 } 573 574 void outputViewProperties(const int level); 575 576 void applyViewPropertyTransforms(mat4& matrix, bool true3dTransform = false); 577 578 void computeOrderingImpl(DrawDisplayListOp* opState, 579 Vector<DrawDisplayListOp*>* compositedChildrenOfProjectionSurface, 580 const mat4* transformFromProjectionSurface); 581 582 template <class T> 583 inline void setViewProperties(OpenGLRenderer& renderer, T& handler, const int level); 584 585 void buildZSortedChildList(Vector<ZDrawDisplayListOpPair>& zTranslatedNodes); 586 587 template <class T> 588 inline void iterate3dChildren(const Vector<ZDrawDisplayListOpPair>& zTranslatedNodes, 589 ChildrenSelectMode mode, OpenGLRenderer& renderer, T& handler); 590 591 template <class T> 592 inline void iterateProjectedChildren(OpenGLRenderer& renderer, T& handler, const int level); 593 594 template <class T> 595 inline void iterate(OpenGLRenderer& renderer, T& handler, const int level); 596 597 void updateMatrix(); 598 599 class TextContainer { 600 public: 601 size_t length() const { 602 return mByteLength; 603 } 604 605 const char* text() const { 606 return (const char*) mText; 607 } 608 609 size_t mByteLength; 610 const char* mText; 611 }; 612 613 DisplayListData* mDisplayListData; 614 615 String8 mName; 616 bool mDestroyed; // used for debugging crash, TODO: remove once invalid state crash fixed 617 618 // Rendering properties 619 bool mClipToBounds; 620 bool mIsolatedZVolume; 621 bool mProjectBackwards; 622 bool mProjectionReceiver; 623 SkPath mOutline; 624 bool mClipToOutline; 625 bool mCastsShadow; 626 bool mUsesGlobalCamera; // TODO: respect value when rendering 627 float mAlpha; 628 bool mHasOverlappingRendering; 629 float mTranslationX, mTranslationY, mTranslationZ; 630 float mRotation, mRotationX, mRotationY; 631 float mScaleX, mScaleY; 632 float mPivotX, mPivotY; 633 float mCameraDistance; 634 int mLeft, mTop, mRight, mBottom; 635 int mWidth, mHeight; 636 int mPrevWidth, mPrevHeight; 637 bool mPivotExplicitlySet; 638 bool mMatrixDirty; 639 bool mMatrixIsIdentity; 640 641 /** 642 * Stores the total transformation of the DisplayList based upon its scalar 643 * translate/rotate/scale properties. 644 * 645 * In the common translation-only case, the matrix isn't allocated and the mTranslation 646 * properties are used directly. 647 */ 648 Matrix4* mTransformMatrix; 649 uint32_t mMatrixFlags; 650 Sk3DView* mTransformCamera; 651 SkMatrix* mTransformMatrix3D; 652 SkMatrix* mStaticMatrix; 653 SkMatrix* mAnimationMatrix; 654 bool mCaching; 655 656 /** 657 * Draw time state - these properties are only set and used during rendering 658 */ 659 660 // for projection surfaces, contains a list of all children items 661 Vector<DrawDisplayListOp*> mProjectedNodes; 662}; // class DisplayList 663 664}; // namespace uirenderer 665}; // namespace android 666 667#endif // ANDROID_HWUI_OPENGL_RENDERER_H 668