1 // Copyright (C) 2016 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 #include "RendererImpl.h"
15
16 #include <assert.h>
17
18 #include <algorithm>
19 #include <utility>
20 #include <variant>
21
22 #include "FrameBuffer.h"
23 #include "RenderChannelImpl.h"
24 #include "RenderThread.h"
25 #include "aemu/base/system/System.h"
26 #include "aemu/base/threads/WorkerThread.h"
27 #include "host-common/logging.h"
28 #include "snapshot/common.h"
29
30 #if GFXSTREAM_ENABLE_HOST_GLES
31 #include "gl/EmulatedEglFenceSync.h"
32 #endif
33
34 namespace gfxstream {
35
36 // kUseSubwindowThread is used to determine whether the RenderWindow should use
37 // a separate thread to manage its subwindow GL/GLES context.
38 // For now, this feature is disabled entirely for the following
39 // reasons:
40 //
41 // - It must be disabled on Windows at all times, otherwise the main window
42 // becomes unresponsive after a few seconds of user interaction (e.g. trying
43 // to move it over the desktop). Probably due to the subtle issues around
44 // input on this platform (input-queue is global, message-queue is
45 // per-thread). Also, this messes considerably the display of the
46 // main window when running the executable under Wine.
47 //
48 // - On Linux/XGL and OSX/Cocoa, this used to be necessary to avoid corruption
49 // issues with the GL state of the main window when using the SDL UI.
50 // After the switch to Qt, this is no longer necessary and may actually cause
51 // undesired interactions between the UI thread and the RenderWindow thread:
52 // for example, in a multi-monitor setup the context might be recreated when
53 // dragging the window between monitors, triggering a Qt-specific callback
54 // in the context of RenderWindow thread, which will become blocked on the UI
55 // thread, which may in turn be blocked on something else.
56 static const bool kUseSubwindowThread = false;
57
58 // This object manages the cleanup of guest process resources when the process
59 // exits. It runs the cleanup in a separate thread to never block the main
60 // render thread for a low-priority task.
61 class RendererImpl::ProcessCleanupThread {
62 public:
ProcessCleanupThread()63 ProcessCleanupThread()
64 : mCleanupWorker([](Cmd cmd) {
65 using android::base::WorkerProcessingResult;
66 struct {
67 WorkerProcessingResult operator()(CleanProcessResources resources) {
68 FrameBuffer::getFB()->cleanupProcGLObjects(resources.puid);
69 // resources.resource are destroyed automatically when going out of the scope.
70 return WorkerProcessingResult::Continue;
71 }
72 WorkerProcessingResult operator()(Exit) {
73 return WorkerProcessingResult::Stop;
74 }
75 } visitor;
76 return std::visit(visitor, std::move(cmd));
77 }) {
78 mCleanupWorker.start();
79 }
80
~ProcessCleanupThread()81 ~ProcessCleanupThread() {
82 mCleanupWorker.enqueue(Exit{});
83 }
84
cleanup(uint64_t processId,std::unique_ptr<ProcessResources> resource)85 void cleanup(uint64_t processId, std::unique_ptr<ProcessResources> resource) {
86 mCleanupWorker.enqueue(CleanProcessResources{
87 .puid = processId,
88 .resource = std::move(resource),
89 });
90 }
91
stop()92 void stop() {
93 mCleanupWorker.enqueue(Exit{});
94 mCleanupWorker.join();
95 }
96
waitForCleanup()97 void waitForCleanup() {
98 mCleanupWorker.waitQueuedItems();
99 }
100
101 private:
102 struct CleanProcessResources {
103 uint64_t puid;
104 std::unique_ptr<ProcessResources> resource;
105 };
106 struct Exit {};
107 using Cmd = std::variant<CleanProcessResources, Exit>;
108 DISALLOW_COPY_AND_ASSIGN(ProcessCleanupThread);
109
110 android::base::WorkerThread<Cmd> mCleanupWorker;
111 };
112
RendererImpl()113 RendererImpl::RendererImpl() {
114 mCleanupThread.reset(new ProcessCleanupThread());
115 }
116
~RendererImpl()117 RendererImpl::~RendererImpl() {
118 stop(true);
119 // We can't finish until the loader render thread has
120 // completed else can get a crash at the end of the destructor.
121 if (mLoaderRenderThread) {
122 mLoaderRenderThread->wait();
123 }
124 mRenderWindow.reset();
125 }
126
initialize(int width,int height,gfxstream::host::FeatureSet features,bool useSubWindow,bool egl2egl)127 bool RendererImpl::initialize(int width, int height, gfxstream::host::FeatureSet features,
128 bool useSubWindow, bool egl2egl) {
129 if (android::base::getEnvironmentVariable("ANDROID_EMUGL_VERBOSE") == "1") {
130 // base_enable_verbose_logs();
131 }
132
133 if (mRenderWindow) {
134 return false;
135 }
136
137 std::unique_ptr<RenderWindow> renderWindow(new RenderWindow(
138 width, height, features, kUseSubwindowThread, useSubWindow, egl2egl));
139 if (!renderWindow) {
140 ERR("Could not create rendering window class\n");
141 GL_LOG("Could not create rendering window class");
142 return false;
143 }
144 if (!renderWindow->isValid()) {
145 ERR("Could not initialize emulated framebuffer\n");
146 return false;
147 }
148
149 mRenderWindow = std::move(renderWindow);
150 GL_LOG("OpenGL renderer initialized successfully");
151
152 // This render thread won't do anything but will only preload resources
153 // for the real threads to start faster.
154 mLoaderRenderThread.reset(new RenderThread(nullptr));
155 mLoaderRenderThread->start();
156
157 return true;
158 }
159
stop(bool wait)160 void RendererImpl::stop(bool wait) {
161 android::base::AutoLock lock(mChannelsLock);
162 mStopped = true;
163 auto channels = std::move(mChannels);
164 lock.unlock();
165
166 if (const auto fb = FrameBuffer::getFB()) {
167 fb->setShuttingDown();
168 }
169 for (const auto& c : channels) {
170 c->stopFromHost();
171 }
172 // We're stopping the renderer, so there's no need to clean up resources
173 // of some pending processes: we'll destroy everything soon.
174 mCleanupThread->stop();
175
176 mStoppedChannels.insert(mStoppedChannels.end(),
177 std::make_move_iterator(channels.begin()),
178 std::make_move_iterator(channels.end()));
179
180 if (!wait) {
181 return;
182 }
183
184 // Each render channel is referenced in the corresponing pipe object, so
185 // even if we clear the |channels| vector they could still be alive
186 // for a while. This means we need to make sure to wait for render thread
187 // exit explicitly.
188 for (const auto& c : mStoppedChannels) {
189 c->renderThread()->wait();
190 }
191 mCleanupThread->waitForCleanup();
192 mStoppedChannels.clear();
193 }
194
finish()195 void RendererImpl::finish() {
196 {
197 android::base::AutoLock lock(mChannelsLock);
198 mRenderWindow->setPaused(true);
199 }
200 cleanupRenderThreads();
201 {
202 android::base::AutoLock lock(mChannelsLock);
203 mRenderWindow->setPaused(false);
204 }
205 }
206
cleanupRenderThreads()207 void RendererImpl::cleanupRenderThreads() {
208 android::base::AutoLock lock(mChannelsLock);
209 const auto channels = std::move(mChannels);
210 assert(mChannels.empty());
211 lock.unlock();
212 for (const auto& c : channels) {
213 // Please DO NOT notify the guest about this event (DO NOT call
214 // stopFromHost() ), because this is used to kill old threads when
215 // loading from a snapshot, and the newly loaded guest should not
216 // be notified for those behavior.
217 c->stop();
218 }
219 for (const auto& c : channels) {
220 c->renderThread()->wait();
221 }
222 }
223
waitForProcessCleanup()224 void RendererImpl::waitForProcessCleanup() {
225 mCleanupThread->waitForCleanup();
226 // Recreate it to make sure we've started from scratch and that we've
227 // finished all in-progress cleanups as well.
228 mCleanupThread.reset(new ProcessCleanupThread());
229 }
230
createRenderChannel(android::base::Stream * loadStream,uint32_t virtioGpuContextId)231 RenderChannelPtr RendererImpl::createRenderChannel(
232 android::base::Stream* loadStream, uint32_t virtioGpuContextId) {
233 const auto channel =
234 std::make_shared<RenderChannelImpl>(loadStream, virtioGpuContextId);
235 {
236 android::base::AutoLock lock(mChannelsLock);
237
238 if (mStopped) {
239 return nullptr;
240 }
241
242 // Clean up the stopped channels.
243 mChannels.erase(
244 std::remove_if(mChannels.begin(), mChannels.end(),
245 [](const std::shared_ptr<RenderChannelImpl>& c) {
246 return c->renderThread()->isFinished();
247 }),
248 mChannels.end());
249 mChannels.emplace_back(channel);
250
251 // Take the time to check if our loader thread is done as well.
252 if (mLoaderRenderThread && mLoaderRenderThread->isFinished()) {
253 mLoaderRenderThread->wait();
254 mLoaderRenderThread.reset();
255 }
256
257 GL_LOG("Started new RenderThread (total %" PRIu64 ") @%p",
258 static_cast<uint64_t>(mChannels.size()), channel->renderThread());
259 }
260
261 return channel;
262 }
263
addListener(FrameBufferChangeEventListener * listener)264 void RendererImpl::addListener(FrameBufferChangeEventListener* listener) {
265 mRenderWindow->addListener(listener);
266 }
267
removeListener(FrameBufferChangeEventListener * listener)268 void RendererImpl::removeListener(FrameBufferChangeEventListener* listener) {
269 mRenderWindow->removeListener(listener);
270 }
271
addressSpaceGraphicsConsumerCreate(struct asg_context context,android::base::Stream * loadStream,android::emulation::asg::ConsumerCallbacks callbacks,uint32_t contextId,uint32_t capsetId,std::optional<std::string> nameOpt)272 void* RendererImpl::addressSpaceGraphicsConsumerCreate(
273 struct asg_context context,
274 android::base::Stream* loadStream,
275 android::emulation::asg::ConsumerCallbacks callbacks,
276 uint32_t contextId, uint32_t capsetId,
277 std::optional<std::string> nameOpt) {
278 auto thread = new RenderThread(context, loadStream, callbacks, contextId,
279 capsetId, std::move(nameOpt));
280 thread->start();
281 android::base::AutoLock lock(mAddressSpaceRenderThreadLock);
282 mAddressSpaceRenderThreads.emplace(thread);
283 return (void*)thread;
284 }
285
addressSpaceGraphicsConsumerDestroy(void * consumer)286 void RendererImpl::addressSpaceGraphicsConsumerDestroy(void* consumer) {
287 RenderThread* thread = (RenderThread*)consumer;
288 {
289 android::base::AutoLock lock(mAddressSpaceRenderThreadLock);
290 mAddressSpaceRenderThreads.erase(thread);
291 }
292 thread->wait();
293 delete thread;
294 }
295
addressSpaceGraphicsConsumerPreSave(void * consumer)296 void RendererImpl::addressSpaceGraphicsConsumerPreSave(void* consumer) {
297 RenderThread* thread = (RenderThread*)consumer;
298 thread->pausePreSnapshot();
299 }
300
addressSpaceGraphicsConsumerSave(void * consumer,android::base::Stream * stream)301 void RendererImpl::addressSpaceGraphicsConsumerSave(void* consumer, android::base::Stream* stream) {
302 RenderThread* thread = (RenderThread*)consumer;
303 thread->save(stream);
304 }
305
addressSpaceGraphicsConsumerPostSave(void * consumer)306 void RendererImpl::addressSpaceGraphicsConsumerPostSave(void* consumer) {
307 RenderThread* thread = (RenderThread*)consumer;
308 thread->resume(true);
309 }
310
addressSpaceGraphicsConsumerRegisterPostLoadRenderThread(void * consumer)311 void RendererImpl::addressSpaceGraphicsConsumerRegisterPostLoadRenderThread(void* consumer) {
312 RenderThread* thread = (RenderThread*)consumer;
313 mAdditionalPostLoadRenderThreads.push_back(thread);
314 }
315
pauseAllPreSave()316 void RendererImpl::pauseAllPreSave() {
317 {
318 android::base::AutoLock lock(mChannelsLock);
319 if (mStopped) {
320 return;
321 }
322 for (const auto& c : mChannels) {
323 c->renderThread()->pausePreSnapshot();
324 }
325 }
326 {
327 android::base::AutoLock lock(mAddressSpaceRenderThreadLock);
328 for (const auto& thread : mAddressSpaceRenderThreads) {
329 thread->pausePreSnapshot();
330 }
331 }
332 waitForProcessCleanup();
333 }
334
resumeAll(bool waitForSave)335 void RendererImpl::resumeAll(bool waitForSave) {
336 {
337 android::base::AutoLock lock(mAddressSpaceRenderThreadLock);
338 for (const auto t : mAdditionalPostLoadRenderThreads) {
339 t->resume(waitForSave);
340 }
341 }
342 {
343 android::base::AutoLock lock(mChannelsLock);
344 if (mStopped) {
345 return;
346 }
347 for (const auto& c : mChannels) {
348 c->renderThread()->resume(waitForSave);
349 }
350 for (const auto& thread : mAddressSpaceRenderThreads) {
351 thread->resume(waitForSave);
352 }
353 mAdditionalPostLoadRenderThreads.clear();
354 }
355
356 repaintOpenGLDisplay();
357 }
358
save(android::base::Stream * stream,const android::snapshot::ITextureSaverPtr & textureSaver)359 void RendererImpl::save(android::base::Stream* stream,
360 const android::snapshot::ITextureSaverPtr& textureSaver) {
361 stream->putByte(mStopped);
362 if (mStopped) {
363 return;
364 }
365 auto fb = FrameBuffer::getFB();
366 assert(fb);
367 fb->onSave(stream, textureSaver);
368 }
369
load(android::base::Stream * stream,const android::snapshot::ITextureLoaderPtr & textureLoader)370 bool RendererImpl::load(android::base::Stream* stream,
371 const android::snapshot::ITextureLoaderPtr& textureLoader) {
372
373 #ifdef SNAPSHOT_PROFILE
374 android::base::System::Duration startTime =
375 android::base::System::get()->getUnixTimeUs();
376 #endif
377 waitForProcessCleanup();
378 #ifdef SNAPSHOT_PROFILE
379 printf("Previous session cleanup time: %lld ms\n",
380 (long long)(android::base::System::get()
381 ->getUnixTimeUs() -
382 startTime) /
383 1000);
384 #endif
385
386 mStopped = stream->getByte();
387 if (mStopped) {
388 return true;
389 }
390 auto fb = FrameBuffer::getFB();
391 assert(fb);
392
393 bool res = true;
394
395 res = fb->onLoad(stream, textureLoader);
396 #if GFXSTREAM_ENABLE_HOST_GLES
397 gl::EmulatedEglFenceSync::onLoad(stream);
398 #endif
399
400 return res;
401 }
402
fillGLESUsages(android_studio::EmulatorGLESUsages * usages)403 void RendererImpl::fillGLESUsages(android_studio::EmulatorGLESUsages* usages) {
404 auto fb = FrameBuffer::getFB();
405 #if GFXSTREAM_ENABLE_HOST_GLES
406 if (fb) fb->fillGLESUsages(usages);
407 #endif
408 }
409
getScreenshot(unsigned int nChannels,unsigned int * width,unsigned int * height,uint8_t * pixels,size_t * cPixels,int displayId=0,int desiredWidth=0,int desiredHeight=0,int desiredRotation=0,Rect rect={{0, 0}, {0, 0}})410 int RendererImpl::getScreenshot(unsigned int nChannels, unsigned int* width, unsigned int* height,
411 uint8_t* pixels, size_t* cPixels, int displayId = 0,
412 int desiredWidth = 0, int desiredHeight = 0,
413 int desiredRotation = 0, Rect rect = {{0, 0}, {0, 0}}) {
414 auto fb = FrameBuffer::getFB();
415 if (fb) {
416 return fb->getScreenshot(nChannels, width, height, pixels, cPixels,
417 displayId, desiredWidth, desiredHeight,
418 desiredRotation, rect);
419 }
420 *cPixels = 0;
421 return -1;
422 }
423
setMultiDisplay(uint32_t id,int32_t x,int32_t y,uint32_t w,uint32_t h,uint32_t dpi,bool add)424 void RendererImpl::setMultiDisplay(uint32_t id,
425 int32_t x,
426 int32_t y,
427 uint32_t w,
428 uint32_t h,
429 uint32_t dpi,
430 bool add) {
431 auto fb = FrameBuffer::getFB();
432 if (fb) {
433 if (add) {
434 fb->createDisplay(&id);
435 fb->setDisplayPose(id, x, y, w, h, dpi);
436 } else {
437 fb->destroyDisplay(id);
438 }
439 }
440 }
441
setMultiDisplayColorBuffer(uint32_t id,uint32_t cb)442 void RendererImpl::setMultiDisplayColorBuffer(uint32_t id, uint32_t cb) {
443 auto fb = FrameBuffer::getFB();
444 if (fb) {
445 fb->setDisplayColorBuffer(id, cb);
446 }
447 }
448
getHardwareStrings()449 RendererImpl::HardwareStrings RendererImpl::getHardwareStrings() {
450 assert(mRenderWindow);
451
452 const char* vendor = nullptr;
453 const char* renderer = nullptr;
454 const char* version = nullptr;
455 if (!mRenderWindow->getHardwareStrings(&vendor, &renderer, &version)) {
456 return {};
457 }
458 HardwareStrings res;
459 res.vendor = vendor ? vendor : "";
460 res.renderer = renderer ? renderer : "";
461 res.version = version ? version : "";
462 return res;
463 }
464
setPostCallback(RendererImpl::OnPostCallback onPost,void * context,bool useBgraReadback,uint32_t displayId)465 void RendererImpl::setPostCallback(RendererImpl::OnPostCallback onPost,
466 void* context,
467 bool useBgraReadback,
468 uint32_t displayId) {
469 assert(mRenderWindow);
470 mRenderWindow->setPostCallback(onPost, context, displayId, useBgraReadback);
471 }
472
asyncReadbackSupported()473 bool RendererImpl::asyncReadbackSupported() {
474 assert(mRenderWindow);
475 return mRenderWindow->asyncReadbackSupported();
476 }
477
478 RendererImpl::ReadPixelsCallback
getReadPixelsCallback()479 RendererImpl::getReadPixelsCallback() {
480 assert(mRenderWindow);
481 return mRenderWindow->getReadPixelsCallback();
482 }
483
484 RendererImpl::FlushReadPixelPipeline
getFlushReadPixelPipeline()485 RendererImpl::getFlushReadPixelPipeline() {
486 assert(mRenderWindow);
487 return mRenderWindow->getFlushReadPixelPipeline();
488 }
489
showOpenGLSubwindow(FBNativeWindowType window,int wx,int wy,int ww,int wh,int fbw,int fbh,float dpr,float zRot,bool deleteExisting,bool hideWindow)490 bool RendererImpl::showOpenGLSubwindow(FBNativeWindowType window,
491 int wx,
492 int wy,
493 int ww,
494 int wh,
495 int fbw,
496 int fbh,
497 float dpr,
498 float zRot,
499 bool deleteExisting,
500 bool hideWindow) {
501 assert(mRenderWindow);
502 return mRenderWindow->setupSubWindow(window, wx, wy, ww, wh, fbw, fbh, dpr,
503 zRot, deleteExisting, hideWindow);
504 }
505
destroyOpenGLSubwindow()506 bool RendererImpl::destroyOpenGLSubwindow() {
507 assert(mRenderWindow);
508 return mRenderWindow->removeSubWindow();
509 }
510
setOpenGLDisplayRotation(float zRot)511 void RendererImpl::setOpenGLDisplayRotation(float zRot) {
512 assert(mRenderWindow);
513 mRenderWindow->setRotation(zRot);
514 }
515
setOpenGLDisplayTranslation(float px,float py)516 void RendererImpl::setOpenGLDisplayTranslation(float px, float py) {
517 assert(mRenderWindow);
518 mRenderWindow->setTranslation(px, py);
519 }
520
repaintOpenGLDisplay()521 void RendererImpl::repaintOpenGLDisplay() {
522 assert(mRenderWindow);
523 mRenderWindow->repaint();
524 }
525
hasGuestPostedAFrame()526 bool RendererImpl::hasGuestPostedAFrame() {
527 if (mRenderWindow) {
528 return mRenderWindow->hasGuestPostedAFrame();
529 }
530 return false;
531 }
532
resetGuestPostedAFrame()533 void RendererImpl::resetGuestPostedAFrame() {
534 if (mRenderWindow) {
535 mRenderWindow->resetGuestPostedAFrame();
536 }
537 }
538
setScreenMask(int width,int height,const unsigned char * rgbaData)539 void RendererImpl::setScreenMask(int width, int height, const unsigned char* rgbaData) {
540 assert(mRenderWindow);
541 mRenderWindow->setScreenMask(width, height, rgbaData);
542 }
543
onGuestGraphicsProcessCreate(uint64_t puid)544 void RendererImpl::onGuestGraphicsProcessCreate(uint64_t puid) {
545 FrameBuffer::getFB()->createGraphicsProcessResources(puid);
546 }
547
cleanupProcGLObjects(uint64_t puid)548 void RendererImpl::cleanupProcGLObjects(uint64_t puid) {
549 std::unique_ptr<ProcessResources> resource =
550 FrameBuffer::getFB()->removeGraphicsProcessResources(puid);
551 mCleanupThread->cleanup(puid, std::move(resource));
552 }
553
554 static struct AndroidVirtioGpuOps sVirtioGpuOps = {
555 .create_buffer_with_handle =
__anon979e1a630402(uint64_t size, uint32_t handle) 556 [](uint64_t size, uint32_t handle) {
557 FrameBuffer::getFB()->createBufferWithHandle(size, handle);
558 },
559 .create_color_buffer_with_handle =
560 [](uint32_t width, uint32_t height, uint32_t format, uint32_t fwkFormat, uint32_t handle,
__anon979e1a630502(uint32_t width, uint32_t height, uint32_t format, uint32_t fwkFormat, uint32_t handle, bool linear) 561 bool linear) {
562 FrameBuffer::getFB()->createColorBufferWithHandle(
563 width, height, (GLenum)format, (FrameworkFormat)fwkFormat, handle, linear);
564 },
__anon979e1a630602(uint32_t handle) 565 .open_color_buffer = [](uint32_t handle) { FrameBuffer::getFB()->openColorBuffer(handle); },
__anon979e1a630702(uint32_t handle) 566 .close_buffer = [](uint32_t handle) { FrameBuffer::getFB()->closeBuffer(handle); },
__anon979e1a630802(uint32_t handle) 567 .close_color_buffer = [](uint32_t handle) { FrameBuffer::getFB()->closeColorBuffer(handle); },
568 .update_buffer =
__anon979e1a630902(uint32_t handle, uint64_t offset, uint64_t size, void* bytes) 569 [](uint32_t handle, uint64_t offset, uint64_t size, void* bytes) {
570 FrameBuffer::getFB()->updateBuffer(handle, offset, size, bytes);
571 },
572 .update_color_buffer =
573 [](uint32_t handle, int x, int y, int width, int height, uint32_t format, uint32_t type,
__anon979e1a630a02(uint32_t handle, int x, int y, int width, int height, uint32_t format, uint32_t type, void* pixels) 574 void* pixels) {
575 FrameBuffer::getFB()->updateColorBuffer(handle, x, y, width, height, format, type,
576 pixels);
577 },
578 .read_buffer =
__anon979e1a630b02(uint32_t handle, uint64_t offset, uint64_t size, void* bytes) 579 [](uint32_t handle, uint64_t offset, uint64_t size, void* bytes) {
580 FrameBuffer::getFB()->readBuffer(handle, offset, size, bytes);
581 },
582 .read_color_buffer =
583 [](uint32_t handle, int x, int y, int width, int height, uint32_t format, uint32_t type,
__anon979e1a630c02(uint32_t handle, int x, int y, int width, int height, uint32_t format, uint32_t type, void* pixels) 584 void* pixels) {
585 FrameBuffer::getFB()->readColorBuffer(handle, x, y, width, height, format, type,
586 pixels);
587 },
588 .read_color_buffer_yuv =
589 [](uint32_t handle, int x, int y, int width, int height, void* pixels,
__anon979e1a630d02(uint32_t handle, int x, int y, int width, int height, void* pixels, uint32_t pixels_size) 590 uint32_t pixels_size) {
591 FrameBuffer::getFB()->readColorBufferYUV(handle, x, y, width, height, pixels,
592 pixels_size);
593 },
__anon979e1a630e02(uint32_t handle) 594 .post_color_buffer = [](uint32_t handle) { FrameBuffer::getFB()->post(handle); },
595 .async_post_color_buffer =
__anon979e1a630f02(uint32_t handle, CpuCompletionCallback cb) 596 [](uint32_t handle, CpuCompletionCallback cb) {
597 FrameBuffer::getFB()->postWithCallback(handle, cb);
598 },
__anon979e1a631002() 599 .repost = []() { FrameBuffer::getFB()->repost(); },
600 #if GFXSTREAM_ENABLE_HOST_GLES
601 .create_yuv_textures =
__anon979e1a631102(uint32_t type, uint32_t count, int width, int height, uint32_t* output) 602 [](uint32_t type, uint32_t count, int width, int height, uint32_t* output) {
603 FrameBuffer::getFB()->createYUVTextures(type, count, width, height, output);
604 },
605 .destroy_yuv_textures =
__anon979e1a631202(uint32_t type, uint32_t count, uint32_t* textures) 606 [](uint32_t type, uint32_t count, uint32_t* textures) {
607 FrameBuffer::getFB()->destroyYUVTextures(type, count, textures);
608 },
609 .update_yuv_textures =
__anon979e1a631302(uint32_t type, uint32_t* textures, void* privData, void* func) 610 [](uint32_t type, uint32_t* textures, void* privData, void* func) {
611 FrameBuffer::getFB()->updateYUVTextures(type, textures, privData, func);
612 },
613 .swap_textures_and_update_color_buffer =
614 [](uint32_t colorbufferhandle, int x, int y, int width, int height, uint32_t format,
__anon979e1a631402(uint32_t colorbufferhandle, int x, int y, int width, int height, uint32_t format, uint32_t type, uint32_t texture_type, uint32_t* textures, void* metadata) 615 uint32_t type, uint32_t texture_type, uint32_t* textures, void* metadata) {
616 FrameBuffer::getFB()->swapTexturesAndUpdateColorBuffer(
617 colorbufferhandle, x, y, width, height, format, type, texture_type, textures);
618 },
619 #endif
620 .get_last_posted_color_buffer =
__anon979e1a631502() 621 []() { return FrameBuffer::getFB()->getLastPostedColorBuffer(); },
622 #if GFXSTREAM_ENABLE_HOST_GLES
623 .bind_color_buffer_to_texture =
__anon979e1a631602(uint32_t handle) 624 [](uint32_t handle) { FrameBuffer::getFB()->bindColorBufferToTexture2(handle); },
__anon979e1a631702() 625 .get_global_egl_context = []() { return FrameBuffer::getFB()->getGlobalEGLContext(); },
__anon979e1a631802(uint64_t eglsync) 626 .wait_for_gpu = [](uint64_t eglsync) { FrameBuffer::getFB()->waitForGpu(eglsync); },
627 #endif
628 .wait_for_gpu_vulkan =
__anon979e1a631902(uint64_t device, uint64_t fence) 629 [](uint64_t device, uint64_t fence) {
630 FrameBuffer::getFB()->waitForGpuVulkan(device, fence);
631 },
632 .set_guest_managed_color_buffer_lifetime =
__anon979e1a631a02(bool guestManaged) 633 [](bool guestManaged) {
634 FrameBuffer::getFB()->setGuestManagedColorBufferLifetime(guestManaged);
635 },
636 #if GFXSTREAM_ENABLE_HOST_GLES
637 .async_wait_for_gpu_with_cb =
__anon979e1a631b02(uint64_t eglsync, FenceCompletionCallback cb) 638 [](uint64_t eglsync, FenceCompletionCallback cb) {
639 FrameBuffer::getFB()->asyncWaitForGpuWithCb(eglsync, cb);
640 },
641 #endif
642 .async_wait_for_gpu_vulkan_with_cb =
__anon979e1a631c02(uint64_t device, uint64_t fence, FenceCompletionCallback cb) 643 [](uint64_t device, uint64_t fence, FenceCompletionCallback cb) {
644 FrameBuffer::getFB()->asyncWaitForGpuVulkanWithCb(device, fence, cb);
645 },
646 .async_wait_for_gpu_vulkan_qsri_with_cb =
__anon979e1a631d02(uint64_t image, FenceCompletionCallback cb) 647 [](uint64_t image, FenceCompletionCallback cb) {
648 FrameBuffer::getFB()->asyncWaitForGpuVulkanQsriWithCb(image, cb);
649 },
650 .wait_for_gpu_vulkan_qsri =
__anon979e1a631e02(uint64_t image) 651 [](uint64_t image) { FrameBuffer::getFB()->waitForGpuVulkanQsri(image); },
652 .update_color_buffer_from_framework_format =
653 [](uint32_t handle, int x, int y, int width, int height, uint32_t fwkFormat,
__anon979e1a631f02(uint32_t handle, int x, int y, int width, int height, uint32_t fwkFormat, uint32_t format, uint32_t type, void* pixels, void* pMetadata) 654 uint32_t format, uint32_t type, void* pixels, void* pMetadata) {
655 FrameBuffer::getFB()->updateColorBufferFromFrameworkFormat(
656 handle, x, y, width, height, (FrameworkFormat)fwkFormat, format, type, pixels,
657 pMetadata);
658 },
659 .platform_import_resource =
__anon979e1a632002(uint32_t handle, uint32_t info, void* resource) 660 [](uint32_t handle, uint32_t info, void* resource) {
661 return FrameBuffer::getFB()->platformImportResource(handle, info, resource);
662 },
663 .platform_resource_info =
__anon979e1a632102(uint32_t handle, int32_t* width, int32_t* height, int32_t* internal_format) 664 [](uint32_t handle, int32_t* width, int32_t* height, int32_t* internal_format) {
665 return FrameBuffer::getFB()->getColorBufferInfo(handle, width, height, internal_format);
666 },
667 #if GFXSTREAM_ENABLE_HOST_GLES
668 .platform_create_shared_egl_context =
__anon979e1a632202() 669 []() { return FrameBuffer::getFB()->platformCreateSharedEglContext(); },
670 .platform_destroy_shared_egl_context =
__anon979e1a632302(void* context) 671 [](void* context) {
672 return FrameBuffer::getFB()->platformDestroySharedEglContext(context);
673 },
674 #endif
675 };
676
getVirtioGpuOps()677 struct AndroidVirtioGpuOps* RendererImpl::getVirtioGpuOps() {
678 return &sVirtioGpuOps;
679 }
680
snapshotOperationCallback(int op,int stage)681 void RendererImpl::snapshotOperationCallback(int op, int stage) {
682 using namespace android::snapshot;
683 switch (op) {
684 case SNAPSHOTTER_OPERATION_LOAD:
685 if (stage == SNAPSHOTTER_STAGE_START) {
686 #ifdef SNAPSHOT_PROFILE
687 android::base::System::Duration startTime =
688 android::base::System::get()->getUnixTimeUs();
689 #endif
690 mRenderWindow->setPaused(true);
691 cleanupRenderThreads();
692 #ifdef SNAPSHOT_PROFILE
693 printf("Previous session suspend time: %lld ms\n",
694 (long long)(android::base::System::get()
695 ->getUnixTimeUs() -
696 startTime) /
697 1000);
698 #endif
699 }
700 if (stage == SNAPSHOTTER_STAGE_END) {
701 mRenderWindow->setPaused(false);
702 }
703 break;
704 default:
705 break;
706 }
707 }
708
setVsyncHz(int vsyncHz)709 void RendererImpl::setVsyncHz(int vsyncHz) {
710 if (mRenderWindow) {
711 mRenderWindow->setVsyncHz(vsyncHz);
712 }
713 }
714
setDisplayConfigs(int configId,int w,int h,int dpiX,int dpiY)715 void RendererImpl::setDisplayConfigs(int configId, int w, int h,
716 int dpiX, int dpiY) {
717 if (mRenderWindow) {
718 mRenderWindow->setDisplayConfigs(configId, w, h, dpiX, dpiY);
719 }
720 }
721
setDisplayActiveConfig(int configId)722 void RendererImpl::setDisplayActiveConfig(int configId) {
723 if (mRenderWindow) {
724 mRenderWindow->setDisplayActiveConfig(configId);
725 }
726 }
727
getEglDispatch()728 const void* RendererImpl::getEglDispatch() {
729 #if GFXSTREAM_ENABLE_HOST_GLES
730 return FrameBuffer::getFB()->getEglDispatch();
731 #else
732 return nullptr;
733 #endif
734 }
735
getGles2Dispatch()736 const void* RendererImpl::getGles2Dispatch() {
737 #if GFXSTREAM_ENABLE_HOST_GLES
738 return FrameBuffer::getFB()->getGles2Dispatch();
739 #else
740 return nullptr;
741 #endif
742 }
743
744 } // namespace gfxstream
745