02b6b78823b9fff07270f01cd13f81c75ee5d79b
[iec.git] / src / type3_AndroidCloud / anbox-master / src / anbox / graphics / emugl / RendererConfig.cpp
1 // Copyright (C) 2015 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 "anbox/graphics/emugl/RendererConfig.h"
16 #include "anbox/logger.h"
17
18 #include "external/android-emugl/host/include/OpenGLESDispatch/EGLDispatch.h"
19
20 #include <stdio.h>
21 #include <string.h>
22
23 namespace {
24 const GLuint kConfigAttributes[] = {
25     EGL_DEPTH_SIZE,       // must be first - see getDepthSize()
26     EGL_STENCIL_SIZE,     // must be second - see getStencilSize()
27     EGL_RENDERABLE_TYPE,  // must be third - see getRenderableType()
28     EGL_SURFACE_TYPE,     // must be fourth - see getSurfaceType()
29     EGL_CONFIG_ID,        // must be fifth  - see chooseConfig()
30     EGL_BUFFER_SIZE, EGL_ALPHA_SIZE, EGL_BLUE_SIZE, EGL_GREEN_SIZE,
31     EGL_RED_SIZE, EGL_CONFIG_CAVEAT, EGL_LEVEL, EGL_MAX_PBUFFER_HEIGHT,
32     EGL_MAX_PBUFFER_PIXELS, EGL_MAX_PBUFFER_WIDTH, EGL_NATIVE_RENDERABLE,
33     EGL_NATIVE_VISUAL_ID, EGL_NATIVE_VISUAL_TYPE, EGL_SAMPLES,
34     EGL_SAMPLE_BUFFERS, EGL_TRANSPARENT_TYPE, EGL_TRANSPARENT_BLUE_VALUE,
35     EGL_TRANSPARENT_GREEN_VALUE, EGL_TRANSPARENT_RED_VALUE,
36     EGL_BIND_TO_TEXTURE_RGB, EGL_BIND_TO_TEXTURE_RGBA, EGL_MIN_SWAP_INTERVAL,
37     EGL_MAX_SWAP_INTERVAL, EGL_LUMINANCE_SIZE, EGL_ALPHA_MASK_SIZE,
38     EGL_COLOR_BUFFER_TYPE,
39     // EGL_MATCH_NATIVE_PIXMAP,
40     EGL_CONFORMANT};
41
42 const size_t kConfigAttributesLen =
43     sizeof(kConfigAttributes) / sizeof(kConfigAttributes[0]);
44
45 bool isCompatibleHostConfig(EGLConfig config, EGLDisplay display) {
46   // Filter out configs which do not support pbuffers, since they
47   // are used to implement window surfaces.
48   EGLint surfaceType;
49   s_egl.eglGetConfigAttrib(display, config, EGL_SURFACE_TYPE, &surfaceType);
50   if (!(surfaceType & EGL_PBUFFER_BIT)) {
51     return false;
52   }
53
54   // Filter out configs that do not support RGB pixel values.
55   EGLint redSize = 0, greenSize = 0, blueSize = 0;
56   s_egl.eglGetConfigAttrib(display, config, EGL_RED_SIZE, &redSize);
57   s_egl.eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &greenSize);
58   s_egl.eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &blueSize);
59
60   if (!redSize || !greenSize || !blueSize) {
61     return false;
62   }
63
64   return true;
65 }
66 }  // namespace
67
68 RendererConfig::~RendererConfig() { delete[] mAttribValues; }
69
70 RendererConfig::RendererConfig(EGLConfig hostConfig, EGLDisplay hostDisplay)
71     : mEglConfig(hostConfig), mAttribValues(NULL) {
72   mAttribValues = new GLint[kConfigAttributesLen];
73   for (size_t i = 0; i < kConfigAttributesLen; ++i) {
74     mAttribValues[i] = 0;
75     s_egl.eglGetConfigAttrib(hostDisplay, hostConfig, kConfigAttributes[i],
76                              &mAttribValues[i]);
77
78     // This implementation supports guest window surfaces by wrapping
79     // them around host Pbuffers, so always report it to the guest.
80     if (kConfigAttributes[i] == EGL_SURFACE_TYPE) {
81       mAttribValues[i] |= EGL_WINDOW_BIT;
82     }
83   }
84 }
85
86 RendererConfigList::RendererConfigList(EGLDisplay display)
87     : mCount(0), mConfigs(NULL), mDisplay(display) {
88   if (display == EGL_NO_DISPLAY) {
89     ERROR("Invalid display value %p (EGL_NO_DISPLAY)", reinterpret_cast<void*>(display));
90     return;
91   }
92
93   EGLint numHostConfigs = 0;
94   if (!s_egl.eglGetConfigs(display, NULL, 0, &numHostConfigs)) {
95     ERROR("Could not get number of host EGL config");
96     return;
97   }
98   EGLConfig* hostConfigs = new EGLConfig[numHostConfigs];
99   s_egl.eglGetConfigs(display, hostConfigs, numHostConfigs, &numHostConfigs);
100
101   mConfigs = new RendererConfig*[numHostConfigs];
102   for (EGLint i = 0; i < numHostConfigs; ++i) {
103     // Filter out configs that are not compatible with our implementation.
104     if (!isCompatibleHostConfig(hostConfigs[i], display)) {
105       continue;
106     }
107     mConfigs[mCount] = new RendererConfig(hostConfigs[i], display);
108     mCount++;
109   }
110
111   delete[] hostConfigs;
112 }
113
114 RendererConfigList::~RendererConfigList() {
115   for (int n = 0; n < mCount; ++n) {
116     delete mConfigs[n];
117   }
118   delete[] mConfigs;
119 }
120
121 int RendererConfigList::chooseConfig(const EGLint* attribs, EGLint* configs,
122                                      EGLint configsSize) const {
123   EGLint numHostConfigs = 0;
124   if (!s_egl.eglGetConfigs(mDisplay, NULL, 0, &numHostConfigs)) {
125     ERROR("Could not get number of host EGL configs");
126     return 0;
127   }
128
129   EGLConfig* matchedConfigs = new EGLConfig[numHostConfigs];
130
131   // If EGL_SURFACE_TYPE appears in |attribs|, the value passed to
132   // eglChooseConfig should be forced to EGL_PBUFFER_BIT because that's
133   // what it used by the current implementation, exclusively. This forces
134   // the rewrite of |attribs| into a new array.
135   bool hasSurfaceType = false;
136   bool mustReplaceSurfaceType = false;
137   int numAttribs = 0;
138   while (attribs[numAttribs] != EGL_NONE) {
139     if (attribs[numAttribs] == EGL_SURFACE_TYPE) {
140       hasSurfaceType = true;
141       if (attribs[numAttribs + 1] != EGL_PBUFFER_BIT) {
142         mustReplaceSurfaceType = true;
143       }
144     }
145     numAttribs += 2;
146   }
147
148   EGLint* newAttribs = NULL;
149
150   if (mustReplaceSurfaceType) {
151     // There is at least on EGL_SURFACE_TYPE in |attribs|. Copy the
152     // array and replace all values with EGL_PBUFFER_BIT
153     newAttribs = new GLint[numAttribs + 1];
154     memcpy(newAttribs, attribs, numAttribs * sizeof(GLint));
155     newAttribs[numAttribs] = EGL_NONE;
156     for (int n = 0; n < numAttribs; n += 2) {
157       if (newAttribs[n] == EGL_SURFACE_TYPE) {
158         newAttribs[n + 1] = EGL_PBUFFER_BIT;
159       }
160     }
161   } else if (!hasSurfaceType) {
162     // There is no EGL_SURFACE_TYPE in |attribs|, then add one entry
163     // with the value EGL_PBUFFER_BIT.
164     newAttribs = new GLint[numAttribs + 3];
165     memcpy(newAttribs, attribs, numAttribs * sizeof(GLint));
166     newAttribs[numAttribs] = EGL_SURFACE_TYPE;
167     newAttribs[numAttribs + 1] = EGL_PBUFFER_BIT;
168     newAttribs[numAttribs + 2] = EGL_NONE;
169   }
170
171   if (!s_egl.eglChooseConfig(mDisplay, newAttribs ? newAttribs : attribs,
172                              matchedConfigs, numHostConfigs, &numHostConfigs)) {
173     numHostConfigs = 0;
174   }
175
176   delete[] newAttribs;
177
178   int result = 0;
179   for (int n = 0; n < numHostConfigs; ++n) {
180     // Don't count or write more than |configsSize| items if |configs|
181     // is not NULL.
182     if (configs && configsSize > 0 && result >= configsSize) {
183       break;
184     }
185     // Skip incompatible host configs.
186     if (!isCompatibleHostConfig(matchedConfigs[n], mDisplay)) {
187       continue;
188     }
189     // Find the FbConfig with the same EGL_CONFIG_ID
190     EGLint hostConfigId;
191     s_egl.eglGetConfigAttrib(mDisplay, matchedConfigs[n], EGL_CONFIG_ID,
192                              &hostConfigId);
193     for (int k = 0; k < mCount; ++k) {
194       int guestConfigId = mConfigs[k]->getConfigId();
195       if (guestConfigId == hostConfigId) {
196         // There is a match. Write it to |configs| if it is not NULL.
197         if (configs && result < configsSize) {
198           configs[result] = static_cast<uint32_t>(k);
199         }
200         result++;
201         break;
202       }
203     }
204   }
205
206   delete[] matchedConfigs;
207
208   return result;
209 }
210
211 void RendererConfigList::getPackInfo(EGLint* numConfigs,
212                                      EGLint* numAttributes) const {
213   if (numConfigs) {
214     *numConfigs = mCount;
215   }
216   if (numAttributes) {
217     *numAttributes = static_cast<EGLint>(kConfigAttributesLen);
218   }
219 }
220
221 EGLint RendererConfigList::packConfigs(GLuint bufferByteSize,
222                                        GLuint* buffer) const {
223   GLuint numAttribs = static_cast<GLuint>(kConfigAttributesLen);
224   GLuint kGLuintSize = static_cast<GLuint>(sizeof(GLuint));
225   GLuint neededByteSize = (mCount + 1) * numAttribs * kGLuintSize;
226   if (!buffer || bufferByteSize < neededByteSize) {
227     return -neededByteSize;
228   }
229   // Write to the buffer the config attribute ids, followed for each one
230   // of the configs, their values.
231   memcpy(buffer, kConfigAttributes, kConfigAttributesLen * kGLuintSize);
232
233   for (int i = 0; i < mCount; ++i) {
234     memcpy(buffer + (i + 1) * kConfigAttributesLen, mConfigs[i]->mAttribValues,
235            kConfigAttributesLen * kGLuintSize);
236   }
237   return mCount;
238 }