1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2021 Google LLC
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#ifndef SkYUVAInfoLocation_DEFINED
9cb93a386Sopenharmony_ci#define SkYUVAInfoLocation_DEFINED
10cb93a386Sopenharmony_ci
11cb93a386Sopenharmony_ci#include "include/core/SkColor.h"
12cb93a386Sopenharmony_ci#include "include/core/SkYUVAInfo.h"
13cb93a386Sopenharmony_ci
14cb93a386Sopenharmony_ci/**
15cb93a386Sopenharmony_ci * The location of Y, U, V, or A values within the planes described by SkYUVAInfo. Computed from a
16cb93a386Sopenharmony_ci * SkYUVAInfo and the set of channels present in a set of pixmaps/textures.
17cb93a386Sopenharmony_ci */
18cb93a386Sopenharmony_cistruct SkYUVAInfo::YUVALocation {
19cb93a386Sopenharmony_ci    /** The index of the plane where the Y, U, V, or A value is to be found. */
20cb93a386Sopenharmony_ci    int fPlane = -1;
21cb93a386Sopenharmony_ci    /** The channel in the plane that contains the Y, U, V, or A value. */
22cb93a386Sopenharmony_ci    SkColorChannel fChannel = SkColorChannel::kA;
23cb93a386Sopenharmony_ci
24cb93a386Sopenharmony_ci    bool operator==(const YUVALocation& that) const {
25cb93a386Sopenharmony_ci        return fPlane == that.fPlane && fChannel == that.fChannel;
26cb93a386Sopenharmony_ci    }
27cb93a386Sopenharmony_ci    bool operator!=(const YUVALocation& that) const { return !(*this == that); }
28cb93a386Sopenharmony_ci
29cb93a386Sopenharmony_ci    static bool AreValidLocations(const SkYUVAInfo::YUVALocations& locations,
30cb93a386Sopenharmony_ci                                  int* numPlanes = nullptr) {
31cb93a386Sopenharmony_ci        int maxSlotUsed = -1;
32cb93a386Sopenharmony_ci        bool used[SkYUVAInfo::kMaxPlanes] = {};
33cb93a386Sopenharmony_ci        bool valid = true;
34cb93a386Sopenharmony_ci        for (int i = 0; i < SkYUVAInfo::kYUVAChannelCount; ++i) {
35cb93a386Sopenharmony_ci            if (locations[i].fPlane < 0) {
36cb93a386Sopenharmony_ci                if (i != SkYUVAInfo::YUVAChannels::kA) {
37cb93a386Sopenharmony_ci                    valid = false;  // only the 'A' plane can be omitted
38cb93a386Sopenharmony_ci                }
39cb93a386Sopenharmony_ci            } else if (locations[i].fPlane >= SkYUVAInfo::kMaxPlanes) {
40cb93a386Sopenharmony_ci                valid = false;  // A maximum of four input textures is allowed
41cb93a386Sopenharmony_ci            } else {
42cb93a386Sopenharmony_ci                maxSlotUsed = std::max(locations[i].fPlane, maxSlotUsed);
43cb93a386Sopenharmony_ci                used[i] = true;
44cb93a386Sopenharmony_ci            }
45cb93a386Sopenharmony_ci        }
46cb93a386Sopenharmony_ci
47cb93a386Sopenharmony_ci        // All the used slots should be packed starting at 0 with no gaps
48cb93a386Sopenharmony_ci        for (int i = 0; i <= maxSlotUsed; ++i) {
49cb93a386Sopenharmony_ci            if (!used[i]) {
50cb93a386Sopenharmony_ci                valid = false;
51cb93a386Sopenharmony_ci            }
52cb93a386Sopenharmony_ci        }
53cb93a386Sopenharmony_ci
54cb93a386Sopenharmony_ci        if (numPlanes) {
55cb93a386Sopenharmony_ci            *numPlanes = valid ? maxSlotUsed + 1 : 0;
56cb93a386Sopenharmony_ci        }
57cb93a386Sopenharmony_ci        return valid;
58cb93a386Sopenharmony_ci    }
59cb93a386Sopenharmony_ci};
60cb93a386Sopenharmony_ci
61cb93a386Sopenharmony_ci#endif
62