1 /*
2 * Copyright (c) 2022 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 "gles_gfx_image.h"
16 #include "window.h"
17 #include "egl_ext_function.h"
18 #include "display_common.h"
19 #include "hardware_buffer.h"
20 #include "display_bytrace.h"
21 #include "display_utils.h"
22 namespace OHOS {
23 namespace HDI {
24 namespace DISPLAY {
GlesGfxImage(EGLDisplay display)25 GlesGfxImage::GlesGfxImage(EGLDisplay display) : eglDisplay_(display)
26 {
27 DISPLAY_LOGD();
28 }
29
~GlesGfxImage()30 GlesGfxImage::~GlesGfxImage()
31 {
32 DISPLAY_LOGD();
33 for (uint32_t i = 0; i < TEXTURE_COUNT; i++) {
34 if (textureId_[i] != 0) {
35 glDeleteTextures(1, &textureId_[i]);
36 }
37 }
38 if (eglImageKHr_ != EGL_NO_IMAGE_KHR) {
39 EglExtFunction::getInstance().eglDestroyImageKHR(eglDisplay_, eglImageKHr_);
40 }
41 }
42
Creat(EGLDisplay display,const BufferHandle & bufferHandle)43 std::unique_ptr<GlesGfxImage> GlesGfxImage::Creat(EGLDisplay display, const BufferHandle &bufferHandle)
44 {
45 DISPLAY_LOGD();
46 DisplayBytrace trace("GlesGfxImage::Creat");
47 auto image = std::make_unique<GlesGfxImage>(display);
48 if (image->Init(display, bufferHandle)) {
49 return image;
50 }
51 DISPLAY_LOGE("Falied to int gfx image");
52 return nullptr;
53 }
54
Init(EGLDisplay display,const BufferHandle & bufferHandle)55 bool GlesGfxImage::Init(EGLDisplay display, const BufferHandle &bufferHandle)
56 {
57 DISPLAY_LOGD();
58 eglDisplay_ = display;
59 if (DisplayUtils::IsYuv(static_cast<PixelFormat>(bufferHandle.format))) {
60 return CreateImageYuv(bufferHandle);
61 } else {
62 return CreateImageRgb(bufferHandle);
63 }
64 }
65
CreateEglImage(EGLDisplay display,const BufferHandle & bufferhandle)66 EGLImage GlesGfxImage::CreateEglImage(EGLDisplay display, const BufferHandle &bufferhandle)
67 {
68 DISPLAY_LOGD();
69 OHOS::sptr<OHOS::SurfaceBuffer> SurfaceBuffer = OHOS::HardwareBuffer::Create(bufferhandle);
70 if (SurfaceBuffer == nullptr) {
71 DISPLAY_LOGE("Failed to create surface buffer");
72 return EGL_NO_IMAGE_KHR;
73 }
74 struct NativeWindowBuffer *nativeWindowBuffer = CreateNativeWindowBufferFromSurfaceBuffer(&SurfaceBuffer);
75 EGLImageKHR img = EglExtFunction::getInstance().eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_OHOS,
76 nativeWindowBuffer, 0);
77 if (img == EGL_NO_IMAGE_KHR) {
78 DISPLAY_LOGE("Failed to create Image Khr");
79 }
80 DestoryNativeWindowBuffer(nativeWindowBuffer);
81 return img;
82 }
83
DestroyEglImage(EGLDisplay display,EGLImageKHR image)84 EGLBoolean GlesGfxImage::DestroyEglImage(EGLDisplay display, EGLImageKHR image)
85 {
86 return EglExtFunction::getInstance().eglDestroyImageKHR(display, image);
87 }
88
89
CreateTextures(uint32_t num)90 void GlesGfxImage::CreateTextures(uint32_t num)
91 {
92 DISPLAY_LOGD("CreateTextures");
93 if (num > TEXTURE_COUNT) {
94 DISPLAY_LOGE("the number is error");
95 num = TEXTURE_COUNT;
96 }
97
98 for (int i = 0; i < num; i++) {
99 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // todo wether need ?
100 glGenTextures(1, &textureId_[i]);
101 glBindTexture(GL_TEXTURE_2D, textureId_[i]);
102 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
103 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
104 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
105 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
106 }
107 }
108
CreateImageRgb(const BufferHandle & bufferHandle)109 bool GlesGfxImage::CreateImageRgb(const BufferHandle &bufferHandle)
110 {
111 DISPLAY_LOGD();
112 CreateTextures(1);
113 glActiveTexture(GL_TEXTURE0);
114 glBindTexture(GL_TEXTURE_2D, textureId_[INDEX_RGB_TEXTURE]);
115 OHOS::sptr<OHOS::SurfaceBuffer> SurfaceBuffer = OHOS::HardwareBuffer::Create(bufferHandle);
116 if (SurfaceBuffer == nullptr) {
117 DISPLAY_LOGE("Failed to create surface buffer");
118 return false;
119 }
120 struct NativeWindowBuffer *nativeWindowBuffer = CreateNativeWindowBufferFromSurfaceBuffer(&SurfaceBuffer);
121 EGLImageKHR img = EglExtFunction::getInstance().eglCreateImageKHR(eglDisplay_, EGL_NO_CONTEXT,
122 EGL_NATIVE_BUFFER_OHOS, nativeWindowBuffer, 0);
123 if (img == EGL_NO_IMAGE_KHR) {
124 DISPLAY_LOGE("Failed to create Image Khr");
125 }
126 EglExtFunction::getInstance().glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, img);
127 eglImageKHr_ = img;
128
129 DestoryNativeWindowBuffer(nativeWindowBuffer);
130 return true;
131 }
132
CreateImageYuv(const BufferHandle & bufferHandle)133 bool GlesGfxImage::CreateImageYuv(const BufferHandle &bufferHandle)
134 {
135 DISPLAY_LOGD("CreateImageYuv");
136 const uint32_t textureCount = 3;
137 constexpr const uint32_t UV_SCALE = 2;
138 if (bufferHandle.virAddr == nullptr) {
139 DISPLAY_LOGE("Failed to create yuv image for the virtual address is nullptr");
140 return false;
141 }
142
143 uint8_t *yData = static_cast<uint8_t *>(bufferHandle.virAddr);
144 uint8_t *uData = yData + (bufferHandle.width * bufferHandle.height); // reduce the width
145 uint8_t *vData = uData + (bufferHandle.width * bufferHandle.height) / UV_SCALE / UV_SCALE; // reduce the width
146 CreateTextures(textureCount);
147 // for Y
148 glActiveTexture(GL_TEXTURE0);
149 glBindTexture(GL_TEXTURE_2D, textureId_[INDEX_Y_TEXTURE]);
150 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, bufferHandle.width, bufferHandle.height, 0, GL_LUMINANCE,
151 GL_UNSIGNED_BYTE, yData);
152
153 glActiveTexture(GL_TEXTURE1);
154 glBindTexture(GL_TEXTURE_2D, textureId_[INDEX_U_TEXTURE]);
155 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, bufferHandle.width / UV_SCALE, bufferHandle.height / UV_SCALE, 0,
156 GL_LUMINANCE, GL_UNSIGNED_BYTE, uData);
157
158 glActiveTexture(GL_TEXTURE2);
159 glBindTexture(GL_TEXTURE_2D, textureId_[INDEX_V_TEXTURE]);
160 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, bufferHandle.width / UV_SCALE, bufferHandle.height / UV_SCALE, 0,
161 GL_LUMINANCE, GL_UNSIGNED_BYTE, vData);
162 return true;
163 }
164 }
165 }
166 }