1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker * Copyright 2021 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker *
4*38e8c45fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker *
8*38e8c45fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker *
10*38e8c45fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker */
16*38e8c45fSAndroid Build Coastguard Worker
17*38e8c45fSAndroid Build Coastguard Worker #include <RenderEngineBench.h>
18*38e8c45fSAndroid Build Coastguard Worker #include <android/bitmap.h>
19*38e8c45fSAndroid Build Coastguard Worker #include <android/data_space.h>
20*38e8c45fSAndroid Build Coastguard Worker #include <android/imagedecoder.h>
21*38e8c45fSAndroid Build Coastguard Worker #include <log/log.h>
22*38e8c45fSAndroid Build Coastguard Worker #include <renderengine/ExternalTexture.h>
23*38e8c45fSAndroid Build Coastguard Worker #include <renderengine/RenderEngine.h>
24*38e8c45fSAndroid Build Coastguard Worker #include <sys/types.h>
25*38e8c45fSAndroid Build Coastguard Worker
26*38e8c45fSAndroid Build Coastguard Worker using namespace android;
27*38e8c45fSAndroid Build Coastguard Worker using namespace android::renderengine;
28*38e8c45fSAndroid Build Coastguard Worker
29*38e8c45fSAndroid Build Coastguard Worker namespace {
30*38e8c45fSAndroid Build Coastguard Worker struct DecoderDeleter {
operator ()__anon795bede20111::DecoderDeleter31*38e8c45fSAndroid Build Coastguard Worker void operator()(AImageDecoder* decoder) { AImageDecoder_delete(decoder); }
32*38e8c45fSAndroid Build Coastguard Worker };
33*38e8c45fSAndroid Build Coastguard Worker
34*38e8c45fSAndroid Build Coastguard Worker using AutoDecoderDeleter = std::unique_ptr<AImageDecoder, DecoderDeleter>;
35*38e8c45fSAndroid Build Coastguard Worker
ok(int aImageDecoderResult,const char * path,const char * method)36*38e8c45fSAndroid Build Coastguard Worker bool ok(int aImageDecoderResult, const char* path, const char* method) {
37*38e8c45fSAndroid Build Coastguard Worker if (aImageDecoderResult == ANDROID_IMAGE_DECODER_SUCCESS) {
38*38e8c45fSAndroid Build Coastguard Worker return true;
39*38e8c45fSAndroid Build Coastguard Worker }
40*38e8c45fSAndroid Build Coastguard Worker
41*38e8c45fSAndroid Build Coastguard Worker ALOGE("Failed AImageDecoder_%s on '%s' with error '%s'", method, path,
42*38e8c45fSAndroid Build Coastguard Worker AImageDecoder_resultToString(aImageDecoderResult));
43*38e8c45fSAndroid Build Coastguard Worker return false;
44*38e8c45fSAndroid Build Coastguard Worker }
45*38e8c45fSAndroid Build Coastguard Worker } // namespace
46*38e8c45fSAndroid Build Coastguard Worker
47*38e8c45fSAndroid Build Coastguard Worker namespace renderenginebench {
48*38e8c45fSAndroid Build Coastguard Worker
decode(const char * path,const sp<GraphicBuffer> & buffer)49*38e8c45fSAndroid Build Coastguard Worker void decode(const char* path, const sp<GraphicBuffer>& buffer) {
50*38e8c45fSAndroid Build Coastguard Worker base::unique_fd fd{open(path, O_RDONLY)};
51*38e8c45fSAndroid Build Coastguard Worker if (fd.get() < 0) {
52*38e8c45fSAndroid Build Coastguard Worker ALOGE("Failed to open %s", path);
53*38e8c45fSAndroid Build Coastguard Worker return;
54*38e8c45fSAndroid Build Coastguard Worker }
55*38e8c45fSAndroid Build Coastguard Worker
56*38e8c45fSAndroid Build Coastguard Worker AImageDecoder* decoder{nullptr};
57*38e8c45fSAndroid Build Coastguard Worker auto result = AImageDecoder_createFromFd(fd.get(), &decoder);
58*38e8c45fSAndroid Build Coastguard Worker if (!ok(result, path, "createFromFd")) {
59*38e8c45fSAndroid Build Coastguard Worker return;
60*38e8c45fSAndroid Build Coastguard Worker }
61*38e8c45fSAndroid Build Coastguard Worker
62*38e8c45fSAndroid Build Coastguard Worker AutoDecoderDeleter deleter(decoder);
63*38e8c45fSAndroid Build Coastguard Worker
64*38e8c45fSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(buffer->getWidth() <= 0 || buffer->getHeight() <= 0,
65*38e8c45fSAndroid Build Coastguard Worker "Impossible buffer size!");
66*38e8c45fSAndroid Build Coastguard Worker auto width = static_cast<int32_t>(buffer->getWidth());
67*38e8c45fSAndroid Build Coastguard Worker auto height = static_cast<int32_t>(buffer->getHeight());
68*38e8c45fSAndroid Build Coastguard Worker result = AImageDecoder_setTargetSize(decoder, width, height);
69*38e8c45fSAndroid Build Coastguard Worker if (!ok(result, path, "setTargetSize")) {
70*38e8c45fSAndroid Build Coastguard Worker return;
71*38e8c45fSAndroid Build Coastguard Worker }
72*38e8c45fSAndroid Build Coastguard Worker
73*38e8c45fSAndroid Build Coastguard Worker void* pixels{nullptr};
74*38e8c45fSAndroid Build Coastguard Worker int32_t stride{0};
75*38e8c45fSAndroid Build Coastguard Worker if (auto status = buffer->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, &pixels,
76*38e8c45fSAndroid Build Coastguard Worker nullptr /*outBytesPerPixel*/, &stride);
77*38e8c45fSAndroid Build Coastguard Worker status < 0) {
78*38e8c45fSAndroid Build Coastguard Worker ALOGE("Failed to lock pixels!");
79*38e8c45fSAndroid Build Coastguard Worker return;
80*38e8c45fSAndroid Build Coastguard Worker }
81*38e8c45fSAndroid Build Coastguard Worker
82*38e8c45fSAndroid Build Coastguard Worker result = AImageDecoder_decodeImage(decoder, pixels, static_cast<size_t>(stride),
83*38e8c45fSAndroid Build Coastguard Worker static_cast<size_t>(stride * height));
84*38e8c45fSAndroid Build Coastguard Worker if (auto status = buffer->unlock(); status < 0) {
85*38e8c45fSAndroid Build Coastguard Worker ALOGE("Failed to unlock pixels!");
86*38e8c45fSAndroid Build Coastguard Worker }
87*38e8c45fSAndroid Build Coastguard Worker
88*38e8c45fSAndroid Build Coastguard Worker // For the side effect of logging.
89*38e8c45fSAndroid Build Coastguard Worker (void)ok(result, path, "decodeImage");
90*38e8c45fSAndroid Build Coastguard Worker }
91*38e8c45fSAndroid Build Coastguard Worker
encodeToJpeg(const char * path,const sp<GraphicBuffer> & buffer)92*38e8c45fSAndroid Build Coastguard Worker void encodeToJpeg(const char* path, const sp<GraphicBuffer>& buffer) {
93*38e8c45fSAndroid Build Coastguard Worker base::unique_fd fd{open(path, O_WRONLY | O_CREAT, S_IWUSR)};
94*38e8c45fSAndroid Build Coastguard Worker if (fd.get() < 0) {
95*38e8c45fSAndroid Build Coastguard Worker ALOGE("Failed to open %s", path);
96*38e8c45fSAndroid Build Coastguard Worker return;
97*38e8c45fSAndroid Build Coastguard Worker }
98*38e8c45fSAndroid Build Coastguard Worker
99*38e8c45fSAndroid Build Coastguard Worker void* pixels{nullptr};
100*38e8c45fSAndroid Build Coastguard Worker int32_t stride{0};
101*38e8c45fSAndroid Build Coastguard Worker if (auto status = buffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, &pixels,
102*38e8c45fSAndroid Build Coastguard Worker nullptr /*outBytesPerPixel*/, &stride);
103*38e8c45fSAndroid Build Coastguard Worker status < 0) {
104*38e8c45fSAndroid Build Coastguard Worker ALOGE("Failed to lock pixels!");
105*38e8c45fSAndroid Build Coastguard Worker return;
106*38e8c45fSAndroid Build Coastguard Worker }
107*38e8c45fSAndroid Build Coastguard Worker
108*38e8c45fSAndroid Build Coastguard Worker AndroidBitmapInfo info{
109*38e8c45fSAndroid Build Coastguard Worker .width = buffer->getWidth(),
110*38e8c45fSAndroid Build Coastguard Worker .height = buffer->getHeight(),
111*38e8c45fSAndroid Build Coastguard Worker .stride = static_cast<uint32_t>(stride),
112*38e8c45fSAndroid Build Coastguard Worker .format = ANDROID_BITMAP_FORMAT_RGBA_8888,
113*38e8c45fSAndroid Build Coastguard Worker .flags = ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE,
114*38e8c45fSAndroid Build Coastguard Worker };
115*38e8c45fSAndroid Build Coastguard Worker int result = AndroidBitmap_compress(&info, ADATASPACE_SRGB, pixels,
116*38e8c45fSAndroid Build Coastguard Worker ANDROID_BITMAP_COMPRESS_FORMAT_JPEG, 80, &fd,
117*38e8c45fSAndroid Build Coastguard Worker [](void* fdPtr, const void* data, size_t size) -> bool {
118*38e8c45fSAndroid Build Coastguard Worker const ssize_t bytesWritten =
119*38e8c45fSAndroid Build Coastguard Worker write(reinterpret_cast<base::unique_fd*>(fdPtr)
120*38e8c45fSAndroid Build Coastguard Worker ->get(),
121*38e8c45fSAndroid Build Coastguard Worker data, size);
122*38e8c45fSAndroid Build Coastguard Worker return bytesWritten > 0 &&
123*38e8c45fSAndroid Build Coastguard Worker static_cast<size_t>(bytesWritten) == size;
124*38e8c45fSAndroid Build Coastguard Worker });
125*38e8c45fSAndroid Build Coastguard Worker if (result == ANDROID_BITMAP_RESULT_SUCCESS) {
126*38e8c45fSAndroid Build Coastguard Worker ALOGD("Successfully encoded to '%s'", path);
127*38e8c45fSAndroid Build Coastguard Worker } else {
128*38e8c45fSAndroid Build Coastguard Worker ALOGE("Failed to encode to %s with error %d", path, result);
129*38e8c45fSAndroid Build Coastguard Worker }
130*38e8c45fSAndroid Build Coastguard Worker
131*38e8c45fSAndroid Build Coastguard Worker if (auto status = buffer->unlock(); status < 0) {
132*38e8c45fSAndroid Build Coastguard Worker ALOGE("Failed to unlock pixels!");
133*38e8c45fSAndroid Build Coastguard Worker }
134*38e8c45fSAndroid Build Coastguard Worker }
135*38e8c45fSAndroid Build Coastguard Worker
136*38e8c45fSAndroid Build Coastguard Worker } // namespace renderenginebench
137