xref: /aosp_15_r20/external/tensorflow/tensorflow/lite/delegates/gpu/gl/egl_context.cc (revision b6fb3261f9314811a0f4371741dbb8839866f948)
1 /* Copyright 2019 The TensorFlow Authors. All Rights Reserved.
2 
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 "tensorflow/lite/delegates/gpu/gl/egl_context.h"
17 
18 #include <cstring>
19 
20 #include "tensorflow/lite/delegates/gpu/common/status.h"
21 #include "tensorflow/lite/delegates/gpu/gl/gl_call.h"
22 #include "tensorflow/lite/delegates/gpu/gl/gl_errors.h"
23 
24 namespace tflite {
25 namespace gpu {
26 namespace gl {
27 namespace {
28 
GetConfig(EGLDisplay display,const EGLint * attributes,EGLConfig * config)29 absl::Status GetConfig(EGLDisplay display, const EGLint* attributes,
30                        EGLConfig* config) {
31   EGLint config_count;
32   bool chosen = eglChooseConfig(display, attributes, config, 1, &config_count);
33   RETURN_IF_ERROR(GetOpenGlErrors());
34   if (!chosen || config_count == 0) {
35     return absl::InternalError("No EGL error, but eglChooseConfig failed.");
36   }
37   return absl::OkStatus();
38 }
39 
CreateContext(EGLDisplay display,EGLContext shared_context,EGLConfig config,EglContext * egl_context)40 absl::Status CreateContext(EGLDisplay display, EGLContext shared_context,
41                            EGLConfig config, EglContext* egl_context) {
42   static const EGLint attributes[] = {EGL_CONTEXT_CLIENT_VERSION, 3,
43 #ifdef _DEBUG  // Add debugging bit
44                                       EGL_CONTEXT_FLAGS_KHR,
45                                       EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR,
46 #endif
47                                       EGL_NONE};
48   EGLContext context =
49       eglCreateContext(display, config, shared_context, attributes);
50   RETURN_IF_ERROR(GetOpenGlErrors());
51   if (context == EGL_NO_CONTEXT) {
52     return absl::InternalError("No EGL error, but eglCreateContext failed.");
53   }
54   *egl_context = EglContext(context, display, config, true);
55   return absl::OkStatus();
56 }
57 
HasExtension(EGLDisplay display,const char * name)58 bool HasExtension(EGLDisplay display, const char* name) {
59   return std::strstr(eglQueryString(display, EGL_EXTENSIONS), name);
60 }
61 
62 }  // namespace
63 
Invalidate()64 void EglContext::Invalidate() {
65   if (context_ != EGL_NO_CONTEXT) {
66     if (has_ownership_) {
67       eglMakeCurrent(display_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
68       eglDestroyContext(display_, context_);
69     }
70     context_ = EGL_NO_CONTEXT;
71   }
72   has_ownership_ = false;
73 }
74 
EglContext(EglContext && other)75 EglContext::EglContext(EglContext&& other)
76     : context_(other.context_),
77       display_(other.display_),
78       config_(other.config_),
79       has_ownership_(other.has_ownership_) {
80   other.context_ = EGL_NO_CONTEXT;
81   other.has_ownership_ = false;
82 }
83 
operator =(EglContext && other)84 EglContext& EglContext::operator=(EglContext&& other) {
85   if (this != &other) {
86     Invalidate();
87     using std::swap;
88     swap(context_, other.context_);
89     display_ = other.display_;
90     config_ = other.config_;
91     swap(has_ownership_, other.has_ownership_);
92   }
93   return *this;
94 }
95 
MakeCurrent(EGLSurface read,EGLSurface write)96 absl::Status EglContext::MakeCurrent(EGLSurface read, EGLSurface write) {
97   bool is_made_current = eglMakeCurrent(display_, write, read, context_);
98   RETURN_IF_ERROR(GetOpenGlErrors());
99   if (!is_made_current) {
100     return absl::InternalError("No EGL error, but eglMakeCurrent failed.");
101   }
102   return absl::OkStatus();
103 }
104 
IsCurrent() const105 bool EglContext::IsCurrent() const {
106   return context_ == eglGetCurrentContext();
107 }
108 
CreateConfiglessContext(EGLDisplay display,EGLContext shared_context,EglContext * egl_context)109 absl::Status CreateConfiglessContext(EGLDisplay display,
110                                      EGLContext shared_context,
111                                      EglContext* egl_context) {
112   if (!HasExtension(display, "EGL_KHR_no_config_context")) {
113     return absl::UnavailableError("EGL_KHR_no_config_context not supported");
114   }
115   return CreateContext(display, shared_context, EGL_NO_CONFIG_KHR, egl_context);
116 }
117 
CreateSurfacelessContext(EGLDisplay display,EGLContext shared_context,EglContext * egl_context)118 absl::Status CreateSurfacelessContext(EGLDisplay display,
119                                       EGLContext shared_context,
120                                       EglContext* egl_context) {
121   if (!HasExtension(display, "EGL_KHR_create_context")) {
122     return absl::UnavailableError("EGL_KHR_create_context not supported");
123   }
124   if (!HasExtension(display, "EGL_KHR_surfaceless_context")) {
125     return absl::UnavailableError("EGL_KHR_surfaceless_context not supported");
126   }
127   const EGLint attributes[] = {EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR,
128                                EGL_NONE};
129   EGLConfig config;
130   RETURN_IF_ERROR(GetConfig(display, attributes, &config));
131   return CreateContext(display, shared_context, config, egl_context);
132 }
133 
CreatePBufferContext(EGLDisplay display,EGLContext shared_context,EglContext * egl_context)134 absl::Status CreatePBufferContext(EGLDisplay display, EGLContext shared_context,
135                                   EglContext* egl_context) {
136   const EGLint attributes[] = {
137       EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,     EGL_BIND_TO_TEXTURE_RGB,
138       EGL_TRUE,         EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR,
139       EGL_NONE};
140   EGLConfig config;
141   RETURN_IF_ERROR(GetConfig(display, attributes, &config));
142   return CreateContext(display, shared_context, config, egl_context);
143 }
144 
145 }  // namespace gl
146 }  // namespace gpu
147 }  // namespace tflite
148