1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <iostream>
17 #include <random>
18 #include <string>
19
20 #include "include/core/SkColor.h"
21 #include "include/core/SkTextBlob.h"
22 #include "refbase.h"
23 #include "render_context/render_context.h"
24 #include "transaction/rs_transaction.h"
25 #include "ui/rs_surface_extractor.h"
26 #include "ui/rs_surface_node.h"
27 #include "wm/window.h"
28
29 namespace OHOS {
30 namespace Rosen {
31 namespace Test {
32 constexpr int DEFAULT_DISPLAY_ID = 0;
33 constexpr int WINDOW_LEFT = 100;
34 constexpr int WINDOW_TOP = 200;
35 constexpr int WINDOW_WIDTH = 360;
36 constexpr int WINDOW_HEIGHT = 360;
37 constexpr int BUFFER_WIDTH = 360;
38 constexpr int BUFFER_HEIGHT = 360;
39 constexpr float MIN_SCALE = 0.5f;
40 constexpr float MAX_SCALE = 2.0f;
41
GetRandomScale()42 float GetRandomScale()
43 {
44 static std::random_device seed;
45 std::mt19937_64 gen(seed());
46 std::uniform_real_distribution<> distribution(MIN_SCALE, MAX_SCALE);
47 return distribution(gen);
48 }
49
50 // we can make this demo and run it on the device,
51 // to visualize the surface's scale effects.
52 class RsSurfaceNodeScaleTestDemo {
53 public:
RsSurfaceNodeScaleTestDemo()54 RsSurfaceNodeScaleTestDemo()
55 {
56 #ifdef ACE_ENABLE_GPU
57 renderContext_ = std::make_unique<RenderContext>();
58 renderContext_->InitializeEglContext();
59 #endif // ACE_ENABLE_GPU
60
61 sptr<WindowOption> option(new WindowOption());
62 option->SetDisplayId(DEFAULT_DISPLAY_ID);
63 option->SetWindowRect( {WINDOW_LEFT, WINDOW_TOP, WINDOW_WIDTH, WINDOW_HEIGHT} );
64 option->SetWindowType(WindowType::APP_MAIN_WINDOW_BASE);
65 option->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING);
66 option->SetWindowName("scale_demo");
67 window_ = Window::Create(option->GetWindowName(), option);
68 if (window_ != nullptr) {
69 surfaceNode_ = window_->GetSurfaceNode();
70 // surface bounds is window rect.
71 surfaceNode_->SetBounds(WINDOW_LEFT, WINDOW_TOP, WINDOW_WIDTH, WINDOW_HEIGHT);
72 RSTransaction::FlushImplicitTransaction();
73 window_->Show();
74 } else {
75 std::cout << "Failed to create window!" << std::endl;
76 }
77 }
78
~RsSurfaceNodeScaleTestDemo()79 ~RsSurfaceNodeScaleTestDemo() noexcept
80 {
81 if (window_ != nullptr) {
82 window_->Hide();
83 window_->Destroy();
84 }
85 }
86
Run()87 void Run()
88 {
89 if (surfaceNode_ == nullptr) {
90 return;
91 }
92
93 auto rsSurface = RSSurfaceExtractor::ExtractRSSurface(surfaceNode_);
94 if (rsSurface == nullptr) {
95 return;
96 }
97
98 #ifdef ACE_ENABLE_GPU
99 if (renderContext_ != nullptr) {
100 rsSurface->SetRenderContext(renderContext_.get());
101 }
102 #endif // ACE_ENABLE_GPU
103
104 // test 50 frames.
105 for (int i = 0; i < 50; ++i) {
106 // get random scales and set them with pivot(start point or center point).
107 float scaleX = GetRandomScale();
108 float scaleY = GetRandomScale();
109 surfaceNode_->SetScale(scaleX, scaleY);
110 // default pivot: center
111 float pivotX = 0.5f; // centerX: 0.5
112 float pivotY = 0.5f; // centerY: 0.5
113 std::string pivotInfo = "Pivot: centor(0.5, 0.5)";
114 // make pivot to start point if (i % 2 == 0)
115 if (i % 2 == 0) {
116 pivotX = 0.0f;
117 pivotY = 0.0f;
118 pivotInfo = "Pivot: start(0, 0)";
119 }
120 surfaceNode_->SetPivot(pivotX, pivotY);
121 RSTransaction::FlushImplicitTransaction();
122
123 auto frame = rsSurface->RequestFrame(BUFFER_WIDTH, BUFFER_HEIGHT);
124 if (frame == nullptr) {
125 std::cout << "Failed to create frame!" << std::endl;
126 return;
127 }
128 auto canvas = frame->GetCanvas();
129 if (canvas == nullptr) {
130 std::cout << "Failed to create canvas!" << std::endl;
131 return;
132 }
133 canvas->clear(SK_ColorWHITE);
134 SkPaint paint;
135 paint.setAntiAlias(true);
136 paint.setStyle(SkPaint::kFill_Style);
137 paint.setStrokeWidth(20); // line width: 20
138 paint.setStrokeJoin(SkPaint::kRound_Join);
139 paint.setColor(SK_ColorBLUE);
140 std::string scaleInfo;
141 scaleInfo += ("ScaleX: " + std::to_string(scaleX) + "\n");
142 scaleInfo += ("ScaleY: " + std::to_string(scaleY) + "\n");
143 sk_sp<SkTextBlob> scaleInfoTextBlob = SkTextBlob::MakeFromString(
144 scaleInfo.c_str(), SkFont(nullptr, 16.0f, 1.0f, 0.0f)); // font size: 16
145 canvas->drawTextBlob(scaleInfoTextBlob.get(), 20, 50, paint); // start point is (20, 50)
146 sk_sp<SkTextBlob> pivotInfoTextBlob = SkTextBlob::MakeFromString(
147 pivotInfo.c_str(), SkFont(nullptr, 16.0f, 1.0f, 0.0f)); // font size: 16
148 canvas->drawTextBlob(pivotInfoTextBlob.get(), 20, 100, paint); // start point is (20, 100)
149 frame->SetDamageRegion(0, 0, BUFFER_WIDTH, BUFFER_HEIGHT);
150 rsSurface->FlushFrame(frame);
151
152 sleep(2); // sleep 2s
153 }
154 }
155
156 private:
157 #ifdef ACE_ENABLE_GPU
158 std::unique_ptr<RenderContext> renderContext_;
159 #endif // ACE_ENABLE_GPU
160
161 sptr<Window> window_;
162 std::shared_ptr<RSSurfaceNode> surfaceNode_;
163 };
164 } // namespace Test
165 } // namespace Rosen
166 } // namespace OHOS
167
main()168 int main()
169 {
170 std::cout << "rs surface node scale demo start!" << std::endl;
171 OHOS::Rosen::Test::RsSurfaceNodeScaleTestDemo demo;
172 demo.Run();
173 std::cout << "rs surface node scale demo end!" << std::endl;
174 return 0;
175 }
176