diff options
Diffstat (limited to 'libs/hwui')
| -rw-r--r-- | libs/hwui/Android.mk | 1 | ||||
| -rw-r--r-- | libs/hwui/DisplayList.cpp | 436 | ||||
| -rw-r--r-- | libs/hwui/DisplayList.h | 422 | ||||
| -rw-r--r-- | libs/hwui/DisplayListOp.h | 2 | ||||
| -rw-r--r-- | libs/hwui/DisplayListRenderer.cpp | 420 | ||||
| -rw-r--r-- | libs/hwui/DisplayListRenderer.h | 379 |
6 files changed, 863 insertions, 797 deletions
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk index 6bc7aefce913..db64c99c289e 100644 --- a/libs/hwui/Android.mk +++ b/libs/hwui/Android.mk @@ -11,6 +11,7 @@ ifeq ($(USE_OPENGL_RENDERER),true) FontRenderer.cpp \ GammaFontRenderer.cpp \ Caches.cpp \ + DisplayList.cpp \ DisplayListLogBuffer.cpp \ DisplayListRenderer.cpp \ Dither.cpp \ diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp new file mode 100644 index 000000000000..a52ea980edd6 --- /dev/null +++ b/libs/hwui/DisplayList.cpp @@ -0,0 +1,436 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "DisplayList.h" +#include "DisplayListOp.h" +#include "DisplayListLogBuffer.h" + +namespace android { +namespace uirenderer { + +void DisplayList::outputLogBuffer(int fd) { + DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance(); + if (logBuffer.isEmpty()) { + return; + } + + FILE *file = fdopen(fd, "a"); + + fprintf(file, "\nRecent DisplayList operations\n"); + logBuffer.outputCommands(file); + + String8 cachesLog; + Caches::getInstance().dumpMemoryUsage(cachesLog); + fprintf(file, "\nCaches:\n%s", cachesLog.string()); + fprintf(file, "\n"); + + fflush(file); +} + +DisplayList::DisplayList(const DisplayListRenderer& recorder) : + mTransformMatrix(NULL), mTransformCamera(NULL), mTransformMatrix3D(NULL), + mStaticMatrix(NULL), mAnimationMatrix(NULL) { + + initFromDisplayListRenderer(recorder); +} + +DisplayList::~DisplayList() { + clearResources(); +} + +void DisplayList::destroyDisplayListDeferred(DisplayList* displayList) { + if (displayList) { + DISPLAY_LIST_LOGD("Deferring display list destruction"); + Caches::getInstance().deleteDisplayListDeferred(displayList); + } +} + +void DisplayList::clearResources() { + mDisplayListData = NULL; + delete mTransformMatrix; + delete mTransformCamera; + delete mTransformMatrix3D; + delete mStaticMatrix; + delete mAnimationMatrix; + + mTransformMatrix = NULL; + mTransformCamera = NULL; + mTransformMatrix3D = NULL; + mStaticMatrix = NULL; + mAnimationMatrix = NULL; + + Caches& caches = Caches::getInstance(); + caches.unregisterFunctors(mFunctorCount); + caches.resourceCache.lock(); + + for (size_t i = 0; i < mBitmapResources.size(); i++) { + caches.resourceCache.decrementRefcountLocked(mBitmapResources.itemAt(i)); + } + + for (size_t i = 0; i < mOwnedBitmapResources.size(); i++) { + SkBitmap* bitmap = mOwnedBitmapResources.itemAt(i); + caches.resourceCache.decrementRefcountLocked(bitmap); + caches.resourceCache.destructorLocked(bitmap); + } + + for (size_t i = 0; i < mFilterResources.size(); i++) { + caches.resourceCache.decrementRefcountLocked(mFilterResources.itemAt(i)); + } + + for (size_t i = 0; i < mShaders.size(); i++) { + caches.resourceCache.decrementRefcountLocked(mShaders.itemAt(i)); + caches.resourceCache.destructorLocked(mShaders.itemAt(i)); + } + + for (size_t i = 0; i < mSourcePaths.size(); i++) { + caches.resourceCache.decrementRefcountLocked(mSourcePaths.itemAt(i)); + } + + for (size_t i = 0; i < mLayers.size(); i++) { + caches.resourceCache.decrementRefcountLocked(mLayers.itemAt(i)); + } + + caches.resourceCache.unlock(); + + for (size_t i = 0; i < mPaints.size(); i++) { + delete mPaints.itemAt(i); + } + + for (size_t i = 0; i < mRegions.size(); i++) { + delete mRegions.itemAt(i); + } + + for (size_t i = 0; i < mPaths.size(); i++) { + SkPath* path = mPaths.itemAt(i); + caches.pathCache.remove(path); + delete path; + } + + for (size_t i = 0; i < mMatrices.size(); i++) { + delete mMatrices.itemAt(i); + } + + mBitmapResources.clear(); + mOwnedBitmapResources.clear(); + mFilterResources.clear(); + mShaders.clear(); + mSourcePaths.clear(); + mPaints.clear(); + mRegions.clear(); + mPaths.clear(); + mMatrices.clear(); + mLayers.clear(); +} + +void DisplayList::reset() { + clearResources(); + init(); +} + +void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing) { + if (reusing) { + // re-using display list - clear out previous allocations + clearResources(); + } + + init(); + + mDisplayListData = recorder.getDisplayListData(); + mSize = mDisplayListData->allocator.usedSize(); + + if (mSize == 0) { + return; + } + + mFunctorCount = recorder.getFunctorCount(); + + Caches& caches = Caches::getInstance(); + caches.registerFunctors(mFunctorCount); + caches.resourceCache.lock(); + + const Vector<SkBitmap*>& bitmapResources = recorder.getBitmapResources(); + for (size_t i = 0; i < bitmapResources.size(); i++) { + SkBitmap* resource = bitmapResources.itemAt(i); + mBitmapResources.add(resource); + caches.resourceCache.incrementRefcountLocked(resource); + } + + const Vector<SkBitmap*> &ownedBitmapResources = recorder.getOwnedBitmapResources(); + for (size_t i = 0; i < ownedBitmapResources.size(); i++) { + SkBitmap* resource = ownedBitmapResources.itemAt(i); + mOwnedBitmapResources.add(resource); + caches.resourceCache.incrementRefcountLocked(resource); + } + + const Vector<SkiaColorFilter*>& filterResources = recorder.getFilterResources(); + for (size_t i = 0; i < filterResources.size(); i++) { + SkiaColorFilter* resource = filterResources.itemAt(i); + mFilterResources.add(resource); + caches.resourceCache.incrementRefcountLocked(resource); + } + + const Vector<SkiaShader*>& shaders = recorder.getShaders(); + for (size_t i = 0; i < shaders.size(); i++) { + SkiaShader* resource = shaders.itemAt(i); + mShaders.add(resource); + caches.resourceCache.incrementRefcountLocked(resource); + } + + const SortedVector<SkPath*>& sourcePaths = recorder.getSourcePaths(); + for (size_t i = 0; i < sourcePaths.size(); i++) { + mSourcePaths.add(sourcePaths.itemAt(i)); + caches.resourceCache.incrementRefcountLocked(sourcePaths.itemAt(i)); + } + + const Vector<Layer*>& layers = recorder.getLayers(); + for (size_t i = 0; i < layers.size(); i++) { + mLayers.add(layers.itemAt(i)); + caches.resourceCache.incrementRefcountLocked(layers.itemAt(i)); + } + + caches.resourceCache.unlock(); + + mPaints.appendVector(recorder.getPaints()); + mRegions.appendVector(recorder.getRegions()); + mPaths.appendVector(recorder.getPaths()); + mMatrices.appendVector(recorder.getMatrices()); +} + +void DisplayList::init() { + mSize = 0; + mIsRenderable = true; + mFunctorCount = 0; + mLeft = 0; + mTop = 0; + mRight = 0; + mBottom = 0; + mClipChildren = true; + mAlpha = 1; + mMultipliedAlpha = 255; + mHasOverlappingRendering = true; + mTranslationX = 0; + mTranslationY = 0; + mRotation = 0; + mRotationX = 0; + mRotationY= 0; + mScaleX = 1; + mScaleY = 1; + mPivotX = 0; + mPivotY = 0; + mCameraDistance = 0; + mMatrixDirty = false; + mMatrixFlags = 0; + mPrevWidth = -1; + mPrevHeight = -1; + mWidth = 0; + mHeight = 0; + mPivotExplicitlySet = false; + mCaching = false; +} + +size_t DisplayList::getSize() { + return mSize; +} + +/** + * This function is a simplified version of replay(), where we simply retrieve and log the + * display list. This function should remain in sync with the replay() function. + */ +void DisplayList::output(uint32_t level) { + ALOGD("%*sStart display list (%p, %s, render=%d)", level * 2, "", this, + mName.string(), isRenderable()); + + ALOGD("%*s%s %d", level * 2, "", "Save", SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag); + outputViewProperties(level); + int flags = DisplayListOp::kOpLogFlag_Recurse; + for (unsigned int i = 0; i < mDisplayListData->displayListOps.size(); i++) { + mDisplayListData->displayListOps[i]->output(level, flags); + } + ALOGD("%*sDone (%p, %s)", level * 2, "", this, mName.string()); +} + +void DisplayList::updateMatrix() { + if (mMatrixDirty) { + if (!mTransformMatrix) { + mTransformMatrix = new SkMatrix(); + } + if (mMatrixFlags == 0 || mMatrixFlags == TRANSLATION) { + mTransformMatrix->reset(); + } else { + if (!mPivotExplicitlySet) { + if (mWidth != mPrevWidth || mHeight != mPrevHeight) { + mPrevWidth = mWidth; + mPrevHeight = mHeight; + mPivotX = mPrevWidth / 2; + mPivotY = mPrevHeight / 2; + } + } + if ((mMatrixFlags & ROTATION_3D) == 0) { + mTransformMatrix->setTranslate(mTranslationX, mTranslationY); + mTransformMatrix->preRotate(mRotation, mPivotX, mPivotY); + mTransformMatrix->preScale(mScaleX, mScaleY, mPivotX, mPivotY); + } else { + if (!mTransformCamera) { + mTransformCamera = new Sk3DView(); + mTransformMatrix3D = new SkMatrix(); + } + mTransformMatrix->reset(); + mTransformCamera->save(); + mTransformMatrix->preScale(mScaleX, mScaleY, mPivotX, mPivotY); + mTransformCamera->rotateX(mRotationX); + mTransformCamera->rotateY(mRotationY); + mTransformCamera->rotateZ(-mRotation); + mTransformCamera->getMatrix(mTransformMatrix3D); + mTransformMatrix3D->preTranslate(-mPivotX, -mPivotY); + mTransformMatrix3D->postTranslate(mPivotX + mTranslationX, + mPivotY + mTranslationY); + mTransformMatrix->postConcat(*mTransformMatrix3D); + mTransformCamera->restore(); + } + } + mMatrixDirty = false; + } +} + +void DisplayList::outputViewProperties(uint32_t level) { + updateMatrix(); + if (mLeft != 0 || mTop != 0) { + ALOGD("%*sTranslate (left, top) %d, %d", level * 2, "", mLeft, mTop); + } + if (mStaticMatrix) { + ALOGD("%*sConcatMatrix (static) %p: " MATRIX_STRING, + level * 2, "", mStaticMatrix, MATRIX_ARGS(mStaticMatrix)); + } + if (mAnimationMatrix) { + ALOGD("%*sConcatMatrix (animation) %p: " MATRIX_STRING, + level * 2, "", mAnimationMatrix, MATRIX_ARGS(mStaticMatrix)); + } + if (mMatrixFlags != 0) { + if (mMatrixFlags == TRANSLATION) { + ALOGD("%*sTranslate %f, %f", level * 2, "", mTranslationX, mTranslationY); + } else { + ALOGD("%*sConcatMatrix %p: " MATRIX_STRING, + level * 2, "", mTransformMatrix, MATRIX_ARGS(mTransformMatrix)); + } + } + if (mAlpha < 1 && !mCaching) { + if (!mHasOverlappingRendering) { + ALOGD("%*sSetAlpha %.2f", level * 2, "", mAlpha); + } else { + int flags = SkCanvas::kHasAlphaLayer_SaveFlag; + if (mClipChildren) { + flags |= SkCanvas::kClipToLayer_SaveFlag; + } + ALOGD("%*sSaveLayerAlpha %.2f, %.2f, %.2f, %.2f, %d, 0x%x", level * 2, "", + (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop, + mMultipliedAlpha, flags); + } + } + if (mClipChildren && !mCaching) { + ALOGD("%*sClipRect %.2f, %.2f, %.2f, %.2f", level * 2, "", 0.0f, 0.0f, + (float) mRight - mLeft, (float) mBottom - mTop); + } +} + +void DisplayList::setViewProperties(OpenGLRenderer& renderer, uint32_t level) { +#if DEBUG_DISPLAYLIST + outputViewProperties(level); +#endif + updateMatrix(); + if (mLeft != 0 || mTop != 0) { + renderer.translate(mLeft, mTop); + } + if (mStaticMatrix) { + renderer.concatMatrix(mStaticMatrix); + } else if (mAnimationMatrix) { + renderer.concatMatrix(mAnimationMatrix); + } + if (mMatrixFlags != 0) { + if (mMatrixFlags == TRANSLATION) { + renderer.translate(mTranslationX, mTranslationY); + } else { + renderer.concatMatrix(mTransformMatrix); + } + } + if (mAlpha < 1 && !mCaching) { + if (!mHasOverlappingRendering) { + renderer.setAlpha(mAlpha); + } else { + // TODO: should be able to store the size of a DL at record time and not + // have to pass it into this call. In fact, this information might be in the + // location/size info that we store with the new native transform data. + int flags = SkCanvas::kHasAlphaLayer_SaveFlag; + if (mClipChildren) { + flags |= SkCanvas::kClipToLayer_SaveFlag; + } + renderer.saveLayerAlpha(0, 0, mRight - mLeft, mBottom - mTop, + mMultipliedAlpha, flags); + } + } + if (mClipChildren && !mCaching) { + renderer.clipRect(0, 0, mRight - mLeft, mBottom - mTop, + SkRegion::kIntersect_Op); + } +} + +status_t DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, uint32_t level) { + status_t drawGlStatus = DrawGlInfo::kStatusDone; + +#if DEBUG_DISPLAY_LIST + Rect* clipRect = renderer.getClipRect(); + DISPLAY_LIST_LOGD("%*sStart display list (%p, %s), clipRect: %.0f, %.f, %.0f, %.0f", + (level+1)*2, "", this, mName.string(), clipRect->left, clipRect->top, + clipRect->right, clipRect->bottom); +#endif + + renderer.startMark(mName.string()); + + int restoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag); + DISPLAY_LIST_LOGD("%*sSave %d %d", level * 2, "", + SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag, restoreTo); + setViewProperties(renderer, level); + + if (renderer.quickRejectNoScissor(0, 0, mWidth, mHeight)) { + DISPLAY_LIST_LOGD("%*sRestoreToCount %d", level * 2, "", restoreTo); + renderer.restoreToCount(restoreTo); + renderer.endMark(); + return drawGlStatus; + } + + DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance(); + int saveCount = renderer.getSaveCount() - 1; + for (unsigned int i = 0; i < mDisplayListData->displayListOps.size(); i++) { + DisplayListOp *op = mDisplayListData->displayListOps[i]; +#if DEBUG_DISPLAY_LIST_OPS_AS_EVENTS + Caches::getInstance().eventMark(strlen(op->name()), op->name()); +#endif + + drawGlStatus |= op->replay(renderer, dirty, flags, + saveCount, level, mCaching, mMultipliedAlpha); + logBuffer.writeCommand(level, op->name()); + } + + DISPLAY_LIST_LOGD("%*sRestoreToCount %d", level * 2, "", restoreTo); + renderer.restoreToCount(restoreTo); + renderer.endMark(); + + DISPLAY_LIST_LOGD("%*sDone (%p, %s), returning %d", (level + 1) * 2, "", this, mName.string(), + drawGlStatus); + return drawGlStatus; +} + +}; // namespace uirenderer +}; // namespace android diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h new file mode 100644 index 000000000000..70a9755f4ee6 --- /dev/null +++ b/libs/hwui/DisplayList.h @@ -0,0 +1,422 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HWUI_DISPLAY_LIST_H +#define ANDROID_HWUI_DISPLAY_LIST_H + +#include <SkCamera.h> +#include <SkMatrix.h> + +#include <utils/RefBase.h> +#include <utils/SortedVector.h> +#include <utils/String8.h> +#include <utils/Vector.h> +#include <cutils/compiler.h> + +#include "utils/LinearAllocator.h" + +#include "Debug.h" + +#define TRANSLATION 0x0001 +#define ROTATION 0x0002 +#define ROTATION_3D 0x0004 +#define SCALE 0x0008 +#define PIVOT 0x0010 + +class SkBitmap; +class SkPaint; +class SkPath; +class SkRegion; + +namespace android { +namespace uirenderer { + +class DisplayListOp; +class DisplayListRenderer; +class OpenGLRenderer; +class Rect; +class Layer; +class SkiaColorFilter; +class SkiaShader; + +/** + * Refcounted structure that holds data used in display list stream + */ +class DisplayListData: public LightRefBase<DisplayListData> { +public: + LinearAllocator allocator; + Vector<DisplayListOp*> displayListOps; +}; + +/** + * Replays recorded drawing commands. + */ +class DisplayList { +public: + DisplayList(const DisplayListRenderer& recorder); + ANDROID_API ~DisplayList(); + + // See flags defined in DisplayList.java + enum ReplayFlag { + kReplayFlag_ClipChildren = 0x1 + }; + + void setViewProperties(OpenGLRenderer& renderer, uint32_t level); + void outputViewProperties(uint32_t level); + + ANDROID_API size_t getSize(); + ANDROID_API static void destroyDisplayListDeferred(DisplayList* displayList); + ANDROID_API static void outputLogBuffer(int fd); + + void initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing = false); + + status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, uint32_t level = 0); + + void output(uint32_t level = 0); + + ANDROID_API void reset(); + + void setRenderable(bool renderable) { + mIsRenderable = renderable; + } + + bool isRenderable() const { + return mIsRenderable; + } + + void setName(const char* name) { + if (name) { + mName.setTo(name); + } + } + + void setClipChildren(bool clipChildren) { + mClipChildren = clipChildren; + } + + void setStaticMatrix(SkMatrix* matrix) { + delete mStaticMatrix; + mStaticMatrix = new SkMatrix(*matrix); + } + + void setAnimationMatrix(SkMatrix* matrix) { + delete mAnimationMatrix; + if (matrix) { + mAnimationMatrix = new SkMatrix(*matrix); + } else { + mAnimationMatrix = NULL; + } + } + + void setAlpha(float alpha) { + alpha = fminf(1.0f, fmaxf(0.0f, alpha)); + if (alpha != mAlpha) { + mAlpha = alpha; + mMultipliedAlpha = (int) (255 * alpha); + } + } + + void setHasOverlappingRendering(bool hasOverlappingRendering) { + mHasOverlappingRendering = hasOverlappingRendering; + } + + void setTranslationX(float translationX) { + if (translationX != mTranslationX) { + mTranslationX = translationX; + mMatrixDirty = true; + if (mTranslationX == 0.0f && mTranslationY == 0.0f) { + mMatrixFlags &= ~TRANSLATION; + } else { + mMatrixFlags |= TRANSLATION; + } + } + } + + void setTranslationY(float translationY) { + if (translationY != mTranslationY) { + mTranslationY = translationY; + mMatrixDirty = true; + if (mTranslationX == 0.0f && mTranslationY == 0.0f) { + mMatrixFlags &= ~TRANSLATION; + } else { + mMatrixFlags |= TRANSLATION; + } + } + } + + void setRotation(float rotation) { + if (rotation != mRotation) { + mRotation = rotation; + mMatrixDirty = true; + if (mRotation == 0.0f) { + mMatrixFlags &= ~ROTATION; + } else { + mMatrixFlags |= ROTATION; + } + } + } + + void setRotationX(float rotationX) { + if (rotationX != mRotationX) { + mRotationX = rotationX; + mMatrixDirty = true; + if (mRotationX == 0.0f && mRotationY == 0.0f) { + mMatrixFlags &= ~ROTATION_3D; + } else { + mMatrixFlags |= ROTATION_3D; + } + } + } + + void setRotationY(float rotationY) { + if (rotationY != mRotationY) { + mRotationY = rotationY; + mMatrixDirty = true; + if (mRotationX == 0.0f && mRotationY == 0.0f) { + mMatrixFlags &= ~ROTATION_3D; + } else { + mMatrixFlags |= ROTATION_3D; + } + } + } + + void setScaleX(float scaleX) { + if (scaleX != mScaleX) { + mScaleX = scaleX; + mMatrixDirty = true; + if (mScaleX == 1.0f && mScaleY == 1.0f) { + mMatrixFlags &= ~SCALE; + } else { + mMatrixFlags |= SCALE; + } + } + } + + void setScaleY(float scaleY) { + if (scaleY != mScaleY) { + mScaleY = scaleY; + mMatrixDirty = true; + if (mScaleX == 1.0f && mScaleY == 1.0f) { + mMatrixFlags &= ~SCALE; + } else { + mMatrixFlags |= SCALE; + } + } + } + + void setPivotX(float pivotX) { + mPivotX = pivotX; + mMatrixDirty = true; + if (mPivotX == 0.0f && mPivotY == 0.0f) { + mMatrixFlags &= ~PIVOT; + } else { + mMatrixFlags |= PIVOT; + } + mPivotExplicitlySet = true; + } + + void setPivotY(float pivotY) { + mPivotY = pivotY; + mMatrixDirty = true; + if (mPivotX == 0.0f && mPivotY == 0.0f) { + mMatrixFlags &= ~PIVOT; + } else { + mMatrixFlags |= PIVOT; + } + mPivotExplicitlySet = true; + } + + void setCameraDistance(float distance) { + if (distance != mCameraDistance) { + mCameraDistance = distance; + mMatrixDirty = true; + if (!mTransformCamera) { + mTransformCamera = new Sk3DView(); + mTransformMatrix3D = new SkMatrix(); + } + mTransformCamera->setCameraLocation(0, 0, distance); + } + } + + void setLeft(int left) { + if (left != mLeft) { + mLeft = left; + mWidth = mRight - mLeft; + if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) { + mMatrixDirty = true; + } + } + } + + void setTop(int top) { + if (top != mTop) { + mTop = top; + mHeight = mBottom - mTop; + if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) { + mMatrixDirty = true; + } + } + } + + void setRight(int right) { + if (right != mRight) { + mRight = right; + mWidth = mRight - mLeft; + if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) { + mMatrixDirty = true; + } + } + } + + void setBottom(int bottom) { + if (bottom != mBottom) { + mBottom = bottom; + mHeight = mBottom - mTop; + if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) { + mMatrixDirty = true; + } + } + } + + void setLeftTop(int left, int top) { + if (left != mLeft || top != mTop) { + mLeft = left; + mTop = top; + mWidth = mRight - mLeft; + mHeight = mBottom - mTop; + if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) { + mMatrixDirty = true; + } + } + } + + void setLeftTopRightBottom(int left, int top, int right, int bottom) { + if (left != mLeft || top != mTop || right != mRight || bottom != mBottom) { + mLeft = left; + mTop = top; + mRight = right; + mBottom = bottom; + mWidth = mRight - mLeft; + mHeight = mBottom - mTop; + if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) { + mMatrixDirty = true; + } + } + } + + void offsetLeftRight(int offset) { + if (offset != 0) { + mLeft += offset; + mRight += offset; + if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) { + mMatrixDirty = true; + } + } + } + + void offsetTopBottom(int offset) { + if (offset != 0) { + mTop += offset; + mBottom += offset; + if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) { + mMatrixDirty = true; + } + } + } + + void setCaching(bool caching) { + mCaching = caching; + } + + int getWidth() { + return mWidth; + } + + int getHeight() { + return mHeight; + } + +private: + void init(); + + void clearResources(); + + void updateMatrix(); + + class TextContainer { + public: + size_t length() const { + return mByteLength; + } + + const char* text() const { + return (const char*) mText; + } + + size_t mByteLength; + const char* mText; + }; + + Vector<SkBitmap*> mBitmapResources; + Vector<SkBitmap*> mOwnedBitmapResources; + Vector<SkiaColorFilter*> mFilterResources; + + Vector<SkPaint*> mPaints; + Vector<SkPath*> mPaths; + SortedVector<SkPath*> mSourcePaths; + Vector<SkRegion*> mRegions; + Vector<SkMatrix*> mMatrices; + Vector<SkiaShader*> mShaders; + Vector<Layer*> mLayers; + + sp<DisplayListData> mDisplayListData; + + size_t mSize; + + bool mIsRenderable; + uint32_t mFunctorCount; + + String8 mName; + + // View properties + bool mClipChildren; + float mAlpha; + int mMultipliedAlpha; + bool mHasOverlappingRendering; + float mTranslationX, mTranslationY; + float mRotation, mRotationX, mRotationY; + float mScaleX, mScaleY; + float mPivotX, mPivotY; + float mCameraDistance; + int mLeft, mTop, mRight, mBottom; + int mWidth, mHeight; + int mPrevWidth, mPrevHeight; + bool mPivotExplicitlySet; + bool mMatrixDirty; + bool mMatrixIsIdentity; + uint32_t mMatrixFlags; + SkMatrix* mTransformMatrix; + Sk3DView* mTransformCamera; + SkMatrix* mTransformMatrix3D; + SkMatrix* mStaticMatrix; + SkMatrix* mAnimationMatrix; + bool mCaching; +}; // class DisplayList + +}; // namespace uirenderer +}; // namespace android + +#endif // ANDROID_HWUI_OPENGL_RENDERER_H diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h index 6425b43dc015..78b432c61f56 100644 --- a/libs/hwui/DisplayListOp.h +++ b/libs/hwui/DisplayListOp.h @@ -19,6 +19,8 @@ #include <SkXfermode.h> +#include <private/hwui/DrawGlInfo.h> + #include "OpenGLRenderer.h" #include "DisplayListRenderer.h" #include "utils/LinearAllocator.h" diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index 17ed8ac5fe20..31291b18d309 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -20,6 +20,7 @@ #include <private/hwui/DrawGlInfo.h> +#include "DisplayList.h" #include "DisplayListLogBuffer.h" #include "DisplayListOp.h" #include "DisplayListRenderer.h" @@ -28,425 +29,6 @@ namespace android { namespace uirenderer { -/////////////////////////////////////////////////////////////////////////////// -// Display list -/////////////////////////////////////////////////////////////////////////////// - -void DisplayList::outputLogBuffer(int fd) { - DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance(); - if (logBuffer.isEmpty()) { - return; - } - - FILE *file = fdopen(fd, "a"); - - fprintf(file, "\nRecent DisplayList operations\n"); - logBuffer.outputCommands(file); - - String8 cachesLog; - Caches::getInstance().dumpMemoryUsage(cachesLog); - fprintf(file, "\nCaches:\n%s", cachesLog.string()); - fprintf(file, "\n"); - - fflush(file); -} - -DisplayList::DisplayList(const DisplayListRenderer& recorder) : - mTransformMatrix(NULL), mTransformCamera(NULL), mTransformMatrix3D(NULL), - mStaticMatrix(NULL), mAnimationMatrix(NULL) { - - initFromDisplayListRenderer(recorder); -} - -DisplayList::~DisplayList() { - clearResources(); -} - -void DisplayList::destroyDisplayListDeferred(DisplayList* displayList) { - if (displayList) { - DISPLAY_LIST_LOGD("Deferring display list destruction"); - Caches::getInstance().deleteDisplayListDeferred(displayList); - } -} - -void DisplayList::clearResources() { - mDisplayListData = NULL; - delete mTransformMatrix; - delete mTransformCamera; - delete mTransformMatrix3D; - delete mStaticMatrix; - delete mAnimationMatrix; - - mTransformMatrix = NULL; - mTransformCamera = NULL; - mTransformMatrix3D = NULL; - mStaticMatrix = NULL; - mAnimationMatrix = NULL; - - Caches& caches = Caches::getInstance(); - caches.unregisterFunctors(mFunctorCount); - caches.resourceCache.lock(); - - for (size_t i = 0; i < mBitmapResources.size(); i++) { - caches.resourceCache.decrementRefcountLocked(mBitmapResources.itemAt(i)); - } - - for (size_t i = 0; i < mOwnedBitmapResources.size(); i++) { - SkBitmap* bitmap = mOwnedBitmapResources.itemAt(i); - caches.resourceCache.decrementRefcountLocked(bitmap); - caches.resourceCache.destructorLocked(bitmap); - } - - for (size_t i = 0; i < mFilterResources.size(); i++) { - caches.resourceCache.decrementRefcountLocked(mFilterResources.itemAt(i)); - } - - for (size_t i = 0; i < mShaders.size(); i++) { - caches.resourceCache.decrementRefcountLocked(mShaders.itemAt(i)); - caches.resourceCache.destructorLocked(mShaders.itemAt(i)); - } - - for (size_t i = 0; i < mSourcePaths.size(); i++) { - caches.resourceCache.decrementRefcountLocked(mSourcePaths.itemAt(i)); - } - - for (size_t i = 0; i < mLayers.size(); i++) { - caches.resourceCache.decrementRefcountLocked(mLayers.itemAt(i)); - } - - caches.resourceCache.unlock(); - - for (size_t i = 0; i < mPaints.size(); i++) { - delete mPaints.itemAt(i); - } - - for (size_t i = 0; i < mRegions.size(); i++) { - delete mRegions.itemAt(i); - } - - for (size_t i = 0; i < mPaths.size(); i++) { - SkPath* path = mPaths.itemAt(i); - caches.pathCache.remove(path); - delete path; - } - - for (size_t i = 0; i < mMatrices.size(); i++) { - delete mMatrices.itemAt(i); - } - - mBitmapResources.clear(); - mOwnedBitmapResources.clear(); - mFilterResources.clear(); - mShaders.clear(); - mSourcePaths.clear(); - mPaints.clear(); - mRegions.clear(); - mPaths.clear(); - mMatrices.clear(); - mLayers.clear(); -} - -void DisplayList::reset() { - clearResources(); - init(); -} - -void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing) { - if (reusing) { - // re-using display list - clear out previous allocations - clearResources(); - } - - init(); - - mDisplayListData = recorder.getDisplayListData(); - mSize = mDisplayListData->allocator.usedSize(); - - if (mSize == 0) { - return; - } - - mFunctorCount = recorder.getFunctorCount(); - - Caches& caches = Caches::getInstance(); - caches.registerFunctors(mFunctorCount); - caches.resourceCache.lock(); - - const Vector<SkBitmap*>& bitmapResources = recorder.getBitmapResources(); - for (size_t i = 0; i < bitmapResources.size(); i++) { - SkBitmap* resource = bitmapResources.itemAt(i); - mBitmapResources.add(resource); - caches.resourceCache.incrementRefcountLocked(resource); - } - - const Vector<SkBitmap*> &ownedBitmapResources = recorder.getOwnedBitmapResources(); - for (size_t i = 0; i < ownedBitmapResources.size(); i++) { - SkBitmap* resource = ownedBitmapResources.itemAt(i); - mOwnedBitmapResources.add(resource); - caches.resourceCache.incrementRefcountLocked(resource); - } - - const Vector<SkiaColorFilter*>& filterResources = recorder.getFilterResources(); - for (size_t i = 0; i < filterResources.size(); i++) { - SkiaColorFilter* resource = filterResources.itemAt(i); - mFilterResources.add(resource); - caches.resourceCache.incrementRefcountLocked(resource); - } - - const Vector<SkiaShader*>& shaders = recorder.getShaders(); - for (size_t i = 0; i < shaders.size(); i++) { - SkiaShader* resource = shaders.itemAt(i); - mShaders.add(resource); - caches.resourceCache.incrementRefcountLocked(resource); - } - - const SortedVector<SkPath*>& sourcePaths = recorder.getSourcePaths(); - for (size_t i = 0; i < sourcePaths.size(); i++) { - mSourcePaths.add(sourcePaths.itemAt(i)); - caches.resourceCache.incrementRefcountLocked(sourcePaths.itemAt(i)); - } - - const Vector<Layer*>& layers = recorder.getLayers(); - for (size_t i = 0; i < layers.size(); i++) { - mLayers.add(layers.itemAt(i)); - caches.resourceCache.incrementRefcountLocked(layers.itemAt(i)); - } - - caches.resourceCache.unlock(); - - mPaints.appendVector(recorder.getPaints()); - mRegions.appendVector(recorder.getRegions()); - mPaths.appendVector(recorder.getPaths()); - mMatrices.appendVector(recorder.getMatrices()); -} - -void DisplayList::init() { - mSize = 0; - mIsRenderable = true; - mFunctorCount = 0; - mLeft = 0; - mTop = 0; - mRight = 0; - mBottom = 0; - mClipChildren = true; - mAlpha = 1; - mMultipliedAlpha = 255; - mHasOverlappingRendering = true; - mTranslationX = 0; - mTranslationY = 0; - mRotation = 0; - mRotationX = 0; - mRotationY= 0; - mScaleX = 1; - mScaleY = 1; - mPivotX = 0; - mPivotY = 0; - mCameraDistance = 0; - mMatrixDirty = false; - mMatrixFlags = 0; - mPrevWidth = -1; - mPrevHeight = -1; - mWidth = 0; - mHeight = 0; - mPivotExplicitlySet = false; - mCaching = false; -} - -size_t DisplayList::getSize() { - return mSize; -} - -/** - * This function is a simplified version of replay(), where we simply retrieve and log the - * display list. This function should remain in sync with the replay() function. - */ -void DisplayList::output(uint32_t level) { - ALOGD("%*sStart display list (%p, %s, render=%d)", level * 2, "", this, - mName.string(), isRenderable()); - - ALOGD("%*s%s %d", level * 2, "", "Save", SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag); - outputViewProperties(level); - int flags = DisplayListOp::kOpLogFlag_Recurse; - for (unsigned int i = 0; i < mDisplayListData->displayListOps.size(); i++) { - mDisplayListData->displayListOps[i]->output(level, flags); - } - ALOGD("%*sDone (%p, %s)", level * 2, "", this, mName.string()); -} - -void DisplayList::updateMatrix() { - if (mMatrixDirty) { - if (!mTransformMatrix) { - mTransformMatrix = new SkMatrix(); - } - if (mMatrixFlags == 0 || mMatrixFlags == TRANSLATION) { - mTransformMatrix->reset(); - } else { - if (!mPivotExplicitlySet) { - if (mWidth != mPrevWidth || mHeight != mPrevHeight) { - mPrevWidth = mWidth; - mPrevHeight = mHeight; - mPivotX = mPrevWidth / 2; - mPivotY = mPrevHeight / 2; - } - } - if ((mMatrixFlags & ROTATION_3D) == 0) { - mTransformMatrix->setTranslate(mTranslationX, mTranslationY); - mTransformMatrix->preRotate(mRotation, mPivotX, mPivotY); - mTransformMatrix->preScale(mScaleX, mScaleY, mPivotX, mPivotY); - } else { - if (!mTransformCamera) { - mTransformCamera = new Sk3DView(); - mTransformMatrix3D = new SkMatrix(); - } - mTransformMatrix->reset(); - mTransformCamera->save(); - mTransformMatrix->preScale(mScaleX, mScaleY, mPivotX, mPivotY); - mTransformCamera->rotateX(mRotationX); - mTransformCamera->rotateY(mRotationY); - mTransformCamera->rotateZ(-mRotation); - mTransformCamera->getMatrix(mTransformMatrix3D); - mTransformMatrix3D->preTranslate(-mPivotX, -mPivotY); - mTransformMatrix3D->postTranslate(mPivotX + mTranslationX, - mPivotY + mTranslationY); - mTransformMatrix->postConcat(*mTransformMatrix3D); - mTransformCamera->restore(); - } - } - mMatrixDirty = false; - } -} - -void DisplayList::outputViewProperties(uint32_t level) { - updateMatrix(); - if (mLeft != 0 || mTop != 0) { - ALOGD("%*sTranslate (left, top) %d, %d", level * 2, "", mLeft, mTop); - } - if (mStaticMatrix) { - ALOGD("%*sConcatMatrix (static) %p: " MATRIX_STRING, - level * 2, "", mStaticMatrix, MATRIX_ARGS(mStaticMatrix)); - } - if (mAnimationMatrix) { - ALOGD("%*sConcatMatrix (animation) %p: " MATRIX_STRING, - level * 2, "", mAnimationMatrix, MATRIX_ARGS(mStaticMatrix)); - } - if (mMatrixFlags != 0) { - if (mMatrixFlags == TRANSLATION) { - ALOGD("%*sTranslate %f, %f", level * 2, "", mTranslationX, mTranslationY); - } else { - ALOGD("%*sConcatMatrix %p: " MATRIX_STRING, - level * 2, "", mTransformMatrix, MATRIX_ARGS(mTransformMatrix)); - } - } - if (mAlpha < 1 && !mCaching) { - if (!mHasOverlappingRendering) { - ALOGD("%*sSetAlpha %.2f", level * 2, "", mAlpha); - } else { - int flags = SkCanvas::kHasAlphaLayer_SaveFlag; - if (mClipChildren) { - flags |= SkCanvas::kClipToLayer_SaveFlag; - } - ALOGD("%*sSaveLayerAlpha %.2f, %.2f, %.2f, %.2f, %d, 0x%x", level * 2, "", - (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop, - mMultipliedAlpha, flags); - } - } - if (mClipChildren && !mCaching) { - ALOGD("%*sClipRect %.2f, %.2f, %.2f, %.2f", level * 2, "", 0.0f, 0.0f, - (float) mRight - mLeft, (float) mBottom - mTop); - } -} - -void DisplayList::setViewProperties(OpenGLRenderer& renderer, uint32_t level) { -#if DEBUG_DISPLAYLIST - outputViewProperties(level); -#endif - updateMatrix(); - if (mLeft != 0 || mTop != 0) { - renderer.translate(mLeft, mTop); - } - if (mStaticMatrix) { - renderer.concatMatrix(mStaticMatrix); - } else if (mAnimationMatrix) { - renderer.concatMatrix(mAnimationMatrix); - } - if (mMatrixFlags != 0) { - if (mMatrixFlags == TRANSLATION) { - renderer.translate(mTranslationX, mTranslationY); - } else { - renderer.concatMatrix(mTransformMatrix); - } - } - if (mAlpha < 1 && !mCaching) { - if (!mHasOverlappingRendering) { - renderer.setAlpha(mAlpha); - } else { - // TODO: should be able to store the size of a DL at record time and not - // have to pass it into this call. In fact, this information might be in the - // location/size info that we store with the new native transform data. - int flags = SkCanvas::kHasAlphaLayer_SaveFlag; - if (mClipChildren) { - flags |= SkCanvas::kClipToLayer_SaveFlag; - } - renderer.saveLayerAlpha(0, 0, mRight - mLeft, mBottom - mTop, - mMultipliedAlpha, flags); - } - } - if (mClipChildren && !mCaching) { - renderer.clipRect(0, 0, mRight - mLeft, mBottom - mTop, - SkRegion::kIntersect_Op); - } -} - -status_t DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, uint32_t level) { - status_t drawGlStatus = DrawGlInfo::kStatusDone; - -#if DEBUG_DISPLAY_LIST - Rect* clipRect = renderer.getClipRect(); - DISPLAY_LIST_LOGD("%*sStart display list (%p, %s), clipRect: %.0f, %.f, %.0f, %.0f", - (level+1)*2, "", this, mName.string(), clipRect->left, clipRect->top, - clipRect->right, clipRect->bottom); -#endif - - renderer.startMark(mName.string()); - - int restoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag); - DISPLAY_LIST_LOGD("%*sSave %d %d", level * 2, "", - SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag, restoreTo); - setViewProperties(renderer, level); - - if (renderer.quickRejectNoScissor(0, 0, mWidth, mHeight)) { - DISPLAY_LIST_LOGD("%*sRestoreToCount %d", level * 2, "", restoreTo); - renderer.restoreToCount(restoreTo); - renderer.endMark(); - return drawGlStatus; - } - - DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance(); - int saveCount = renderer.getSaveCount() - 1; - for (unsigned int i = 0; i < mDisplayListData->displayListOps.size(); i++) { - DisplayListOp *op = mDisplayListData->displayListOps[i]; -#if DEBUG_DISPLAY_LIST_OPS_AS_EVENTS - Caches::getInstance().eventMark(strlen(op->name()), op->name()); -#endif - - drawGlStatus |= op->replay(renderer, dirty, flags, - saveCount, level, mCaching, mMultipliedAlpha); - logBuffer.writeCommand(level, op->name()); - } - - DISPLAY_LIST_LOGD("%*sRestoreToCount %d", level * 2, "", restoreTo); - renderer.restoreToCount(restoreTo); - renderer.endMark(); - - DISPLAY_LIST_LOGD("%*sDone (%p, %s), returning %d", (level + 1) * 2, "", this, mName.string(), - drawGlStatus); - return drawGlStatus; -} - -/////////////////////////////////////////////////////////////////////////////// -// Base structure -/////////////////////////////////////////////////////////////////////////////// - DisplayListRenderer::DisplayListRenderer(): mCaches(Caches::getInstance()), mDisplayListData(new DisplayListData), mTranslateX(0.0f), mTranslateY(0.0f), mHasTranslate(false), diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h index b25288b1f059..97a25085830d 100644 --- a/libs/hwui/DisplayListRenderer.h +++ b/libs/hwui/DisplayListRenderer.h @@ -17,21 +17,14 @@ #ifndef ANDROID_HWUI_DISPLAY_LIST_RENDERER_H #define ANDROID_HWUI_DISPLAY_LIST_RENDERER_H -#include <SkChunkAlloc.h> -#include <SkFlattenable.h> #include <SkMatrix.h> -#include <SkCamera.h> #include <SkPaint.h> #include <SkPath.h> -#include <SkRefCnt.h> -#include <SkTDArray.h> -#include <SkTSearch.h> - #include <cutils/compiler.h> +#include "DisplayList.h" #include "DisplayListLogBuffer.h" #include "OpenGLRenderer.h" -#include "utils/LinearAllocator.h" namespace android { namespace uirenderer { @@ -50,12 +43,6 @@ namespace uirenderer { #define DISPLAY_LIST_LOGD(...) #endif -#define TRANSLATION 0x0001 -#define ROTATION 0x0002 -#define ROTATION_3D 0x0004 -#define SCALE 0x0008 -#define PIVOT 0x0010 - /////////////////////////////////////////////////////////////////////////////// // Display list /////////////////////////////////////////////////////////////////////////////// @@ -65,370 +52,6 @@ class DisplayListOp; class DrawOp; class StateOp; -/** - * Refcounted structure that holds data used in display list stream - */ -class DisplayListData: public LightRefBase<DisplayListData> { -public: - LinearAllocator allocator; - Vector<DisplayListOp*> displayListOps; -}; - -/** - * Replays recorded drawing commands. - */ -class DisplayList { -public: - DisplayList(const DisplayListRenderer& recorder); - ANDROID_API ~DisplayList(); - - // See flags defined in DisplayList.java - enum ReplayFlag { - kReplayFlag_ClipChildren = 0x1 - }; - - void setViewProperties(OpenGLRenderer& renderer, uint32_t level); - void outputViewProperties(uint32_t level); - - ANDROID_API size_t getSize(); - ANDROID_API static void destroyDisplayListDeferred(DisplayList* displayList); - ANDROID_API static void outputLogBuffer(int fd); - - void initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing = false); - - status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, uint32_t level = 0); - - void output(uint32_t level = 0); - - ANDROID_API void reset(); - - void setRenderable(bool renderable) { - mIsRenderable = renderable; - } - - bool isRenderable() const { - return mIsRenderable; - } - - void setName(const char* name) { - if (name) { - mName.setTo(name); - } - } - - void setClipChildren(bool clipChildren) { - mClipChildren = clipChildren; - } - - void setStaticMatrix(SkMatrix* matrix) { - delete mStaticMatrix; - mStaticMatrix = new SkMatrix(*matrix); - } - - void setAnimationMatrix(SkMatrix* matrix) { - delete mAnimationMatrix; - if (matrix) { - mAnimationMatrix = new SkMatrix(*matrix); - } else { - mAnimationMatrix = NULL; - } - } - - void setAlpha(float alpha) { - alpha = fminf(1.0f, fmaxf(0.0f, alpha)); - if (alpha != mAlpha) { - mAlpha = alpha; - mMultipliedAlpha = (int) (255 * alpha); - } - } - - void setHasOverlappingRendering(bool hasOverlappingRendering) { - mHasOverlappingRendering = hasOverlappingRendering; - } - - void setTranslationX(float translationX) { - if (translationX != mTranslationX) { - mTranslationX = translationX; - mMatrixDirty = true; - if (mTranslationX == 0.0f && mTranslationY == 0.0f) { - mMatrixFlags &= ~TRANSLATION; - } else { - mMatrixFlags |= TRANSLATION; - } - } - } - - void setTranslationY(float translationY) { - if (translationY != mTranslationY) { - mTranslationY = translationY; - mMatrixDirty = true; - if (mTranslationX == 0.0f && mTranslationY == 0.0f) { - mMatrixFlags &= ~TRANSLATION; - } else { - mMatrixFlags |= TRANSLATION; - } - } - } - - void setRotation(float rotation) { - if (rotation != mRotation) { - mRotation = rotation; - mMatrixDirty = true; - if (mRotation == 0.0f) { - mMatrixFlags &= ~ROTATION; - } else { - mMatrixFlags |= ROTATION; - } - } - } - - void setRotationX(float rotationX) { - if (rotationX != mRotationX) { - mRotationX = rotationX; - mMatrixDirty = true; - if (mRotationX == 0.0f && mRotationY == 0.0f) { - mMatrixFlags &= ~ROTATION_3D; - } else { - mMatrixFlags |= ROTATION_3D; - } - } - } - - void setRotationY(float rotationY) { - if (rotationY != mRotationY) { - mRotationY = rotationY; - mMatrixDirty = true; - if (mRotationX == 0.0f && mRotationY == 0.0f) { - mMatrixFlags &= ~ROTATION_3D; - } else { - mMatrixFlags |= ROTATION_3D; - } - } - } - - void setScaleX(float scaleX) { - if (scaleX != mScaleX) { - mScaleX = scaleX; - mMatrixDirty = true; - if (mScaleX == 1.0f && mScaleY == 1.0f) { - mMatrixFlags &= ~SCALE; - } else { - mMatrixFlags |= SCALE; - } - } - } - - void setScaleY(float scaleY) { - if (scaleY != mScaleY) { - mScaleY = scaleY; - mMatrixDirty = true; - if (mScaleX == 1.0f && mScaleY == 1.0f) { - mMatrixFlags &= ~SCALE; - } else { - mMatrixFlags |= SCALE; - } - } - } - - void setPivotX(float pivotX) { - mPivotX = pivotX; - mMatrixDirty = true; - if (mPivotX == 0.0f && mPivotY == 0.0f) { - mMatrixFlags &= ~PIVOT; - } else { - mMatrixFlags |= PIVOT; - } - mPivotExplicitlySet = true; - } - - void setPivotY(float pivotY) { - mPivotY = pivotY; - mMatrixDirty = true; - if (mPivotX == 0.0f && mPivotY == 0.0f) { - mMatrixFlags &= ~PIVOT; - } else { - mMatrixFlags |= PIVOT; - } - mPivotExplicitlySet = true; - } - - void setCameraDistance(float distance) { - if (distance != mCameraDistance) { - mCameraDistance = distance; - mMatrixDirty = true; - if (!mTransformCamera) { - mTransformCamera = new Sk3DView(); - mTransformMatrix3D = new SkMatrix(); - } - mTransformCamera->setCameraLocation(0, 0, distance); - } - } - - void setLeft(int left) { - if (left != mLeft) { - mLeft = left; - mWidth = mRight - mLeft; - if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) { - mMatrixDirty = true; - } - } - } - - void setTop(int top) { - if (top != mTop) { - mTop = top; - mHeight = mBottom - mTop; - if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) { - mMatrixDirty = true; - } - } - } - - void setRight(int right) { - if (right != mRight) { - mRight = right; - mWidth = mRight - mLeft; - if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) { - mMatrixDirty = true; - } - } - } - - void setBottom(int bottom) { - if (bottom != mBottom) { - mBottom = bottom; - mHeight = mBottom - mTop; - if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) { - mMatrixDirty = true; - } - } - } - - void setLeftTop(int left, int top) { - if (left != mLeft || top != mTop) { - mLeft = left; - mTop = top; - mWidth = mRight - mLeft; - mHeight = mBottom - mTop; - if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) { - mMatrixDirty = true; - } - } - } - - void setLeftTopRightBottom(int left, int top, int right, int bottom) { - if (left != mLeft || top != mTop || right != mRight || bottom != mBottom) { - mLeft = left; - mTop = top; - mRight = right; - mBottom = bottom; - mWidth = mRight - mLeft; - mHeight = mBottom - mTop; - if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) { - mMatrixDirty = true; - } - } - } - - void offsetLeftRight(int offset) { - if (offset != 0) { - mLeft += offset; - mRight += offset; - if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) { - mMatrixDirty = true; - } - } - } - - void offsetTopBottom(int offset) { - if (offset != 0) { - mTop += offset; - mBottom += offset; - if (mMatrixFlags > TRANSLATION && !mPivotExplicitlySet) { - mMatrixDirty = true; - } - } - } - - void setCaching(bool caching) { - mCaching = caching; - } - - int getWidth() { - return mWidth; - } - - int getHeight() { - return mHeight; - } - -private: - void init(); - - void clearResources(); - - void updateMatrix(); - - class TextContainer { - public: - size_t length() const { - return mByteLength; - } - - const char* text() const { - return (const char*) mText; - } - - size_t mByteLength; - const char* mText; - }; - - Vector<SkBitmap*> mBitmapResources; - Vector<SkBitmap*> mOwnedBitmapResources; - Vector<SkiaColorFilter*> mFilterResources; - - Vector<SkPaint*> mPaints; - Vector<SkPath*> mPaths; - SortedVector<SkPath*> mSourcePaths; - Vector<SkRegion*> mRegions; - Vector<SkMatrix*> mMatrices; - Vector<SkiaShader*> mShaders; - Vector<Layer*> mLayers; - - sp<DisplayListData> mDisplayListData; - - size_t mSize; - - bool mIsRenderable; - uint32_t mFunctorCount; - - String8 mName; - - // View properties - bool mClipChildren; - float mAlpha; - int mMultipliedAlpha; - bool mHasOverlappingRendering; - float mTranslationX, mTranslationY; - float mRotation, mRotationX, mRotationY; - float mScaleX, mScaleY; - float mPivotX, mPivotY; - float mCameraDistance; - int mLeft, mTop, mRight, mBottom; - int mWidth, mHeight; - int mPrevWidth, mPrevHeight; - bool mPivotExplicitlySet; - bool mMatrixDirty; - bool mMatrixIsIdentity; - uint32_t mMatrixFlags; - SkMatrix* mTransformMatrix; - Sk3DView* mTransformCamera; - SkMatrix* mTransformMatrix3D; - SkMatrix* mStaticMatrix; - SkMatrix* mAnimationMatrix; - bool mCaching; -}; - /////////////////////////////////////////////////////////////////////////////// // Renderer /////////////////////////////////////////////////////////////////////////////// |