1 /*
2 * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development 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 "rosen_context_impl.h"
17
18 #include "ui/rs_surface_extractor.h"
19 #include "backend/rs_surface_ohos_gl.h"
20
21 using namespace OHOS;
22 using namespace Rosen;
23
RosenContextImpl()24 RosenContextImpl::RosenContextImpl()
25 {
26 InitEgl();
27 InitProducer();
28 }
29
ShowConfig(EGLConfig cfg)30 void RosenContextImpl::ShowConfig(EGLConfig cfg)
31 {
32 EGLint red, green, blue, alpha, depth, stencil, samples, sft, rt;
33
34 eglGetConfigAttrib(eglDisplay_, cfg, EGL_RED_SIZE, &red);
35 eglGetConfigAttrib(eglDisplay_, cfg, EGL_GREEN_SIZE, &green);
36 eglGetConfigAttrib(eglDisplay_, cfg, EGL_BLUE_SIZE, &blue);
37 eglGetConfigAttrib(eglDisplay_, cfg, EGL_ALPHA_SIZE, &alpha);
38 eglGetConfigAttrib(eglDisplay_, cfg, EGL_DEPTH_SIZE, &depth);
39 eglGetConfigAttrib(eglDisplay_, cfg, EGL_STENCIL_SIZE, &stencil);
40 eglGetConfigAttrib(eglDisplay_, cfg, EGL_SAMPLES, &samples);
41 eglGetConfigAttrib(eglDisplay_, cfg, EGL_SURFACE_TYPE, &sft);
42 eglGetConfigAttrib(eglDisplay_, cfg, EGL_RENDERABLE_TYPE, &rt);
43
44 printf("%8d%8d%8d%8d%8d%8d%8d%8d%8d\n", red, green, blue, alpha, depth, stencil, samples, sft, rt);
45 }
46
InitProducer()47 void RosenContextImpl::InitProducer()
48 {
49 displayNode_ = RSDisplayNode::Create(RSDisplayNodeConfig());
50 surfaceNode_ = RSSurfaceNode::Create(RSSurfaceNodeConfig());
51 surfaceNode_->SetBounds(0, 0, 512, 512);
52 displayNode_->AddChild(surfaceNode_, -1);
53
54 std::shared_ptr<RSSurface> rsSurface = RSSurfaceExtractor::ExtractRSSurface(surfaceNode_);
55 std::shared_ptr<RSSurfaceOhosGl> rsSurfaceOhosGl = std::static_pointer_cast<RSSurfaceOhosGl>(rsSurface);
56 producer_ = rsSurfaceOhosGl->GetSurface();
57 }
58
InitEgl()59 bool RosenContextImpl::InitEgl()
60 {
61 if(eglInited_) {
62 return true;
63 }
64 eglDisplay_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
65 if (eglDisplay_ == EGL_NO_DISPLAY)
66 {
67 printf("Failed to create EGLDisplay gl errno : %x", eglGetError());
68 return false;
69 }
70
71 EGLint major, minor;
72 if (eglInitialize(eglDisplay_, &major, &minor) == EGL_FALSE)
73 {
74 printf("Failed to initialize EGLDisplay");
75 return false;
76 }
77
78 glDepthMask(GL_TRUE);
79
80 eglGetConfigs(eglDisplay_, NULL, 0, &configCount_);
81 allConfigs_ = new EGLConfig[configCount_];
82 eglGetConfigs(eglDisplay_, allConfigs_, configCount_, &configCount_);
83
84 printf("config count : %d\n", configCount_);
85 for (int i = 0; i < configCount_; i++)
86 {
87 ShowConfig(allConfigs_[i]);
88 }
89 eglInited_ = true;
90 return true;
91 }
92
SetConfig(int32_t w,int32_t h,RCI_GLES_VERSION ver,RCI_PIXEL_FORMAT pf,RCI_SURFACE_TYPE st,RCI_PROFILE tp,RCI_CONTEXT_FLAG flags)93 bool RosenContextImpl::SetConfig(int32_t w, int32_t h, RCI_GLES_VERSION ver, RCI_PIXEL_FORMAT pf, RCI_SURFACE_TYPE st, RCI_PROFILE tp, RCI_CONTEXT_FLAG flags)
94 {
95 glesVersion_ = ver;
96 typeProfile_ = tp;
97 contextFlags_ = flags;
98 surfaceType_ = st;
99 width_ = w;
100 height_ = h;
101 pixelFormat_ = pf;
102
103 EGLint eglApi;
104 switch (typeProfile_)
105 {
106 case RCI_PROFILE::ES:
107 eglApi = EGL_OPENGL_ES_API;
108 break;
109 case RCI_PROFILE::CORE:
110 eglApi = EGL_OPENGL_API;
111 break;
112 case RCI_PROFILE::COMPATIBILITY:
113 eglApi = EGL_OPENGL_API;
114 break;
115 default:
116 return false;
117 }
118 if (eglBindAPI(EGL_OPENGL_ES_API) == EGL_FALSE)
119 {
120 printf("Failed to bind OpenGL ES API");
121 return false;
122 }
123
124 std::vector<EGLint> frameBufferAttribs;
125 frameBufferAttribs.push_back(EGL_RENDERABLE_TYPE);
126 switch (static_cast<int>(glesVersion_) / 10)
127 {
128 case 3:
129 frameBufferAttribs.push_back(EGL_OPENGL_ES3_BIT);
130 break;
131 case 2:
132 frameBufferAttribs.push_back(EGL_OPENGL_ES2_BIT);
133 break;
134 default:
135 frameBufferAttribs.push_back(EGL_OPENGL_ES_BIT);
136 }
137
138 frameBufferAttribs.push_back(EGL_SURFACE_TYPE);
139 switch (surfaceType_)
140 {
141 case RCI_SURFACE_TYPE::NONE:
142 frameBufferAttribs.push_back(EGL_DONT_CARE);
143 break;
144 case RCI_SURFACE_TYPE::PBUFFER:
145 frameBufferAttribs.push_back(EGL_PBUFFER_BIT);
146 break;
147 case RCI_SURFACE_TYPE::PIXMAP:
148 frameBufferAttribs.push_back(EGL_PIXMAP_BIT);
149 break;
150 case RCI_SURFACE_TYPE::WINDOW:
151 frameBufferAttribs.push_back(EGL_WINDOW_BIT);
152 break;
153 }
154
155 if (pixelFormat_.redBits != -1)
156 {
157 frameBufferAttribs.push_back(EGL_RED_SIZE);
158 frameBufferAttribs.push_back(pixelFormat_.redBits);
159 }
160 if (pixelFormat_.greenBits != -1)
161 {
162 frameBufferAttribs.push_back(EGL_GREEN_SIZE);
163 frameBufferAttribs.push_back(pixelFormat_.greenBits);
164 }
165 if (pixelFormat_.blueBits != -1)
166 {
167 frameBufferAttribs.push_back(EGL_BLUE_SIZE);
168 frameBufferAttribs.push_back(pixelFormat_.blueBits);
169 }
170 if (pixelFormat_.alphaBits != -1)
171 {
172 frameBufferAttribs.push_back(EGL_ALPHA_SIZE);
173 frameBufferAttribs.push_back(pixelFormat_.alphaBits);
174 }
175 if (pixelFormat_.depthBits != -1)
176 {
177 frameBufferAttribs.push_back(EGL_DEPTH_SIZE);
178 frameBufferAttribs.push_back(pixelFormat_.depthBits);
179 }
180 if (pixelFormat_.stencilBits != -1)
181 {
182 frameBufferAttribs.push_back(EGL_STENCIL_SIZE);
183 frameBufferAttribs.push_back(pixelFormat_.stencilBits);
184 }
185 if (pixelFormat_.numSamples != -1)
186 {
187 frameBufferAttribs.push_back(EGL_SAMPLES);
188 frameBufferAttribs.push_back(pixelFormat_.numSamples);
189 }
190 frameBufferAttribs.push_back(EGL_NONE);
191
192 unsigned int ret;
193 EGLint count;
194 ret = eglChooseConfig(eglDisplay_, &frameBufferAttribs[0], &config_, 1, &count);
195 printf("ret=%d,count=%d\n", ret, count);
196 if (!(ret && static_cast<unsigned int>(count) >= 1))
197 {
198 printf("Failed to eglChooseConfig\n");
199 return false;
200 }
201 EGLint red, green, blue, alpha, depth, stencil, samples;
202 eglGetConfigAttrib(eglDisplay_, config_, EGL_RED_SIZE, &red);
203 eglGetConfigAttrib(eglDisplay_, config_, EGL_GREEN_SIZE, &green);
204 eglGetConfigAttrib(eglDisplay_, config_, EGL_BLUE_SIZE, &blue);
205 eglGetConfigAttrib(eglDisplay_, config_, EGL_ALPHA_SIZE, &alpha);
206 eglGetConfigAttrib(eglDisplay_, config_, EGL_DEPTH_SIZE, &depth);
207 eglGetConfigAttrib(eglDisplay_, config_, EGL_STENCIL_SIZE, &stencil);
208 eglGetConfigAttrib(eglDisplay_, config_, EGL_SAMPLES, &samples);
209 ShowConfig(config_);
210 if (pixelFormat_.redBits == -1)
211 {
212 pixelFormat_.redBits = red;
213 }
214 else if (pixelFormat_.redBits != red)
215 {
216 printf("Failed to eglChooseConfig redBits %d != %d\n", pixelFormat_.redBits, red);
217 return false;
218 }
219
220 if (pixelFormat_.greenBits == -1)
221 {
222 pixelFormat_.greenBits = green;
223 }
224 else if (pixelFormat_.greenBits != green)
225 {
226 printf("Failed to eglChooseConfig redBits %d != %d\n", pixelFormat_.greenBits, green);
227 return false;
228 }
229
230 if (pixelFormat_.blueBits != blue)
231 {
232 if (pixelFormat_.blueBits != -1)
233 printf("Failed to eglChooseConfig blueBits %d != %d\n", pixelFormat_.blueBits, blue);
234 pixelFormat_.blueBits = blue;
235 }
236
237 if (pixelFormat_.alphaBits != alpha)
238 {
239 if (pixelFormat_.alphaBits != -1)
240 printf("Failed to eglChooseConfig alphaBits %d != %d\n", pixelFormat_.alphaBits, alpha);
241 pixelFormat_.alphaBits = alpha;
242 }
243
244 if (pixelFormat_.depthBits != depth)
245 {
246 if (pixelFormat_.depthBits != -1)
247 printf("Failed to eglChooseConfig depthBits %d != %d\n", pixelFormat_.depthBits, depth);
248 pixelFormat_.depthBits = depth;
249 }
250
251 if (pixelFormat_.stencilBits != stencil)
252 {
253 if (pixelFormat_.stencilBits != -1)
254 printf("Failed to eglChooseConfig stencilBits %d != %d\n", pixelFormat_.stencilBits, stencil);
255 pixelFormat_.stencilBits = stencil;
256 }
257
258 if (pixelFormat_.numSamples != samples)
259 {
260 if (pixelFormat_.numSamples != -1)
261 printf("Failed to eglChooseConfig numSamples %d != %d\n", pixelFormat_.numSamples, samples);
262 pixelFormat_.numSamples = samples;
263 }
264 printf("config ok\n");
265 return true;
266 }
267
InitNativeWindow()268 bool RosenContextImpl::InitNativeWindow()
269 {
270 if (nativeWindow_ == nullptr)
271 {
272 nativeWindow_ = CreateNativeWindowFromSurface(&producer_);
273 }
274 NativeWindowHandleOpt(nativeWindow_, SET_BUFFER_GEOMETRY, width_, height_);
275 if (pixelFormat_.stencilBits != -1)
276 {
277 NativeWindowHandleOpt(nativeWindow_, SET_STRIDE, pixelFormat_.stencilBits);
278 }
279 if (pixelFormat_.redBits == 8 && pixelFormat_.greenBits == 8 && pixelFormat_.blueBits == 8 && pixelFormat_.alphaBits == 8)
280 {
281 NativeWindowHandleOpt(nativeWindow_, SET_FORMAT, GRAPHIC_PIXEL_FMT_RGBA_8888);
282 //NativeWindowHandleOpt(nativeWindow_, SET_FORMAT, PIXEL_FMT_RGBA_8888);
283 }
284 else if (pixelFormat_.redBits == 5 && pixelFormat_.greenBits == 6 && pixelFormat_.blueBits == 5 && pixelFormat_.alphaBits == 0)
285 {
286 NativeWindowHandleOpt(nativeWindow_, SET_FORMAT, GRAPHIC_PIXEL_FMT_RGB_565);
287 //NativeWindowHandleOpt(nativeWindow_, SET_FORMAT, PIXEL_FMT_RGB_565);
288 }
289 else if (pixelFormat_.redBits == 4 && pixelFormat_.greenBits == 4 && pixelFormat_.blueBits == 4 && pixelFormat_.alphaBits == 4)
290 {
291 NativeWindowHandleOpt(nativeWindow_, SET_FORMAT, GRAPHIC_PIXEL_FMT_RGBA_4444);
292 //NativeWindowHandleOpt(nativeWindow_, SET_FORMAT, PIXEL_FMT_RGBA_4444);
293 }
294 printf("native window ok\n");
295 return true;
296 }
297
InitEglSurface()298 bool RosenContextImpl::InitEglSurface()
299 {
300 if(eglSurface_ != EGL_NO_SURFACE) {
301 eglDestroySurface(eglDisplay_, eglSurface_);
302 eglSurface_ = EGL_NO_SURFACE;
303 }
304
305 eglMakeCurrent(eglDisplay_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
306
307 std::vector<EGLint> surfaceAttribs;
308
309 switch (surfaceType_)
310 {
311 case RCI_SURFACE_TYPE::NONE:
312 break;
313 case RCI_SURFACE_TYPE::WINDOW:
314 // surfaceAttribs.push_back(EGL_GL_COLORSPACE_KHR);
315 //TODO: EGL_GL_COLORSPACE_LINEAR_KHR, EGL_GL_COLORSPACE_SRGB_KHR
316 // surfaceAttribs.push_back(EGL_GL_COLORSPACE_LINEAR_KHR);
317 surfaceAttribs.push_back(EGL_NONE);
318
319 eglSurface_ = eglCreateWindowSurface(eglDisplay_, config_, nativeWindow_, &surfaceAttribs[0]);
320 if (eglSurface_ == EGL_NO_SURFACE)
321 {
322 printf("Failed to create eglsurface!!! %x\n", eglGetError());
323 return false;
324 }
325 break;
326 case RCI_SURFACE_TYPE::PBUFFER:
327 case RCI_SURFACE_TYPE::PIXMAP:
328 surfaceAttribs.push_back(EGL_WIDTH);
329 surfaceAttribs.push_back(width_);
330 surfaceAttribs.push_back(EGL_HEIGHT);
331 surfaceAttribs.push_back(height_);
332 surfaceAttribs.push_back(EGL_NONE);
333 break;
334 }
335 printf("egl surface ok\n");
336 return true;
337 }
338
InitEglContext()339 bool RosenContextImpl::InitEglContext()
340 {
341 if(eglContext_ != EGL_NO_CONTEXT) {
342 eglDestroyContext(eglDisplay_, eglContext_);
343 eglContext_ = EGL_NO_CONTEXT;
344 }
345
346 std::vector<EGLint> contextAttribs;
347 contextAttribs.push_back(EGL_CONTEXT_MAJOR_VERSION_KHR);
348 contextAttribs.push_back(static_cast<int>(glesVersion_) / 10);
349 contextAttribs.push_back(EGL_CONTEXT_MINOR_VERSION_KHR);
350 contextAttribs.push_back(static_cast<int>(glesVersion_) % 10);
351
352 switch (typeProfile_)
353 {
354 case RCI_PROFILE::ES:
355 break;
356 case RCI_PROFILE::CORE:
357 contextAttribs.push_back(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR);
358 contextAttribs.push_back(EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR);
359 break;
360 case RCI_PROFILE::COMPATIBILITY:
361 contextAttribs.push_back(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR);
362 contextAttribs.push_back(EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR);
363 break;
364 }
365
366 EGLint flags = 0;
367 if ((static_cast<int>(contextFlags_) & static_cast<int>(RCI_CONTEXT_FLAG::DEBUG)) != 0)
368 flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
369
370 if ((static_cast<int>(contextFlags_) & static_cast<int>(RCI_CONTEXT_FLAG::ROBUST)) != 0)
371 flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
372
373 if ((static_cast<int>(contextFlags_) & static_cast<int>(RCI_CONTEXT_FLAG::FORWARD_COMPATIBLE)) != 0)
374 flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
375
376 contextAttribs.push_back(EGL_CONTEXT_FLAGS_KHR);
377 contextAttribs.push_back(flags);
378
379 contextAttribs.push_back(EGL_NONE);
380
381 eglContext_ = eglCreateContext(eglDisplay_, config_, EGL_NO_CONTEXT, &contextAttribs[0]);
382 if (eglContext_ == EGL_NO_CONTEXT)
383 {
384 printf("Failed to create egl context %x\n", eglGetError());
385 return false;
386 }
387 printf("context ok\n");
388 return true;
389 }
390
MakeCurrent()391 void RosenContextImpl::MakeCurrent()
392 {
393 if (!eglMakeCurrent(eglDisplay_, eglSurface_, eglSurface_, eglContext_))
394 {
395 printf("eglMakeCurrent FAIL\n");
396 }
397 }
398
SwapBuffer()399 void RosenContextImpl::SwapBuffer()
400 {
401 eglSwapBuffers(eglDisplay_, eglSurface_);
402 RSTransactionProxy::GetInstance()->FlushImplicitTransaction();
403 }
404
GetAttrib(int32_t attrType)405 int32_t RosenContextImpl::GetAttrib(int32_t attrType)
406 {
407 int32_t ret;
408 eglGetConfigAttrib(eglDisplay_, config_, attrType, &ret);
409 return ret;
410 }
411
CreateWindow(uint32_t x,uint32_t y,uint32_t width,uint32_t height)412 uint64_t RosenContextImpl::CreateWindow(uint32_t x,uint32_t y,uint32_t width,uint32_t height)
413 {
414 static uint64_t windowId = 1;
415 uint64_t wid = windowId++;
416
417 // printf("impl create window %llu\n",wid);
418 if(displayNode_==nullptr){
419 displayNode_ = RSDisplayNode::Create(RSDisplayNodeConfig());
420 }
421 vulkanWindows_[wid].surfaceNode_ = RSSurfaceNode::Create(RSSurfaceNodeConfig());
422 vulkanWindows_[wid].surfaceNode_->SetBounds(x,y,width,height);
423 displayNode_->AddChild(vulkanWindows_[wid].surfaceNode_, -1);
424
425 std::shared_ptr<RSSurface> rsSurface = RSSurfaceExtractor::ExtractRSSurface(vulkanWindows_[wid].surfaceNode_);
426 std::shared_ptr<RSSurfaceOhosGl> rsSurfaceOhosGl = std::static_pointer_cast<RSSurfaceOhosGl>(rsSurface);
427 vulkanWindows_[wid].producer_ = rsSurfaceOhosGl->GetSurface();
428
429 vulkanWindows_[wid].nativeWindow_ = CreateNativeWindowFromSurface(&vulkanWindows_[wid].producer_);
430 return wid;
431 }
432
GetNativeWindow(uint64_t windowId)433 void *RosenContextImpl::GetNativeWindow(uint64_t windowId)
434 {
435 // printf("impl get native window %llu\n",windowId);
436 return vulkanWindows_[windowId].nativeWindow_;
437 }
438
DestoryWindow(uint64_t windowId)439 void RosenContextImpl::DestoryWindow(uint64_t windowId)
440 {
441 // printf("impl destory window %llu\n",windowId);
442 displayNode_->RemoveChild(vulkanWindows_[windowId].surfaceNode_);
443 vulkanWindows_.erase(windowId);
444 }