OSDN Git Service

Merge "Make the binder_lock category optional" am: 61e58d5a47 am: c4a8373ccd
[android-x86/frameworks-native.git] / services / surfaceflinger / RenderEngine / RenderEngine.cpp
1 /*
2  * Copyright 2013 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
17 #include <log/log.h>
18 #include <ui/Rect.h>
19 #include <ui/Region.h>
20
21 #include "RenderEngine.h"
22 #include "GLES20RenderEngine.h"
23 #include "GLExtensions.h"
24 #include "Mesh.h"
25
26 #include <vector>
27 #include <SurfaceFlinger.h>
28
29 EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
30
31 // ---------------------------------------------------------------------------
32 namespace android {
33 // ---------------------------------------------------------------------------
34
35 static bool findExtension(const char* exts, const char* name) {
36     if (!exts)
37         return false;
38     size_t len = strlen(name);
39
40     const char* pos = exts;
41     while ((pos = strstr(pos, name)) != NULL) {
42         if (pos[len] == '\0' || pos[len] == ' ')
43             return true;
44         pos += len;
45     }
46
47     return false;
48 }
49
50 RenderEngine* RenderEngine::create(EGLDisplay display, int hwcFormat) {
51     // EGL_ANDROIDX_no_config_context is an experimental extension with no
52     // written specification. It will be replaced by something more formal.
53     // SurfaceFlinger is using it to allow a single EGLContext to render to
54     // both a 16-bit primary display framebuffer and a 32-bit virtual display
55     // framebuffer.
56     //
57     // The code assumes that ES2 or later is available if this extension is
58     // supported.
59     EGLConfig config = EGL_NO_CONFIG;
60     if (!findExtension(
61             eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS),
62             "EGL_ANDROIDX_no_config_context")) {
63         config = chooseEglConfig(display, hwcFormat);
64     }
65
66     EGLint renderableType = 0;
67     if (config == EGL_NO_CONFIG) {
68         renderableType = EGL_OPENGL_ES2_BIT;
69     } else if (!eglGetConfigAttrib(display, config,
70             EGL_RENDERABLE_TYPE, &renderableType)) {
71         LOG_ALWAYS_FATAL("can't query EGLConfig RENDERABLE_TYPE");
72     }
73     EGLint contextClientVersion = 0;
74     if (renderableType & EGL_OPENGL_ES2_BIT) {
75         contextClientVersion = 2;
76     } else if (renderableType & EGL_OPENGL_ES_BIT) {
77         contextClientVersion = 1;
78     } else {
79         LOG_ALWAYS_FATAL("no supported EGL_RENDERABLE_TYPEs");
80     }
81
82     std::vector<EGLint> contextAttributes;
83     contextAttributes.reserve(6);
84     contextAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION);
85     contextAttributes.push_back(contextClientVersion);
86 #ifdef EGL_IMG_context_priority
87     if (SurfaceFlinger::useContextPriority) {
88         contextAttributes.push_back(EGL_CONTEXT_PRIORITY_LEVEL_IMG);
89         contextAttributes.push_back(EGL_CONTEXT_PRIORITY_HIGH_IMG);
90     }
91 #endif
92     contextAttributes.push_back(EGL_NONE);
93     contextAttributes.push_back(EGL_NONE);
94
95     EGLContext ctxt = eglCreateContext(display, config, NULL,
96                                        contextAttributes.data());
97
98     // if can't create a GL context, we can only abort.
99     LOG_ALWAYS_FATAL_IF(ctxt==EGL_NO_CONTEXT, "EGLContext creation failed");
100
101
102     // now figure out what version of GL did we actually get
103     // NOTE: a dummy surface is not needed if KHR_create_context is supported
104
105     EGLConfig dummyConfig = config;
106     if (dummyConfig == EGL_NO_CONFIG) {
107         dummyConfig = chooseEglConfig(display, hwcFormat);
108     }
109     EGLint attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE };
110     EGLSurface dummy = eglCreatePbufferSurface(display, dummyConfig, attribs);
111     LOG_ALWAYS_FATAL_IF(dummy==EGL_NO_SURFACE, "can't create dummy pbuffer");
112     EGLBoolean success = eglMakeCurrent(display, dummy, dummy, ctxt);
113     LOG_ALWAYS_FATAL_IF(!success, "can't make dummy pbuffer current");
114
115     GLExtensions& extensions(GLExtensions::getInstance());
116     extensions.initWithGLStrings(
117             glGetString(GL_VENDOR),
118             glGetString(GL_RENDERER),
119             glGetString(GL_VERSION),
120             glGetString(GL_EXTENSIONS));
121
122     GlesVersion version = parseGlesVersion( extensions.getVersion() );
123
124     // initialize the renderer while GL is current
125
126     RenderEngine* engine = NULL;
127     switch (version) {
128     case GLES_VERSION_1_0:
129     case GLES_VERSION_1_1:
130         LOG_ALWAYS_FATAL("SurfaceFlinger requires OpenGL ES 2.0 minimum to run.");
131         break;
132     case GLES_VERSION_2_0:
133     case GLES_VERSION_3_0:
134         engine = new GLES20RenderEngine();
135         break;
136     }
137     engine->setEGLHandles(config, ctxt);
138
139     ALOGI("OpenGL ES informations:");
140     ALOGI("vendor    : %s", extensions.getVendor());
141     ALOGI("renderer  : %s", extensions.getRenderer());
142     ALOGI("version   : %s", extensions.getVersion());
143     ALOGI("extensions: %s", extensions.getExtension());
144     ALOGI("GL_MAX_TEXTURE_SIZE = %zu", engine->getMaxTextureSize());
145     ALOGI("GL_MAX_VIEWPORT_DIMS = %zu", engine->getMaxViewportDims());
146
147     eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
148     eglDestroySurface(display, dummy);
149
150     return engine;
151 }
152
153 RenderEngine::RenderEngine() : mEGLConfig(NULL), mEGLContext(EGL_NO_CONTEXT) {
154 }
155
156 RenderEngine::~RenderEngine() {
157 }
158
159 void RenderEngine::setEGLHandles(EGLConfig config, EGLContext ctxt) {
160     mEGLConfig = config;
161     mEGLContext = ctxt;
162 }
163
164 EGLContext RenderEngine::getEGLConfig() const {
165     return mEGLConfig;
166 }
167
168 EGLContext RenderEngine::getEGLContext() const {
169     return mEGLContext;
170 }
171
172 void RenderEngine::checkErrors() const {
173     do {
174         // there could be more than one error flag
175         GLenum error = glGetError();
176         if (error == GL_NO_ERROR)
177             break;
178         ALOGE("GL error 0x%04x", int(error));
179     } while (true);
180 }
181
182 RenderEngine::GlesVersion RenderEngine::parseGlesVersion(const char* str) {
183     int major, minor;
184     if (sscanf(str, "OpenGL ES-CM %d.%d", &major, &minor) != 2) {
185         if (sscanf(str, "OpenGL ES %d.%d", &major, &minor) != 2) {
186             ALOGW("Unable to parse GL_VERSION string: \"%s\"", str);
187             return GLES_VERSION_1_0;
188         }
189     }
190
191     if (major == 1 && minor == 0) return GLES_VERSION_1_0;
192     if (major == 1 && minor >= 1) return GLES_VERSION_1_1;
193     if (major == 2 && minor >= 0) return GLES_VERSION_2_0;
194     if (major == 3 && minor >= 0) return GLES_VERSION_3_0;
195
196     ALOGW("Unrecognized OpenGL ES version: %d.%d", major, minor);
197     return GLES_VERSION_1_0;
198 }
199
200 void RenderEngine::fillRegionWithColor(const Region& region, uint32_t height,
201         float red, float green, float blue, float alpha) {
202     size_t c;
203     Rect const* r = region.getArray(&c);
204     Mesh mesh(Mesh::TRIANGLES, c*6, 2);
205     Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
206     for (size_t i=0 ; i<c ; i++, r++) {
207         position[i*6 + 0].x = r->left;
208         position[i*6 + 0].y = height - r->top;
209         position[i*6 + 1].x = r->left;
210         position[i*6 + 1].y = height - r->bottom;
211         position[i*6 + 2].x = r->right;
212         position[i*6 + 2].y = height - r->bottom;
213         position[i*6 + 3].x = r->left;
214         position[i*6 + 3].y = height - r->top;
215         position[i*6 + 4].x = r->right;
216         position[i*6 + 4].y = height - r->bottom;
217         position[i*6 + 5].x = r->right;
218         position[i*6 + 5].y = height - r->top;
219     }
220     setupFillWithColor(red, green, blue, alpha);
221     drawMesh(mesh);
222 }
223
224 void RenderEngine::flush() {
225     glFlush();
226 }
227
228 void RenderEngine::clearWithColor(float red, float green, float blue, float alpha) {
229     glClearColor(red, green, blue, alpha);
230     glClear(GL_COLOR_BUFFER_BIT);
231 }
232
233 void RenderEngine::setScissor(
234         uint32_t left, uint32_t bottom, uint32_t right, uint32_t top) {
235     glScissor(left, bottom, right, top);
236     glEnable(GL_SCISSOR_TEST);
237 }
238
239 void RenderEngine::disableScissor() {
240     glDisable(GL_SCISSOR_TEST);
241 }
242
243 void RenderEngine::genTextures(size_t count, uint32_t* names) {
244     glGenTextures(count, names);
245 }
246
247 void RenderEngine::deleteTextures(size_t count, uint32_t const* names) {
248     glDeleteTextures(count, names);
249 }
250
251 void RenderEngine::readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* pixels) {
252     glReadPixels(l, b, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
253 }
254
255 void RenderEngine::dump(String8& result) {
256     const GLExtensions& extensions(GLExtensions::getInstance());
257     result.appendFormat("GLES: %s, %s, %s\n",
258             extensions.getVendor(),
259             extensions.getRenderer(),
260             extensions.getVersion());
261     result.appendFormat("%s\n", extensions.getExtension());
262 }
263
264 // ---------------------------------------------------------------------------
265
266 RenderEngine::BindImageAsFramebuffer::BindImageAsFramebuffer(
267         RenderEngine& engine, EGLImageKHR image) : mEngine(engine)
268 {
269     mEngine.bindImageAsFramebuffer(image, &mTexName, &mFbName, &mStatus);
270
271     ALOGE_IF(mStatus != GL_FRAMEBUFFER_COMPLETE_OES,
272             "glCheckFramebufferStatusOES error %d", mStatus);
273 }
274
275 RenderEngine::BindImageAsFramebuffer::~BindImageAsFramebuffer() {
276     // back to main framebuffer
277     mEngine.unbindFramebuffer(mTexName, mFbName);
278 }
279
280 status_t RenderEngine::BindImageAsFramebuffer::getStatus() const {
281     return mStatus == GL_FRAMEBUFFER_COMPLETE_OES ? NO_ERROR : BAD_VALUE;
282 }
283
284 // ---------------------------------------------------------------------------
285
286 static status_t selectConfigForAttribute(EGLDisplay dpy, EGLint const* attrs,
287         EGLint attribute, EGLint wanted, EGLConfig* outConfig) {
288     EGLint numConfigs = -1, n = 0;
289     eglGetConfigs(dpy, NULL, 0, &numConfigs);
290     EGLConfig* const configs = new EGLConfig[numConfigs];
291     eglChooseConfig(dpy, attrs, configs, numConfigs, &n);
292
293     if (n) {
294         if (attribute != EGL_NONE) {
295             for (int i=0 ; i<n ; i++) {
296                 EGLint value = 0;
297                 eglGetConfigAttrib(dpy, configs[i], attribute, &value);
298                 if (wanted == value) {
299                     *outConfig = configs[i];
300                     delete [] configs;
301                     return NO_ERROR;
302                 }
303             }
304         } else {
305             // just pick the first one
306             *outConfig = configs[0];
307             delete [] configs;
308             return NO_ERROR;
309         }
310     }
311     delete [] configs;
312     return NAME_NOT_FOUND;
313 }
314
315 class EGLAttributeVector {
316     struct Attribute;
317     class Adder;
318     friend class Adder;
319     KeyedVector<Attribute, EGLint> mList;
320     struct Attribute {
321         Attribute() : v(0) {};
322         explicit Attribute(EGLint v) : v(v) { }
323         EGLint v;
324         bool operator < (const Attribute& other) const {
325             // this places EGL_NONE at the end
326             EGLint lhs(v);
327             EGLint rhs(other.v);
328             if (lhs == EGL_NONE) lhs = 0x7FFFFFFF;
329             if (rhs == EGL_NONE) rhs = 0x7FFFFFFF;
330             return lhs < rhs;
331         }
332     };
333     class Adder {
334         friend class EGLAttributeVector;
335         EGLAttributeVector& v;
336         EGLint attribute;
337         Adder(EGLAttributeVector& v, EGLint attribute)
338             : v(v), attribute(attribute) {
339         }
340     public:
341         void operator = (EGLint value) {
342             if (attribute != EGL_NONE) {
343                 v.mList.add(Attribute(attribute), value);
344             }
345         }
346         operator EGLint () const { return v.mList[attribute]; }
347     };
348 public:
349     EGLAttributeVector() {
350         mList.add(Attribute(EGL_NONE), EGL_NONE);
351     }
352     void remove(EGLint attribute) {
353         if (attribute != EGL_NONE) {
354             mList.removeItem(Attribute(attribute));
355         }
356     }
357     Adder operator [] (EGLint attribute) {
358         return Adder(*this, attribute);
359     }
360     EGLint operator [] (EGLint attribute) const {
361        return mList[attribute];
362     }
363     // cast-operator to (EGLint const*)
364     operator EGLint const* () const { return &mList.keyAt(0).v; }
365 };
366
367
368 static status_t selectEGLConfig(EGLDisplay display, EGLint format,
369     EGLint renderableType, EGLConfig* config) {
370     // select our EGLConfig. It must support EGL_RECORDABLE_ANDROID if
371     // it is to be used with WIFI displays
372     status_t err;
373     EGLint wantedAttribute;
374     EGLint wantedAttributeValue;
375
376     EGLAttributeVector attribs;
377     if (renderableType) {
378         attribs[EGL_RENDERABLE_TYPE]            = renderableType;
379         attribs[EGL_RECORDABLE_ANDROID]         = EGL_TRUE;
380         attribs[EGL_SURFACE_TYPE]               = EGL_WINDOW_BIT|EGL_PBUFFER_BIT;
381         attribs[EGL_FRAMEBUFFER_TARGET_ANDROID] = EGL_TRUE;
382         attribs[EGL_RED_SIZE]                   = 8;
383         attribs[EGL_GREEN_SIZE]                 = 8;
384         attribs[EGL_BLUE_SIZE]                  = 8;
385         attribs[EGL_ALPHA_SIZE]                 = 8;
386         wantedAttribute                         = EGL_NONE;
387         wantedAttributeValue                    = EGL_NONE;
388     } else {
389         // if no renderable type specified, fallback to a simplified query
390         wantedAttribute                         = EGL_NATIVE_VISUAL_ID;
391         wantedAttributeValue                    = format;
392     }
393
394     err = selectConfigForAttribute(display, attribs,
395             wantedAttribute, wantedAttributeValue, config);
396     if (err == NO_ERROR) {
397         EGLint caveat;
398         if (eglGetConfigAttrib(display, *config, EGL_CONFIG_CAVEAT, &caveat))
399             ALOGW_IF(caveat == EGL_SLOW_CONFIG, "EGL_SLOW_CONFIG selected!");
400     }
401
402     return err;
403 }
404
405 EGLConfig RenderEngine::chooseEglConfig(EGLDisplay display, int format) {
406     status_t err;
407     EGLConfig config;
408
409     // First try to get an ES2 config
410     err = selectEGLConfig(display, format, EGL_OPENGL_ES2_BIT, &config);
411     if (err != NO_ERROR) {
412         // If ES2 fails, try ES1
413         err = selectEGLConfig(display, format, EGL_OPENGL_ES_BIT, &config);
414         if (err != NO_ERROR) {
415             // still didn't work, probably because we're on the emulator...
416             // try a simplified query
417             ALOGW("no suitable EGLConfig found, trying a simpler query");
418             err = selectEGLConfig(display, format, 0, &config);
419             if (err != NO_ERROR) {
420                 // this EGL is too lame for android
421                 LOG_ALWAYS_FATAL("no suitable EGLConfig found, giving up");
422             }
423         }
424     }
425
426     // print some debugging info
427     EGLint r,g,b,a;
428     eglGetConfigAttrib(display, config, EGL_RED_SIZE,   &r);
429     eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g);
430     eglGetConfigAttrib(display, config, EGL_BLUE_SIZE,  &b);
431     eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a);
432     ALOGI("EGL information:");
433     ALOGI("vendor    : %s", eglQueryString(display, EGL_VENDOR));
434     ALOGI("version   : %s", eglQueryString(display, EGL_VERSION));
435     ALOGI("extensions: %s", eglQueryString(display, EGL_EXTENSIONS));
436     ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
437     ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);
438
439     return config;
440 }
441
442
443 void RenderEngine::primeCache() const {
444     // Getting the ProgramCache instance causes it to prime its shader cache,
445     // which is performed in its constructor
446     ProgramCache::getInstance();
447 }
448
449 // ---------------------------------------------------------------------------
450 }; // namespace android
451 // ---------------------------------------------------------------------------