• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include "EglContext.h"
17 #include "EglDisplay.h"
18 #include "EglGlobalInfo.h"
19 #include "EglOsApi.h"
20 #include "EglPbufferSurface.h"
21 #include "ThreadInfo.h"
22 
23 #include <GLcommon/GLEScontext.h>
24 
25 unsigned int EglContext::s_nextContextHndl = 0;
26 
27 extern EglGlobalInfo* g_eglInfo; // defined in EglImp.cpp
28 
usingSurface(SurfacePtr surface)29 bool EglContext::usingSurface(SurfacePtr surface) {
30   return surface.get() == m_read.get() || surface.get() == m_draw.get();
31 }
32 
EglContext(EglDisplay * dpy,uint64_t shareGroupId,EglConfig * config,GLEScontext * glesCtx,GLESVersion ver,EGLint profileMask,ObjectNameManager * mngr,android::base::Stream * stream)33 EglContext::EglContext(EglDisplay *dpy,
34                        uint64_t shareGroupId,
35                        EglConfig* config,
36                        GLEScontext* glesCtx,
37                        GLESVersion ver,
38                        EGLint profileMask,
39                        ObjectNameManager* mngr,
40                        android::base::Stream* stream) :
41         m_dpy(dpy),
42         m_config(config),
43         m_glesContext(glesCtx),
44         m_version(ver),
45         m_mngr(mngr),
46         // If we already have set core profile flag
47         // (through the first context creation in Framebuffer initialization
48         // or what have you),
49         // set all follow contexts to use core as well.
50         // Otherwise, we can end up testing unreliable driver paths where
51         // core and non-core contexts need to interact with each other.
52         m_profileMask(isCoreProfile() ?
53                       (profileMask | EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR) :
54                       profileMask)
55 {
56     // Set the GLES-side core profile flag,
57     // and the global EGL flag.
58     bool usingCoreProfile =
59         m_profileMask & EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
60     setCoreProfile(usingCoreProfile);
61     glesCtx->setCoreProfile(usingCoreProfile);
62 
63     if (stream) {
64         EGLint configId = EGLint(stream->getBe32());
65         m_config = dpy->getConfig(configId);
66         if (!m_config) {
67             m_config = dpy->getDefaultConfig();
68         }
69         assert(m_config);
70         shareGroupId = static_cast<uint64_t>(stream->getBe64());
71     }
72 
73     EglOS::Context* globalSharedContext = dpy->getGlobalSharedContext();
74     m_native =
75         dpy->nativeType()->createContext(
76             m_profileMask,
77             m_config->nativeFormat(),
78             globalSharedContext);
79 
80     if (m_native) {
81         // When loading from a snapshot, the first context within a share group
82         // will load share group data.
83         m_shareGroup = mngr->attachOrCreateShareGroup(
84                 m_native.get(), shareGroupId, stream,
85                 [glesCtx](NamedObjectType type,
86                           ObjectLocalName localName,
87                           android::base::Stream* stream) {
88                     return glesCtx->loadObject(type, localName, stream);
89                 });
90         if (stream) {
91             glesCtx->setShareGroup(m_shareGroup);
92             glesCtx->postLoad();
93         }
94         m_hndl = ++s_nextContextHndl;
95     } else {
96         m_hndl = 0;
97     }
98 }
99 
~EglContext()100 EglContext::~EglContext()
101 {
102     ThreadInfo* thread = getThreadInfo();
103     // get the current context
104     ContextPtr currentCtx = thread->eglContext;
105     if (currentCtx && !m_dpy->getContext((EGLContext)SafePointerFromUInt(
106                         currentCtx->getHndl()))) {
107         currentCtx.reset();
108     }
109     SurfacePtr currentRead = currentCtx ? currentCtx->read() : nullptr;
110     SurfacePtr currentDraw = currentCtx ? currentCtx->draw() : nullptr;
111     // we need to make the context current before releasing GL resources.
112     // create a dummy surface first
113     EglPbufferSurface pbSurface(m_dpy, m_config);
114     pbSurface.setAttrib(EGL_WIDTH, 1);
115     pbSurface.setAttrib(EGL_HEIGHT, 1);
116     EglOS::PbufferInfo pbInfo;
117     pbSurface.getDim(&pbInfo.width, &pbInfo.height, &pbInfo.largest);
118     pbSurface.getTexInfo(&pbInfo.target, &pbInfo.format);
119     pbInfo.hasMipmap = false;
120     EglOS::Surface* pb = m_dpy->nativeType()->createPbufferSurface(
121             m_config->nativeFormat(), &pbInfo);
122     assert(pb);
123     if (pb) {
124         const bool res = m_dpy->nativeType()->makeCurrent(pb, pb, m_native.get());
125         assert(res);
126         (void)res;
127         pbSurface.setNativePbuffer(pb);
128     }
129     //
130     // release GL resources. m_shareGroup, m_mngr and m_glesContext hold
131     // smart pointers to share groups. We must clean them up when the context
132     // is current.
133     //
134     g_eglInfo->getIface(version())->setShareGroup(m_glesContext, {});
135     if (m_mngr) {
136         m_mngr->deleteShareGroup(m_native.get());
137     }
138     m_shareGroup.reset();
139 
140     //
141     // call the client-api to remove the GLES context
142     //
143     g_eglInfo->getIface(version())->deleteGLESContext(m_glesContext);
144     //
145     // restore the current context
146     //
147     if (currentCtx) {
148         m_dpy->nativeType()->makeCurrent(currentRead->native(),
149                                          currentDraw->native(),
150                                          currentCtx->nativeType());
151     } else {
152         m_dpy->nativeType()->makeCurrent(nullptr, nullptr, nullptr);
153     }
154 }
155 
setSurfaces(SurfacePtr read,SurfacePtr draw)156 void EglContext::setSurfaces(SurfacePtr read,SurfacePtr draw)
157 {
158     m_read = read;
159     m_draw = draw;
160 }
161 
getAttrib(EGLint attrib,EGLint * value)162 bool EglContext::getAttrib(EGLint attrib,EGLint* value) {
163     switch(attrib) {
164     case EGL_CONFIG_ID:
165         *value = m_config->id();
166         break;
167     default:
168         return false;
169     }
170     return true;
171 }
172 
onSave(android::base::Stream * stream)173 void EglContext::onSave(android::base::Stream* stream) {
174     // Save gles context first
175     assert(m_glesContext);
176     m_glesContext->onSave(stream);
177     // We save the information that
178     // is needed to restore the contexts.
179     // That means (1) context configurations (2) shared group IDs.
180 
181     // Save the config.
182     // The current implementation is pretty hacky. It stores the config id.
183     // It almost only works when snapshot saving and loading happens on the
184     // same system with the same GPU driver and hardware.
185     // TODO: make it more general
186     stream->putBe32(getConfig()->id());
187     // Save shared group ID
188     stream->putBe64(m_shareGroup->getId());
189     m_shareGroup->onSave(stream);
190 }
191 
postSave(android::base::Stream * stream)192 void EglContext::postSave(android::base::Stream* stream) {
193     m_glesContext->postSave(stream);
194     m_shareGroup->postSave(stream);
195 }
196