RenderEngine.cpp 15 KB

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