• 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 <memory>
19 #include <sync_fence.h>
20 #include <GLES2/gl2ext.h>
21 
22 #include "colorspace_helper.h"
23 #include "common_utils.h"
24 #include "effect_trace.h"
25 #include "effect_log.h"
26 #include "format_helper.h"
27 #include "metadata_helper.h"
28 #include "base/math/math_utils.h"
29 
30 #include "native_window.h"
31 
32 namespace OHOS {
33 namespace Media {
34 namespace Effect {
35 const char* const DEFAULT_FSHADER = "#extension GL_OES_EGL_image_external : require\n"
36     "precision highp float;\n"
37     "uniform samplerExternalOES inputTexture;\n"
38     "varying vec2 textureCoordinate;\n"
39     "void main()\n"
40     "{\n"
41     "    gl_FragColor = texture2D(inputTexture, textureCoordinate);\n"
42     "}\n";
43 
44 constexpr const static uint32_t RGB_PLANE_SIZE = 3;
45 constexpr const static int G_POS = 1;
46 constexpr const static int B_POS = 2;
47 constexpr const static uint32_t UV_PLANE_SIZE = 2;
48 
GetEGLStatus() const49 EGLStatus RenderEnvironment::GetEGLStatus() const
50 {
51     return isEGLReady;
52 }
53 
Init(bool isCustomEnv)54 void RenderEnvironment::Init(bool isCustomEnv)
55 {
56     EFFECT_TRACE_NAME("RenderEnvironment::Init()");
57     EFFECT_LOGI("RenderEnvironment init enter!");
58     isCustomEnv_ = isCustomEnv;
59     if (isCustomEnv_) {
60         param_ = new RenderParam();
61         isEGLReady = EGLStatus::READY;
62         return;
63     }
64     EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
65     needTerminate_ = true;
66     if (eglInitialize(display, nullptr, nullptr) == EGL_FALSE) {
67         needTerminate_ = false;
68         EFFECT_LOGE("EGL Initialize failed");
69     }
70     param_ = new RenderParam();
71     param_->context_ = new RenderContext();
72 
73     if (param_->context_->Init()) {
74         isEGLReady = EGLStatus::READY;
75     }
76     EFFECT_LOGI("RenderEnvironment init end!");
77 }
78 
Prepare()79 void RenderEnvironment::Prepare()
80 {
81     EFFECT_TRACE_NAME("RenderEnvironment::Prepare()");
82     if (isCustomEnv_) {
83         InitDefaultShaderMT(param_);
84         InitDefaultMeshMT(param_);
85         param_->threadReady_ = true;
86         return;
87     }
88     if (param_->context_->MakeCurrent(screenSurface_)) {
89         param_->renderer_ = new RenderOpenglRenderer();
90         InitDefaultShaderMT(param_);
91         InitDefaultMeshMT(param_);
92         param_->threadReady_ = true;
93     } else {
94         param_->threadReady_ = false;
95     }
96 }
97 
CreateMeshMT(RenderParam * param,bool isBackGround,RenderGeneralProgram * shader)98 RenderMesh *RenderEnvironment::CreateMeshMT(RenderParam *param, bool isBackGround, RenderGeneralProgram *shader)
99 {
100     const std::vector<std::vector<float>> meshData = isBackGround ? DEFAULT_FLIP_VERTEX_DATA : DEFAULT_VERTEX_DATA;
101     RenderMesh *mesh = new RenderMesh(meshData);
102     mesh->Bind(shader);
103     return mesh;
104 }
105 
InitDefaultMeshMT(RenderParam * param)106 void RenderEnvironment::InitDefaultMeshMT(RenderParam *param)
107 {
108     param->meshBase_ = CreateMeshMT(param, false, param->shaderBase_);
109     param->meshBaseFlip_ = CreateMeshMT(param, true, param->shaderBase_);
110     param->meshBaseDMA_ = CreateMeshMT(param, false, param->shaderBaseDMA_);
111     param->meshBaseFlipYUVDMA_ = CreateMeshMT(param, true, param->shaderBaseYUVDMA2RGB2D_);
112     param->meshBaseYUVDMA_ = CreateMeshMT(param, false, param->shaderBaseYUVDMA2RGB2D_);
113     param->meshBaseDrawFrame_ = CreateMeshMT(param, false, param->shaderBaseDrawFrame_);
114     param->meshBaseDrawFrameYUV_ = CreateMeshMT(param, true, param->shaderBaseDrawFrameYUV_);
115 }
116 
InitDefaultShaderMT(RenderParam * param)117 void RenderEnvironment::InitDefaultShaderMT(RenderParam *param)
118 {
119     param->shaderBase_ = new RenderGeneralProgram(DEFAULT_VERTEX_SHADER_SCREEN_CODE,
120         DEFAULT_FRAGMENT_SHADER_CODE);
121     param->shaderBase_->Init();
122     param->shaderBaseDMA_ = new RenderGeneralProgram(DEFAULT_VERTEX_SHADER_SCREEN_CODE,
123         DEFAULT_FSHADER);
124     param->shaderBaseDMA_->Init();
125     param->shaderBaseYUVDMA_ = new RenderGeneralProgram(DEFAULT_YUV_VERTEX_SHADER,
126         DEFAULT_YUV_SHADER_CODE);
127     param->shaderBaseYUVDMA_->Init();
128     param->shaderBaseYUVDMA2RGB2D_ = new RenderGeneralProgram(DEFAULT_YUV_VERTEX_SHADER,
129         DEFAULT_YUV_RGBA_SHADER_CODE);
130     param->shaderBaseYUVDMA2RGB2D_->Init();
131     param->shaderBaseRGB2D2YUVDMA_ = new RenderGeneralProgram(DEFAULT_YUV_VERTEX_SHADER,
132         DEFAULT_RGBA_YUV_SHADER_CODE);
133     param->shaderBaseRGB2D2YUVDMA_->Init();
134     param->shaderBaseDrawFrame_ = new RenderGeneralProgram(TRANSFORM_VERTEX_SHADER_SCREEN_CODE,
135         DEFAULT_FRAGMENT_SHADER_CODE);
136     param->shaderBaseDrawFrame_->Init();
137     param->shaderBaseDrawFrameYUV_ = new RenderGeneralProgram(TRANSFORM_YUV_VERTEX_SHADER,
138         DEFAULT_YUV_RGBA_SHADER_CODE);
139     param->shaderBaseDrawFrameYUV_->Init();
140 }
141 
InitEngine(OHNativeWindow * window)142 void RenderEnvironment::InitEngine(OHNativeWindow *window)
143 {
144     EFFECT_LOGI("RenderEnvironment InitEngine start");
145     if (window_ != nullptr) {
146         return;
147     }
148     window_ = window;
149     screenSurface_ = new RenderSurface(std::string());
150     screenSurface_->SetAttrib(attribute_);
151     screenSurface_->Create(window);
152 }
153 
SetNativeWindowColorSpace(EffectColorSpace colorSpace)154 void RenderEnvironment::SetNativeWindowColorSpace(EffectColorSpace colorSpace)
155 {
156     OH_NativeBuffer_ColorSpace bufferColorSpace = ColorSpaceHelper::ConvertToNativeBufferColorSpace(colorSpace);
157     OH_NativeBuffer_ColorSpace currentColorSpace;
158     OH_NativeWindow_GetColorSpace(window_, &currentColorSpace);
159     if (bufferColorSpace != currentColorSpace) {
160         OH_NativeWindow_SetColorSpace(window_, bufferColorSpace);
161     }
162 }
163 
BeginFrame()164 bool RenderEnvironment::BeginFrame()
165 {
166     if (isCustomEnv_) {
167         return true;
168     }
169     return param_->context_->MakeCurrent(screenSurface_);
170 }
171 
RequestBuffer(int width,int height,GLenum format)172 RenderTexturePtr RenderEnvironment::RequestBuffer(int width, int height, GLenum format)
173 {
174     RenderTexturePtr renderTex = param_->resCache_->RequestTexture(width, height, format);
175     return renderTex;
176 }
177 
IsPrepared() const178 bool RenderEnvironment::IsPrepared() const
179 {
180     return param_->threadReady_;
181 }
182 
ReCreateTexture(RenderTexturePtr renderTex,int width,int height,bool isHdr10) const183 RenderTexturePtr RenderEnvironment::ReCreateTexture(RenderTexturePtr renderTex, int width, int height,
184     bool isHdr10) const
185 {
186     RenderTexturePtr tempTex = param_->resCache_->RequestTexture(width, height, isHdr10 ? GL_RGB10_A2 : GL_RGBA8);
187     GLuint tempFbo = GLUtils::CreateFramebuffer(tempTex->GetName());
188     RenderViewport vp(0, 0, renderTex->Width(), renderTex->Height());
189 
190     param_->renderer_->Draw(renderTex->GetName(), tempFbo, param_->meshBase_, param_->shaderBase_, &vp, GL_TEXTURE_2D);
191     GLUtils::DeleteFboOnly(tempFbo);
192 
193     return tempTex;
194 }
195 
GetOrCreateTextureFromCache(RenderTexturePtr & renderTex,const std::string & texName,int width,int height,bool isHdr10) const196 bool RenderEnvironment::GetOrCreateTextureFromCache(RenderTexturePtr& renderTex, const std::string& texName,
197     int width, int height, bool isHdr10) const
198 {
199     renderTex = param_->resCache_->GetTexGlobalCache(texName);
200     if (renderTex == nullptr || hasInputChanged) {
201         renderTex = param_->resCache_->RequestTexture(width, height, isHdr10 ? GL_RGB10_A2 : GL_RGBA8);
202         param_->resCache_->AddTexGlobalCache(texName, renderTex);
203         return true;
204     }
205     return false;
206 }
207 
GenMainTex(const std::shared_ptr<EffectBuffer> & source,bool isHdr10)208 RenderTexturePtr RenderEnvironment::GenMainTex(const std::shared_ptr<EffectBuffer> &source, bool isHdr10)
209 {
210     std::shared_ptr<BufferInfo> info = source->bufferInfo_;
211     RenderTexturePtr renderTex = nullptr;
212     int width = static_cast<int>(info->width_);
213     int height = static_cast<int>(info->height_);
214 
215     bool needRender = GetOrCreateTextureFromCache(renderTex, "Main", width, height, isHdr10);
216     if (needRender || hasInputChanged) {
217         DrawBufferToTexture(renderTex, source.get());
218         hasInputChanged = false;
219     }
220 
221     return ReCreateTexture(renderTex, width, height, isHdr10);
222 }
223 
GenHdr8GainMapTexs(const std::shared_ptr<EffectBuffer> & source)224 std::unordered_map<std::string, RenderTexturePtr> RenderEnvironment::GenHdr8GainMapTexs(
225     const std::shared_ptr<EffectBuffer> &source)
226 {
227     std::unordered_map<std::string, RenderTexturePtr> texMap{};
228 
229     auto mainTexInfo = source->bufferInfo_;
230     auto gainMapBufferInfo = source->auxiliaryBufferInfos->at(EffectPixelmapType::GAINMAP);
231     auto gainMapExtraInfo = std::make_shared<ExtraInfo>();
232     auto gainMapBuffer = std::make_shared<EffectBuffer>(gainMapBufferInfo, nullptr, gainMapExtraInfo);
233     RenderTexturePtr primaryTex = nullptr;
234     RenderTexturePtr gainMapTex = nullptr;
235 
236     bool needRender = GetOrCreateTextureFromCache(primaryTex, "Primary", static_cast<int>(mainTexInfo->width_),
237         static_cast<int>(mainTexInfo->height_), false);
238     needRender |= GetOrCreateTextureFromCache(gainMapTex, "GainMap",
239         static_cast<int>(gainMapBufferInfo->width_), static_cast<int>(gainMapBufferInfo->height_), false);
240     if (needRender || hasInputChanged) {
241         DrawBufferToTexture(primaryTex, source.get());
242         DrawBufferToTexture(gainMapTex, gainMapBuffer.get());
243         hasInputChanged = false;
244     }
245 
246     texMap.insert({"Primary", ReCreateTexture(primaryTex, static_cast<int>(mainTexInfo->width_),
247         static_cast<int>(mainTexInfo->height_), false)});
248     texMap.insert({"GainMap", ReCreateTexture(gainMapTex, static_cast<int>(gainMapBufferInfo->width_),
249         static_cast<int>(gainMapBufferInfo->height_), false)});
250 
251     return texMap;
252 }
253 
GenTex(const std::shared_ptr<EffectBuffer> & source,std::shared_ptr<EffectBuffer> & output)254 void RenderEnvironment::GenTex(const std::shared_ptr<EffectBuffer> &source, std::shared_ptr<EffectBuffer> &output)
255 {
256     auto info = source->bufferInfo_;
257     output = GenTexEffectBuffer(source);
258 
259     switch (info->hdrFormat_) {
260         case HdrFormat::HDR8_GAINMAP: {
261             auto texMap = GenHdr8GainMapTexs(source);
262             output->bufferInfo_->tex_ = texMap["Primary"];
263             output->auxiliaryBufferInfos->at(EffectPixelmapType::GAINMAP)->tex_ = texMap["GainMap"];
264             break;
265         }
266         case HdrFormat::HDR10:
267             output->bufferInfo_->tex_ = GenMainTex(source, true);
268             break;
269         case HdrFormat::SDR:
270         case HdrFormat::DEFAULT:
271         default:
272             output->bufferInfo_->tex_ = GenMainTex(source, false);
273             break;
274     }
275 }
276 
DrawFlipTex(RenderTexturePtr input,RenderTexturePtr output)277 void RenderEnvironment::DrawFlipTex(RenderTexturePtr input, RenderTexturePtr output)
278 {
279     GLuint tempFbo = GLUtils::CreateFramebuffer(output->GetName());
280     RenderViewport vp(0, 0, input->Width(), input->Height());
281     param_->renderer_->Draw(input->GetName(), tempFbo, param_->meshBaseFlip_, param_->shaderBase_, &vp, GL_TEXTURE_2D);
282     GLUtils::DeleteFboOnly(tempFbo);
283 }
284 
DrawTex(RenderTexturePtr input,RenderTexturePtr output)285 void RenderEnvironment::DrawTex(RenderTexturePtr input, RenderTexturePtr output)
286 {
287     GLuint tempFbo = GLUtils::CreateFramebuffer(output->GetName());
288     RenderViewport vp(0, 0, input->Width(), input->Height());
289     param_->renderer_->Draw(input->GetName(), tempFbo, param_->meshBase_, param_->shaderBase_, &vp, GL_TEXTURE_2D);
290     GLUtils::DeleteFboOnly(tempFbo);
291 }
292 
ConvertBufferToTexture(EffectBuffer * source)293 std::shared_ptr<EffectBuffer> RenderEnvironment::ConvertBufferToTexture(EffectBuffer *source)
294 {
295     std::shared_ptr<BufferInfo> info = source->bufferInfo_;
296     GLenum interFmt = source->bufferInfo_->hdrFormat_ == HdrFormat::HDR10 ? GL_RGB10_A2 : GL_RGBA8;
297     RenderTexturePtr renderTex = param_->resCache_->RequestTexture(static_cast<int>(info->width_),
298         static_cast<int>(info->height_), interFmt);
299     DrawBufferToTexture(renderTex, source);
300 
301     std::shared_ptr<BufferInfo> bufferInfo = std::make_unique<BufferInfo>();
302     CommonUtils::CopyBufferInfo(*info, *bufferInfo);
303     std::shared_ptr<ExtraInfo> extraInfo = std::make_unique<ExtraInfo>();
304     CommonUtils::CopyExtraInfo(*source->extraInfo_, *extraInfo);
305     extraInfo->dataType = DataType::TEX;
306     std::shared_ptr<EffectBuffer> output = std::make_shared<EffectBuffer>(bufferInfo, nullptr, extraInfo);
307     output->bufferInfo_->tex_ = renderTex;
308     if (source->bufferInfo_->hdrFormat_ == HdrFormat::HDR8_GAINMAP && source->auxiliaryBufferInfos != nullptr) {
309         output->auxiliaryBufferInfos =
310             std::make_unique<std::unordered_map<EffectPixelmapType, std::shared_ptr<BufferInfo>>>();
311         for (const auto& entry : *source->auxiliaryBufferInfos) {
312             std::shared_ptr<BufferInfo> auxiliaryBufferInfo = std::make_shared<BufferInfo>();
313             CommonUtils::CopyBufferInfo(*(entry.second), *auxiliaryBufferInfo);
314             output->auxiliaryBufferInfos->emplace(entry.first, auxiliaryBufferInfo);
315         }
316 
317         auto gainBuffer = source -> auxiliaryBufferInfos->find(EffectPixelmapType::GAINMAP);
318         if (gainBuffer != source -> auxiliaryBufferInfos -> end()) {
319             auto gainBufferInfo = gainBuffer->second;
320             if (gainBufferInfo != nullptr) {
321                 std::shared_ptr<ExtraInfo> gainExtraInfo = std::make_unique<ExtraInfo>();
322                 auto tempGainBuffer =
323                     std::make_shared<EffectBuffer>(gainBufferInfo, gainBufferInfo->addr_, gainExtraInfo);
324                 RenderTexturePtr gainTex = param_->resCache_->RequestTexture(
325                     static_cast<int>(gainBufferInfo->width_), static_cast<int>(gainBufferInfo->height_), GL_RGBA8);
326                 DrawBufferToTexture(gainTex, tempGainBuffer.get());
327                 gainBufferInfo->tex_ = gainTex;
328             }
329         }
330     }
331     return output;
332 }
333 
NotifyInputChanged()334 void RenderEnvironment::NotifyInputChanged()
335 {
336     hasInputChanged = true;
337 }
338 
IfNeedGenMainTex() const339 bool RenderEnvironment::IfNeedGenMainTex() const
340 {
341     return hasInputChanged;
342 }
343 
UpdateCanvas()344 void RenderEnvironment::UpdateCanvas()
345 {
346     if (window_ != nullptr) {
347         OH_NativeWindow_NativeWindowHandleOpt(window_, GET_BUFFER_GEOMETRY, &canvasHeight, &canvasWidth);
348         param_->viewport_.Set(0, 0, canvasWidth, canvasHeight);
349     }
350 }
351 
DrawBufferToTexture(RenderTexturePtr renderTex,const EffectBuffer * source)352 void RenderEnvironment::DrawBufferToTexture(RenderTexturePtr renderTex, const EffectBuffer *source)
353 {
354     CHECK_AND_RETURN_LOG(source != nullptr, "DrawBufferToTexture: source is null!");
355     int width = static_cast<int>(source->bufferInfo_->width_);
356     int height = static_cast<int>(source->bufferInfo_->height_);
357     IEffectFormat format = source->bufferInfo_->formatType_;
358     if (source->bufferInfo_->surfaceBuffer_ != nullptr) {
359         source->bufferInfo_->surfaceBuffer_->FlushCache();
360         DrawTexFromSurfaceBuffer(renderTex, source->bufferInfo_->surfaceBuffer_, format);
361     } else {
362         GLuint tex;
363         CHECK_AND_RETURN_LOG(renderTex != nullptr, "DrawBufferToTexture: renderTex is null!");
364         GLuint tempFbo = GLUtils::CreateFramebuffer(renderTex->GetName());
365         if (source->bufferInfo_->formatType_ == IEffectFormat::RGBA8888 ||
366             source->bufferInfo_->formatType_ == IEffectFormat::RGBA_1010102) {
367             int stride = static_cast<int>(source->bufferInfo_->rowStride_ / 4);
368             tex = GenTextureWithPixels(source->buffer_, width, height, stride, format);
369         } else {
370             tex = ConvertFromYUVToRGB(source, format);
371         }
372         RenderViewport vp(0, 0, renderTex->Width(), renderTex->Height());
373         param_->renderer_->Draw(tex, tempFbo, param_->meshBase_, param_->shaderBase_, &vp, GL_TEXTURE_2D);
374         glBindTexture(GL_TEXTURE_2D, 0);
375         GLUtils::DeleteTexture(tex);
376         GLUtils::DeleteFboOnly(tempFbo);
377     }
378 }
379 
ConvertFromYUVToRGB(const EffectBuffer * source,IEffectFormat format)380 GLuint RenderEnvironment::ConvertFromYUVToRGB(const EffectBuffer *source, IEffectFormat format)
381 {
382     int width = static_cast<int>(source->bufferInfo_->width_);
383     int height = static_cast<int>(source->bufferInfo_->height_);
384     auto *srcNV12 = static_cast<unsigned char *>(source->buffer_);
385     uint8_t *srcNV12UV = srcNV12 + width * height;
386     auto data = std::make_unique<unsigned char[]>(width * height * RGBA_SIZE_PER_PIXEL);
387     for (uint32_t i = 0; i < static_cast<uint32_t>(height); i++) {
388         for (uint32_t j = 0; j < static_cast<uint32_t>(width); j++) {
389             uint32_t nvIndex =
390                 i / UV_PLANE_SIZE * static_cast<uint32_t>(width) + j - j % UV_PLANE_SIZE; // 2 mean u/v split factor
391             uint32_t yIndex = i * static_cast<uint32_t>(width) + j;
392             uint8_t y;
393             uint8_t u;
394             uint8_t v;
395             if (format == IEffectFormat::YUVNV12) {
396                 y = srcNV12[yIndex];
397                 u = srcNV12UV[nvIndex];
398                 v = srcNV12UV[nvIndex + 1];
399             } else {
400                 y = srcNV12[yIndex];
401                 v = srcNV12UV[nvIndex];
402                 u = srcNV12UV[nvIndex + 1];
403             }
404             uint8_t r = FormatHelper::YuvToR(y, u, v);
405             uint8_t g = FormatHelper::YuvToG(y, u, v);
406             uint8_t b = FormatHelper::YuvToB(y, u, v);
407             uint32_t rgbIndex = i * static_cast<uint32_t>(width) * RGB_PLANE_SIZE + j * RGB_PLANE_SIZE;
408             data[rgbIndex] = r;
409             data[rgbIndex + G_POS] = g;
410             data[rgbIndex + B_POS] = b;
411         }
412     }
413     GLuint tex = GLUtils::CreateTexWithStorage(GL_TEXTURE_2D, 1, GL_RGB, width, height);
414     return tex;
415 }
416 
ConvertFromRGBToYUV(RenderTexturePtr input,IEffectFormat format,void * data)417 void RenderEnvironment::ConvertFromRGBToYUV(RenderTexturePtr input, IEffectFormat format, void *data)
418 {
419     int width = static_cast<int>(input->Width());
420     int height = static_cast<int>(input->Height());
421     auto rgbData = std::make_unique<unsigned char[]>(width * height * RGBA_SIZE_PER_PIXEL);
422     ReadPixelsFromTex(input, rgbData.get(), width, height, width);
423     auto *srcNV12 = static_cast<unsigned char *>(data);
424     uint8_t *srcNV12UV = srcNV12 + static_cast<uint32_t>(width * height);
425     for (uint32_t i = 0; i < static_cast<uint32_t>(height); i++) {
426         for (uint32_t j = 0; j < static_cast<uint32_t>(width); j++) {
427             uint32_t yIndex = i * static_cast<uint32_t>(width) + j;
428             uint32_t nvIndex =
429                 i / UV_PLANE_SIZE * static_cast<uint32_t>(width) + j - j % UV_PLANE_SIZE; // 2 mean u/v split factor
430             uint32_t rgbIndex = i * static_cast<uint32_t>(width) * static_cast<uint32_t>(RGBA_SIZE_PER_PIXEL) +
431                 j * static_cast<uint32_t>(RGBA_SIZE_PER_PIXEL);
432             uint8_t r = rgbData[rgbIndex];
433             uint8_t g = rgbData[rgbIndex + G_POS];
434             uint8_t b = rgbData[rgbIndex + B_POS];
435             srcNV12[yIndex] = FormatHelper::RGBToY(r, g, b);
436             if (format == IEffectFormat::YUVNV12) {
437                 srcNV12UV[nvIndex] = FormatHelper::RGBToU(r, g, b);
438                 srcNV12UV[nvIndex + 1] = FormatHelper::RGBToV(r, g, b);
439             } else {
440                 srcNV12UV[nvIndex] = FormatHelper::RGBToV(r, g, b);
441                 srcNV12UV[nvIndex + 1] = FormatHelper::RGBToU(r, g, b);
442             }
443         }
444     }
445 }
446 
GetContext()447 RenderContext *RenderEnvironment::GetContext()
448 {
449     return param_->context_;
450 }
451 
GetResourceCache()452 ResourceCache *RenderEnvironment::GetResourceCache()
453 {
454     return param_->resCache_;
455 }
456 
GetTransformMatrix(GraphicTransformType type)457 glm::mat4 GetTransformMatrix(GraphicTransformType type)
458 {
459     glm::mat4 trans = glm::mat4(1.0f);
460     switch (type) {
461         case GRAPHIC_ROTATE_90:
462             trans = glm::rotate(trans, glm::radians(90.0f), glm::vec3(0.0, 0.0, 1.0));
463             break;
464         case GRAPHIC_ROTATE_180:
465             trans = glm::rotate(trans, glm::radians(180.0f), glm::vec3(0.0, 0.0, 1.0));
466             break;
467         case GRAPHIC_ROTATE_270:
468             trans = glm::rotate(trans, glm::radians(270.0f), glm::vec3(0.0, 0.0, 1.0));
469             break;
470         default:
471             break;
472     }
473     return trans;
474 }
475 
DrawFrameWithTransform(const std::shared_ptr<EffectBuffer> & buffer,GraphicTransformType type)476 void RenderEnvironment::DrawFrameWithTransform(const std::shared_ptr<EffectBuffer> &buffer, GraphicTransformType type)
477 {
478     if (param_ != nullptr) {
479         BeginFrame();
480         UpdateCanvas();
481         glBindFramebuffer(GL_FRAMEBUFFER, 0);
482         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
483         glm::mat4 trans = GetTransformMatrix(type);
484         if (buffer->bufferInfo_->tex_ == nullptr) {
485             EFFECT_LOGE("RenderEnvironment DrawFrameWithTransform tex is nullptr");
486             return;
487         }
488         param_->renderer_->DrawOnScreen(buffer->bufferInfo_->tex_->GetName(), param_->meshBaseDrawFrame_,
489             param_->shaderBaseDrawFrame_, &param_->viewport_, MathUtils::NativePtr(trans), GL_TEXTURE_2D);
490 
491         if (screenSurface_ == nullptr) {
492             EFFECT_LOGE("RenderEnvironment screenSurface_ is nullptr");
493             return;
494         }
495         param_->context_->SwapBuffers(screenSurface_);
496         GLUtils::CheckError(__FILE_NAME__, __LINE__);
497     }
498 }
499 
DrawFrame(GLuint texId,GraphicTransformType type)500 void RenderEnvironment::DrawFrame(GLuint texId, GraphicTransformType type)
501 {
502     if (param_ != nullptr) {
503         BeginFrame();
504         UpdateCanvas();
505         glBindFramebuffer(GL_FRAMEBUFFER, 0);
506         glClearColor(1.0, 0, 0, 0);
507         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
508 
509         auto mesh = std::make_shared<RenderMesh>(DEFAULT_FLIP_VERTEX_DATA);
510         mesh->Bind(param_->shaderBaseDrawFrameYUV_);
511         param_->renderer_->DrawOnScreenWithTransform(texId, mesh.get(),
512             param_->shaderBaseDrawFrameYUV_, &param_->viewport_, type, GL_TEXTURE_EXTERNAL_OES);
513         glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
514         if (screenSurface_ == nullptr) {
515             EFFECT_LOGE("RenderEnvironment screenSurface_ is nullptr");
516             return;
517         }
518         param_->context_->SwapBuffers(screenSurface_);
519         GLUtils::CheckError(__FILE_NAME__, __LINE__);
520     }
521 }
522 
ConvertTextureToBuffer(RenderTexturePtr source,EffectBuffer * output,bool needProcessCache)523 void RenderEnvironment::ConvertTextureToBuffer(RenderTexturePtr source, EffectBuffer *output, bool needProcessCache)
524 {
525     int w = static_cast<int>(source->Width());
526     int h = static_cast<int>(source->Height());
527     if (output->bufferInfo_->surfaceBuffer_ == nullptr) {
528         if (output->bufferInfo_->formatType_ == IEffectFormat::RGBA8888 ||
529             output->bufferInfo_->formatType_ == IEffectFormat::RGBA_1010102) {
530             ReadPixelsFromTex(source, output->buffer_, w, h, output->bufferInfo_->rowStride_ / RGBA_SIZE_PER_PIXEL);
531         } else {
532             ConvertFromRGBToYUV(source, output->bufferInfo_->formatType_, output->buffer_);
533         }
534     } else {
535         DrawSurfaceBufferFromTex(source, output->bufferInfo_->surfaceBuffer_, output->bufferInfo_->formatType_);
536         if (needProcessCache) {
537             output->bufferInfo_->surfaceBuffer_->InvalidateCache();
538         }
539     }
540     GLUtils::CheckError(__FILE_NAME__, __LINE__);
541 }
542 
ConvertYUV2RGBA(std::shared_ptr<EffectBuffer> & source,std::shared_ptr<EffectBuffer> & out)543 void RenderEnvironment::ConvertYUV2RGBA(std::shared_ptr<EffectBuffer> &source, std::shared_ptr<EffectBuffer> &out)
544 {
545     int width = static_cast<int>(source->bufferInfo_->width_);
546     int height = static_cast<int>(source->bufferInfo_->height_);
547     RenderTexturePtr outTex;
548     if (source->bufferInfo_->surfaceBuffer_ == nullptr) {
549         outTex = std::make_shared<RenderTexture>(width, height, GL_RGBA8);
550         outTex->SetName(ConvertFromYUVToRGB(source.get(), source->bufferInfo_->formatType_));
551     } else {
552         outTex = param_->resCache_->RequestTexture(width, height, GL_RGBA8);
553         EGLImageKHR img = GLUtils::CreateEGLImage(eglGetDisplay(EGL_DEFAULT_DISPLAY),
554             source->bufferInfo_->surfaceBuffer_);
555         GLuint sourceTex = GLUtils::CreateTextureFromImage(img);
556         GLuint tempFbo = GLUtils::CreateFramebufferWithTarget(outTex->GetName(), GL_TEXTURE_2D);
557         RenderViewport vp(0, 0, width, height);
558         param_->renderer_->Draw(sourceTex, tempFbo, param_->meshBaseFlipYUVDMA_, param_->shaderBaseYUVDMA2RGB2D_, &vp,
559             GL_TEXTURE_EXTERNAL_OES);
560         glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
561         GLUtils::DestroyImage(img);
562     }
563 
564     out = GenTexEffectBuffer(source);
565     out->bufferInfo_->formatType_ = IEffectFormat::RGBA8888;
566     out->bufferInfo_->tex_ = outTex;
567     GLUtils::CheckError(__FILE_NAME__, __LINE__);
568 }
569 
ConvertRGBA2YUV(std::shared_ptr<EffectBuffer> & source,std::shared_ptr<EffectBuffer> & out)570 void RenderEnvironment::ConvertRGBA2YUV(std::shared_ptr<EffectBuffer> &source, std::shared_ptr<EffectBuffer> &out)
571 {
572     int width = static_cast<int>(source->bufferInfo_->width_);
573     int height = static_cast<int>(source->bufferInfo_->height_);
574     RenderTexturePtr sourceTex = source->bufferInfo_->tex_;
575     EGLImageKHR img = GLUtils::CreateEGLImage(eglGetDisplay(EGL_DEFAULT_DISPLAY), out->bufferInfo_->surfaceBuffer_);
576     GLuint outTex = GLUtils::CreateTextureFromImage(img);
577     RenderTexturePtr tex = std::make_shared<RenderTexture>(width, height, GL_RGBA8);
578     tex->SetName(outTex);
579     Draw2D2OES(sourceTex, tex);
580     glFinish();
581     GLUtils::DestroyImage(img);
582 }
583 
Draw2D2OES(RenderTexturePtr source,RenderTexturePtr output)584 void RenderEnvironment::Draw2D2OES(RenderTexturePtr source, RenderTexturePtr output)
585 {
586     int w = static_cast<int>(source->Width());
587     int h = static_cast<int>(source->Height());
588     GLuint tempFbo = GLUtils::CreateFramebufferWithTarget(output->GetName(), GL_TEXTURE_EXTERNAL_OES);
589     RenderViewport vp(0, 0, w, h);
590     param_->renderer_->Draw(source->GetName(), tempFbo, param_->meshBaseDMA_, param_->shaderBaseRGB2D2YUVDMA_, &vp,
591         GL_TEXTURE_2D);
592     glBindTexture(GL_TEXTURE_2D, 0);
593     GLUtils::CheckError(__FILE_NAME__, __LINE__);
594 }
595 
ReadPixelsFromTex(RenderTexturePtr tex,void * data,int width,int height,int stride)596 void RenderEnvironment::ReadPixelsFromTex(RenderTexturePtr tex, void *data, int width, int height, int stride)
597 {
598     GLuint inFbo = GLUtils::CreateFramebuffer(tex->GetName());
599     glBindFramebuffer(GL_FRAMEBUFFER, inFbo);
600     glPixelStorei(GL_PACK_ROW_LENGTH, stride);
601     GLenum type = tex->Format() == GL_RGB10_A2 ? GL_UNSIGNED_INT_2_10_10_10_REV : GL_UNSIGNED_BYTE;
602     glReadPixels(0, 0, width, height, GL_RGBA, type, data);
603     glPixelStorei(GL_PACK_ROW_LENGTH, 0);
604     glBindFramebuffer(GL_FRAMEBUFFER, GL_NONE);
605     GLUtils::DeleteFboOnly(inFbo);
606 }
607 
GenTextureWithPixels(void * data,int width,int height,int stride,IEffectFormat format)608 GLuint RenderEnvironment::GenTextureWithPixels(void *data, int width, int height, int stride, IEffectFormat format)
609 {
610     GLuint tex = GLUtils::CreateTexWithStorage(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
611     glBindTexture(GL_TEXTURE_2D, tex);
612     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
613     GLenum type = format == IEffectFormat::RGBA_1010102 ? GL_UNSIGNED_INT_2_10_10_10_REV : GL_UNSIGNED_BYTE;
614     if (width == stride) {
615         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, type, data);
616     } else {
617         glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
618         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, type, data);
619         glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
620     }
621     return tex;
622 }
623 
DrawSurfaceBufferFromTex(RenderTexturePtr tex,SurfaceBuffer * buffer,IEffectFormat format)624 void RenderEnvironment::DrawSurfaceBufferFromTex(RenderTexturePtr tex, SurfaceBuffer *buffer, IEffectFormat format)
625 {
626     EGLImageKHR img = GLUtils::CreateEGLImage(eglGetDisplay(EGL_DEFAULT_DISPLAY), buffer);
627     GLuint outTex = GLUtils::CreateTextureFromImage(img);
628     GLuint tempFbo = GLUtils::CreateFramebufferWithTarget(outTex, GL_TEXTURE_EXTERNAL_OES);
629     RenderViewport vp(0, 0, tex->Width(), tex->Height());
630     if (format == IEffectFormat::RGBA8888 || format == IEffectFormat::RGBA_1010102) {
631         param_->renderer_->Draw(tex->GetName(), tempFbo, param_->meshBase_, param_->shaderBase_, &vp, GL_TEXTURE_2D);
632     } else {
633         param_->renderer_->Draw(tex->GetName(), tempFbo, param_->meshBaseDMA_, param_->shaderBaseRGB2D2YUVDMA_, &vp,
634             GL_TEXTURE_2D);
635     }
636     glBindTexture(GL_TEXTURE_2D, 0);
637     glFinish();
638     GLUtils::DeleteTexture(outTex);
639     GLUtils::DeleteFboOnly(tempFbo);
640     GLUtils::DestroyImage(img);
641     GLUtils::CheckError(__FILE_NAME__, __LINE__);
642 }
643 
DrawFlipSurfaceBufferFromTex(RenderTexturePtr tex,SurfaceBuffer * buffer,IEffectFormat format)644 void RenderEnvironment::DrawFlipSurfaceBufferFromTex(RenderTexturePtr tex, SurfaceBuffer *buffer, IEffectFormat format)
645 {
646     EGLImageKHR img = GLUtils::CreateEGLImage(eglGetDisplay(EGL_DEFAULT_DISPLAY), buffer);
647     GLuint outTex = GLUtils::CreateTextureFromImage(img);
648     GLuint tempFbo = GLUtils::CreateFramebufferWithTarget(outTex, GL_TEXTURE_EXTERNAL_OES);
649     RenderViewport vp(0, 0, tex->Width(), tex->Height());
650     if (format == IEffectFormat::RGBA8888) {
651         param_->renderer_->Draw(tex->GetName(), tempFbo, param_->meshBaseFlip_, param_->shaderBase_, &vp,
652             GL_TEXTURE_2D);
653     } else {
654         param_->renderer_->Draw(tex->GetName(), tempFbo, param_->meshBaseFlipYUVDMA_, param_->shaderBaseRGB2D2YUVDMA_,
655             &vp, GL_TEXTURE_2D);
656     }
657     glBindTexture(GL_TEXTURE_2D, 0);
658     glFinish();
659     GLUtils::DeleteTexture(outTex);
660     GLUtils::DeleteFboOnly(tempFbo);
661     GLUtils::DestroyImage(img);
662     GLUtils::CheckError(__FILE_NAME__, __LINE__);
663 }
664 
DrawOesTexture2DFromTexture(RenderTexturePtr inputTex,GLuint outputTex,int32_t width,int32_t height,IEffectFormat format)665 void RenderEnvironment::DrawOesTexture2DFromTexture(RenderTexturePtr inputTex, GLuint outputTex, int32_t width,
666     int32_t height, IEffectFormat format)
667 {
668     CHECK_AND_RETURN_LOG(inputTex && outputTex != 0,
669         "DrawSurfaceBufferFromSurfaceBuffer: inputTex or outputTex is nullptr");
670     GLuint outputFbo = GLUtils::CreateFramebufferWithTarget(outputTex, GL_TEXTURE_EXTERNAL_OES);
671     RenderViewport vp(0, 0, width, height);
672     if (format == IEffectFormat::RGBA8888 || format == IEffectFormat::RGBA_1010102) {
673         param_->renderer_->Draw(inputTex->GetName(), outputFbo,
674             param_->meshBase_, param_->shaderBase_, &vp, GL_TEXTURE_2D);
675     } else {
676         param_->renderer_->Draw(inputTex->GetName(), outputFbo,
677             param_->meshBaseDMA_, param_->shaderBaseRGB2D2YUVDMA_, &vp, GL_TEXTURE_2D);
678     }
679     glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
680     GLUtils::DeleteFboOnly(outputFbo);
681 }
682 
DrawSurfaceBufferFromSurfaceBuffer(SurfaceBuffer * inBuffer,SurfaceBuffer * outBuffer,IEffectFormat format) const683 void RenderEnvironment::DrawSurfaceBufferFromSurfaceBuffer(SurfaceBuffer *inBuffer, SurfaceBuffer *outBuffer,
684     IEffectFormat format) const
685 {
686     CHECK_AND_RETURN_LOG(inBuffer && outBuffer, "DrawSurfaceBufferFromSurfaceBuffer: inBuffer or outBuffer is nullptr");
687     EGLImageKHR inputImg = GLUtils::CreateEGLImage(eglGetDisplay(EGL_DEFAULT_DISPLAY), inBuffer);
688     GLuint inputTex = GLUtils::CreateTextureFromImage(inputImg);
689 
690     EGLImageKHR outputImg = GLUtils::CreateEGLImage(eglGetDisplay(EGL_DEFAULT_DISPLAY), outBuffer);
691     GLuint outputTex = GLUtils::CreateTextureFromImage(outputImg);
692     GLuint outputFbo = GLUtils::CreateFramebufferWithTarget(outputTex, GL_TEXTURE_EXTERNAL_OES);
693 
694     RenderViewport vp(0, 0, outBuffer->GetWidth(), outBuffer->GetHeight());
695     RenderGeneralProgram *program;
696     RenderMesh *mesh;
697     if (format == IEffectFormat::RGBA8888 || format == IEffectFormat::RGBA_1010102) {
698         program = param_->shaderBaseDMA_;
699         mesh = param_->meshBaseDMA_;
700     } else {
701         program = param_->shaderBaseYUVDMA2RGB2D_;
702         mesh = param_->meshBaseYUVDMA_;
703     }
704     param_->renderer_->Draw(inputTex, outputFbo, mesh, program, &vp, GL_TEXTURE_EXTERNAL_OES);
705     glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
706     GLUtils::DeleteTexture(inputTex);
707     GLUtils::DeleteTexture(outputTex);
708     GLUtils::DeleteFboOnly(outputFbo);
709     GLUtils::DestroyImage(inputImg);
710     GLUtils::DestroyImage(outputImg);
711 }
712 
DrawTexFromSurfaceBuffer(RenderTexturePtr tex,SurfaceBuffer * buffer,IEffectFormat format)713 void RenderEnvironment::DrawTexFromSurfaceBuffer(RenderTexturePtr tex, SurfaceBuffer *buffer, IEffectFormat format)
714 {
715     CHECK_AND_RETURN_LOG(tex != nullptr, "DrawTexFromSurfaceBuffer: tex is null!");
716     GLuint tempFbo = GLUtils::CreateFramebuffer(tex->GetName());
717     EGLImageKHR img = GLUtils::CreateEGLImage(eglGetDisplay(EGL_DEFAULT_DISPLAY), buffer);
718     GLuint input = GLUtils::CreateTextureFromImage(img);
719     RenderViewport vp(0, 0, tex->Width(), tex->Height());
720     RenderGeneralProgram *program;
721     RenderMesh *mesh;
722     if (format == IEffectFormat::RGBA8888 || format == IEffectFormat::RGBA_1010102) {
723         program = param_->shaderBaseDMA_;
724         mesh = param_->meshBaseDMA_;
725     } else {
726         program = param_->shaderBaseYUVDMA2RGB2D_;
727         mesh = param_->meshBaseYUVDMA_;
728     }
729     param_->renderer_->Draw(input, tempFbo, mesh, program, &vp, GL_TEXTURE_EXTERNAL_OES);
730     glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
731     GLUtils::DeleteTexture(input);
732     GLUtils::DeleteFboOnly(tempFbo);
733     GLUtils::DestroyImage(img);
734 }
735 
GenTexEffectBuffer(const std::shared_ptr<EffectBuffer> & input)736 std::shared_ptr<EffectBuffer> RenderEnvironment::GenTexEffectBuffer(const std::shared_ptr<EffectBuffer>& input)
737 {
738     EFFECT_LOGD("GenTexEffectBuffer: dataType = %{public}d", input->extraInfo_->dataType);
739     auto info = input->bufferInfo_;
740     auto bufferInfo = std::make_shared<BufferInfo>();
741     CommonUtils::CopyBufferInfo(*info, *bufferInfo);
742 
743     auto extraInfo = std::make_shared<ExtraInfo>();
744     CommonUtils::CopyExtraInfo(*input->extraInfo_, *extraInfo);
745     extraInfo->dataType = DataType::TEX;
746 
747     auto out = std::make_shared<EffectBuffer>(bufferInfo, nullptr, extraInfo);
748     if (bufferInfo->hdrFormat_ != HdrFormat::HDR8_GAINMAP) return out;
749 
750     if (input->auxiliaryBufferInfos != nullptr) {
751         out->auxiliaryBufferInfos = std::make_shared<std::unordered_map<
752                 EffectPixelmapType, std::shared_ptr<BufferInfo>>>();
753         for (const auto& [pixType, effectBufferInfo] : *input->auxiliaryBufferInfos) {
754             auto auxiliaryBufferInfo = std::make_shared<BufferInfo>();
755             CommonUtils::CopyBufferInfo(*effectBufferInfo, *auxiliaryBufferInfo);
756 
757             out->auxiliaryBufferInfos->emplace(pixType, auxiliaryBufferInfo);
758         }
759     }
760     return out;
761 }
762 
GetOutputType() const763 DataType RenderEnvironment::GetOutputType() const
764 {
765     return outType_;
766 }
767 
SetOutputType(DataType type)768 void RenderEnvironment::SetOutputType(DataType type)
769 {
770     outType_ = type;
771 }
772 
Release()773 void RenderEnvironment::Release()
774 {
775     window_ = nullptr;
776     if (screenSurface_) {
777         screenSurface_->Release();
778         delete screenSurface_;
779         screenSurface_ = nullptr;
780     }
781     if (needTerminate_) {
782         eglTerminate(eglGetDisplay(EGL_DEFAULT_DISPLAY));
783         needTerminate_ = false;
784     }
785 }
786 
ReleaseParam()787 void RenderEnvironment::ReleaseParam()
788 {
789     if (param_ == nullptr) {
790         return;
791     }
792     delete param_;
793     param_ = nullptr;
794     isEGLReady = EGLStatus::UNREADY;
795 }
796 } // namespace Effect
797 } // namespace Media
798 } // namespace OHOS