CanvasState.cpp revision 14e513058ed4168c94e015638d16f5f87fd8063a
114e513058ed4168c94e015638d16f5f87fd8063aChris Craik/* 214e513058ed4168c94e015638d16f5f87fd8063aChris Craik * Copyright (C) 2014 The Android Open Source Project 314e513058ed4168c94e015638d16f5f87fd8063aChris Craik * 414e513058ed4168c94e015638d16f5f87fd8063aChris Craik * Licensed under the Apache License, Version 2.0 (the "License"); 514e513058ed4168c94e015638d16f5f87fd8063aChris Craik * you may not use this file except in compliance with the License. 614e513058ed4168c94e015638d16f5f87fd8063aChris Craik * You may obtain a copy of the License at 714e513058ed4168c94e015638d16f5f87fd8063aChris Craik * 814e513058ed4168c94e015638d16f5f87fd8063aChris Craik * http://www.apache.org/licenses/LICENSE-2.0 914e513058ed4168c94e015638d16f5f87fd8063aChris Craik * 1014e513058ed4168c94e015638d16f5f87fd8063aChris Craik * Unless required by applicable law or agreed to in writing, software 1114e513058ed4168c94e015638d16f5f87fd8063aChris Craik * distributed under the License is distributed on an "AS IS" BASIS, 1214e513058ed4168c94e015638d16f5f87fd8063aChris Craik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1314e513058ed4168c94e015638d16f5f87fd8063aChris Craik * See the License for the specific language governing permissions and 1414e513058ed4168c94e015638d16f5f87fd8063aChris Craik * limitations under the License. 1514e513058ed4168c94e015638d16f5f87fd8063aChris Craik */ 1614e513058ed4168c94e015638d16f5f87fd8063aChris Craik 1714e513058ed4168c94e015638d16f5f87fd8063aChris Craik#include <SkCanvas.h> 1814e513058ed4168c94e015638d16f5f87fd8063aChris Craik 1914e513058ed4168c94e015638d16f5f87fd8063aChris Craik#include "StatefulBaseRenderer.h" 2014e513058ed4168c94e015638d16f5f87fd8063aChris Craik 2114e513058ed4168c94e015638d16f5f87fd8063aChris Craiknamespace android { 2214e513058ed4168c94e015638d16f5f87fd8063aChris Craiknamespace uirenderer { 2314e513058ed4168c94e015638d16f5f87fd8063aChris Craik 2414e513058ed4168c94e015638d16f5f87fd8063aChris CraikStatefulBaseRenderer::StatefulBaseRenderer() : 2514e513058ed4168c94e015638d16f5f87fd8063aChris Craik mSaveCount(1), mFirstSnapshot(new Snapshot), mSnapshot(mFirstSnapshot) { 2614e513058ed4168c94e015638d16f5f87fd8063aChris Craik} 2714e513058ed4168c94e015638d16f5f87fd8063aChris Craik 2814e513058ed4168c94e015638d16f5f87fd8063aChris Craikvoid StatefulBaseRenderer::initializeSaveStack(float clipLeft, float clipTop, 2914e513058ed4168c94e015638d16f5f87fd8063aChris Craik float clipRight, float clipBottom) { 3014e513058ed4168c94e015638d16f5f87fd8063aChris Craik mSnapshot = new Snapshot(mFirstSnapshot, 3114e513058ed4168c94e015638d16f5f87fd8063aChris Craik SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag); 3214e513058ed4168c94e015638d16f5f87fd8063aChris Craik mSnapshot->setClip(clipLeft, clipTop, clipRight, clipBottom); 3314e513058ed4168c94e015638d16f5f87fd8063aChris Craik mSnapshot->fbo = getTargetFbo(); 3414e513058ed4168c94e015638d16f5f87fd8063aChris Craik mSaveCount = 1; 3514e513058ed4168c94e015638d16f5f87fd8063aChris Craik} 3614e513058ed4168c94e015638d16f5f87fd8063aChris Craik 3714e513058ed4168c94e015638d16f5f87fd8063aChris Craikvoid StatefulBaseRenderer::initializeViewport(int width, int height) { 3814e513058ed4168c94e015638d16f5f87fd8063aChris Craik mWidth = width; 3914e513058ed4168c94e015638d16f5f87fd8063aChris Craik mHeight = height; 4014e513058ed4168c94e015638d16f5f87fd8063aChris Craik 4114e513058ed4168c94e015638d16f5f87fd8063aChris Craik mFirstSnapshot->height = height; 4214e513058ed4168c94e015638d16f5f87fd8063aChris Craik mFirstSnapshot->viewport.set(0, 0, width, height); 4314e513058ed4168c94e015638d16f5f87fd8063aChris Craik} 4414e513058ed4168c94e015638d16f5f87fd8063aChris Craik 4514e513058ed4168c94e015638d16f5f87fd8063aChris Craik/////////////////////////////////////////////////////////////////////////////// 4614e513058ed4168c94e015638d16f5f87fd8063aChris Craik// Save (layer) 4714e513058ed4168c94e015638d16f5f87fd8063aChris Craik/////////////////////////////////////////////////////////////////////////////// 4814e513058ed4168c94e015638d16f5f87fd8063aChris Craik 4914e513058ed4168c94e015638d16f5f87fd8063aChris Craik/** 5014e513058ed4168c94e015638d16f5f87fd8063aChris Craik * Non-virtual implementation of save, guaranteed to save without side-effects 5114e513058ed4168c94e015638d16f5f87fd8063aChris Craik * 5214e513058ed4168c94e015638d16f5f87fd8063aChris Craik * The approach here and in restoreSnapshot(), allows subclasses to directly manipulate the save 5314e513058ed4168c94e015638d16f5f87fd8063aChris Craik * stack, and ensures restoreToCount() doesn't call back into subclass overrides. 5414e513058ed4168c94e015638d16f5f87fd8063aChris Craik */ 5514e513058ed4168c94e015638d16f5f87fd8063aChris Craikint StatefulBaseRenderer::saveSnapshot(int flags) { 5614e513058ed4168c94e015638d16f5f87fd8063aChris Craik mSnapshot = new Snapshot(mSnapshot, flags); 5714e513058ed4168c94e015638d16f5f87fd8063aChris Craik return mSaveCount++; 5814e513058ed4168c94e015638d16f5f87fd8063aChris Craik} 5914e513058ed4168c94e015638d16f5f87fd8063aChris Craik 6014e513058ed4168c94e015638d16f5f87fd8063aChris Craikint StatefulBaseRenderer::save(int flags) { 6114e513058ed4168c94e015638d16f5f87fd8063aChris Craik return saveSnapshot(flags); 6214e513058ed4168c94e015638d16f5f87fd8063aChris Craik} 6314e513058ed4168c94e015638d16f5f87fd8063aChris Craik 6414e513058ed4168c94e015638d16f5f87fd8063aChris Craik/** 6514e513058ed4168c94e015638d16f5f87fd8063aChris Craik * Non-virtual implementation of restore, guaranteed to restore without side-effects. 6614e513058ed4168c94e015638d16f5f87fd8063aChris Craik */ 6714e513058ed4168c94e015638d16f5f87fd8063aChris Craikvoid StatefulBaseRenderer::restoreSnapshot() { 6814e513058ed4168c94e015638d16f5f87fd8063aChris Craik sp<Snapshot> toRemove = mSnapshot; 6914e513058ed4168c94e015638d16f5f87fd8063aChris Craik sp<Snapshot> toRestore = mSnapshot->previous; 7014e513058ed4168c94e015638d16f5f87fd8063aChris Craik 7114e513058ed4168c94e015638d16f5f87fd8063aChris Craik mSaveCount--; 7214e513058ed4168c94e015638d16f5f87fd8063aChris Craik mSnapshot = toRestore; 7314e513058ed4168c94e015638d16f5f87fd8063aChris Craik 7414e513058ed4168c94e015638d16f5f87fd8063aChris Craik // subclass handles restore implementation 7514e513058ed4168c94e015638d16f5f87fd8063aChris Craik onSnapshotRestored(*toRemove, *toRestore); 7614e513058ed4168c94e015638d16f5f87fd8063aChris Craik} 7714e513058ed4168c94e015638d16f5f87fd8063aChris Craik 7814e513058ed4168c94e015638d16f5f87fd8063aChris Craikvoid StatefulBaseRenderer::restore() { 7914e513058ed4168c94e015638d16f5f87fd8063aChris Craik if (mSaveCount > 1) { 8014e513058ed4168c94e015638d16f5f87fd8063aChris Craik restoreSnapshot(); 8114e513058ed4168c94e015638d16f5f87fd8063aChris Craik } 8214e513058ed4168c94e015638d16f5f87fd8063aChris Craik} 8314e513058ed4168c94e015638d16f5f87fd8063aChris Craik 8414e513058ed4168c94e015638d16f5f87fd8063aChris Craikvoid StatefulBaseRenderer::restoreToCount(int saveCount) { 8514e513058ed4168c94e015638d16f5f87fd8063aChris Craik if (saveCount < 1) saveCount = 1; 8614e513058ed4168c94e015638d16f5f87fd8063aChris Craik 8714e513058ed4168c94e015638d16f5f87fd8063aChris Craik while (mSaveCount > saveCount) { 8814e513058ed4168c94e015638d16f5f87fd8063aChris Craik restoreSnapshot(); 8914e513058ed4168c94e015638d16f5f87fd8063aChris Craik } 9014e513058ed4168c94e015638d16f5f87fd8063aChris Craik} 9114e513058ed4168c94e015638d16f5f87fd8063aChris Craik 9214e513058ed4168c94e015638d16f5f87fd8063aChris Craik/////////////////////////////////////////////////////////////////////////////// 9314e513058ed4168c94e015638d16f5f87fd8063aChris Craik// Matrix 9414e513058ed4168c94e015638d16f5f87fd8063aChris Craik/////////////////////////////////////////////////////////////////////////////// 9514e513058ed4168c94e015638d16f5f87fd8063aChris Craik 9614e513058ed4168c94e015638d16f5f87fd8063aChris Craikvoid StatefulBaseRenderer::getMatrix(SkMatrix* matrix) const { 9714e513058ed4168c94e015638d16f5f87fd8063aChris Craik mSnapshot->transform->copyTo(*matrix); 9814e513058ed4168c94e015638d16f5f87fd8063aChris Craik} 9914e513058ed4168c94e015638d16f5f87fd8063aChris Craik 10014e513058ed4168c94e015638d16f5f87fd8063aChris Craikvoid StatefulBaseRenderer::translate(float dx, float dy, float dz) { 10114e513058ed4168c94e015638d16f5f87fd8063aChris Craik mSnapshot->transform->translate(dx, dy, dz); 10214e513058ed4168c94e015638d16f5f87fd8063aChris Craik} 10314e513058ed4168c94e015638d16f5f87fd8063aChris Craik 10414e513058ed4168c94e015638d16f5f87fd8063aChris Craikvoid StatefulBaseRenderer::rotate(float degrees) { 10514e513058ed4168c94e015638d16f5f87fd8063aChris Craik mSnapshot->transform->rotate(degrees, 0.0f, 0.0f, 1.0f); 10614e513058ed4168c94e015638d16f5f87fd8063aChris Craik} 10714e513058ed4168c94e015638d16f5f87fd8063aChris Craik 10814e513058ed4168c94e015638d16f5f87fd8063aChris Craikvoid StatefulBaseRenderer::scale(float sx, float sy) { 10914e513058ed4168c94e015638d16f5f87fd8063aChris Craik mSnapshot->transform->scale(sx, sy, 1.0f); 11014e513058ed4168c94e015638d16f5f87fd8063aChris Craik} 11114e513058ed4168c94e015638d16f5f87fd8063aChris Craik 11214e513058ed4168c94e015638d16f5f87fd8063aChris Craikvoid StatefulBaseRenderer::skew(float sx, float sy) { 11314e513058ed4168c94e015638d16f5f87fd8063aChris Craik mSnapshot->transform->skew(sx, sy); 11414e513058ed4168c94e015638d16f5f87fd8063aChris Craik} 11514e513058ed4168c94e015638d16f5f87fd8063aChris Craik 11614e513058ed4168c94e015638d16f5f87fd8063aChris Craikvoid StatefulBaseRenderer::setMatrix(SkMatrix* matrix) { 11714e513058ed4168c94e015638d16f5f87fd8063aChris Craik if (matrix) { 11814e513058ed4168c94e015638d16f5f87fd8063aChris Craik mSnapshot->transform->load(*matrix); 11914e513058ed4168c94e015638d16f5f87fd8063aChris Craik } else { 12014e513058ed4168c94e015638d16f5f87fd8063aChris Craik mSnapshot->transform->loadIdentity(); 12114e513058ed4168c94e015638d16f5f87fd8063aChris Craik } 12214e513058ed4168c94e015638d16f5f87fd8063aChris Craik} 12314e513058ed4168c94e015638d16f5f87fd8063aChris Craik 12414e513058ed4168c94e015638d16f5f87fd8063aChris Craikvoid StatefulBaseRenderer::setMatrix(const Matrix4& matrix) { 12514e513058ed4168c94e015638d16f5f87fd8063aChris Craik mSnapshot->transform->load(matrix); 12614e513058ed4168c94e015638d16f5f87fd8063aChris Craik} 12714e513058ed4168c94e015638d16f5f87fd8063aChris Craik 12814e513058ed4168c94e015638d16f5f87fd8063aChris Craikvoid StatefulBaseRenderer::concatMatrix(SkMatrix* matrix) { 12914e513058ed4168c94e015638d16f5f87fd8063aChris Craik mat4 transform(*matrix); 13014e513058ed4168c94e015638d16f5f87fd8063aChris Craik mSnapshot->transform->multiply(transform); 13114e513058ed4168c94e015638d16f5f87fd8063aChris Craik} 13214e513058ed4168c94e015638d16f5f87fd8063aChris Craik 13314e513058ed4168c94e015638d16f5f87fd8063aChris Craikvoid StatefulBaseRenderer::concatMatrix(const Matrix4& matrix) { 13414e513058ed4168c94e015638d16f5f87fd8063aChris Craik mSnapshot->transform->multiply(matrix); 13514e513058ed4168c94e015638d16f5f87fd8063aChris Craik} 13614e513058ed4168c94e015638d16f5f87fd8063aChris Craik 13714e513058ed4168c94e015638d16f5f87fd8063aChris Craik/////////////////////////////////////////////////////////////////////////////// 13814e513058ed4168c94e015638d16f5f87fd8063aChris Craik// Clip 13914e513058ed4168c94e015638d16f5f87fd8063aChris Craik/////////////////////////////////////////////////////////////////////////////// 14014e513058ed4168c94e015638d16f5f87fd8063aChris Craik 14114e513058ed4168c94e015638d16f5f87fd8063aChris Craik 14214e513058ed4168c94e015638d16f5f87fd8063aChris Craik/////////////////////////////////////////////////////////////////////////////// 14314e513058ed4168c94e015638d16f5f87fd8063aChris Craik// Quick Rejection 14414e513058ed4168c94e015638d16f5f87fd8063aChris Craik/////////////////////////////////////////////////////////////////////////////// 14514e513058ed4168c94e015638d16f5f87fd8063aChris Craik 14614e513058ed4168c94e015638d16f5f87fd8063aChris Craik/** 14714e513058ed4168c94e015638d16f5f87fd8063aChris Craik * Calculates whether content drawn within the passed bounds would be outside of, or intersect with 14814e513058ed4168c94e015638d16f5f87fd8063aChris Craik * the clipRect. Does not modify the scissor. 14914e513058ed4168c94e015638d16f5f87fd8063aChris Craik * 15014e513058ed4168c94e015638d16f5f87fd8063aChris Craik * @param clipRequired if not null, will be set to true if element intersects clip 15114e513058ed4168c94e015638d16f5f87fd8063aChris Craik * (and wasn't rejected) 15214e513058ed4168c94e015638d16f5f87fd8063aChris Craik * 15314e513058ed4168c94e015638d16f5f87fd8063aChris Craik * @param snapOut if set, the geometry will be treated as having an AA ramp. 15414e513058ed4168c94e015638d16f5f87fd8063aChris Craik * See Rect::snapGeometryToPixelBoundaries() 15514e513058ed4168c94e015638d16f5f87fd8063aChris Craik */ 15614e513058ed4168c94e015638d16f5f87fd8063aChris Craikbool StatefulBaseRenderer::calculateQuickRejectForScissor(float left, float top, 15714e513058ed4168c94e015638d16f5f87fd8063aChris Craik float right, float bottom, bool* clipRequired, bool snapOut) const { 15814e513058ed4168c94e015638d16f5f87fd8063aChris Craik if (mSnapshot->isIgnored() || bottom <= top || right <= left) { 15914e513058ed4168c94e015638d16f5f87fd8063aChris Craik return true; 16014e513058ed4168c94e015638d16f5f87fd8063aChris Craik } 16114e513058ed4168c94e015638d16f5f87fd8063aChris Craik 16214e513058ed4168c94e015638d16f5f87fd8063aChris Craik Rect r(left, top, right, bottom); 16314e513058ed4168c94e015638d16f5f87fd8063aChris Craik currentTransform().mapRect(r); 16414e513058ed4168c94e015638d16f5f87fd8063aChris Craik r.snapGeometryToPixelBoundaries(snapOut); 16514e513058ed4168c94e015638d16f5f87fd8063aChris Craik 16614e513058ed4168c94e015638d16f5f87fd8063aChris Craik Rect clipRect(currentClipRect()); 16714e513058ed4168c94e015638d16f5f87fd8063aChris Craik clipRect.snapToPixelBoundaries(); 16814e513058ed4168c94e015638d16f5f87fd8063aChris Craik 16914e513058ed4168c94e015638d16f5f87fd8063aChris Craik if (!clipRect.intersects(r)) return true; 17014e513058ed4168c94e015638d16f5f87fd8063aChris Craik 17114e513058ed4168c94e015638d16f5f87fd8063aChris Craik // clip is required if geometry intersects clip rect 17214e513058ed4168c94e015638d16f5f87fd8063aChris Craik if (clipRequired) *clipRequired = !clipRect.contains(r); 17314e513058ed4168c94e015638d16f5f87fd8063aChris Craik return false; 17414e513058ed4168c94e015638d16f5f87fd8063aChris Craik} 17514e513058ed4168c94e015638d16f5f87fd8063aChris Craik 17614e513058ed4168c94e015638d16f5f87fd8063aChris Craik/** 17714e513058ed4168c94e015638d16f5f87fd8063aChris Craik * Returns false if drawing won't be clipped out. 17814e513058ed4168c94e015638d16f5f87fd8063aChris Craik * 17914e513058ed4168c94e015638d16f5f87fd8063aChris Craik * Makes the decision conservatively, by rounding out the mapped rect before comparing with the 18014e513058ed4168c94e015638d16f5f87fd8063aChris Craik * clipRect. To be used when perfect, pixel accuracy is not possible (esp. with tessellation) but 18114e513058ed4168c94e015638d16f5f87fd8063aChris Craik * rejection is still desired. 18214e513058ed4168c94e015638d16f5f87fd8063aChris Craik * 18314e513058ed4168c94e015638d16f5f87fd8063aChris Craik * This function, unlike quickRejectSetupScissor, should be used where precise geometry information 18414e513058ed4168c94e015638d16f5f87fd8063aChris Craik * isn't known (esp. when geometry adjusts based on scale). Generally, this will be first pass 18514e513058ed4168c94e015638d16f5f87fd8063aChris Craik * rejection where precise rejection isn't important, or precise information isn't available. 18614e513058ed4168c94e015638d16f5f87fd8063aChris Craik */ 18714e513058ed4168c94e015638d16f5f87fd8063aChris Craikbool StatefulBaseRenderer::quickRejectConservative(float left, float top, 18814e513058ed4168c94e015638d16f5f87fd8063aChris Craik float right, float bottom) const { 18914e513058ed4168c94e015638d16f5f87fd8063aChris Craik if (mSnapshot->isIgnored() || bottom <= top || right <= left) { 19014e513058ed4168c94e015638d16f5f87fd8063aChris Craik return true; 19114e513058ed4168c94e015638d16f5f87fd8063aChris Craik } 19214e513058ed4168c94e015638d16f5f87fd8063aChris Craik 19314e513058ed4168c94e015638d16f5f87fd8063aChris Craik Rect r(left, top, right, bottom); 19414e513058ed4168c94e015638d16f5f87fd8063aChris Craik currentTransform().mapRect(r); 19514e513058ed4168c94e015638d16f5f87fd8063aChris Craik r.roundOut(); // rounded out to be conservative 19614e513058ed4168c94e015638d16f5f87fd8063aChris Craik 19714e513058ed4168c94e015638d16f5f87fd8063aChris Craik Rect clipRect(currentClipRect()); 19814e513058ed4168c94e015638d16f5f87fd8063aChris Craik clipRect.snapToPixelBoundaries(); 19914e513058ed4168c94e015638d16f5f87fd8063aChris Craik 20014e513058ed4168c94e015638d16f5f87fd8063aChris Craik if (!clipRect.intersects(r)) return true; 20114e513058ed4168c94e015638d16f5f87fd8063aChris Craik 20214e513058ed4168c94e015638d16f5f87fd8063aChris Craik return false; 20314e513058ed4168c94e015638d16f5f87fd8063aChris Craik} 20414e513058ed4168c94e015638d16f5f87fd8063aChris Craik 20514e513058ed4168c94e015638d16f5f87fd8063aChris Craik}; // namespace uirenderer 20614e513058ed4168c94e015638d16f5f87fd8063aChris Craik}; // namespace android 207