1ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy/* 2ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy * Copyright (C) 2012 The Android Open Source Project 3ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy * 4ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy * Licensed under the Apache License, Version 2.0 (the "License"); 5ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy * you may not use this file except in compliance with the License. 6ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy * You may obtain a copy of the License at 7ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy * 8ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy * http://www.apache.org/licenses/LICENSE-2.0 9ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy * 10ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy * Unless required by applicable law or agreed to in writing, software 11ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy * distributed under the License is distributed on an "AS IS" BASIS, 12ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy * See the License for the specific language governing permissions and 14ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy * limitations under the License. 15ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy */ 16ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 17ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy#include "Snapshot.h" 18ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 19dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include "hwui/Canvas.h" 20ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 21ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guynamespace android { 22ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guynamespace uirenderer { 23ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 24ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy/////////////////////////////////////////////////////////////////////////////// 25ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy// Constructors 26ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy/////////////////////////////////////////////////////////////////////////////// 27ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 28e4aa95e3627226bcb0d8cc3e42dca6e4df8f421cChris CraikSnapshot::Snapshot() 29e4aa95e3627226bcb0d8cc3e42dca6e4df8f421cChris Craik : flags(0) 30d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik , previous(nullptr) 31d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik , layer(nullptr) 32e4aa95e3627226bcb0d8cc3e42dca6e4df8f421cChris Craik , fbo(0) 33deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik , alpha(1.0f) 34487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk , roundRectClipState(nullptr) 35fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik , projectionPathMask(nullptr) 36487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk , mClipArea(&mClipAreaRoot) { 37ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy transform = &mTransformRoot; 38de89c2fd708d9d7a7e7990e2d6da77c8481a0217Keith Mok mRelativeLightCenter.x = mRelativeLightCenter.y = mRelativeLightCenter.z = 0; 39ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy} 40ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 41ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy/** 42ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy * Copies the specified snapshot/ The specified snapshot is stored as 43ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy * the previous snapshot. 44ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy */ 45d9ee550888011a64fa3f35e666360ec8278597d8John ReckSnapshot::Snapshot(Snapshot* s, int saveFlags) 46e4aa95e3627226bcb0d8cc3e42dca6e4df8f421cChris Craik : flags(0) 47e4aa95e3627226bcb0d8cc3e42dca6e4df8f421cChris Craik , previous(s) 48e4aa95e3627226bcb0d8cc3e42dca6e4df8f421cChris Craik , layer(s->layer) 49e4aa95e3627226bcb0d8cc3e42dca6e4df8f421cChris Craik , fbo(s->fbo) 50a64a2bef1048db5a742843f1e3bea9e80d0defc5Chris Craik , alpha(s->alpha) 51deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik , roundRectClipState(s->roundRectClipState) 52fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik , projectionPathMask(s->projectionPathMask) 53487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk , mClipArea(nullptr) 5469e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik , mViewportData(s->mViewportData) 5569e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik , mRelativeLightCenter(s->mRelativeLightCenter) { 56eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita if (saveFlags & SaveFlags::Matrix) { 577c85c54499994c687a833644f7f213e747fadb98Chris Craik mTransformRoot = *s->transform; 58ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy transform = &mTransformRoot; 59ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy } else { 60ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy transform = s->transform; 61ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy } 62ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 63eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita if (saveFlags & SaveFlags::Clip) { 64487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipAreaRoot = s->getClipArea(); 65487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipArea = &mClipAreaRoot; 66ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy } else { 67487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipArea = s->mClipArea; 68ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy } 69ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy} 70ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 71ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy/////////////////////////////////////////////////////////////////////////////// 72ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy// Clipping 73ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy/////////////////////////////////////////////////////////////////////////////// 74ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 756e49c9f007c879f05b035c40c0ba543c00f9d0d0Mike Reedvoid Snapshot::clip(const Rect& localClip, SkClipOp op) { 76487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk flags |= Snapshot::kFlagClipSet; 776e49c9f007c879f05b035c40c0ba543c00f9d0d0Mike Reed mClipArea->clipRectWithTransform(localClip, transform, static_cast<SkRegion::Op>(op)); 78ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy} 79ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 806e49c9f007c879f05b035c40c0ba543c00f9d0d0Mike Reedvoid Snapshot::clipPath(const SkPath& path, SkClipOp op) { 81487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk flags |= Snapshot::kFlagClipSet; 826e49c9f007c879f05b035c40c0ba543c00f9d0d0Mike Reed mClipArea->clipPathWithTransform(path, transform, static_cast<SkRegion::Op>(op)); 83ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy} 84ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 85ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guyvoid Snapshot::setClip(float left, float top, float right, float bottom) { 86ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy flags |= Snapshot::kFlagClipSet; 874d3e704b04c6abd7995df640d12662b0271f6c7bChris Craik mClipArea->setClip(left, top, right, bottom); 88ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy} 89ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 90a3dc55f83ab583e0a66b893c71b849afa046770aRomain Guybool Snapshot::hasPerspectiveTransform() const { 91a3dc55f83ab583e0a66b893c71b849afa046770aRomain Guy return transform->isPerspective(); 92a3dc55f83ab583e0a66b893c71b849afa046770aRomain Guy} 93a3dc55f83ab583e0a66b893c71b849afa046770aRomain Guy 94ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guyconst Rect& Snapshot::getLocalClip() { 95ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy mat4 inverse; 96ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy inverse.loadInverse(*transform); 97ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 98487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mLocalClip.set(mClipArea->getClipRect()); 99ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy inverse.mapRect(mLocalClip); 100ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 101ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy return mLocalClip; 102ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy} 103ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 104ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guyvoid Snapshot::resetClip(float left, float top, float right, float bottom) { 1053bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy // TODO: This is incorrect, when we start rendering into a new layer, 1063bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy // we may have to modify the previous snapshot's clip rect and clip 1073bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy // region if the previous restore() call did not restore the clip 108487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipArea = &mClipAreaRoot; 109967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy setClip(left, top, right, bottom); 110ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy} 111ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 112ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy/////////////////////////////////////////////////////////////////////////////// 113af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik// Clipping round rect 114deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik/////////////////////////////////////////////////////////////////////////////// 115deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik 116e83cbd451868a734bfac07ccd680d5617080b579Chris Craikvoid Snapshot::setClippingRoundRect(LinearAllocator& allocator, const Rect& bounds, 117e83cbd451868a734bfac07ccd680d5617080b579Chris Craik float radius, bool highPriority) { 118af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik if (bounds.isEmpty()) { 119487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipArea->setEmpty(); 120af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik return; 121af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik } 122deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik 123e83cbd451868a734bfac07ccd680d5617080b579Chris Craik if (roundRectClipState && roundRectClipState->highPriority) { 124e83cbd451868a734bfac07ccd680d5617080b579Chris Craik // ignore, don't replace, already have a high priority clip 125e83cbd451868a734bfac07ccd680d5617080b579Chris Craik return; 126e83cbd451868a734bfac07ccd680d5617080b579Chris Craik } 127e83cbd451868a734bfac07ccd680d5617080b579Chris Craik 128deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik RoundRectClipState* state = new (allocator) RoundRectClipState; 129deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik 130e83cbd451868a734bfac07ccd680d5617080b579Chris Craik state->highPriority = highPriority; 131e83cbd451868a734bfac07ccd680d5617080b579Chris Craik 132deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik // store the inverse drawing matrix 1337c85c54499994c687a833644f7f213e747fadb98Chris Craik Matrix4 roundRectDrawingMatrix = getOrthoMatrix(); 134af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik roundRectDrawingMatrix.multiply(*transform); 135af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik state->matrix.loadInverse(roundRectDrawingMatrix); 136deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik 137deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik // compute area under rounded corners - only draws overlapping these rects need to be clipped 138deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik for (int i = 0 ; i < 4; i++) { 139deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik state->dangerRects[i] = bounds; 140deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik } 141deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik state->dangerRects[0].bottom = state->dangerRects[1].bottom = bounds.top + radius; 142deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik state->dangerRects[0].right = state->dangerRects[2].right = bounds.left + radius; 143deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik state->dangerRects[1].left = state->dangerRects[3].left = bounds.right - radius; 144deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik state->dangerRects[2].top = state->dangerRects[3].top = bounds.bottom - radius; 145deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik for (int i = 0; i < 4; i++) { 146deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik transform->mapRect(state->dangerRects[i]); 147deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik 148deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik // round danger rects out as though they are AA geometry (since they essentially are) 149deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik state->dangerRects[i].snapGeometryToPixelBoundaries(true); 150deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik } 151deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik 152deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik // store RR area 153af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik state->innerRect = bounds; 154af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik state->innerRect.inset(radius); 155af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik state->radius = radius; 156deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik 157deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik // store as immutable so, for this frame, pointer uniquely identifies this bundle of shader info 158deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik roundRectClipState = state; 159deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik} 160deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik 1615e00c7ce063116c11315639f0035aca8ad73e8ccChris Craikvoid Snapshot::setProjectionPathMask(const SkPath* path) { 162678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik projectionPathMask = path; 163fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik} 164fca52b7583d1e5f5ff8ed06554875d2a30ef56faChris Craik 16504d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craikstatic Snapshot* getClipRoot(Snapshot* target) { 16604d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik while (target->previous && target->previous->previous) { 16704d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik target = target->previous; 16804d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik } 16904d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik return target; 17004d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik} 17104d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik 17204d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craikconst ClipBase* Snapshot::serializeIntersectedClip(LinearAllocator& allocator, 17304d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik const ClipBase* recordedClip, const Matrix4& recordedClipTransform) { 17404d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik auto target = this; 17504d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik if (CC_UNLIKELY(recordedClip && recordedClip->intersectWithRoot)) { 17604d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik // Clip must be intersected with root, instead of current clip. 17704d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik target = getClipRoot(this); 17804d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik } 17904d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik 18004d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik return target->mClipArea->serializeIntersectedClip(allocator, 18104d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik recordedClip, recordedClipTransform); 18204d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik} 18304d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik 18404d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craikvoid Snapshot::applyClip(const ClipBase* recordedClip, const Matrix4& transform) { 18504d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik if (CC_UNLIKELY(recordedClip && recordedClip->intersectWithRoot)) { 18604d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik // current clip is being replaced, but must intersect with clip root 18704d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik *mClipArea = *(getClipRoot(this)->mClipArea); 18804d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik } 18904d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik mClipArea->applyClip(recordedClip, transform); 19004d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik} 19104d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik 192deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik/////////////////////////////////////////////////////////////////////////////// 193ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy// Queries 194ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy/////////////////////////////////////////////////////////////////////////////// 195ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 1965f803623559aab395a29d575c37c4e39c23a4b4eChris Craikvoid Snapshot::dump() const { 1975e00c7ce063116c11315639f0035aca8ad73e8ccChris Craik ALOGD("Snapshot %p, flags %x, prev %p, height %d, hasComplexClip %d", 1985e00c7ce063116c11315639f0035aca8ad73e8ccChris Craik this, flags, previous, getViewportHeight(), !mClipArea->isSimple()); 199487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const Rect& clipRect(mClipArea->getClipRect()); 200e9c01a40a2f0f0da195dfbb2909aaee5c005d1c6Chris Craik ALOGD(" ClipRect %.1f %.1f %.1f %.1f, clip simple %d", 201e9c01a40a2f0f0da195dfbb2909aaee5c005d1c6Chris Craik clipRect.left, clipRect.top, clipRect.right, clipRect.bottom, mClipArea->isSimple()); 202e9c01a40a2f0f0da195dfbb2909aaee5c005d1c6Chris Craik 2035f803623559aab395a29d575c37c4e39c23a4b4eChris Craik ALOGD(" Transform (at %p):", transform); 2045f803623559aab395a29d575c37c4e39c23a4b4eChris Craik transform->dump(); 2055f803623559aab395a29d575c37c4e39c23a4b4eChris Craik} 2065f803623559aab395a29d575c37c4e39c23a4b4eChris Craik 207ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy}; // namespace uirenderer 208ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy}; // namespace android 209