• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2022 The Android Open Source Project
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 #include "DisplaySurfaceGl.h"
16 
17 #include "OpenGLESDispatch/DispatchTables.h"
18 #include "OpenGLESDispatch/EGLDispatch.h"
19 #include "host-common/GfxstreamFatalError.h"
20 #include "host-common/logging.h"
21 
22 namespace gfxstream {
23 namespace gl {
24 namespace {
25 
26 using emugl::ABORT_REASON_OTHER;
27 using emugl::FatalError;
28 
29 class DisplaySurfaceGlContextHelper : public ContextHelper {
30   public:
DisplaySurfaceGlContextHelper(EGLDisplay display,EGLSurface surface,EGLContext context)31     DisplaySurfaceGlContextHelper(EGLDisplay display,
32                                   EGLSurface surface,
33                                   EGLContext context)
34         : mDisplay(display),
35           mSurface(surface),
36           mContext(context) {
37         if (mDisplay == EGL_NO_DISPLAY) {
38             GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
39                 << "DisplaySurfaceGlContextHelper created with no display?";
40         }
41         if (mSurface == EGL_NO_SURFACE) {
42             GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
43                 << "DisplaySurfaceGlContextHelper created with no surface?";
44         }
45         if (mContext == EGL_NO_CONTEXT) {
46             GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
47                 << "DisplaySurfaceGlContextHelper created with no context?";
48         }
49     }
50 
setupContext()51     bool setupContext() override {
52         EGLContext currentContext = s_egl.eglGetCurrentContext();
53         EGLSurface currentDrawSurface = s_egl.eglGetCurrentSurface(EGL_DRAW);
54         EGLSurface currentReadSurface = s_egl.eglGetCurrentSurface(EGL_READ);
55 
56         if (currentContext != mContext ||
57             currentDrawSurface != mSurface ||
58             currentReadSurface != mSurface) {
59             if (!s_egl.eglMakeCurrent(mDisplay, mSurface, mSurface, mContext)) {
60                 ERR("Failed to make display surface context current: %d", s_egl.eglGetError());
61                 return false;
62             }
63         }
64 
65         mPreviousContext = currentContext;
66         mPreviousDrawSurface = currentDrawSurface;
67         mPreviousReadSurface = currentReadSurface;
68 
69         mIsBound = true;
70 
71         return mIsBound;
72     }
73 
teardownContext()74     void teardownContext() override {
75         EGLContext currentContext = s_egl.eglGetCurrentContext();
76         EGLSurface currentDrawSurface = s_egl.eglGetCurrentSurface(EGL_DRAW);
77         EGLSurface currentReadSurface = s_egl.eglGetCurrentSurface(EGL_READ);
78 
79         if (currentContext != mPreviousContext ||
80             currentDrawSurface != mPreviousDrawSurface ||
81             currentReadSurface != mPreviousReadSurface) {
82             if (!s_egl.eglMakeCurrent(mDisplay,
83                                       mPreviousDrawSurface,
84                                       mPreviousReadSurface,
85                                       mPreviousContext)) {
86                 ERR("Failed to make restore previous context: %d", s_egl.eglGetError());
87                 return;
88             }
89         }
90 
91         mPreviousContext = EGL_NO_CONTEXT;
92         mPreviousDrawSurface = EGL_NO_SURFACE;
93         mPreviousReadSurface = EGL_NO_SURFACE;
94         mIsBound = false;
95     }
96 
isBound() const97     bool isBound() const override { return mIsBound; }
98 
99   private:
100     EGLDisplay mDisplay = EGL_NO_DISPLAY;
101     EGLSurface mSurface = EGL_NO_SURFACE;
102     EGLContext mContext = EGL_NO_CONTEXT;
103 
104     EGLContext mPreviousContext = EGL_NO_CONTEXT;
105     EGLSurface mPreviousReadSurface = EGL_NO_SURFACE;
106     EGLSurface mPreviousDrawSurface = EGL_NO_SURFACE;
107 
108     bool mIsBound = false;
109 };
110 
111 }  // namespace
112 
113 /*static*/
createPbufferSurface(EGLDisplay display,EGLConfig config,EGLContext shareContext,const EGLint * contextAttribs,EGLint width,EGLint height)114 std::unique_ptr<DisplaySurfaceGl> DisplaySurfaceGl::createPbufferSurface(
115         EGLDisplay display,
116         EGLConfig config,
117         EGLContext shareContext,
118         const EGLint* contextAttribs,
119         EGLint width,
120         EGLint height) {
121     EGLContext context = s_egl.eglCreateContext(display, config, shareContext, contextAttribs);
122     if (context == EGL_NO_CONTEXT) {
123         ERR("Failed to create context for DisplaySurfaceGl.");
124         return nullptr;
125     }
126 
127     const EGLint surfaceAttribs[] = {
128         EGL_WIDTH, width,   //
129         EGL_HEIGHT, height, //
130         EGL_NONE,           //
131     };
132     EGLSurface surface = s_egl.eglCreatePbufferSurface(display, config, surfaceAttribs);
133     if (surface == EGL_NO_SURFACE) {
134         ERR("Failed to create pbuffer surface for DisplaySurfaceGl.");
135         return nullptr;
136     }
137 
138     return std::unique_ptr<DisplaySurfaceGl>(new DisplaySurfaceGl(display, surface, context));
139 }
140 
141 /*static*/
createWindowSurface(EGLDisplay display,EGLConfig config,EGLContext shareContext,const GLint * contextAttribs,FBNativeWindowType window)142 std::unique_ptr<DisplaySurfaceGl> DisplaySurfaceGl::createWindowSurface(
143         EGLDisplay display,
144         EGLConfig config,
145         EGLContext shareContext,
146         const GLint* contextAttribs,
147         FBNativeWindowType window) {
148     EGLContext context = s_egl.eglCreateContext(display, config, shareContext, contextAttribs);
149     if (context == EGL_NO_CONTEXT) {
150         ERR("Failed to create context for DisplaySurfaceGl.");
151         return nullptr;
152     }
153 
154     EGLSurface surface = s_egl.eglCreateWindowSurface(display, config, window, nullptr);
155     if (surface == EGL_NO_SURFACE) {
156         ERR("Failed to create window surface for DisplaySurfaceGl.");
157         return nullptr;
158     }
159 
160     return std::unique_ptr<DisplaySurfaceGl>(new DisplaySurfaceGl(display, surface, context));
161 }
162 
DisplaySurfaceGl(EGLDisplay display,EGLSurface surface,EGLContext context)163 DisplaySurfaceGl::DisplaySurfaceGl(EGLDisplay display,
164                                    EGLSurface surface,
165                                    EGLContext context)
166     : mDisplay(display),
167       mSurface(surface),
168       mContext(context),
169       mContextHelper(new DisplaySurfaceGlContextHelper(display, surface, context)) {}
170 
~DisplaySurfaceGl()171 DisplaySurfaceGl::~DisplaySurfaceGl() {
172     if (mDisplay != EGL_NO_DISPLAY) {
173         if (mSurface) {
174             s_egl.eglDestroySurface(mDisplay, mSurface);
175         }
176         if (mContext) {
177             s_egl.eglDestroyContext(mDisplay, mContext);
178         }
179     }
180 }
181 
182 }  // namespace gl
183 }  // namespace gfxstream