1 /*
2 * Copyright (c) 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 #include "hdi_gles_composition.h"
16 #include "gles_gfx_image.h"
17 #include "display_mock_surface.h"
18 #include "display_utils.h"
19 #include "window.h"
20 namespace OHOS {
21 namespace HDI {
22 namespace DISPLAY {
23 static const char g_vertexShader[] = "attribute vec4 vertexPosition; \n"
24 "attribute vec2 textureCoord; \n"
25 "varying vec2 textureCoordVar; \n"
26 "uniform int width; \n"
27 "uniform int height; \n"
28 "void main() \n"
29 "{ \n"
30 " vec2 zeroToOne = vertexPosition.xy / vec2(width, height);\n"
31 " vec2 zeroToTwo = zeroToOne * 2.0;\n"
32 " vec2 clipSpace = zeroToTwo - 1.0;\n"
33 " gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);\n"
34 " textureCoordVar = textureCoord; \n"
35 "} \n";
36
37 static const char g_textureFragmentShaderRgba[] = "precision mediump float; \n"
38 "varying vec2 textureCoordVar; \n"
39 "uniform sampler2D textureSampler; \n"
40 "void main() \n"
41 "{ \n"
42 " gl_FragColor = texture2D( textureSampler, textureCoordVar );\n"
43 "} \n";
44
45 /* Declare common fragment shader uniforms */
46 #define FRAGMENT_CONVERT_YUV \
47 " gl_FragColor.r = y + 1.59602678 * v;\n" \
48 " gl_FragColor.g = y - 0.39176229 * u - 0.81296764 * v;\n" \
49 " gl_FragColor.b = y + 2.01723214 * u;\n" \
50 " gl_FragColor.a = 1.0;\n" \
51 " } \n"
52
53 static const char g_textureFragmentFhaderYuv[] = "precision mediump float;\n"
54 "uniform sampler2D s_texureY;\n"
55 "uniform sampler2D s_texureU;\n"
56 "uniform sampler2D s_texureV;\n"
57 "varying vec2 textureCoordVar;\n"
58 "void main() {\n"
59 " float y = 1.16438356 * (texture2D(s_texureY, textureCoordVar).x - 0.0625);\n"
60 " float u = texture2D(s_texureU, textureCoordVar).x - 0.5;\n"
61 " float v = texture2D(s_texureV, textureCoordVar).x - 0.5;\n"
62 " gl_FragColor.r = y + 1.59602678 * v;\n"
63 " gl_FragColor.g = y - 0.39176229 * u - 0.81296764 * v;\n"
64 " gl_FragColor.b = y + 2.01723214 * u;\n"
65 " gl_FragColor.a = 1.0;\n"
66 "} \n";
67
68 static const char g_clearfragmentShader[] = "precision mediump float;\n"
69 "void main()\n"
70 "{\n"
71 " gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);\n"
72 "}\n";
73
InitProgram(uint32_t width,uint32_t height)74 int32_t HdiGlesComposition::InitProgram(uint32_t width, uint32_t height)
75 {
76 bool ret;
77 // init the rgba program
78 programRgba_ = std::make_unique<GlesProgram>();
79 DISPLAY_CHK_RETURN((programRgba_ == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("can not create program for rgba"));
80 ret = programRgba_->Init(g_vertexShader, g_textureFragmentShaderRgba);
81 DISPLAY_CHK_RETURN((!ret), DISPLAY_FAILURE, DISPLAY_LOGE("Failed to init rgba program"));
82
83 programRgba_->Use();
84
85 programRgba_->SetUniform("textureSampler", 0);
86 programRgba_->SetUniform("width", static_cast<int32_t>(width));
87 programRgba_->SetUniform("height", static_cast<int32_t>(height));
88 // init the yuv program
89 programYuv_ = std::make_unique<GlesProgram>();
90 DISPLAY_CHK_RETURN((programYuv_ == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("can not create program for rgba"));
91 ret = programYuv_->Init(g_vertexShader, g_textureFragmentFhaderYuv);
92 DISPLAY_CHK_RETURN((!ret), DISPLAY_FAILURE, DISPLAY_LOGE("Failed to init yuv program"));
93
94 programYuv_->Use();
95
96 programYuv_->SetUniform("s_texureY", GlesGfxImage::INDEX_Y_TEXTURE);
97 programYuv_->SetUniform("s_texureU", GlesGfxImage::INDEX_U_TEXTURE);
98 programYuv_->SetUniform("s_texureV", GlesGfxImage::INDEX_V_TEXTURE);
99 programRgba_->SetUniform("width", static_cast<int32_t>(width));
100 programRgba_->SetUniform("height", static_cast<int32_t>(height));
101
102 // init the clear program
103 programClear_ = std::make_unique<GlesProgram>();
104 DISPLAY_CHK_RETURN((programClear_ == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("can not create program for rgba"));
105 programClear_->Init(g_vertexShader, g_clearfragmentShader);
106 DISPLAY_CHK_RETURN((!ret), DISPLAY_FAILURE, DISPLAY_LOGE("Failed to init clear program"));
107
108 programClear_->Use();
109
110 return DISPLAY_SUCCESS;
111 }
112
Init(uint32_t width,uint32_t height)113 int32_t HdiGlesComposition::Init(uint32_t width, uint32_t height)
114 {
115 DISPLAY_LOGD();
116 int32_t ret;
117 OHOS::sptr<OHOS::DisplayMockSurface> mockSurface = new DisplayMockSurface();
118 DISPLAY_CHK_RETURN((mockSurface == nullptr), false, DISPLAY_LOGE("can not create client surface"));
119 if (!mockSurface->Init(width, height)) {
120 DISPLAY_LOGE("Failed to init client surface");
121 return DISPLAY_FAILURE;
122 }
123 clientSurface_ = mockSurface;
124
125 nativeWindow_ = CreateNativeWindowFromSurface(&clientSurface_);
126 DISPLAY_CHK_RETURN((nativeWindow_ == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("Failed create native window"));
127
128 eglState_ = std::make_unique<GlEglState>();
129 DISPLAY_CHK_RETURN((eglState_ == nullptr), DISPLAY_FAILURE, DISPLAY_LOGE("Failed to create eglState"));
130 if (!eglState_->Init(nativeWindow_)) { // todo should get the resolustion
131 DISPLAY_LOGE("can not init EglState");
132 }
133 eglState_->MakeCurrent(); // todo need ?
134 ret = InitProgram(width, height);
135 glViewport(0, 0, width, height);
136 DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("can not init program"));
137 return DISPLAY_SUCCESS;
138 }
139
CanHandle(HdiLayer & hdiLayer)140 bool HdiGlesComposition::CanHandle(HdiLayer &hdiLayer)
141 {
142 DISPLAY_LOGD();
143 return true;
144 }
145
SetLayers(std::vector<HdiLayer * > & layers,HdiLayer & clientLayer)146 int32_t HdiGlesComposition::SetLayers(std::vector<HdiLayer *> &layers, HdiLayer &clientLayer)
147 {
148 DISPLAY_LOGD("layers size %{public}d", layers.size());
149 mClientLayer = &clientLayer;
150 mCompLayers.clear();
151 for (auto &layer : layers) {
152 if (CanHandle(*layer)) {
153 if ((layer->GetCompositionType() != COMPOSITION_VIDEO) &&
154 (layer->GetCompositionType() != COMPOSITION_CURSOR)) {
155 layer->SetDeviceSelect(COMPOSITION_DEVICE);
156 } else {
157 layer->SetDeviceSelect(layer->GetCompositionType());
158 }
159 mCompLayers.push_back(layer);
160 }
161 }
162 DISPLAY_LOGD("composer layers size %{public}d", mCompLayers.size());
163 return DISPLAY_SUCCESS;
164 }
165
Apply(bool modeSet)166 int32_t HdiGlesComposition::Apply(bool modeSet)
167 {
168 int32_t ret;
169 eglState_->MakeCurrent();
170 DISPLAY_LOGD("composer layers size %{public}d", mCompLayers.size());
171 DisplayBytrace trace("gles apply");
172 clientSurface_->SetReleaseFence(mClientLayer->GetReleaseFenceFd());
173 for (uint32_t i = 0; i < mCompLayers.size(); i++) {
174 HdiLayer *layer = mCompLayers[i];
175 CompositionType compType = layer->GetDeviceSelect();
176 switch (compType) {
177 case COMPOSITION_VIDEO:
178 ret = ClearLayer(*layer);
179 DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE,
180 DISPLAY_LOGE("clear layer %{public}d failed", i));
181 break;
182 case COMPOSITION_DEVICE:
183 ret = DrawLayer(*layer);
184 DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE,
185 DISPLAY_LOGE("blit layer %{public}d failed ", i));
186 break;
187 default:
188 DISPLAY_LOGE("the gfx composition can not surpport the type %{public}d", compType);
189 break;
190 }
191 }
192 glFinish(); // now wo no to use fence
193 eglState_->SwapBuffer();
194 clientSurface_->AcquireBufferHandle(*mClientLayer);
195
196 return DISPLAY_SUCCESS;
197 }
198
~HdiGlesComposition()199 HdiGlesComposition::~HdiGlesComposition()
200 {
201 DISPLAY_LOGD();
202 }
203
DrawLayer(HdiLayer & layer)204 int32_t HdiGlesComposition::DrawLayer(HdiLayer &layer)
205 {
206 HdiLayerBuffer *srcBuffer = layer.GetCurrentBuffer();
207 DISPLAY_CHK_RETURN((srcBuffer == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGE("the srcbuffer is null"));
208 DISPLAY_CHK_RETURN((srcBuffer->mHandle == nullptr), DISPLAY_NULL_PTR, DISPLAY_LOGD("the handle is nullptr"));
209 layer.WaitAcquireFence();
210 if (DisplayUtils::IsYuv(static_cast<PixelFormat>(srcBuffer->GetFormat()))) {
211 DISPLAY_LOGD("draw yuv layer");
212 return DrawLayer(*(srcBuffer->mHandle), layer.GetLayerDisplayRect(), *programYuv_);
213 } else {
214 DISPLAY_LOGD("draw rgba layer");
215 return DrawLayer(*(srcBuffer->mHandle), layer.GetLayerDisplayRect(), *programRgba_);
216 }
217 }
218
GetVertexArrays(const IRect & displayRect)219 std::vector<float> HdiGlesComposition::GetVertexArrays(const IRect &displayRect)
220 {
221 std::vector<float> vertexArrays;
222 vertexArrays.push_back((float)(displayRect.x));
223 vertexArrays.push_back((float)(displayRect.y));
224 vertexArrays.push_back((float)(displayRect.x + displayRect.w));
225 vertexArrays.push_back((float)(displayRect.y));
226 vertexArrays.push_back((float)(displayRect.x + displayRect.w));
227 vertexArrays.push_back((float)(displayRect.y + displayRect.h));
228 vertexArrays.push_back((float)(displayRect.x));
229 vertexArrays.push_back((float)(displayRect.y + displayRect.h));
230 return vertexArrays;
231 }
232
ClearLayer(HdiLayer & layer)233 int32_t HdiGlesComposition::ClearLayer(HdiLayer &layer)
234 {
235 DisplayBytrace trace("ClearLayer");
236 DISPLAY_LOGD();
237 glDisable(GL_BLEND);
238 auto vertexArrays = GetVertexArrays(layer.GetLayerDisplayRect());
239 std::vector<float> textureArrays = {
240 0.0f, 0.0f, // TexCoord 0
241 1.0f, 0.0f, // TexCoord 3
242 1.0f, 1.0f, // TexCoord 2
243 0.0f, 1.0f, // TexCoord 1
244 };
245 programClear_->Use();
246 glBindAttribLocation(programClear_->Get(), 0, "vertexPosition");
247 glBindAttribLocation(programClear_->Get(), 1, "textureCoord");
248 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertexArrays.data()); // step 2
249 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, textureArrays.data()); // step 2
250 glEnableVertexAttribArray(0);
251 glEnableVertexAttribArray(1);
252 DisplayBytrace traceDraw("draw");
253 glDrawArrays(GL_TRIANGLE_FAN, 0, 4); // 4 points
254
255 return DISPLAY_SUCCESS;
256 }
257
DrawLayer(const BufferHandle & bufferHandle,const IRect & displayRect,GlesProgram & program)258 int32_t HdiGlesComposition::DrawLayer(const BufferHandle &bufferHandle, const IRect &displayRect, GlesProgram &program)
259 {
260 glEnable(GL_BLEND);
261 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
262 DisplayBytrace trace("DrawLayer");
263 auto img = GlesGfxImage::Creat(eglState_->GetDisplay(), bufferHandle);
264 if (img == nullptr) {
265 DISPLAY_LOGE("Failed to drawlayer imag is nullptr");
266 return DISPLAY_FAILURE;
267 }
268 program.Use();
269 auto vertexArrays = GetVertexArrays(displayRect);
270 std::vector<float> textureArrays = {
271 0.0f, 0.0f, // TexCoord 0
272 1.0f, 0.0f, // TexCoord 3
273 1.0f, 1.0f, // TexCoord 2
274 0.0f, 1.0f, // TexCoord 1
275 };
276 glBindAttribLocation(program.Get(), 0, "vertexPosition");
277 glBindAttribLocation(program.Get(), 1, "textureCoord");
278 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertexArrays.data()); // step 2
279 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, textureArrays.data()); // step 2
280 glEnableVertexAttribArray(0);
281 glEnableVertexAttribArray(1);
282 DisplayBytrace traceDraw("draw");
283 glDrawArrays(GL_TRIANGLE_FAN, 0, 4); // 4 points
284
285 return DISPLAY_SUCCESS;
286 }
287 } // namespace OHOS
288 } // namespace HDI
289 } // namespace DISPLAY
290