1 /* 2 * Copyright 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 */ 17 #include <jni.h> 18 #include <set> 19 #include <unistd.h> 20 21 #include "CameraTestHelpers.h" 22 #include "ImageReaderTestHelpers.h" 23 #include "NativeTestHelpers.h" 24 #include "VulkanTestHelpers.h" 25 26 namespace { 27 28 // Constants used to control test execution. 29 static constexpr uint32_t kTestImageWidth = 640; 30 static constexpr uint32_t kTestImageHeight = 480; 31 static constexpr uint32_t kTestImageFormat = AIMAGE_FORMAT_PRIVATE; 32 static constexpr uint64_t kTestImageUsage = 33 AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; 34 static constexpr uint32_t kTestImageCount = 3; 35 36 // Checks if a vector has more than 10 unique values, in which case we consider 37 // it noisy. 38 bool isNoisy(const std::vector<uint32_t> &data) { 39 std::set<uint32_t> values_seen; 40 for (uint32_t value : data) { 41 values_seen.insert(value); 42 } 43 return values_seen.size() > 10; 44 } 45 46 } // namespace 47 48 // A basic test which does the following: 49 // 1) Reads a Camera frame into an AHardwareBuffer. 50 // 2) Creates a VkImage from this AHardwareBuffer. 51 // 3) Renders the AHardwareBuffer to a Vulkan RGBA intermediate. 52 // 4) Reads back the intermediate into a CPU accessible VkBuffer. 53 // 5) Validates that there is noise in the buffer. 54 static void loadCameraAndVerifyFrameImport(JNIEnv *env, jclass, 55 jobject assetMgr) { 56 // Initialize Vulkan. 57 VkInit init; 58 if (!init.init()) { 59 // Could not initialize Vulkan due to lack of device support, skip test. 60 return; 61 } 62 VkImageRenderer renderer(&init, kTestImageWidth, kTestImageHeight, 63 VK_FORMAT_R8G8B8A8_UNORM, 4); 64 ASSERT(renderer.init(env, assetMgr), "Could not init VkImageRenderer."); 65 66 // Initialize image reader and camera helpers. 67 ImageReaderHelper imageReader(kTestImageWidth, kTestImageHeight, 68 kTestImageFormat, kTestImageUsage, 69 kTestImageCount); 70 CameraHelper camera; 71 ASSERT(imageReader.initImageReader() >= 0, 72 "Failed to initialize image reader."); 73 ASSERT(camera.initCamera(imageReader.getNativeWindow()) >= 0, 74 "Failed to initialize camera."); 75 ASSERT(camera.isCameraReady(), "Camera is not ready."); 76 77 // Acquire an AHardwareBuffer from the camera. 78 ASSERT(camera.takePicture() >= 0, "Camera failed to take picture."); 79 AHardwareBuffer *buffer; 80 int ret = imageReader.getBufferFromCurrentImage(&buffer); 81 while (ret != 0) { 82 usleep(1000); 83 ret = imageReader.getBufferFromCurrentImage(&buffer); 84 } 85 86 // Impor the AHardwareBuffer into Vulkan. 87 VkAHardwareBufferImage vkImage(&init); 88 ASSERT(vkImage.init(buffer, true /* useExternalFormat */), "Could not initialize VkAHardwareBufferImage."); 89 90 // Render the AHardwareBuffer using Vulkan and read back the result. 91 std::vector<uint32_t> imageData; 92 ASSERT(renderer.renderImageAndReadback( 93 vkImage.image(), vkImage.sampler(), vkImage.view(), 94 vkImage.semaphore(), vkImage.isSamplerImmutable(), &imageData), 95 "Could not render/read-back Vulkan pixels."); 96 97 // Ensure that we see noise. 98 ASSERT(isNoisy(imageData), "Camera data should be noisy."); 99 } 100 101 static JNINativeMethod gMethods[] = { 102 {"loadCameraAndVerifyFrameImport", "(Landroid/content/res/AssetManager;)V", 103 (void *)loadCameraAndVerifyFrameImport}, 104 }; 105 106 int register_android_graphics_cts_CameraVulkanGpuTest(JNIEnv *env) { 107 jclass clazz = env->FindClass("android/graphics/cts/CameraVulkanGpuTest"); 108 return env->RegisterNatives(clazz, gMethods, 109 sizeof(gMethods) / sizeof(JNINativeMethod)); 110 } 111