save code

This commit is contained in:
xsl
2026-04-26 00:12:56 +08:00
parent 50680ee854
commit c5ec7c7dc5
22 changed files with 1170 additions and 216 deletions
+58 -19
View File
@@ -191,19 +191,35 @@ void android_main(struct android_app *pApp) {
}
} while (!pApp->destroyRequested);
DebugLog::log("android_main: destroyRequested, running cleanup");
//application.cleanup();
g_Application->cleanupSecondInit();
// 关键:这里只复位 FaceApp 的"second-init" 状态机标记,**不销毁**任何
// Vulkan 资源。
//
// - 窗口相关资源(surface/swapchain/framebuffers/imageViews/
// commandBuffers/sync)已经在 APP_CMD_TERM_WINDOW → onWindowLost()
// 里被 cleanupForWindowLost() 干净销毁;
// - renderPass / graphicsPipeline / pipelineLayout / VkDevice /
// VkInstance / VMA / 所有 textures / FaceApp 自身 pipelines 是 g_Application
// 单例的"全局资源",跨 NativeActivity 实例复用。下次 Activity 启动
// onWindowInit 会走 reinitForNewWindow() 重建窗口资源、复用全局资源。
//
// 历史教训:之前这里调过 g_Application->cleanupSecondInit(),那个函数会
// 把 renderPass / graphicsPipeline / pipelineLayout 全部 destroy 掉但既
// 不置 VK_NULL_HANDLE 也不复位 _applicationInited。结果用户从主界面切镜
// 头再进 MakeupActivity 时,onWindowInit 看到 _applicationInited=1 走 reinit
// 复用路径,引用悬空的 renderPass 调 vkCreateFramebuffervalidation
// layer 检测出 use-after-free 直接 SEGV。
g_Application->clearnSecondFaceApp();
DebugLog::log("android_main: exit");
}
}
extern void TextureLoadProcessWithVulkan(uint8_t* data, int width, int height, int rowStride, size_t dataSize);
extern void TextureLoadProcessWithVulkan(uint8_t* data, int width, int height, int rowStride, size_t dataSize, int rotation, bool mirrorX);
extern void ReceiveFacePoint(float* pos, int count, int width, int height);
void processWithVulkan(uint8_t* data, int width, int height, int format,
int rowStride, size_t dataSize) {
TextureLoadProcessWithVulkan(data, width, height, rowStride, dataSize);
int rowStride, size_t dataSize, int rotation, bool mirrorX) {
TextureLoadProcessWithVulkan(data, width, height, rowStride, dataSize, rotation, mirrorX);
}
@@ -213,14 +229,13 @@ JNIEXPORT void JNICALL
Java_com_hmwl_face_1sdk_FaceActivity_processImageNative(JNIEnv *env, jobject thiz, jobject buffer,
jint width, jint height, jint format,
jint row_stride, jint pixel_stride,
jint rotation) {
jint rotation, jboolean mirror_x) {
static std::atomic<uint64_t> s_imgCount{0};
uint64_t n = s_imgCount.fetch_add(1) + 1;
if (n == 1 || n % 300 == 0) {
DebugLog::log("processImageNative #%llu tid=%d w=%d h=%d",
(unsigned long long)n, dbg_tid(), width, height);
DebugLog::log("processImageNative #%llu tid=%d w=%d h=%d mirror=%d",
(unsigned long long)n, dbg_tid(), width, height, (int)mirror_x);
}
// TODO: implement processImageNative()
uint8_t* imageData = static_cast<uint8_t*>(env->GetDirectBufferAddress(buffer));
jlong capacity = env->GetDirectBufferCapacity(buffer);
@@ -228,9 +243,12 @@ Java_com_hmwl_face_1sdk_FaceActivity_processImageNative(JNIEnv *env, jobject thi
return;
}
// 在这里将图像数据传递给 Vulkan
// 创建 Vulkan 图像或更新现有图像
processWithVulkan(imageData, width, height, format, row_stride, capacity);
// rotation = ImageInfo.getRotationDegrees(),给 shader 用来做 UV 旋转,
// 让不同 sensor orientation 的设备显示方向一致。
// mirror_x = true 表示前置摄像头:所有顶点 shader 会把 gl_Position.x 翻转
// 一次,达到"镜子效果"——这是化妆/美妆类 app 的标准体验。
processWithVulkan(imageData, width, height, format, row_stride, capacity,
(int)rotation, mirror_x == JNI_TRUE);
}
extern "C"
JNIEXPORT void JNICALL
@@ -238,19 +256,21 @@ Java_com_hmwl_face_1sdk_FaceActivity_passDataToNative(JNIEnv *env, jobject thiz,
jint point_count, jint width, jint height) {
static std::atomic<uint64_t> s_ptCount{0};
uint64_t n = s_ptCount.fetch_add(1) + 1;
if (n == 1 || n % 300 == 0) {
DebugLog::log("passDataToNative #%llu tid=%d point_count=%d w=%d h=%d",
(unsigned long long)n, dbg_tid(), point_count, width, height);
}
// TODO: implement passDataToNative()
float* pos = static_cast<float*>(env->GetDirectBufferAddress(buffer));
if (pos == nullptr) {
// 处理错误
DebugLog::log_throttled("passDataToNative.nullBuffer",
"passDataToNative #%llu got NULL DirectBufferAddress!",
(unsigned long long)n);
return;
}
// 节流:每 120 次实际数据通路打一行(约每 4 秒一次,足够确认通路活着即可)。
if (n == 1 || n % 120 == 0) {
DebugLog::log("passDataToNative #%llu point_count=%d w=%d h=%d p0=(%.3f,%.3f,%.3f)",
(unsigned long long)n, point_count, width, height,
pos[0], pos[1], pos[2]);
}
// 或者直接将指针传递给Vulkan
ReceiveFacePoint(pos, point_count, width, height);
}
@@ -491,4 +511,23 @@ JNIEXPORT void JNICALL
Java_com_hmwl_face_1sdk_FaceActivity_ResumeMotionNative(JNIEnv *env, jobject thiz) {
DebugLog::log("JNI ResumeMotionNative tid=%d", dbg_tid());
g_Application->ResumeMotion();
}
// 给 Java/Kotlin 侧用的日志桥:把 Java 端关键事件写进 native 的
// face_sdk_debug.log,使 Java + native + Vulkan 渲染日志能在同一个
// 文件里按时间戳排好序,一次 adb pull 就能拿到完整时间线。
extern "C"
JNIEXPORT void JNICALL
Java_com_hmwl_face_1sdk_DebugLog_nativeLog(JNIEnv *env, jclass clazz,
jstring jtag, jstring jmsg) {
if (jmsg == nullptr) return;
const char* tag = jtag ? env->GetStringUTFChars(jtag, nullptr) : nullptr;
const char* msg = env->GetStringUTFChars(jmsg, nullptr);
if (tag) {
DebugLog::log("[J][%s] %s", tag, msg);
} else {
DebugLog::log("[J] %s", msg);
}
if (tag) env->ReleaseStringUTFChars(jtag, tag);
env->ReleaseStringUTFChars(jmsg, msg);
}