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