10826e83eSopenharmony_ci/* 20826e83eSopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd. 30826e83eSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 40826e83eSopenharmony_ci * you may not use this file except in compliance with the License. 50826e83eSopenharmony_ci * You may obtain a copy of the License at 60826e83eSopenharmony_ci * 70826e83eSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 80826e83eSopenharmony_ci * 90826e83eSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 100826e83eSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 110826e83eSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 120826e83eSopenharmony_ci * See the License for the specific language governing permissions and 130826e83eSopenharmony_ci * limitations under the License. 140826e83eSopenharmony_ci */ 150826e83eSopenharmony_ci 160826e83eSopenharmony_ci#include "nweb_surface_adapter.h" 170826e83eSopenharmony_ci 180826e83eSopenharmony_ci#include <display_type.h> 190826e83eSopenharmony_ci#include <securec.h> 200826e83eSopenharmony_ci#include <sync_fence.h> 210826e83eSopenharmony_ci 220826e83eSopenharmony_ci#include "graphic_common.h" 230826e83eSopenharmony_ci#include "graphic_common_c.h" 240826e83eSopenharmony_ci#include "nweb_log.h" 250826e83eSopenharmony_ci#include "surface_type.h" 260826e83eSopenharmony_ci 270826e83eSopenharmony_cinamespace { 280826e83eSopenharmony_ciconstexpr int BITS_PER_PIXEL = 4; 290826e83eSopenharmony_ci} 300826e83eSopenharmony_ci 310826e83eSopenharmony_cinamespace OHOS::NWeb { 320826e83eSopenharmony_ciclass NWebOutputFrameCallbackImpl : public NWebOutputFrameCallback { 330826e83eSopenharmony_cipublic: 340826e83eSopenharmony_ci NWebOutputFrameCallbackImpl(wptr<Surface> surface, NWebSurfaceAdapter *adapter) : surface_(surface), 350826e83eSopenharmony_ci adapter_(adapter) {} 360826e83eSopenharmony_ci ~NWebOutputFrameCallbackImpl() = default; 370826e83eSopenharmony_ci 380826e83eSopenharmony_ci bool Handle(const char* buffer, uint32_t width, uint32_t height) override 390826e83eSopenharmony_ci { 400826e83eSopenharmony_ci return adapter_->OutputFrameCallback(buffer, width, height, surface_); 410826e83eSopenharmony_ci } 420826e83eSopenharmony_ci 430826e83eSopenharmony_ciprivate: 440826e83eSopenharmony_ci wptr<Surface> surface_ = nullptr; 450826e83eSopenharmony_ci NWebSurfaceAdapter *adapter_ = nullptr; 460826e83eSopenharmony_ci}; 470826e83eSopenharmony_ci 480826e83eSopenharmony_ciNWebSurfaceAdapter &NWebSurfaceAdapter::Instance() 490826e83eSopenharmony_ci{ 500826e83eSopenharmony_ci static NWebSurfaceAdapter surfaceAdapter; 510826e83eSopenharmony_ci return surfaceAdapter; 520826e83eSopenharmony_ci} 530826e83eSopenharmony_ci 540826e83eSopenharmony_cistd::shared_ptr<NWebCreateInfoImpl> NWebSurfaceAdapter::GetCreateInfo(sptr<Surface> surface, 550826e83eSopenharmony_ci std::shared_ptr<NWebEngineInitArgs> initArgs, uint32_t width, uint32_t height, bool incognitoMode) 560826e83eSopenharmony_ci{ 570826e83eSopenharmony_ci std::shared_ptr<NWebCreateInfoImpl> createInfo = std::make_shared<NWebCreateInfoImpl>(); 580826e83eSopenharmony_ci createInfo->SetEngineInitArgs(initArgs); 590826e83eSopenharmony_ci createInfo->SetProducerSurface(reinterpret_cast<void *>(&surface)); 600826e83eSopenharmony_ci 610826e83eSopenharmony_ci if (surface == nullptr) { 620826e83eSopenharmony_ci return createInfo; 630826e83eSopenharmony_ci } 640826e83eSopenharmony_ci 650826e83eSopenharmony_ci createInfo->SetIsIncognitoMode(incognitoMode); 660826e83eSopenharmony_ci createInfo->SetWidth((width == 0) ? (uint32_t)surface->GetDefaultWidth() : width); 670826e83eSopenharmony_ci createInfo->SetHeight((height == 0) ? (uint32_t)surface->GetDefaultHeight() : height); 680826e83eSopenharmony_ci 690826e83eSopenharmony_ci wptr<Surface> surfaceWeak(surface); 700826e83eSopenharmony_ci createInfo->SetOutputFrameCallback(std::make_shared<NWebOutputFrameCallbackImpl>(surfaceWeak, this)); 710826e83eSopenharmony_ci return createInfo; 720826e83eSopenharmony_ci} 730826e83eSopenharmony_ci 740826e83eSopenharmony_cibool NWebSurfaceAdapter::OutputFrameCallback(const char *buffer, uint32_t width, uint32_t height, 750826e83eSopenharmony_ci wptr<Surface> surfaceWeak) 760826e83eSopenharmony_ci{ 770826e83eSopenharmony_ci sptr<Surface> surface = surfaceWeak.promote(); 780826e83eSopenharmony_ci if (surface == nullptr) { 790826e83eSopenharmony_ci WVLOG_E("surface is nullptr or has expired"); 800826e83eSopenharmony_ci return false; 810826e83eSopenharmony_ci } 820826e83eSopenharmony_ci 830826e83eSopenharmony_ci sptr<SurfaceBuffer> surfaceBuffer = this->RequestBuffer(surface, width, height); 840826e83eSopenharmony_ci if (surfaceBuffer == nullptr) { 850826e83eSopenharmony_ci return false; 860826e83eSopenharmony_ci } 870826e83eSopenharmony_ci 880826e83eSopenharmony_ci if (!this->CopyFrame(surfaceBuffer, buffer, width, height)) { 890826e83eSopenharmony_ci surface->CancelBuffer(surfaceBuffer); 900826e83eSopenharmony_ci return false; 910826e83eSopenharmony_ci } 920826e83eSopenharmony_ci 930826e83eSopenharmony_ci return this->FlushBuffer(surface, surfaceBuffer, width, height); 940826e83eSopenharmony_ci} 950826e83eSopenharmony_ci 960826e83eSopenharmony_cisptr<SurfaceBuffer> NWebSurfaceAdapter::RequestBuffer(sptr<Surface> surface, uint32_t width, uint32_t height) 970826e83eSopenharmony_ci{ 980826e83eSopenharmony_ci if (surface == nullptr) { 990826e83eSopenharmony_ci return nullptr; 1000826e83eSopenharmony_ci } 1010826e83eSopenharmony_ci 1020826e83eSopenharmony_ci BufferRequestConfig config = { 1030826e83eSopenharmony_ci .width = width, 1040826e83eSopenharmony_ci .height = height, 1050826e83eSopenharmony_ci .strideAlignment = sizeof(void *), 1060826e83eSopenharmony_ci .format = PIXEL_FMT_RGBA_8888, 1070826e83eSopenharmony_ci .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA, 1080826e83eSopenharmony_ci .timeout = 0, 1090826e83eSopenharmony_ci }; 1100826e83eSopenharmony_ci 1110826e83eSopenharmony_ci sptr<SurfaceBuffer> surfaceBuffer = nullptr; 1120826e83eSopenharmony_ci int32_t releaseFence = -1; 1130826e83eSopenharmony_ci SurfaceError ret = surface->RequestBuffer(surfaceBuffer, releaseFence, config); 1140826e83eSopenharmony_ci if (ret != SURFACE_ERROR_OK) { 1150826e83eSopenharmony_ci WVLOG_E("fail to request buffer from surface, errorcode=%{public}d", ret); 1160826e83eSopenharmony_ci return nullptr; 1170826e83eSopenharmony_ci } 1180826e83eSopenharmony_ci 1190826e83eSopenharmony_ci sptr<SyncFence> tempFence = new (std::nothrow) SyncFence(releaseFence); 1200826e83eSopenharmony_ci if (tempFence == nullptr) { 1210826e83eSopenharmony_ci WVLOG_E("new tempFence failed"); 1220826e83eSopenharmony_ci return nullptr; 1230826e83eSopenharmony_ci } 1240826e83eSopenharmony_ci tempFence->Wait(100); // 100 ms 1250826e83eSopenharmony_ci 1260826e83eSopenharmony_ci return surfaceBuffer; 1270826e83eSopenharmony_ci} 1280826e83eSopenharmony_ci 1290826e83eSopenharmony_cibool NWebSurfaceAdapter::CopyFrame( 1300826e83eSopenharmony_ci sptr<SurfaceBuffer> surfaceBuffer, const char *src, uint32_t width, uint32_t height) 1310826e83eSopenharmony_ci{ 1320826e83eSopenharmony_ci if (surfaceBuffer == nullptr) { 1330826e83eSopenharmony_ci return false; 1340826e83eSopenharmony_ci } 1350826e83eSopenharmony_ci 1360826e83eSopenharmony_ci char *dst = reinterpret_cast<char *>(surfaceBuffer->GetVirAddr()); 1370826e83eSopenharmony_ci if (dst == nullptr) { 1380826e83eSopenharmony_ci WVLOG_E("fail to get buffer addr"); 1390826e83eSopenharmony_ci return false; 1400826e83eSopenharmony_ci } 1410826e83eSopenharmony_ci 1420826e83eSopenharmony_ci uint32_t srcStride = width * BITS_PER_PIXEL; 1430826e83eSopenharmony_ci uint32_t dstStride = (uint32_t)surfaceBuffer->GetStride(); 1440826e83eSopenharmony_ci uint32_t copiedSize = 0; 1450826e83eSopenharmony_ci 1460826e83eSopenharmony_ci for (uint32_t currHeight = 0; currHeight < height; ++currHeight) { 1470826e83eSopenharmony_ci if (copiedSize + dstStride > surfaceBuffer->GetSize()) { 1480826e83eSopenharmony_ci WVLOG_E("copy size overflow, drop this frame(%{public}u*%{public}u)", width, height); 1490826e83eSopenharmony_ci return false; 1500826e83eSopenharmony_ci } 1510826e83eSopenharmony_ci errno_t ret = memcpy_s(dst, static_cast<size_t>(srcStride), src, static_cast<size_t>(srcStride)); 1520826e83eSopenharmony_ci if (ret != EOK) { 1530826e83eSopenharmony_ci WVLOG_E("memcpy_s failed"); 1540826e83eSopenharmony_ci return false; 1550826e83eSopenharmony_ci } 1560826e83eSopenharmony_ci src += srcStride; 1570826e83eSopenharmony_ci dst += dstStride; 1580826e83eSopenharmony_ci copiedSize += dstStride; 1590826e83eSopenharmony_ci } 1600826e83eSopenharmony_ci 1610826e83eSopenharmony_ci return true; 1620826e83eSopenharmony_ci} 1630826e83eSopenharmony_ci 1640826e83eSopenharmony_cibool NWebSurfaceAdapter::FlushBuffer( 1650826e83eSopenharmony_ci sptr<Surface> surface, sptr<SurfaceBuffer> surfaceBuffer, uint32_t width, uint32_t height) 1660826e83eSopenharmony_ci{ 1670826e83eSopenharmony_ci if (surface == nullptr) { 1680826e83eSopenharmony_ci return false; 1690826e83eSopenharmony_ci } 1700826e83eSopenharmony_ci 1710826e83eSopenharmony_ci BufferFlushConfig flushConfig = { 1720826e83eSopenharmony_ci .damage = { 1730826e83eSopenharmony_ci .w = width, 1740826e83eSopenharmony_ci .h = height, 1750826e83eSopenharmony_ci }, 1760826e83eSopenharmony_ci .timestamp = 0, 1770826e83eSopenharmony_ci }; 1780826e83eSopenharmony_ci 1790826e83eSopenharmony_ci SurfaceError ret = surface->FlushBuffer(surfaceBuffer, -1, flushConfig); 1800826e83eSopenharmony_ci if (ret != SURFACE_ERROR_OK) { 1810826e83eSopenharmony_ci WVLOG_E("FAIL flush nweb render frame, ret=%{public}d", ret); 1820826e83eSopenharmony_ci return false; 1830826e83eSopenharmony_ci } 1840826e83eSopenharmony_ci 1850826e83eSopenharmony_ci return true; 1860826e83eSopenharmony_ci} 1870826e83eSopenharmony_ci} // namespace OHOS::NWeb 188