Loading libs/hwui/BakedOpDispatcher.cpp +30 −0 Original line number Diff line number Diff line Loading @@ -705,6 +705,36 @@ void BakedOpDispatcher::onTextOp(BakedOpRenderer& renderer, const TextOp& op, co renderTextOp(renderer, op, state, clip, TextRenderType::Flush); } void BakedOpDispatcher::onTextOnPathOp(BakedOpRenderer& renderer, const TextOnPathOp& op, const BakedOpState& state) { // Note: can't trust clipSideFlags since we record with unmappedBounds == clip. // TODO: respect clipSideFlags, once we record with bounds const Rect* renderTargetClip = &state.computedState.clipRect; FontRenderer& fontRenderer = renderer.caches().fontRenderer.getFontRenderer(); fontRenderer.setFont(op.paint, SkMatrix::I()); fontRenderer.setTextureFiltering(true); Rect layerBounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f); int alpha = PaintUtils::getAlphaDirect(op.paint) * state.alpha; SkXfermode::Mode mode = PaintUtils::getXfermodeDirect(op.paint); TextDrawFunctor functor(&renderer, &state, renderTargetClip, 0.0f, 0.0f, false, alpha, mode, op.paint); bool mustDirtyRenderTarget = renderer.offscreenRenderTarget(); const Rect localSpaceClip = state.computedState.computeLocalSpaceClip(); if (fontRenderer.renderTextOnPath(op.paint, &localSpaceClip, reinterpret_cast<const char*>(op.glyphs), op.glyphCount, op.path, op.hOffset, op.vOffset, mustDirtyRenderTarget ? &layerBounds : nullptr, &functor)) { if (mustDirtyRenderTarget) { // manually dirty render target, since TextDrawFunctor won't state.computedState.transform.mapRect(layerBounds); renderer.dirtyRenderTarget(layerBounds); } } } void BakedOpDispatcher::onLayerOp(BakedOpRenderer& renderer, const LayerOp& op, const BakedOpState& state) { OffscreenBuffer* buffer = *op.layerHandle; Loading libs/hwui/BakedOpState.h +9 −0 Original line number Diff line number Diff line Loading @@ -124,6 +124,15 @@ public: clipSideFlags = OpClipSideFlags::Full; } Rect computeLocalSpaceClip() const { Matrix4 inverse; inverse.loadInverse(transform); Rect outClip(clipRect); inverse.mapRect(outClip); return outClip; } Matrix4 transform; Rect clipRect; int clipSideFlags = 0; Loading libs/hwui/OpReorderer.cpp +17 −13 Original line number Diff line number Diff line Loading @@ -90,7 +90,9 @@ public: } MergingOpBatch(batchid_t batchId, BakedOpState* op) : BatchBase(batchId, op, true) { : BatchBase(batchId, op, true) , mClipSideFlags(op->computedState.clipSideFlags) , mClipRect(op->computedState.clipRect) { } /* Loading Loading @@ -202,11 +204,11 @@ public: if (newClipSideFlags & OpClipSideFlags::Bottom) mClipRect.bottom = opClip.bottom; } bool getClipSideFlags() const { return mClipSideFlags; } int getClipSideFlags() const { return mClipSideFlags; } const Rect& getClipRect() const { return mClipRect; } private: int mClipSideFlags = 0; int mClipSideFlags; Rect mClipRect; }; Loading Loading @@ -308,12 +310,6 @@ void OpReorderer::LayerReorderer::replayBakedOpsImpl(void* arg, mergingBatch->getClipSideFlags(), mergingBatch->getClipRect() }; if (data.clipSideFlags) { // if right or bottom sides aren't used to clip, init them to viewport bounds // in the clip rect, so it can be used to scissor if (!(data.clipSideFlags & OpClipSideFlags::Right)) data.clip.right = width; if (!(data.clipSideFlags & OpClipSideFlags::Bottom)) data.clip.bottom = height; } mergedReceivers[opId](arg, data); } else { for (const BakedOpState* op : batch->getOps()) { Loading Loading @@ -850,14 +846,16 @@ void OpReorderer::deferSimpleRectsOp(const SimpleRectsOp& op) { currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::Vertices); } static batchid_t textBatchId(const SkPaint& paint) { // TODO: better handling of shader (since we won't care about color then) return paint.getColor() == SK_ColorBLACK ? OpBatchType::Text : OpBatchType::ColorText; } void OpReorderer::deferTextOp(const TextOp& op) { BakedOpState* bakedState = tryBakeOpState(op); if (!bakedState) return; // quick rejected // TODO: better handling of shader (since we won't care about color then) batchid_t batchId = op.paint->getColor() == SK_ColorBLACK ? OpBatchType::Text : OpBatchType::ColorText; batchid_t batchId = textBatchId(*(op.paint)); if (bakedState->computedState.transform.isPureTranslate() && PaintUtils::getXfermodeDirect(op.paint) == SkXfermode::kSrcOver_Mode) { mergeid_t mergeId = reinterpret_cast<mergeid_t>(op.paint->getColor()); Loading @@ -867,6 +865,12 @@ void OpReorderer::deferTextOp(const TextOp& op) { } } void OpReorderer::deferTextOnPathOp(const TextOnPathOp& op) { BakedOpState* bakedState = tryBakeOpState(op); if (!bakedState) return; // quick rejected currentLayer().deferUnmergeableOp(mAllocator, bakedState, textBatchId(*(op.paint))); } void OpReorderer::saveForLayer(uint32_t layerWidth, uint32_t layerHeight, float contentTranslateX, float contentTranslateY, const Rect& repaintRect, Loading libs/hwui/RecordedOp.h +18 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,7 @@ struct Vertex; U_OP_FN(ShadowOp) \ U_OP_FN(SimpleRectsOp) \ M_OP_FN(TextOp) \ U_OP_FN(TextOnPathOp) \ U_OP_FN(BeginLayerOp) \ U_OP_FN(EndLayerOp) \ U_OP_FN(LayerOp) Loading Loading @@ -327,6 +328,23 @@ struct TextOp : RecordedOp { const float y; }; struct TextOnPathOp : RecordedOp { TextOnPathOp(BASE_PARAMS, const glyph_t* glyphs, int glyphCount, const SkPath* path, float hOffset, float vOffset) : SUPER(TextOnPathOp) , glyphs(glyphs) , glyphCount(glyphCount) , path(path) , hOffset(hOffset) , vOffset(vOffset) {} const glyph_t* glyphs; const int glyphCount; const SkPath* path; const float hOffset; const float vOffset; }; //////////////////////////////////////////////////////////////////////////////////////////////////// // Layers //////////////////////////////////////////////////////////////////////////////////////////////////// Loading libs/hwui/RecordingCanvas.cpp +8 −2 Original line number Diff line number Diff line Loading @@ -503,9 +503,15 @@ void RecordingCanvas::drawText(const uint16_t* glyphs, const float* positions, i drawTextDecorations(x, y, totalAdvance, paint); } void RecordingCanvas::drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path, void RecordingCanvas::drawTextOnPath(const uint16_t* glyphs, int glyphCount, const SkPath& path, float hOffset, float vOffset, const SkPaint& paint) { LOG_ALWAYS_FATAL("TODO!"); if (!glyphs || glyphCount <= 0 || PaintUtils::paintWillNotDrawText(paint)) return; glyphs = refBuffer<glyph_t>(glyphs, glyphCount); addOp(new (alloc()) TextOnPathOp( mState.getRenderTargetClipBounds(), // TODO: explicitly define bounds *(mState.currentSnapshot()->transform), mState.getRenderTargetClipBounds(), refPaint(&paint), glyphs, glyphCount, refPath(&path), hOffset, vOffset)); } void RecordingCanvas::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) { Loading Loading
libs/hwui/BakedOpDispatcher.cpp +30 −0 Original line number Diff line number Diff line Loading @@ -705,6 +705,36 @@ void BakedOpDispatcher::onTextOp(BakedOpRenderer& renderer, const TextOp& op, co renderTextOp(renderer, op, state, clip, TextRenderType::Flush); } void BakedOpDispatcher::onTextOnPathOp(BakedOpRenderer& renderer, const TextOnPathOp& op, const BakedOpState& state) { // Note: can't trust clipSideFlags since we record with unmappedBounds == clip. // TODO: respect clipSideFlags, once we record with bounds const Rect* renderTargetClip = &state.computedState.clipRect; FontRenderer& fontRenderer = renderer.caches().fontRenderer.getFontRenderer(); fontRenderer.setFont(op.paint, SkMatrix::I()); fontRenderer.setTextureFiltering(true); Rect layerBounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f); int alpha = PaintUtils::getAlphaDirect(op.paint) * state.alpha; SkXfermode::Mode mode = PaintUtils::getXfermodeDirect(op.paint); TextDrawFunctor functor(&renderer, &state, renderTargetClip, 0.0f, 0.0f, false, alpha, mode, op.paint); bool mustDirtyRenderTarget = renderer.offscreenRenderTarget(); const Rect localSpaceClip = state.computedState.computeLocalSpaceClip(); if (fontRenderer.renderTextOnPath(op.paint, &localSpaceClip, reinterpret_cast<const char*>(op.glyphs), op.glyphCount, op.path, op.hOffset, op.vOffset, mustDirtyRenderTarget ? &layerBounds : nullptr, &functor)) { if (mustDirtyRenderTarget) { // manually dirty render target, since TextDrawFunctor won't state.computedState.transform.mapRect(layerBounds); renderer.dirtyRenderTarget(layerBounds); } } } void BakedOpDispatcher::onLayerOp(BakedOpRenderer& renderer, const LayerOp& op, const BakedOpState& state) { OffscreenBuffer* buffer = *op.layerHandle; Loading
libs/hwui/BakedOpState.h +9 −0 Original line number Diff line number Diff line Loading @@ -124,6 +124,15 @@ public: clipSideFlags = OpClipSideFlags::Full; } Rect computeLocalSpaceClip() const { Matrix4 inverse; inverse.loadInverse(transform); Rect outClip(clipRect); inverse.mapRect(outClip); return outClip; } Matrix4 transform; Rect clipRect; int clipSideFlags = 0; Loading
libs/hwui/OpReorderer.cpp +17 −13 Original line number Diff line number Diff line Loading @@ -90,7 +90,9 @@ public: } MergingOpBatch(batchid_t batchId, BakedOpState* op) : BatchBase(batchId, op, true) { : BatchBase(batchId, op, true) , mClipSideFlags(op->computedState.clipSideFlags) , mClipRect(op->computedState.clipRect) { } /* Loading Loading @@ -202,11 +204,11 @@ public: if (newClipSideFlags & OpClipSideFlags::Bottom) mClipRect.bottom = opClip.bottom; } bool getClipSideFlags() const { return mClipSideFlags; } int getClipSideFlags() const { return mClipSideFlags; } const Rect& getClipRect() const { return mClipRect; } private: int mClipSideFlags = 0; int mClipSideFlags; Rect mClipRect; }; Loading Loading @@ -308,12 +310,6 @@ void OpReorderer::LayerReorderer::replayBakedOpsImpl(void* arg, mergingBatch->getClipSideFlags(), mergingBatch->getClipRect() }; if (data.clipSideFlags) { // if right or bottom sides aren't used to clip, init them to viewport bounds // in the clip rect, so it can be used to scissor if (!(data.clipSideFlags & OpClipSideFlags::Right)) data.clip.right = width; if (!(data.clipSideFlags & OpClipSideFlags::Bottom)) data.clip.bottom = height; } mergedReceivers[opId](arg, data); } else { for (const BakedOpState* op : batch->getOps()) { Loading Loading @@ -850,14 +846,16 @@ void OpReorderer::deferSimpleRectsOp(const SimpleRectsOp& op) { currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::Vertices); } static batchid_t textBatchId(const SkPaint& paint) { // TODO: better handling of shader (since we won't care about color then) return paint.getColor() == SK_ColorBLACK ? OpBatchType::Text : OpBatchType::ColorText; } void OpReorderer::deferTextOp(const TextOp& op) { BakedOpState* bakedState = tryBakeOpState(op); if (!bakedState) return; // quick rejected // TODO: better handling of shader (since we won't care about color then) batchid_t batchId = op.paint->getColor() == SK_ColorBLACK ? OpBatchType::Text : OpBatchType::ColorText; batchid_t batchId = textBatchId(*(op.paint)); if (bakedState->computedState.transform.isPureTranslate() && PaintUtils::getXfermodeDirect(op.paint) == SkXfermode::kSrcOver_Mode) { mergeid_t mergeId = reinterpret_cast<mergeid_t>(op.paint->getColor()); Loading @@ -867,6 +865,12 @@ void OpReorderer::deferTextOp(const TextOp& op) { } } void OpReorderer::deferTextOnPathOp(const TextOnPathOp& op) { BakedOpState* bakedState = tryBakeOpState(op); if (!bakedState) return; // quick rejected currentLayer().deferUnmergeableOp(mAllocator, bakedState, textBatchId(*(op.paint))); } void OpReorderer::saveForLayer(uint32_t layerWidth, uint32_t layerHeight, float contentTranslateX, float contentTranslateY, const Rect& repaintRect, Loading
libs/hwui/RecordedOp.h +18 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,7 @@ struct Vertex; U_OP_FN(ShadowOp) \ U_OP_FN(SimpleRectsOp) \ M_OP_FN(TextOp) \ U_OP_FN(TextOnPathOp) \ U_OP_FN(BeginLayerOp) \ U_OP_FN(EndLayerOp) \ U_OP_FN(LayerOp) Loading Loading @@ -327,6 +328,23 @@ struct TextOp : RecordedOp { const float y; }; struct TextOnPathOp : RecordedOp { TextOnPathOp(BASE_PARAMS, const glyph_t* glyphs, int glyphCount, const SkPath* path, float hOffset, float vOffset) : SUPER(TextOnPathOp) , glyphs(glyphs) , glyphCount(glyphCount) , path(path) , hOffset(hOffset) , vOffset(vOffset) {} const glyph_t* glyphs; const int glyphCount; const SkPath* path; const float hOffset; const float vOffset; }; //////////////////////////////////////////////////////////////////////////////////////////////////// // Layers //////////////////////////////////////////////////////////////////////////////////////////////////// Loading
libs/hwui/RecordingCanvas.cpp +8 −2 Original line number Diff line number Diff line Loading @@ -503,9 +503,15 @@ void RecordingCanvas::drawText(const uint16_t* glyphs, const float* positions, i drawTextDecorations(x, y, totalAdvance, paint); } void RecordingCanvas::drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path, void RecordingCanvas::drawTextOnPath(const uint16_t* glyphs, int glyphCount, const SkPath& path, float hOffset, float vOffset, const SkPaint& paint) { LOG_ALWAYS_FATAL("TODO!"); if (!glyphs || glyphCount <= 0 || PaintUtils::paintWillNotDrawText(paint)) return; glyphs = refBuffer<glyph_t>(glyphs, glyphCount); addOp(new (alloc()) TextOnPathOp( mState.getRenderTargetClipBounds(), // TODO: explicitly define bounds *(mState.currentSnapshot()->transform), mState.getRenderTargetClipBounds(), refPaint(&paint), glyphs, glyphCount, refPath(&path), hOffset, vOffset)); } void RecordingCanvas::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) { Loading