• 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 #include "pixel_map_gl_post_proc_program.h"
16 
17 #include <atomic>
18 #include <cstdint>
19 #include <memory>
20 #include <string>
21 #include <sys/stat.h>
22 #include <fcntl.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <sys/time.h>
26 #include <sys/mman.h>
27 #include <iostream>
28 
29 #include "native_buffer.h"
30 #include "pixel_map_gl_shader.h"
31 #include "securec.h"
32 #include "sync_fence.h"
33 #include "image_utils.h"
34 #include <fstream>
35 #include <sstream>
36 #undef LOG_DOMAIN
37 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
38 
39 #undef LOG_TAG
40 #define LOG_TAG "PixelMapGLPostProcProgram"
41 #define PI 3.1415926
42 
43 namespace OHOS {
44 namespace Media {
45 using namespace GlCommon;
46 std::once_flag shaderInitFlag[PixelMapGlShader::SHADER_MAX];
47 std::mutex g_shaderMtx;
48 std::condition_variable g_shaderCv;
49 std::atomic<int> g_shaderCount = 0;
50 std::atomic<int> g_shaderFailCount = 0;
51 
PixelMapGLPostProcProgram()52 PixelMapGLPostProcProgram::PixelMapGLPostProcProgram()
53 {
54 }
55 
~PixelMapGLPostProcProgram()56 PixelMapGLPostProcProgram::~PixelMapGLPostProcProgram() noexcept
57 {
58     Clear();
59     IMAGE_LOGE("slr_gpu ~PixelMapGLPostProcProgram()");
60 }
61 
SetGPUTransformData(GPUTransformData & transformData)62 void PixelMapGLPostProcProgram::SetGPUTransformData(GPUTransformData &transformData)
63 {
64     this->transformData_ = transformData;
65 }
66 
Clear()67 void PixelMapGLPostProcProgram::Clear() noexcept
68 {
69     if (renderContext_ != nullptr && renderContext_->eglContext_ != EGL_NO_CONTEXT) {
70         renderContext_->MakeCurrentSimple(true);
71         if (rotateShader_) {
72             rotateShader_->Clear();
73             rotateShader_.reset();
74         }
75         if (slrShader_) {
76             slrShader_->Clear();
77             slrShader_.reset();
78         }
79         if (lapShader_) {
80             lapShader_->Clear();
81             lapShader_.reset();
82         }
83         if (vertexShader_) {
84             vertexShader_->Clear();
85             vertexShader_.reset();
86         }
87         renderContext_->MakeCurrentSimple(false);
88     }
89 }
90 
BuildShader()91 bool PixelMapGLPostProcProgram::BuildShader()
92 {
93     ImageTrace imageTrace("PixelMapGLPostProcProgram::BuildShader");
94     static PixelMapGlContext renderContextAll(true);
95     for (int i = PixelMapGlShader::SHADER_ROTATE; i < PixelMapGlShader::SHADER_MAX; i++) {
96         std::call_once(shaderInitFlag[i], [&]() {
97             auto shader = PixelMapGlShader::ShaderFactory::GetInstance().Get(PixelMapGlShader::ShaderType(i));
98             g_shaderCount++;
99             if (!shader || !shader->LoadProgram()) {
100                 g_shaderFailCount++;
101             }
102             std::unique_lock<std::mutex> lock(g_shaderMtx);
103             g_shaderCv.notify_all();
104         });
105     }
106     {
107         std::unique_lock<std::mutex> lock(g_shaderMtx);
108         g_shaderCv.wait(lock, [] {
109             return g_shaderCount == PixelMapGlShader::SHADER_MAX - PixelMapGlShader::SHADER_ROTATE;
110         });
111     }
112     return g_shaderFailCount == 0;
113 }
114 
Init()115 bool PixelMapGLPostProcProgram::Init()
116 {
117     if (renderContext_ == nullptr) {
118         ImageTrace imageTrace("OpenGL context create");
119         renderContext_ = make_unique<PixelMapGlContext>();
120         if (!renderContext_->InitEGLContext()) {
121             IMAGE_LOGE("slr_gpu CreatePixelMapFromSurface: init renderContext failed.");
122             return false;
123         }
124         return InitGLResource();
125     }
126     return true;
127 }
128 
CreateNormalImage(const uint8_t * data,GLuint & imageTexId)129 bool PixelMapGLPostProcProgram::CreateNormalImage(const uint8_t *data, GLuint &imageTexId)
130 {
131     const Size &sourceSize = transformData_.sourceInfo_.size;
132     int perPixelSize = transformData_.sourceInfo_.pixelBytes;
133     if (data == nullptr) {
134         return false;
135     }
136     if (imageTexId != 0) {
137         glDeleteTextures(1, &imageTexId);
138     }
139     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
140     glGenTextures(1, &imageTexId);
141     glBindTexture(GL_TEXTURE_2D, imageTexId);
142     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
143     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
144     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, sourceSize.width, sourceSize.height, 0,
145         transformData_.glFormat, GL_UNSIGNED_BYTE, NULL);
146     if (perPixelSize * sourceSize.width == transformData_.sourceInfo_.stride) {
147         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, sourceSize.width, sourceSize.height,
148             transformData_.glFormat, GL_UNSIGNED_BYTE, data);
149     } else {
150         GLuint pbo = 0;
151         glGenBuffers(1, &pbo);
152         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
153         glBufferData(GL_PIXEL_UNPACK_BUFFER,
154             sourceSize.width * sourceSize.height * perPixelSize, NULL, GL_STREAM_DRAW);
155         char *mapPointer = (char *)glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0,
156             sourceSize.width * sourceSize.height * perPixelSize, GL_MAP_WRITE_BIT);
157         if (mapPointer == NULL) {
158             return false;
159         }
160         for (int i = 0; i < sourceSize.height; i++) {
161             if (memcpy_s(mapPointer + sourceSize.width * perPixelSize * i,
162                 sourceSize.width * perPixelSize * (sourceSize.height - i),
163                 data + perPixelSize * i, sourceSize.width * perPixelSize) != 0) {
164                 IMAGE_LOGE("slr_gpu %{public}s memcpy_s failed", __func__);
165                 return false;
166             }
167         }
168         glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
169         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, sourceSize.width, sourceSize.height, 0,
170             transformData_.glFormat, GL_UNSIGNED_BYTE, NULL);
171         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
172         glDeleteBuffers(1, &pbo);
173     }
174     GLenum err = glGetError();
175     if (err != GL_NO_ERROR) {
176         IMAGE_LOGE("slr_gpu %{public}s failed gl error: %{public}x", __func__, err);
177         return false;
178     }
179     return true;
180 }
181 
CreateEGLImage(OHNativeWindowBuffer * nativeBuffer,EGLImageKHR & eglImage,GLuint & imageTexId)182 bool PixelMapGLPostProcProgram::CreateEGLImage(OHNativeWindowBuffer *nativeBuffer,
183     EGLImageKHR &eglImage, GLuint &imageTexId)
184 {
185     if (nativeBuffer == nullptr) {
186         return false;
187     }
188     static EGLint attrs[] = {
189         EGL_IMAGE_PRESERVED,
190         EGL_TRUE,
191         EGL_NONE,
192     };
193     eglImage = eglCreateImageKHR(
194         renderContext_->GetEGLDisplay(), EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_OHOS,
195         nativeBuffer, attrs);
196     if (eglImage == EGL_NO_IMAGE_KHR) {
197         IMAGE_LOGE("slr_gpu %{public}s create egl image fail %{public}d", __func__, eglGetError());
198         return false;
199     }
200     if (imageTexId != 0) {
201         glDeleteTextures(1, &imageTexId);
202     }
203     glGenTextures(1, &imageTexId);
204     glBindTexture(GL_TEXTURE_EXTERNAL_OES, imageTexId);
205     glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
206     glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
207     static auto glEGLImageTargetTexture2DOESFunc = reinterpret_cast<PFNGLEGLIMAGETARGETTEXTURE2DOESPROC>(
208         eglGetProcAddress("glEGLImageTargetTexture2DOES"));
209     if (glEGLImageTargetTexture2DOESFunc == nullptr) {
210         IMAGE_LOGE("slr_gpu %{public}s glEGLImageTargetTexture2DOES func not found: %{public}d",
211             __func__, eglGetError());
212         return false;
213     }
214     glEGLImageTargetTexture2DOESFunc(GL_TEXTURE_EXTERNAL_OES, static_cast<GLeglImageOES>(eglImage));
215     return true;
216 }
217 
UseEGLImageCreateNormalImage(GLuint & imageTexId)218 bool PixelMapGLPostProcProgram::UseEGLImageCreateNormalImage(GLuint &imageTexId)
219 {
220     GLuint eglImageTexId = imageTexId;
221     Size &sourceSize = transformData_.sourceInfo_.size;
222     GLuint tempFbo[NUM_2];
223     glGenFramebuffers(NUM_2, tempFbo);
224     glBindFramebuffer(GL_READ_FRAMEBUFFER, tempFbo[0]);
225     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_EXTERNAL_OES, eglImageTexId, 0);
226     IMAGE_LOGD("readfbo status %{public}x", glCheckFramebufferStatus(GL_READ_FRAMEBUFFER));
227 
228     glGenTextures(1, &imageTexId);
229     glBindTexture(GL_TEXTURE_2D, imageTexId);
230     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
231     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
232     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, sourceSize.width, sourceSize.height, 0,
233         transformData_.glFormat, GL_UNSIGNED_BYTE, NULL);
234 
235     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, tempFbo[1]);
236     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, imageTexId, 0);
237     IMAGE_LOGD("drawfbo status %{public}x", glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER));
238 
239     glBlitFramebuffer(0, 0, sourceSize.width, sourceSize.height, 0, 0, sourceSize.width,
240         sourceSize.height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
241     eglDestroyImageKHR(renderContext_->GetEGLDisplay(), eglImage_);
242     glDeleteTextures(1, &eglImageTexId);
243     glDeleteFramebuffers(NUM_2, tempFbo);
244     eglImage_ = EGL_NO_IMAGE_KHR;
245     GLenum err = glGetError();
246     if (err != GL_NO_ERROR) {
247         IMAGE_LOGE("slr_gpu %{public}s failed gl error: %{public}x", __func__, err);
248         return false;
249     }
250     return true;
251 }
252 
GLMakecurrent(bool needCurrent)253 bool PixelMapGLPostProcProgram::GLMakecurrent(bool needCurrent)
254 {
255     if (!renderContext_) {
256         IMAGE_LOGE("slr_gpu GLMakecurrent renderContext_ == nullptr");
257         return false;
258     }
259     return renderContext_->MakeCurrentSimple(needCurrent);
260 }
261 
InitGLResource()262 bool PixelMapGLPostProcProgram::InitGLResource()
263 {
264     vertexShader_ = std::make_shared<PixelMapGlShader::VertexShader>();
265     if (!vertexShader_->LoadProgram()) {
266         return false;
267     }
268     rotateShader_ = std::make_shared<PixelMapGlShader::RotateShader>();
269     if (!rotateShader_->LoadProgram()) {
270         return false;
271     }
272     slrShader_ = std::make_shared<PixelMapGlShader::SLRShader>();
273     if (!slrShader_->LoadProgram()) {
274         return false;
275     }
276     lapShader_ = std::make_shared<PixelMapGlShader::LapShader>();
277     if (!lapShader_->LoadProgram()) {
278         return false;
279     }
280     return true;
281 }
282 
BuildProcTexture(bool needThumb,bool needUpload,GLuint & readTexId)283 bool PixelMapGLPostProcProgram::BuildProcTexture(bool needThumb, bool needUpload, GLuint &readTexId)
284 {
285     OHNativeWindowBuffer *nativeBuffer = nullptr;
286     const uint8_t *normalBuffer = nullptr;
287     if (!transformData_.isDma) {
288         normalBuffer = transformData_.sourceInfo_.addr;
289         if (!CreateNormalImage(normalBuffer, readTexId)) {
290             return false;
291         }
292     } else {
293         void *surfaceBuffer = transformData_.sourceInfo_.context;
294         nativeBuffer = CreateNativeWindowBufferFromSurfaceBuffer(&surfaceBuffer);
295         if (!CreateEGLImage(nativeBuffer, eglImage_, readTexId)) {
296             DestroyNativeWindowBuffer(nativeBuffer);
297             return false;
298         }
299         DestroyNativeWindowBuffer(nativeBuffer);
300         if (!UseEGLImageCreateNormalImage(readTexId)) {
301             return false;
302         }
303     }
304     GLenum err = glGetError();
305     if (err != GL_NO_ERROR) {
306         IMAGE_LOGE("slr_gpu %{public}s failed gl error: %{public}d %{public}x", __func__, __LINE__, err);
307         return false;
308     }
309     return true;
310 }
311 
DestroyProcTexture()312 void PixelMapGLPostProcProgram::DestroyProcTexture()
313 {
314     glBindTexture(GL_TEXTURE_2D, 0);
315     glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
316     if (eglImage_ != EGL_NO_IMAGE_KHR) {
317         eglDestroyImageKHR(renderContext_->GetEGLDisplay(), eglImage_);
318     }
319     eglImage_ = EGL_NO_IMAGE_KHR;
320     return;
321 }
322 
GenProcEndData(char * lcdData)323 bool PixelMapGLPostProcProgram::GenProcEndData(char *lcdData)
324 {
325     ImageTrace imageTrace("GenProcEndData");
326     switch (transformData_.transformationType) {
327         case TransformationType::SCALE :
328             if (!(BuildProcTexture(false, true, slrShader_->GetReadTexId()) &&
329                 ResizeScaleWithGL() && ReadEndData(lcdData, lapShader_->GetWriteTexId()))) {
330                 return false;
331             }
332             break;
333         case TransformationType::ROTATE :
334             if (!(BuildProcTexture(false, true, rotateShader_->GetReadTexId()) &&
335                 ResizeRotateWithGL() && ReadEndData(lcdData, rotateShader_->GetWriteTexId()))) {
336                 return false;
337             }
338             break;
339         default:
340             break;
341     }
342 
343     DestroyProcTexture();
344     return true;
345 }
346 
GenProcDmaEndData(void * surfaceBuffer)347 bool PixelMapGLPostProcProgram::GenProcDmaEndData(void *surfaceBuffer)
348 {
349     ImageTrace imageTrace("GenProcEndData-surface");
350     switch (transformData_.transformationType) {
351         case TransformationType::SCALE :
352             if (!(BuildProcTexture(false, true, slrShader_->GetReadTexId()) &&
353                 ResizeScaleWithGL() && ReadEndDMAData(surfaceBuffer, lapShader_->GetWriteFbo()))) {
354                 return false;
355             }
356             break;
357         case TransformationType::ROTATE :
358             if (!(BuildProcTexture(false, true, rotateShader_->GetReadTexId()) &&
359                 ResizeRotateWithGL() && ReadEndDMAData(surfaceBuffer, rotateShader_->GetWriteFbo()))) {
360                 return false;
361             }
362             break;
363         default:
364             break;
365     }
366     DestroyProcTexture();
367     return true;
368 }
369 
ResizeScaleWithGL()370 bool PixelMapGLPostProcProgram::ResizeScaleWithGL()
371 {
372     ImageTrace imageTrace("ResizeScaleWithGL");
373     ((PixelMapGlShader::SLRShader*)(slrShader_.get()))->SetEglImage(eglImage_);
374     ((PixelMapGlShader::SLRShader*)(slrShader_.get()))->SetParams(transformData_);
375     if (!slrShader_->Use()) {
376         return false;
377     }
378     ((PixelMapGlShader::LapShader*)(lapShader_.get()))->SetParams(transformData_);
379     lapShader_->GetReadTexId() = slrShader_->GetWriteTexId();
380     if (!lapShader_->Use()) {
381         return false;
382     }
383     GLenum err = glGetError();
384     if (err != GL_NO_ERROR) {
385         IMAGE_LOGE("slr_gpu 3 %{public}s failed gl error: %{public}x", __func__, err);
386         return false;
387     }
388     return true;
389 }
390 
ResizeRotateWithGL()391 bool PixelMapGLPostProcProgram::ResizeRotateWithGL()
392 {
393     ImageTrace imageTrace("ResizeRotateWithGL");
394     rotateShader_->SetParams(transformData_);
395     if (!rotateShader_->Use()) {
396         return false;
397     }
398     return true;
399 }
400 
ReadEndData(char * targetData,GLuint & writeTexId)401 bool PixelMapGLPostProcProgram::ReadEndData(char *targetData, GLuint &writeTexId)
402 {
403     ImageTrace imageTrace("ReadEndData");
404     if (targetData == nullptr) {
405         return false;
406     }
407     Size &targetSize = transformData_.targetInfo_.size;
408     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, writeTexId, 0);
409     if (targetSize.width * NUM_4 >= transformData_.targetInfo_.stride) {
410         glReadPixels(0, 0, targetSize.width, targetSize.height, GL_RGBA, GL_UNSIGNED_BYTE, targetData);
411     } else {
412         GLuint pbo = 0;
413         glGenBuffers(1, &pbo);
414         glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
415         glBufferData(GL_PIXEL_PACK_BUFFER, targetSize.width * targetSize.height * NUM_4, NULL, GL_STREAM_READ);
416         glReadPixels(0, 0, targetSize.width, targetSize.height, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
417         char *mapPointer = (char *)glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0,
418             targetSize.width * targetSize.height * NUM_4, GL_MAP_READ_BIT);
419         if (mapPointer == NULL) {
420             return false;
421         }
422         for (int i = 0; i < targetSize.height; i++) {
423             if (memcpy_s(targetData + transformData_.targetInfo_.stride * i,
424                 targetSize.width * NUM_4 * (targetSize.height - i),
425                 mapPointer + targetSize.width * NUM_4 * i, targetSize.width * NUM_4) != 0) {
426                 IMAGE_LOGE("slr_gpu %{public}s memcpy_s fail", __func__);
427                 return false;
428             }
429         }
430         glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
431         glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
432         glDeleteBuffers(1, &pbo);
433     }
434 
435     glFinish();
436     GLenum err = glGetError();
437     if (err != GL_NO_ERROR) {
438         IMAGE_LOGE("slr_gpu %{public}s fail %{public}x", __func__, err);
439         return false;
440     }
441     return true;
442 }
443 
ReadEndDMAData(void * surfaceBuffer,GLuint & writeFbo)444 bool PixelMapGLPostProcProgram::ReadEndDMAData(void *surfaceBuffer, GLuint &writeFbo)
445 {
446     ImageTrace imageTrace("ReadEndDMAData ");
447     OHNativeWindowBuffer *nativeBuffer = CreateNativeWindowBufferFromSurfaceBuffer(&surfaceBuffer);
448     EGLImage endEglImage;
449     GLuint endReadTexId;
450     if (!CreateEGLImage(nativeBuffer, endEglImage, endReadTexId)) {
451         IMAGE_LOGE("slr_gpu ReadEndDMAData CreateEGLImage fail %{public}d", eglGetError());
452         return false;
453     }
454     GLuint endFbo;
455     glGenFramebuffers(1, &endFbo);
456     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, endFbo);
457     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_EXTERNAL_OES, endReadTexId, 0);
458     glBindFramebuffer(GL_READ_FRAMEBUFFER, writeFbo);
459     Size &targetSize = transformData_.targetInfo_.size;
460     glBlitFramebuffer(0, 0, targetSize.width, targetSize.height, 0, 0,
461         targetSize.width, targetSize.height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
462     eglDestroyImageKHR(renderContext_->GetEGLDisplay(), endEglImage);
463     glDeleteTextures(1, &endReadTexId);
464     glDeleteFramebuffers(1, &endFbo);
465     DestroyNativeWindowBuffer(nativeBuffer);
466     glFinish();
467     GLenum err = glGetError();
468     if (err != GL_NO_ERROR) {
469         IMAGE_LOGE("slr_gpu %{public}s failed gl error: %{public}x", __func__, err);
470         return false;
471     }
472     return true;
473 }
474 
Execute()475 bool PixelMapGLPostProcProgram::Execute()
476 {
477     if (!GLMakecurrent(true)) {
478         IMAGE_LOGE("slr_gpu GenProcEndData cannot makecurent with opengl");
479         return false;
480     }
481     bool ret = true;
482     if (transformData_.isDma) {
483         ret = GenProcDmaEndData(transformData_.targetInfo_.context);
484     } else {
485         ret = GenProcEndData((char*)transformData_.targetInfo_.outdata);
486     }
487     if (!GLMakecurrent(false)) {
488         IMAGE_LOGE("slr_gpu GenProcEndData Unbinding failed");
489         return false;
490     }
491     return ret;
492 }
493 } // namespace Media
494 } //