diff options
| author | 2015-12-22 16:32:23 -0800 | |
|---|---|---|
| committer | 2016-01-04 17:00:03 -0800 | |
| commit | e4db79de127cfe961195f52907af8451026eaa20 (patch) | |
| tree | 94be898632cc176b599aa2997072e91628d16dd3 /libs/hwui/BakedOpState.cpp | |
| parent | 33e9b426da2863cdd9e675cde018b450a66e9ab4 (diff) | |
Stencil support in new recorder/reorderer
bug:22480459
bug:26358504
Adds complex (non-rectangular) clipping support, and overdraw
visualization. Doesn't support stencil clipping in layers.
Change-Id: I8d10c7f1d2769ab5756774ca672344cc09901f87
Diffstat (limited to 'libs/hwui/BakedOpState.cpp')
| -rw-r--r-- | libs/hwui/BakedOpState.cpp | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/libs/hwui/BakedOpState.cpp b/libs/hwui/BakedOpState.cpp new file mode 100644 index 000000000000..e6b943a606d5 --- /dev/null +++ b/libs/hwui/BakedOpState.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "BakedOpState.h" + +#include "ClipArea.h" + +namespace android { +namespace uirenderer { + +ResolvedRenderState::ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot, + const RecordedOp& recordedOp, bool expandForStroke) { + // resolvedMatrix = parentMatrix * localMatrix + transform.loadMultiply(*snapshot.transform, recordedOp.localMatrix); + + // resolvedClippedBounds = intersect(resolvedMatrix * opBounds, resolvedClipRect) + clippedBounds = recordedOp.unmappedBounds; + if (CC_UNLIKELY(expandForStroke)) { + // account for non-hairline stroke + clippedBounds.outset(recordedOp.paint->getStrokeWidth() * 0.5f); + } + transform.mapRect(clippedBounds); + if (CC_UNLIKELY(expandForStroke + && (!transform.isPureTranslate() || recordedOp.paint->getStrokeWidth() < 1.0f))) { + // account for hairline stroke when stroke may be < 1 scaled pixel + // Non translate || strokeWidth < 1 is conservative, but will cover all cases + clippedBounds.outset(0.5f); + } + + // resolvedClipRect = intersect(parentMatrix * localClip, parentClip) + clipState = snapshot.mutateClipArea().serializeIntersectedClip(allocator, + recordedOp.localClip, *(snapshot.transform)); + LOG_ALWAYS_FATAL_IF(!clipState, "must clip!"); + + const Rect& clipRect = clipState->rect; + if (CC_UNLIKELY(clipRect.isEmpty() || !clippedBounds.intersects(clipRect))) { + // Rejected based on either empty clip, or bounds not intersecting with clip + if (clipState) { + allocator.rewindIfLastAlloc(clipState); + clipState = nullptr; + } + clippedBounds.setEmpty(); + } else { + // Not rejected! compute true clippedBounds and clipSideFlags + if (clipRect.left > clippedBounds.left) clipSideFlags |= OpClipSideFlags::Left; + if (clipRect.top > clippedBounds.top) clipSideFlags |= OpClipSideFlags::Top; + if (clipRect.right < clippedBounds.right) clipSideFlags |= OpClipSideFlags::Right; + if (clipRect.bottom < clippedBounds.bottom) clipSideFlags |= OpClipSideFlags::Bottom; + clippedBounds.doIntersect(clipRect); + } +} + +ResolvedRenderState::ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot) { + transform = *snapshot.transform; + + // Since the op doesn't have known bounds, we conservatively set the mapped bounds + // to the current clipRect, and clipSideFlags to Full. + clipState = snapshot.mutateClipArea().serializeClip(allocator); + LOG_ALWAYS_FATAL_IF(!clipState, "clipState required"); + clippedBounds = clipState->rect; + transform.mapRect(clippedBounds); + clipSideFlags = OpClipSideFlags::Full; +} + +} // namespace uirenderer +} // namespace android |