• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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