19762338dSopenharmony_ci/*
29762338dSopenharmony_ci * Copyright (c) 2023-2024 Huawei Device Co., Ltd.
39762338dSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
49762338dSopenharmony_ci * you may not use this file except in compliance with the License.
59762338dSopenharmony_ci * You may obtain a copy of the License at
69762338dSopenharmony_ci *
79762338dSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
89762338dSopenharmony_ci *
99762338dSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
109762338dSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
119762338dSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
129762338dSopenharmony_ci * See the License for the specific language governing permissions and
139762338dSopenharmony_ci * limitations under the License.
149762338dSopenharmony_ci */
159762338dSopenharmony_ci
169762338dSopenharmony_ci#include "hdi_composition_check.h"
179762338dSopenharmony_ci#include "display_test.h"
189762338dSopenharmony_cinamespace OHOS {
199762338dSopenharmony_cinamespace HDI {
209762338dSopenharmony_cinamespace Display {
219762338dSopenharmony_cinamespace TEST {
229762338dSopenharmony_ciusing namespace OHOS::HDI::Display::Composer::V1_1;
239762338dSopenharmony_cistatic void GetCheckPoints(Point center, std::vector<Point> &points)
249762338dSopenharmony_ci{
259762338dSopenharmony_ci    const uint32_t STEP = 3;
269762338dSopenharmony_ci    points.push_back(center);
279762338dSopenharmony_ci    points.push_back({center.x + STEP, center.y});
289762338dSopenharmony_ci    points.push_back({center.x + STEP, center.y + STEP});
299762338dSopenharmony_ci    points.push_back({center.x + STEP, center.y - STEP});
309762338dSopenharmony_ci    points.push_back({center.x, center.y + STEP});
319762338dSopenharmony_ci    points.push_back({center.x - STEP, center.y});
329762338dSopenharmony_ci    points.push_back({center.x - STEP, center.y - STEP});
339762338dSopenharmony_ci    points.push_back({center.x - STEP, center.y + STEP});
349762338dSopenharmony_ci    points.push_back({center.x, center.y - STEP});
359762338dSopenharmony_ci}
369762338dSopenharmony_ci// simple hande the alpha it may not compatible with all scenarios
379762338dSopenharmony_cistatic void SimpleHandleAlpha(const LayerSettings& layers, uint32_t& color)
389762338dSopenharmony_ci{
399762338dSopenharmony_ci    const float INV = 1.0f / 255.0f;
409762338dSopenharmony_ci    const uint32_t WHITE_TRANSPARENT = 0xffffff00;
419762338dSopenharmony_ci    const int32_t ALPHA = 0xff;
429762338dSopenharmony_ci    if (layers.alpha != -1) {
439762338dSopenharmony_ci        switch (layers.blendType) {
449762338dSopenharmony_ci            case BLEND_SRC:
459762338dSopenharmony_ci                color = (color & WHITE_TRANSPARENT) | (layers.alpha & ALPHA); // get the alpha
469762338dSopenharmony_ci                break;
479762338dSopenharmony_ci            case BLEND_SRCOVER:
489762338dSopenharmony_ci                color = color * (layers.alpha * INV);
499762338dSopenharmony_ci                color = (color & WHITE_TRANSPARENT) | (layers.alpha & ALPHA); // get the alpha
509762338dSopenharmony_ci                break;
519762338dSopenharmony_ci            default:
529762338dSopenharmony_ci                break;
539762338dSopenharmony_ci        }
549762338dSopenharmony_ci    }
559762338dSopenharmony_ci}
569762338dSopenharmony_ci
579762338dSopenharmony_cistatic std::vector<uint32_t> GetCheckColors(const std::vector<LayerSettings> &layers, const std::vector<Point> &points)
589762338dSopenharmony_ci{
599762338dSopenharmony_ci    std::vector<uint32_t> colors;
609762338dSopenharmony_ci    for (auto point : points) {
619762338dSopenharmony_ci        uint32_t color = 0;
629762338dSopenharmony_ci        for (uint32_t i = layers.size(); i > 0; i--) {
639762338dSopenharmony_ci            auto layer = layers[i - 1];
649762338dSopenharmony_ci            const IRect& RECT = layer.displayRect;
659762338dSopenharmony_ci            // check whether the point is inside the rect
669762338dSopenharmony_ci            if ((point.x >= RECT.x) && (point.x < (RECT.x + RECT.w)) && (point.y >= RECT.y) &&
679762338dSopenharmony_ci                (point.y < (RECT.y + RECT.h))) {
689762338dSopenharmony_ci                if (layer.compositionType != Composer::V1_0::CompositionType::COMPOSITION_VIDEO) {
699762338dSopenharmony_ci                    color = layer.color;
709762338dSopenharmony_ci                    SimpleHandleAlpha(layer, color);
719762338dSopenharmony_ci                }
729762338dSopenharmony_ci                break;
739762338dSopenharmony_ci            }
749762338dSopenharmony_ci        }
759762338dSopenharmony_ci        colors.push_back(color);
769762338dSopenharmony_ci    }
779762338dSopenharmony_ci    return colors;
789762338dSopenharmony_ci}
799762338dSopenharmony_ci
809762338dSopenharmony_ciint32_t HdiCompositionCheck::Check(const std::vector<LayerSettings> &layers,
819762338dSopenharmony_ci    const BufferHandle& clientBuffer, uint32_t checkType) const
829762338dSopenharmony_ci{
839762338dSopenharmony_ci    int ret = DISPLAY_SUCCESS;
849762338dSopenharmony_ci    const int MID_POS = 2;
859762338dSopenharmony_ci    // get the all check point
869762338dSopenharmony_ci    std::vector<Point> points;
879762338dSopenharmony_ci    for (auto layer : layers) {
889762338dSopenharmony_ci        const IRect& RECT = layer.displayRect;
899762338dSopenharmony_ci        if (checkType == CHECK_VERTEX) {
909762338dSopenharmony_ci            GetCheckPoints({RECT.x, RECT.y}, points);
919762338dSopenharmony_ci            GetCheckPoints({RECT.x, RECT.y + RECT.h}, points);
929762338dSopenharmony_ci            GetCheckPoints({RECT.x + RECT.w, RECT.y}, points);
939762338dSopenharmony_ci            GetCheckPoints({RECT.x + RECT.w, RECT.y + RECT.h}, points);
949762338dSopenharmony_ci        } else {
959762338dSopenharmony_ci            GetCheckPoints({RECT.x + RECT.w / MID_POS, RECT.y + RECT.h / MID_POS}, points); // center point
969762338dSopenharmony_ci        }
979762338dSopenharmony_ci    }
989762338dSopenharmony_ci
999762338dSopenharmony_ci    // get all the check color
1009762338dSopenharmony_ci    std::vector<uint32_t> colors = GetCheckColors(layers, points);
1019762338dSopenharmony_ci    DISPLAY_TEST_CHK_RETURN((colors.size() != points.size()), DISPLAY_FAILURE,
1029762338dSopenharmony_ci        DISPLAY_TEST_LOGE("Points and colors don't match"));
1039762338dSopenharmony_ci    for (uint32_t i = 0; i < points.size(); i++) {
1049762338dSopenharmony_ci        if ((points[i].x >= clientBuffer.width) || (points[i].x < 0) || (points[i].y < 0) ||
1059762338dSopenharmony_ci            (points[i].y >= clientBuffer.height)) {
1069762338dSopenharmony_ci            continue;
1079762338dSopenharmony_ci        }
1089762338dSopenharmony_ci        ret = CheckPixel(clientBuffer, points[i].x, points[i].y, colors[i]);
1099762338dSopenharmony_ci        if (ret != DISPLAY_SUCCESS) {
1109762338dSopenharmony_ci            DISPLAY_TEST_LOGE("check failed");
1119762338dSopenharmony_ci            break;
1129762338dSopenharmony_ci        }
1139762338dSopenharmony_ci    }
1149762338dSopenharmony_ci    return ret;
1159762338dSopenharmony_ci}
1169762338dSopenharmony_ci} // OHOS
1179762338dSopenharmony_ci} // HDI
1189762338dSopenharmony_ci} // Display
1199762338dSopenharmony_ci} // TEST
120