1 /*
2  * Copyright (C) 2024 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 "render_environment.h"
17 
18 #include <GLES2/gl2ext.h>
19 
20 #include "effect_trace.h"
21 #include "effect_log.h"
22 #include "effect_memory.h"
23 #include "format_helper.h"
24 #include "base/math/math_utils.h"
25 
26 namespace OHOS {
27 namespace Media {
28 namespace Effect {
29 const char* const DEFAULT_FSHADER = "#extension GL_OES_EGL_image_external : require\n"
30     "precision highp float;\n"
31     "uniform samplerExternalOES inputTexture;\n"
32     "varying vec2 textureCoordinate;\n"
33     "void main()\n"
34     "{\n"
35     "    gl_FragColor = texture2D(inputTexture, textureCoordinate);\n"
36     "}\n";
37 
38 constexpr const static int RGB_PLANE_SIZE = 3;
39 constexpr const static int G_POS = 1;
40 constexpr const static int B_POS = 2;
41 constexpr const static int UV_PLANE_SIZE = 2;
42 
GetEGLStatus() const43 EGLStatus RenderEnvironment::GetEGLStatus() const
44 {
45     return isEGLReady;
46 }
47 
Init()48 void RenderEnvironment::Init()
49 {
50     EFFECT_LOGI("RenderEnvironment start init");
51     EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
52     if (eglInitialize(display, nullptr, nullptr) == EGL_FALSE) {
53         EFFECT_LOGE("EGL Initialize failed");
54     }
55     param_ = new RenderParam();
56     param_->context_ = new RenderContext();
57 
58     if (param_->context_->Init()) {
59         isEGLReady = EGLStatus::READY;
60     }
61 }
62 
Prepare()63 void RenderEnvironment::Prepare()
64 {
65     if (param_->context_->MakeCurrent(screenSurface_)) {
66         param_->renderer_ = new RenderOpenglRenderer();
67         InitDefaultShaderMT(param_);
68         InitDefaultMeshMT(param_);
69         param_->threadReady_ = true;
70     } else {
71         param_->threadReady_ = false;
72     }
73 }
74 
CreateMeshMT(RenderParam *param, bool isBackGround, RenderGeneralProgram *shader)75 RenderMesh *RenderEnvironment::CreateMeshMT(RenderParam *param, bool isBackGround, RenderGeneralProgram *shader)
76 {
77     const std::vector<std::vector<float>> meshData = isBackGround ? DEFAULT_FLIP_VERTEX_DATA : DEFAULT_VERTEX_DATA;
78     RenderMesh *mesh = new RenderMesh(meshData);
79     mesh->Bind(shader);
80     return mesh;
81 }
82 
InitDefaultMeshMT(RenderParam *param)83 void RenderEnvironment::InitDefaultMeshMT(RenderParam *param)
84 {
85     param->meshBase_ = CreateMeshMT(param, false, param->shaderBase_);
86     param->meshBaseFlip_ = CreateMeshMT(param, true, param->shaderBase_);
87     param->meshBaseDMA_ = CreateMeshMT(param, false, param->shaderBaseDMA_);
88     param->meshBaseFlipYUVDMA_ = CreateMeshMT(param, true, param->shaderBaseYUVDMA2RGB2D_);
89     param->meshBaseYUVDMA_ = CreateMeshMT(param, false, param->shaderBaseYUVDMA2RGB2D_);
90     param->meshBaseDrawFrame_ = CreateMeshMT(param, false, param->shaderBaseDrawFrame_);
91     param->meshBaseDrawFrameYUV_ = CreateMeshMT(param, true, param->shaderBaseDrawFrameYUV_);
92 }
93 
InitDefaultShaderMT(RenderParam *param)94 void RenderEnvironment::InitDefaultShaderMT(RenderParam *param)
95 {
96     param->shaderBase_ = new RenderGeneralProgram(param->context_, DEFAULT_VERTEX_SHADER_SCREEN_CODE,
97         DEFAULT_FRAGMENT_SHADER_CODE);
98     param->shaderBase_->Init();
99     param->shaderBaseDMA_ = new RenderGeneralProgram(param->context_, DEFAULT_VERTEX_SHADER_SCREEN_CODE,
100         DEFAULT_FSHADER);
101     param->shaderBaseDMA_->Init();
102     param->shaderBaseYUVDMA_ = new RenderGeneralProgram(param->context_, DEFAULT_YUV_VERTEX_SHADER,
103         DEFAULT_YUV_SHADER_CODE);
104     param->shaderBaseYUVDMA_->Init();
105     param->shaderBaseYUVDMA2RGB2D_ = new RenderGeneralProgram(param->context_, DEFAULT_YUV_VERTEX_SHADER,
106         DEFAULT_YUV_RGBA_SHADER_CODE);
107     param->shaderBaseYUVDMA2RGB2D_->Init();
108     param->shaderBaseRGB2D2YUVDMA_ = new RenderGeneralProgram(param->context_, DEFAULT_YUV_VERTEX_SHADER,
109         DEFAULT_RGBA_YUV_SHADER_CODE);
110     param->shaderBaseRGB2D2YUVDMA_->Init();
111     param->shaderBaseDrawFrame_ = new RenderGeneralProgram(param->context_, TRANSFORM_VERTEX_SHADER_SCREEN_CODE,
112         DEFAULT_FRAGMENT_SHADER_CODE);
113     param->shaderBaseDrawFrame_->Init();
114     param->shaderBaseDrawFrameYUV_ = new RenderGeneralProgram(param->context_, TRANSFORM_YUV_VERTEX_SHADER,
115         DEFAULT_YUV_RGBA_SHADER_CODE);
116     param->shaderBaseDrawFrameYUV_->Init();
117 }
118 
InitEngine(OHNativeWindow *window)119 void RenderEnvironment::InitEngine(OHNativeWindow *window)
120 {
121     EFFECT_LOGI("RenderEnvironment InitEngine start");
122     if (window_ != nullptr) {
123         return;
124     }
125     window_ = window;
126     screenSurface_ = new RenderSurface(std::string());
127     screenSurface_->SetAttrib(attribute_);
128     screenSurface_->Create(window);
129 }
130 
BeginFrame()131 bool RenderEnvironment::BeginFrame()
132 {
133     return param_->context_->MakeCurrent(screenSurface_);
134 }
135 
RequestBuffer(int width, int height)136 RenderTexturePtr RenderEnvironment::RequestBuffer(int width, int height)
137 {
138     RenderTexturePtr renderTex = param_->resCache_->RequestTexture(param_->context_, width, height, GL_RGBA8);
139     return renderTex;
140 }
141 
IsPrepared() const142 bool RenderEnvironment::IsPrepared() const
143 {
144     return param_->threadReady_;
145 }
146 
GenMainTex(const std::shared_ptr<EffectBuffer> &source, std::shared_ptr<EffectBuffer> &output)147 void RenderEnvironment::GenMainTex(const std::shared_ptr<EffectBuffer> &source, std::shared_ptr<EffectBuffer> &output)
148 {
149     std::shared_ptr<BufferInfo> info =source->bufferInfo_;
150     int width = static_cast<int>(info->width_);
151     int height = static_cast<int>(info->height_);
152     RenderTexturePtr renderTex;
153     bool needRender = true;
154     renderTex = param_->resCache_->GetTexGlobalCache("Main");
155     if (renderTex == nullptr || hasInputChanged) {
156         renderTex = param_->resCache_->RequestTexture(param_->context_, width, height, GL_RGBA8);
157         param_->resCache_->AddTexGlobalCache("Main", renderTex);
158     } else {
159         needRender = false;
160     }
161 
162     if (needRender || hasInputChanged) {
163         DrawBufferToTexture(renderTex, source.get());
164         hasInputChanged = false;
165     }
166 
167     if (outType_ == DataType::NATIVE_WINDOW) {
168         RenderTexturePtr tempTex = param_->resCache_->RequestTexture(param_->context_, width, height, GL_RGBA8);
169         DrawFlipTex(renderTex, tempTex);
170         renderTex = tempTex;
171     }
172     output = GenTexEffectBuffer(source);
173     output->bufferInfo_->formatType_ = IEffectFormat::RGBA8888;
174     output->tex = renderTex;
175 }
176 
DrawFlipTex(RenderTexturePtr input, RenderTexturePtr output)177 void RenderEnvironment::DrawFlipTex(RenderTexturePtr input, RenderTexturePtr output)
178 {
179     GLuint tempFbo = GLUtils::CreateFramebuffer(output->GetName());
180     RenderViewport vp(0, 0, input->Width(), input->Height());
181     param_->renderer_->Draw(input->GetName(), tempFbo, param_->meshBaseFlip_, param_->shaderBase_, &vp, GL_TEXTURE_2D);
182     GLUtils::DeleteFboOnly(tempFbo);
183 }
184 
ConvertBufferToTexture(EffectBuffer *source)185 std::shared_ptr<EffectBuffer> RenderEnvironment::ConvertBufferToTexture(EffectBuffer *source)
186 {
187     std::shared_ptr<BufferInfo> info = source->bufferInfo_;
188     int width = static_cast<int>(info->width_);
189     int height = static_cast<int>(info->height_);
190     RenderTexturePtr renderTex = param_->resCache_->RequestTexture(param_->context_, width, height, GL_RGBA8);
191     DrawBufferToTexture(renderTex, source);
192 
193     std::shared_ptr<BufferInfo> bufferInfo = std::make_unique<BufferInfo>();
194     bufferInfo->width_ = info->width_;
195     bufferInfo->height_ = info->height_;
196     bufferInfo->rowStride_ = info->rowStride_;
197     bufferInfo->len_ = info->len_;
198     bufferInfo->formatType_ = info->formatType_;
199     std::shared_ptr<ExtraInfo> extraInfo = std::make_unique<ExtraInfo>();
200     extraInfo->dataType = DataType::TEX;
201     std::shared_ptr<EffectBuffer> output = std::make_shared<EffectBuffer>(bufferInfo, nullptr, extraInfo);
202     output->tex = renderTex;
203     return output;
204 }
205 
NotifyInputChanged()206 void RenderEnvironment::NotifyInputChanged()
207 {
208     hasInputChanged = true;
209 }
210 
IfNeedGenMainTex() const211 bool RenderEnvironment::IfNeedGenMainTex() const
212 {
213     return hasInputChanged;
214 }
215 
UpdateCanvas()216 void RenderEnvironment::UpdateCanvas()
217 {
218     if (window_ != nullptr) {
219         OH_NativeWindow_NativeWindowHandleOpt(window_, GET_BUFFER_GEOMETRY, &canvasHeight, &canvasWidth);
220         param_->viewport_.Set(0, 0, canvasWidth, canvasHeight);
221     }
222 }
223 
DrawBufferToTexture(RenderTexturePtr renderTex, const EffectBuffer *source)224 void RenderEnvironment::DrawBufferToTexture(RenderTexturePtr renderTex, const EffectBuffer *source)
225 {
226     int width = static_cast<int>(source->bufferInfo_->width_);
227     int height = static_cast<int>(source->bufferInfo_->height_);
228     if (source->extraInfo_->surfaceBuffer != nullptr) {
229         source->extraInfo_->surfaceBuffer->FlushCache();
230         DrawTexFromSurfaceBuffer(renderTex, source->extraInfo_->surfaceBuffer);
231     } else {
232         GLuint tex;
233         GLuint tempFbo = GLUtils::CreateFramebuffer(renderTex->GetName());
234         if (source->bufferInfo_->formatType_ == IEffectFormat::RGBA8888) {
235             int stride = static_cast<int>(source->bufferInfo_->rowStride_) / 4;
236             tex = GenTextureWithPixels(source->buffer_, width, height, stride);
237         } else {
238             tex = ConvertFromYUVToRGB(source, source->bufferInfo_->formatType_);
239         }
240         RenderViewport vp(0, 0, renderTex->Width(), renderTex->Height());
241         param_->renderer_->Draw(tex, tempFbo, param_->meshBase_, param_->shaderBase_, &vp, GL_TEXTURE_2D);
242         glBindTexture(GL_TEXTURE_2D, 0);
243         GLUtils::DeleteTexture(tex);
244         GLUtils::DeleteFboOnly(tempFbo);
245     }
246 }
247 
ConvertFromYUVToRGB(const EffectBuffer *source, IEffectFormat format)248 GLuint RenderEnvironment::ConvertFromYUVToRGB(const EffectBuffer *source, IEffectFormat format)
249 {
250     uint32_t width = source->bufferInfo_->width_;
251     uint32_t height = source->bufferInfo_->height_;
252     auto *srcNV12 = static_cast<unsigned char *>(source->buffer_);
253     uint8_t *srcNV12UV = srcNV12 + width * height;
254     auto data = std::make_unique<unsigned char[]>(width * height * RGBA_SIZE_PER_PIXEL);
255     for (uint32_t i = 0; i < height; i++) {
256         for (uint32_t j = 0; j < width; j++) {
257             uint32_t nv_index = i / UV_PLANE_SIZE * width + j - j % UV_PLANE_SIZE; // 2 mean u/v split factor
258             uint32_t y_index = i * width + j;
259 
260             uint8_t y;
261             uint8_t u;
262             uint8_t v;
263             if (format == IEffectFormat::YUVNV12) {
264                 y = srcNV12[y_index];
265                 u = srcNV12UV[nv_index];
266                 v = srcNV12UV[nv_index + 1];
267             } else {
268                 y = srcNV12[y_index];
269                 v = srcNV12UV[nv_index];
270                 u = srcNV12UV[nv_index + 1];
271             }
272             uint8_t r = FormatHelper::YuvToR(y, u, v);
273             uint8_t g = FormatHelper::YuvToG(y, u, v);
274             uint8_t b = FormatHelper::YuvToB(y, u, v);
275             uint32_t rgb_index = i * width * RGB_PLANE_SIZE + j * RGB_PLANE_SIZE;
276             data[rgb_index] = r;
277             data[rgb_index + G_POS] = g;
278             data[rgb_index + B_POS] = b;
279         }
280     }
281     GLuint tex = GLUtils::CreateTexWithStorage(GL_TEXTURE_2D, 1, GL_RGB, width, height);
282     return tex;
283 }
284 
ConvertFromRGBToYUV(RenderTexturePtr input, IEffectFormat format, void *data)285 void RenderEnvironment::ConvertFromRGBToYUV(RenderTexturePtr input, IEffectFormat format, void *data)
286 {
287     uint32_t width = input->Width();
288     uint32_t height = input->Height();
289     auto rgbData = std::make_unique<unsigned char[]>(width * height * RGBA_SIZE_PER_PIXEL);
290     ReadPixelsFromTex(input, rgbData.get(), width, height, width);
291     auto *srcNV12 = static_cast<unsigned char *>(data);
292     uint8_t *srcNV12UV = srcNV12 + width * height;
293     for (uint32_t i = 0; i < height; i++) {
294         for (uint32_t j = 0; j < width; j++) {
295             uint32_t y_index = i * width + j;
296             uint32_t nv_index = i / UV_PLANE_SIZE * width + j - j % UV_PLANE_SIZE; // 2 mean u/v split factor
297             uint32_t rgb_index = i * width * RGBA_SIZE_PER_PIXEL + j * RGBA_SIZE_PER_PIXEL;
298             uint8_t r = rgbData[rgb_index];
299             uint8_t g = rgbData[rgb_index + G_POS];
300             uint8_t b = rgbData[rgb_index + B_POS];
301             srcNV12[y_index] = FormatHelper::RGBToY(r, g, b);
302             if (format == IEffectFormat::YUVNV12) {
303                 srcNV12UV[nv_index] = FormatHelper::RGBToU(r, g, b);
304                 srcNV12UV[nv_index + 1] = FormatHelper::RGBToV(r, g, b);
305             } else {
306                 srcNV12UV[nv_index] = FormatHelper::RGBToV(r, g, b);
307                 srcNV12UV[nv_index + 1] = FormatHelper::RGBToU(r, g, b);
308             }
309         }
310     }
311 }
312 
GetContext()313 RenderContext *RenderEnvironment::GetContext()
314 {
315     return param_->context_;
316 }
317 
GetResourceCache()318 ResourceCache *RenderEnvironment::GetResourceCache()
319 {
320     return param_->resCache_;
321 }
322 
GetTransformMatrix(GraphicTransformType type)323 glm::mat4 GetTransformMatrix(GraphicTransformType type)
324 {
325     glm::mat4 trans = glm::mat4(1.0f);
326     switch (type) {
327         case GRAPHIC_ROTATE_90:
328             trans = glm::rotate(trans, glm::radians(90.0f), glm::vec3(0.0, 0.0, 1.0));
329             break;
330         case GRAPHIC_ROTATE_180:
331             trans = glm::rotate(trans, glm::radians(180.0f), glm::vec3(0.0, 0.0, 1.0));
332             break;
333         case GRAPHIC_ROTATE_270:
334             trans = glm::rotate(trans, glm::radians(270.0f), glm::vec3(0.0, 0.0, 1.0));
335             break;
336         default:
337             break;
338     }
339     return trans;
340 }
341 
DrawFrameWithTransform(const std::shared_ptr<EffectBuffer> &buffer, GraphicTransformType type)342 void RenderEnvironment::DrawFrameWithTransform(const std::shared_ptr<EffectBuffer> &buffer, GraphicTransformType type)
343 {
344     if (param_ != nullptr) {
345         BeginFrame();
346         UpdateCanvas();
347         glBindFramebuffer(GL_FRAMEBUFFER, 0);
348         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
349         glm::mat4 trans = GetTransformMatrix(type);
350         if (buffer->tex == nullptr) {
351             EFFECT_LOGE("RenderEnvironment DrawFrameWithTransform tex is nullptr");
352             return;
353         }
354         param_->renderer_->DrawOnScreen(buffer->tex->GetName(), param_->meshBaseDrawFrame_,
355             param_->shaderBaseDrawFrame_, &param_->viewport_, MathUtils::NativePtr(trans), GL_TEXTURE_2D);
356 
357         if (screenSurface_ == nullptr) {
358             EFFECT_LOGE("RenderEnvironment screenSurface_ is nullptr");
359             return;
360         }
361         param_->context_->SwapBuffers(screenSurface_);
362         GLUtils::CheckError(__FILE_NAME__, __LINE__);
363     }
364 }
365 
DrawFrame(GLuint texId, GraphicTransformType type)366 void RenderEnvironment::DrawFrame(GLuint texId, GraphicTransformType type)
367 {
368     if (param_ != nullptr) {
369         BeginFrame();
370         UpdateCanvas();
371         glBindFramebuffer(GL_FRAMEBUFFER, 0);
372         glClearColor(1.0, 0, 0, 0);
373         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
374 
375         RenderMesh *mesh = new RenderMesh(DEFAULT_FLIP_VERTEX_DATA);
376         mesh->Bind(param_->shaderBaseDrawFrameYUV_);
377         param_->renderer_->DrawOnScreenWithTransform(texId, mesh,
378             param_->shaderBaseDrawFrameYUV_, &param_->viewport_, type, GL_TEXTURE_EXTERNAL_OES);
379         glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
380         if (screenSurface_ == nullptr) {
381             EFFECT_LOGE("RenderEnvironment screenSurface_ is nullptr");
382             delete(mesh);
383             mesh = nullptr;
384             return;
385         }
386         param_->context_->SwapBuffers(screenSurface_);
387         GLUtils::CheckError(__FILE_NAME__, __LINE__);
388     }
389 }
390 
ConvertTextureToBuffer(RenderTexturePtr source, EffectBuffer *output)391 void RenderEnvironment::ConvertTextureToBuffer(RenderTexturePtr source, EffectBuffer *output)
392 {
393     int w = static_cast<int>(source->Width());
394     int h = static_cast<int>(source->Height());
395     if (output->extraInfo_->surfaceBuffer == nullptr) {
396         if (output->bufferInfo_->formatType_ == IEffectFormat::RGBA8888) {
397             ReadPixelsFromTex(source, output->buffer_, w, h, output->bufferInfo_->rowStride_ / RGBA_SIZE_PER_PIXEL);
398         } else {
399             ConvertFromRGBToYUV(source, output->bufferInfo_->formatType_, output->buffer_);
400         }
401     } else {
402         DrawSurfaceBufferFromTex(source, output->extraInfo_->surfaceBuffer, output->bufferInfo_->formatType_);
403     }
404     GLUtils::CheckError(__FILE_NAME__, __LINE__);
405 }
406 
ConvertYUV2RGBA(std::shared_ptr<EffectBuffer> &source, std::shared_ptr<EffectBuffer> &out)407 void RenderEnvironment::ConvertYUV2RGBA(std::shared_ptr<EffectBuffer> &source, std::shared_ptr<EffectBuffer> &out)
408 {
409     int width = static_cast<int>(source->bufferInfo_->width_);
410     int height = static_cast<int>(source->bufferInfo_->height_);
411     RenderTexturePtr outTex;
412     if (source->extraInfo_->surfaceBuffer == nullptr) {
413         outTex = std::make_shared<RenderTexture>(param_->context_, width, height, GL_RGBA8);
414         outTex->SetName(ConvertFromYUVToRGB(source.get(), source->bufferInfo_->formatType_));
415     } else {
416         outTex = param_->resCache_->RequestTexture(param_->context_, width, height, GL_RGBA8);
417         EGLImageKHR img = GLUtils::CreateEGLImage(eglGetDisplay(EGL_DEFAULT_DISPLAY),
418             source->extraInfo_->surfaceBuffer);
419         GLuint sourceTex = GLUtils::CreateTextureFromImage(img);
420         GLuint tempFbo = GLUtils::CreateFramebufferWithTarget(outTex->GetName(), GL_TEXTURE_2D);
421         RenderViewport vp(0, 0, width, height);
422         param_->renderer_->Draw(sourceTex, tempFbo, param_->meshBaseFlipYUVDMA_, param_->shaderBaseYUVDMA2RGB2D_, &vp,
423             GL_TEXTURE_EXTERNAL_OES);
424         glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
425         GLUtils::DestroyImage(img);
426     }
427 
428     out = GenTexEffectBuffer(source);
429     out->bufferInfo_->formatType_ = IEffectFormat::RGBA8888;
430     out->tex = outTex;
431     GLUtils::CheckError(__FILE_NAME__, __LINE__);
432 }
433 
ConvertRGBA2YUV(std::shared_ptr<EffectBuffer> &source, std::shared_ptr<EffectBuffer> &out)434 void RenderEnvironment::ConvertRGBA2YUV(std::shared_ptr<EffectBuffer> &source, std::shared_ptr<EffectBuffer> &out)
435 {
436     int width = static_cast<int>(source->bufferInfo_->width_);
437     int height = static_cast<int>(source->bufferInfo_->height_);
438     RenderTexturePtr sourceTex = source->tex;
439     EGLImageKHR img = GLUtils::CreateEGLImage(eglGetDisplay(EGL_DEFAULT_DISPLAY), out->extraInfo_->surfaceBuffer);
440     GLuint outTex = GLUtils::CreateTextureFromImage(img);
441     RenderTexturePtr tex = std::make_shared<RenderTexture>(param_->context_, width, height, GL_RGBA8);
442     tex->SetName(outTex);
443     Draw2D2OES(sourceTex, tex);
444     glFinish();
445     GLUtils::DestroyImage(img);
446 }
447 
Draw2D2OES(RenderTexturePtr source, RenderTexturePtr output)448 void RenderEnvironment::Draw2D2OES(RenderTexturePtr source, RenderTexturePtr output)
449 {
450     int w = static_cast<int>(source->Width());
451     int h = static_cast<int>(source->Height());
452     GLuint tempFbo = GLUtils::CreateFramebufferWithTarget(output->GetName(), GL_TEXTURE_EXTERNAL_OES);
453     RenderViewport vp(0, 0, w, h);
454     param_->renderer_->Draw(source->GetName(), tempFbo, param_->meshBaseDMA_, param_->shaderBaseRGB2D2YUVDMA_, &vp,
455         GL_TEXTURE_2D);
456     glBindTexture(GL_TEXTURE_2D, 0);
457     GLUtils::CheckError(__FILE_NAME__, __LINE__);
458 }
459 
ReadPixelsFromTex(RenderTexturePtr tex, void *data, int width, int height, int stride)460 void RenderEnvironment::ReadPixelsFromTex(RenderTexturePtr tex, void *data, int width, int height, int stride)
461 {
462     GLuint inFbo = GLUtils::CreateFramebuffer(tex->GetName());
463     glBindFramebuffer(GL_FRAMEBUFFER, inFbo);
464     glPixelStorei(GL_PACK_ROW_LENGTH, stride);
465     glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
466     glPixelStorei(GL_PACK_ROW_LENGTH, 0);
467     glBindFramebuffer(GL_FRAMEBUFFER, GL_NONE);
468     GLUtils::DeleteFboOnly(inFbo);
469 }
470 
GenTextureWithPixels(void *data, int width, int height, int stride)471 GLuint RenderEnvironment::GenTextureWithPixels(void *data, int width, int height, int stride)
472 {
473     GLuint tex = GLUtils::CreateTexWithStorage(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
474     glBindTexture(GL_TEXTURE_2D, tex);
475     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
476     if (width == stride) {
477         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
478     } else {
479         glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
480         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
481         glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
482     }
483     return tex;
484 }
485 
DrawSurfaceBufferFromTex(RenderTexturePtr tex, SurfaceBuffer *buffer, IEffectFormat format)486 void RenderEnvironment::DrawSurfaceBufferFromTex(RenderTexturePtr tex, SurfaceBuffer *buffer, IEffectFormat format)
487 {
488     EGLImageKHR img = GLUtils::CreateEGLImage(eglGetDisplay(EGL_DEFAULT_DISPLAY), buffer);
489     GLuint outTex = GLUtils::CreateTextureFromImage(img);
490     GLuint tempFbo = GLUtils::CreateFramebufferWithTarget(outTex, GL_TEXTURE_EXTERNAL_OES);
491     RenderViewport vp(0, 0, tex->Width(), tex->Height());
492     if (format == IEffectFormat::RGBA8888) {
493         param_->renderer_->Draw(tex->GetName(), tempFbo, param_->meshBase_, param_->shaderBase_, &vp, GL_TEXTURE_2D);
494     } else {
495         param_->renderer_->Draw(tex->GetName(), tempFbo, param_->meshBaseDMA_, param_->shaderBaseRGB2D2YUVDMA_, &vp,
496             GL_TEXTURE_2D);
497     }
498     glBindTexture(GL_TEXTURE_2D, 0);
499     glFinish();
500     GLUtils::DeleteTexture(outTex);
501     GLUtils::DeleteFboOnly(tempFbo);
502     GLUtils::DestroyImage(img);
503     GLUtils::CheckError(__FILE_NAME__, __LINE__);
504 }
505 
DrawFlipSurfaceBufferFromTex(RenderTexturePtr tex, SurfaceBuffer *buffer, IEffectFormat format)506 void RenderEnvironment::DrawFlipSurfaceBufferFromTex(RenderTexturePtr tex, SurfaceBuffer *buffer, IEffectFormat format)
507 {
508     EGLImageKHR img = GLUtils::CreateEGLImage(eglGetDisplay(EGL_DEFAULT_DISPLAY), buffer);
509     GLuint outTex = GLUtils::CreateTextureFromImage(img);
510     GLuint tempFbo = GLUtils::CreateFramebufferWithTarget(outTex, GL_TEXTURE_EXTERNAL_OES);
511     RenderViewport vp(0, 0, tex->Width(), tex->Height());
512     if (format == IEffectFormat::RGBA8888) {
513         param_->renderer_->Draw(tex->GetName(), tempFbo, param_->meshBaseFlip_, param_->shaderBase_, &vp,
514             GL_TEXTURE_2D);
515     } else {
516         param_->renderer_->Draw(tex->GetName(), tempFbo, param_->meshBaseFlipYUVDMA_, param_->shaderBaseRGB2D2YUVDMA_,
517             &vp, GL_TEXTURE_2D);
518     }
519     glBindTexture(GL_TEXTURE_2D, 0);
520     glFinish();
521     GLUtils::DeleteTexture(outTex);
522     GLUtils::DeleteFboOnly(tempFbo);
523     GLUtils::DestroyImage(img);
524     GLUtils::CheckError(__FILE_NAME__, __LINE__);
525 }
526 
DrawTexFromSurfaceBuffer(RenderTexturePtr tex, SurfaceBuffer *buffer, IEffectFormat format)527 void RenderEnvironment::DrawTexFromSurfaceBuffer(RenderTexturePtr tex, SurfaceBuffer *buffer, IEffectFormat format)
528 {
529     CHECK_AND_RETURN_LOG(tex != nullptr, "DrawTexFromSurfaceBuffer: tex is null!");
530     GLuint tempFbo = GLUtils::CreateFramebuffer(tex->GetName());
531     EGLImageKHR img = GLUtils::CreateEGLImage(eglGetDisplay(EGL_DEFAULT_DISPLAY), buffer);
532     GLuint input = GLUtils::CreateTextureFromImage(img);
533     RenderViewport vp(0, 0, tex->Width(), tex->Height());
534     RenderGeneralProgram *program;
535     RenderMesh *mesh;
536     if (format == IEffectFormat::RGBA8888) {
537         program = param_->shaderBaseDMA_;
538         mesh = param_->meshBaseDMA_;
539     } else {
540         program = param_->shaderBaseYUVDMA2RGB2D_;
541         mesh = param_->meshBaseYUVDMA_;
542     }
543     param_->renderer_->Draw(input, tempFbo, mesh, program, &vp, GL_TEXTURE_EXTERNAL_OES);
544     glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
545     GLUtils::DeleteTexture(input);
546     GLUtils::DeleteFboOnly(tempFbo);
547     GLUtils::DestroyImage(img);
548 }
549 
GenTexEffectBuffer(std::shared_ptr<EffectBuffer> input)550 std::shared_ptr<EffectBuffer> RenderEnvironment::GenTexEffectBuffer(std::shared_ptr<EffectBuffer> input)
551 {
552     std::shared_ptr<BufferInfo> info = input->bufferInfo_;
553     std::shared_ptr<BufferInfo> bufferInfo = std::make_unique<BufferInfo>();
554     bufferInfo->width_ = info->width_;
555     bufferInfo->height_ = info->height_;
556     bufferInfo->rowStride_ = info->rowStride_;
557     bufferInfo->len_ = info->len_;
558     bufferInfo->formatType_ = info->formatType_;
559     std::shared_ptr<ExtraInfo> extraInfo = std::make_unique<ExtraInfo>();
560     extraInfo->dataType = DataType::TEX;
561     std::shared_ptr<EffectBuffer> out = std::make_unique<EffectBuffer>(bufferInfo, nullptr, extraInfo);
562     return out;
563 }
564 
GetOutputType() const565 DataType RenderEnvironment::GetOutputType() const
566 {
567     return outType_;
568 }
569 
SetOutputType(DataType type)570 void RenderEnvironment::SetOutputType(DataType type)
571 {
572     outType_ = type;
573 }
574 
Release()575 void RenderEnvironment::Release()
576 {
577     window_ = nullptr;
578     if (screenSurface_) {
579         screenSurface_->Release();
580         delete screenSurface_;
581         screenSurface_ = nullptr;
582     }
583     eglTerminate(eglGetDisplay(EGL_DEFAULT_DISPLAY));
584 }
585 
ReleaseParam()586 void RenderEnvironment::ReleaseParam()
587 {
588     if (param_ == nullptr) {
589         return;
590     }
591     delete param_;
592     param_ = nullptr;
593     isEGLReady = EGLStatus::UNREADY;
594 }
595 } // namespace Effect
596 } // namespace Media
597 } // namespace OHOS