• 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 "EglDisplay.h"
17 
18 #include "aemu/base/containers/Lookup.h"
19 #include "aemu/base/files/StreamSerializing.h"
20 #include "EglConfig.h"
21 #include "EglGlobalInfo.h"
22 #include "EglOsApi.h"
23 #include <GLcommon/GLutils.h>
24 
25 #include <algorithm>
26 
EglDisplay(EGLNativeDisplayType dpy,EglOS::Display * idpy)27 EglDisplay::EglDisplay(EGLNativeDisplayType dpy,
28                        EglOS::Display* idpy) :
29     m_dpy(dpy),
30     m_idpy(idpy)
31 {
32     m_manager[GLES_1_1] = new ObjectNameManager(&m_globalNameSpace);
33     m_manager[GLES_2_0] = new ObjectNameManager(&m_globalNameSpace);
34     m_manager[GLES_3_0] = m_manager[GLES_2_0];
35     m_manager[GLES_3_1] = m_manager[GLES_2_0];
36 };
37 
~EglDisplay()38 EglDisplay::~EglDisplay() {
39     android::base::AutoLock mutex(m_lock);
40 
41     m_configs.clear();
42 
43     delete m_manager[GLES_1_1];
44     delete m_manager[GLES_2_0];
45 
46     delete m_idpy;
47 }
48 
initialize(int renderableType)49 void EglDisplay::initialize(int renderableType) {
50     android::base::AutoLock mutex(m_lock);
51     m_initialized = true;
52     initConfigurations(renderableType);
53     m_configInitialized = true;
54 }
55 
isInitialize()56 bool EglDisplay::isInitialize() {
57     android::base::AutoLock mutex(m_lock);
58     return m_initialized;
59 }
60 
terminate()61 void EglDisplay::terminate(){
62     android::base::AutoLock mutex(m_lock);
63     m_contexts.clear();
64     m_surfaces.clear();
65     m_initialized = false;
66 }
67 
68 namespace CompareEglConfigs {
69 
70 // Old compare function used to initialize to something decently sorted.
71 struct StaticCompare {
operator ()CompareEglConfigs::StaticCompare72     bool operator()(const std::unique_ptr<EglConfig>& first,
73                     const std::unique_ptr<EglConfig>& second) const {
74         return *first < *second;
75     }
76 };
77 
78 // In actual usage, we need to dynamically re-sort configs
79 // that are returned to the user.
80 struct DynamicCompare;
81 // This is because the sorting order of configs is affected
82 // based on dynamic properties.
83 //
84 // See https://www.khronos.org/registry/egl/sdk/docs/man/html/eglChooseConfig.xhtml
85 // and the section on config sorting.
86 //
87 // If the user requests an EGL config with a particular EGL_RED_SIZE,
88 // for example, we must sort configs based on that criteria, while if that
89 // was not specified, we would just skip right on to sorting by buffer size.
90 // Below is an implementation of EGL config sorting according
91 // to spec, that takes the dynamic properties into account.
ColorBufferTypeVal(EGLenum type)92 static int ColorBufferTypeVal(EGLenum type) {
93     switch (type) {
94     case EGL_RGB_BUFFER: return 0;
95     case EGL_LUMINANCE_BUFFER: return 1;
96     case EGL_YUV_BUFFER_EXT: return 2;
97     }
98     return 3;
99 }
100 
nonTrivialAttribVal(EGLint val)101 static bool nonTrivialAttribVal(EGLint val) {
102     return val != 0 && val != EGL_DONT_CARE;
103 }
104 
105 struct DynamicCompare {
106 public:
DynamicCompareCompareEglConfigs::DynamicCompare107     DynamicCompare(const EglConfig& wantedAttribs) {
108 
109         EGLint wantedRVal = wantedAttribs.getConfAttrib(EGL_RED_SIZE);
110         EGLint wantedGVal = wantedAttribs.getConfAttrib(EGL_GREEN_SIZE);
111         EGLint wantedBVal = wantedAttribs.getConfAttrib(EGL_BLUE_SIZE);
112         EGLint wantedLVal = wantedAttribs.getConfAttrib(EGL_LUMINANCE_SIZE);
113         EGLint wantedAVal = wantedAttribs.getConfAttrib(EGL_ALPHA_SIZE);
114 
115         wantedR = wantedAttribs.isWantedAttrib(EGL_RED_SIZE) && nonTrivialAttribVal(wantedRVal);
116         wantedG = wantedAttribs.isWantedAttrib(EGL_GREEN_SIZE) && nonTrivialAttribVal(wantedGVal);
117         wantedB = wantedAttribs.isWantedAttrib(EGL_BLUE_SIZE) && nonTrivialAttribVal(wantedBVal);
118         wantedL = wantedAttribs.isWantedAttrib(EGL_LUMINANCE_SIZE) && nonTrivialAttribVal(wantedLVal);
119         wantedA = wantedAttribs.isWantedAttrib(EGL_ALPHA_SIZE) && nonTrivialAttribVal(wantedAVal);
120     }
121 
operator ()CompareEglConfigs::DynamicCompare122     bool operator()(EglConfig* a, EglConfig* b) const {
123         EGLint aConformant = a->getConfAttrib(EGL_CONFORMANT);
124         EGLint bConformant = b->getConfAttrib(EGL_CONFORMANT);
125 
126         if (aConformant != bConformant) {
127             return aConformant != 0;
128         }
129 
130         EGLint aCaveat = a->getConfAttrib(EGL_CONFIG_CAVEAT);
131         EGLint bCaveat = b->getConfAttrib(EGL_CONFIG_CAVEAT);
132         if (aCaveat != bCaveat) {
133             return aCaveat < bCaveat;
134         }
135 
136         EGLint aCbType = a->getConfAttrib(EGL_COLOR_BUFFER_TYPE);
137         EGLint bCbType = b->getConfAttrib(EGL_COLOR_BUFFER_TYPE);
138         if (aCbType != bCbType) {
139             return ColorBufferTypeVal(aCbType) <
140                    ColorBufferTypeVal(bCbType);
141         }
142 
143         EGLint aCbSize = 0;
144         EGLint bCbSize = 0;
145 
146         if (wantedR) {
147             aCbSize += a->getConfAttrib(EGL_RED_SIZE);
148             bCbSize += b->getConfAttrib(EGL_RED_SIZE);
149         }
150         if (wantedG) {
151             aCbSize += a->getConfAttrib(EGL_GREEN_SIZE);
152             bCbSize += b->getConfAttrib(EGL_GREEN_SIZE);
153         }
154         if (wantedB) {
155             aCbSize += a->getConfAttrib(EGL_BLUE_SIZE);
156             bCbSize += b->getConfAttrib(EGL_BLUE_SIZE);
157         }
158         if (wantedL) {
159             aCbSize += a->getConfAttrib(EGL_LUMINANCE_SIZE);
160             bCbSize += b->getConfAttrib(EGL_LUMINANCE_SIZE);
161         }
162         if (wantedA) {
163             aCbSize += a->getConfAttrib(EGL_ALPHA_SIZE);
164             bCbSize += b->getConfAttrib(EGL_ALPHA_SIZE);
165         }
166 
167         if (aCbSize != bCbSize) {
168             return aCbSize > bCbSize;
169         }
170 
171         EGLint aBufferSize = a->getConfAttrib(EGL_BUFFER_SIZE);
172         EGLint bBufferSize = b->getConfAttrib(EGL_BUFFER_SIZE);
173         if (aBufferSize != bBufferSize) {
174             return aBufferSize < bBufferSize;
175         }
176 
177         EGLint aSampleBuffersNum = a->getConfAttrib(EGL_SAMPLE_BUFFERS);
178         EGLint bSampleBuffersNum = b->getConfAttrib(EGL_SAMPLE_BUFFERS);
179         if (aSampleBuffersNum != bSampleBuffersNum) {
180             return aSampleBuffersNum < bSampleBuffersNum;
181         }
182 
183         EGLint aSPP = a->getConfAttrib(EGL_SAMPLES);
184         EGLint bSPP = b->getConfAttrib(EGL_SAMPLES);
185         if (aSPP != bSPP) {
186             return aSPP < bSPP;
187         }
188 
189         EGLint aDepthSize = a->getConfAttrib(EGL_DEPTH_SIZE);
190         EGLint bDepthSize = b->getConfAttrib(EGL_DEPTH_SIZE);
191         if (aDepthSize != bDepthSize) {
192             return aDepthSize < bDepthSize;
193         }
194 
195         EGLint aStencilSize = a->getConfAttrib(EGL_STENCIL_SIZE);
196         EGLint bStencilSize = b->getConfAttrib(EGL_STENCIL_SIZE);
197         if (aStencilSize != bStencilSize) {
198             return aStencilSize < bStencilSize;
199         }
200 
201         return a->getConfAttrib(EGL_CONFIG_ID) < b->getConfAttrib(EGL_CONFIG_ID);
202     }
203 
204     bool wantedR;
205     bool wantedG;
206     bool wantedB;
207     bool wantedL;
208     bool wantedA;
209 };
210 
211 }
212 
addSimplePixelFormat(int red_size,int green_size,int blue_size,int alpha_size,int sample_per_pixel)213 EglConfig* EglDisplay::addSimplePixelFormat(int red_size,
214                                       int green_size,
215                                       int blue_size,
216                                       int alpha_size,
217                                       int sample_per_pixel) {
218     std::sort(m_configs.begin(), m_configs.end(), CompareEglConfigs::StaticCompare());
219 
220     EGLConfig match;
221 
222     EglConfig dummy(red_size,
223                     green_size,
224                     blue_size,
225                     alpha_size,  // RGB_565
226                     EGL_DONT_CARE,
227                     16, // Depth
228                     EGL_DONT_CARE,
229                     EGL_DONT_CARE,
230                     EGL_DONT_CARE,
231                     EGL_DONT_CARE,
232                     EGL_DONT_CARE,
233                     EGL_DONT_CARE,
234                     EGL_DONT_CARE,
235                     EGL_DONT_CARE,
236                     sample_per_pixel,
237                     EGL_DONT_CARE,
238                     EGL_DONT_CARE,
239                     EGL_DONT_CARE,
240                     EGL_DONT_CARE,
241                     EGL_DONT_CARE,
242                     EGL_DONT_CARE,
243                     EGL_DONT_CARE,
244                     NULL);
245 
246     if(!doChooseConfigs(dummy, &match, 1))
247     {
248         return nullptr;
249     }
250 
251     EglConfig* config = (EglConfig*)match;
252 
253     int bSize;
254     config->getConfAttrib(EGL_BUFFER_SIZE,&bSize);
255 
256     if(bSize == 16)
257     {
258         return config;
259     }
260 
261     std::unique_ptr<EglConfig> newConfig(
262          new EglConfig(*config,
263                        red_size, green_size, blue_size,
264                        alpha_size));
265 
266     if (m_uniqueConfigs.insert(*newConfig).second) {
267         config = newConfig.release();
268         m_configs.emplace_back(config);
269     }
270     return config;
271 }
272 
273 // BUG: 246999412
274 // We might want to deprecate this list.
275 static const EGLint kCommonCfgs[][5] = {
276     {8, 8, 8, 0, EGL_DONT_CARE},
277     {8, 8, 8, 8, EGL_DONT_CARE},
278     // 565 fails with ANGLE on Mac
279     // {5, 6, 5, 0, EGL_DONT_CARE},
280     // The following are multi-sample configs. They have issues with CTS test:
281     // (API26) run cts -m CtsOpenGLTestCases -t
282     // android.opengl.cts.EglConfigTest#testEglConfigs
283     // We disable them until we figure out how to fix that test properly
284     // BUG: 69421199
285     // {5, 6, 5, 0, 2},
286     // {8, 8, 8, 0, 2},
287     // {8, 8, 8, 8, 2},
288     // {5, 6, 5, 0, 4},
289     // {8, 8, 8, 0, 4},
290     // {8, 8, 8, 8, 4},
291 };
292 
293 static constexpr int kReservedIdNum = sizeof(kCommonCfgs) / 5 / sizeof(EGLint);
294 
addReservedConfigs()295 void EglDisplay::addReservedConfigs() {
296     for (int i = 0; i < kReservedIdNum; i++) {
297         EglConfig* cfg = nullptr;
298         cfg = addSimplePixelFormat(kCommonCfgs[i][0],
299                 kCommonCfgs[i][1],
300                 kCommonCfgs[i][2],
301                 kCommonCfgs[i][3],
302                 kCommonCfgs[i][4]);
303         if (!cfg) { // if multi-sample fails, fall back to the basic ones
304             int fallbackCfg = 2;
305             do {
306                 cfg = addSimplePixelFormat(kCommonCfgs[fallbackCfg][0],
307                         kCommonCfgs[fallbackCfg][1],
308                         kCommonCfgs[fallbackCfg][2],
309                         kCommonCfgs[fallbackCfg][3],
310                         kCommonCfgs[fallbackCfg][4]);
311                 fallbackCfg --;
312             } while (!cfg && fallbackCfg >= 0);
313             if (cfg) {
314                 // Clone the basic cfg, and give it a different ID later
315                 cfg = new EglConfig(*cfg);
316                 m_configs.emplace_back(cfg);
317             }
318         }
319         // ID starts with 1
320         if (cfg) {
321             cfg->setId(i + 1);
322         }
323     }
324 }
325 
initConfigurations(int renderableType)326 void EglDisplay::initConfigurations(int renderableType) {
327     if (m_configInitialized) {
328         return;
329     }
330     m_idpy->queryConfigs(renderableType, addConfig, this);
331 
332     for (size_t i = 0; i < m_configs.size(); i++) {
333         // ID starts with 1
334         m_configs[i]->setId(static_cast<EGLint>(i + 1 + kReservedIdNum));
335     }
336     addReservedConfigs();
337     // It is ok if config id is not continual.
338     std::sort(m_configs.begin(), m_configs.end(), CompareEglConfigs::StaticCompare());
339 
340 #if EMUGL_DEBUG
341     for (ConfigsList::const_iterator it = m_configs.begin();
342          it != m_configs.end();
343          ++it) {
344         EglConfig* config = it->get();
345         EGLint red, green, blue, alpha, depth, stencil, renderable, surface;
346         config->getConfAttrib(EGL_RED_SIZE, &red);
347         config->getConfAttrib(EGL_GREEN_SIZE, &green);
348         config->getConfAttrib(EGL_BLUE_SIZE, &blue);
349         config->getConfAttrib(EGL_ALPHA_SIZE, &alpha);
350         config->getConfAttrib(EGL_DEPTH_SIZE, &depth);
351         config->getConfAttrib(EGL_STENCIL_SIZE, &stencil);
352         config->getConfAttrib(EGL_RENDERABLE_TYPE, &renderable);
353         config->getConfAttrib(EGL_SURFACE_TYPE, &surface);
354     }
355 #endif  // EMUGL_DEBUG
356 }
357 
getConfig(EGLConfig conf) const358 EglConfig* EglDisplay::getConfig(EGLConfig conf) const {
359     android::base::AutoLock mutex(m_lock);
360 
361     for(ConfigsList::const_iterator it = m_configs.begin();
362         it != m_configs.end();
363         ++it) {
364         if(static_cast<EGLConfig>(it->get()) == conf) {
365             return it->get();
366         }
367     }
368     return NULL;
369 }
370 
getSurface(EGLSurface surface) const371 SurfacePtr EglDisplay::getSurface(EGLSurface surface) const {
372     android::base::AutoLock mutex(m_lock);
373     /* surface is "key" in map<unsigned int, SurfacePtr>. */
374     unsigned int hndl = SafeUIntFromPointer(surface);
375     SurfacesHndlMap::const_iterator it = m_surfaces.find(hndl);
376     return it != m_surfaces.end() ?
377                                   (*it).second :
378                                    SurfacePtr();
379 }
380 
getContext(EGLContext ctx) const381 ContextPtr EglDisplay::getContext(EGLContext ctx) const {
382     android::base::AutoLock mutex(m_lock);
383     /* ctx is "key" in map<unsigned int, ContextPtr>. */
384     unsigned int hndl = SafeUIntFromPointer(ctx);
385     ContextsHndlMap::const_iterator it = m_contexts.find(hndl);
386     return it != m_contexts.end() ?
387                                   (*it).second :
388                                    ContextPtr();
389 }
390 
getLowLevelContext(EGLContext ctx) const391 void* EglDisplay::getLowLevelContext(EGLContext ctx) const {
392     auto lctx = getContext(ctx);
393     if (lctx) {
394         return lctx->nativeType()->lowLevelContext();
395     }
396     return nullptr;
397 }
398 
removeSurface(EGLSurface s)399 bool EglDisplay::removeSurface(EGLSurface s) {
400     android::base::AutoLock mutex(m_lock);
401     /* s is "key" in map<unsigned int, SurfacePtr>. */
402     unsigned int hndl = SafeUIntFromPointer(s);
403     SurfacesHndlMap::iterator it = m_surfaces.find(hndl);
404     if(it != m_surfaces.end()) {
405         m_surfaces.erase(it);
406         return true;
407     }
408     return false;
409 }
410 
removeContext(EGLContext ctx)411 bool EglDisplay::removeContext(EGLContext ctx) {
412     android::base::AutoLock mutex(m_lock);
413     /* ctx is "key" in map<unsigned int, ContextPtr>. */
414     unsigned int hndl = SafeUIntFromPointer(ctx);
415     ContextsHndlMap::iterator it = m_contexts.find(hndl);
416     if(it != m_contexts.end()) {
417         m_contexts.erase(it);
418         return true;
419     }
420     return false;
421 }
422 
removeContext(ContextPtr ctx)423 bool EglDisplay::removeContext(ContextPtr ctx) {
424     android::base::AutoLock mutex(m_lock);
425 
426     ContextsHndlMap::iterator it;
427     for(it = m_contexts.begin(); it != m_contexts.end();++it) {
428         if((*it).second.get() == ctx.get()){
429             break;
430         }
431     }
432     if(it != m_contexts.end()) {
433         m_contexts.erase(it);
434         return true;
435     }
436     return false;
437 }
438 
getConfig(EGLint id) const439 EglConfig* EglDisplay::getConfig(EGLint id) const {
440     android::base::AutoLock mutex(m_lock);
441 
442     for(ConfigsList::const_iterator it = m_configs.begin();
443         it != m_configs.end();
444         ++it) {
445         if((*it)->id() == id) {
446             return it->get();
447         }
448     }
449     return NULL;
450 }
451 
getDefaultConfig() const452 EglConfig* EglDisplay::getDefaultConfig() const {
453     return getConfig(2); // rgba8888
454 }
455 
getConfigs(EGLConfig * configs,int config_size) const456 int EglDisplay::getConfigs(EGLConfig* configs,int config_size) const {
457     android::base::AutoLock mutex(m_lock);
458     int i = 0;
459     for(ConfigsList::const_iterator it = m_configs.begin();
460         it != m_configs.end() && i < config_size;
461         i++, ++it) {
462         configs[i] = static_cast<EGLConfig>(it->get());
463     }
464     return i;
465 }
466 
chooseConfigs(const EglConfig & dummy,EGLConfig * configs,int config_size) const467 int EglDisplay::chooseConfigs(const EglConfig& dummy,
468                               EGLConfig* configs,
469                               int config_size) const {
470     android::base::AutoLock mutex(m_lock);
471     return doChooseConfigs(dummy, configs, config_size);
472 }
473 
doChooseConfigs(const EglConfig & dummy,EGLConfig * configs,int config_size) const474 int EglDisplay::doChooseConfigs(const EglConfig& dummy,
475                                 EGLConfig* configs,
476                                 int config_size) const {
477     int added = 0;
478 
479     std::vector<EglConfig*> validConfigs;
480 
481     CHOOSE_CONFIG_DLOG("returning configs. ids: {");
482     for(ConfigsList::const_iterator it = m_configs.begin();
483         it != m_configs.end() && (added < config_size || !configs);
484         ++it) {
485         if( (*it)->chosen(dummy)){
486             if(configs) {
487                 CHOOSE_CONFIG_DLOG("valid config: id=0x%x", it->get()->id());
488                 validConfigs.push_back(it->get());
489             }
490             added++;
491        }
492     }
493 
494     CHOOSE_CONFIG_DLOG("sorting valid configs...");
495 
496     std::sort(validConfigs.begin(),
497               validConfigs.end(),
498               CompareEglConfigs::DynamicCompare(dummy));
499 
500     for (int i = 0; configs && i < added; i++) {
501         configs[i] = static_cast<EGLConfig>(validConfigs[i]);
502     }
503 
504     CHOOSE_CONFIG_DLOG("returning configs. ids end }");
505     return added;
506 }
507 
addSurface(SurfacePtr s)508 EGLSurface EglDisplay::addSurface(SurfacePtr s ) {
509     android::base::AutoLock mutex(m_lock);
510    unsigned int hndl = s.get()->getHndl();
511    EGLSurface ret =reinterpret_cast<EGLSurface> (hndl);
512 
513    if(m_surfaces.find(hndl) != m_surfaces.end()) {
514        return ret;
515    }
516 
517    m_surfaces[hndl] = s;
518    return ret;
519 }
520 
addContext(ContextPtr ctx)521 EGLContext EglDisplay::addContext(ContextPtr ctx ) {
522     android::base::AutoLock mutex(m_lock);
523 
524    unsigned int hndl = ctx.get()->getHndl();
525    EGLContext ret    = reinterpret_cast<EGLContext> (hndl);
526 
527    if(m_contexts.find(hndl) != m_contexts.end()) {
528        return ret;
529    }
530    m_contexts[hndl] = ctx;
531    return ret;
532 }
533 
534 
addImageKHR(ImagePtr img)535 EGLImageKHR EglDisplay::addImageKHR(ImagePtr img) {
536     android::base::AutoLock mutex(m_lock);
537     do {
538         ++m_nextEglImageId;
539     } while(m_nextEglImageId == 0
540             || android::base::contains(m_eglImages, m_nextEglImageId));
541     img->imageId = m_nextEglImageId;
542     m_eglImages[m_nextEglImageId] = img;
543     return reinterpret_cast<EGLImageKHR>(m_nextEglImageId);
544 }
545 
touchEglImage(EglImage * eglImage,SaveableTexture::restorer_t restorer)546 static void touchEglImage(EglImage* eglImage,
547         SaveableTexture::restorer_t restorer) {
548     if (eglImage->needRestore) {
549         if (eglImage->saveableTexture.get()) {
550             restorer(eglImage->saveableTexture.get());
551             eglImage->saveableTexture->fillEglImage(eglImage);
552         }
553         eglImage->needRestore = false;
554     }
555 }
556 
getImage(EGLImageKHR img,SaveableTexture::restorer_t restorer) const557 ImagePtr EglDisplay::getImage(EGLImageKHR img,
558         SaveableTexture::restorer_t restorer) const {
559     android::base::AutoLock mutex(m_lock);
560     /* img is "key" in map<unsigned int, ImagePtr>. */
561     unsigned int hndl = SafeUIntFromPointer(img);
562     ImagesHndlMap::const_iterator i( m_eglImages.find(hndl) );
563     if (i == m_eglImages.end()) {
564         return ImagePtr();
565     }
566     touchEglImage(i->second.get(), restorer);
567     return i->second;
568 }
569 
destroyImageKHR(EGLImageKHR img)570 bool EglDisplay:: destroyImageKHR(EGLImageKHR img) {
571     android::base::AutoLock mutex(m_lock);
572     /* img is "key" in map<unsigned int, ImagePtr>. */
573     unsigned int hndl = SafeUIntFromPointer(img);
574     ImagesHndlMap::iterator i( m_eglImages.find(hndl) );
575     if (i != m_eglImages.end())
576     {
577         m_eglImages.erase(i);
578         return true;
579     }
580     return false;
581 }
582 
getGlobalSharedContext() const583 EglOS::Context* EglDisplay::getGlobalSharedContext() const {
584     android::base::AutoLock mutex(m_lock);
585 #ifndef _WIN32
586     // find an existing OpenGL context to share with, if exist
587     EglOS::Context* ret =
588         (EglOS::Context*)m_manager[GLES_1_1]->getGlobalContext();
589     if (!ret)
590         ret = (EglOS::Context*)m_manager[GLES_2_0]->getGlobalContext();
591     return ret;
592 #else
593     if (!m_globalSharedContext) {
594         //
595         // On windows we create a dummy context to serve as the
596         // "global context" which all contexts share with.
597         // This is because on windows it is not possible to share
598         // with a context which is already current. This dummy context
599         // will never be current to any thread so it is safe to share with.
600         // Create that context using the first config
601         if (m_configs.empty()) {
602             // Should not happen! config list should be initialized at this point
603             return NULL;
604         }
605         EglConfig *cfg = m_configs.front().get();
606         m_globalSharedContext = m_idpy->createContext(
607                 isCoreProfile() ? EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR : 0,
608                 cfg->nativeFormat(), NULL);
609     }
610 
611     return m_globalSharedContext.get();
612 #endif
613 }
614 
615 // static
addConfig(void * opaque,const EglOS::ConfigInfo * info)616 void EglDisplay::addConfig(void* opaque, const EglOS::ConfigInfo* info) {
617     EglDisplay* display = static_cast<EglDisplay*>(opaque);
618 
619     // Greater than 24 bits of color,
620     // or having no depth/stencil causes some
621     // unexpected behavior in real usage, such
622     // as frame corruption and wrong drawing order.
623     // Also, disallow high MSAA.
624     // Just don't use those configs.
625     if (info->red_size > 8 ||
626         info->green_size > 8 ||
627         info->blue_size > 8 ||
628         info->depth_size < 24 ||
629         info->stencil_size < 8 ||
630         info->samples_per_pixel > 0) {
631         return;
632     }
633 
634     std::unique_ptr<EglConfig> config(new EglConfig(
635          info->red_size,
636          info->green_size,
637          info->blue_size,
638          info->alpha_size,
639          info->caveat,
640          info->depth_size,
641          info->frame_buffer_level,
642          info->max_pbuffer_width,
643          info->max_pbuffer_height,
644          info->max_pbuffer_size,
645          info->native_renderable,
646          info->renderable_type,
647          info->native_visual_id,
648          info->native_visual_type,
649          info->samples_per_pixel,
650          info->stencil_size,
651          info->surface_type,
652          info->transparent_type,
653          info->trans_red_val,
654          info->trans_green_val,
655          info->trans_blue_val,
656          info->recordable_android,
657          info->frmt));
658 
659     if (display->m_uniqueConfigs.insert(*config).second) {
660         display->m_configs.emplace_back(config.release());
661     }
662 }
663 
onSaveAllImages(android::base::Stream * stream,const android::snapshot::ITextureSaverPtr & textureSaver,SaveableTexture::saver_t saver,SaveableTexture::restorer_t restorer)664 void EglDisplay::onSaveAllImages(android::base::Stream* stream,
665                                  const android::snapshot::ITextureSaverPtr& textureSaver,
666                                  SaveableTexture::saver_t saver,
667                                  SaveableTexture::restorer_t restorer) {
668     // we could consider calling presave for all ShareGroups from here
669     // but it would introduce overheads because not all share groups need to be
670     // saved
671     android::base::AutoLock mutex(m_lock);
672     for (auto& image : m_eglImages) {
673         // In case we loaded textures from a previous snapshot and have not
674         // yet restore them to GPU, we do the restoration here.
675         // TODO: skip restoration and write saveableTexture directly to the
676         // new snapshot for better performance
677         touchEglImage(image.second.get(), restorer);
678         getGlobalNameSpace()->preSaveAddEglImage(image.second.get());
679     }
680     m_globalNameSpace.onSave(stream, textureSaver, saver);
681     saveCollection(stream, m_eglImages, [](
682             android::base::Stream* stream,
683             const ImagesHndlMap::value_type& img) {
684         stream->putBe32(img.first);
685         stream->putBe32(img.second->globalTexObj->getGlobalName());
686         // We do not need to save other fields in EglImage. We can load them
687         // from SaveableTexture.
688     });
689 }
690 
onLoadAllImages(android::base::Stream * stream,const android::snapshot::ITextureLoaderPtr & textureLoader,SaveableTexture::creator_t creator)691 void EglDisplay::onLoadAllImages(android::base::Stream* stream,
692                                  const android::snapshot::ITextureLoaderPtr& textureLoader,
693                                  SaveableTexture::creator_t creator) {
694     if (!m_eglImages.empty()) {
695         // Could be triggered by this bug:
696         // b/36654917
697         fprintf(stderr, "Warning: unreleased EGL image handles\n");
698     }
699     m_eglImages.clear();
700     android::base::AutoLock mutex(m_lock);
701     m_globalNameSpace.setIfaces(
702         EglGlobalInfo::getInstance()->getEglIface(),
703         EglGlobalInfo::getInstance()->getIface(GLES_2_0));
704     m_globalNameSpace.onLoad(stream, textureLoader, creator);
705 
706     loadCollection(stream, &m_eglImages, [this](
707         android::base::Stream* stream) {
708         unsigned int hndl = stream->getBe32();
709         unsigned int globalName = stream->getBe32();
710         ImagePtr eglImg(new EglImage);
711         eglImg->imageId = hndl;
712         eglImg->saveableTexture =
713                 m_globalNameSpace.getSaveableTextureFromLoad(globalName);
714         eglImg->needRestore = true;
715         return std::make_pair(hndl, std::move(eglImg));
716     });
717 }
718 
postLoadAllImages(android::base::Stream * stream)719 void EglDisplay::postLoadAllImages(android::base::Stream* stream) {
720     m_globalNameSpace.postLoad(stream);
721 }
722