Snapshot.cpp revision 487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8
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 175f803623559aab395a29d575c37c4e39c23a4b4eChris Craik#define LOG_TAG "OpenGLRenderer" 185f803623559aab395a29d575c37c4e39c23a4b4eChris Craik 19ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy#include "Snapshot.h" 20ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 21ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy#include <SkCanvas.h> 22ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 23ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guynamespace android { 24ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guynamespace uirenderer { 25ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 26ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy/////////////////////////////////////////////////////////////////////////////// 27ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy// Constructors 28ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy/////////////////////////////////////////////////////////////////////////////// 29ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 30e4aa95e3627226bcb0d8cc3e42dca6e4df8f421cChris CraikSnapshot::Snapshot() 31e4aa95e3627226bcb0d8cc3e42dca6e4df8f421cChris Craik : flags(0) 32d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik , previous(nullptr) 33d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik , layer(nullptr) 34e4aa95e3627226bcb0d8cc3e42dca6e4df8f421cChris Craik , fbo(0) 35e4aa95e3627226bcb0d8cc3e42dca6e4df8f421cChris Craik , invisible(false) 36e4aa95e3627226bcb0d8cc3e42dca6e4df8f421cChris Craik , empty(false) 37deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik , alpha(1.0f) 38487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk , roundRectClipState(nullptr) 39487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk , mClipArea(&mClipAreaRoot) { 40ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy transform = &mTransformRoot; 41d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik region = nullptr; 42ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy} 43ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 44ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy/** 45ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy * Copies the specified snapshot/ The specified snapshot is stored as 46ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy * the previous snapshot. 47ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy */ 48e4aa95e3627226bcb0d8cc3e42dca6e4df8f421cChris CraikSnapshot::Snapshot(const sp<Snapshot>& s, int saveFlags) 49e4aa95e3627226bcb0d8cc3e42dca6e4df8f421cChris Craik : flags(0) 50e4aa95e3627226bcb0d8cc3e42dca6e4df8f421cChris Craik , previous(s) 51e4aa95e3627226bcb0d8cc3e42dca6e4df8f421cChris Craik , layer(s->layer) 52e4aa95e3627226bcb0d8cc3e42dca6e4df8f421cChris Craik , fbo(s->fbo) 53e4aa95e3627226bcb0d8cc3e42dca6e4df8f421cChris Craik , invisible(s->invisible) 54e4aa95e3627226bcb0d8cc3e42dca6e4df8f421cChris Craik , empty(false) 55a64a2bef1048db5a742843f1e3bea9e80d0defc5Chris Craik , alpha(s->alpha) 56deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik , roundRectClipState(s->roundRectClipState) 57487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk , mClipArea(nullptr) 5869e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik , mViewportData(s->mViewportData) 5969e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik , mRelativeLightCenter(s->mRelativeLightCenter) { 60ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy if (saveFlags & SkCanvas::kMatrix_SaveFlag) { 61ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy mTransformRoot.load(*s->transform); 62ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy transform = &mTransformRoot; 63ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy } else { 64ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy transform = s->transform; 65ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy } 66ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 67ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy if (saveFlags & SkCanvas::kClip_SaveFlag) { 68487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipAreaRoot = s->getClipArea(); 69487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipArea = &mClipAreaRoot; 70ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy } else { 71487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipArea = s->mClipArea; 72ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy } 73ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 74ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy if (s->flags & Snapshot::kFlagFboTarget) { 75ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy flags |= Snapshot::kFlagFboTarget; 76ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy region = s->region; 77ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy } else { 78d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik region = nullptr; 79ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy } 80ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy} 81ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 82ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy/////////////////////////////////////////////////////////////////////////////// 83ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy// Clipping 84ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy/////////////////////////////////////////////////////////////////////////////// 85ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 868ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guybool Snapshot::clipRegionTransformed(const SkRegion& region, SkRegion::Op op) { 878ce00301a023eecaeb8891ce906f67b513ebb42aRomain Guy flags |= Snapshot::kFlagClipSet; 88487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return mClipArea->clipRegion(region, op); 89967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy} 90967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy 91ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guybool Snapshot::clip(float left, float top, float right, float bottom, SkRegion::Op op) { 92487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk flags |= Snapshot::kFlagClipSet; 93487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return mClipArea->clipRectWithTransform(left, top, right, bottom, transform, op); 94ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy} 95ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 96487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsukbool Snapshot::clipPath(const SkPath& path, SkRegion::Op op) { 97487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk flags |= Snapshot::kFlagClipSet; 98487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk return mClipArea->clipPathWithTransform(path, transform, op); 99ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy} 100ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 101ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guyvoid Snapshot::setClip(float left, float top, float right, float bottom) { 102487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipArea->setClip(left, top, right, bottom); 103ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy flags |= Snapshot::kFlagClipSet; 104ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy} 105ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 106a3dc55f83ab583e0a66b893c71b849afa046770aRomain Guybool Snapshot::hasPerspectiveTransform() const { 107a3dc55f83ab583e0a66b893c71b849afa046770aRomain Guy return transform->isPerspective(); 108a3dc55f83ab583e0a66b893c71b849afa046770aRomain Guy} 109a3dc55f83ab583e0a66b893c71b849afa046770aRomain Guy 110ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guyconst Rect& Snapshot::getLocalClip() { 111ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy mat4 inverse; 112ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy inverse.loadInverse(*transform); 113ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 114487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mLocalClip.set(mClipArea->getClipRect()); 115ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy inverse.mapRect(mLocalClip); 116ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 117ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy return mLocalClip; 118ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy} 119ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 120ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guyvoid Snapshot::resetClip(float left, float top, float right, float bottom) { 1213bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy // TODO: This is incorrect, when we start rendering into a new layer, 1223bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy // we may have to modify the previous snapshot's clip rect and clip 1233bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy // region if the previous restore() call did not restore the clip 124487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipArea = &mClipAreaRoot; 125967e2bf3ac8943a8e8a374bf86021915445cda67Romain Guy setClip(left, top, right, bottom); 126ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy} 127ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 128ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy/////////////////////////////////////////////////////////////////////////////// 129ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy// Transforms 130ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy/////////////////////////////////////////////////////////////////////////////// 131ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 132ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guyvoid Snapshot::resetTransform(float x, float y, float z) { 13369e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik // before resetting, map current light pos with inverse of current transform 13469e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik Vector3 center = mRelativeLightCenter; 13569e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik mat4 inverse; 13669e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik inverse.loadInverse(*transform); 13769e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik inverse.mapPoint3d(center); 13869e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik mRelativeLightCenter = center; 13969e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik 140ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy transform = &mTransformRoot; 141ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy transform->loadTranslate(x, y, z); 142ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy} 143ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 144ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy/////////////////////////////////////////////////////////////////////////////// 145af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik// Clipping round rect 146deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik/////////////////////////////////////////////////////////////////////////////// 147deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik 148e83cbd451868a734bfac07ccd680d5617080b579Chris Craikvoid Snapshot::setClippingRoundRect(LinearAllocator& allocator, const Rect& bounds, 149e83cbd451868a734bfac07ccd680d5617080b579Chris Craik float radius, bool highPriority) { 150af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik if (bounds.isEmpty()) { 151487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk mClipArea->setEmpty(); 152af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik return; 153af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik } 154deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik 155e83cbd451868a734bfac07ccd680d5617080b579Chris Craik if (roundRectClipState && roundRectClipState->highPriority) { 156e83cbd451868a734bfac07ccd680d5617080b579Chris Craik // ignore, don't replace, already have a high priority clip 157e83cbd451868a734bfac07ccd680d5617080b579Chris Craik return; 158e83cbd451868a734bfac07ccd680d5617080b579Chris Craik } 159e83cbd451868a734bfac07ccd680d5617080b579Chris Craik 160deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik RoundRectClipState* state = new (allocator) RoundRectClipState; 161deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik 162e83cbd451868a734bfac07ccd680d5617080b579Chris Craik state->highPriority = highPriority; 163e83cbd451868a734bfac07ccd680d5617080b579Chris Craik 164deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik // store the inverse drawing matrix 165af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik Matrix4 roundRectDrawingMatrix; 166af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik roundRectDrawingMatrix.load(getOrthoMatrix()); 167af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik roundRectDrawingMatrix.multiply(*transform); 168af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik state->matrix.loadInverse(roundRectDrawingMatrix); 169deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik 170deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik // compute area under rounded corners - only draws overlapping these rects need to be clipped 171deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik for (int i = 0 ; i < 4; i++) { 172deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik state->dangerRects[i] = bounds; 173deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik } 174deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik state->dangerRects[0].bottom = state->dangerRects[1].bottom = bounds.top + radius; 175deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik state->dangerRects[0].right = state->dangerRects[2].right = bounds.left + radius; 176deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik state->dangerRects[1].left = state->dangerRects[3].left = bounds.right - radius; 177deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik state->dangerRects[2].top = state->dangerRects[3].top = bounds.bottom - radius; 178deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik for (int i = 0; i < 4; i++) { 179deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik transform->mapRect(state->dangerRects[i]); 180deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik 181deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik // round danger rects out as though they are AA geometry (since they essentially are) 182deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik state->dangerRects[i].snapGeometryToPixelBoundaries(true); 183deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik } 184deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik 185deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik // store RR area 186af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik state->innerRect = bounds; 187af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik state->innerRect.inset(radius); 188af4d04cab6d48ae0d6a5e79bd30f679af87abaadChris Craik state->radius = radius; 189deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik 190deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik // store as immutable so, for this frame, pointer uniquely identifies this bundle of shader info 191deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik roundRectClipState = state; 192deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik} 193deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik 194deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik/////////////////////////////////////////////////////////////////////////////// 195ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy// Queries 196ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy/////////////////////////////////////////////////////////////////////////////// 197ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 198ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guybool Snapshot::isIgnored() const { 199ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy return invisible || empty; 200ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy} 201ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy 2025f803623559aab395a29d575c37c4e39c23a4b4eChris Craikvoid Snapshot::dump() const { 2035f803623559aab395a29d575c37c4e39c23a4b4eChris Craik ALOGD("Snapshot %p, flags %x, prev %p, height %d, ignored %d, hasComplexClip %d", 204487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk this, flags, previous.get(), getViewportHeight(), isIgnored(), !mClipArea->isSimple()); 205487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk const Rect& clipRect(mClipArea->getClipRect()); 2065f803623559aab395a29d575c37c4e39c23a4b4eChris Craik ALOGD(" ClipRect (at %p) %.1f %.1f %.1f %.1f", 207487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk clipRect, clipRect.left, clipRect.top, clipRect.right, clipRect.bottom); 2085f803623559aab395a29d575c37c4e39c23a4b4eChris Craik ALOGD(" Transform (at %p):", transform); 2095f803623559aab395a29d575c37c4e39c23a4b4eChris Craik transform->dump(); 2105f803623559aab395a29d575c37c4e39c23a4b4eChris Craik} 2115f803623559aab395a29d575c37c4e39c23a4b4eChris Craik 212ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy}; // namespace uirenderer 213ada4d53d50dc869b8278573ad640dc44118d3bcfRomain Guy}; // namespace android 214