1 /*
2 * Copyright (c) 2021 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 <cinttypes>
17 #include <cstdio>
18 #include <cstdlib>
19 #include <fstream>
20 #include <memory>
21 #include <securec.h>
22 #include <sstream>
23 #include <unistd.h>
24
25 #include <sync_fence.h>
26
27 #include <event_handler.h>
28 #include <surface.h>
29 #include "hdi_backend.h"
30 #include "hdi_layer.h"
31 #include "hdi_layer_info.h"
32 #include "hdi_output.h"
33 #include "hdi_screen.h"
34
35 #include "draw/color.h"
36 #include "draw/brush.h"
37 #include "draw/canvas.h"
38 #include "draw/pen.h"
39 #include "draw/path.h"
40 #include "draw/clip.h"
41 #include "effect/path_effect.h"
42 #include "effect/shader_effect.h"
43 #include "image/bitmap.h"
44 #include "image/image.h"
45 #include "utils/rect.h"
46
47 #include "utils/matrix.h"
48 #include "utils/camera3d.h"
49
50 using namespace OHOS;
51 using namespace Rosen;
52 using namespace Drawing;
53
54 namespace {
55 /*
56 * base layer: status bar/launcher/navigation bar
57 */
58 constexpr uint32_t BASE_LAYER_NUM = 3;
59 }
60
61 class HelloDrawing : public IBufferConsumerListenerClazz {
62 public:
63 void Init(uint32_t width, uint32_t height, HdiBackend* backend);
64 void DoDrawData(void *image, uint32_t width, uint32_t height);
65 void DoDrawBaseData(void *image, uint32_t width, uint32_t height, uint32_t index);
66 void Draw();
67 void DrawSurface();
68 void Sync(int64_t, void *data);
69 void CreatePyhsicalScreen();
70 void DoPrepareCompleted(sptr<Surface>& surface, const struct PrepareCompleteParam ¶m);
71 void OnBufferAvailable() override;
72 SurfaceError ProduceBuffer(sptr<Surface> &produceSurface, uint32_t width,
73 uint32_t height, uint32_t index, bool baseLayer);
74 bool FillBaseLayer(std::shared_ptr<HdiLayerInfo> &showLayer, uint32_t index, uint32_t zorder,
75 GraphicIRect &dstRect);
76 bool DrawBaseLayer(std::vector<LayerInfoPtr> &layerVec);
77 void CreateBaseSurface(uint32_t index);
78 void OnHotPlugEvent(std::shared_ptr<HdiOutput> &output, bool connected);
79
80 void TestDrawPathPro(Canvas &canvas, uint32_t width, uint32_t height);
81 void TestDrawImage(Canvas &canvas, uint32_t width, uint32_t height);
82
83 uint32_t freq_ = 30;
84 uint32_t width_ = 0;
85 uint32_t height_ = 0;
86
87 uint32_t display_w = 480;
88 uint32_t display_h = 960;
89
90 bool initDeviceFinished_ = false;
91 bool deviceConnected_ = false;
92 std::shared_ptr<HdiOutput> output = nullptr;
93
94 private:
95 uint32_t currentModeIndex_ = 0;
96 std::vector<GraphicDisplayModeInfo> displayModeInfos_;
97 std::vector<uint32_t> baseWidthVec_;
98 std::vector<uint32_t> baseHeightVec_;
99 std::unique_ptr<HdiScreen> screen = nullptr;
100
101 std::vector<sptr<Surface>> basePSurfaceVec_;
102 std::vector<sptr<Surface>> baseCSurfaceVec_;
103
104 HdiBackend* backend = nullptr;
105
106 bool ready = false;
107 };
108
OnBufferAvailable()109 void HelloDrawing::OnBufferAvailable()
110 {
111 }
112
TestDrawPathPro(Canvas & canvas,uint32_t width,uint32_t height)113 void HelloDrawing::TestDrawPathPro(Canvas &canvas, uint32_t width, uint32_t height)
114 {
115 int len = 300;
116 Point a(500, 500); // point position
117
118 Point c;
119 Point d;
120
121 d.SetX(a.GetX() - len * std::sin(18.0f)); // degree is 18
122 d.SetY(a.GetY() + len * std::cos(18.0f)); // degree is 18
123
124 c.SetX(a.GetX() + len * std::sin(18.0f)); // degree is 18
125 c.SetY(d.GetY());
126
127 Point b;
128 b.SetX(a.GetX() + (len / 2.0));
129 b.SetY(a.GetY() + std::sqrt((c.GetX() - d.GetX()) * (c.GetX() - d.GetX()) + (len / 2.0) * (len / 2.0)));
130
131 Point e;
132 e.SetX(a.GetX() - (len / 2.0));
133 e.SetY(b.GetY());
134
135 Path path;
136 path.MoveTo(a.GetX(), a.GetY());
137 path.LineTo(b.GetX(), b.GetY());
138 path.LineTo(c.GetX(), c.GetY());
139 path.LineTo(d.GetX(), d.GetY());
140 path.LineTo(e.GetX(), e.GetY());
141 path.Close();
142
143 Pen pen;
144 pen.SetAntiAlias(true);
145 pen.SetColor(Drawing::Color::COLOR_RED);
146 pen.SetWidth(10); // The thickness of the pen is 10
147 canvas.AttachPen(pen);
148
149 Brush brush;
150 brush.SetColor(Drawing::Color::COLOR_BLUE);
151 canvas.AttachBrush(brush);
152
153 canvas.DrawPath(path);
154 }
155
TestDrawImage(Canvas & canvas,uint32_t width,uint32_t height)156 void HelloDrawing::TestDrawImage(Canvas& canvas, uint32_t width, uint32_t height)
157 {
158 LOGI("+++++++ TestDrawImage");
159 Bitmap bmp;
160 BitmapFormat format {COLORTYPE_RGBA_8888, ALPHATYPE_OPAQUE};
161 bmp.Build(300, 300, format); // bitmap width and height
162 bmp.ClearWithColor(Drawing::Color::COLOR_BLUE);
163
164 Image image;
165 image.BuildFromBitmap(bmp);
166 int imageWidth = image.GetWidth();
167 int imageHeight = image.GetHeight();
168 LOGI("image width = %{public}d, image height = %{public}d", imageWidth, imageHeight);
169 Matrix matrix;
170 // Set matrix to rotate by degrees 45 about a pivot point at (0, 0).
171 matrix.Rotate(45, 0, 0);
172 auto e = ShaderEffect::CreateImageShader(image, TileMode::REPEAT, TileMode::MIRROR, SamplingOptions(), matrix);
173 auto c = Drawing::ColorSpace::CreateRefImage(image);
174
175 Pen pen;
176 pen.SetAntiAlias(true);
177 pen.SetColor(Drawing::Color::COLOR_BLUE);
178 pen.SetColor(pen.GetColor4f(), c);
179 pen.SetWidth(10); // The thickness of the pen is 10
180 pen.SetShaderEffect(e);
181 canvas.AttachPen(pen);
182 canvas.DrawImage(image, 500, 500, SamplingOptions()); // draw image at (500,500)
183
184 LOGI("------- TestDrawImage");
185 }
186
DoDrawData(void * image,uint32_t width,uint32_t height)187 void HelloDrawing::DoDrawData(void *image, uint32_t width, uint32_t height)
188 {
189 Bitmap bitmap;
190 BitmapFormat format {COLORTYPE_RGBA_8888, ALPHATYPE_OPAQUE};
191 bitmap.Build(width, height, format);
192
193 Canvas canvas;
194 canvas.Bind(bitmap);
195 canvas.Clear(Color::COLOR_WHITE);
196
197 TestDrawImage(canvas, width, height);
198 constexpr uint32_t stride = 4;
199 int32_t addrSize = width * height * stride;
200 auto ret = memcpy_s(image, addrSize, bitmap.GetPixels(), addrSize);
201 if (ret != EOK) {
202 LOGE("memcpy_s failed");
203 }
204 }
205
DoDrawBaseData(void * image,uint32_t width,uint32_t height,uint32_t index)206 void HelloDrawing::DoDrawBaseData(void *image, uint32_t width, uint32_t height, uint32_t index)
207 {
208 Bitmap bitmap;
209 BitmapFormat format {COLORTYPE_RGBA_8888, ALPHATYPE_OPAQUE};
210 bitmap.Build(width, height, format);
211
212 Canvas canvas;
213 canvas.Bind(bitmap);
214 canvas.Clear(Color::COLOR_RED);
215 if (index == 1) {
216 canvas.Clear(Color::COLOR_WHITE);
217 TestDrawImage(canvas, width, height);
218 }
219 constexpr uint32_t stride = 4;
220 int32_t addrSize = width * height * stride;
221 auto ret = memcpy_s(image, addrSize, bitmap.GetPixels(), addrSize);
222 if (ret != EOK) {
223 LOGE("memcpy_s failed");
224 }
225 }
226
ProduceBuffer(sptr<Surface> & produceSurface,uint32_t width,uint32_t height,uint32_t index,bool baseLayer)227 SurfaceError HelloDrawing::ProduceBuffer(sptr<Surface> &produceSurface, uint32_t width,
228 uint32_t height, uint32_t index, bool baseLayer)
229 {
230 OHOS::sptr<SurfaceBuffer> buffer;
231 int32_t releaseFence = -1;
232 BufferRequestConfig config = {
233 .width = width,
234 .height = height,
235 .strideAlignment = 0x8,
236 .format = GRAPHIC_PIXEL_FMT_RGBA_8888,
237 .usage = produceSurface->GetDefaultUsage(),
238 };
239
240 SurfaceError ret = produceSurface->RequestBuffer(buffer, releaseFence, config);
241 if (ret != 0) {
242 LOGE("RequestBuffer failed: %{public}s", SurfaceErrorStr(ret).c_str());
243 return ret;
244 }
245
246 sptr<SyncFence> tempFence = new SyncFence(releaseFence);
247 tempFence->Wait(100); // 100ms
248
249 if (buffer == nullptr) {
250 LOGE("%s: buffer is nullptr", __func__);
251 return SURFACE_ERROR_NULLPTR;
252 }
253
254 LOGI("ProduceBuffer: width: %{public}d height:%{public}d stride:%{public}d size:%{public}d",
255 buffer->GetWidth(), buffer->GetHeight(), buffer->GetBufferHandle()->stride, buffer->GetSize());
256
257 auto addr = static_cast<uint8_t *>(buffer->GetVirAddr());
258 if (baseLayer) {
259 DoDrawBaseData(addr, buffer->GetWidth(), buffer->GetHeight(), index);
260 } else {
261 DoDrawData(addr, buffer->GetWidth(), buffer->GetHeight());
262 }
263
264 BufferFlushConfig flushConfig = {
265 .damage = {
266 .w = width,
267 .h = height,
268 },
269 };
270
271 int32_t acquireFence = -1;
272 ret = produceSurface->FlushBuffer(buffer, acquireFence, flushConfig);
273
274 LOGI("Sync %{public}s", SurfaceErrorStr(ret).c_str());
275 return SURFACE_ERROR_OK;
276 }
277
Draw()278 void HelloDrawing::Draw()
279 {
280 static int32_t count = 0;
281
282 do {
283 std::vector<LayerInfoPtr> layerVec;
284 layerVec.resize(BASE_LAYER_NUM);
285 for (uint32_t i = 0; i < BASE_LAYER_NUM; i++) {
286 std::shared_ptr<HdiLayerInfo> showLayer = HdiLayerInfo::CreateHdiLayerInfo();
287 layerVec[i] = showLayer;
288 }
289
290 if (BASE_LAYER_NUM == 3) {
291 if (!DrawBaseLayer(layerVec)) {
292 continue;
293 }
294 }
295
296 output->SetLayerInfo(layerVec);
297
298 GraphicIRect damageRect;
299 damageRect.x = 0; // Absolute coordinates, with offset
300 damageRect.y = 0;
301 damageRect.w = display_w;
302 damageRect.h = display_h;
303 std::vector<GraphicIRect> outputDamages;
304 outputDamages.emplace_back(damageRect);
305 output->SetOutputDamages(outputDamages);
306
307 backend->Repaint(output);
308 for (uint32_t i = 0; i < BASE_LAYER_NUM; i++) {
309 int32_t releaseFence = -1;
310 sptr<SyncFence> tempFence = new SyncFence(releaseFence);
311 baseCSurfaceVec_[i]->ReleaseBuffer(baseCSurfaceVec_[i]->GetBuffer(), tempFence);
312 tempFence->Wait(100); // 100 ms
313 }
314
315 count++;
316 #ifdef DEBUG_DUMP
317 std::string result;
318 output->Dump(result);
319 LOGI("Dump layer result after ReleaseBuffer : %{public}s", result.c_str());
320 #endif
321 } while (false);
322 }
323
DrawBaseLayer(std::vector<LayerInfoPtr> & layerVec)324 bool HelloDrawing::DrawBaseLayer(std::vector<LayerInfoPtr> &layerVec)
325 {
326 // status bar
327 int32_t zorder = 1;
328 GraphicIRect dstRect;
329 dstRect.x = 0; // Absolute coordinates, with offset
330 dstRect.y = 0;
331 dstRect.w = baseWidthVec_[0];
332 dstRect.h = baseHeightVec_[0];
333 if (!FillBaseLayer(layerVec[0], 0, zorder, dstRect)) {
334 return false;
335 }
336
337 // launcher
338 zorder = 0;
339 dstRect.x = 0; // Absolute coordinates, with offset
340 dstRect.y = 112;
341 dstRect.w = baseWidthVec_[1];
342 dstRect.h = baseHeightVec_[1];
343 if (!FillBaseLayer(layerVec[1], 1, zorder, dstRect)) {
344 return false;
345 }
346
347 // navigation bar
348 zorder = 1;
349 dstRect.x = 0; // Absolute coordinates, with offset
350 dstRect.y = 1488;
351 dstRect.w = baseWidthVec_[2];
352 dstRect.h = baseHeightVec_[2];
353 if (!FillBaseLayer(layerVec[2], 2, zorder, dstRect)) {
354 return false;
355 }
356
357 return true;
358 }
359
FillBaseLayer(std::shared_ptr<HdiLayerInfo> & showLayer,uint32_t index,uint32_t zorder,GraphicIRect & dstRect)360 bool HelloDrawing::FillBaseLayer(std::shared_ptr<HdiLayerInfo> &showLayer, uint32_t index,
361 uint32_t zorder, GraphicIRect &dstRect)
362 {
363 sptr<Surface> pSurface = basePSurfaceVec_[index];
364 sptr<Surface> cSurface = baseCSurfaceVec_[index];
365
366 if (ProduceBuffer(pSurface, dstRect.w, dstRect.h, index, true) != SURFACE_ERROR_OK) {
367 LOGE("Produce cBuffer failed");
368 return false;
369 }
370
371 OHOS::sptr<SurfaceBuffer> cbuffer = nullptr;
372 int32_t fence;
373 int64_t timestamp;
374 OHOS::Rect damage;
375 SurfaceError ret = cSurface->AcquireBuffer(cbuffer, fence, timestamp, damage);
376 if (ret != SURFACE_ERROR_OK) {
377 LOGE("Acquire cBuffer failed");
378 return false;
379 }
380
381 GraphicIRect srcRect;
382 srcRect.x = 0;
383 srcRect.y = 0;
384 srcRect.w = dstRect.w;
385 srcRect.h = dstRect.h;
386
387 GraphicLayerAlpha alpha = { .enPixelAlpha = true };
388
389 showLayer->SetSurface(cSurface);
390 showLayer->SetBuffer(cbuffer, fence);
391 showLayer->SetZorder(zorder);
392 showLayer->SetAlpha(alpha);
393 // if rotate is not null, SetTransform
394 showLayer->SetCompositionType(GraphicCompositionType::GRAPHIC_COMPOSITION_DEVICE);
395 std::vector<GraphicIRect> visibleRegions;
396 visibleRegions.emplace_back(srcRect);
397 showLayer->SetVisibleRegions(visibleRegions);
398 std::vector<GraphicIRect> dirtyRegions;
399 dirtyRegions.emplace_back(srcRect);
400 showLayer->SetDirtyRegions(dirtyRegions);
401 showLayer->SetLayerSize(dstRect);
402 showLayer->SetBlendType(GraphicBlendType::GRAPHIC_BLEND_SRC);
403 showLayer->SetCropRect(srcRect);
404 showLayer->SetPreMulti(false);
405
406 return true;
407 }
408
Sync(int64_t,void * data)409 void HelloDrawing::Sync(int64_t, void *data)
410 {
411 struct OHOS::FrameCallback cb = {
412 .frequency_ = freq_,
413 .timestamp_ = 0,
414 .userdata_ = data,
415 .callback_ = std::bind(&HelloDrawing::Sync, this, SYNC_FUNC_ARG),
416 };
417
418 OHOS::VsyncError ret = OHOS::VsyncHelper::Current()->RequestFrameCallback(cb);
419 if (ret) {
420 LOGE("RequestFrameCallback inner %{public}d\n", ret);
421 }
422
423 if (!ready) {
424 return;
425 }
426
427 Draw();
428 }
429
Init(uint32_t width,uint32_t height,HdiBackend * backend)430 void HelloDrawing::Init(uint32_t width, uint32_t height, HdiBackend* backend)
431 {
432 this->backend = backend;
433
434 baseWidthVec_.resize(BASE_LAYER_NUM);
435 baseHeightVec_.resize(BASE_LAYER_NUM);
436 baseCSurfaceVec_.resize(BASE_LAYER_NUM);
437 basePSurfaceVec_.resize(BASE_LAYER_NUM);
438
439 if (BASE_LAYER_NUM == 3) {
440 baseWidthVec_[0] = 2560;
441 baseWidthVec_[1] = 2560;
442 baseWidthVec_[2] = 2560;
443 baseHeightVec_[0] = 112;
444 baseHeightVec_[1] = 1376;
445 baseHeightVec_[2] = 112;
446 }
447
448 for (uint32_t i = 0; i < BASE_LAYER_NUM; i++) {
449 CreateBaseSurface(i);
450 }
451 Sync(0, nullptr);
452 }
453
CreateBaseSurface(uint32_t index)454 void HelloDrawing::CreateBaseSurface(uint32_t index)
455 {
456 sptr<IConsumerSurface> cSurface = IConsumerSurface::Create();
457 cSurface->SetDefaultWidthAndHeight(baseWidthVec_[index], baseHeightVec_[index]);
458 cSurface->SetDefaultUsage(BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA);
459
460 sptr<IBufferProducer> producer = cSurface->GetProducer();
461 sptr<Surface> pSurface = Surface::CreateSurfaceAsProducer(producer);
462 cSurface->RegisterConsumerListener(this);
463
464 baseCSurfaceVec_[index] = cSurface;
465 basePSurfaceVec_[index] = pSurface;
466 }
467
CreatePyhsicalScreen()468 void HelloDrawing::CreatePyhsicalScreen()
469 {
470 screen = HdiScreen::CreateHdiScreen(output->GetScreenId());
471 screen->Init();
472 screen->GetScreenSupportedModes(displayModeInfos_);
473 size_t supportModeNum = displayModeInfos_.size();
474 if (supportModeNum > 0) {
475 screen->GetScreenMode(currentModeIndex_);
476 LOGI("currentModeIndex:%{public}d", currentModeIndex_);
477 for (size_t i = 0; i < supportModeNum; i++) {
478 LOGI("modes(%{public}d) %{public}dx%{public}d freq:%{public}d",
479 displayModeInfos_[i].id, displayModeInfos_[i].width,
480 displayModeInfos_[i].height, displayModeInfos_[i].freshRate);
481 if (displayModeInfos_[i].id == static_cast<int32_t>(currentModeIndex_)) {
482 this->freq_ = displayModeInfos_[i].freshRate;
483 this->display_w = displayModeInfos_[i].width;
484 this->display_h = displayModeInfos_[i].height;
485 break;
486 }
487 }
488 screen->SetScreenPowerStatus(GraphicDispPowerStatus::GRAPHIC_POWER_STATUS_ON);
489 screen->SetScreenMode(currentModeIndex_);
490 LOGI("SetScreenMode: currentModeIndex(%{public}d)", currentModeIndex_);
491
492 GraphicDispPowerStatus powerState;
493 screen->SetScreenPowerStatus(GraphicDispPowerStatus::GRAPHIC_POWER_STATUS_ON);
494 screen->GetScreenPowerStatus(powerState);
495 LOGI("get poweState:%{public}d", powerState);
496 }
497
498 GraphicDisplayCapability info;
499 screen->GetScreenCapability(info);
500 LOGI("GetScreenCapability: name(%{public}s), type(%{public}d), phyWidth(%{public}d), phyHeight(%{public}d)",
501 info.name, info.type, info.phyWidth, info.phyHeight);
502 LOGI("GetScreenCapability: supportLayers(%{public}d), virtualDispCount(%{public}d)",
503 info.supportLayers, info.virtualDispCount);
504 LOGI("GetScreenCapability: supportWriteBack(%{public}d), propertyCount(%{public}d)",
505 info.supportWriteBack, info.propertyCount);
506 ready = true;
507 }
508
OnScreenPlug(std::shared_ptr<HdiOutput> & output,bool connected,void * data)509 static void OnScreenPlug(std::shared_ptr<HdiOutput> &output, bool connected, void* data)
510 {
511 LOGI("enter OnScreenPlug, connected is %{public}d", connected);
512 auto* thisPtr = static_cast<HelloDrawing *>(data);
513 thisPtr->OnHotPlugEvent(output, connected);
514 }
515
OnHotPlugEvent(std::shared_ptr<HdiOutput> & output,bool connected)516 void HelloDrawing::OnHotPlugEvent(std::shared_ptr<HdiOutput> &output, bool connected)
517 {
518 /*
519 * Currently, IPC communication cannot be nested. Therefore, Vblank registration can be
520 * initiated only after the initialization of the device is complete.
521 */
522 this->output = output;
523 deviceConnected_ = connected;
524
525 if (!initDeviceFinished_) {
526 LOGI("Init the device has not finished yet");
527 return;
528 }
529
530 LOGI("Callback HotPlugEvent, connected is %{public}u", connected);
531
532 if (connected) {
533 CreatePyhsicalScreen();
534 }
535 }
536
DoPrepareCompleted(sptr<Surface> & surface,const struct PrepareCompleteParam & param)537 void HelloDrawing::DoPrepareCompleted(sptr<Surface>& surface, const struct PrepareCompleteParam ¶m)
538 {
539 BufferRequestConfig requestConfig = {
540 .width = display_w, // need display width
541 .height = display_h, // need display height
542 .strideAlignment = 0x8,
543 .format = GRAPHIC_PIXEL_FMT_BGRA_8888,
544 .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA | BUFFER_USAGE_MEM_FB,
545 .timeout = 0,
546 };
547
548 if (surface == nullptr) {
549 LOGE("surface is null");
550 return;
551 }
552
553 int32_t releaseFence = -1;
554 sptr<SurfaceBuffer> fbBuffer = nullptr;
555 SurfaceError ret = surface->RequestBuffer(fbBuffer, releaseFence, requestConfig);
556 if (ret != 0) {
557 LOGE("RequestBuffer failed: %{public}s", SurfaceErrorStr(ret).c_str());
558 return;
559 }
560
561 sptr<SyncFence> tempFence = new SyncFence(releaseFence);
562 tempFence->Wait(100); // 100ms
563
564 uint32_t clientCount = 0;
565 bool hasClient = false;
566 const std::vector<LayerInfoPtr> &layers = param.layers;
567 for (const LayerInfoPtr &layer : layers) {
568 if (layer->GetCompositionType() == GraphicCompositionType::GRAPHIC_COMPOSITION_CLIENT) {
569 hasClient = true;
570 clientCount++;
571 }
572 }
573
574 LOGI("fb fence is %{public}d, clientCount is %{public}d", releaseFence, clientCount);
575
576 auto addr = static_cast<uint8_t *>(fbBuffer->GetVirAddr());
577 if (hasClient) {
578 DoDrawData(addr, fbBuffer->GetWidth(), fbBuffer->GetHeight());
579 } else {
580 int32_t ret = memset_s(addr, fbBuffer->GetSize(), 0, fbBuffer->GetSize());
581 if (ret != 0) {
582 LOGE("memset_s failed");
583 }
584 }
585
586 BufferFlushConfig flushConfig = {
587 .damage = {
588 .w = display_w,
589 .h = display_h,
590 }
591 };
592
593 /*
594 * if use GPU produce data, flush with gpu fence
595 */
596 ret = surface->FlushBuffer(fbBuffer, -1, flushConfig);
597 if (ret != 0) {
598 LOGE("FlushBuffer failed: %{public}s", SurfaceErrorStr(ret).c_str());
599 }
600 }
601
OnPrepareCompleted(sptr<Surface> & surface,const struct PrepareCompleteParam & param,void * data)602 static void OnPrepareCompleted(
603 sptr<Surface> &surface, const struct PrepareCompleteParam ¶m, void* data)
604 {
605 if (!param.needFlushFramebuffer) {
606 return;
607 }
608
609 if (surface == nullptr) {
610 return;
611 }
612
613 if (data == nullptr) {
614 return;
615 }
616
617 LOGI("OnPrepareCompleted param.layer size is %{public}d", param.layers.size());
618 auto* thisPtr = static_cast<HelloDrawing *>(data);
619 thisPtr->DoPrepareCompleted(surface, param);
620 }
621
main(int32_t argc,const char * argv[])622 int32_t main(int32_t argc, const char *argv[])
623 {
624 HelloDrawing m;
625
626 LOGI("start to HdiBackend::GetInstance");
627 HdiBackend* backend = OHOS::Rosen::HdiBackend::GetInstance();
628 if (backend == nullptr) {
629 LOGE("HdiBackend::GetInstance fail");
630 return -1;
631 }
632
633 backend->RegScreenHotplug(OnScreenPlug, &m);
634 while (1) {
635 if (m.output != nullptr) {
636 break;
637 }
638 }
639
640 if (!m.initDeviceFinished_) {
641 if (m.deviceConnected_) {
642 m.CreatePyhsicalScreen();
643 }
644 m.initDeviceFinished_ = true;
645 }
646 LOGI("Init screen succeed");
647
648 backend->RegPrepareComplete(OnPrepareCompleted, &m);
649
650 m.width_ = 480; // display width
651 m.height_ = 960; // display height
652 sleep(1); // wait 1s
653
654 auto runner = OHOS::AppExecFwk::EventRunner::Create(false);
655 auto handler = std::make_shared<OHOS::AppExecFwk::EventHandler>(runner);
656 handler->PostTask(std::bind(&HelloDrawing::Init, &m, m.width_, m.height_, backend));
657 runner->Run();
658 return 0;
659 }
660