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