Added implementation for YogaNodeJNIBatching and logic for passing array from c++ to java

Summary: This diff adds the logic to transfer layout outputs using a float array

Reviewed By: davidaurelio

Differential Revision: D14368120

fbshipit-source-id: d1f22283bcea051d15657f42c15b90edaa0a8a7a
This commit is contained in:
Sidharth Guglani
2019-04-01 06:11:51 -07:00
committed by Facebook Github Bot
parent 5fad8008ab
commit c11faf2d56
2 changed files with 320 additions and 66 deletions

View File

@@ -0,0 +1,177 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree.
*/
package com.facebook.yoga;
import javax.annotation.Nullable;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public class YogaNodeJNIBatching extends YogaNodeJNIBase {
/* Those flags needs be in sync with YGJNI.cpp */
private static final byte MARGIN = 1;
private static final byte PADDING = 2;
private static final byte BORDER = 4;
private static final byte DOES_LEGACY_STRETCH_BEHAVIOUR = 8;
private static final byte HAS_NEW_LAYOUT = 16;
private static final byte LAYOUT_EDGE_SET_FLAG_INDEX = 0;
private static final byte LAYOUT_WIDTH_INDEX = 1;
private static final byte LAYOUT_HEIGHT_INDEX = 2;
private static final byte LAYOUT_LEFT_INDEX = 3;
private static final byte LAYOUT_TOP_INDEX = 4;
private static final byte LAYOUT_DIRECTION_INDEX = 5;
private static final byte LAYOUT_MARGIN_START_INDEX = 6;
private static final byte LAYOUT_PADDING_START_INDEX = 10;
private static final byte LAYOUT_BORDER_START_INDEX = 14;
@DoNotStrip
private @Nullable float[] arr = null;
@DoNotStrip
private int mLayoutDirection = 0;
private boolean mHasNewLayout = true;
public YogaNodeJNIBatching() {
super();
}
public YogaNodeJNIBatching(YogaConfig config) {
super(config);
}
@Override
public void reset() {
super.reset();
arr = null;
mHasNewLayout = true;
mLayoutDirection = 0;
}
@Override
public float getLayoutX() {
return arr != null ? arr[LAYOUT_LEFT_INDEX] : 0;
}
@Override
public float getLayoutY() {
return arr != null ? arr[LAYOUT_TOP_INDEX] : 0;
}
@Override
public float getLayoutWidth() {
return arr != null ? arr[LAYOUT_WIDTH_INDEX] : 0;
}
@Override
public float getLayoutHeight() {
return arr != null ? arr[LAYOUT_HEIGHT_INDEX] : 0;
}
@Override
public boolean getDoesLegacyStretchFlagAffectsLayout() {
return arr != null && (((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & DOES_LEGACY_STRETCH_BEHAVIOUR) == DOES_LEGACY_STRETCH_BEHAVIOUR);
}
@Override
public float getLayoutMargin(YogaEdge edge) {
if (arr != null && ((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & MARGIN) == MARGIN) {
switch (edge) {
case LEFT:
return arr[LAYOUT_MARGIN_START_INDEX];
case TOP:
return arr[LAYOUT_MARGIN_START_INDEX + 1];
case RIGHT:
return arr[LAYOUT_MARGIN_START_INDEX + 2];
case BOTTOM:
return arr[LAYOUT_MARGIN_START_INDEX + 3];
case START:
return getLayoutDirection() == YogaDirection.RTL ? arr[LAYOUT_MARGIN_START_INDEX + 2] : arr[LAYOUT_MARGIN_START_INDEX];
case END:
return getLayoutDirection() == YogaDirection.RTL ? arr[LAYOUT_MARGIN_START_INDEX] : arr[LAYOUT_MARGIN_START_INDEX + 2];
default:
throw new IllegalArgumentException("Cannot get layout margins of multi-edge shorthands");
}
} else {
return 0;
}
}
@Override
public float getLayoutPadding(YogaEdge edge) {
if (arr != null && ((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & PADDING) == PADDING) {
int paddingStartIndex = LAYOUT_PADDING_START_INDEX - ((((int)arr[LAYOUT_EDGE_SET_FLAG_INDEX] & MARGIN) == MARGIN) ? 0 : 4);
switch (edge) {
case LEFT:
return arr[paddingStartIndex];
case TOP:
return arr[paddingStartIndex + 1];
case RIGHT:
return arr[paddingStartIndex + 2];
case BOTTOM:
return arr[paddingStartIndex + 3];
case START:
return getLayoutDirection() == YogaDirection.RTL ? arr[paddingStartIndex + 2] : arr[paddingStartIndex];
case END:
return getLayoutDirection() == YogaDirection.RTL ? arr[paddingStartIndex] : arr[paddingStartIndex + 2];
default:
throw new IllegalArgumentException("Cannot get layout paddings of multi-edge shorthands");
}
} else {
return 0;
}
}
@Override
public float getLayoutBorder(YogaEdge edge) {
if (arr != null && ((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & BORDER) == BORDER) {
int borderStartIndex = LAYOUT_BORDER_START_INDEX - ((((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & MARGIN) == MARGIN) ? 0 : 4) - ((((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX] & PADDING) == PADDING) ? 0 : 4);
switch (edge) {
case LEFT:
return arr[borderStartIndex];
case TOP:
return arr[borderStartIndex + 1];
case RIGHT:
return arr[borderStartIndex + 2];
case BOTTOM:
return arr[borderStartIndex + 3];
case START:
return getLayoutDirection() == YogaDirection.RTL ? arr[borderStartIndex + 2] : arr[borderStartIndex];
case END:
return getLayoutDirection() == YogaDirection.RTL ? arr[borderStartIndex] : arr[borderStartIndex + 2];
default:
throw new IllegalArgumentException("Cannot get layout border of multi-edge shorthands");
}
} else {
return 0;
}
}
@Override
public YogaDirection getLayoutDirection() {
return YogaDirection.fromInt(arr != null ? (int) arr[LAYOUT_DIRECTION_INDEX] : mLayoutDirection);
}
@Override
public boolean hasNewLayout() {
if (arr != null) {
return (((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX]) & HAS_NEW_LAYOUT) == HAS_NEW_LAYOUT;
} else {
return mHasNewLayout;
}
}
@Override
public void markLayoutSeen() {
if (arr != null) {
arr[LAYOUT_EDGE_SET_FLAG_INDEX] = ((int) arr[LAYOUT_EDGE_SET_FLAG_INDEX]) & ~(HAS_NEW_LAYOUT);
}
mHasNewLayout = false;
}
}

View File

@@ -62,6 +62,16 @@ enum YGStyleInput {
IsReferenceBaseline, IsReferenceBaseline,
}; };
const short int LAYOUT_EDGE_SET_FLAG_INDEX = 0;
const short int LAYOUT_WIDTH_INDEX = 1;
const short int LAYOUT_HEIGHT_INDEX = 2;
const short int LAYOUT_LEFT_INDEX = 3;
const short int LAYOUT_TOP_INDEX = 4;
const short int LAYOUT_DIRECTION_INDEX = 5;
const short int LAYOUT_MARGIN_START_INDEX = 6;
const short int LAYOUT_PADDING_START_INDEX = 10;
const short int LAYOUT_BORDER_START_INDEX = 14;
class PtrJNodeMap { class PtrJNodeMap {
using JNodeArray = JArrayClass<JYogaNode::javaobject>; using JNodeArray = JArrayClass<JYogaNode::javaobject>;
std::map<YGNodeRef, size_t> ptrsToIdxs_; std::map<YGNodeRef, size_t> ptrsToIdxs_;
@@ -97,6 +107,9 @@ union YGNodeContext {
void* asVoidPtr; void* asVoidPtr;
}; };
const int DOES_LEGACY_STRETCH_BEHAVIOUR = 8;
const int HAS_NEW_LAYOUT = 16;
class YGNodeEdges { class YGNodeEdges {
uintptr_t edges_; uintptr_t edges_;
@@ -127,6 +140,10 @@ public:
edges_ |= edge; edges_ |= edge;
return *this; return *this;
} }
int get() {
return edges_;
}
}; };
struct YogaValue { struct YogaValue {
@@ -177,6 +194,60 @@ static void YGTransferLayoutOutputsRecursive(
auto edgesSet = YGNodeEdges{root}; auto edgesSet = YGNodeEdges{root};
if (false) {
bool marginFieldSet = edgesSet.has(YGNodeEdges::MARGIN);
bool paddingFieldSet = edgesSet.has(YGNodeEdges::PADDING);
bool borderFieldSet = edgesSet.has(YGNodeEdges::BORDER);
int fieldFlags = edgesSet.get();
fieldFlags |= HAS_NEW_LAYOUT;
if (YGNodeLayoutGetDidLegacyStretchFlagAffectLayout(root)) {
fieldFlags |= DOES_LEGACY_STRETCH_BEHAVIOUR;
}
const int arrSize = 6 + (marginFieldSet ? 4 : 0) +
(paddingFieldSet ? 4 : 0) + (borderFieldSet ? 4 : 0);
float arr[18];
arr[LAYOUT_EDGE_SET_FLAG_INDEX] = fieldFlags;
arr[LAYOUT_WIDTH_INDEX] = YGNodeLayoutGetWidth(root);
arr[LAYOUT_HEIGHT_INDEX] = YGNodeLayoutGetHeight(root);
arr[LAYOUT_LEFT_INDEX] = YGNodeLayoutGetLeft(root);
arr[LAYOUT_TOP_INDEX] = YGNodeLayoutGetTop(root);
arr[LAYOUT_DIRECTION_INDEX] =
static_cast<jint>(YGNodeLayoutGetDirection(root));
if (marginFieldSet) {
arr[LAYOUT_MARGIN_START_INDEX] = YGNodeLayoutGetMargin(root, YGEdgeLeft);
arr[LAYOUT_MARGIN_START_INDEX + 1] =
YGNodeLayoutGetMargin(root, YGEdgeTop);
arr[LAYOUT_MARGIN_START_INDEX + 2] =
YGNodeLayoutGetMargin(root, YGEdgeRight);
arr[LAYOUT_MARGIN_START_INDEX + 3] =
YGNodeLayoutGetMargin(root, YGEdgeBottom);
}
if (paddingFieldSet) {
int paddingStartIndex =
LAYOUT_PADDING_START_INDEX - (marginFieldSet ? 0 : 4);
arr[paddingStartIndex] = YGNodeLayoutGetPadding(root, YGEdgeLeft);
arr[paddingStartIndex + 1] = YGNodeLayoutGetPadding(root, YGEdgeTop);
arr[paddingStartIndex + 2] = YGNodeLayoutGetPadding(root, YGEdgeRight);
arr[paddingStartIndex + 3] = YGNodeLayoutGetPadding(root, YGEdgeBottom);
}
if (borderFieldSet) {
int borderStartIndex = LAYOUT_BORDER_START_INDEX -
(marginFieldSet ? 0 : 4) - (paddingFieldSet ? 0 : 4);
arr[borderStartIndex] = YGNodeLayoutGetBorder(root, YGEdgeLeft);
arr[borderStartIndex + 1] = YGNodeLayoutGetBorder(root, YGEdgeTop);
arr[borderStartIndex + 2] = YGNodeLayoutGetBorder(root, YGEdgeRight);
arr[borderStartIndex + 3] = YGNodeLayoutGetBorder(root, YGEdgeBottom);
}
static auto arrField = obj->getClass()->getField<jfloatArray>("arr");
local_ref<jfloatArray> arrFinal = make_float_array(arrSize);
arrFinal->setRegion(0, arrSize, arr);
obj->setFieldValue<jfloatArray>(arrField, arrFinal.get());
} else {
static auto widthField = obj->getClass()->getField<jfloat>("mWidth"); static auto widthField = obj->getClass()->getField<jfloat>("mWidth");
static auto heightField = obj->getClass()->getField<jfloat>("mHeight"); static auto heightField = obj->getClass()->getField<jfloat>("mHeight");
static auto leftField = obj->getClass()->getField<jfloat>("mLeft"); static auto leftField = obj->getClass()->getField<jfloat>("mLeft");
@@ -184,7 +255,8 @@ static void YGTransferLayoutOutputsRecursive(
static auto marginLeftField = static auto marginLeftField =
obj->getClass()->getField<jfloat>("mMarginLeft"); obj->getClass()->getField<jfloat>("mMarginLeft");
static auto marginTopField = obj->getClass()->getField<jfloat>("mMarginTop"); static auto marginTopField =
obj->getClass()->getField<jfloat>("mMarginTop");
static auto marginRightField = static auto marginRightField =
obj->getClass()->getField<jfloat>("mMarginRight"); obj->getClass()->getField<jfloat>("mMarginRight");
static auto marginBottomField = static auto marginBottomField =
@@ -201,7 +273,8 @@ static void YGTransferLayoutOutputsRecursive(
static auto borderLeftField = static auto borderLeftField =
obj->getClass()->getField<jfloat>("mBorderLeft"); obj->getClass()->getField<jfloat>("mBorderLeft");
static auto borderTopField = obj->getClass()->getField<jfloat>("mBorderTop"); static auto borderTopField =
obj->getClass()->getField<jfloat>("mBorderTop");
static auto borderRightField = static auto borderRightField =
obj->getClass()->getField<jfloat>("mBorderRight"); obj->getClass()->getField<jfloat>("mBorderRight");
static auto borderBottomField = static auto borderBottomField =
@@ -209,7 +282,8 @@ static void YGTransferLayoutOutputsRecursive(
static auto hasNewLayoutField = static auto hasNewLayoutField =
obj->getClass()->getField<jboolean>("mHasNewLayout"); obj->getClass()->getField<jboolean>("mHasNewLayout");
static auto doesLegacyStretchBehaviour = obj->getClass()->getField<jboolean>( static auto doesLegacyStretchBehaviour =
obj->getClass()->getField<jboolean>(
"mDoesLegacyStretchFlagAffectsLayout"); "mDoesLegacyStretchFlagAffectsLayout");
obj->setFieldValue(widthField, YGNodeLayoutGetWidth(root)); obj->setFieldValue(widthField, YGNodeLayoutGetWidth(root));
@@ -225,7 +299,8 @@ static void YGTransferLayoutOutputsRecursive(
if (edgesSet.has(YGNodeEdges::MARGIN)) { if (edgesSet.has(YGNodeEdges::MARGIN)) {
obj->setFieldValue( obj->setFieldValue(
marginLeftField, YGNodeLayoutGetMargin(root, YGEdgeLeft)); marginLeftField, YGNodeLayoutGetMargin(root, YGEdgeLeft));
obj->setFieldValue(marginTopField, YGNodeLayoutGetMargin(root, YGEdgeTop)); obj->setFieldValue(
marginTopField, YGNodeLayoutGetMargin(root, YGEdgeTop));
obj->setFieldValue( obj->setFieldValue(
marginRightField, YGNodeLayoutGetMargin(root, YGEdgeRight)); marginRightField, YGNodeLayoutGetMargin(root, YGEdgeRight));
obj->setFieldValue( obj->setFieldValue(
@@ -246,12 +321,14 @@ static void YGTransferLayoutOutputsRecursive(
if (edgesSet.has(YGNodeEdges::BORDER)) { if (edgesSet.has(YGNodeEdges::BORDER)) {
obj->setFieldValue( obj->setFieldValue(
borderLeftField, YGNodeLayoutGetBorder(root, YGEdgeLeft)); borderLeftField, YGNodeLayoutGetBorder(root, YGEdgeLeft));
obj->setFieldValue(borderTopField, YGNodeLayoutGetBorder(root, YGEdgeTop)); obj->setFieldValue(
borderTopField, YGNodeLayoutGetBorder(root, YGEdgeTop));
obj->setFieldValue( obj->setFieldValue(
borderRightField, YGNodeLayoutGetBorder(root, YGEdgeRight)); borderRightField, YGNodeLayoutGetBorder(root, YGEdgeRight));
obj->setFieldValue( obj->setFieldValue(
borderBottomField, YGNodeLayoutGetBorder(root, YGEdgeBottom)); borderBottomField, YGNodeLayoutGetBorder(root, YGEdgeBottom));
} }
}
root->setHasNewLayout(false); root->setHasNewLayout(false);