• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "render_context_sample.h"
17 
18 #include "window.h"
19 #include <securec.h>
20 #include <event_handler.h>
21 #include <iostream>
22 
23 using namespace OHOS;
24 using namespace OHOS::Rosen;
25 
Run()26 void RenderContextSample::Run()
27 {
28     std::cout << "start to HdiBackend::GetInstance" << std::endl;
29     backend_ = OHOS::Rosen::HdiBackend::GetInstance();
30     if (backend_ == nullptr) {
31         std::cout << "HdiBackend::GetInstance fail" << std::endl;
32         return;
33     }
34 
35     backend_->RegScreenHotplug(RenderContextSample::OnScreenPlug, this);
36     while (1) {
37         if (output_ != nullptr) {
38             break;
39         }
40     }
41 
42     if (!initDeviceFinished_) {
43         if (deviceConnected_) {
44             CreatePhysicalScreen();
45         }
46         initDeviceFinished_ = true;
47     }
48     std::cout << "Init screen succeed" << std::endl;
49 
50     backend_->RegPrepareComplete(RenderContextSample::OnPrepareCompleted, this);
51 
52     sleep(1);
53 
54     auto runner = OHOS::AppExecFwk::EventRunner::Create(false);
55     auto handler = std::make_shared<OHOS::AppExecFwk::EventHandler>(runner);
56     handler->PostTask(std::bind(&RenderContextSample::Init, this));
57     runner->Run();
58 }
59 
OnScreenPlug(std::shared_ptr<HdiOutput> & output,bool connected,void * data)60 void RenderContextSample::OnScreenPlug(std::shared_ptr<HdiOutput> &output, bool connected, void* data)
61 {
62     std::cout << "enter OnScreenPlug, connected is " << connected << std::endl;
63     auto* thisPtr = static_cast<RenderContextSample *>(data);
64     thisPtr->OnHotPlugEvent(output, connected);
65 }
66 
OnPrepareCompleted(sptr<Surface> & surface,const struct PrepareCompleteParam & param,void * data)67 void RenderContextSample::OnPrepareCompleted(
68     sptr<Surface> &surface, const struct PrepareCompleteParam &param, void* data)
69 {
70     if (!param.needFlushFramebuffer) {
71         return;
72     }
73 
74     if (surface == nullptr) {
75         return;
76     }
77 
78     if (data == nullptr) {
79         return;
80     }
81 
82     std::cout << "OnPrepareCompleted param.layer size is " << (int)param.layers.size() << std::endl;
83     auto* thisPtr = static_cast<RenderContextSample *>(data);
84     thisPtr->DoPrepareCompleted(surface, param);
85 }
86 
InitEGL()87 void RenderContextSample::InitEGL()
88 {
89     renderContext = new RenderContext();
90     renderContext->InitializeEglContext();
91 }
92 
Init()93 void RenderContextSample::Init()
94 {
95     backGroundWidth = 2560;
96     backGroundHeight = 1600;
97 
98     drawingWidth = 1200;
99     drawingHeight = 800;
100 
101     CreateBackGroundSurface();
102 
103     CreateDrawingSurface();
104 
105     InitEGL();
106 
107     Sync(0, nullptr);
108 }
109 
Sync(int64_t,void * data)110 void RenderContextSample::Sync(int64_t, void *data)
111 {
112     struct OHOS::FrameCallback cb = {
113         .frequency_ = freq_,
114         .timestamp_ = 0,
115         .userdata_ = data,
116         .callback_ = std::bind(&RenderContextSample::Sync, this, SYNC_FUNC_ARG),
117     };
118 
119     OHOS::VsyncError ret = OHOS::VsyncHelper::Current()->RequestFrameCallback(cb);
120     if (ret) {
121         std::cout << "RequestFrameCallback inner " <<  ret << std::endl;
122     }
123 
124     if (!ready_) {
125         return;
126     }
127 
128     Draw();
129 }
130 
CreateBackGroundSurface()131 void RenderContextSample::CreateBackGroundSurface()
132 {
133     backGroundCSurface = IConsumerSurface::Create();
134     backGroundCSurface->SetDefaultWidthAndHeight(backGroundWidth, backGroundHeight);
135     backGroundCSurface->SetDefaultUsage(BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA);
136 
137     sptr<IBufferProducer> producer = backGroundCSurface->GetProducer();
138     backGroundPSurface= Surface::CreateSurfaceAsProducer(producer);
139     backGroundCSurface->RegisterConsumerListener(this);
140 
141     prevBufferMap_[backGroundCSurface->GetUniqueId()] = nullptr;
142     prevFenceMap_[backGroundCSurface->GetUniqueId()] = SyncFence::INVALID_FENCE;
143 }
144 
CreateDrawingSurface()145 void RenderContextSample::CreateDrawingSurface()
146 {
147     drawingCSurface = IConsumerSurface::Create();
148     drawingCSurface->SetDefaultWidthAndHeight(backGroundWidth, backGroundHeight);
149     drawingCSurface->SetDefaultUsage(BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA);
150 
151     sptr<IBufferProducer> producer = drawingCSurface->GetProducer();
152     drawingPSurface= Surface::CreateSurfaceAsProducer(producer);
153     drawingCSurface->RegisterConsumerListener(this);
154 
155     prevBufferMap_[drawingCSurface->GetUniqueId()] = nullptr;
156     prevFenceMap_[drawingCSurface->GetUniqueId()] = SyncFence::INVALID_FENCE;
157 }
158 
OnBufferAvailable()159 void RenderContextSample::OnBufferAvailable()
160 {
161 }
162 
ProduceBackGroundBuffer(uint32_t width,uint32_t height)163 SurfaceError RenderContextSample::ProduceBackGroundBuffer(uint32_t width, uint32_t height)
164 {
165     OHOS::sptr<SurfaceBuffer> buffer;
166     int32_t releaseFence = -1;
167     BufferRequestConfig config = {
168         .width = width,
169         .height = height,
170         .strideAlignment = 0x8,
171         .format = GRAPHIC_PIXEL_FMT_RGBA_8888,
172         .usage = backGroundPSurface->GetDefaultUsage(),
173     };
174 
175     SurfaceError ret = backGroundPSurface->RequestBuffer(buffer, releaseFence, config);
176     if (ret != 0) {
177         std::cout << "RequestBuffer failed:" << SurfaceErrorStr(ret).c_str() << std::endl;
178         return ret;
179     }
180 
181     sptr<SyncFence> tempFence = new SyncFence(releaseFence);
182     tempFence->Wait(100);
183 
184     if (buffer == nullptr) {
185         std::cout << "buffer is nullptr" << std::endl;
186         return SURFACE_ERROR_NULLPTR;
187     }
188 
189     void* addr = static_cast<uint8_t *>(buffer->GetVirAddr());
190     static uint32_t value = 0xffffffff;
191 
192     uint32_t *pixel = static_cast<uint32_t*>(addr);
193 
194     for (uint32_t x = 0; x < width; x++) {
195         for (uint32_t y = 0;  y < height; y++) {
196             *pixel++ = value;
197         }
198     }
199 
200     BufferFlushConfig flushConfig = {
201         .damage = {
202             .w = width,
203             .h = height,
204         },
205     };
206 
207     int32_t acquireFence = -1;
208     ret = backGroundPSurface->FlushBuffer(buffer, acquireFence, flushConfig);
209 
210     std::cout << "Sync: " << SurfaceErrorStr(ret).c_str() << std::endl;
211     return SURFACE_ERROR_OK;
212 }
213 
ProduceDrawingBuffer(uint32_t width,uint32_t height)214 SurfaceError RenderContextSample::ProduceDrawingBuffer(uint32_t width, uint32_t height)
215 {
216     std::cout << "ProduceDrawingBuffer start" << std::endl;
217 
218     if (nwindow == nullptr) {
219         nwindow = CreateNativeWindowFromSurface(&drawingPSurface);
220         eglSurface = renderContext->CreateEGLSurface((EGLNativeWindowType)nwindow);
221     }
222 
223     NativeWindowHandleOpt(nwindow, SET_BUFFER_GEOMETRY, width, height);
224 
225     renderContext->MakeCurrent(eglSurface);
226 
227     SkCanvas* canvas = renderContext->AcquireSkCanvas(width, height);
228 
229     canvas->clear(SkColorSetARGB(0x20, 0x20, 0x20, 0xFF));
230     SkPaint paint;
231     paint.setColor(SK_ColorRED);
232     paint.setAntiAlias(true);
233     canvas->drawCircle(128, 128, 90, paint);
234     paint.setColor(SK_ColorGREEN);
235     canvas->drawCircle(86, 86, 20, paint);
236     canvas->drawCircle(160, 76, 20, paint);
237     canvas->drawCircle(140, 150, 35, paint);
238 
239     renderContext->RenderFrame();
240     renderContext->SwapBuffers(eglSurface);
241 
242     std::cout << "ProduceDrawingBuffer end" << std::endl;
243 
244     return SURFACE_ERROR_OK;
245 }
246 
DrawBackgroundLayer(std::shared_ptr<HdiLayerInfo> & layer)247 bool RenderContextSample::DrawBackgroundLayer(std::shared_ptr<HdiLayerInfo> &layer)
248 {
249     int32_t zorder = 0;
250     GraphicIRect dstRect;
251 
252     dstRect.x = 0;  // Absolute coordinates, with offset
253     dstRect.y = 0;
254     dstRect.w = 2560;
255     dstRect.h = 1600;
256 
257     if (!FillBackGroundLayer(layer, zorder, dstRect)) {
258         return false;
259     }
260     return true;
261 }
262 
DrawDrawingLayer(std::shared_ptr<HdiLayerInfo> & layer)263 bool RenderContextSample::DrawDrawingLayer(std::shared_ptr<HdiLayerInfo> &layer)
264 {
265     int32_t zorder = 1;
266     GraphicIRect dstRect;
267 
268     dstRect.x = 0;  // Absolute coordinates, with offset
269     dstRect.y = 0;
270 
271     dstRect.w = 1200;
272     dstRect.h = 800;
273 
274     if (!FillDrawingLayer(layer, 0, zorder, dstRect)) {
275         return false;
276     }
277     return true;
278 }
279 
Draw()280 void RenderContextSample::Draw()
281 {
282     static int32_t count = 0;
283     std::shared_ptr<HdiLayerInfo> backgroundLayer = HdiLayerInfo::CreateHdiLayerInfo();
284     std::shared_ptr<HdiLayerInfo> drawingLayer = HdiLayerInfo::CreateHdiLayerInfo();
285     do {
286         std::cout << "+++++++ draw count " << count << std::endl;
287         if (!DrawBackgroundLayer(backgroundLayer)) {
288             std::cout << "DrawBackgroundLayer failed!" << std::endl;
289             return;
290         }
291 
292         if (!DrawDrawingLayer(drawingLayer)) {
293             std::cout << "DrawDrawingLayer failed!" << std::endl;
294             return;
295         }
296 
297         std::vector<LayerInfoPtr> layers;
298         layers.push_back(backgroundLayer);
299         layers.push_back(drawingLayer);
300 
301         output_->SetLayerInfo(layers);
302 
303         GraphicIRect damageRect;
304         damageRect.x = 0;
305         damageRect.y = 0;
306         damageRect.w = display_w;
307         damageRect.h = display_h;
308         std::vector<GraphicIRect> outputDamages;
309         outputDamages.emplace_back(damageRect);
310         output_->SetOutputDamages(outputDamages);
311 
312         backend_->Repaint(output_);
313         for (auto layerI : layers) {
314             int32_t releaseFence = -1;
315             sptr<SyncFence> tempFence = new SyncFence(releaseFence);
316             layerI->GetSurface()->ReleaseBuffer(layerI->GetBuffer(), tempFence);
317             tempFence->Wait(100); // 100 ms
318         }
319         std::cout << "------ draw count " << count << std::endl;
320         count++;
321     } while (false);
322 }
323 
FillDrawingLayer(std::shared_ptr<HdiLayerInfo> & showLayer,uint32_t index,uint32_t zorder,GraphicIRect & dstRect)324 bool RenderContextSample::FillDrawingLayer(std::shared_ptr<HdiLayerInfo> &showLayer, uint32_t index,
325     uint32_t zorder, GraphicIRect &dstRect)
326 {
327     if (ProduceDrawingBuffer(drawingWidth, drawingHeight) != SURFACE_ERROR_OK) {
328         std::cout << "FillDrawingLayer produce cBuffer failed" << std::endl;
329         return false;
330     }
331 
332     OHOS::sptr<SurfaceBuffer> cbuffer = nullptr;
333     int32_t fence = -1;
334     int64_t timestamp;
335     Rect damage;
336     SurfaceError ret = drawingCSurface->AcquireBuffer(cbuffer, fence, timestamp, damage);
337     sptr<SyncFence> acquireSyncFence = new SyncFence(fence);
338     if (ret != SURFACE_ERROR_OK) {
339         std::cout << "Acquire cBuffer failed: " << ret << std::endl;
340         return false;
341     }
342 
343     GraphicIRect srcRect;
344     srcRect.x = 0;
345     srcRect.y = 0;
346     srcRect.w = drawingWidth;
347     srcRect.h = drawingHeight;
348 
349     GraphicLayerAlpha alpha = { .enPixelAlpha = true };
350 
351     showLayer->SetSurface(drawingCSurface);
352     showLayer->SetBuffer(cbuffer, acquireSyncFence);
353     showLayer->SetZorder(zorder);
354     showLayer->SetAlpha(alpha);
355     showLayer->SetTransform(GraphicTransformType::GRAPHIC_ROTATE_NONE);
356     showLayer->SetCompositionType(GraphicCompositionType::GRAPHIC_COMPOSITION_DEVICE);
357     std::vector<GraphicIRect> visibleRegions;
358     visibleRegions.emplace_back(srcRect);
359     showLayer->SetVisibleRegions(visibleRegions);
360     std::vector<GraphicIRect> dirtyRegions;
361     dirtyRegions.emplace_back(srcRect);
362     showLayer->SetDirtyRegions(dirtyRegions);
363     showLayer->SetLayerSize(dstRect);
364     showLayer->SetBlendType(GraphicBlendType::GRAPHIC_BLEND_SRC);
365     showLayer->SetCropRect(srcRect);
366     showLayer->SetPreMulti(false);
367 
368     prevBufferMap_[drawingCSurface->GetUniqueId()] = cbuffer;
369     prevFenceMap_[drawingCSurface->GetUniqueId()] = acquireSyncFence;
370 
371     return true;
372 }
373 
FillBackGroundLayer(std::shared_ptr<HdiLayerInfo> & showLayer,uint32_t zorder,GraphicIRect & dstRect)374 bool RenderContextSample::FillBackGroundLayer(std::shared_ptr<HdiLayerInfo> &showLayer,
375                                               uint32_t zorder, GraphicIRect &dstRect)
376 {
377     if (ProduceBackGroundBuffer(dstRect.w, dstRect.h) != SURFACE_ERROR_OK) {
378         std::cout << "Produce background cBuffer failed" << std::endl;
379         return false;
380     }
381 
382     OHOS::sptr<SurfaceBuffer> cbuffer = nullptr;
383     int32_t fence = -1;
384     int64_t timestamp;
385     Rect damage;
386     SurfaceError ret = backGroundCSurface->AcquireBuffer(cbuffer, fence, timestamp, damage);
387     sptr<SyncFence> acquireSyncFence = new SyncFence(fence);
388     if (ret != SURFACE_ERROR_OK) {
389         std::cout << "Acquire cBuffer failed" << std::endl;
390         return false;
391     }
392 
393     GraphicIRect srcRect;
394     srcRect.x = 0;
395     srcRect.y = 0;
396     srcRect.w = dstRect.w;
397     srcRect.h = dstRect.h;
398 
399     GraphicLayerAlpha alpha = { .enPixelAlpha = true };
400 
401     showLayer->SetSurface(backGroundCSurface);
402     showLayer->SetBuffer(cbuffer, acquireSyncFence);
403     showLayer->SetZorder(zorder);
404     showLayer->SetAlpha(alpha);
405     showLayer->SetCompositionType(GraphicCompositionType::GRAPHIC_COMPOSITION_DEVICE);
406     std::vector<GraphicIRect> visibleRegions;
407     visibleRegions.emplace_back(srcRect);
408     showLayer->SetVisibleRegions(visibleRegions);
409     std::vector<GraphicIRect> dirtyRegions;
410     dirtyRegions.emplace_back(srcRect);
411     showLayer->SetDirtyRegions(dirtyRegions);
412     showLayer->SetLayerSize(dstRect);
413     showLayer->SetBlendType(GraphicBlendType::GRAPHIC_BLEND_SRC);
414     showLayer->SetCropRect(srcRect);
415     showLayer->SetPreMulti(false);
416 
417     prevBufferMap_[backGroundCSurface->GetUniqueId()] = cbuffer;
418     prevFenceMap_[backGroundCSurface->GetUniqueId()] = acquireSyncFence;
419 
420     std::cout << "FillBackGroundLayer finished" << std::endl;
421     return true;
422 }
423 
CreatePhysicalScreen()424 void RenderContextSample::CreatePhysicalScreen()
425 {
426     screen_ = HdiScreen::CreateHdiScreen(output_->GetScreenId());
427     screen_->Init();
428     screen_->GetScreenSupportedModes(displayModeInfos_);
429     size_t supportModeNum = displayModeInfos_.size();
430     if (supportModeNum > 0) {
431         screen_->GetScreenMode(currentModeIndex_);
432         for (size_t i = 0; i < supportModeNum; i++) {
433             if (displayModeInfos_[i].id == static_cast<int32_t>(currentModeIndex_)) {
434                 this->freq_ = displayModeInfos_[i].freshRate;
435                 this->display_w = displayModeInfos_[i].width;
436                 this->display_h = displayModeInfos_[i].height;
437             }
438         }
439         screen_->SetScreenPowerStatus(GraphicDispPowerStatus::GRAPHIC_POWER_STATUS_ON);
440         screen_->SetScreenMode(currentModeIndex_);
441 
442         GraphicDispPowerStatus powerState;
443         screen_->SetScreenPowerStatus(GraphicDispPowerStatus::GRAPHIC_POWER_STATUS_ON);
444         screen_->GetScreenPowerStatus(powerState);
445     }
446 
447     GraphicDisplayCapability info;
448     screen_->GetScreenCapability(info);
449 
450     ready_ = true;
451 }
452 
OnHotPlugEvent(const std::shared_ptr<HdiOutput> & output,bool connected)453 void RenderContextSample::OnHotPlugEvent(const std::shared_ptr<HdiOutput> &output, bool connected)
454 {
455     /*
456      * Currently, IPC communication cannot be nested. Therefore, Vblank registration can be
457      * initiated only after the initialization of the device is complete.
458      */
459     output_ = output;
460     deviceConnected_ = connected;
461 
462     if (!initDeviceFinished_) {
463         std::cout << "Init the device has not finished yet" << std::endl;
464         return;
465     }
466 
467     std::cout << "Callback HotPlugEvent, connected is " << connected << std::endl;
468 
469     if (connected) {
470         CreatePhysicalScreen();
471     }
472  }
473 
DoPrepareCompleted(sptr<Surface> surface,const struct PrepareCompleteParam & param)474 void RenderContextSample::DoPrepareCompleted(sptr<Surface> surface, const struct PrepareCompleteParam &param)
475 {
476     BufferRequestConfig requestConfig = {
477         .width = display_w,  // need display width
478         .height = display_h, // need display height
479         .strideAlignment = 0x8,
480         .format = GRAPHIC_PIXEL_FMT_BGRA_8888,
481         .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA | BUFFER_USAGE_MEM_FB,
482         .timeout = 0,
483     };
484 
485     if (surface == nullptr) {
486         std::cout << "surface is null" << std::endl;
487         return;
488     }
489 
490     int32_t releaseFence = -1;
491     sptr<SurfaceBuffer> fbBuffer = nullptr;
492     SurfaceError ret1 = surface->RequestBuffer(fbBuffer, releaseFence, requestConfig);
493     if (ret1 != 0) {
494         std::cout << "RequestBuffer failed " << SurfaceErrorStr(ret1).c_str() << std::endl;
495         return;
496     }
497 
498     sptr<SyncFence> tempFence = new SyncFence(releaseFence);
499     tempFence->Wait(100);
500 
501 
502     auto addr = static_cast<uint8_t *>(fbBuffer->GetVirAddr());
503     int32_t ret2 = memset_s(addr, fbBuffer->GetSize(), 0, fbBuffer->GetSize());
504     if (ret2 != 0) {
505         std::cout << "memset_s failed" << std::endl;
506     }
507 
508     BufferFlushConfig flushConfig = {
509         .damage = {
510             .w = display_w,
511             .h = display_h,
512         }
513     };
514 
515     /*
516      * if use GPU produce data, flush with gpu fence
517      */
518     ret2 = surface->FlushBuffer(fbBuffer, -1, flushConfig);
519     if (ret2 != 0) {
520         std::cout << "DoPrepareCompleted FlushBuffer failed"<< std::endl;
521     }
522 }
523