BakedOpState.cpp revision b87eadda1818034ce03d85f30388384d1ac65916
1e4db79de127cfe961195f52907af8451026eaa20Chris Craik/*
2e4db79de127cfe961195f52907af8451026eaa20Chris Craik * Copyright (C) 2015 The Android Open Source Project
3e4db79de127cfe961195f52907af8451026eaa20Chris Craik *
4e4db79de127cfe961195f52907af8451026eaa20Chris Craik * Licensed under the Apache License, Version 2.0 (the "License");
5e4db79de127cfe961195f52907af8451026eaa20Chris Craik * you may not use this file except in compliance with the License.
6e4db79de127cfe961195f52907af8451026eaa20Chris Craik * You may obtain a copy of the License at
7e4db79de127cfe961195f52907af8451026eaa20Chris Craik *
8e4db79de127cfe961195f52907af8451026eaa20Chris Craik *      http://www.apache.org/licenses/LICENSE-2.0
9e4db79de127cfe961195f52907af8451026eaa20Chris Craik *
10e4db79de127cfe961195f52907af8451026eaa20Chris Craik * Unless required by applicable law or agreed to in writing, software
11e4db79de127cfe961195f52907af8451026eaa20Chris Craik * distributed under the License is distributed on an "AS IS" BASIS,
12e4db79de127cfe961195f52907af8451026eaa20Chris Craik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e4db79de127cfe961195f52907af8451026eaa20Chris Craik * See the License for the specific language governing permissions and
14e4db79de127cfe961195f52907af8451026eaa20Chris Craik * limitations under the License.
15e4db79de127cfe961195f52907af8451026eaa20Chris Craik */
16e4db79de127cfe961195f52907af8451026eaa20Chris Craik
17e4db79de127cfe961195f52907af8451026eaa20Chris Craik#include "BakedOpState.h"
18e4db79de127cfe961195f52907af8451026eaa20Chris Craik
19e4db79de127cfe961195f52907af8451026eaa20Chris Craik#include "ClipArea.h"
20e4db79de127cfe961195f52907af8451026eaa20Chris Craik
21e4db79de127cfe961195f52907af8451026eaa20Chris Craiknamespace android {
22e4db79de127cfe961195f52907af8451026eaa20Chris Craiknamespace uirenderer {
23e4db79de127cfe961195f52907af8451026eaa20Chris Craik
24e4db79de127cfe961195f52907af8451026eaa20Chris CraikResolvedRenderState::ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot,
25e4db79de127cfe961195f52907af8451026eaa20Chris Craik        const RecordedOp& recordedOp, bool expandForStroke) {
26e4db79de127cfe961195f52907af8451026eaa20Chris Craik    // resolvedMatrix = parentMatrix * localMatrix
27e4db79de127cfe961195f52907af8451026eaa20Chris Craik    transform.loadMultiply(*snapshot.transform, recordedOp.localMatrix);
28e4db79de127cfe961195f52907af8451026eaa20Chris Craik
29e4db79de127cfe961195f52907af8451026eaa20Chris Craik    // resolvedClippedBounds = intersect(resolvedMatrix * opBounds, resolvedClipRect)
30e4db79de127cfe961195f52907af8451026eaa20Chris Craik    clippedBounds = recordedOp.unmappedBounds;
31e4db79de127cfe961195f52907af8451026eaa20Chris Craik    if (CC_UNLIKELY(expandForStroke)) {
32e4db79de127cfe961195f52907af8451026eaa20Chris Craik        // account for non-hairline stroke
33e4db79de127cfe961195f52907af8451026eaa20Chris Craik        clippedBounds.outset(recordedOp.paint->getStrokeWidth() * 0.5f);
34e4db79de127cfe961195f52907af8451026eaa20Chris Craik    }
35e4db79de127cfe961195f52907af8451026eaa20Chris Craik    transform.mapRect(clippedBounds);
36e4db79de127cfe961195f52907af8451026eaa20Chris Craik    if (CC_UNLIKELY(expandForStroke
37e4db79de127cfe961195f52907af8451026eaa20Chris Craik            && (!transform.isPureTranslate() || recordedOp.paint->getStrokeWidth() < 1.0f))) {
38e4db79de127cfe961195f52907af8451026eaa20Chris Craik        // account for hairline stroke when stroke may be < 1 scaled pixel
39e4db79de127cfe961195f52907af8451026eaa20Chris Craik        // Non translate || strokeWidth < 1 is conservative, but will cover all cases
40e4db79de127cfe961195f52907af8451026eaa20Chris Craik        clippedBounds.outset(0.5f);
41e4db79de127cfe961195f52907af8451026eaa20Chris Craik    }
42e4db79de127cfe961195f52907af8451026eaa20Chris Craik
43e4db79de127cfe961195f52907af8451026eaa20Chris Craik    // resolvedClipRect = intersect(parentMatrix * localClip, parentClip)
44e4db79de127cfe961195f52907af8451026eaa20Chris Craik    clipState = snapshot.mutateClipArea().serializeIntersectedClip(allocator,
45e4db79de127cfe961195f52907af8451026eaa20Chris Craik            recordedOp.localClip, *(snapshot.transform));
46e4db79de127cfe961195f52907af8451026eaa20Chris Craik    LOG_ALWAYS_FATAL_IF(!clipState, "must clip!");
47e4db79de127cfe961195f52907af8451026eaa20Chris Craik
48e4db79de127cfe961195f52907af8451026eaa20Chris Craik    const Rect& clipRect = clipState->rect;
49e4db79de127cfe961195f52907af8451026eaa20Chris Craik    if (CC_UNLIKELY(clipRect.isEmpty() || !clippedBounds.intersects(clipRect))) {
50e4db79de127cfe961195f52907af8451026eaa20Chris Craik        // Rejected based on either empty clip, or bounds not intersecting with clip
51e4db79de127cfe961195f52907af8451026eaa20Chris Craik        if (clipState) {
52e4db79de127cfe961195f52907af8451026eaa20Chris Craik            allocator.rewindIfLastAlloc(clipState);
53e4db79de127cfe961195f52907af8451026eaa20Chris Craik            clipState = nullptr;
54e4db79de127cfe961195f52907af8451026eaa20Chris Craik        }
55e4db79de127cfe961195f52907af8451026eaa20Chris Craik        clippedBounds.setEmpty();
56e4db79de127cfe961195f52907af8451026eaa20Chris Craik    } else {
57e4db79de127cfe961195f52907af8451026eaa20Chris Craik        // Not rejected! compute true clippedBounds and clipSideFlags
58e4db79de127cfe961195f52907af8451026eaa20Chris Craik        if (clipRect.left > clippedBounds.left) clipSideFlags |= OpClipSideFlags::Left;
59e4db79de127cfe961195f52907af8451026eaa20Chris Craik        if (clipRect.top > clippedBounds.top) clipSideFlags |= OpClipSideFlags::Top;
60e4db79de127cfe961195f52907af8451026eaa20Chris Craik        if (clipRect.right < clippedBounds.right) clipSideFlags |= OpClipSideFlags::Right;
61e4db79de127cfe961195f52907af8451026eaa20Chris Craik        if (clipRect.bottom < clippedBounds.bottom) clipSideFlags |= OpClipSideFlags::Bottom;
62e4db79de127cfe961195f52907af8451026eaa20Chris Craik        clippedBounds.doIntersect(clipRect);
63e4db79de127cfe961195f52907af8451026eaa20Chris Craik    }
64e4db79de127cfe961195f52907af8451026eaa20Chris Craik}
65e4db79de127cfe961195f52907af8451026eaa20Chris Craik
66e4db79de127cfe961195f52907af8451026eaa20Chris CraikResolvedRenderState::ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot) {
67e4db79de127cfe961195f52907af8451026eaa20Chris Craik    transform = *snapshot.transform;
68e4db79de127cfe961195f52907af8451026eaa20Chris Craik
69e4db79de127cfe961195f52907af8451026eaa20Chris Craik    // Since the op doesn't have known bounds, we conservatively set the mapped bounds
70e4db79de127cfe961195f52907af8451026eaa20Chris Craik    // to the current clipRect, and clipSideFlags to Full.
71e4db79de127cfe961195f52907af8451026eaa20Chris Craik    clipState = snapshot.mutateClipArea().serializeClip(allocator);
72e4db79de127cfe961195f52907af8451026eaa20Chris Craik    LOG_ALWAYS_FATAL_IF(!clipState, "clipState required");
73e4db79de127cfe961195f52907af8451026eaa20Chris Craik    clippedBounds = clipState->rect;
74e4db79de127cfe961195f52907af8451026eaa20Chris Craik    transform.mapRect(clippedBounds);
75e4db79de127cfe961195f52907af8451026eaa20Chris Craik    clipSideFlags = OpClipSideFlags::Full;
76e4db79de127cfe961195f52907af8451026eaa20Chris Craik}
77e4db79de127cfe961195f52907af8451026eaa20Chris Craik
78b87eadda1818034ce03d85f30388384d1ac65916Chris CraikResolvedRenderState::ResolvedRenderState(const Rect& dstRect)
79b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        : transform(Matrix4::identity())
80b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        , clipState(nullptr)
81b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        , clippedBounds(dstRect)
82b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        , clipSideFlags(OpClipSideFlags::None) {}
83b87eadda1818034ce03d85f30388384d1ac65916Chris Craik
84e4db79de127cfe961195f52907af8451026eaa20Chris Craik} // namespace uirenderer
85e4db79de127cfe961195f52907af8451026eaa20Chris Craik} // namespace android
86