2 * Copyright (C) 2011 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "anbox/graphics/emugl/RenderControl.h"
18 #include "anbox/graphics/emugl/DispatchTables.h"
19 #include "anbox/graphics/emugl/DisplayManager.h"
20 #include "anbox/graphics/emugl/RenderThreadInfo.h"
21 #include "anbox/graphics/emugl/Renderer.h"
22 #include "anbox/graphics/emugl/RendererConfig.h"
23 #include "anbox/graphics/layer_composer.h"
24 #include "anbox/logger.h"
26 #include "external/android-emugl/shared/OpenglCodecCommon/ChecksumCalculatorThreadInfo.h"
27 #include "external/android-emugl/host/include/OpenGLESDispatch/EGLDispatch.h"
33 static const GLint rendererVersion = 1;
34 static std::shared_ptr<anbox::graphics::LayerComposer> composer;
35 static std::shared_ptr<Renderer> renderer;
37 void registerLayerComposer(
38 const std::shared_ptr<anbox::graphics::LayerComposer> &c) {
42 void registerRenderer(const std::shared_ptr<Renderer> &r) {
46 static GLint rcGetRendererVersion() { return rendererVersion; }
48 static EGLint rcGetEGLVersion(EGLint *major, EGLint *minor) {
52 *major = static_cast<EGLint>(renderer->getCaps().eglMajor);
53 *minor = static_cast<EGLint>(renderer->getCaps().eglMinor);
58 static std::string filter_extensions(const std::string& extensions, const std::vector<std::string>& whitelist) {
59 std::stringstream approved_extensions;
60 auto extension_list = anbox::utils::string_split(extensions, ' ');
61 for (const auto& ext : extension_list) {
62 if (std::find(whitelist.begin(), whitelist.end(), ext) == whitelist.end())
65 if (approved_extensions.tellp() > 0)
66 approved_extensions << " ";
68 approved_extensions << ext;
70 return approved_extensions.str();
73 static EGLint rcQueryEGLString(EGLenum name, void* buffer, EGLint bufferSize) {
77 std::string result = s_egl.eglQueryString(renderer->getDisplay(), name);
81 if (name == EGL_EXTENSIONS) {
82 // We need to drop a few extensions from the list reported by the driver
83 // as not all are well enough support by our EGL implementation.
84 std::vector<std::string> whitelisted_extensions = {
86 "EGL_KHR_gl_texture_2D_image",
88 result = filter_extensions(result, whitelisted_extensions);
91 int len = result.length() + 1;
92 if (!buffer || len > bufferSize) {
96 strcpy(static_cast<char*>(buffer), result.c_str());
100 static EGLint rcGetGLString(EGLenum name, void* buffer, EGLint bufferSize) {
101 RenderThreadInfo* tInfo = RenderThreadInfo::get();
104 if (tInfo && tInfo->currContext) {
105 const char* str = nullptr;
106 if (tInfo->currContext->isGL2())
107 str = reinterpret_cast<const char*>(s_gles2.glGetString(name));
109 str = reinterpret_cast<const char*>(s_gles1.glGetString(name));
115 // We're forcing version 2.0 no matter what the host provides as
116 // our emulation layer isn't prepared for anything newer (yet).
117 // This goes in parallel with filtering the extension set for
118 // any unwanted extensions. If we don't force the right version
119 // here certain parts of the system will assume API conditions
121 if (name == GL_VERSION)
122 result = "OpenGL ES 2.0";
123 else if (name == GL_EXTENSIONS) {
124 // We need to drop a few extensions from the list reported by the driver
125 // as not all are well enough support by our GL implementation.
126 std::vector<std::string> whitelisted_extensions = {
128 "GL_OES_EGL_image_external",
131 "GL_OES_element_index_uint",
132 "GL_OES_texture_float",
133 "GL_OES_texture_float_linear",
134 "GL_OES_compressed_paletted_texture",
135 "GL_OES_compressed_ETC1_RGB8_texture",
136 "GL_OES_depth_texture",
137 "GL_OES_texture_half_float",
138 "GL_OES_texture_half_float_linear",
139 "GL_OES_packed_depth_stencil",
140 "GL_OES_vertex_half_float",
141 "GL_OES_standard_derivatives",
142 "GL_OES_texture_npot",
146 result = filter_extensions(result, whitelisted_extensions);
149 int nextBufferSize = result.size() + 1;
151 if (!buffer || nextBufferSize > bufferSize)
152 return -nextBufferSize;
154 snprintf(static_cast<char*>(buffer), nextBufferSize, "%s", result.c_str());
155 return nextBufferSize;
158 static EGLint rcGetNumConfigs(uint32_t *p_numAttribs) {
159 int numConfigs = 0, numAttribs = 0;
161 renderer->getConfigs()->getPackInfo(&numConfigs, &numAttribs);
163 *p_numAttribs = static_cast<uint32_t>(numAttribs);
168 static EGLint rcGetConfigs(uint32_t bufSize, GLuint *buffer) {
169 GLuint bufferSize = static_cast<GLuint>(bufSize);
170 return renderer->getConfigs()->packConfigs(bufferSize, buffer);
173 static EGLint rcChooseConfig(EGLint *attribs, uint32_t attribs_size,
174 uint32_t *configs, uint32_t configs_size) {
175 if (!renderer || attribs_size == 0)
178 return renderer->getConfigs()->chooseConfig(attribs, reinterpret_cast<EGLint *>(configs),
179 static_cast<EGLint>(configs_size));
182 static EGLint rcGetFBParam(EGLint param) {
190 ret = static_cast<EGLint>(anbox::graphics::emugl::DisplayInfo::get()->vertical_resolution());
193 ret = static_cast<EGLint>(anbox::graphics::emugl::DisplayInfo::get()->horizontal_resolution());
196 ret = 72; // XXX: should be implemented
199 ret = 72; // XXX: should be implemented
204 case FB_MIN_SWAP_INTERVAL:
205 ret = 1; // XXX: should be implemented
207 case FB_MAX_SWAP_INTERVAL:
208 ret = 1; // XXX: should be implemented
217 static uint32_t rcCreateContext(uint32_t config, uint32_t share,
218 uint32_t glVersion) {
222 // To make it consistent with the guest, create GLES2 context when GL
225 renderer->createRenderContext(config, share, glVersion == 2 || glVersion == 3);
229 static void rcDestroyContext(uint32_t context) {
233 renderer->DestroyRenderContext(context);
236 static uint32_t rcCreateWindowSurface(uint32_t config, uint32_t width,
241 return renderer->createWindowSurface(config, width, height);
244 static void rcDestroyWindowSurface(uint32_t windowSurface) {
248 renderer->DestroyWindowSurface(windowSurface);
251 static uint32_t rcCreateColorBuffer(uint32_t width, uint32_t height,
252 GLenum internalFormat) {
256 return renderer->createColorBuffer(width, height, internalFormat);
259 static int rcOpenColorBuffer2(uint32_t colorbuffer) {
263 return renderer->openColorBuffer(colorbuffer);
266 // Deprecated, kept for compatibility with old system images only.
267 // Use rcOpenColorBuffer2 instead.
268 static void rcOpenColorBuffer(uint32_t colorbuffer) {
269 (void)rcOpenColorBuffer2(colorbuffer);
272 static void rcCloseColorBuffer(uint32_t colorbuffer) {
276 renderer->closeColorBuffer(colorbuffer);
279 static int rcFlushWindowColorBuffer(uint32_t windowSurface) {
283 if (!renderer->flushWindowSurfaceColorBuffer(windowSurface))
289 static void rcSetWindowColorBuffer(uint32_t windowSurface,
290 uint32_t colorBuffer) {
294 renderer->setWindowSurfaceColorBuffer(windowSurface, colorBuffer);
297 static EGLint rcMakeCurrent(uint32_t context, uint32_t drawSurf,
302 bool ret = renderer->bindContext(context, drawSurf, readSurf);
304 return (ret ? EGL_TRUE : EGL_FALSE);
307 static void rcFBPost(uint32_t) { WARNING("Not implemented"); }
309 static void rcFBSetSwapInterval(EGLint) {
310 // XXX: TBD - should be implemented
313 static void rcBindTexture(uint32_t colorBuffer) {
317 renderer->bindColorBufferToTexture(colorBuffer);
320 static void rcBindRenderbuffer(uint32_t colorBuffer) {
324 renderer->bindColorBufferToRenderbuffer(colorBuffer);
327 static EGLint rcColorBufferCacheFlush(uint32_t, EGLint,
329 // XXX: TBD - should be implemented
333 static void rcReadColorBuffer(uint32_t colorBuffer, GLint x, GLint y,
334 GLint width, GLint height, GLenum format,
335 GLenum type, void *pixels) {
339 renderer->readColorBuffer(colorBuffer, x, y, width, height, format, type, pixels);
342 static int rcUpdateColorBuffer(uint32_t colorBuffer, GLint x, GLint y,
343 GLint width, GLint height, GLenum format,
344 GLenum type, void *pixels) {
348 renderer->updateColorBuffer(colorBuffer, x, y, width, height, format, type, pixels);
352 static uint32_t rcCreateClientImage(uint32_t context, EGLenum target,
357 return renderer->createClientImage(context, target, buffer);
360 static int rcDestroyClientImage(uint32_t image) {
364 return renderer->destroyClientImage(image);
367 static void rcSelectChecksumCalculator(uint32_t protocol, uint32_t) {
368 ChecksumCalculatorThreadInfo::setVersion(protocol);
371 int rcGetNumDisplays() {
372 // For now we only support a single display but that single display
373 // will contain more than one display so that we simply spawn up a big
374 // virtual display which should match the real display arrangement
379 int rcGetDisplayWidth(uint32_t display_id) {
381 return static_cast<int>(anbox::graphics::emugl::DisplayInfo::get()->vertical_resolution());
384 int rcGetDisplayHeight(uint32_t display_id) {
386 return static_cast<int>(anbox::graphics::emugl::DisplayInfo::get()->horizontal_resolution());
389 int rcGetDisplayDpiX(uint32_t display_id) {
394 int rcGetDisplayDpiY(uint32_t display_id) {
399 int rcGetDisplayVsyncPeriod(uint32_t display_id) {
404 static std::vector<Renderable> frame_layers;
406 bool is_layer_blacklisted(const std::string &name) {
407 static std::vector<std::string> blacklist = {
408 // The 'Sprite' layer is the mouse cursor Android uses as soon
409 // as it has a pointer input device available. We don't want to
410 // display this layer at all but don't have a good way of disabling
411 // the cursor on the Android side yet.
414 return std::find(blacklist.begin(), blacklist.end(), name) != blacklist.end();
417 void rcPostLayer(const char *name, uint32_t color_buffer, float alpha,
418 int32_t sourceCropLeft, int32_t sourceCropTop,
419 int32_t sourceCropRight, int32_t sourceCropBottom,
420 int32_t displayFrameLeft, int32_t displayFrameTop,
421 int32_t displayFrameRight, int32_t displayFrameBottom) {
426 {displayFrameLeft, displayFrameTop, displayFrameRight, displayFrameBottom},
427 {sourceCropLeft, sourceCropTop, sourceCropRight, sourceCropBottom}};
428 frame_layers.push_back(r);
431 void rcPostAllLayersDone() {
432 if (composer) composer->submit_layers(frame_layers);
434 frame_layers.clear();
437 void initRenderControlContext(renderControl_decoder_context_t *dec) {
438 dec->rcGetRendererVersion = rcGetRendererVersion;
439 dec->rcGetEGLVersion = rcGetEGLVersion;
440 dec->rcQueryEGLString = rcQueryEGLString;
441 dec->rcGetGLString = rcGetGLString;
442 dec->rcGetNumConfigs = rcGetNumConfigs;
443 dec->rcGetConfigs = rcGetConfigs;
444 dec->rcChooseConfig = rcChooseConfig;
445 dec->rcGetFBParam = rcGetFBParam;
446 dec->rcCreateContext = rcCreateContext;
447 dec->rcDestroyContext = rcDestroyContext;
448 dec->rcCreateWindowSurface = rcCreateWindowSurface;
449 dec->rcDestroyWindowSurface = rcDestroyWindowSurface;
450 dec->rcCreateColorBuffer = rcCreateColorBuffer;
451 dec->rcOpenColorBuffer = rcOpenColorBuffer;
452 dec->rcCloseColorBuffer = rcCloseColorBuffer;
453 dec->rcSetWindowColorBuffer = rcSetWindowColorBuffer;
454 dec->rcFlushWindowColorBuffer = rcFlushWindowColorBuffer;
455 dec->rcMakeCurrent = rcMakeCurrent;
456 dec->rcFBPost = rcFBPost;
457 dec->rcFBSetSwapInterval = rcFBSetSwapInterval;
458 dec->rcBindTexture = rcBindTexture;
459 dec->rcBindRenderbuffer = rcBindRenderbuffer;
460 dec->rcColorBufferCacheFlush = rcColorBufferCacheFlush;
461 dec->rcReadColorBuffer = rcReadColorBuffer;
462 dec->rcUpdateColorBuffer = rcUpdateColorBuffer;
463 dec->rcOpenColorBuffer2 = rcOpenColorBuffer2;
464 dec->rcCreateClientImage = rcCreateClientImage;
465 dec->rcDestroyClientImage = rcDestroyClientImage;
466 dec->rcSelectChecksumCalculator = rcSelectChecksumCalculator;
467 dec->rcGetNumDisplays = rcGetNumDisplays;
468 dec->rcGetDisplayWidth = rcGetDisplayWidth;
469 dec->rcGetDisplayHeight = rcGetDisplayHeight;
470 dec->rcGetDisplayDpiX = rcGetDisplayDpiX;
471 dec->rcGetDisplayDpiY = rcGetDisplayDpiY;
472 dec->rcGetDisplayVsyncPeriod = rcGetDisplayVsyncPeriod;
473 dec->rcPostLayer = rcPostLayer;
474 dec->rcPostAllLayersDone = rcPostAllLayersDone;