* Copyright (c) 2023 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 "surface_adapter_impl.h"
#include <unordered_map>
#include "v1_0/display_composer_type.h"
#include "nweb_log.h"
namespace OHOS::NWeb {
namespace {
bool IsSupportFormat(int32_t format)
{
switch (format) {
case PIXEL_FMT_RGBA_8888:
case PIXEL_FMT_YCBCR_420_SP:
return true;
default:
return false;
}
}
}
SurfaceBufferAdapterImpl::SurfaceBufferAdapterImpl(sptr<SurfaceBuffer> buffer) : buffer_(buffer) {}
int32_t SurfaceBufferAdapterImpl::GetFileDescriptor()
{
if (!buffer_) {
WVLOG_E("buffer_ is nullptr");
return -1;
}
return buffer_->GetFileDescriptor();
}
int32_t SurfaceBufferAdapterImpl::GetWidth()
{
if (!buffer_) {
WVLOG_E("buffer_ is nullptr");
return -1;
}
return buffer_->GetWidth();
}
int32_t SurfaceBufferAdapterImpl::GetHeight()
{
if (!buffer_) {
WVLOG_E("buffer_ is nullptr");
return -1;
}
return buffer_->GetHeight();
}
int32_t SurfaceBufferAdapterImpl::GetStride()
{
if (!buffer_) {
WVLOG_E("buffer_ is nullptr");
return -1;
}
return buffer_->GetStride();
}
int32_t SurfaceBufferAdapterImpl::GetFormat()
{
if (!buffer_) {
WVLOG_E("buffer_ is nullptr");
return -1;
}
return buffer_->GetFormat();
}
uint32_t SurfaceBufferAdapterImpl::GetSize()
{
if (!buffer_) {
WVLOG_E("buffer_ is nullptr");
return 0;
}
return buffer_->GetSize();
}
void* SurfaceBufferAdapterImpl::GetVirAddr()
{
if (!buffer_) {
WVLOG_E("buffer_ is nullptr");
return nullptr;
}
return buffer_->GetVirAddr();
}
sptr<SurfaceBuffer>& SurfaceBufferAdapterImpl::GetBuffer()
{
return buffer_;
}
BufferConsumerListenerImpl::BufferConsumerListenerImpl(
wptr<IConsumerSurface> surface, std::shared_ptr<IBufferConsumerListenerAdapter> listener)
: cSurface_(surface), listener_(std::move(listener))
{}
void BufferConsumerListenerImpl::OnBufferAvailable()
{
if (cSurface_ == nullptr || listener_ == nullptr) {
WVLOG_E("cSurface_ or listener_ is nullptr");
return;
}
auto surfaceTemp = cSurface_.promote();
if (surfaceTemp == nullptr) {
WVLOG_E("surface is nullptr");
return;
}
sptr<SurfaceBuffer> buffer;
int32_t fence;
int64_t timestamp;
Rect damage;
GSError ret = surfaceTemp->AcquireBuffer(buffer, fence, timestamp, damage);
if (ret != (int32_t)GSERROR_OK) {
WVLOG_E("acquire buffer failed, ret=%{public}d", ret);
return;
}
int32_t format = buffer->GetFormat();
if (!IsSupportFormat(format)) {
WVLOG_E("unsupport format for:%{public}d", format);
surfaceTemp->ReleaseBuffer(buffer, -1);
return;
}
auto bufferAdapter = std::make_shared<SurfaceBufferAdapterImpl>(buffer);
listener_->OnBufferAvailable(std::move(bufferAdapter));
}
ConsumerSurfaceAdapterImpl::ConsumerSurfaceAdapterImpl() : cSurface_(IConsumerSurface::Create()) {}
int32_t ConsumerSurfaceAdapterImpl::RegisterConsumerListener(
std::shared_ptr<IBufferConsumerListenerAdapter> listenerAdapter)
{
if (!cSurface_ || !listenerAdapter) {
WVLOG_E("cSurface_ or listener_ is nullptr");
return -1;
}
sptr<IBufferConsumerListener> listener =
new (std::nothrow) BufferConsumerListenerImpl(cSurface_, std::move(listenerAdapter));
if (!listener) {
WVLOG_E("listener create failed");
return -1;
}
return cSurface_->RegisterConsumerListener(listener);
}
int32_t ConsumerSurfaceAdapterImpl::ReleaseBuffer(std::shared_ptr<SurfaceBufferAdapter> bufferAdapter, int32_t fence)
{
if (!cSurface_ || !bufferAdapter) {
WVLOG_E("cSurface_ or bufferAdapter is nullptr");
return -1;
}
auto bufferImpl = static_cast<SurfaceBufferAdapterImpl*>(bufferAdapter.get());
return cSurface_->ReleaseBuffer(bufferImpl->GetBuffer(), fence);
}
int32_t ConsumerSurfaceAdapterImpl::SetUserData(const std::string& key, const std::string& val)
{
if (!cSurface_) {
WVLOG_E("cSurface_ is nullptr");
return -1;
}
return cSurface_->SetUserData(key, val);
}
int32_t ConsumerSurfaceAdapterImpl::SetQueueSize(uint32_t queueSize)
{
if (!cSurface_) {
WVLOG_E("cSurface_ is nullptr");
return -1;
}
return cSurface_->SetQueueSize(queueSize);
}
sptr<IConsumerSurface>& ConsumerSurfaceAdapterImpl::GetConsumerSurface()
{
return cSurface_;
}
const std::unordered_map<TransformTypeAdapter, GraphicTransformType> TO_TRANSFORM_TYPE_MAP = {
{ TransformTypeAdapter::ROTATE_NONE, GraphicTransformType::GRAPHIC_ROTATE_NONE },
{ TransformTypeAdapter::ROTATE_90, GraphicTransformType::GRAPHIC_ROTATE_90 },
{ TransformTypeAdapter::ROTATE_180, GraphicTransformType::GRAPHIC_ROTATE_180 },
{ TransformTypeAdapter::ROTATE_270, GraphicTransformType::GRAPHIC_ROTATE_270 },
{ TransformTypeAdapter::FLIP_H, GraphicTransformType::GRAPHIC_FLIP_H },
{ TransformTypeAdapter::FLIP_V, GraphicTransformType::GRAPHIC_FLIP_V },
{ TransformTypeAdapter::FLIP_H_ROT90, GraphicTransformType::GRAPHIC_FLIP_H_ROT90 },
{ TransformTypeAdapter::FLIP_V_ROT90, GraphicTransformType::GRAPHIC_FLIP_V_ROT90 },
{ TransformTypeAdapter::FLIP_H_ROT180, GraphicTransformType::GRAPHIC_FLIP_H_ROT180 },
{ TransformTypeAdapter::FLIP_V_ROT180, GraphicTransformType::GRAPHIC_FLIP_V_ROT180 },
{ TransformTypeAdapter::FLIP_H_ROT270, GraphicTransformType::GRAPHIC_FLIP_H_ROT270 },
{ TransformTypeAdapter::FLIP_V_ROT270, GraphicTransformType::GRAPHIC_FLIP_V_ROT270 },
{ TransformTypeAdapter::ROTATE_BUTT, GraphicTransformType::GRAPHIC_ROTATE_BUTT },
};
const std::unordered_map<ColorGamutAdapter, GraphicColorGamut> TO_GRAPHIC_COLOR_GAMUT_MAP = {
{ ColorGamutAdapter::INVALID, GraphicColorGamut::GRAPHIC_COLOR_GAMUT_INVALID },
{ ColorGamutAdapter::NATIVE, GraphicColorGamut::GRAPHIC_COLOR_GAMUT_NATIVE },
{ ColorGamutAdapter::STANDARD_BT601, GraphicColorGamut::GRAPHIC_COLOR_GAMUT_STANDARD_BT601 },
{ ColorGamutAdapter::STANDARD_BT709, GraphicColorGamut::GRAPHIC_COLOR_GAMUT_STANDARD_BT709 },
{ ColorGamutAdapter::DCI_P3, GraphicColorGamut::GRAPHIC_COLOR_GAMUT_DCI_P3 },
{ ColorGamutAdapter::SRGB, GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB },
{ ColorGamutAdapter::ADOBE_RGB, GraphicColorGamut::GRAPHIC_COLOR_GAMUT_ADOBE_RGB },
{ ColorGamutAdapter::DISPLAY_P3, GraphicColorGamut::GRAPHIC_COLOR_GAMUT_DISPLAY_P3 },
{ ColorGamutAdapter::BT2020, GraphicColorGamut::GRAPHIC_COLOR_GAMUT_BT2020 },
{ ColorGamutAdapter::BT2100_PQ, GraphicColorGamut::GRAPHIC_COLOR_GAMUT_BT2100_PQ },
{ ColorGamutAdapter::BT2100_HLG, GraphicColorGamut::GRAPHIC_COLOR_GAMUT_BT2100_HLG },
{ ColorGamutAdapter::DISPLAY_BT2020, GraphicColorGamut::GRAPHIC_COLOR_GAMUT_DISPLAY_BT2020 },
};
ProducerSurfaceAdapterImpl::ProducerSurfaceAdapterImpl(sptr<Surface> surface) : surface_(surface) {}
GraphicTransformType ProducerSurfaceAdapterImpl::TransToTransformType(const TransformTypeAdapter& type)
{
auto item = TO_TRANSFORM_TYPE_MAP.find(type);
if (item == TO_TRANSFORM_TYPE_MAP.end()) {
WVLOG_E("to graphic transform type %{public}d not found", type);
return GraphicTransformType::GRAPHIC_ROTATE_NONE;
}
return item->second;
}
GraphicColorGamut ProducerSurfaceAdapterImpl::TransToGraphicColorGamut(const ColorGamutAdapter& colorGamut)
{
auto item = TO_GRAPHIC_COLOR_GAMUT_MAP.find(colorGamut);
if (item == TO_GRAPHIC_COLOR_GAMUT_MAP.end()) {
WVLOG_E("to graphic color gamut %{public}d not found", colorGamut);
return GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB;
}
return item->second;
}
void ProducerSurfaceAdapterImpl::TransToBufferConfig(
const std::shared_ptr<BufferRequestConfigAdapter> configAdapter, BufferRequestConfig& config)
{
if (!configAdapter) {
WVLOG_E("TransToBufferConfig configAdapter is null");
return;
}
config.width = configAdapter->GetWidth();
config.height = configAdapter->GetHeight();
config.strideAlignment = configAdapter->GetStrideAlignment();
config.format = GRAPHIC_PIXEL_FMT_YCBCR_420_P;
config.usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA;
config.timeout = configAdapter->GetTimeout();
config.colorGamut = TransToGraphicColorGamut(configAdapter->GetColorGamut());
config.transform = TransToTransformType(configAdapter->GetTransformType());
}
std::shared_ptr<SurfaceBufferAdapter> ProducerSurfaceAdapterImpl::RequestBuffer(
int32_t& fence, std::shared_ptr<BufferRequestConfigAdapter> configAdapter)
{
if (!surface_) {
WVLOG_E("Surface_ is nullptr when request");
return nullptr;
}
if (!configAdapter) {
WVLOG_E("configAdapter is nullptr when request");
return nullptr;
}
OHOS::sptr<OHOS::SurfaceBuffer> buffer = nullptr;
BufferRequestConfig config;
TransToBufferConfig(configAdapter, config);
surface_->RequestBuffer(buffer, fence, config);
return std::make_shared<SurfaceBufferAdapterImpl>(buffer);
}
int32_t ProducerSurfaceAdapterImpl::FlushBuffer(std::shared_ptr<SurfaceBufferAdapter> bufferAdapter, int32_t fence,
std::shared_ptr<BufferFlushConfigAdapter> flushConfigAdapter)
{
if (!surface_ || !bufferAdapter || !flushConfigAdapter) {
WVLOG_E("Surface_ or params is nullptr when flush");
return -1;
}
auto bufferImpl = static_cast<SurfaceBufferAdapterImpl*>(bufferAdapter.get());
BufferFlushConfig config;
config.damage.x = flushConfigAdapter->GetX();
config.damage.y = flushConfigAdapter->GetY();
config.damage.w = flushConfigAdapter->GetW();
config.damage.h = flushConfigAdapter->GetH();
config.timestamp = flushConfigAdapter->GetTimestamp();
return surface_->FlushBuffer(bufferImpl->GetBuffer(), fence, config);
}
}