// This file is part of the 64k demo project. // It implements reusable test helpers for GPU effect testing. // Provides pixel validation and lifecycle testing utilities. #if !defined(STRIP_ALL) // Test code only - zero size impact on final binary #include "effect_test_helpers.h" #include "gpu/effect.h" #include // ============================================================================ // Pixel Validation Helpers // ============================================================================ bool validate_pixels( const std::vector& pixels, int width, int height, std::function predicate) { const size_t pixel_count = width * height; for (size_t i = 0; i < pixel_count; ++i) { const size_t offset = i * 4; // BGRA8 = 4 bytes/pixel const uint8_t b = pixels[offset + 0]; const uint8_t g = pixels[offset + 1]; const uint8_t r = pixels[offset + 2]; const uint8_t a = pixels[offset + 3]; if (predicate(r, g, b, a)) { return true; // At least one pixel matches } } return false; // No pixels matched } bool has_rendered_content(const std::vector& pixels, int width, int height) { return validate_pixels(pixels, width, height, [](uint8_t r, uint8_t g, uint8_t b, uint8_t a) { return r > 0 || g > 0 || b > 0; }); } bool all_pixels_match_color(const std::vector& pixels, int width, int height, uint8_t target_r, uint8_t target_g, uint8_t target_b, uint8_t tolerance) { const size_t pixel_count = width * height; for (size_t i = 0; i < pixel_count; ++i) { const size_t offset = i * 4; const uint8_t b = pixels[offset + 0]; const uint8_t g = pixels[offset + 1]; const uint8_t r = pixels[offset + 2]; const int diff_r = static_cast(r) - static_cast(target_r); const int diff_g = static_cast(g) - static_cast(target_g); const int diff_b = static_cast(b) - static_cast(target_b); if (diff_r * diff_r + diff_g * diff_g + diff_b * diff_b > tolerance * tolerance) { return false; // At least one pixel doesn't match } } return true; // All pixels match } uint64_t hash_pixels(const std::vector& pixels) { // Simple FNV-1a hash uint64_t hash = 14695981039346656037ULL; for (const uint8_t byte : pixels) { hash ^= byte; hash *= 1099511628211ULL; } return hash; } // ============================================================================ // Effect Lifecycle Helpers // ============================================================================ bool test_effect_lifecycle(Effect* effect, MainSequence* main_seq) { assert(effect && "Effect pointer is null"); assert(main_seq && "MainSequence pointer is null"); // Check initial state if (effect->is_initialized) { return false; // Should not be initialized yet } // Initialize effect effect->init(main_seq); // Check initialized state if (!effect->is_initialized) { return false; // Should be initialized now } return true; // Lifecycle test passed } bool test_effect_render_smoke(Effect* effect) { assert(effect && "Effect pointer is null"); // Smoke test: Just call render with dummy parameters // If this doesn't crash, consider it a success // Note: This requires the effect to be initialized first if (!effect->is_initialized) { return false; // Cannot render uninitialized effect } // We cannot actually render without a full render pass setup // This is a placeholder for more sophisticated render testing // Real render tests should use OffscreenRenderTarget return true; // Smoke test passed (no crash) } #endif /* !defined(STRIP_ALL) */