VavCore Android implementation
This commit is contained in:
@@ -0,0 +1,265 @@
|
||||
#include "TestFramework.h"
|
||||
#include "Decoder/AndroidMediaCodecAV1Decoder.h"
|
||||
#include "Common/VideoTypes.h"
|
||||
#include <GLES3/gl3.h>
|
||||
#include <GLES2/gl2ext.h>
|
||||
#include <memory>
|
||||
|
||||
namespace VavCoreTest {
|
||||
|
||||
bool TestOpenGLESTextureCreation(std::string& error_msg) {
|
||||
LOGI("Testing OpenGL ES texture creation...");
|
||||
|
||||
// Verify OpenGL ES context is available
|
||||
const char* gl_version = reinterpret_cast<const char*>(glGetString(GL_VERSION));
|
||||
TEST_ASSERT_NOT_NULL(gl_version, "OpenGL ES context not available");
|
||||
|
||||
LOGI("OpenGL ES Version: %s", gl_version);
|
||||
|
||||
// Test basic texture creation
|
||||
GLuint texture_id = 0;
|
||||
glGenTextures(1, &texture_id);
|
||||
TEST_ASSERT_NE(0, texture_id, "Failed to generate OpenGL ES texture");
|
||||
|
||||
LOGI("Generated texture ID: %u", texture_id);
|
||||
|
||||
// Test GL_TEXTURE_EXTERNAL_OES binding
|
||||
glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture_id);
|
||||
GLenum error = glGetError();
|
||||
TEST_ASSERT_EQ(GL_NO_ERROR, error, "Failed to bind GL_TEXTURE_EXTERNAL_OES texture");
|
||||
|
||||
// Configure texture parameters
|
||||
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
error = glGetError();
|
||||
TEST_ASSERT_EQ(GL_NO_ERROR, error, "Failed to set texture parameters");
|
||||
|
||||
// Clean up
|
||||
glDeleteTextures(1, &texture_id);
|
||||
|
||||
LOGI("✅ OpenGL ES texture creation test passed");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestAndroidMediaCodecOpenGLESSetup(std::string& error_msg) {
|
||||
LOGI("Testing AndroidMediaCodecAV1Decoder OpenGL ES setup...");
|
||||
|
||||
// Create decoder instance
|
||||
auto decoder = std::make_unique<VavCore::AndroidMediaCodecAV1Decoder>();
|
||||
TEST_ASSERT_NOT_NULL(decoder.get(), "Failed to create AndroidMediaCodecAV1Decoder");
|
||||
|
||||
// Test video metadata (example AV1 stream)
|
||||
VavCore::VideoMetadata metadata;
|
||||
metadata.codec_type = VavCore::VideoCodecType::AV1;
|
||||
metadata.width = 1920;
|
||||
metadata.height = 1080;
|
||||
metadata.frame_rate = 30.0;
|
||||
|
||||
// Initialize decoder
|
||||
bool init_result = decoder->Initialize(metadata);
|
||||
if (!init_result) {
|
||||
LOGW("Decoder initialization failed - likely no hardware AV1 support");
|
||||
// This is not necessarily a test failure - many devices don't support AV1 hardware
|
||||
LOGI("⚠️ AndroidMediaCodec OpenGL ES setup test skipped (no AV1 hardware support)");
|
||||
return true;
|
||||
}
|
||||
|
||||
LOGI("Decoder initialized successfully");
|
||||
|
||||
// Test hardware acceleration check
|
||||
bool is_hw_accelerated = decoder->IsHardwareAccelerated();
|
||||
LOGI("Hardware acceleration: %s", is_hw_accelerated ? "YES" : "NO");
|
||||
|
||||
if (!is_hw_accelerated) {
|
||||
LOGW("No hardware acceleration available - OpenGL ES texture output not supported");
|
||||
LOGI("⚠️ AndroidMediaCodec OpenGL ES setup test skipped (no hardware acceleration)");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Test OpenGL ES context setup
|
||||
void* egl_context = TestFramework::GetEGLContext();
|
||||
TEST_ASSERT_NOT_NULL(egl_context, "EGL context not available");
|
||||
|
||||
bool context_result = decoder->SetOpenGLESContext(egl_context);
|
||||
TEST_ASSERT(context_result, "Failed to set OpenGL ES context");
|
||||
|
||||
LOGI("OpenGL ES context set successfully");
|
||||
|
||||
// Test OpenGL ES texture creation through decoder
|
||||
uint32_t texture_id = 0;
|
||||
bool texture_result = decoder->CreateOpenGLESTexture(&texture_id);
|
||||
TEST_ASSERT(texture_result, "Failed to create OpenGL ES texture through decoder");
|
||||
TEST_ASSERT_NE(0, texture_id, "Invalid texture ID returned");
|
||||
|
||||
LOGI("OpenGL ES texture created through decoder: %u", texture_id);
|
||||
|
||||
// Test SurfaceTexture setup
|
||||
bool surface_result = decoder->SetupSurfaceTexture(texture_id);
|
||||
TEST_ASSERT(surface_result, "Failed to setup SurfaceTexture");
|
||||
|
||||
LOGI("SurfaceTexture setup completed successfully");
|
||||
|
||||
// Test optimal surface type for OpenGL ES
|
||||
VavCoreSurfaceType optimal_type = decoder->GetOptimalSurfaceType();
|
||||
LOGI("Optimal surface type: %d", static_cast<int>(optimal_type));
|
||||
|
||||
// Verify OpenGL ES texture is supported
|
||||
bool supports_gles = decoder->SupportsSurfaceType(VAVCORE_SURFACE_OPENGL_ES_TEXTURE);
|
||||
TEST_ASSERT(supports_gles, "OpenGL ES texture surface not supported");
|
||||
|
||||
LOGI("OpenGL ES texture surface is supported");
|
||||
|
||||
// Test Godot integration info
|
||||
std::string godot_info = decoder->GetGodotIntegrationInfo();
|
||||
LOGI("Godot integration info: %s", godot_info.c_str());
|
||||
|
||||
bool is_optimal_for_godot = decoder->IsOptimalForGodot();
|
||||
LOGI("Optimal for Godot: %s", is_optimal_for_godot ? "YES" : "NO");
|
||||
|
||||
// Clean up
|
||||
decoder->Cleanup();
|
||||
|
||||
LOGI("✅ AndroidMediaCodec OpenGL ES setup test passed");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestOpenGLESTextureUpdate(std::string& error_msg) {
|
||||
LOGI("Testing OpenGL ES texture update mechanism...");
|
||||
|
||||
// Create decoder instance
|
||||
auto decoder = std::make_unique<VavCore::AndroidMediaCodecAV1Decoder>();
|
||||
TEST_ASSERT_NOT_NULL(decoder.get(), "Failed to create AndroidMediaCodecAV1Decoder");
|
||||
|
||||
// Test video metadata
|
||||
VavCore::VideoMetadata metadata;
|
||||
metadata.codec_type = VavCore::VideoCodecType::AV1;
|
||||
metadata.width = 854; // Smaller resolution for testing
|
||||
metadata.height = 480;
|
||||
metadata.frame_rate = 30.0;
|
||||
|
||||
// Initialize decoder
|
||||
bool init_result = decoder->Initialize(metadata);
|
||||
if (!init_result) {
|
||||
LOGW("Decoder initialization failed - skipping texture update test");
|
||||
LOGI("⚠️ OpenGL ES texture update test skipped (no AV1 hardware support)");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check hardware acceleration
|
||||
if (!decoder->IsHardwareAccelerated()) {
|
||||
LOGW("No hardware acceleration - skipping texture update test");
|
||||
LOGI("⚠️ OpenGL ES texture update test skipped (no hardware acceleration)");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Set OpenGL ES context
|
||||
void* egl_context = TestFramework::GetEGLContext();
|
||||
bool context_result = decoder->SetOpenGLESContext(egl_context);
|
||||
TEST_ASSERT(context_result, "Failed to set OpenGL ES context");
|
||||
|
||||
// Create texture
|
||||
uint32_t texture_id = 0;
|
||||
bool texture_result = decoder->CreateOpenGLESTexture(&texture_id);
|
||||
TEST_ASSERT(texture_result, "Failed to create OpenGL ES texture");
|
||||
|
||||
// Setup SurfaceTexture
|
||||
bool surface_result = decoder->SetupSurfaceTexture(texture_id);
|
||||
TEST_ASSERT(surface_result, "Failed to setup SurfaceTexture");
|
||||
|
||||
// Test texture update mechanism
|
||||
bool update_result = decoder->UpdateSurfaceTexture();
|
||||
// Note: This might fail if no frame has been decoded yet, which is expected
|
||||
if (!update_result) {
|
||||
LOGW("SurfaceTexture update failed - this is expected without decoded frames");
|
||||
} else {
|
||||
LOGI("SurfaceTexture update succeeded");
|
||||
}
|
||||
|
||||
LOGI("✅ OpenGL ES texture update test completed");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestOpenGLESDecodeToSurface(std::string& error_msg) {
|
||||
LOGI("Testing OpenGL ES decode to surface...");
|
||||
|
||||
// Create decoder instance
|
||||
auto decoder = std::make_unique<VavCore::AndroidMediaCodecAV1Decoder>();
|
||||
TEST_ASSERT_NOT_NULL(decoder.get(), "Failed to create AndroidMediaCodecAV1Decoder");
|
||||
|
||||
// Test video metadata
|
||||
VavCore::VideoMetadata metadata;
|
||||
metadata.codec_type = VavCore::VideoCodecType::AV1;
|
||||
metadata.width = 640;
|
||||
metadata.height = 360;
|
||||
metadata.frame_rate = 30.0;
|
||||
|
||||
// Initialize decoder
|
||||
bool init_result = decoder->Initialize(metadata);
|
||||
if (!init_result) {
|
||||
LOGW("Decoder initialization failed - skipping decode to surface test");
|
||||
LOGI("⚠️ OpenGL ES decode to surface test skipped (no AV1 hardware support)");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check hardware acceleration
|
||||
if (!decoder->IsHardwareAccelerated()) {
|
||||
LOGW("No hardware acceleration - skipping decode to surface test");
|
||||
LOGI("⚠️ OpenGL ES decode to surface test skipped (no hardware acceleration)");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Set OpenGL ES context
|
||||
void* egl_context = TestFramework::GetEGLContext();
|
||||
bool context_result = decoder->SetOpenGLESContext(egl_context);
|
||||
TEST_ASSERT(context_result, "Failed to set OpenGL ES context");
|
||||
|
||||
// Create texture
|
||||
uint32_t texture_id = 0;
|
||||
bool texture_result = decoder->CreateOpenGLESTexture(&texture_id);
|
||||
TEST_ASSERT(texture_result, "Failed to create OpenGL ES texture");
|
||||
|
||||
// Setup SurfaceTexture
|
||||
bool surface_result = decoder->SetupSurfaceTexture(texture_id);
|
||||
TEST_ASSERT(surface_result, "Failed to setup SurfaceTexture");
|
||||
|
||||
// Test DecodeToSurface with dummy data
|
||||
uint8_t dummy_packet[] = { 0x12, 0x00, 0x0A, 0x0A, 0x00, 0x00, 0x00, 0x01 }; // Minimal AV1 OBU
|
||||
size_t packet_size = sizeof(dummy_packet);
|
||||
|
||||
VavCore::VideoFrame output_frame;
|
||||
bool decode_result = decoder->DecodeToSurface(
|
||||
dummy_packet, packet_size,
|
||||
VAVCORE_SURFACE_OPENGL_ES_TEXTURE,
|
||||
static_cast<void*>(&texture_id),
|
||||
output_frame
|
||||
);
|
||||
|
||||
// Note: This will likely fail with real dummy data, but we're testing the API flow
|
||||
if (!decode_result) {
|
||||
LOGW("DecodeToSurface failed with dummy data - this is expected");
|
||||
} else {
|
||||
LOGI("DecodeToSurface succeeded with dummy data");
|
||||
|
||||
// Verify frame metadata
|
||||
TEST_ASSERT_EQ(640, output_frame.width, "Incorrect frame width");
|
||||
TEST_ASSERT_EQ(360, output_frame.height, "Incorrect frame height");
|
||||
|
||||
LOGI("Frame metadata: %dx%d", output_frame.width, output_frame.height);
|
||||
}
|
||||
|
||||
LOGI("✅ OpenGL ES decode to surface test completed");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Test registration function
|
||||
void RegisterOpenGLESTextureTests(TestFramework& framework) {
|
||||
framework.RegisterTest("OpenGLES_TextureCreation", TestOpenGLESTextureCreation);
|
||||
framework.RegisterTest("OpenGLES_MediaCodecSetup", TestAndroidMediaCodecOpenGLESSetup);
|
||||
framework.RegisterTest("OpenGLES_TextureUpdate", TestOpenGLESTextureUpdate);
|
||||
framework.RegisterTest("OpenGLES_DecodeToSurface", TestOpenGLESDecodeToSurface);
|
||||
}
|
||||
|
||||
} // namespace VavCoreTest
|
||||
@@ -0,0 +1,275 @@
|
||||
#include "TestFramework.h"
|
||||
#include <chrono>
|
||||
#include <EGL/egl.h>
|
||||
#include <GLES3/gl3.h>
|
||||
|
||||
namespace VavCoreTest {
|
||||
|
||||
// Static EGL context variables
|
||||
void* TestFramework::s_egl_display = nullptr;
|
||||
void* TestFramework::s_egl_context = nullptr;
|
||||
void* TestFramework::s_egl_surface = nullptr;
|
||||
|
||||
TestFramework::TestFramework() {
|
||||
LOGI("VavCore Texture Binding Test Framework initialized");
|
||||
}
|
||||
|
||||
TestFramework::~TestFramework() {
|
||||
CleanupEGL();
|
||||
LOGI("VavCore Texture Binding Test Framework destroyed");
|
||||
}
|
||||
|
||||
void TestFramework::RegisterTest(const std::string& name, TestFunction test_func) {
|
||||
TestCase test_case = { name, test_func };
|
||||
m_test_cases.push_back(test_case);
|
||||
LOGI("Registered test: %s", name.c_str());
|
||||
}
|
||||
|
||||
bool TestFramework::RunAllTests() {
|
||||
LOGI("=== Starting VavCore Texture Binding Tests ===");
|
||||
|
||||
// Initialize EGL context for OpenGL ES tests
|
||||
if (!InitializeEGL()) {
|
||||
LOGE("Failed to initialize EGL context");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool all_passed = true;
|
||||
m_results.clear();
|
||||
|
||||
for (const auto& test_case : m_test_cases) {
|
||||
LOGI("Running test: %s", test_case.name.c_str());
|
||||
|
||||
auto start_time = std::chrono::high_resolution_clock::now();
|
||||
|
||||
std::string error_message;
|
||||
bool passed = false;
|
||||
|
||||
try {
|
||||
passed = test_case.function(error_message);
|
||||
} catch (const std::exception& e) {
|
||||
passed = false;
|
||||
error_message = std::string("Exception: ") + e.what();
|
||||
} catch (...) {
|
||||
passed = false;
|
||||
error_message = "Unknown exception occurred";
|
||||
}
|
||||
|
||||
auto end_time = std::chrono::high_resolution_clock::now();
|
||||
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time);
|
||||
double execution_time_ms = duration.count() / 1000.0;
|
||||
|
||||
TestResult result;
|
||||
result.test_name = test_case.name;
|
||||
result.passed = passed;
|
||||
result.error_message = error_message;
|
||||
result.execution_time_ms = execution_time_ms;
|
||||
|
||||
m_results.push_back(result);
|
||||
|
||||
if (passed) {
|
||||
LOGI("✅ Test passed: %s (%.2f ms)", test_case.name.c_str(), execution_time_ms);
|
||||
} else {
|
||||
LOGE("❌ Test failed: %s - %s (%.2f ms)",
|
||||
test_case.name.c_str(), error_message.c_str(), execution_time_ms);
|
||||
all_passed = false;
|
||||
}
|
||||
}
|
||||
|
||||
CleanupEGL();
|
||||
|
||||
LOGI("=== Test Results Summary ===");
|
||||
PrintSummary();
|
||||
|
||||
return all_passed;
|
||||
}
|
||||
|
||||
bool TestFramework::RunTest(const std::string& test_name) {
|
||||
for (const auto& test_case : m_test_cases) {
|
||||
if (test_case.name == test_name) {
|
||||
LOGI("Running single test: %s", test_name.c_str());
|
||||
|
||||
if (!InitializeEGL()) {
|
||||
LOGE("Failed to initialize EGL context for test: %s", test_name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string error_message;
|
||||
bool passed = test_case.function(error_message);
|
||||
|
||||
CleanupEGL();
|
||||
|
||||
if (passed) {
|
||||
LOGI("✅ Test passed: %s", test_name.c_str());
|
||||
} else {
|
||||
LOGE("❌ Test failed: %s - %s", test_name.c_str(), error_message.c_str());
|
||||
}
|
||||
|
||||
return passed;
|
||||
}
|
||||
}
|
||||
|
||||
LOGE("Test not found: %s", test_name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
void TestFramework::PrintSummary() const {
|
||||
int total_tests = static_cast<int>(m_results.size());
|
||||
int passed_tests = 0;
|
||||
double total_time = 0.0;
|
||||
|
||||
for (const auto& result : m_results) {
|
||||
if (result.passed) {
|
||||
passed_tests++;
|
||||
}
|
||||
total_time += result.execution_time_ms;
|
||||
}
|
||||
|
||||
int failed_tests = total_tests - passed_tests;
|
||||
|
||||
LOGI("Total tests: %d", total_tests);
|
||||
LOGI("Passed: %d", passed_tests);
|
||||
LOGI("Failed: %d", failed_tests);
|
||||
LOGI("Total execution time: %.2f ms", total_time);
|
||||
LOGI("Success rate: %.1f%%",
|
||||
total_tests > 0 ? (static_cast<double>(passed_tests) / total_tests * 100.0) : 0.0);
|
||||
|
||||
if (failed_tests > 0) {
|
||||
LOGI("Failed tests:");
|
||||
for (const auto& result : m_results) {
|
||||
if (!result.passed) {
|
||||
LOGI(" - %s: %s", result.test_name.c_str(), result.error_message.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool TestFramework::InitializeEGL() {
|
||||
LOGI("Initializing EGL context for OpenGL ES tests");
|
||||
|
||||
// Get EGL display
|
||||
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
if (display == EGL_NO_DISPLAY) {
|
||||
LOGE("Failed to get EGL display");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize EGL
|
||||
EGLint major, minor;
|
||||
if (!eglInitialize(display, &major, &minor)) {
|
||||
LOGE("Failed to initialize EGL");
|
||||
return false;
|
||||
}
|
||||
|
||||
LOGI("EGL version: %d.%d", major, minor);
|
||||
|
||||
// Configure EGL
|
||||
EGLint config_attribs[] = {
|
||||
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
|
||||
EGL_RED_SIZE, 8,
|
||||
EGL_GREEN_SIZE, 8,
|
||||
EGL_BLUE_SIZE, 8,
|
||||
EGL_ALPHA_SIZE, 8,
|
||||
EGL_DEPTH_SIZE, 16,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
EGLConfig config;
|
||||
EGLint num_configs;
|
||||
if (!eglChooseConfig(display, config_attribs, &config, 1, &num_configs)) {
|
||||
LOGE("Failed to choose EGL config");
|
||||
eglTerminate(display);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create EGL context
|
||||
EGLint context_attribs[] = {
|
||||
EGL_CONTEXT_CLIENT_VERSION, 3,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
EGLContext context = eglCreateContext(display, config, EGL_NO_CONTEXT, context_attribs);
|
||||
if (context == EGL_NO_CONTEXT) {
|
||||
LOGE("Failed to create EGL context");
|
||||
eglTerminate(display);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a minimal pbuffer surface for testing
|
||||
EGLint surface_attribs[] = {
|
||||
EGL_WIDTH, 1,
|
||||
EGL_HEIGHT, 1,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
EGLSurface surface = eglCreatePbufferSurface(display, config, surface_attribs);
|
||||
if (surface == EGL_NO_SURFACE) {
|
||||
LOGE("Failed to create EGL surface");
|
||||
eglDestroyContext(display, context);
|
||||
eglTerminate(display);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make context current
|
||||
if (!eglMakeCurrent(display, surface, surface, context)) {
|
||||
LOGE("Failed to make EGL context current");
|
||||
eglDestroySurface(display, surface);
|
||||
eglDestroyContext(display, context);
|
||||
eglTerminate(display);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Store EGL objects
|
||||
s_egl_display = static_cast<void*>(display);
|
||||
s_egl_context = static_cast<void*>(context);
|
||||
s_egl_surface = static_cast<void*>(surface);
|
||||
|
||||
// Verify OpenGL ES context
|
||||
const char* gl_version = reinterpret_cast<const char*>(glGetString(GL_VERSION));
|
||||
const char* gl_vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
|
||||
const char* gl_renderer = reinterpret_cast<const char*>(glGetString(GL_RENDERER));
|
||||
|
||||
LOGI("OpenGL ES Version: %s", gl_version ? gl_version : "unknown");
|
||||
LOGI("OpenGL ES Vendor: %s", gl_vendor ? gl_vendor : "unknown");
|
||||
LOGI("OpenGL ES Renderer: %s", gl_renderer ? gl_renderer : "unknown");
|
||||
|
||||
LOGI("EGL context initialized successfully");
|
||||
return true;
|
||||
}
|
||||
|
||||
void TestFramework::CleanupEGL() {
|
||||
if (s_egl_display) {
|
||||
EGLDisplay display = static_cast<EGLDisplay>(s_egl_display);
|
||||
EGLContext context = static_cast<EGLContext>(s_egl_context);
|
||||
EGLSurface surface = static_cast<EGLSurface>(s_egl_surface);
|
||||
|
||||
eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
|
||||
if (surface != EGL_NO_SURFACE) {
|
||||
eglDestroySurface(display, surface);
|
||||
}
|
||||
|
||||
if (context != EGL_NO_CONTEXT) {
|
||||
eglDestroyContext(display, context);
|
||||
}
|
||||
|
||||
eglTerminate(display);
|
||||
|
||||
s_egl_display = nullptr;
|
||||
s_egl_context = nullptr;
|
||||
s_egl_surface = nullptr;
|
||||
|
||||
LOGI("EGL context cleaned up");
|
||||
}
|
||||
}
|
||||
|
||||
bool TestFramework::CreateEGLContext() {
|
||||
return InitializeEGL();
|
||||
}
|
||||
|
||||
void TestFramework::DestroyEGLContext() {
|
||||
CleanupEGL();
|
||||
}
|
||||
|
||||
} // namespace VavCoreTest
|
||||
@@ -0,0 +1,109 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <android/log.h>
|
||||
|
||||
// Logging macros
|
||||
#define LOG_TAG "VavCoreTextureTest"
|
||||
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
|
||||
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
|
||||
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
|
||||
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
|
||||
|
||||
namespace VavCoreTest {
|
||||
|
||||
// Test result structure
|
||||
struct TestResult {
|
||||
std::string test_name;
|
||||
bool passed;
|
||||
std::string error_message;
|
||||
double execution_time_ms;
|
||||
};
|
||||
|
||||
// Test case function type
|
||||
using TestFunction = std::function<bool(std::string&)>;
|
||||
|
||||
// Test framework class
|
||||
class TestFramework {
|
||||
public:
|
||||
TestFramework();
|
||||
~TestFramework();
|
||||
|
||||
// Test registration
|
||||
void RegisterTest(const std::string& name, TestFunction test_func);
|
||||
|
||||
// Test execution
|
||||
bool RunAllTests();
|
||||
bool RunTest(const std::string& test_name);
|
||||
|
||||
// Results
|
||||
std::vector<TestResult> GetResults() const { return m_results; }
|
||||
void PrintSummary() const;
|
||||
|
||||
// Utility methods
|
||||
static bool InitializeEGL();
|
||||
static void CleanupEGL();
|
||||
static bool CreateEGLContext();
|
||||
static void DestroyEGLContext();
|
||||
|
||||
// Context access for tests
|
||||
static void* GetEGLContext() { return s_egl_context; }
|
||||
|
||||
private:
|
||||
struct TestCase {
|
||||
std::string name;
|
||||
TestFunction function;
|
||||
};
|
||||
|
||||
std::vector<TestCase> m_test_cases;
|
||||
std::vector<TestResult> m_results;
|
||||
|
||||
// EGL context management
|
||||
static void* s_egl_display;
|
||||
static void* s_egl_context;
|
||||
static void* s_egl_surface;
|
||||
};
|
||||
|
||||
// Test macros
|
||||
#define TEST_ASSERT(condition, message) \
|
||||
do { \
|
||||
if (!(condition)) { \
|
||||
error_msg = std::string("Assertion failed: ") + (message); \
|
||||
LOGE("%s", error_msg.c_str()); \
|
||||
return false; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define TEST_ASSERT_EQ(expected, actual, message) \
|
||||
do { \
|
||||
if ((expected) != (actual)) { \
|
||||
error_msg = std::string("Assertion failed: ") + (message) + \
|
||||
" (expected: " + std::to_string(expected) + \
|
||||
", actual: " + std::to_string(actual) + ")"; \
|
||||
LOGE("%s", error_msg.c_str()); \
|
||||
return false; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define TEST_ASSERT_NE(not_expected, actual, message) \
|
||||
do { \
|
||||
if ((not_expected) == (actual)) { \
|
||||
error_msg = std::string("Assertion failed: ") + (message) + \
|
||||
" (should not be: " + std::to_string(not_expected) + ")"; \
|
||||
LOGE("%s", error_msg.c_str()); \
|
||||
return false; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define TEST_ASSERT_NOT_NULL(ptr, message) \
|
||||
do { \
|
||||
if ((ptr) == nullptr) { \
|
||||
error_msg = std::string("Assertion failed: ") + (message) + " (pointer is null)"; \
|
||||
LOGE("%s", error_msg.c_str()); \
|
||||
return false; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
} // namespace VavCoreTest
|
||||
@@ -0,0 +1,317 @@
|
||||
#include "TestFramework.h"
|
||||
#include "Decoder/AndroidMediaCodecAV1Decoder.h"
|
||||
#include "Common/VideoTypes.h"
|
||||
#include <android/hardware_buffer.h>
|
||||
#include <sys/system_properties.h>
|
||||
#include <memory>
|
||||
|
||||
#ifndef PROP_VALUE_MAX
|
||||
#define PROP_VALUE_MAX 92
|
||||
#endif
|
||||
|
||||
namespace VavCoreTest {
|
||||
|
||||
bool TestVulkanAvailability(std::string& error_msg) {
|
||||
LOGI("Testing Vulkan availability...");
|
||||
|
||||
// Test Android API level requirement
|
||||
char sdk_version[PROP_VALUE_MAX] = {};
|
||||
int api_level = 29; // Default
|
||||
|
||||
if (__system_property_get("ro.build.version.sdk", sdk_version) > 0) {
|
||||
api_level = std::atoi(sdk_version);
|
||||
}
|
||||
|
||||
LOGI("Android API Level: %d", api_level);
|
||||
|
||||
if (api_level < 29) {
|
||||
LOGW("Android API %d < 29, Vulkan AHardwareBuffer integration not fully supported", api_level);
|
||||
LOGI("⚠️ Vulkan availability test skipped (API level too low)");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Test AHardwareBuffer availability (API 26+)
|
||||
if (api_level < 26) {
|
||||
LOGW("Android API %d < 26, AHardwareBuffer not available", api_level);
|
||||
error_msg = "AHardwareBuffer requires API 26+";
|
||||
return false;
|
||||
}
|
||||
|
||||
LOGI("✅ Vulkan availability requirements met");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestAHardwareBufferCreation(std::string& error_msg) {
|
||||
LOGI("Testing AHardwareBuffer creation...");
|
||||
|
||||
// Check Android API level
|
||||
char sdk_version[PROP_VALUE_MAX] = {};
|
||||
int api_level = 29;
|
||||
|
||||
if (__system_property_get("ro.build.version.sdk", sdk_version) > 0) {
|
||||
api_level = std::atoi(sdk_version);
|
||||
}
|
||||
|
||||
if (api_level < 26) {
|
||||
LOGW("AHardwareBuffer requires API 26+, current API: %d", api_level);
|
||||
LOGI("⚠️ AHardwareBuffer creation test skipped (API level too low)");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Test AHardwareBuffer allocation
|
||||
AHardwareBuffer_Desc desc = {};
|
||||
desc.width = 1920;
|
||||
desc.height = 1080;
|
||||
desc.layers = 1;
|
||||
desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM; // RGBA format (YV12 not available in NDK)
|
||||
desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
|
||||
AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER;
|
||||
|
||||
AHardwareBuffer* buffer = nullptr;
|
||||
int result = AHardwareBuffer_allocate(&desc, &buffer);
|
||||
|
||||
if (result != 0) {
|
||||
LOGW("AHardwareBuffer allocation failed with code: %d", result);
|
||||
LOGI("⚠️ AHardwareBuffer creation test skipped (allocation failed)");
|
||||
return true; // Not a hard failure - device might not support this format
|
||||
}
|
||||
|
||||
TEST_ASSERT_NOT_NULL(buffer, "AHardwareBuffer allocation returned null");
|
||||
|
||||
LOGI("AHardwareBuffer created successfully: %p", buffer);
|
||||
|
||||
// Test buffer description retrieval
|
||||
AHardwareBuffer_Desc retrieved_desc;
|
||||
AHardwareBuffer_describe(buffer, &retrieved_desc);
|
||||
|
||||
TEST_ASSERT_EQ(desc.width, retrieved_desc.width, "Buffer width mismatch");
|
||||
TEST_ASSERT_EQ(desc.height, retrieved_desc.height, "Buffer height mismatch");
|
||||
TEST_ASSERT_EQ(desc.format, retrieved_desc.format, "Buffer format mismatch");
|
||||
|
||||
LOGI("Buffer description verified: %ux%u, format: 0x%x",
|
||||
retrieved_desc.width, retrieved_desc.height, retrieved_desc.format);
|
||||
|
||||
// Clean up
|
||||
AHardwareBuffer_release(buffer);
|
||||
|
||||
LOGI("✅ AHardwareBuffer creation test passed");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestAndroidMediaCodecVulkanSetup(std::string& error_msg) {
|
||||
LOGI("Testing AndroidMediaCodecAV1Decoder Vulkan setup...");
|
||||
|
||||
// Create decoder instance
|
||||
auto decoder = std::make_unique<VavCore::AndroidMediaCodecAV1Decoder>();
|
||||
TEST_ASSERT_NOT_NULL(decoder.get(), "Failed to create AndroidMediaCodecAV1Decoder");
|
||||
|
||||
// Test video metadata
|
||||
VavCore::VideoMetadata metadata;
|
||||
metadata.codec_type = VavCore::VideoCodecType::AV1;
|
||||
metadata.width = 1920;
|
||||
metadata.height = 1080;
|
||||
metadata.frame_rate = 30.0;
|
||||
|
||||
// Initialize decoder
|
||||
bool init_result = decoder->Initialize(metadata);
|
||||
if (!init_result) {
|
||||
LOGW("Decoder initialization failed - likely no hardware AV1 support");
|
||||
LOGI("⚠️ AndroidMediaCodec Vulkan setup test skipped (no AV1 hardware support)");
|
||||
return true;
|
||||
}
|
||||
|
||||
LOGI("Decoder initialized successfully");
|
||||
|
||||
// Test hardware acceleration check
|
||||
bool is_hw_accelerated = decoder->IsHardwareAccelerated();
|
||||
LOGI("Hardware acceleration: %s", is_hw_accelerated ? "YES" : "NO");
|
||||
|
||||
if (!is_hw_accelerated) {
|
||||
LOGW("No hardware acceleration available - Vulkan image output not supported");
|
||||
LOGI("⚠️ AndroidMediaCodec Vulkan setup test skipped (no hardware acceleration)");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Test Vulkan device setup (mock objects for testing)
|
||||
void* mock_vk_device = reinterpret_cast<void*>(0x12345678); // Mock Vulkan device
|
||||
void* mock_vk_instance = reinterpret_cast<void*>(0x87654321); // Mock Vulkan instance
|
||||
|
||||
bool vulkan_result = decoder->SetVulkanDevice(mock_vk_device, mock_vk_instance);
|
||||
TEST_ASSERT(vulkan_result, "Failed to set Vulkan device");
|
||||
|
||||
LOGI("Vulkan device set successfully");
|
||||
|
||||
// Test Vulkan image creation
|
||||
bool image_result = decoder->CreateVulkanImage(mock_vk_device, mock_vk_instance);
|
||||
if (!image_result) {
|
||||
LOGW("Vulkan image creation failed - this might be expected on some devices");
|
||||
LOGI("⚠️ Vulkan image creation test skipped (creation failed)");
|
||||
return true; // Not a hard failure
|
||||
}
|
||||
|
||||
LOGI("Vulkan image created successfully");
|
||||
|
||||
// Test optimal surface type for Vulkan
|
||||
VavCoreSurfaceType optimal_type = decoder->GetOptimalSurfaceType();
|
||||
LOGI("Optimal surface type: %d", static_cast<int>(optimal_type));
|
||||
|
||||
// Verify Vulkan image is supported
|
||||
bool supports_vulkan = decoder->SupportsSurfaceType(VAVCORE_SURFACE_VULKAN_IMAGE);
|
||||
LOGI("Vulkan image surface supported: %s", supports_vulkan ? "YES" : "NO");
|
||||
|
||||
// Test Godot integration info for Vulkan
|
||||
std::string godot_info = decoder->GetGodotIntegrationInfo();
|
||||
LOGI("Godot integration info: %s", godot_info.c_str());
|
||||
|
||||
bool is_optimal_for_godot = decoder->IsOptimalForGodot();
|
||||
LOGI("Optimal for Godot: %s", is_optimal_for_godot ? "YES" : "NO");
|
||||
|
||||
// Clean up
|
||||
decoder->Cleanup();
|
||||
|
||||
LOGI("✅ AndroidMediaCodec Vulkan setup test passed");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestVulkanDecodeToSurface(std::string& error_msg) {
|
||||
LOGI("Testing Vulkan decode to surface...");
|
||||
|
||||
// Create decoder instance
|
||||
auto decoder = std::make_unique<VavCore::AndroidMediaCodecAV1Decoder>();
|
||||
TEST_ASSERT_NOT_NULL(decoder.get(), "Failed to create AndroidMediaCodecAV1Decoder");
|
||||
|
||||
// Test video metadata
|
||||
VavCore::VideoMetadata metadata;
|
||||
metadata.codec_type = VavCore::VideoCodecType::AV1;
|
||||
metadata.width = 1280;
|
||||
metadata.height = 720;
|
||||
metadata.frame_rate = 30.0;
|
||||
|
||||
// Initialize decoder
|
||||
bool init_result = decoder->Initialize(metadata);
|
||||
if (!init_result) {
|
||||
LOGW("Decoder initialization failed - skipping Vulkan decode to surface test");
|
||||
LOGI("⚠️ Vulkan decode to surface test skipped (no AV1 hardware support)");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check hardware acceleration
|
||||
if (!decoder->IsHardwareAccelerated()) {
|
||||
LOGW("No hardware acceleration - skipping Vulkan decode to surface test");
|
||||
LOGI("⚠️ Vulkan decode to surface test skipped (no hardware acceleration)");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Set Vulkan device
|
||||
void* mock_vk_device = reinterpret_cast<void*>(0x12345678);
|
||||
void* mock_vk_instance = reinterpret_cast<void*>(0x87654321);
|
||||
|
||||
bool vulkan_result = decoder->SetVulkanDevice(mock_vk_device, mock_vk_instance);
|
||||
TEST_ASSERT(vulkan_result, "Failed to set Vulkan device");
|
||||
|
||||
// Create Vulkan image
|
||||
bool image_result = decoder->CreateVulkanImage(mock_vk_device, mock_vk_instance);
|
||||
if (!image_result) {
|
||||
LOGW("Vulkan image creation failed - skipping decode to surface test");
|
||||
LOGI("⚠️ Vulkan decode to surface test skipped (image creation failed)");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Test DecodeToSurface with dummy data
|
||||
uint8_t dummy_packet[] = { 0x12, 0x00, 0x0A, 0x0A, 0x00, 0x00, 0x00, 0x01 }; // Minimal AV1 OBU
|
||||
size_t packet_size = sizeof(dummy_packet);
|
||||
|
||||
VavCore::VideoFrame output_frame;
|
||||
bool decode_result = decoder->DecodeToSurface(
|
||||
dummy_packet, packet_size,
|
||||
VAVCORE_SURFACE_VULKAN_IMAGE,
|
||||
mock_vk_device, // Mock VkImage
|
||||
output_frame
|
||||
);
|
||||
|
||||
// Note: This will likely fail with real dummy data, but we're testing the API flow
|
||||
if (!decode_result) {
|
||||
LOGW("DecodeToSurface failed with dummy data - this is expected");
|
||||
} else {
|
||||
LOGI("DecodeToSurface succeeded with dummy data");
|
||||
|
||||
// Verify frame metadata
|
||||
TEST_ASSERT_EQ(1280, output_frame.width, "Incorrect frame width");
|
||||
TEST_ASSERT_EQ(720, output_frame.height, "Incorrect frame height");
|
||||
|
||||
LOGI("Frame metadata: %dx%d", output_frame.width, output_frame.height);
|
||||
}
|
||||
|
||||
LOGI("✅ Vulkan decode to surface test completed");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestVulkanSurfaceTypeOptimization(std::string& error_msg) {
|
||||
LOGI("Testing Vulkan surface type optimization...");
|
||||
|
||||
// Create decoder instance
|
||||
auto decoder = std::make_unique<VavCore::AndroidMediaCodecAV1Decoder>();
|
||||
TEST_ASSERT_NOT_NULL(decoder.get(), "Failed to create AndroidMediaCodecAV1Decoder");
|
||||
|
||||
// Test video metadata
|
||||
VavCore::VideoMetadata metadata;
|
||||
metadata.codec_type = VavCore::VideoCodecType::AV1;
|
||||
metadata.width = 1920;
|
||||
metadata.height = 1080;
|
||||
metadata.frame_rate = 60.0;
|
||||
|
||||
// Initialize decoder
|
||||
bool init_result = decoder->Initialize(metadata);
|
||||
if (!init_result) {
|
||||
LOGW("Decoder initialization failed - skipping surface type optimization test");
|
||||
LOGI("⚠️ Vulkan surface type optimization test skipped (no AV1 hardware support)");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Test all Vulkan-related surface types
|
||||
std::vector<std::pair<VavCoreSurfaceType, std::string>> surface_types = {
|
||||
{ VAVCORE_SURFACE_VULKAN_IMAGE, "VULKAN_IMAGE" },
|
||||
{ VAVCORE_SURFACE_ANDROID_HARDWARE_BUFFER, "ANDROID_HARDWARE_BUFFER" },
|
||||
{ VAVCORE_SURFACE_OPENGL_ES_TEXTURE, "OPENGL_ES_TEXTURE" },
|
||||
{ VAVCORE_SURFACE_ANDROID_NATIVE_WINDOW, "ANDROID_NATIVE_WINDOW" },
|
||||
{ VAVCORE_SURFACE_CPU, "CPU" }
|
||||
};
|
||||
|
||||
for (const auto& surface_type_pair : surface_types) {
|
||||
VavCoreSurfaceType type = surface_type_pair.first;
|
||||
const std::string& name = surface_type_pair.second;
|
||||
|
||||
bool supported = decoder->SupportsSurfaceType(type);
|
||||
LOGI("Surface type %s: %s", name.c_str(), supported ? "SUPPORTED" : "NOT SUPPORTED");
|
||||
}
|
||||
|
||||
// Test optimal surface type selection
|
||||
VavCoreSurfaceType optimal_type = decoder->GetOptimalSurfaceType();
|
||||
LOGI("Optimal surface type for this device: %d", static_cast<int>(optimal_type));
|
||||
|
||||
// Test Godot-specific optimization
|
||||
bool is_optimal_for_godot = decoder->IsOptimalForGodot();
|
||||
LOGI("Optimal for Godot integration: %s", is_optimal_for_godot ? "YES" : "NO");
|
||||
|
||||
// Get detailed Godot integration information
|
||||
std::string godot_info = decoder->GetGodotIntegrationInfo();
|
||||
LOGI("Godot integration details: %s", godot_info.c_str());
|
||||
|
||||
// Verify that at least CPU surface is supported (fallback)
|
||||
bool cpu_supported = decoder->SupportsSurfaceType(VAVCORE_SURFACE_CPU);
|
||||
TEST_ASSERT(cpu_supported, "CPU surface should always be supported");
|
||||
|
||||
LOGI("✅ Vulkan surface type optimization test passed");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Test registration function
|
||||
void RegisterVulkanImageTests(TestFramework& framework) {
|
||||
framework.RegisterTest("Vulkan_Availability", TestVulkanAvailability);
|
||||
framework.RegisterTest("Vulkan_AHardwareBuffer", TestAHardwareBufferCreation);
|
||||
framework.RegisterTest("Vulkan_MediaCodecSetup", TestAndroidMediaCodecVulkanSetup);
|
||||
framework.RegisterTest("Vulkan_DecodeToSurface", TestVulkanDecodeToSurface);
|
||||
framework.RegisterTest("Vulkan_SurfaceOptimization", TestVulkanSurfaceTypeOptimization);
|
||||
}
|
||||
|
||||
} // namespace VavCoreTest
|
||||
132
vav2/platforms/android/tests/texture-binding-test/src/main.cpp
Normal file
132
vav2/platforms/android/tests/texture-binding-test/src/main.cpp
Normal file
@@ -0,0 +1,132 @@
|
||||
#include "TestFramework.h"
|
||||
#include <android/log.h>
|
||||
#include <jni.h>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
|
||||
// Forward declarations for test registration functions
|
||||
namespace VavCoreTest {
|
||||
void RegisterOpenGLESTextureTests(TestFramework& framework);
|
||||
void RegisterVulkanImageTests(TestFramework& framework);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
__android_log_print(ANDROID_LOG_INFO, "VavCoreTextureTest", "=== VavCore Texture Binding Test Application ===");
|
||||
__android_log_print(ANDROID_LOG_INFO, "VavCoreTextureTest", "Starting comprehensive OpenGL ES and Vulkan texture binding tests");
|
||||
|
||||
// Create test framework
|
||||
VavCoreTest::TestFramework framework;
|
||||
|
||||
// Register all test suites
|
||||
__android_log_print(ANDROID_LOG_INFO, "VavCoreTextureTest", "Registering OpenGL ES texture tests...");
|
||||
VavCoreTest::RegisterOpenGLESTextureTests(framework);
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "VavCoreTextureTest", "Registering Vulkan image tests...");
|
||||
VavCoreTest::RegisterVulkanImageTests(framework);
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "VavCoreTextureTest", "All tests registered successfully");
|
||||
|
||||
// Check for specific test name argument
|
||||
bool run_all = true;
|
||||
std::string specific_test;
|
||||
|
||||
if (argc > 1) {
|
||||
specific_test = argv[1];
|
||||
run_all = false;
|
||||
__android_log_print(ANDROID_LOG_INFO, "VavCoreTextureTest", "Running specific test: %s", specific_test.c_str());
|
||||
} else {
|
||||
__android_log_print(ANDROID_LOG_INFO, "VavCoreTextureTest", "Running all tests");
|
||||
}
|
||||
|
||||
// Run tests
|
||||
bool all_passed = false;
|
||||
|
||||
if (run_all) {
|
||||
all_passed = framework.RunAllTests();
|
||||
} else {
|
||||
all_passed = framework.RunTest(specific_test);
|
||||
}
|
||||
|
||||
// Print final results
|
||||
__android_log_print(ANDROID_LOG_INFO, "VavCoreTextureTest", "=== Final Test Results ===");
|
||||
|
||||
if (run_all) {
|
||||
auto results = framework.GetResults();
|
||||
int total_tests = static_cast<int>(results.size());
|
||||
int passed_tests = 0;
|
||||
|
||||
for (const auto& result : results) {
|
||||
if (result.passed) {
|
||||
passed_tests++;
|
||||
}
|
||||
}
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "VavCoreTextureTest", "Total tests run: %d", total_tests);
|
||||
__android_log_print(ANDROID_LOG_INFO, "VavCoreTextureTest", "Tests passed: %d", passed_tests);
|
||||
__android_log_print(ANDROID_LOG_INFO, "VavCoreTextureTest", "Tests failed: %d", total_tests - passed_tests);
|
||||
|
||||
if (total_tests > 0) {
|
||||
double success_rate = (static_cast<double>(passed_tests) / total_tests) * 100.0;
|
||||
__android_log_print(ANDROID_LOG_INFO, "VavCoreTextureTest", "Success rate: %.1f%%", success_rate);
|
||||
}
|
||||
}
|
||||
|
||||
if (all_passed) {
|
||||
__android_log_print(ANDROID_LOG_INFO, "VavCoreTextureTest", "🎉 All tests PASSED!");
|
||||
__android_log_print(ANDROID_LOG_INFO, "VavCoreTextureTest", "OpenGL ES and Vulkan texture binding implementation is working correctly");
|
||||
} else {
|
||||
__android_log_print(ANDROID_LOG_ERROR, "VavCoreTextureTest", "❌ Some tests FAILED!");
|
||||
__android_log_print(ANDROID_LOG_ERROR, "VavCoreTextureTest", "Please check the logs above for detailed error information");
|
||||
}
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "VavCoreTextureTest", "=== VavCore Texture Binding Test Complete ===");
|
||||
|
||||
// Return appropriate exit code
|
||||
return all_passed ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Additional utility functions for Android environment
|
||||
|
||||
extern "C" {
|
||||
|
||||
// JNI function for running tests from Java (if needed)
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_vavcore_texturetest_MainActivity_runNativeTests(JNIEnv *env, jobject thiz) {
|
||||
__android_log_print(ANDROID_LOG_INFO, "VavCoreTextureTest", "Running tests from JNI call");
|
||||
|
||||
// Store JavaVM for decoder usage
|
||||
JavaVM* jvm;
|
||||
env->GetJavaVM(&jvm);
|
||||
|
||||
// Run main test function
|
||||
char* dummy_argv[] = { const_cast<char*>("VavCoreTextureBindingTest") };
|
||||
int result = main(1, dummy_argv);
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "VavCoreTextureTest", "JNI test execution completed with result: %d", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// JNI function for running specific test from Java
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_vavcore_texturetest_MainActivity_runSpecificTest(JNIEnv *env, jobject thiz, jstring test_name) {
|
||||
const char* test_name_str = env->GetStringUTFChars(test_name, nullptr);
|
||||
__android_log_print(ANDROID_LOG_INFO, "VavCoreTextureTest", "Running specific test from JNI: %s", test_name_str);
|
||||
|
||||
// Store JavaVM for decoder usage
|
||||
JavaVM* jvm;
|
||||
env->GetJavaVM(&jvm);
|
||||
|
||||
// Run specific test
|
||||
char* argv[] = {
|
||||
const_cast<char*>("VavCoreTextureBindingTest"),
|
||||
const_cast<char*>(test_name_str)
|
||||
};
|
||||
int result = main(2, argv);
|
||||
|
||||
env->ReleaseStringUTFChars(test_name, test_name_str);
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "VavCoreTextureTest", "JNI specific test execution completed with result: %d", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
Reference in New Issue
Block a user