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