StatefulBaseRenderer.cpp revision 14e513058ed4168c94e015638d16f5f87fd8063a
1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <SkCanvas.h> 18 19#include "StatefulBaseRenderer.h" 20 21namespace android { 22namespace uirenderer { 23 24StatefulBaseRenderer::StatefulBaseRenderer() : 25 mSaveCount(1), mFirstSnapshot(new Snapshot), mSnapshot(mFirstSnapshot) { 26} 27 28void StatefulBaseRenderer::initializeSaveStack(float clipLeft, float clipTop, 29 float clipRight, float clipBottom) { 30 mSnapshot = new Snapshot(mFirstSnapshot, 31 SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag); 32 mSnapshot->setClip(clipLeft, clipTop, clipRight, clipBottom); 33 mSnapshot->fbo = getTargetFbo(); 34 mSaveCount = 1; 35} 36 37void StatefulBaseRenderer::initializeViewport(int width, int height) { 38 mWidth = width; 39 mHeight = height; 40 41 mFirstSnapshot->height = height; 42 mFirstSnapshot->viewport.set(0, 0, width, height); 43} 44 45/////////////////////////////////////////////////////////////////////////////// 46// Save (layer) 47/////////////////////////////////////////////////////////////////////////////// 48 49/** 50 * Non-virtual implementation of save, guaranteed to save without side-effects 51 * 52 * The approach here and in restoreSnapshot(), allows subclasses to directly manipulate the save 53 * stack, and ensures restoreToCount() doesn't call back into subclass overrides. 54 */ 55int StatefulBaseRenderer::saveSnapshot(int flags) { 56 mSnapshot = new Snapshot(mSnapshot, flags); 57 return mSaveCount++; 58} 59 60int StatefulBaseRenderer::save(int flags) { 61 return saveSnapshot(flags); 62} 63 64/** 65 * Non-virtual implementation of restore, guaranteed to restore without side-effects. 66 */ 67void StatefulBaseRenderer::restoreSnapshot() { 68 sp<Snapshot> toRemove = mSnapshot; 69 sp<Snapshot> toRestore = mSnapshot->previous; 70 71 mSaveCount--; 72 mSnapshot = toRestore; 73 74 // subclass handles restore implementation 75 onSnapshotRestored(*toRemove, *toRestore); 76} 77 78void StatefulBaseRenderer::restore() { 79 if (mSaveCount > 1) { 80 restoreSnapshot(); 81 } 82} 83 84void StatefulBaseRenderer::restoreToCount(int saveCount) { 85 if (saveCount < 1) saveCount = 1; 86 87 while (mSaveCount > saveCount) { 88 restoreSnapshot(); 89 } 90} 91 92/////////////////////////////////////////////////////////////////////////////// 93// Matrix 94/////////////////////////////////////////////////////////////////////////////// 95 96void StatefulBaseRenderer::getMatrix(SkMatrix* matrix) const { 97 mSnapshot->transform->copyTo(*matrix); 98} 99 100void StatefulBaseRenderer::translate(float dx, float dy, float dz) { 101 mSnapshot->transform->translate(dx, dy, dz); 102} 103 104void StatefulBaseRenderer::rotate(float degrees) { 105 mSnapshot->transform->rotate(degrees, 0.0f, 0.0f, 1.0f); 106} 107 108void StatefulBaseRenderer::scale(float sx, float sy) { 109 mSnapshot->transform->scale(sx, sy, 1.0f); 110} 111 112void StatefulBaseRenderer::skew(float sx, float sy) { 113 mSnapshot->transform->skew(sx, sy); 114} 115 116void StatefulBaseRenderer::setMatrix(SkMatrix* matrix) { 117 if (matrix) { 118 mSnapshot->transform->load(*matrix); 119 } else { 120 mSnapshot->transform->loadIdentity(); 121 } 122} 123 124void StatefulBaseRenderer::setMatrix(const Matrix4& matrix) { 125 mSnapshot->transform->load(matrix); 126} 127 128void StatefulBaseRenderer::concatMatrix(SkMatrix* matrix) { 129 mat4 transform(*matrix); 130 mSnapshot->transform->multiply(transform); 131} 132 133void StatefulBaseRenderer::concatMatrix(const Matrix4& matrix) { 134 mSnapshot->transform->multiply(matrix); 135} 136 137/////////////////////////////////////////////////////////////////////////////// 138// Clip 139/////////////////////////////////////////////////////////////////////////////// 140 141 142/////////////////////////////////////////////////////////////////////////////// 143// Quick Rejection 144/////////////////////////////////////////////////////////////////////////////// 145 146/** 147 * Calculates whether content drawn within the passed bounds would be outside of, or intersect with 148 * the clipRect. Does not modify the scissor. 149 * 150 * @param clipRequired if not null, will be set to true if element intersects clip 151 * (and wasn't rejected) 152 * 153 * @param snapOut if set, the geometry will be treated as having an AA ramp. 154 * See Rect::snapGeometryToPixelBoundaries() 155 */ 156bool StatefulBaseRenderer::calculateQuickRejectForScissor(float left, float top, 157 float right, float bottom, bool* clipRequired, bool snapOut) const { 158 if (mSnapshot->isIgnored() || bottom <= top || right <= left) { 159 return true; 160 } 161 162 Rect r(left, top, right, bottom); 163 currentTransform().mapRect(r); 164 r.snapGeometryToPixelBoundaries(snapOut); 165 166 Rect clipRect(currentClipRect()); 167 clipRect.snapToPixelBoundaries(); 168 169 if (!clipRect.intersects(r)) return true; 170 171 // clip is required if geometry intersects clip rect 172 if (clipRequired) *clipRequired = !clipRect.contains(r); 173 return false; 174} 175 176/** 177 * Returns false if drawing won't be clipped out. 178 * 179 * Makes the decision conservatively, by rounding out the mapped rect before comparing with the 180 * clipRect. To be used when perfect, pixel accuracy is not possible (esp. with tessellation) but 181 * rejection is still desired. 182 * 183 * This function, unlike quickRejectSetupScissor, should be used where precise geometry information 184 * isn't known (esp. when geometry adjusts based on scale). Generally, this will be first pass 185 * rejection where precise rejection isn't important, or precise information isn't available. 186 */ 187bool StatefulBaseRenderer::quickRejectConservative(float left, float top, 188 float right, float bottom) const { 189 if (mSnapshot->isIgnored() || bottom <= top || right <= left) { 190 return true; 191 } 192 193 Rect r(left, top, right, bottom); 194 currentTransform().mapRect(r); 195 r.roundOut(); // rounded out to be conservative 196 197 Rect clipRect(currentClipRect()); 198 clipRect.snapToPixelBoundaries(); 199 200 if (!clipRect.intersects(r)) return true; 201 202 return false; 203} 204 205}; // namespace uirenderer 206}; // namespace android 207