1*38e8c45fSAndroid Build Coastguard Worker /** 2*38e8c45fSAndroid Build Coastguard Worker * Copyright (C) 2023 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 // #define LOG_NDEBUG 0 18*38e8c45fSAndroid Build Coastguard Worker #pragma once 19*38e8c45fSAndroid Build Coastguard Worker 20*38e8c45fSAndroid Build Coastguard Worker #include "BackgroundExecutor.h" 21*38e8c45fSAndroid Build Coastguard Worker 22*38e8c45fSAndroid Build Coastguard Worker #pragma clang diagnostic push 23*38e8c45fSAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wconversion" 24*38e8c45fSAndroid Build Coastguard Worker #include <SkCanvas.h> 25*38e8c45fSAndroid Build Coastguard Worker #include <SkPaint.h> 26*38e8c45fSAndroid Build Coastguard Worker #pragma clang diagnostic pop 27*38e8c45fSAndroid Build Coastguard Worker 28*38e8c45fSAndroid Build Coastguard Worker #include <gui/SurfaceComposerClient.h> 29*38e8c45fSAndroid Build Coastguard Worker #include <utils/StrongPointer.h> 30*38e8c45fSAndroid Build Coastguard Worker 31*38e8c45fSAndroid Build Coastguard Worker namespace android { 32*38e8c45fSAndroid Build Coastguard Worker 33*38e8c45fSAndroid Build Coastguard Worker inline constexpr int kDigitWidth = 64; 34*38e8c45fSAndroid Build Coastguard Worker inline constexpr int kDigitHeight = 100; 35*38e8c45fSAndroid Build Coastguard Worker inline constexpr int kDigitSpace = 16; 36*38e8c45fSAndroid Build Coastguard Worker 37*38e8c45fSAndroid Build Coastguard Worker // HdrSdrRatioOverlay re-uses this value though it doesn't really need such amount buffer. 38*38e8c45fSAndroid Build Coastguard Worker // for output good-looking and code conciseness. 39*38e8c45fSAndroid Build Coastguard Worker inline constexpr int kMaxDigits = /*displayFps*/ 3 + /*renderFps*/ 3 + /*spinner*/ 1; 40*38e8c45fSAndroid Build Coastguard Worker inline constexpr int kBufferWidth = kMaxDigits * kDigitWidth + (kMaxDigits - 1) * kDigitSpace; 41*38e8c45fSAndroid Build Coastguard Worker inline constexpr int kBufferHeight = kDigitHeight; 42*38e8c45fSAndroid Build Coastguard Worker 43*38e8c45fSAndroid Build Coastguard Worker class SurfaceControl; 44*38e8c45fSAndroid Build Coastguard Worker 45*38e8c45fSAndroid Build Coastguard Worker // Helper class to delete the SurfaceControl on a helper thread as 46*38e8c45fSAndroid Build Coastguard Worker // SurfaceControl assumes its destruction happens without SurfaceFlinger::mStateLock held. 47*38e8c45fSAndroid Build Coastguard Worker class SurfaceControlHolder { 48*38e8c45fSAndroid Build Coastguard Worker public: SurfaceControlHolder(sp<SurfaceControl> sc)49*38e8c45fSAndroid Build Coastguard Worker explicit SurfaceControlHolder(sp<SurfaceControl> sc) : mSurfaceControl(std::move(sc)){}; 50*38e8c45fSAndroid Build Coastguard Worker ~SurfaceControlHolder()51*38e8c45fSAndroid Build Coastguard Worker ~SurfaceControlHolder() { 52*38e8c45fSAndroid Build Coastguard Worker // Hand the sp<SurfaceControl> to the helper thread to release the last 53*38e8c45fSAndroid Build Coastguard Worker // reference. This makes sure that the SurfaceControl is destructed without 54*38e8c45fSAndroid Build Coastguard Worker // SurfaceFlinger::mStateLock held. 55*38e8c45fSAndroid Build Coastguard Worker BackgroundExecutor::getInstance().sendCallbacks( 56*38e8c45fSAndroid Build Coastguard Worker {[sc = std::move(mSurfaceControl)]() mutable { sc.clear(); }}); 57*38e8c45fSAndroid Build Coastguard Worker } 58*38e8c45fSAndroid Build Coastguard Worker createSurfaceControlHolder(const String8 & name)59*38e8c45fSAndroid Build Coastguard Worker static std::unique_ptr<SurfaceControlHolder> createSurfaceControlHolder(const String8& name) { 60*38e8c45fSAndroid Build Coastguard Worker sp<SurfaceControl> surfaceControl = 61*38e8c45fSAndroid Build Coastguard Worker SurfaceComposerClient::getDefault() 62*38e8c45fSAndroid Build Coastguard Worker ->createSurface(name, kBufferWidth, kBufferHeight, PIXEL_FORMAT_RGBA_8888, 63*38e8c45fSAndroid Build Coastguard Worker ISurfaceComposerClient::eFXSurfaceBufferState); 64*38e8c45fSAndroid Build Coastguard Worker return std::make_unique<SurfaceControlHolder>(std::move(surfaceControl)); 65*38e8c45fSAndroid Build Coastguard Worker } 66*38e8c45fSAndroid Build Coastguard Worker get()67*38e8c45fSAndroid Build Coastguard Worker const sp<SurfaceControl>& get() const { return mSurfaceControl; } 68*38e8c45fSAndroid Build Coastguard Worker 69*38e8c45fSAndroid Build Coastguard Worker private: 70*38e8c45fSAndroid Build Coastguard Worker sp<SurfaceControl> mSurfaceControl; 71*38e8c45fSAndroid Build Coastguard Worker }; 72*38e8c45fSAndroid Build Coastguard Worker 73*38e8c45fSAndroid Build Coastguard Worker // Helper class to draw digit and decimal point. 74*38e8c45fSAndroid Build Coastguard Worker class SegmentDrawer { 75*38e8c45fSAndroid Build Coastguard Worker public: 76*38e8c45fSAndroid Build Coastguard Worker enum class Segment { 77*38e8c45fSAndroid Build Coastguard Worker Upper, 78*38e8c45fSAndroid Build Coastguard Worker UpperLeft, 79*38e8c45fSAndroid Build Coastguard Worker UpperRight, 80*38e8c45fSAndroid Build Coastguard Worker Middle, 81*38e8c45fSAndroid Build Coastguard Worker LowerLeft, 82*38e8c45fSAndroid Build Coastguard Worker LowerRight, 83*38e8c45fSAndroid Build Coastguard Worker Bottom, 84*38e8c45fSAndroid Build Coastguard Worker DecimalPoint 85*38e8c45fSAndroid Build Coastguard Worker }; drawSegment(Segment segment,int left,SkColor color,SkCanvas & canvas)86*38e8c45fSAndroid Build Coastguard Worker static void drawSegment(Segment segment, int left, SkColor color, SkCanvas& canvas) { 87*38e8c45fSAndroid Build Coastguard Worker const SkRect rect = [&]() { 88*38e8c45fSAndroid Build Coastguard Worker switch (segment) { 89*38e8c45fSAndroid Build Coastguard Worker case Segment::Upper: 90*38e8c45fSAndroid Build Coastguard Worker return SkRect::MakeLTRB(left, 0, left + kDigitWidth, kDigitSpace); 91*38e8c45fSAndroid Build Coastguard Worker case Segment::UpperLeft: 92*38e8c45fSAndroid Build Coastguard Worker return SkRect::MakeLTRB(left, 0, left + kDigitSpace, kDigitHeight / 2.); 93*38e8c45fSAndroid Build Coastguard Worker case Segment::UpperRight: 94*38e8c45fSAndroid Build Coastguard Worker return SkRect::MakeLTRB(left + kDigitWidth - kDigitSpace, 0, left + kDigitWidth, 95*38e8c45fSAndroid Build Coastguard Worker kDigitHeight / 2.); 96*38e8c45fSAndroid Build Coastguard Worker case Segment::Middle: 97*38e8c45fSAndroid Build Coastguard Worker return SkRect::MakeLTRB(left, kDigitHeight / 2. - kDigitSpace / 2., 98*38e8c45fSAndroid Build Coastguard Worker left + kDigitWidth, 99*38e8c45fSAndroid Build Coastguard Worker kDigitHeight / 2. + kDigitSpace / 2.); 100*38e8c45fSAndroid Build Coastguard Worker case Segment::LowerLeft: 101*38e8c45fSAndroid Build Coastguard Worker return SkRect::MakeLTRB(left, kDigitHeight / 2., left + kDigitSpace, 102*38e8c45fSAndroid Build Coastguard Worker kDigitHeight); 103*38e8c45fSAndroid Build Coastguard Worker case Segment::LowerRight: 104*38e8c45fSAndroid Build Coastguard Worker return SkRect::MakeLTRB(left + kDigitWidth - kDigitSpace, kDigitHeight / 2., 105*38e8c45fSAndroid Build Coastguard Worker left + kDigitWidth, kDigitHeight); 106*38e8c45fSAndroid Build Coastguard Worker case Segment::Bottom: 107*38e8c45fSAndroid Build Coastguard Worker return SkRect::MakeLTRB(left, kDigitHeight - kDigitSpace, left + kDigitWidth, 108*38e8c45fSAndroid Build Coastguard Worker kDigitHeight); 109*38e8c45fSAndroid Build Coastguard Worker case Segment::DecimalPoint: 110*38e8c45fSAndroid Build Coastguard Worker return SkRect::MakeLTRB(left, kDigitHeight - kDigitSpace, left + kDigitSpace, 111*38e8c45fSAndroid Build Coastguard Worker kDigitHeight); 112*38e8c45fSAndroid Build Coastguard Worker } 113*38e8c45fSAndroid Build Coastguard Worker }(); 114*38e8c45fSAndroid Build Coastguard Worker 115*38e8c45fSAndroid Build Coastguard Worker SkPaint paint; 116*38e8c45fSAndroid Build Coastguard Worker paint.setColor(color); 117*38e8c45fSAndroid Build Coastguard Worker paint.setBlendMode(SkBlendMode::kSrc); 118*38e8c45fSAndroid Build Coastguard Worker canvas.drawRect(rect, paint); 119*38e8c45fSAndroid Build Coastguard Worker } 120*38e8c45fSAndroid Build Coastguard Worker drawDigit(int digit,int left,SkColor color,SkCanvas & canvas)121*38e8c45fSAndroid Build Coastguard Worker static void drawDigit(int digit, int left, SkColor color, SkCanvas& canvas) { 122*38e8c45fSAndroid Build Coastguard Worker if (digit < 0 || digit > 9) return; 123*38e8c45fSAndroid Build Coastguard Worker 124*38e8c45fSAndroid Build Coastguard Worker if (digit == 0 || digit == 2 || digit == 3 || digit == 5 || digit == 6 || digit == 7 || 125*38e8c45fSAndroid Build Coastguard Worker digit == 8 || digit == 9) 126*38e8c45fSAndroid Build Coastguard Worker drawSegment(Segment::Upper, left, color, canvas); 127*38e8c45fSAndroid Build Coastguard Worker if (digit == 0 || digit == 4 || digit == 5 || digit == 6 || digit == 8 || digit == 9) 128*38e8c45fSAndroid Build Coastguard Worker drawSegment(Segment::UpperLeft, left, color, canvas); 129*38e8c45fSAndroid Build Coastguard Worker if (digit == 0 || digit == 1 || digit == 2 || digit == 3 || digit == 4 || digit == 7 || 130*38e8c45fSAndroid Build Coastguard Worker digit == 8 || digit == 9) 131*38e8c45fSAndroid Build Coastguard Worker drawSegment(Segment::UpperRight, left, color, canvas); 132*38e8c45fSAndroid Build Coastguard Worker if (digit == 2 || digit == 3 || digit == 4 || digit == 5 || digit == 6 || digit == 8 || 133*38e8c45fSAndroid Build Coastguard Worker digit == 9) 134*38e8c45fSAndroid Build Coastguard Worker drawSegment(Segment::Middle, left, color, canvas); 135*38e8c45fSAndroid Build Coastguard Worker if (digit == 0 || digit == 2 || digit == 6 || digit == 8) 136*38e8c45fSAndroid Build Coastguard Worker drawSegment(Segment::LowerLeft, left, color, canvas); 137*38e8c45fSAndroid Build Coastguard Worker if (digit == 0 || digit == 1 || digit == 3 || digit == 4 || digit == 5 || digit == 6 || 138*38e8c45fSAndroid Build Coastguard Worker digit == 7 || digit == 8 || digit == 9) 139*38e8c45fSAndroid Build Coastguard Worker drawSegment(Segment::LowerRight, left, color, canvas); 140*38e8c45fSAndroid Build Coastguard Worker if (digit == 0 || digit == 2 || digit == 3 || digit == 5 || digit == 6 || digit == 8 || 141*38e8c45fSAndroid Build Coastguard Worker digit == 9) 142*38e8c45fSAndroid Build Coastguard Worker drawSegment(Segment::Bottom, left, color, canvas); 143*38e8c45fSAndroid Build Coastguard Worker } 144*38e8c45fSAndroid Build Coastguard Worker }; 145*38e8c45fSAndroid Build Coastguard Worker 146*38e8c45fSAndroid Build Coastguard Worker } // namespace android 147