Skip to content
This repository has been archived by the owner on Jun 3, 2021. It is now read-only.

[Android] solve components exceed gpu limit problem #2603

Merged
merged 15 commits into from
Jul 1, 2019
10 changes: 9 additions & 1 deletion android/sdk/src/main/java/com/taobao/weex/WXSDKInstance.java
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ public class WXSDKInstance implements IWXActivityStateListener,View.OnLayoutChan
private Map<String,String> mContainerInfo;

public boolean isNewFsEnd = false;
private List<String> componentsInfoExceedGPULimit = new ArrayList<>();

/**
* bundle type
Expand Down Expand Up @@ -206,6 +207,13 @@ public class WXSDKInstance implements IWXActivityStateListener,View.OnLayoutChan
* */
private boolean mAutoAdjustDeviceWidth = WXEnvironment.AUTO_ADJUST_ENV_DEVICE_WIDTH;

public List<String> getComponentsExceedGPULimit(){return componentsInfoExceedGPULimit;}
@RestrictTo(Scope.LIBRARY)
public void setComponentsInfoExceedGPULimit(String componentInfo){
if(componentInfo != null && !TextUtils.isEmpty(componentInfo)){
componentsInfoExceedGPULimit.add(componentInfo);
}
}

public List<String> getLayerOverFlowListeners() {
return mLayerOverFlowListeners;
Expand Down Expand Up @@ -827,7 +835,7 @@ private void renderInternal(String pageName,
mWXPerformance.JSTemplateSize = template.length() / 1024f;
mApmForInstance.addStats(WXInstanceApm.KEY_PAGE_STATS_BUNDLE_SIZE,mWXPerformance.JSTemplateSize);
mRenderStartTime = System.currentTimeMillis();
WXSDKManager.getInstance().setCrashInfo(WXEnvironment.WEEX_CURRENT_KEY,pageName);;
WXSDKManager.getInstance().setCrashInfo(WXEnvironment.WEEX_CURRENT_KEY,pageName);
if(mAutoAdjustDeviceWidth && WXDeviceUtils.isAutoResize(mContext)){
if(WXEnvironment.AUTO_UPDATE_APPLICATION_SCREEN_SIZE) {
WXViewUtils.updateApplicationScreen(mContext);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
import com.taobao.weex.performance.WXInstanceApm;
import com.taobao.weex.performance.WXStateRecord;
import com.taobao.weex.ui.WXComponentRegistry;
import com.taobao.weex.ui.WXRenderManager;
import com.taobao.weex.ui.action.ActionReloadPage;
import com.taobao.weex.ui.action.BasicGraphicAction;
import com.taobao.weex.ui.action.GraphicActionAddElement;
Expand Down Expand Up @@ -102,11 +103,13 @@
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Stack;
import java.util.concurrent.CountDownLatch;
Expand Down Expand Up @@ -2948,7 +2951,74 @@ public int callUpdateAttrs(String instanceId, String ref, HashMap<String, String

return IWXBridge.INSTANCE_RENDERING;
}
public boolean shouldReportGPULimit() {
YorkShen marked this conversation as resolved.
Show resolved Hide resolved
IWXConfigAdapter adapter = WXSDKManager.getInstance().getWxConfigAdapter();
boolean report_gpu_limited_layout = false;
if (adapter != null) {
float sample_rate_of_report = Float.parseFloat(adapter
YorkShen marked this conversation as resolved.
Show resolved Hide resolved
.getConfig("android_weex_test_gpu",
"sample_rate_of_report",
"0"));
WXLogUtils.e("sample_rate_of_report : " + sample_rate_of_report);
YorkShen marked this conversation as resolved.
Show resolved Hide resolved
if(Math.random() < sample_rate_of_report){
report_gpu_limited_layout = true;
}
}
return report_gpu_limited_layout;
}

public void reportIfReachGPULimit(String instanceId,String ref,GraphicSize layoutSize){
YorkShen marked this conversation as resolved.
Show resolved Hide resolved
float limit = WXRenderManager.getOpenGLRenderLimitValue();
if((layoutSize.getHeight() > limit || layoutSize.getWidth() > limit) && shouldReportGPULimit()){
Map<String, String> ext = new ArrayMap<>();
YorkShen marked this conversation as resolved.
Show resolved Hide resolved
WXComponent component = WXSDKManager.getInstance().getWXRenderManager().getWXComponent(instanceId,ref);
ext.put("GPU limit",String.valueOf(limit));
ext.put("component.width",String.valueOf(layoutSize.getWidth()));
ext.put("component.height",String.valueOf(layoutSize.getHeight()));
if (component.getComponentType() != null && !component.getComponentType().isEmpty()) {
ext.put("component.type", component.getComponentType());
}
if (component.getStyles() != null && !component.getStyles().isEmpty()) {
ext.put("component.style", component.getStyles().toString());
}
if (component.getAttrs() != null && !component.getAttrs().isEmpty()) {
ext.put("component.attr", component.getAttrs().toString());
}
if (component.getEvents() != null && !component.getEvents().isEmpty()) {
ext.put("component.event", component.getEvents().toString());
}
if (component.getMargin() != null) {
ext.put("component.margin", component.getMargin().toString());
}
if (component.getPadding() != null) {
ext.put("component.padding", component.getPadding().toString());
}
if (component.getBorder() != null) {
ext.put("component.border", component.getBorder().toString());
}
WXSDKManager.getInstance().getSDKInstance(instanceId).setComponentsInfoExceedGPULimit(transComponentInfo(ext));
WXExceptionUtils.commitCriticalExceptionRT(instanceId
, WXErrorCode.WX_RENDER_WAR_GPU_LIMIT_LAYOUT,
"WXBridgeManager",
String.format(Locale.ENGLISH,"You are creating a component(%s x %2$s) which exceeds the limit of gpu(%3$s x %3$s),it may cause crash",
String.valueOf(layoutSize.getWidth()),String.valueOf(layoutSize.getHeight()),String.valueOf(limit)),
ext);
}
}
public String transComponentInfo(Map<String,String> map){
JSONObject data = new JSONObject();
if(map != null) {
try {
for (String key : map.keySet()) {
data.put(key, map.get(key));
}
} catch (Exception e) {
e.printStackTrace();
}
}
return data.toString();

}
public int callLayout(String pageId, String ref, int top, int bottom, int left, int right, int height, int width, boolean isRTL, int index) {

if (TextUtils.isEmpty(pageId) || TextUtils.isEmpty(ref)) {
Expand Down Expand Up @@ -2982,6 +3052,7 @@ public int callLayout(String pageId, String ref, int top, int bottom, int left,
if (instance != null) {
GraphicSize size = new GraphicSize(width, height);
GraphicPosition position = new GraphicPosition(left, top, right, bottom);
reportIfReachGPULimit(pageId,ref,size);
GraphicActionAddElement addAction = instance.getInActiveAddElementAction(ref);
if(addAction!=null) {
addAction.setRTL(isRTL);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ public enum WXErrorCode {
WX_RENDER_ERR_INSTANCE_ID_NULL("-9618", "WX_RENDER_ERR_INSTANCE_ID_NULL", ErrorType.NATIVE_ERROR, ErrorGroup.NATIVE),
WX_RENDER_ERR_LIST_INVALID_COLUMN_COUNT("-9619", "WX_RENDER_ERR_LIST_INVALID_COLUMNJ_CONUNT", ErrorType.JS_ERROR, ErrorGroup.JS),
WX_RENDER_ERR_TEXTURE_SETBACKGROUND("-9620", "WX_RENDER_ERR_TEXTURE_SETBACKGROUND", ErrorType.NATIVE_ERROR, ErrorGroup.NATIVE),
WX_RENDER_WAR_GPU_LIMIT_LAYOUT("-9621", "WX_RENDER_WAR_GPU_LIMIT_LAYOUT", ErrorType.JS_ERROR,ErrorGroup.JS),

WX_KEY_EXCEPTION_NO_BUNDLE_TYPE("-9801", "Fatal Error : No bundle type in js bundle head, cause white screen or memory leak!!", ErrorType.JS_ERROR, ErrorGroup.JS),
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,27 @@
*/
package com.taobao.weex.ui;

import android.opengl.GLES10;
import android.os.Build;
import android.support.annotation.Nullable;
import android.support.annotation.RestrictTo;
import android.support.annotation.RestrictTo.Scope;
import android.support.v4.util.ArrayMap;
import android.text.TextUtils;

import com.taobao.weex.WXSDKInstance;
import com.taobao.weex.WXSDKManager;
import com.taobao.weex.common.WXErrorCode;
import com.taobao.weex.common.WXRuntimeException;
import com.taobao.weex.common.WXThread;
import com.taobao.weex.dom.RenderContext;
import com.taobao.weex.performance.WXInstanceApm;
import com.taobao.weex.ui.action.BasicGraphicAction;
import com.taobao.weex.ui.action.GraphicActionBatchAction;
import com.taobao.weex.ui.action.GraphicSize;
import com.taobao.weex.ui.component.WXComponent;
import com.taobao.weex.utils.WXExceptionUtils;
import com.taobao.weex.utils.WXLogUtils;
import com.taobao.weex.utils.WXUtils;

import java.util.ArrayList;
Expand All @@ -41,6 +47,12 @@
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.egl.EGLSurface;

/**
* Manager class for render operation, mainly for managing {@link RenderContextImpl}.
* This is <strong>not</strong> a thread-safe class
Expand Down Expand Up @@ -81,6 +93,51 @@ public WXSDKInstance getWXSDKInstance(String instanceId) {
return statement.getWXSDKInstance();
}

public static int getOpenGLRenderLimitValue() {
int maxsize ;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
EGL10 egl = (EGL10) EGLContext.getEGL();
YorkShen marked this conversation as resolved.
Show resolved Hide resolved
EGLDisplay dpy = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
int[] vers = new int[2];
egl.eglInitialize(dpy, vers);
int[] configAttr = {
EGL10.EGL_COLOR_BUFFER_TYPE, EGL10.EGL_RGB_BUFFER,
EGL10.EGL_LEVEL,0,
EGL10.EGL_SURFACE_TYPE, EGL10.EGL_PBUFFER_BIT,
EGL10.EGL_NONE};
EGLConfig[] configs =new EGLConfig[1];
int[] numConfig =new int[1];
egl.eglChooseConfig(dpy, configAttr, configs,1, numConfig);
if (numConfig[0] ==0) {// TROUBLE! No config found.
YorkShen marked this conversation as resolved.
Show resolved Hide resolved
}
EGLConfig config = configs[0];
int[] surfAttr = {
EGL10.EGL_WIDTH,64,
EGL10.EGL_HEIGHT,64,
EGL10.EGL_NONE};
EGLSurface surf = egl.eglCreatePbufferSurface(dpy, config, surfAttr);
final int EGL_CONTEXT_CLIENT_VERSION =0x3098;// missing in EGL10
int[] ctxAttrib = {
EGL_CONTEXT_CLIENT_VERSION,1,
EGL10.EGL_NONE};
EGLContext ctx = egl.eglCreateContext(dpy, config, EGL10.EGL_NO_CONTEXT, ctxAttrib);
egl.eglMakeCurrent(dpy, surf, surf, ctx);
int[] maxSize =new int[1];
GLES10.glGetIntegerv(GLES10.GL_MAX_TEXTURE_SIZE, maxSize,0);
egl.eglMakeCurrent(dpy, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE,
EGL10.EGL_NO_CONTEXT);
egl.eglDestroySurface(dpy, surf);
egl.eglDestroyContext(dpy, ctx);
egl.eglTerminate(dpy);
maxsize = maxSize[0];
}else {
int[] maxSize =new int[1];
GLES10.glGetIntegerv(GLES10.GL_MAX_TEXTURE_SIZE, maxSize,0);
maxsize = maxSize[0];
}
return maxsize == 0 ? 4096 : maxsize;
YorkShen marked this conversation as resolved.
Show resolved Hide resolved
}

@RestrictTo(Scope.LIBRARY)
public void postOnUiThread(Runnable runnable, long delayMillis) {
mWXRenderHandler.postDelayed(WXThread.secure(runnable), delayMillis);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
import com.taobao.weex.WXSDKInstance;
import com.taobao.weex.WXSDKManager;
import com.taobao.weex.adapter.IWXAccessibilityRoleAdapter;
import com.taobao.weex.adapter.IWXConfigAdapter;
import com.taobao.weex.bridge.EventResult;
import com.taobao.weex.bridge.Invoker;
import com.taobao.weex.bridge.WXBridgeManager;
Expand All @@ -78,6 +79,7 @@
import com.taobao.weex.tracing.Stopwatch;
import com.taobao.weex.tracing.WXTracing;
import com.taobao.weex.ui.IFComponentHolder;
import com.taobao.weex.ui.WXRenderManager;
import com.taobao.weex.ui.action.BasicComponentData;
import com.taobao.weex.ui.action.GraphicActionAnimation;
import com.taobao.weex.ui.action.GraphicActionUpdateStyle;
Expand Down Expand Up @@ -1682,12 +1684,29 @@ public void setBackgroundImage(@NonNull String bgImage) {
getOrCreateBorder().setImage(shader);
}
}
public boolean shouldCancelHardwareAccelerate() {
YorkShen marked this conversation as resolved.
Show resolved Hide resolved
IWXConfigAdapter adapter = WXSDKManager.getInstance().getWxConfigAdapter();
boolean cancel_hardware_accelerate = false;
if (adapter != null) {
cancel_hardware_accelerate = Boolean.parseBoolean(adapter
YorkShen marked this conversation as resolved.
Show resolved Hide resolved
.getConfig("android_weex_test_gpu",
"cancel_hardware_accelerate",
"false"));
WXLogUtils.e("cancel_hardware_accelerate : " + cancel_hardware_accelerate);
YorkShen marked this conversation as resolved.
Show resolved Hide resolved
}
return cancel_hardware_accelerate;
}

public void setOpacity(float opacity) {
if (opacity >= 0 && opacity <= 1 && mHost.getAlpha() != opacity) {
int limit = WXRenderManager.getOpenGLRenderLimitValue();
if (isLayerTypeEnabled()) {
mHost.setLayerType(View.LAYER_TYPE_HARDWARE, null);
}
if(shouldCancelHardwareAccelerate() && (getLayoutHeight() > limit ||
getLayoutWidth() > limit)){
mHost.setLayerType(View.LAYER_TYPE_SOFTWARE,null);
YorkShen marked this conversation as resolved.
Show resolved Hide resolved
}
mHost.setAlpha(opacity);
}
}
Expand Down