update drawingengine sample code

Signed-off-by: mk_gc <mengkun@huawei.com>
Change-Id: I8dba83adee3c57fb257634bbeaa1e80f6ae47dd3
Signed-off-by: mk_gc <mengkun@huawei.com>
This commit is contained in:
mk_gc 2022-04-13 23:00:27 +08:00
parent 516d897ab7
commit 981f1e5f5e
6 changed files with 456 additions and 590 deletions

View File

@ -55,6 +55,7 @@
"//foundation/graphic/standard/rosen/modules/composer:libcomposer",
"//foundation/graphic/standard/rosen/modules/2d_graphics:2d_graphics",
"//foundation/graphic/standard/rosen/samples/2d_graphics:drawing_sample_rs",
"//foundation/graphic/standard/rosen/samples/2d_graphics:drawing_engine_sample",
"//foundation/graphic/standard/rosen/samples/2d_graphics/test:drawing_sample",
"//foundation/graphic/standard/rosen/modules/render_service_base:librender_service_base",
"//foundation/graphic/standard/rosen/modules/render_service_base/test:render_service_client",

View File

@ -15,59 +15,57 @@ import("//build/ohos.gni")
import("//foundation/graphic/standard/graphic_config.gni")
import("//third_party/wayland_standard/wayland_protocol.gni")
if (ace_enable_gpu) {
ohos_executable("render_context_sample") {
install_enable = true
cflags = [
"-Wall",
"-Werror",
"-Wno-unused-parameter",
"-Wno-missing-field-initializers",
"-Wno-unused-variable",
]
ohos_executable("drawing_engine_sample") {
install_enable = true
cflags = [
"-Wall",
"-Werror",
"-Wno-unused-parameter",
"-Wno-missing-field-initializers",
"-Wno-unused-variable",
]
sources = [
"main.cpp",
"render_context_sample.cpp",
]
sources = [
"drawing_engine_sample.cpp",
"main.cpp",
]
configs = []
configs = []
include_dirs = [
"include",
"//foundation/graphic/standard/rosen/modules/2d_graphics/include",
"//foundation/graphic/standard/rosen/modules/2d_graphics/src",
"//foundation/graphic/standard/rosen/modules/render_service_base/src",
"//foundation/graphic/standard/rosen/modules/composer/hdi_backend/include",
"//foundation/graphic/standard/interfaces/innerkits/vsync_module",
"//foundation/graphic/standard/utils/sync_fence/export",
"//foundation/graphic/standard/rosen/include/common",
"//foundation/graphic/standard/rosen/modules/render_service_base/include",
]
include_dirs = [
"include",
"//foundation/graphic/standard/rosen/modules/2d_graphics/include",
"//foundation/graphic/standard/rosen/modules/2d_graphics/src",
"//foundation/graphic/standard/rosen/modules/render_service_base/src",
"//foundation/graphic/standard/rosen/modules/composer/hdi_backend/include",
"//foundation/graphic/standard/interfaces/innerkits/vsync_module",
"//foundation/graphic/standard/utils/sync_fence/export",
"//foundation/graphic/standard/rosen/include/common",
"//foundation/graphic/standard/rosen/modules/render_service_base/include",
]
deps = [
"//foundation/ace/ace_engine/build/external_config/flutter/skia:ace_skia_ohos",
"//foundation/graphic/standard:libsurface",
"//foundation/graphic/standard:libvsync_client",
"//foundation/graphic/standard:libwmclient",
"//foundation/graphic/standard:libwmservice",
"//foundation/graphic/standard/frameworks/vsync:libvsync_module",
"//foundation/graphic/standard/rosen/modules/2d_graphics:2d_graphics",
"//foundation/graphic/standard/rosen/modules/composer:libcomposer",
"//foundation/graphic/standard/rosen/modules/render_service_base:librender_service_base",
"//foundation/graphic/standard/utils:sync_fence",
"//third_party/zlib:libz",
]
deps = [
"//foundation/ace/ace_engine/build/external_config/flutter/skia:ace_skia_ohos",
"//foundation/graphic/standard:libsurface",
"//foundation/graphic/standard:libvsync_client",
"//foundation/graphic/standard:libwmclient",
"//foundation/graphic/standard:libwmservice",
"//foundation/graphic/standard/frameworks/vsync:libvsync_module",
"//foundation/graphic/standard/rosen/modules/2d_graphics:2d_graphics",
"//foundation/graphic/standard/rosen/modules/composer:libcomposer",
"//foundation/graphic/standard/rosen/modules/render_service_base:librender_service_base",
"//foundation/graphic/standard/utils:sync_fence",
"//third_party/zlib:libz",
]
external_deps = [
"hilog_native:libhilog",
"multimedia_image_standard:image_native",
"utils_base:utils",
]
external_deps = [
"hilog_native:libhilog",
"multimedia_image_standard:image_native",
"utils_base:utils",
]
subsystem_name = "graphic"
part_name = "graphic_standard"
}
subsystem_name = "graphic"
part_name = "graphic_standard"
}
ohos_executable("drawing_sample_rs") {

View File

@ -0,0 +1,385 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "drawing_engine_sample.h"
#include "window.h"
#include <securec.h>
#include <vsync_generator.h>
#include <vsync_controller.h>
#include <vsync_distributor.h>
#include <vsync_helper.h>
#include <vsync_receiver.h>
#include <iostream>
using namespace OHOS;
using namespace OHOS::Rosen;
namespace {
sptr<VSyncReceiver> g_receiver = nullptr;
}
void DrawingEngineSample::Run()
{
auto generator = CreateVSyncGenerator();
sptr<VSyncController> vsyncController = new VSyncController(generator, 0);
sptr<VSyncDistributor> vsyncDistributor = new VSyncDistributor(vsyncController, "HelloComposer");
sptr<VSyncConnection> vsyncConnection = new VSyncConnection(vsyncDistributor, "HelloComposer");
vsyncDistributor->AddConnection(vsyncConnection);
std::cout << "start to HdiBackend::GetInstance" << std::endl;
backend_ = OHOS::Rosen::HdiBackend::GetInstance();
if (backend_ == nullptr) {
std::cout << "HdiBackend::GetInstance fail" << std::endl;
return;
}
backend_->RegScreenHotplug(DrawingEngineSample::OnScreenPlug, this);
while (1) {
if (output_ != nullptr) {
break;
}
}
if (!initDeviceFinished_) {
if (deviceConnected_) {
CreatePhysicalScreen();
}
initDeviceFinished_ = true;
}
std::cout << "Init screen succeed" << std::endl;
backend_->RegPrepareComplete(DrawingEngineSample::OnPrepareCompleted, this);
sleep(1);
auto runner = OHOS::AppExecFwk::EventRunner::Create(false);
auto handler = std::make_shared<OHOS::AppExecFwk::EventHandler>(runner);
g_receiver = new VSyncReceiver(vsyncConnection, handler);
g_receiver->Init();
handler->PostTask(std::bind(&DrawingEngineSample::Init, this));
runner->Run();
}
void DrawingEngineSample::OnScreenPlug(std::shared_ptr<HdiOutput> &output, bool connected, void* data)
{
std::cout << "enter OnScreenPlug, connected is " << connected << std::endl;
auto* thisPtr = static_cast<DrawingEngineSample *>(data);
thisPtr->OnHotPlugEvent(output, connected);
}
void DrawingEngineSample::OnPrepareCompleted(
std::shared_ptr<RSSurface> &rsSurface, const struct PrepareCompleteParam &param, void* data)
{
if (!param.needFlushFramebuffer) {
return;
}
if (rsSurface == nullptr) {
LOGE("surface is null");
return;
}
if (data == nullptr) {
LOGE("data ptr is null");
return;
}
auto* thisPtr = static_cast<DrawingEngineSample *>(data);
sptr<Surface> surface = std::static_pointer_cast<RSSurfaceOhos>(rsSurface)->GetSurface();
thisPtr->DoPrepareCompleted(surface, param);
}
void DrawingEngineSample::InitContext()
{
drawingProxy = new DrawingProxy();
drawingProxy->InitDrawContext();
}
void DrawingEngineSample::Init()
{
LOGI("DrawingEngineSample::Init+");
CreateDrawingSurface();
InitContext();
Sync(0, nullptr);
Initilized = true;
LOGI("DrawingEngineSample::Init-");
}
void DrawingEngineSample::Sync(int64_t, void *data)
{
VSyncReceiver::FrameCallback fcb = {
.userData_ = data,
.callback_ = std::bind(&DrawingEngineSample::Sync, this, ::std::placeholders::_1, ::std::placeholders::_2),
};
if (g_receiver != nullptr) {
g_receiver->RequestNextVSync(fcb);
}
if (!ready_) {
LOGE("hdi screen is not ready");
return;
}
if (Initilized == false) {
LOGI("call init function");
return;
}
OutPutDisplay();
}
void DrawingEngineSample::CreateDrawingSurface()
{
drawingCSurface = Surface::CreateSurfaceAsConsumer();
drawingCSurface->SetDefaultWidthAndHeight(drawingWidth, drawingHeight);
drawingCSurface->SetDefaultUsage(HBM_USE_CPU_READ | HBM_USE_CPU_WRITE | HBM_USE_MEM_DMA);
sptr<IBufferProducer> producer = drawingCSurface->GetProducer();
drawingPSurface= Surface::CreateSurfaceAsProducer(producer);
drawingCSurface->RegisterConsumerListener(this);
prevBufferMap_[drawingCSurface->GetUniqueId()] = nullptr;
prevFenceMap_[drawingCSurface->GetUniqueId()] = SyncFence::INVALID_FENCE;
}
void DrawingEngineSample::OnBufferAvailable()
{
}
void DrawingEngineSample::Draw(SkCanvas* canvas)
{
SkPaint paint;
paint.setAntiAlias(true);
paint.setColor(0xFF9A67BE);
paint.setStrokeWidth(20);
canvas->skew(1, 0);
canvas->drawLine(32, 96,32, 160, paint); // point position
canvas->skew(-2, 0);
canvas->drawLine(288, 96, 288, 160, paint); // point position
}
SurfaceError DrawingEngineSample::DoDraw()
{
LOGI("DrawingEngineSample::DoDraw+");
std::shared_ptr<RSSurface> rsSurface = OHOS::Rosen::RSSurfaceOhos::CreateSurface(drawingPSurface);
rsSurface->SetDrawingProxy(drawingProxy);
auto surfaceFrame = rsSurface->RequestFrame(drawingWidth, drawingHeight);
if (surfaceFrame == nullptr) {
std::cout << "Request Frame Failed" << std::endl;
return SURFACE_ERROR_ERROR;
}
SkCanvas* canvas = rsSurface->GetCanvas(surfaceFrame);
Draw(canvas);
rsSurface->FlushFrame(surfaceFrame);
LOGI("DrawingEngineSample::DoDraw-");
return SURFACE_ERROR_OK;
}
bool DrawingEngineSample::DrawDrawingLayer(std::shared_ptr<HdiLayerInfo> &layer)
{
int32_t zorder = 1;
IRect dstRect;
dstRect.x = 0; // Absolute coordinates, with offset
dstRect.y = 0;
dstRect.w = display_w;
dstRect.h = display_h;
int index = -1;
SurfaceError err = DoDraw();
if (err != SURFACE_ERROR_OK) {
std::cout << "DoDraw failed" << std::endl;
return false;
}
OHOS::sptr<SurfaceBuffer> cbuffer = nullptr;
int32_t fence = -1;
int64_t timestamp;
Rect damage;
SurfaceError ret = drawingCSurface->AcquireBuffer(cbuffer, fence, timestamp, damage);
sptr<SyncFence> acquireSyncFence = new SyncFence(fence);
if (ret != SURFACE_ERROR_OK) {
std::cout << "Acquire cBuffer failed: " << ret << std::endl;
return false;
}
IRect srcRect;
srcRect.x = 0;
srcRect.y = 0;
srcRect.w = drawingWidth;
srcRect.h = drawingHeight;
LayerAlpha alpha = { .enPixelAlpha = true };
layer->SetSurface(drawingCSurface);
layer->SetBuffer(cbuffer, acquireSyncFence, prevBufferMap_[drawingCSurface->GetUniqueId()],
prevFenceMap_[drawingCSurface->GetUniqueId()]);
layer->SetZorder(zorder);
layer->SetAlpha(alpha);
layer->SetTransform(TransformType::ROTATE_NONE);
if (index == 0) {
// COMPOSITION_CLIENT
layer->SetCompositionType(CompositionType::COMPOSITION_DEVICE);
} else {
layer->SetCompositionType(CompositionType::COMPOSITION_DEVICE);
}
layer->SetVisibleRegion(1, srcRect);
layer->SetDirtyRegion(srcRect);
layer->SetLayerSize(dstRect);
layer->SetBlendType(BlendType::BLEND_SRC);
layer->SetCropRect(srcRect);
layer->SetPreMulti(false);
prevBufferMap_[drawingCSurface->GetUniqueId()] = cbuffer;
prevFenceMap_[drawingCSurface->GetUniqueId()] = acquireSyncFence;
return true;
}
void DrawingEngineSample::OutPutDisplay()
{
static int32_t count = 0;
std::shared_ptr<HdiLayerInfo> drawingLayer = HdiLayerInfo::CreateHdiLayerInfo();
do {
std::cout << " draw count " << count << std::endl;
LOGI("OutPutDisplay draw count is %{pubic}d", count);
if (!DrawDrawingLayer(drawingLayer)) {
std::cout << "DrawDrawingLayer failed!" << std::endl;
return;
}
std::vector<LayerInfoPtr> layers;
layers.push_back(drawingLayer);
output_->SetLayerInfo(layers);
IRect damageRect;
damageRect.x = 0;
damageRect.y = 0;
damageRect.w = display_w;
damageRect.h = display_h;
output_->SetOutputDamage(1, damageRect);
backend_->Repaint(outputs_);
std::cout << "draw count " << count << std::endl;
std::cout << "display width is " << display_w << ", display height is " << display_h << std::endl;
count++;
} while (false);
}
void DrawingEngineSample::CreatePhysicalScreen()
{
screen_ = HdiScreen::CreateHdiScreen(output_->GetScreenId());
screen_->Init();
screen_->GetScreenSupportedModes(displayModeInfos_);
outputs_.push_back(output_);
size_t supportModeNum = displayModeInfos_.size();
if (supportModeNum > 0) {
screen_->GetScreenMode(currentModeIndex_);
for (size_t i = 0; i < supportModeNum; i++) {
if (displayModeInfos_[i].id == static_cast<int32_t>(currentModeIndex_)) {
this->freq_ = displayModeInfos_[i].freshRate;
this->display_w = displayModeInfos_[i].width;
this->display_h = displayModeInfos_[i].height;
}
}
screen_->SetScreenPowerStatus(DispPowerStatus::POWER_STATUS_ON);
screen_->SetScreenMode(currentModeIndex_);
DispPowerStatus powerState;
screen_->SetScreenPowerStatus(DispPowerStatus::POWER_STATUS_ON);
screen_->GetScreenPowerStatus(powerState);
}
DisplayCapability info;
screen_->GetScreenCapability(info);
std::cout << "display width is " << this->display_w << " display height is " << this->display_h << std::endl;
drawingWidth = this->display_w;
drawingHeight = this->display_h;
ready_ = true;
}
void DrawingEngineSample::OnHotPlugEvent(std::shared_ptr<HdiOutput> &output, bool connected)
{
/*
* Currently, IPC communication cannot be nested. Therefore, Vblank registration can be
* initiated only after the initialization of the device is complete.
*/
output_ = output;
deviceConnected_ = connected;
if (!initDeviceFinished_) {
std::cout << "Init the device has not finished yet" << std::endl;
return;
}
std::cout << "Callback HotPlugEvent, connected is " << connected << std::endl;
if (connected) {
CreatePhysicalScreen();
}
}
void DrawingEngineSample::DoPrepareCompleted(sptr<Surface> &surface, const struct PrepareCompleteParam &param)
{
BufferRequestConfig requestConfig = {
.width = display_w, // need display width
.height = display_h, // need display height
.strideAlignment = 0x8,
.format = PIXEL_FMT_BGRA_8888,
.usage = HBM_USE_CPU_READ | HBM_USE_CPU_WRITE | HBM_USE_MEM_DMA | HBM_USE_MEM_FB,
.timeout = 0,
};
int32_t releaseFence = -1;
sptr<SurfaceBuffer> fbBuffer = nullptr;
SurfaceError err = surface->RequestBuffer(fbBuffer, releaseFence, requestConfig);
if (err != 0) {
LOGE("RequestBuffer failed: %{public}s", SurfaceErrorStr(err).c_str());
return;
}
sptr<SyncFence> tempFence = new SyncFence(releaseFence);
tempFence->Wait(100); // 100 ms
int32_t ret = 0;
auto addr = static_cast<uint8_t *>(fbBuffer->GetVirAddr());
ret = memset_s(addr, fbBuffer->GetSize(), 0, fbBuffer->GetSize());
if (ret != 0) {
std::cout << "memset_s failed" << std::endl;
}
BufferFlushConfig flushConfig = {
.damage = {
.w = display_w,
.h = display_h,
}
};
/*
* if use GPU produce data, flush with gpu fence
*/
ret = surface->FlushBuffer(fbBuffer, -1, flushConfig);
if (ret != 0) {
std::cout << "DoPrepareCompleted FlushBuffer failed"<< std::endl;
}
}

View File

@ -13,81 +13,71 @@
* limitations under the License.
*/
#ifndef RENDER_CONTEXT_SAMPLE_H
#define RENDER_CONTEXT_SAMPLE_H
#ifndef DRAWING_ENGINE_SAMPLE_H
#define DRAWING_ENGINE_SAMPLE_H
#include "include/core/SkCanvas.h"
#include "include/core/SkPaint.h"
#include <display_type.h>
#include <surface.h>
#include <sync_fence.h>
#include <event_handler.h>
#include "hdi_backend.h"
#include "hdi_layer_info.h"
#include "hdi_output.h"
#include "hdi_screen.h"
#include "render_context/render_context.h"
#include <unordered_map>
#include "drawing_engine/drawing_utils.h"
#include "drawing_engine/drawing_proxy.h"
#include "drawing_engine/drawing_surface/rs_surface_ohos.h"
namespace OHOS {
namespace Rosen {
class RenderContextSample : public IBufferConsumerListenerClazz {
class DrawingEngineSample : public IBufferConsumerListenerClazz {
public:
RenderContextSample() = default;
virtual ~RenderContextSample() = default;
DrawingEngineSample() = default;
virtual ~DrawingEngineSample() = default;
void Run();
private:
uint32_t freq_ = 30;
uint32_t display_w = 480;
uint32_t display_h = 960;
uint32_t display_w = 0;
uint32_t display_h = 0;
uint32_t currentModeIndex_ = 0;
uint32_t backGroundWidth = 0;
uint32_t backGroundHeight = 0;
uint32_t drawingWidth = 0;
uint32_t drawingHeight = 0;
std::vector<DisplayModeInfo> displayModeInfos_;
std::vector<std::shared_ptr<HdiOutput>> outputs_;
sptr<Surface> backGroundCSurface;
sptr<Surface> backGroundPSurface;
std::shared_ptr<OHOS::AppExecFwk::EventHandler> handler;
sptr<Surface> drawingCSurface;
sptr<Surface> drawingPSurface;
bool ready_ = false;
bool initDeviceFinished_ = false;
bool deviceConnected_ = false;
bool Initilized = false;
std::unique_ptr<HdiScreen> screen_ = nullptr;
HdiBackend* backend_ = nullptr;
std::shared_ptr<HdiOutput> output_ = nullptr;
struct NativeWindow* nwindow = nullptr;
RenderContext* renderContext = nullptr;
EGLSurface eglSurface = EGL_NO_SURFACE;
DrawingProxy* drawingProxy = nullptr;
std::unordered_map<uint64_t, sptr<SurfaceBuffer>> prevBufferMap_;
std::unordered_map<uint64_t, sptr<SyncFence>> prevFenceMap_;
void Init();
void InitEGL();
void Draw();
void DrawSurface();
void InitContext();
void OutPutDisplay();
void Sync(int64_t, void *data);
void CreatePhysicalScreen();
void DoPrepareCompleted(sptr<Surface> &surface, const struct PrepareCompleteParam &param);
virtual void OnBufferAvailable() override;
SurfaceError ProduceBackGroundBuffer(uint32_t width, uint32_t height);
SurfaceError ProduceDrawingBuffer(uint32_t width, uint32_t height);
bool FillDrawingLayer(std::shared_ptr<HdiLayerInfo> &showLayer, uint32_t index, uint32_t zorder, IRect &dstRect);
bool FillBackGroundLayer(std::shared_ptr<HdiLayerInfo> &showLayer, uint32_t zorder, IRect &dstRect);
bool DrawBackgroundLayer(std::shared_ptr<HdiLayerInfo> &layer);
SurfaceError DoDraw();
void Draw(SkCanvas* canvas);
bool DrawDrawingLayer(std::shared_ptr<HdiLayerInfo> &layer);
void CreateBackGroundSurface();
void CreateDrawingSurface();
void OnHotPlugEvent(std::shared_ptr<HdiOutput> &output, bool connected);
static void OnScreenPlug(std::shared_ptr<HdiOutput> &output, bool connected, void* data);
static void OnPrepareCompleted(OHOS::sptr<Surface> &surface, const struct PrepareCompleteParam &param, void* data);
static void OnPrepareCompleted(
std::shared_ptr<RSSurface> &rsSurface, const struct PrepareCompleteParam &param, void* data);
};
} // namespace Rosen
} // namespace OHOS

View File

@ -13,11 +13,11 @@
* limitations under the License.
*/
#include "render_context_sample.h"
#include "drawing_engine_sample.h"
int32_t main(int32_t argc, const char *argv[])
{
OHOS::Rosen::RenderContextSample m;
OHOS::Rosen::DrawingEngineSample m;
m.Run();
return 0;

View File

@ -1,508 +0,0 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "render_context_sample.h"
#include "window.h"
#include <securec.h>
#include <vsync_helper.h>
#include <iostream>
using namespace OHOS;
using namespace OHOS::Rosen;
void RenderContextSample::Run()
{
std::cout << "start to HdiBackend::GetInstance" << std::endl;
backend_ = OHOS::Rosen::HdiBackend::GetInstance();
if (backend_ == nullptr) {
std::cout << "HdiBackend::GetInstance fail" << std::endl;
return;
}
backend_->RegScreenHotplug(RenderContextSample::OnScreenPlug, this);
while (1) {
if (output_ != nullptr) {
break;
}
}
if (!initDeviceFinished_) {
if (deviceConnected_) {
CreatePhysicalScreen();
}
initDeviceFinished_ = true;
}
std::cout << "Init screen succeed" << std::endl;
backend_->RegPrepareComplete(RenderContextSample::OnPrepareCompleted, this);
sleep(1);
auto runner = OHOS::AppExecFwk::EventRunner::Create(false);
auto handler = std::make_shared<OHOS::AppExecFwk::EventHandler>(runner);
handler->PostTask(std::bind(&RenderContextSample::Init, this));
runner->Run();
}
void RenderContextSample::OnScreenPlug(std::shared_ptr<HdiOutput> &output, bool connected, void* data)
{
std::cout << "enter OnScreenPlug, connected is " << connected << std::endl;
auto* thisPtr = static_cast<RenderContextSample *>(data);
thisPtr->OnHotPlugEvent(output, connected);
}
void RenderContextSample::OnPrepareCompleted(sptr<Surface> &surface, const struct PrepareCompleteParam &param, void* data)
{
if (!param.needFlushFramebuffer) {
return;
}
if (data == nullptr) {
return;
}
std::cout << "OnPrepareCompleted param.layer size is " << (int)param.layers.size() << std::endl;
auto* thisPtr = static_cast<RenderContextSample *>(data);
thisPtr->DoPrepareCompleted(surface, param);
}
void RenderContextSample::InitEGL()
{
renderContext = new RenderContext();
renderContext->InitializeEglContext();
}
void RenderContextSample::Init()
{
backGroundWidth = 2560;
backGroundHeight = 1600;
drawingWidth = 1200;
drawingHeight = 800;
CreateBackGroundSurface();
CreateDrawingSurface();
InitEGL();
Sync(0, nullptr);
}
void RenderContextSample::Sync(int64_t, void *data)
{
struct OHOS::FrameCallback cb = {
.frequency_ = freq_,
.timestamp_ = 0,
.userdata_ = data,
.callback_ = std::bind(&RenderContextSample::Sync, this, SYNC_FUNC_ARG),
};
OHOS::VsyncError ret = OHOS::VsyncHelper::Current()->RequestFrameCallback(cb);
if (ret) {
std::cout << "RequestFrameCallback inner " << ret << std::endl;
}
if (!ready_) {
return;
}
Draw();
}
void RenderContextSample::CreateBackGroundSurface()
{
backGroundCSurface = Surface::CreateSurfaceAsConsumer();
backGroundCSurface->SetDefaultWidthAndHeight(backGroundWidth, backGroundHeight);
backGroundCSurface->SetDefaultUsage(HBM_USE_CPU_READ | HBM_USE_CPU_WRITE | HBM_USE_MEM_DMA);
sptr<IBufferProducer> producer = backGroundCSurface->GetProducer();
backGroundPSurface= Surface::CreateSurfaceAsProducer(producer);
backGroundCSurface->RegisterConsumerListener(this);
prevBufferMap_[backGroundCSurface->GetUniqueId()] = nullptr;
prevFenceMap_[backGroundCSurface->GetUniqueId()] = SyncFence::INVALID_FENCE;
}
void RenderContextSample::CreateDrawingSurface()
{
drawingCSurface = Surface::CreateSurfaceAsConsumer();
drawingCSurface->SetDefaultWidthAndHeight(backGroundWidth, backGroundHeight);
drawingCSurface->SetDefaultUsage(HBM_USE_CPU_READ | HBM_USE_CPU_WRITE | HBM_USE_MEM_DMA);
sptr<IBufferProducer> producer = drawingCSurface->GetProducer();
drawingPSurface= Surface::CreateSurfaceAsProducer(producer);
drawingCSurface->RegisterConsumerListener(this);
prevBufferMap_[drawingCSurface->GetUniqueId()] = nullptr;
prevFenceMap_[drawingCSurface->GetUniqueId()] = SyncFence::INVALID_FENCE;
}
void RenderContextSample::OnBufferAvailable()
{
}
SurfaceError RenderContextSample::ProduceBackGroundBuffer(uint32_t width, uint32_t height)
{
OHOS::sptr<SurfaceBuffer> buffer;
int32_t releaseFence = -1;
BufferRequestConfig config = {
.width = width,
.height = height,
.strideAlignment = 0x8,
.format = PIXEL_FMT_RGBA_8888,
.usage = backGroundPSurface->GetDefaultUsage(),
};
SurfaceError ret = backGroundPSurface->RequestBuffer(buffer, releaseFence, config);
if (ret != 0) {
std::cout << "RequestBuffer failed:" << SurfaceErrorStr(ret).c_str() << std::endl;
return ret;
}
sptr<SyncFence> tempFence = new SyncFence(releaseFence);
tempFence->Wait(100);
if (buffer == nullptr) {
std::cout << "buffer is nullptr" << std::endl;
return SURFACE_ERROR_NULLPTR;
}
void* addr = static_cast<uint8_t *>(buffer->GetVirAddr());
static uint32_t value = 0xffffffff;
uint32_t *pixel = static_cast<uint32_t*>(addr);
for (uint32_t x = 0; x < width; x++) {
for (uint32_t y = 0; y < height; y++) {
*pixel++ = value;
}
}
BufferFlushConfig flushConfig = {
.damage = {
.w = width,
.h = height,
},
};
int32_t acquireFence = -1;
ret = backGroundPSurface->FlushBuffer(buffer, acquireFence, flushConfig);
std::cout << "Sync: " << SurfaceErrorStr(ret).c_str() << std::endl;
return SURFACE_ERROR_OK;
}
SurfaceError RenderContextSample::ProduceDrawingBuffer(uint32_t width, uint32_t height)
{
std::cout << "ProduceDrawingBuffer start" << std::endl;
if (nwindow == nullptr) {
nwindow = CreateNativeWindowFromSurface(&drawingPSurface);
eglSurface = renderContext->CreateEGLSurface((EGLNativeWindowType)nwindow);
}
NativeWindowHandleOpt(nwindow, SET_BUFFER_GEOMETRY, width, height);
renderContext->MakeCurrent(eglSurface);
SkCanvas* canvas = renderContext->AcquireCanvas(width, height);
canvas->clear(SkColorSetARGB(0x20, 0x20, 0x20, 0xFF));
SkPaint paint;
paint.setColor(SK_ColorRED);
paint.setAntiAlias(true);
canvas->drawCircle(128, 128, 90, paint);
paint.setColor(SK_ColorGREEN);
canvas->drawCircle(86, 86, 20, paint);
canvas->drawCircle(160, 76, 20, paint);
canvas->drawCircle(140, 150, 35, paint);
renderContext->RenderFrame();
renderContext->SwapBuffers(eglSurface);
std::cout << "ProduceDrawingBuffer end" << std::endl;
return SURFACE_ERROR_OK;
}
bool RenderContextSample::DrawBackgroundLayer(std::shared_ptr<HdiLayerInfo> &layer)
{
int32_t zorder = 0;
IRect dstRect;
dstRect.x = 0; // Absolute coordinates, with offset
dstRect.y = 0;
dstRect.w = 2560;
dstRect.h = 1600;
if (!FillBackGroundLayer(layer, zorder, dstRect)) {
return false;
}
return true;
}
bool RenderContextSample::DrawDrawingLayer(std::shared_ptr<HdiLayerInfo> &layer)
{
int32_t zorder = 1;
IRect dstRect;
dstRect.x = 0; // Absolute coordinates, with offset
dstRect.y = 0;
dstRect.w = 1200;
dstRect.h = 800;
if (!FillDrawingLayer(layer, 0, zorder, dstRect)) {
return false;
}
return true;
}
void RenderContextSample::Draw()
{
static int32_t count = 0;
std::shared_ptr<HdiLayerInfo> backgroundLayer = HdiLayerInfo::CreateHdiLayerInfo();
std::shared_ptr<HdiLayerInfo> drawingLayer = HdiLayerInfo::CreateHdiLayerInfo();
do {
std::cout << "+++++++ draw count " << count << std::endl;
if (!DrawBackgroundLayer(backgroundLayer)) {
std::cout << "DrawBackgroundLayer failed!" << std::endl;
return;
}
if (!DrawDrawingLayer(drawingLayer)) {
std::cout << "DrawDrawingLayer failed!" << std::endl;
return;
}
std::vector<LayerInfoPtr> layers;
layers.push_back(backgroundLayer);
layers.push_back(drawingLayer);
output_->SetLayerInfo(layers);
IRect damageRect;
damageRect.x = 0;
damageRect.y = 0;
damageRect.w = display_w;
damageRect.h = display_h;
output_->SetOutputDamage(1, damageRect);
backend_->Repaint(outputs_);
std::cout << "------ draw count " << count << std::endl;
count++;
} while (false);
}
bool RenderContextSample::FillDrawingLayer(std::shared_ptr<HdiLayerInfo> &showLayer, uint32_t index,
uint32_t zorder, IRect &dstRect)
{
if (ProduceDrawingBuffer(drawingWidth, drawingHeight) != SURFACE_ERROR_OK) {
std::cout << "FillDrawingLayer produce cBuffer failed" << std::endl;
return false;
}
OHOS::sptr<SurfaceBuffer> cbuffer = nullptr;
int32_t fence = -1;
int64_t timestamp;
Rect damage;
SurfaceError ret = drawingCSurface->AcquireBuffer(cbuffer, fence, timestamp, damage);
sptr<SyncFence> acquireSyncFence = new SyncFence(fence);
if (ret != SURFACE_ERROR_OK) {
std::cout << "Acquire cBuffer failed: " << ret << std::endl;
return false;
}
IRect srcRect;
srcRect.x = 0;
srcRect.y = 0;
srcRect.w = drawingWidth;
srcRect.h = drawingHeight;
LayerAlpha alpha = { .enPixelAlpha = true };
showLayer->SetSurface(drawingCSurface);
showLayer->SetBuffer(cbuffer, acquireSyncFence, prevBufferMap_[drawingCSurface->GetUniqueId()],
prevFenceMap_[drawingCSurface->GetUniqueId()]);
showLayer->SetZorder(zorder);
showLayer->SetAlpha(alpha);
showLayer->SetTransform(TransformType::ROTATE_NONE);
if (index == 0) {
// COMPOSITION_CLIENT
showLayer->SetCompositionType(CompositionType::COMPOSITION_DEVICE);
} else {
showLayer->SetCompositionType(CompositionType::COMPOSITION_DEVICE);
}
showLayer->SetVisibleRegion(1, srcRect);
showLayer->SetDirtyRegion(srcRect);
showLayer->SetLayerSize(dstRect);
showLayer->SetBlendType(BlendType::BLEND_SRC);
showLayer->SetCropRect(srcRect);
showLayer->SetPreMulti(false);
prevBufferMap_[drawingCSurface->GetUniqueId()] = cbuffer;
prevFenceMap_[drawingCSurface->GetUniqueId()] = acquireSyncFence;
return true;
}
bool RenderContextSample::FillBackGroundLayer(std::shared_ptr<HdiLayerInfo> &showLayer, uint32_t zorder, IRect &dstRect)
{
if (ProduceBackGroundBuffer(dstRect.w, dstRect.h) != SURFACE_ERROR_OK) {
std::cout << "Produce background cBuffer failed" << std::endl;
return false;
}
OHOS::sptr<SurfaceBuffer> cbuffer = nullptr;
int32_t fence = -1;
int64_t timestamp;
Rect damage;
SurfaceError ret = backGroundCSurface->AcquireBuffer(cbuffer, fence, timestamp, damage);
sptr<SyncFence> acquireSyncFence = new SyncFence(fence);
if (ret != SURFACE_ERROR_OK) {
std::cout << "Acquire cBuffer failed" << std::endl;
return false;
}
IRect srcRect;
srcRect.x = 0;
srcRect.y = 0;
srcRect.w = dstRect.w;
srcRect.h = dstRect.h;
LayerAlpha alpha = { .enPixelAlpha = true };
showLayer->SetSurface(backGroundCSurface);
showLayer->SetBuffer(cbuffer, acquireSyncFence, prevBufferMap_[backGroundCSurface->GetUniqueId()],
prevFenceMap_[backGroundCSurface->GetUniqueId()]);
showLayer->SetZorder(zorder);
showLayer->SetAlpha(alpha);
showLayer->SetCompositionType(CompositionType::COMPOSITION_DEVICE);
showLayer->SetVisibleRegion(1, srcRect);
showLayer->SetDirtyRegion(srcRect);
showLayer->SetLayerSize(dstRect);
showLayer->SetBlendType(BlendType::BLEND_SRC);
showLayer->SetCropRect(srcRect);
showLayer->SetPreMulti(false);
prevBufferMap_[backGroundCSurface->GetUniqueId()] = cbuffer;
prevFenceMap_[backGroundCSurface->GetUniqueId()] = acquireSyncFence;
std::cout << "FillBackGroundLayer finished" << std::endl;
return true;
}
void RenderContextSample::CreatePhysicalScreen()
{
screen_ = HdiScreen::CreateHdiScreen(output_->GetScreenId());
screen_->Init();
screen_->GetScreenSupportedModes(displayModeInfos_);
outputs_.push_back(output_);
size_t supportModeNum = displayModeInfos_.size();
if (supportModeNum > 0) {
screen_->GetScreenMode(currentModeIndex_);
for (size_t i = 0; i < supportModeNum; i++) {
if (displayModeInfos_[i].id == static_cast<int32_t>(currentModeIndex_)) {
this->freq_ = displayModeInfos_[i].freshRate;
this->display_w = displayModeInfos_[i].width;
this->display_h = displayModeInfos_[i].height;
}
}
screen_->SetScreenPowerStatus(DispPowerStatus::POWER_STATUS_ON);
screen_->SetScreenMode(currentModeIndex_);
DispPowerStatus powerState;
screen_->SetScreenPowerStatus(DispPowerStatus::POWER_STATUS_ON);
screen_->GetScreenPowerStatus(powerState);
}
DisplayCapability info;
screen_->GetScreenCapability(info);
ready_ = true;
}
void RenderContextSample::OnHotPlugEvent(std::shared_ptr<HdiOutput> &output, bool connected)
{
/*
* Currently, IPC communication cannot be nested. Therefore, Vblank registration can be
* initiated only after the initialization of the device is complete.
*/
output_ = output;
deviceConnected_ = connected;
if (!initDeviceFinished_) {
std::cout << "Init the device has not finished yet" << std::endl;
return;
}
std::cout << "Callback HotPlugEvent, connected is " << connected << std::endl;
if (connected) {
CreatePhysicalScreen();
}
}
void RenderContextSample::DoPrepareCompleted(sptr<Surface> &surface, const struct PrepareCompleteParam &param)
{
BufferRequestConfig requestConfig = {
.width = display_w, // need display width
.height = display_h, // need display height
.strideAlignment = 0x8,
.format = PIXEL_FMT_BGRA_8888,
.usage = HBM_USE_CPU_READ | HBM_USE_CPU_WRITE | HBM_USE_MEM_DMA | HBM_USE_MEM_FB,
.timeout = 0,
};
if (surface == nullptr) {
std::cout << "surface is null" << std::endl;
return;
}
int32_t releaseFence = -1;
sptr<SurfaceBuffer> fbBuffer = nullptr;
SurfaceError ret1 = surface->RequestBuffer(fbBuffer, releaseFence, requestConfig);
if (ret1 != 0) {
std::cout << "RequestBuffer failed " << SurfaceErrorStr(ret1).c_str() << std::endl;
return;
}
sptr<SyncFence> tempFence = new SyncFence(releaseFence);
tempFence->Wait(100);
auto addr = static_cast<uint8_t *>(fbBuffer->GetVirAddr());
int32_t ret2 = memset_s(addr, fbBuffer->GetSize(), 0, fbBuffer->GetSize());
if (ret2 != 0) {
std::cout << "memset_s failed" << std::endl;
}
BufferFlushConfig flushConfig = {
.damage = {
.w = display_w,
.h = display_h,
}
};
/*
* if use GPU produce data, flush with gpu fence
*/
ret2 = surface->FlushBuffer(fbBuffer, -1, flushConfig);
if (ret2 != 0) {
std::cout << "DoPrepareCompleted FlushBuffer failed"<< std::endl;
}
}