RenderProperties.cpp revision cc39e16cb98855f35079941b5e7e6eac2b7bc388
1acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck/* 2acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * Copyright (C) 2014 The Android Open Source Project 3acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * 4acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * Licensed under the Apache License, Version 2.0 (the "License"); 5d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck * you mPrimitiveFields.may not use this file except in compliance with the License. 6d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck * You mPrimitiveFields.may obtain a copy of the License at 7acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * 8acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * http://www.apache.org/licenses/LICENSE-2.0 9acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * 10acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * Unless required by applicable law or agreed to in writing, software 11acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * distributed under the License is distributed on an "AS IS" BASIS, 12acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * See the License for the specific language governing permissions and 14acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck * limitations under the License. 15acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck */ 16d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck 17d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck#define LOG_TAG "OpenGLRenderer" 18d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck 19acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck#include "RenderProperties.h" 20acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck 21d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck#include <utils/Trace.h> 22d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck 23d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck#include <SkCanvas.h> 24acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck#include <SkMatrix.h> 258c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik#include <SkPath.h> 268c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik#include <SkPathOps.h> 27acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck 28acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck#include "Matrix.h" 29e0bb87d4bdbd3b08ab6a8569c8e564ed59b8a5a7Chris Craik#include "utils/MathUtils.h" 30f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck 31acb6f07623b7df3d4179f70ae03ade574616ffa6John Recknamespace android { 32acb6f07623b7df3d4179f70ae03ade574616ffa6John Recknamespace uirenderer { 33acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck 34d0a0b2a3140bfb1819a116413ce9d81886697a07John ReckRenderProperties::PrimitiveFields::PrimitiveFields() 35acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck : mClipToBounds(true) 36acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck , mProjectBackwards(false) 37acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck , mProjectionReceiver(false) 38acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck , mAlpha(1) 39acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck , mHasOverlappingRendering(true) 40cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik , mElevation(0) 41acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck , mTranslationX(0), mTranslationY(0), mTranslationZ(0) 42acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck , mRotation(0), mRotationX(0), mRotationY(0) 43acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck , mScaleX(1), mScaleY(1) 44acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck , mPivotX(0), mPivotY(0) 45acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck , mLeft(0), mTop(0), mRight(0), mBottom(0) 46acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck , mWidth(0), mHeight(0) 47acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck , mPivotExplicitlySet(false) 48f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck , mMatrixOrPivotDirty(false) 49acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck , mCaching(false) { 50acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck} 51acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck 52d0a0b2a3140bfb1819a116413ce9d81886697a07John ReckRenderProperties::ComputedFields::ComputedFields() 53d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck : mTransformMatrix(NULL) 548c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik , mClipPath(NULL) { 55d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck} 56d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck 57d0a0b2a3140bfb1819a116413ce9d81886697a07John ReckRenderProperties::ComputedFields::~ComputedFields() { 58acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck delete mTransformMatrix; 598c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik delete mClipPath; 60d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck} 61d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck 62d0a0b2a3140bfb1819a116413ce9d81886697a07John ReckRenderProperties::RenderProperties() 6349e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik : mStaticMatrix(NULL) 64d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck , mAnimationMatrix(NULL) { 65d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck} 66d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck 67d0a0b2a3140bfb1819a116413ce9d81886697a07John ReckRenderProperties::~RenderProperties() { 68acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck delete mStaticMatrix; 69acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck delete mAnimationMatrix; 70acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck} 71acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck 72d0a0b2a3140bfb1819a116413ce9d81886697a07John ReckRenderProperties& RenderProperties::operator=(const RenderProperties& other) { 73d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck if (this != &other) { 74d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck mPrimitiveFields = other.mPrimitiveFields; 75d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck setStaticMatrix(other.getStaticMatrix()); 76d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck setAnimationMatrix(other.getAnimationMatrix()); 77d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck setCameraDistance(other.getCameraDistance()); 78d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck 7949e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik // Update the computed clip path 808c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik updateClipPath(); 8149e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik 8249e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik // Force recalculation of the matrix, since other's dirty bit may be clear 83f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck mPrimitiveFields.mMatrixOrPivotDirty = true; 8449e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik updateMatrix(); 85d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck } 86d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck return *this; 87acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck} 88acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck 89d0a0b2a3140bfb1819a116413ce9d81886697a07John Reckvoid RenderProperties::debugOutputProperties(const int level) const { 90d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck if (mPrimitiveFields.mLeft != 0 || mPrimitiveFields.mTop != 0) { 91d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck ALOGD("%*sTranslate (left, top) %d, %d", level * 2, "", mPrimitiveFields.mLeft, mPrimitiveFields.mTop); 92d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck } 93d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck if (mStaticMatrix) { 94d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck ALOGD("%*sConcatMatrix (static) %p: " SK_MATRIX_STRING, 95d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck level * 2, "", mStaticMatrix, SK_MATRIX_ARGS(mStaticMatrix)); 96d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck } 97d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck if (mAnimationMatrix) { 98d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck ALOGD("%*sConcatMatrix (animation) %p: " SK_MATRIX_STRING, 99d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck level * 2, "", mAnimationMatrix, SK_MATRIX_ARGS(mAnimationMatrix)); 100d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck } 101f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck if (hasTransformMatrix()) { 102f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck if (isTransformTranslateOnly()) { 103d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck ALOGD("%*sTranslate %.2f, %.2f, %.2f", 104cc39e16cb98855f35079941b5e7e6eac2b7bc388Chris Craik level * 2, "", getTranslationX(), getTranslationY(), getZ()); 105d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck } else { 10649e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik ALOGD("%*sConcatMatrix %p: " SK_MATRIX_STRING, 10749e6c73913e9bee58ea5e3984be151ee8e033163Chris Craik level * 2, "", mComputedFields.mTransformMatrix, SK_MATRIX_ARGS(mComputedFields.mTransformMatrix)); 108d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck } 109d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck } 110d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck 111d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck bool clipToBoundsNeeded = mPrimitiveFields.mCaching ? false : mPrimitiveFields.mClipToBounds; 112d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck if (mPrimitiveFields.mAlpha < 1) { 113d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck if (mPrimitiveFields.mCaching) { 114d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck ALOGD("%*sSetOverrideLayerAlpha %.2f", level * 2, "", mPrimitiveFields.mAlpha); 115d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck } else if (!mPrimitiveFields.mHasOverlappingRendering) { 116d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck ALOGD("%*sScaleAlpha %.2f", level * 2, "", mPrimitiveFields.mAlpha); 117d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck } else { 118d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck int flags = SkCanvas::kHasAlphaLayer_SaveFlag; 119d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck if (clipToBoundsNeeded) { 120d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck flags |= SkCanvas::kClipToLayer_SaveFlag; 121d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck clipToBoundsNeeded = false; // clipping done by save layer 122d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck } 12378ce1c5247de60a4247d81d168fd9fa97c7591d0John Reck ALOGD("%*sSaveLayerAlpha %d, %d, %d, %d, %d, 0x%x", level * 2, "", 12478ce1c5247de60a4247d81d168fd9fa97c7591d0John Reck 0, 0, getWidth(), getHeight(), 125d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck (int)(mPrimitiveFields.mAlpha * 255), flags); 126d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck } 127d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck } 128d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck if (clipToBoundsNeeded) { 12978ce1c5247de60a4247d81d168fd9fa97c7591d0John Reck ALOGD("%*sClipRect %d, %d, %d, %d", level * 2, "", 13078ce1c5247de60a4247d81d168fd9fa97c7591d0John Reck 0, 0, getWidth(), getHeight()); 131d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck } 132acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck} 133acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck 134acb6f07623b7df3d4179f70ae03ade574616ffa6John Reckvoid RenderProperties::updateMatrix() { 135f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck if (mPrimitiveFields.mMatrixOrPivotDirty) { 136f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck if (!mComputedFields.mTransformMatrix) { 137f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck // only allocate a mPrimitiveFields.matrix if we have a complex transform 138f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck mComputedFields.mTransformMatrix = new SkMatrix(); 139f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck } 140f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck if (!mPrimitiveFields.mPivotExplicitlySet) { 141f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck mPrimitiveFields.mPivotX = mPrimitiveFields.mWidth / 2.0f; 142f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck mPrimitiveFields.mPivotY = mPrimitiveFields.mHeight / 2.0f; 143f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck } 144f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck SkMatrix* transform = mComputedFields.mTransformMatrix; 145f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck transform->reset(); 146e0bb87d4bdbd3b08ab6a8569c8e564ed59b8a5a7Chris Craik if (MathUtils::isZero(getRotationX()) && MathUtils::isZero(getRotationY())) { 147f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck transform->setTranslate(getTranslationX(), getTranslationY()); 148f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck transform->preRotate(getRotation(), getPivotX(), getPivotY()); 149f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck transform->preScale(getScaleX(), getScaleY(), getPivotX(), getPivotY()); 150f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck } else { 151f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck SkMatrix transform3D; 152f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck mComputedFields.mTransformCamera.save(); 153f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck transform->preScale(getScaleX(), getScaleY(), getPivotX(), getPivotY()); 154f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck mComputedFields.mTransformCamera.rotateX(mPrimitiveFields.mRotationX); 155f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck mComputedFields.mTransformCamera.rotateY(mPrimitiveFields.mRotationY); 156f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck mComputedFields.mTransformCamera.rotateZ(-mPrimitiveFields.mRotation); 157f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck mComputedFields.mTransformCamera.getMatrix(&transform3D); 158f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck transform3D.preTranslate(-getPivotX(), -getPivotY()); 159f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck transform3D.postTranslate(getPivotX() + getTranslationX(), 160f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck getPivotY() + getTranslationY()); 161f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck transform->postConcat(transform3D); 162f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck mComputedFields.mTransformCamera.restore(); 163acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck } 164f7483e3af0513a1baa8341d403df2e0c0896a9ffJohn Reck mPrimitiveFields.mMatrixOrPivotDirty = false; 165acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck } 166acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck} 167acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck 1688c271ca63b62061fd22cfee78fd6a574b44476fdChris Craikvoid RenderProperties::updateClipPath() { 1698c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik const SkPath* outlineClipPath = mPrimitiveFields.mOutline.willClip() 1708c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik ? mPrimitiveFields.mOutline.getPath() : NULL; 1718c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik const SkPath* revealClipPath = mPrimitiveFields.mRevealClip.getPath(); 1728c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik 1738c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik if (!outlineClipPath && !revealClipPath) { 1748c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik // mComputedFields.mClipPath doesn't need to be updated, since it won't be used 1758c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik return; 1768c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik } 1778c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik 1788c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik if (mComputedFields.mClipPath == NULL) { 1798c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik mComputedFields.mClipPath = new SkPath(); 1808c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik } 1818c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik SkPath* clipPath = mComputedFields.mClipPath; 1828c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik mComputedFields.mClipPathOp = SkRegion::kIntersect_Op; 1838c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik 1848c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik if (outlineClipPath && revealClipPath) { 1858c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik SkPathOp op = kIntersect_PathOp; 1868c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik if (mPrimitiveFields.mRevealClip.isInverseClip()) { 1878c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik op = kDifference_PathOp; // apply difference step in the Op below, instead of draw time 1888c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik } 1898c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik 1908c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik Op(*outlineClipPath, *revealClipPath, op, clipPath); 1918c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik } else if (outlineClipPath) { 1928c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik *clipPath = *outlineClipPath; 1938c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik } else { 1948c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik *clipPath = *revealClipPath; 1958c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik if (mPrimitiveFields.mRevealClip.isInverseClip()) { 1968c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik // apply difference step at draw time 1978c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik mComputedFields.mClipPathOp = SkRegion::kDifference_Op; 1988c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik } 1998c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik } 2008c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik} 2018c271ca63b62061fd22cfee78fd6a574b44476fdChris Craik 202acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck} /* namespace uirenderer */ 203acb6f07623b7df3d4179f70ae03ade574616ffa6John Reck} /* namespace android */ 204