1 /*
2  * Copyright (c) 2021-2022 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 "rs_surface_ohos_gl.h"
17 #include "platform/common/rs_log.h"
18 #include "window.h"
19 #include <hilog/log.h>
20 #include "pipeline/rs_render_thread.h"
21 
22 namespace OHOS {
23 namespace Rosen {
24 
RSSurfaceOhosGl(const sptr<Surface> & producer)25 RSSurfaceOhosGl::RSSurfaceOhosGl(const sptr<Surface>& producer) : RSSurfaceOhos(producer)
26 {
27     bufferUsage_ = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_MEM_DMA;
28 }
29 
SetSurfaceBufferUsage(uint64_t usage)30 void RSSurfaceOhosGl::SetSurfaceBufferUsage(uint64_t usage)
31 {
32     bufferUsage_ = usage;
33 }
34 
SetSurfacePixelFormat(int32_t pixelFormat)35 void RSSurfaceOhosGl::SetSurfacePixelFormat(int32_t pixelFormat)
36 {
37     pixelFormat_ = pixelFormat;
38 }
39 
~RSSurfaceOhosGl()40 RSSurfaceOhosGl::~RSSurfaceOhosGl()
41 {
42     if (context_ != nullptr) {
43         context_->DestroyEGLSurface(mEglSurface);
44     }
45     DestoryNativeWindow(mWindow);
46     mWindow = nullptr;
47     mEglSurface = EGL_NO_SURFACE;
48 }
49 
RequestFrame(int32_t width,int32_t height,uint64_t uiTimestamp,bool useAFBC,bool isProtected)50 std::unique_ptr<RSSurfaceFrame> RSSurfaceOhosGl::RequestFrame(int32_t width, int32_t height,
51     uint64_t uiTimestamp, bool useAFBC, bool isProtected)
52 {
53     RenderContext* context = GetRenderContext();
54     if (context == nullptr) {
55         ROSEN_LOGE("RSSurfaceOhosGl::RequestFrame, GetRenderContext failed!");
56         return nullptr;
57     }
58     context->SetColorSpace(colorSpace_);
59     context->SetPixelFormat(pixelFormat_);
60     if (mWindow == nullptr) {
61         mWindow = CreateNativeWindowFromSurface(&producer_);
62         mEglSurface = context->CreateEGLSurface((EGLNativeWindowType)mWindow);
63         ROSEN_LOGD("RSSurfaceOhosGl: create and Init EglSurface");
64     }
65 
66     if (mEglSurface == EGL_NO_SURFACE) {
67         ROSEN_LOGE("RSSurfaceOhosGl: Invalid eglSurface, return");
68         return nullptr;
69     }
70 
71     std::unique_ptr<RSSurfaceFrameOhosGl> frame = std::make_unique<RSSurfaceFrameOhosGl>(width, height);
72 
73     NativeWindowHandleOpt(mWindow, SET_FORMAT, pixelFormat_);
74 #ifdef RS_ENABLE_AFBC
75     if (RSSystemProperties::GetAFBCEnabled()) {
76         int32_t format = 0;
77         NativeWindowHandleOpt(mWindow, GET_FORMAT, &format);
78         if (format == GRAPHIC_PIXEL_FMT_RGBA_8888 && useAFBC) {
79             bufferUsage_ =
80                 (BUFFER_USAGE_HW_RENDER | BUFFER_USAGE_HW_TEXTURE | BUFFER_USAGE_HW_COMPOSER | BUFFER_USAGE_MEM_DMA);
81         }
82     }
83 #endif
84     NativeWindowHandleOpt(mWindow, SET_USAGE, bufferUsage_);
85     NativeWindowHandleOpt(mWindow, SET_BUFFER_GEOMETRY, width, height);
86     NativeWindowHandleOpt(mWindow, GET_BUFFER_GEOMETRY, &mHeight, &mWidth);
87     NativeWindowHandleOpt(mWindow, SET_COLOR_GAMUT, colorSpace_);
88     NativeWindowHandleOpt(mWindow, SET_UI_TIMESTAMP, uiTimestamp);
89 
90     context->MakeCurrent(mEglSurface);
91 
92     ROSEN_LOGD("RSSurfaceOhosGl:RequestFrame, width is %d, height is %d",
93         mWidth, mHeight);
94 
95     frame->SetRenderContext(context);
96 
97     std::unique_ptr<RSSurfaceFrame> ret(std::move(frame));
98 
99     return ret;
100 }
101 
SetUiTimeStamp(const std::unique_ptr<RSSurfaceFrame> & frame,uint64_t uiTimestamp)102 void RSSurfaceOhosGl::SetUiTimeStamp(const std::unique_ptr<RSSurfaceFrame>& frame, uint64_t uiTimestamp)
103 {
104     struct timespec curTime = {0, 0};
105     clock_gettime(CLOCK_MONOTONIC, &curTime);
106     // 1000000000 is used for transfer second to nsec
107     uint64_t duration = static_cast<uint64_t>(curTime.tv_sec) * 1000000000 + static_cast<uint64_t>(curTime.tv_nsec);
108     NativeWindowHandleOpt(mWindow, SET_UI_TIMESTAMP, duration);
109 }
110 
FlushFrame(std::unique_ptr<RSSurfaceFrame> & frame,uint64_t uiTimestamp)111 bool RSSurfaceOhosGl::FlushFrame(std::unique_ptr<RSSurfaceFrame>& frame, uint64_t uiTimestamp)
112 {
113     RenderContext* context = GetRenderContext();
114     if (context == nullptr) {
115         ROSEN_LOGE("RSSurfaceOhosGl::FlushFrame, GetRenderContext failed!");
116         return false;
117     }
118 
119     // gpu render flush
120     context->RenderFrame();
121     context->SwapBuffers(mEglSurface);
122     ROSEN_LOGD("RSSurfaceOhosGl: FlushFrame, SwapBuffers eglsurface");
123     return true;
124 }
125 
ClearBuffer()126 void RSSurfaceOhosGl::ClearBuffer()
127 {
128     if (context_ != nullptr && mEglSurface != EGL_NO_SURFACE && producer_ != nullptr) {
129         ROSEN_LOGD("RSSurfaceOhosGl: Clear surface buffer!");
130         DestoryNativeWindow(mWindow);
131         context_->MakeCurrent(EGL_NO_SURFACE);
132         context_->DestroyEGLSurface(mEglSurface);
133         mEglSurface = EGL_NO_SURFACE;
134         mWindow = nullptr;
135         producer_->GoBackground();
136     }
137 }
138 
ResetBufferAge()139 void RSSurfaceOhosGl::ResetBufferAge()
140 {
141     if (context_ != nullptr && mEglSurface != EGL_NO_SURFACE && producer_ != nullptr) {
142         ROSEN_LOGD("RSSurfaceOhosGl: Reset Buffer Age!");
143         DestoryNativeWindow(mWindow);
144         context_->MakeCurrent(EGL_NO_SURFACE, context_->GetEGLContext());
145         context_->DestroyEGLSurface(mEglSurface);
146         mEglSurface = EGL_NO_SURFACE;
147         mWindow = nullptr;
148     }
149 }
150 } // namespace Rosen
151 } // namespace OHOS
152