blob: 5907b84e0b47d3824213d628e4ea6118ea6e0670 [file] [log] [blame]
Joshua Duong9dfbd852022-11-14 13:12:59 -08001// Copyright 2020 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 "host-common/opengles.h"
16
17#include "aemu/base/GLObjectCounter.h"
18#include "aemu/base/files/PathUtils.h"
19#include "aemu/base/files/Stream.h"
20#include "aemu/base/memory/MemoryTracker.h"
21#include "aemu/base/SharedLibrary.h"
22#include "aemu/base/system/System.h"
23#include "host-common/address_space_device.h"
24#include "host-common/address_space_graphics.h"
25#include "host-common/address_space_graphics_types.h"
26#include "host-common/GfxstreamFatalError.h"
27#include "host-common/GoldfishDma.h"
28#include "host-common/RefcountPipe.h"
29#include "host-common/FeatureControl.h"
30#include "host-common/globals.h"
31#include "host-common/opengl/emugl_config.h"
32#include "host-common/opengl/GLProcessPipe.h"
33#include "host-common/opengl/logger.h"
34#include "host-common/opengl/gpuinfo.h"
35
36#include "render-utils/render_api_functions.h"
37#include "OpenGLESDispatch/EGLDispatch.h"
38#include "OpenGLESDispatch/GLESv2Dispatch.h"
39
40#include <assert.h>
41#include <stdio.h>
42#include <stdlib.h>
43
44#include <optional>
45
46#define D(...)
47#define DD(...)
48#define E(...)
49
50// #define D(...) do { \
51// VERBOSE_PRINT(init,__VA_ARGS__); \
52// android_opengl_logger_write(__VA_ARGS__); \
53// } while(0);
54//
55// #define DD(...) do { \
56// VERBOSE_PRINT(gles,__VA_ARGS__); \
57// android_opengl_logger_write(__VA_ARGS__); \
58// } while(0);
59//
60// #define E(fmt,...) do { \
61// derror(fmt, ##__VA_ARGS__); \
62// android_opengl_logger_write(fmt "\n", ##__VA_ARGS__); \
63// } while(0);
64
65using android::base::pj;
66using android::base::SharedLibrary;
67using android::emulation::asg::AddressSpaceGraphicsContext;
68using android::emulation::asg::ConsumerCallbacks;
69using android::emulation::asg::ConsumerInterface;
70using emugl::ABORT_REASON_OTHER;
71using emugl::FatalError;
Jason Macnaked0c9e62023-03-30 15:58:24 -070072using gfxstream::gl::EGLDispatch;
73using gfxstream::gl::GLESv2Dispatch;
Joshua Duong9dfbd852022-11-14 13:12:59 -080074
75/* Name of the GLES rendering library we're going to use */
76#define RENDERER_LIB_NAME "libOpenglRender"
77
78/* Declared in "android/globals.h" */
79int android_gles_fast_pipes = 1;
80
81// Define the Render API function pointers.
82#define FUNCTION_(ret, name, sig, params) \
83 inline ret (*name) sig = NULL;
84LIST_RENDER_API_FUNCTIONS(FUNCTION_)
85#undef FUNCTION_
86
87static bool sOpenglLoggerInitialized = false;
88static bool sRendererUsesSubWindow = false;
89static bool sEgl2egl = false;
Jason Macnaked0c9e62023-03-30 15:58:24 -070090static gfxstream::RenderLib* sRenderLib = nullptr;
91static gfxstream::RendererPtr sRenderer = nullptr;
Joshua Duong9dfbd852022-11-14 13:12:59 -080092
Joshua Duong9dfbd852022-11-14 13:12:59 -080093int android_prepareOpenglesEmulation() {
94 android_init_opengl_logger();
95
96 bool glFineLogging = android::base::getEnvironmentVariable("ANDROID_EMUGL_FINE_LOG") == "1";
97 bool glLogPrinting = android::base::getEnvironmentVariable("ANDROID_EMUGL_LOG_PRINT") == "1";
98
99 AndroidOpenglLoggerFlags loggerFlags =
100 static_cast<AndroidOpenglLoggerFlags>(
101 (glFineLogging ? OPENGL_LOGGER_DO_FINE_LOGGING : 0) |
102 (glLogPrinting ? OPENGL_LOGGER_PRINT_TO_STDOUT : 0));
103
104 android_opengl_logger_set_flags(loggerFlags);
105
106 sOpenglLoggerInitialized = true;
107 sRendererUsesSubWindow = true;
108
109 sEgl2egl = false;
110 if (android::base::getEnvironmentVariable("ANDROID_EGL_ON_EGL") == "1") {
111 sEgl2egl = true;
112 }
113
114 return 0;
115}
Joshua Duong9dfbd852022-11-14 13:12:59 -0800116
117int android_setOpenglesEmulation(void* renderLib, void* eglDispatch, void* glesv2Dispatch) {
Jason Macnaked0c9e62023-03-30 15:58:24 -0700118 sRenderLib = (gfxstream::RenderLib*)renderLib;
Jason Macnake70b8e32023-01-20 13:59:35 -0800119 (void)eglDispatch;
120 (void)glesv2Dispatch;
121 sEgl2egl = android::base::getEnvironmentVariable("ANDROID_EGL_ON_EGL") == "1";
Joshua Duong9dfbd852022-11-14 13:12:59 -0800122 return 0;
123}
124
125int android_initOpenglesEmulation() {
126 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
127 << "Not meant to call android_initOpenglesEmulation in the new build.";
128}
129
130int
Jason Macnak26872122024-02-23 10:46:09 -0800131android_startOpenglesRenderer(int width, int height,
132 bool guestPhoneApi, int guestApiLevel,
Joshua Duong9dfbd852022-11-14 13:12:59 -0800133 const QAndroidVmOperations *vm_operations,
134 const QAndroidEmulatorWindowAgent *window_agent,
135 const QAndroidMultiDisplayAgent *multi_display_agent,
Jason Macnak26872122024-02-23 10:46:09 -0800136 const void* gfxstreamFeatures,
Joshua Duong9dfbd852022-11-14 13:12:59 -0800137 int* glesMajorVersion_out,
138 int* glesMinorVersion_out)
139{
140 if (!sRenderLib) {
141 D("Can't start OpenGLES renderer without support libraries");
142 return -1;
143 }
144
Joshua Duong9dfbd852022-11-14 13:12:59 -0800145 if (sRenderer) {
146 return 0;
147 }
148
149 const GpuInfoList& gpuList = globalGpuInfoList();
150 std::string gpuInfoAsString = gpuList.dump();
151 android_opengl_logger_write("%s: gpu info", __func__);
152 android_opengl_logger_write("%s", gpuInfoAsString.c_str());
153
154 sRenderLib->setRenderer(emuglConfig_get_current_renderer());
155 sRenderLib->setAvdInfo(guestPhoneApi, guestApiLevel);
156 // sRenderLib->setCrashReporter(&crashhandler_die_format);
157 // sRenderLib->setFeatureController(&android::featurecontrol::isEnabled);
158 sRenderLib->setSyncDevice(goldfish_sync_create_timeline,
159 goldfish_sync_create_fence,
160 goldfish_sync_timeline_inc,
161 goldfish_sync_destroy_timeline,
162 goldfish_sync_register_trigger_wait,
163 goldfish_sync_device_exists);
164
165 emugl_logger_struct logfuncs;
166 logfuncs.coarse = android_opengl_logger_write;
167 logfuncs.fine = android_opengl_cxt_logger_write;
168 sRenderLib->setLogger(logfuncs);
169 sRenderLib->setGLObjectCounter(android::base::GLObjectCounter::get());
170 emugl_dma_ops dma_ops;
171 dma_ops.get_host_addr = android_goldfish_dma_ops.get_host_addr;
172 dma_ops.unlock = android_goldfish_dma_ops.unlock;
173 sRenderLib->setDmaOps(dma_ops);
174 sRenderLib->setVmOps(*vm_operations);
175 sRenderLib->setAddressSpaceDeviceControlOps(get_address_space_device_control_ops());
176 sRenderLib->setWindowOps(*window_agent, *multi_display_agent);
177 // sRenderLib->setUsageTracker(android::base::CpuUsage::get(),
178 // android::base::MemoryTracker::get());
179
Jason Macnak26872122024-02-23 10:46:09 -0800180 const auto* features = reinterpret_cast<const gfxstream::host::FeatureSet*>(gfxstreamFeatures);
181 sRenderer = sRenderLib->initRenderer(width, height, *features, sRendererUsesSubWindow, sEgl2egl);
Joshua Duongc256a3c2023-05-09 08:14:24 -0700182 android_setOpenglesRenderer(&sRenderer);
Joshua Duong9dfbd852022-11-14 13:12:59 -0800183
184 // android::snapshot::Snapshotter::get().addOperationCallback(
185 // [](android::snapshot::Snapshotter::Operation op,
186 // android::snapshot::Snapshotter::Stage stage) {
187 // sRenderer->snapshotOperationCallback(op, stage);
188 // });
189
190 android::emulation::registerOnLastRefCallback(
191 sRenderLib->getOnLastColorBufferRef());
192
193 ConsumerInterface iface = {
194 // create
195 [](struct asg_context context,
196 android::base::Stream* loadStream, ConsumerCallbacks callbacks,
197 uint32_t contextId, uint32_t capsetId,
198 std::optional<std::string> nameOpt) {
199 return sRenderer->addressSpaceGraphicsConsumerCreate(
200 context, loadStream, callbacks, contextId, capsetId, std::move(nameOpt));
201 },
202 // destroy
203 [](void* consumer) {
204 sRenderer->addressSpaceGraphicsConsumerDestroy(consumer);
205 },
206 // pre save
207 [](void* consumer) {
208 sRenderer->addressSpaceGraphicsConsumerPreSave(consumer);
209 },
210 // global presave
211 []() {
212 sRenderer->pauseAllPreSave();
213 },
214 // save
215 [](void* consumer, android::base::Stream* stream) {
216 sRenderer->addressSpaceGraphicsConsumerSave(consumer, stream);
217 },
218 // global postsave
219 []() {
220 sRenderer->resumeAll();
221 },
222 // postSave
223 [](void* consumer) {
224 sRenderer->addressSpaceGraphicsConsumerPostSave(consumer);
225 },
226 // postLoad
227 [](void* consumer) {
228 sRenderer->addressSpaceGraphicsConsumerRegisterPostLoadRenderThread(consumer);
229 },
230 // global preload
231 []() {
232 // This wants to address that when using asg, pipe wants to clean
233 // up all render threads and wait for gl objects, but framebuffer
234 // notices that there is a render thread info that is still not
235 // cleaned up because these render threads come from asg.
236 android::opengl::forEachProcessPipeIdRunAndErase([](uint64_t id) {
237 android_cleanupProcGLObjects(id);
238 });
239 android_waitForOpenglesProcessCleanup();
240 },
241 };
242 AddressSpaceGraphicsContext::setConsumer(iface);
243
244 if (!sRenderer) {
245 D("Can't start OpenGLES renderer?");
246 return -1;
247 }
248
249 // after initRenderer is a success, the maximum GLES API is calculated depending
250 // on feature control and host GPU support. Set the obtained GLES version here.
251 if (glesMajorVersion_out && glesMinorVersion_out)
252 sRenderLib->getGlesVersion(glesMajorVersion_out, glesMinorVersion_out);
253 return 0;
254}
255
256bool
257android_asyncReadbackSupported() {
258 if (sRenderer) {
259 return sRenderer->asyncReadbackSupported();
260 } else {
261 D("tried to query async readback support "
262 "before renderer initialized. Likely guest rendering");
263 return false;
264 }
265}
266
267void
268android_setPostCallback(OnPostFunc onPost, void* onPostContext, bool useBgraReadback, uint32_t displayId)
269{
270 if (sRenderer) {
271 sRenderer->setPostCallback(onPost, onPostContext, useBgraReadback, displayId);
272 }
273}
274
275ReadPixelsFunc android_getReadPixelsFunc() {
276 if (sRenderer) {
277 return sRenderer->getReadPixelsCallback();
278 } else {
279 return nullptr;
280 }
281}
282
283FlushReadPixelPipeline android_getFlushReadPixelPipeline() {
284 if (sRenderer) {
285 return sRenderer->getFlushReadPixelPipeline();
286 } else {
287 return nullptr;
288 }
289}
290
291
292static char* strdupBaseString(const char* src) {
293 const char* begin = strchr(src, '(');
294 if (!begin) {
295 return strdup(src);
296 }
297
298 const char* end = strrchr(begin + 1, ')');
299 if (!end) {
300 return strdup(src);
301 }
302
303 // src is of the form:
304 // "foo (barzzzzzzzzzz)"
305 // ^ ^
306 // (b+1) e
307 // = 5 18
308 int len;
309 begin += 1;
310 len = end - begin;
311
312 char* result;
313 result = (char*)malloc(len + 1);
314 memcpy(result, begin, len);
315 result[len] = '\0';
316 return result;
317}
318
319void android_getOpenglesHardwareStrings(char** vendor,
320 char** renderer,
321 char** version) {
322 assert(vendor != NULL && renderer != NULL && version != NULL);
323 assert(*vendor == NULL && *renderer == NULL && *version == NULL);
324 if (!sRenderer) {
325 D("Can't get OpenGL ES hardware strings when renderer not started");
326 return;
327 }
328
Jason Macnaked0c9e62023-03-30 15:58:24 -0700329 const gfxstream::Renderer::HardwareStrings strings = sRenderer->getHardwareStrings();
Joshua Duong9dfbd852022-11-14 13:12:59 -0800330 D("OpenGL Vendor=[%s]", strings.vendor.c_str());
331 D("OpenGL Renderer=[%s]", strings.renderer.c_str());
332 D("OpenGL Version=[%s]", strings.version.c_str());
333
334 /* Special case for the default ES to GL translators: extract the strings
335 * of the underlying OpenGL implementation. */
336 if (strncmp(strings.vendor.c_str(), "Google", 6) == 0 &&
337 strncmp(strings.renderer.c_str(), "Android Emulator OpenGL ES Translator", 37) == 0) {
338 *vendor = strdupBaseString(strings.vendor.c_str());
339 *renderer = strdupBaseString(strings.renderer.c_str());
340 *version = strdupBaseString(strings.version.c_str());
341 } else {
342 *vendor = strdup(strings.vendor.c_str());
343 *renderer = strdup(strings.renderer.c_str());
344 *version = strdup(strings.version.c_str());
345 }
346}
347
348void android_getOpenglesVersion(int* maj, int* min) {
349 sRenderLib->getGlesVersion(maj, min);
350 fprintf(stderr, "%s: maj min %d %d\n", __func__, *maj, *min);
351}
352
353void
354android_stopOpenglesRenderer(bool wait)
355{
356 if (sRenderer) {
357 sRenderer->stop(wait);
358 if (wait) {
359 sRenderer.reset();
360 android_stop_opengl_logger();
361 }
362 }
363}
364
365void
366android_finishOpenglesRenderer()
367{
368 if (sRenderer) {
369 sRenderer->finish();
370 }
371}
372
Jason Macnaked0c9e62023-03-30 15:58:24 -0700373static gfxstream::RenderOpt sOpt;
Joshua Duong9dfbd852022-11-14 13:12:59 -0800374static int sWidth, sHeight;
375static int sNewWidth, sNewHeight;
376
377int android_showOpenglesWindow(void* window,
378 int wx,
379 int wy,
380 int ww,
381 int wh,
382 int fbw,
383 int fbh,
384 float dpr,
385 float rotation,
386 bool deleteExisting,
387 bool hideWindow) {
388 if (!sRenderer) {
389 return -1;
390 }
391 FBNativeWindowType win = (FBNativeWindowType)(uintptr_t)window;
392 bool success = sRenderer->showOpenGLSubwindow(win, wx, wy, ww, wh, fbw, fbh,
393 dpr, rotation, deleteExisting,
394 hideWindow);
395 sNewWidth = ww * dpr;
396 sNewHeight = wh * dpr;
397 return success ? 0 : -1;
398}
399
400void
401android_setOpenglesTranslation(float px, float py)
402{
403 if (sRenderer) {
404 sRenderer->setOpenGLDisplayTranslation(px, py);
405 }
406}
407
408void
409android_setOpenglesScreenMask(int width, int height, const unsigned char* rgbaData)
410{
411 if (sRenderer) {
412 sRenderer->setScreenMask(width, height, rgbaData);
413 }
414}
415
416int
417android_hideOpenglesWindow(void)
418{
419 if (!sRenderer) {
420 return -1;
421 }
422 bool success = sRenderer->destroyOpenGLSubwindow();
423 return success ? 0 : -1;
424}
425
426void
427android_redrawOpenglesWindow(void)
428{
429 if (sRenderer) {
430 sRenderer->repaintOpenGLDisplay();
431 }
432}
433
434bool
435android_hasGuestPostedAFrame(void)
436{
437 if (sRenderer) {
438 return sRenderer->hasGuestPostedAFrame();
439 }
440 return false;
441}
442
443void
444android_resetGuestPostedAFrame(void)
445{
446 if (sRenderer) {
447 sRenderer->resetGuestPostedAFrame();
448 }
449}
450
451static ScreenshotFunc sScreenshotFunc = nullptr;
452
453void android_registerScreenshotFunc(ScreenshotFunc f)
454{
455 sScreenshotFunc = f;
456}
457
458bool android_screenShot(const char* dirname, uint32_t displayId)
459{
460 if (sScreenshotFunc) {
461 return sScreenshotFunc(dirname, displayId);
462 }
463 return false;
464}
465
Jason Macnaked0c9e62023-03-30 15:58:24 -0700466const gfxstream::RendererPtr& android_getOpenglesRenderer() { return sRenderer; }
Joshua Duong9dfbd852022-11-14 13:12:59 -0800467
Joshua Duongc256a3c2023-05-09 08:14:24 -0700468void android_setOpenglesRenderer(gfxstream::RendererPtr* renderer) {
469 sRenderer = *renderer;
470}
471
Joshua Duong9dfbd852022-11-14 13:12:59 -0800472void android_onGuestGraphicsProcessCreate(uint64_t puid) {
473 if (sRenderer) {
474 sRenderer->onGuestGraphicsProcessCreate(puid);
475 }
476}
477
478void android_cleanupProcGLObjects(uint64_t puid) {
479 if (sRenderer) {
480 sRenderer->cleanupProcGLObjects(puid);
481 }
482}
483
484void android_cleanupProcGLObjectsAndWaitFinished(uint64_t puid) {
485 if (sRenderer) {
486 sRenderer->cleanupProcGLObjects(puid);
487 }
488}
489
490void android_waitForOpenglesProcessCleanup() {
491 if (sRenderer) {
492 sRenderer->waitForProcessCleanup();
493 }
494}
495
Joshua Duong9dfbd852022-11-14 13:12:59 -0800496struct AndroidVirtioGpuOps* android_getVirtioGpuOps() {
497 if (sRenderer) {
498 return sRenderer->getVirtioGpuOps();
499 }
500 return nullptr;
501}
502
503const void* android_getEGLDispatch() {
Jason Macnake70b8e32023-01-20 13:59:35 -0800504 if (sRenderer) {
505 return sRenderer->getEglDispatch();
506 }
507 return nullptr;
Joshua Duong9dfbd852022-11-14 13:12:59 -0800508}
509
510const void* android_getGLESv2Dispatch() {
Jason Macnake70b8e32023-01-20 13:59:35 -0800511 if (sRenderer) {
512 return sRenderer->getGles2Dispatch();
513 }
514 return nullptr;
Joshua Duong9dfbd852022-11-14 13:12:59 -0800515}
Lingfeng Yang66d96102021-07-30 16:01:15 -0700516
517void android_setVsyncHz(int vsyncHz) {
518 if (sRenderer) {
519 sRenderer->setVsyncHz(vsyncHz);
520 }
521}
Huan Songc3a1aeb2021-09-22 08:27:19 -0700522
523void android_setOpenglesDisplayConfigs(int configId, int w, int h, int dpiX,
524 int dpiY) {
525 if (sRenderer) {
526 sRenderer->setDisplayConfigs(configId, w, h, dpiX, dpiY);
527 }
528}
529
530void android_setOpenglesDisplayActiveConfig(int configId) {
531 if (sRenderer) {
532 sRenderer->setDisplayActiveConfig(configId);
533 }
534}