144d362409d5469aed47d19e7908d19bd194493aThomas Graf/* 244d362409d5469aed47d19e7908d19bd194493aThomas Graf * Copyright (C) 2014 The Android Open Source Project 344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 444d362409d5469aed47d19e7908d19bd194493aThomas Graf * Licensed under the Apache License, Version 2.0 (the "License"); 544d362409d5469aed47d19e7908d19bd194493aThomas Graf * you may not use this file except in compliance with the License. 644d362409d5469aed47d19e7908d19bd194493aThomas Graf * You may obtain a copy of the License at 744d362409d5469aed47d19e7908d19bd194493aThomas Graf * 844d362409d5469aed47d19e7908d19bd194493aThomas Graf * http://www.apache.org/licenses/LICENSE-2.0 98a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * 1044d362409d5469aed47d19e7908d19bd194493aThomas Graf * Unless required by applicable law or agreed to in writing, software 1144d362409d5469aed47d19e7908d19bd194493aThomas Graf * distributed under the License is distributed on an "AS IS" BASIS, 1244d362409d5469aed47d19e7908d19bd194493aThomas Graf * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1344d362409d5469aed47d19e7908d19bd194493aThomas Graf * See the License for the specific language governing permissions and 1444d362409d5469aed47d19e7908d19bd194493aThomas Graf * limitations under the License. 1544d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1644d362409d5469aed47d19e7908d19bd194493aThomas Graf 1744d362409d5469aed47d19e7908d19bd194493aThomas Graf#define LOG_TAG "OpenGLRenderer" 1844d362409d5469aed47d19e7908d19bd194493aThomas Graf 1944d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <SkCanvas.h> 2044d362409d5469aed47d19e7908d19bd194493aThomas Graf 2144d362409d5469aed47d19e7908d19bd194493aThomas Graf#include "StatefulBaseRenderer.h" 2244d362409d5469aed47d19e7908d19bd194493aThomas Graf 2344d362409d5469aed47d19e7908d19bd194493aThomas Graf#include "utils/MathUtils.h" 2444d362409d5469aed47d19e7908d19bd194493aThomas Graf 2544d362409d5469aed47d19e7908d19bd194493aThomas Grafnamespace android { 2644d362409d5469aed47d19e7908d19bd194493aThomas Grafnamespace uirenderer { 2744d362409d5469aed47d19e7908d19bd194493aThomas Graf 2844d362409d5469aed47d19e7908d19bd194493aThomas GrafStatefulBaseRenderer::StatefulBaseRenderer() 2944d362409d5469aed47d19e7908d19bd194493aThomas Graf : mDirtyClip(false) 3044d362409d5469aed47d19e7908d19bd194493aThomas Graf , mWidth(-1) 3144d362409d5469aed47d19e7908d19bd194493aThomas Graf , mHeight(-1) 3244d362409d5469aed47d19e7908d19bd194493aThomas Graf , mSaveCount(1) 3344d362409d5469aed47d19e7908d19bd194493aThomas Graf , mFirstSnapshot(new Snapshot) 3444d362409d5469aed47d19e7908d19bd194493aThomas Graf , mSnapshot(mFirstSnapshot) { 3544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 3644d362409d5469aed47d19e7908d19bd194493aThomas Graf 3744d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid StatefulBaseRenderer::initializeSaveStack(float clipLeft, float clipTop, 3844d362409d5469aed47d19e7908d19bd194493aThomas Graf float clipRight, float clipBottom, const Vector3& lightCenter) { 3944d362409d5469aed47d19e7908d19bd194493aThomas Graf mSnapshot = new Snapshot(mFirstSnapshot, 4044d362409d5469aed47d19e7908d19bd194493aThomas Graf SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag); 4144d362409d5469aed47d19e7908d19bd194493aThomas Graf mSnapshot->setClip(clipLeft, clipTop, clipRight, clipBottom); 4244d362409d5469aed47d19e7908d19bd194493aThomas Graf mSnapshot->fbo = getTargetFbo(); 4344d362409d5469aed47d19e7908d19bd194493aThomas Graf mSnapshot->setRelativeLightCenter(lightCenter); 4444d362409d5469aed47d19e7908d19bd194493aThomas Graf mSaveCount = 1; 4544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 4644d362409d5469aed47d19e7908d19bd194493aThomas Graf 4744d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid StatefulBaseRenderer::setViewport(int width, int height) { 4844d362409d5469aed47d19e7908d19bd194493aThomas Graf mWidth = width; 4944d362409d5469aed47d19e7908d19bd194493aThomas Graf mHeight = height; 5044d362409d5469aed47d19e7908d19bd194493aThomas Graf mFirstSnapshot->initializeViewport(width, height); 5144d362409d5469aed47d19e7908d19bd194493aThomas Graf onViewportInitialized(); 5244d362409d5469aed47d19e7908d19bd194493aThomas Graf 5344d362409d5469aed47d19e7908d19bd194493aThomas Graf // create a temporary 1st snapshot, so old snapshots are released, 5444d362409d5469aed47d19e7908d19bd194493aThomas Graf // and viewport can be queried safely. 5544d362409d5469aed47d19e7908d19bd194493aThomas Graf // TODO: remove, combine viewport + save stack initialization 5644d362409d5469aed47d19e7908d19bd194493aThomas Graf mSnapshot = new Snapshot(mFirstSnapshot, 5744d362409d5469aed47d19e7908d19bd194493aThomas Graf SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag); 5844d362409d5469aed47d19e7908d19bd194493aThomas Graf mSaveCount = 1; 5944d362409d5469aed47d19e7908d19bd194493aThomas Graf} 6044d362409d5469aed47d19e7908d19bd194493aThomas Graf 6144d362409d5469aed47d19e7908d19bd194493aThomas Graf/////////////////////////////////////////////////////////////////////////////// 6244d362409d5469aed47d19e7908d19bd194493aThomas Graf// Save (layer) 6344d362409d5469aed47d19e7908d19bd194493aThomas Graf/////////////////////////////////////////////////////////////////////////////// 641155370f520cb64657e25153255cf7dc1424317fThomas Graf 6544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 6644d362409d5469aed47d19e7908d19bd194493aThomas Graf * Non-virtual implementation of save, guaranteed to save without side-effects 6744d362409d5469aed47d19e7908d19bd194493aThomas Graf * 6844d362409d5469aed47d19e7908d19bd194493aThomas Graf * The approach here and in restoreSnapshot(), allows subclasses to directly manipulate the save 6944d362409d5469aed47d19e7908d19bd194493aThomas Graf * stack, and ensures restoreToCount() doesn't call back into subclass overrides. 7044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 7144d362409d5469aed47d19e7908d19bd194493aThomas Grafint StatefulBaseRenderer::saveSnapshot(int flags) { 7244d362409d5469aed47d19e7908d19bd194493aThomas Graf mSnapshot = new Snapshot(mSnapshot, flags); 7344d362409d5469aed47d19e7908d19bd194493aThomas Graf return mSaveCount++; 7444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 7544d362409d5469aed47d19e7908d19bd194493aThomas Graf 7644d362409d5469aed47d19e7908d19bd194493aThomas Grafint StatefulBaseRenderer::save(int flags) { 7744d362409d5469aed47d19e7908d19bd194493aThomas Graf return saveSnapshot(flags); 7844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 7944d362409d5469aed47d19e7908d19bd194493aThomas Graf 8044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 8144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Non-virtual implementation of restore, guaranteed to restore without side-effects. 8244d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 8344d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid StatefulBaseRenderer::restoreSnapshot() { 8444d362409d5469aed47d19e7908d19bd194493aThomas Graf sp<Snapshot> toRemove = mSnapshot; 8544d362409d5469aed47d19e7908d19bd194493aThomas Graf sp<Snapshot> toRestore = mSnapshot->previous; 8644d362409d5469aed47d19e7908d19bd194493aThomas Graf 8744d362409d5469aed47d19e7908d19bd194493aThomas Graf mSaveCount--; 8844d362409d5469aed47d19e7908d19bd194493aThomas Graf mSnapshot = toRestore; 89531029c130db95a82c9f2121e59698e86cd84e79Thomas Graf 9044d362409d5469aed47d19e7908d19bd194493aThomas Graf // subclass handles restore implementation 9144d362409d5469aed47d19e7908d19bd194493aThomas Graf onSnapshotRestored(*toRemove, *toRestore); 9244d362409d5469aed47d19e7908d19bd194493aThomas Graf} 9344d362409d5469aed47d19e7908d19bd194493aThomas Graf 9444d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid StatefulBaseRenderer::restore() { 9544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (mSaveCount > 1) { 9644d362409d5469aed47d19e7908d19bd194493aThomas Graf restoreSnapshot(); 9744d362409d5469aed47d19e7908d19bd194493aThomas Graf } 9844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 9944d362409d5469aed47d19e7908d19bd194493aThomas Graf 10044d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid StatefulBaseRenderer::restoreToCount(int saveCount) { 10144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (saveCount < 1) saveCount = 1; 10244d362409d5469aed47d19e7908d19bd194493aThomas Graf 10344d362409d5469aed47d19e7908d19bd194493aThomas Graf while (mSaveCount > saveCount) { 10444d362409d5469aed47d19e7908d19bd194493aThomas Graf restoreSnapshot(); 10544d362409d5469aed47d19e7908d19bd194493aThomas Graf } 10644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 10744d362409d5469aed47d19e7908d19bd194493aThomas Graf 10844d362409d5469aed47d19e7908d19bd194493aThomas Graf/////////////////////////////////////////////////////////////////////////////// 10944d362409d5469aed47d19e7908d19bd194493aThomas Graf// Matrix 11044d362409d5469aed47d19e7908d19bd194493aThomas Graf/////////////////////////////////////////////////////////////////////////////// 11144d362409d5469aed47d19e7908d19bd194493aThomas Graf 1121155370f520cb64657e25153255cf7dc1424317fThomas Grafvoid StatefulBaseRenderer::getMatrix(SkMatrix* matrix) const { 11344d362409d5469aed47d19e7908d19bd194493aThomas Graf mSnapshot->transform->copyTo(*matrix); 11444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 11544d362409d5469aed47d19e7908d19bd194493aThomas Graf 11644d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid StatefulBaseRenderer::translate(float dx, float dy, float dz) { 11744d362409d5469aed47d19e7908d19bd194493aThomas Graf mSnapshot->transform->translate(dx, dy, dz); 11844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 11944d362409d5469aed47d19e7908d19bd194493aThomas Graf 12044d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid StatefulBaseRenderer::rotate(float degrees) { 12144d362409d5469aed47d19e7908d19bd194493aThomas Graf mSnapshot->transform->rotate(degrees, 0.0f, 0.0f, 1.0f); 12244d362409d5469aed47d19e7908d19bd194493aThomas Graf} 12344d362409d5469aed47d19e7908d19bd194493aThomas Graf 12444d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid StatefulBaseRenderer::scale(float sx, float sy) { 12544d362409d5469aed47d19e7908d19bd194493aThomas Graf mSnapshot->transform->scale(sx, sy, 1.0f); 12644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 12744d362409d5469aed47d19e7908d19bd194493aThomas Graf 12844d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid StatefulBaseRenderer::skew(float sx, float sy) { 12944d362409d5469aed47d19e7908d19bd194493aThomas Graf mSnapshot->transform->skew(sx, sy); 13044d362409d5469aed47d19e7908d19bd194493aThomas Graf} 13144d362409d5469aed47d19e7908d19bd194493aThomas Graf 13244d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid StatefulBaseRenderer::setMatrix(const SkMatrix& matrix) { 13344d362409d5469aed47d19e7908d19bd194493aThomas Graf mSnapshot->transform->load(matrix); 13444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 13544d362409d5469aed47d19e7908d19bd194493aThomas Graf 13644d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid StatefulBaseRenderer::setMatrix(const Matrix4& matrix) { 13744d362409d5469aed47d19e7908d19bd194493aThomas Graf mSnapshot->transform->load(matrix); 13844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 13944d362409d5469aed47d19e7908d19bd194493aThomas Graf 14044d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid StatefulBaseRenderer::concatMatrix(const SkMatrix& matrix) { 14144d362409d5469aed47d19e7908d19bd194493aThomas Graf mat4 transform(matrix); 142531029c130db95a82c9f2121e59698e86cd84e79Thomas Graf mSnapshot->transform->multiply(transform); 14344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 14444d362409d5469aed47d19e7908d19bd194493aThomas Graf 14544d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid StatefulBaseRenderer::concatMatrix(const Matrix4& matrix) { 14644d362409d5469aed47d19e7908d19bd194493aThomas Graf mSnapshot->transform->multiply(matrix); 14744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 14844d362409d5469aed47d19e7908d19bd194493aThomas Graf 14944d362409d5469aed47d19e7908d19bd194493aThomas Graf/////////////////////////////////////////////////////////////////////////////// 15044d362409d5469aed47d19e7908d19bd194493aThomas Graf// Clip 15144d362409d5469aed47d19e7908d19bd194493aThomas Graf/////////////////////////////////////////////////////////////////////////////// 15244d362409d5469aed47d19e7908d19bd194493aThomas Graf 15344d362409d5469aed47d19e7908d19bd194493aThomas Grafbool StatefulBaseRenderer::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) { 15444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (CC_LIKELY(currentTransform()->rectToRect())) { 15544d362409d5469aed47d19e7908d19bd194493aThomas Graf mDirtyClip |= mSnapshot->clip(left, top, right, bottom, op); 15644d362409d5469aed47d19e7908d19bd194493aThomas Graf return !mSnapshot->clipRect->isEmpty(); 15744d362409d5469aed47d19e7908d19bd194493aThomas Graf } 15844d362409d5469aed47d19e7908d19bd194493aThomas Graf 15944d362409d5469aed47d19e7908d19bd194493aThomas Graf SkPath path; 16044d362409d5469aed47d19e7908d19bd194493aThomas Graf path.addRect(left, top, right, bottom); 16144d362409d5469aed47d19e7908d19bd194493aThomas Graf 16244d362409d5469aed47d19e7908d19bd194493aThomas Graf return StatefulBaseRenderer::clipPath(&path, op); 16344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 16444d362409d5469aed47d19e7908d19bd194493aThomas Graf 16544d362409d5469aed47d19e7908d19bd194493aThomas Grafbool StatefulBaseRenderer::clipPath(const SkPath* path, SkRegion::Op op) { 16644d362409d5469aed47d19e7908d19bd194493aThomas Graf SkMatrix transform; 16744d362409d5469aed47d19e7908d19bd194493aThomas Graf currentTransform()->copyTo(transform); 16844d362409d5469aed47d19e7908d19bd194493aThomas Graf 16944d362409d5469aed47d19e7908d19bd194493aThomas Graf SkPath transformed; 17044d362409d5469aed47d19e7908d19bd194493aThomas Graf path->transform(transform, &transformed); 17144d362409d5469aed47d19e7908d19bd194493aThomas Graf 17244d362409d5469aed47d19e7908d19bd194493aThomas Graf SkRegion clip; 17344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!mSnapshot->previous->clipRegion->isEmpty()) { 17444d362409d5469aed47d19e7908d19bd194493aThomas Graf clip.setRegion(*mSnapshot->previous->clipRegion); 17544d362409d5469aed47d19e7908d19bd194493aThomas Graf } else { 17644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (mSnapshot->previous == firstSnapshot()) { 17744d362409d5469aed47d19e7908d19bd194493aThomas Graf clip.setRect(0, 0, getWidth(), getHeight()); 17844d362409d5469aed47d19e7908d19bd194493aThomas Graf } else { 17944d362409d5469aed47d19e7908d19bd194493aThomas Graf Rect* bounds = mSnapshot->previous->clipRect; 18044d362409d5469aed47d19e7908d19bd194493aThomas Graf clip.setRect(bounds->left, bounds->top, bounds->right, bounds->bottom); 18144d362409d5469aed47d19e7908d19bd194493aThomas Graf } 18244d362409d5469aed47d19e7908d19bd194493aThomas Graf } 18344d362409d5469aed47d19e7908d19bd194493aThomas Graf 18444d362409d5469aed47d19e7908d19bd194493aThomas Graf SkRegion region; 18544d362409d5469aed47d19e7908d19bd194493aThomas Graf region.setPath(transformed, clip); 18644d362409d5469aed47d19e7908d19bd194493aThomas Graf 18744d362409d5469aed47d19e7908d19bd194493aThomas Graf // region is the transformed input path, masked by the previous clip 18844d362409d5469aed47d19e7908d19bd194493aThomas Graf mDirtyClip |= mSnapshot->clipRegionTransformed(region, op); 18944d362409d5469aed47d19e7908d19bd194493aThomas Graf return !mSnapshot->clipRect->isEmpty(); 1908a3efffa5b3fde252675239914118664d36a2c24Thomas Graf} 19144d362409d5469aed47d19e7908d19bd194493aThomas Graf 19244d362409d5469aed47d19e7908d19bd194493aThomas Grafbool StatefulBaseRenderer::clipRegion(const SkRegion* region, SkRegion::Op op) { 19344d362409d5469aed47d19e7908d19bd194493aThomas Graf mDirtyClip |= mSnapshot->clipRegionTransformed(*region, op); 1948a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return !mSnapshot->clipRect->isEmpty(); 19544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 19644d362409d5469aed47d19e7908d19bd194493aThomas Graf 19744d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid StatefulBaseRenderer::setClippingOutline(LinearAllocator& allocator, const Outline* outline) { 19844d362409d5469aed47d19e7908d19bd194493aThomas Graf Rect bounds; 19944d362409d5469aed47d19e7908d19bd194493aThomas Graf float radius; 20044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!outline->getAsRoundRect(&bounds, &radius)) return; // only RR supported 20144d362409d5469aed47d19e7908d19bd194493aThomas Graf 20244d362409d5469aed47d19e7908d19bd194493aThomas Graf bool outlineIsRounded = MathUtils::isPositive(radius); 20344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!outlineIsRounded || currentTransform()->isSimple()) { 20444d362409d5469aed47d19e7908d19bd194493aThomas Graf // TODO: consider storing this rect separately, so that this can't be replaced with clip ops 20544d362409d5469aed47d19e7908d19bd194493aThomas Graf clipRect(bounds.left, bounds.top, bounds.right, bounds.bottom, SkRegion::kIntersect_Op); 20644d362409d5469aed47d19e7908d19bd194493aThomas Graf } 20744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (outlineIsRounded) { 20844d362409d5469aed47d19e7908d19bd194493aThomas Graf setClippingRoundRect(allocator, bounds, radius, false); 20944d362409d5469aed47d19e7908d19bd194493aThomas Graf } 21044d362409d5469aed47d19e7908d19bd194493aThomas Graf} 21144d362409d5469aed47d19e7908d19bd194493aThomas Graf 21244d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid StatefulBaseRenderer::setClippingRoundRect(LinearAllocator& allocator, 21344d362409d5469aed47d19e7908d19bd194493aThomas Graf const Rect& rect, float radius, bool highPriority) { 214535e83162249ed6274ba46bc72d8cc683ba20e17Thomas Graf mSnapshot->setClippingRoundRect(allocator, rect, radius, highPriority); 21544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 21644d362409d5469aed47d19e7908d19bd194493aThomas Graf 21744d362409d5469aed47d19e7908d19bd194493aThomas Graf 21844d362409d5469aed47d19e7908d19bd194493aThomas Graf/////////////////////////////////////////////////////////////////////////////// 21944d362409d5469aed47d19e7908d19bd194493aThomas Graf// Quick Rejection 22044d362409d5469aed47d19e7908d19bd194493aThomas Graf/////////////////////////////////////////////////////////////////////////////// 22144d362409d5469aed47d19e7908d19bd194493aThomas Graf 22244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 22344d362409d5469aed47d19e7908d19bd194493aThomas Graf * Calculates whether content drawn within the passed bounds would be outside of, or intersect with 22444d362409d5469aed47d19e7908d19bd194493aThomas Graf * the clipRect. Does not modify the scissor. 22544d362409d5469aed47d19e7908d19bd194493aThomas Graf * 22644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @param clipRequired if not null, will be set to true if element intersects clip 22744d362409d5469aed47d19e7908d19bd194493aThomas Graf * (and wasn't rejected) 22844d362409d5469aed47d19e7908d19bd194493aThomas Graf * 22944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @param snapOut if set, the geometry will be treated as having an AA ramp. 23044d362409d5469aed47d19e7908d19bd194493aThomas Graf * See Rect::snapGeometryToPixelBoundaries() 23144d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 23244d362409d5469aed47d19e7908d19bd194493aThomas Grafbool StatefulBaseRenderer::calculateQuickRejectForScissor(float left, float top, 23344d362409d5469aed47d19e7908d19bd194493aThomas Graf float right, float bottom, 23444d362409d5469aed47d19e7908d19bd194493aThomas Graf bool* clipRequired, bool* roundRectClipRequired, 23544d362409d5469aed47d19e7908d19bd194493aThomas Graf bool snapOut) const { 23644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (mSnapshot->isIgnored() || bottom <= top || right <= left) { 23744d362409d5469aed47d19e7908d19bd194493aThomas Graf return true; 23844d362409d5469aed47d19e7908d19bd194493aThomas Graf } 23944d362409d5469aed47d19e7908d19bd194493aThomas Graf 24044d362409d5469aed47d19e7908d19bd194493aThomas Graf Rect r(left, top, right, bottom); 24144d362409d5469aed47d19e7908d19bd194493aThomas Graf currentTransform()->mapRect(r); 24244d362409d5469aed47d19e7908d19bd194493aThomas Graf r.snapGeometryToPixelBoundaries(snapOut); 24344d362409d5469aed47d19e7908d19bd194493aThomas Graf 24444d362409d5469aed47d19e7908d19bd194493aThomas Graf Rect clipRect(*currentClipRect()); 24544d362409d5469aed47d19e7908d19bd194493aThomas Graf clipRect.snapToPixelBoundaries(); 24644d362409d5469aed47d19e7908d19bd194493aThomas Graf 24744d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!clipRect.intersects(r)) return true; 24844d362409d5469aed47d19e7908d19bd194493aThomas Graf 24944d362409d5469aed47d19e7908d19bd194493aThomas Graf // clip is required if geometry intersects clip rect 25044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (clipRequired) { 25144d362409d5469aed47d19e7908d19bd194493aThomas Graf *clipRequired = !clipRect.contains(r); 25244d362409d5469aed47d19e7908d19bd194493aThomas Graf } 2533040a1d6254465bed9e44e4d1bf279c2c50cd16aThomas Graf 25444d362409d5469aed47d19e7908d19bd194493aThomas Graf // round rect clip is required if RR clip exists, and geometry intersects its corners 25544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (roundRectClipRequired) { 25644d362409d5469aed47d19e7908d19bd194493aThomas Graf *roundRectClipRequired = mSnapshot->roundRectClipState != NULL 25744d362409d5469aed47d19e7908d19bd194493aThomas Graf && mSnapshot->roundRectClipState->areaRequiresRoundRectClip(r); 25844d362409d5469aed47d19e7908d19bd194493aThomas Graf } 25944d362409d5469aed47d19e7908d19bd194493aThomas Graf return false; 26044d362409d5469aed47d19e7908d19bd194493aThomas Graf} 26144d362409d5469aed47d19e7908d19bd194493aThomas Graf 2628a3efffa5b3fde252675239914118664d36a2c24Thomas Graf/** 26344d362409d5469aed47d19e7908d19bd194493aThomas Graf * Returns false if drawing won't be clipped out. 26444d362409d5469aed47d19e7908d19bd194493aThomas Graf * 26544d362409d5469aed47d19e7908d19bd194493aThomas Graf * Makes the decision conservatively, by rounding out the mapped rect before comparing with the 26644d362409d5469aed47d19e7908d19bd194493aThomas Graf * clipRect. To be used when perfect, pixel accuracy is not possible (esp. with tessellation) but 26744d362409d5469aed47d19e7908d19bd194493aThomas Graf * rejection is still desired. 26844d362409d5469aed47d19e7908d19bd194493aThomas Graf * 26944d362409d5469aed47d19e7908d19bd194493aThomas Graf * This function, unlike quickRejectSetupScissor, should be used where precise geometry information 27044d362409d5469aed47d19e7908d19bd194493aThomas Graf * isn't known (esp. when geometry adjusts based on scale). Generally, this will be first pass 27144d362409d5469aed47d19e7908d19bd194493aThomas Graf * rejection where precise rejection isn't important, or precise information isn't available. 27244d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 27344d362409d5469aed47d19e7908d19bd194493aThomas Grafbool StatefulBaseRenderer::quickRejectConservative(float left, float top, 27444d362409d5469aed47d19e7908d19bd194493aThomas Graf float right, float bottom) const { 27544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (mSnapshot->isIgnored() || bottom <= top || right <= left) { 27644d362409d5469aed47d19e7908d19bd194493aThomas Graf return true; 27744d362409d5469aed47d19e7908d19bd194493aThomas Graf } 27844d362409d5469aed47d19e7908d19bd194493aThomas Graf 27944d362409d5469aed47d19e7908d19bd194493aThomas Graf Rect r(left, top, right, bottom); 28044d362409d5469aed47d19e7908d19bd194493aThomas Graf currentTransform()->mapRect(r); 28144d362409d5469aed47d19e7908d19bd194493aThomas Graf r.roundOut(); // rounded out to be conservative 28244d362409d5469aed47d19e7908d19bd194493aThomas Graf 28344d362409d5469aed47d19e7908d19bd194493aThomas Graf Rect clipRect(*currentClipRect()); 284eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf clipRect.snapToPixelBoundaries(); 285eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf 286eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf if (!clipRect.intersects(r)) return true; 28744d362409d5469aed47d19e7908d19bd194493aThomas Graf 288eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Graf return false; 28944d362409d5469aed47d19e7908d19bd194493aThomas Graf} 29044d362409d5469aed47d19e7908d19bd194493aThomas Graf 29144d362409d5469aed47d19e7908d19bd194493aThomas Graf}; // namespace uirenderer 29244d362409d5469aed47d19e7908d19bd194493aThomas Graf}; // namespace android 29344d362409d5469aed47d19e7908d19bd194493aThomas Graf