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