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 #ifdef CONFIG_AEMU
130     if (android::base::getEnvironmentVariable("ANDROID_EMUGL_VERBOSE") == "1") {
131         set_gfxstream_enable_verbose_logs();
132     }
133     if (android::base::getEnvironmentVariable("ANDROID_EMUGL_LOG_COLORS") == "1") {
134         set_gfxstream_enable_log_colors();
135     }
136 #endif
137 
138     if (mRenderWindow) {
139         return false;
140     }
141 
142     std::unique_ptr<RenderWindow> renderWindow(new RenderWindow(
143             width, height, features, kUseSubwindowThread, useSubWindow, egl2egl));
144     if (!renderWindow) {
145         ERR("Could not create rendering window class\n");
146         GL_LOG("Could not create rendering window class");
147         return false;
148     }
149     if (!renderWindow->isValid()) {
150         ERR("Could not initialize emulated framebuffer\n");
151         return false;
152     }
153 
154     mRenderWindow = std::move(renderWindow);
155     GL_LOG("OpenGL renderer initialized successfully");
156 
157     // This render thread won't do anything but will only preload resources
158     // for the real threads to start faster.
159     mLoaderRenderThread.reset(new RenderThread(nullptr));
160     mLoaderRenderThread->start();
161 
162     return true;
163 }
164 
stop(bool wait)165 void RendererImpl::stop(bool wait) {
166     android::base::AutoLock lock(mChannelsLock);
167     mStopped = true;
168     auto channels = std::move(mChannels);
169     lock.unlock();
170 
171     if (const auto fb = FrameBuffer::getFB()) {
172         fb->setShuttingDown();
173     }
174     for (const auto& c : channels) {
175         c->stopFromHost();
176     }
177     // We're stopping the renderer, so there's no need to clean up resources
178     // of some pending processes: we'll destroy everything soon.
179     mCleanupThread->stop();
180 
181     mStoppedChannels.insert(mStoppedChannels.end(),
182                             std::make_move_iterator(channels.begin()),
183                             std::make_move_iterator(channels.end()));
184 
185     if (!wait) {
186         return;
187     }
188 
189     // Each render channel is referenced in the corresponing pipe object, so
190     // even if we clear the |channels| vector they could still be alive
191     // for a while. This means we need to make sure to wait for render thread
192     // exit explicitly.
193     for (const auto& c : mStoppedChannels) {
194         c->renderThread()->wait();
195     }
196     mCleanupThread->waitForCleanup();
197     mStoppedChannels.clear();
198 }
199 
finish()200 void RendererImpl::finish() {
201     {
202         android::base::AutoLock lock(mChannelsLock);
203         mRenderWindow->setPaused(true);
204     }
205     cleanupRenderThreads();
206     {
207         android::base::AutoLock lock(mChannelsLock);
208         mRenderWindow->setPaused(false);
209     }
210 }
211 
cleanupRenderThreads()212 void RendererImpl::cleanupRenderThreads() {
213     android::base::AutoLock lock(mChannelsLock);
214     const auto channels = std::move(mChannels);
215     assert(mChannels.empty());
216     lock.unlock();
217     for (const auto& c : channels) {
218         // Please DO NOT notify the guest about this event (DO NOT call
219         // stopFromHost() ), because this is used to kill old threads when
220         // loading from a snapshot, and the newly loaded guest should not
221         // be notified for those behavior.
222         c->stop();
223     }
224     for (const auto& c : channels) {
225         c->renderThread()->wait();
226     }
227 }
228 
waitForProcessCleanup()229 void RendererImpl::waitForProcessCleanup() {
230     mCleanupThread->waitForCleanup();
231     // Recreate it to make sure we've started from scratch and that we've
232     // finished all in-progress cleanups as well.
233     mCleanupThread.reset(new ProcessCleanupThread());
234 }
235 
createRenderChannel(android::base::Stream * loadStream,uint32_t virtioGpuContextId)236 RenderChannelPtr RendererImpl::createRenderChannel(
237         android::base::Stream* loadStream, uint32_t virtioGpuContextId) {
238     const auto channel =
239         std::make_shared<RenderChannelImpl>(loadStream, virtioGpuContextId);
240     {
241         android::base::AutoLock lock(mChannelsLock);
242 
243         if (mStopped) {
244             return nullptr;
245         }
246 
247         // Clean up the stopped channels.
248         mChannels.erase(
249                 std::remove_if(mChannels.begin(), mChannels.end(),
250                                [](const std::shared_ptr<RenderChannelImpl>& c) {
251                                    return c->renderThread()->isFinished();
252                                }),
253                 mChannels.end());
254         mChannels.emplace_back(channel);
255 
256         // Take the time to check if our loader thread is done as well.
257         if (mLoaderRenderThread && mLoaderRenderThread->isFinished()) {
258             mLoaderRenderThread->wait();
259             mLoaderRenderThread.reset();
260         }
261 
262         GL_LOG("Started new RenderThread (total %" PRIu64 ") @%p",
263                static_cast<uint64_t>(mChannels.size()), channel->renderThread());
264     }
265 
266     return channel;
267 }
268 
addListener(FrameBufferChangeEventListener * listener)269 void RendererImpl::addListener(FrameBufferChangeEventListener* listener) {
270     mRenderWindow->addListener(listener);
271 }
272 
removeListener(FrameBufferChangeEventListener * listener)273 void RendererImpl::removeListener(FrameBufferChangeEventListener* listener) {
274     mRenderWindow->removeListener(listener);
275 }
276 
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)277 void* RendererImpl::addressSpaceGraphicsConsumerCreate(
278     struct asg_context context,
279     android::base::Stream* loadStream,
280     android::emulation::asg::ConsumerCallbacks callbacks,
281     uint32_t contextId, uint32_t capsetId,
282     std::optional<std::string> nameOpt) {
283     auto thread = new RenderThread(context, loadStream, callbacks, contextId,
284                                    capsetId, std::move(nameOpt));
285     thread->start();
286     android::base::AutoLock lock(mAddressSpaceRenderThreadLock);
287     mAddressSpaceRenderThreads.emplace(thread);
288     return (void*)thread;
289 }
290 
addressSpaceGraphicsConsumerDestroy(void * consumer)291 void RendererImpl::addressSpaceGraphicsConsumerDestroy(void* consumer) {
292     RenderThread* thread = (RenderThread*)consumer;
293     {
294         android::base::AutoLock lock(mAddressSpaceRenderThreadLock);
295         mAddressSpaceRenderThreads.erase(thread);
296     }
297     thread->wait();
298     delete thread;
299 }
300 
addressSpaceGraphicsConsumerPreSave(void * consumer)301 void RendererImpl::addressSpaceGraphicsConsumerPreSave(void* consumer) {
302     RenderThread* thread = (RenderThread*)consumer;
303     thread->pausePreSnapshot();
304 }
305 
addressSpaceGraphicsConsumerSave(void * consumer,android::base::Stream * stream)306 void RendererImpl::addressSpaceGraphicsConsumerSave(void* consumer, android::base::Stream* stream) {
307     RenderThread* thread = (RenderThread*)consumer;
308     thread->save(stream);
309 }
310 
addressSpaceGraphicsConsumerPostSave(void * consumer)311 void RendererImpl::addressSpaceGraphicsConsumerPostSave(void* consumer) {
312     RenderThread* thread = (RenderThread*)consumer;
313     thread->resume(true);
314 }
315 
addressSpaceGraphicsConsumerRegisterPostLoadRenderThread(void * consumer)316 void RendererImpl::addressSpaceGraphicsConsumerRegisterPostLoadRenderThread(void* consumer) {
317     RenderThread* thread = (RenderThread*)consumer;
318     mAdditionalPostLoadRenderThreads.push_back(thread);
319 }
320 
pauseAllPreSave()321 void RendererImpl::pauseAllPreSave() {
322     {
323         android::base::AutoLock lock(mChannelsLock);
324         if (mStopped) {
325             return;
326         }
327         for (const auto& c : mChannels) {
328             c->renderThread()->pausePreSnapshot();
329         }
330     }
331     {
332         android::base::AutoLock lock(mAddressSpaceRenderThreadLock);
333         for (const auto& thread : mAddressSpaceRenderThreads) {
334             thread->pausePreSnapshot();
335         }
336     }
337     waitForProcessCleanup();
338 }
339 
resumeAll(bool waitForSave)340 void RendererImpl::resumeAll(bool waitForSave) {
341     {
342         android::base::AutoLock lock(mAddressSpaceRenderThreadLock);
343         for (const auto t : mAdditionalPostLoadRenderThreads) {
344             t->resume(waitForSave);
345         }
346     }
347     {
348         android::base::AutoLock lock(mChannelsLock);
349         if (mStopped) {
350             return;
351         }
352         for (const auto& c : mChannels) {
353             c->renderThread()->resume(waitForSave);
354         }
355         for (const auto& thread : mAddressSpaceRenderThreads) {
356             thread->resume(waitForSave);
357         }
358         mAdditionalPostLoadRenderThreads.clear();
359     }
360 
361     repaintOpenGLDisplay();
362 }
363 
save(android::base::Stream * stream,const android::snapshot::ITextureSaverPtr & textureSaver)364 void RendererImpl::save(android::base::Stream* stream,
365                         const android::snapshot::ITextureSaverPtr& textureSaver) {
366     stream->putByte(mStopped);
367     if (mStopped) {
368         return;
369     }
370     auto fb = FrameBuffer::getFB();
371     assert(fb);
372     fb->onSave(stream, textureSaver);
373 }
374 
load(android::base::Stream * stream,const android::snapshot::ITextureLoaderPtr & textureLoader)375 bool RendererImpl::load(android::base::Stream* stream,
376                         const android::snapshot::ITextureLoaderPtr& textureLoader) {
377 
378 #ifdef SNAPSHOT_PROFILE
379     android::base::System::Duration startTime =
380             android::base::System::get()->getUnixTimeUs();
381 #endif
382     waitForProcessCleanup();
383 #ifdef SNAPSHOT_PROFILE
384     printf("Previous session cleanup time: %lld ms\n",
385            (long long)(android::base::System::get()
386                                ->getUnixTimeUs() -
387                        startTime) /
388                    1000);
389 #endif
390 
391     mStopped = stream->getByte();
392     if (mStopped) {
393         return true;
394     }
395     auto fb = FrameBuffer::getFB();
396     assert(fb);
397     return fb->onLoad(stream, textureLoader);
398 }
399 
fillGLESUsages(android_studio::EmulatorGLESUsages * usages)400 void RendererImpl::fillGLESUsages(android_studio::EmulatorGLESUsages* usages) {
401     auto fb = FrameBuffer::getFB();
402 #if GFXSTREAM_ENABLE_HOST_GLES
403     if (fb) fb->fillGLESUsages(usages);
404 #endif
405 }
406 
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}})407 int RendererImpl::getScreenshot(unsigned int nChannels, unsigned int* width, unsigned int* height,
408                                 uint8_t* pixels, size_t* cPixels, int displayId = 0,
409                                 int desiredWidth = 0, int desiredHeight = 0,
410                                 int desiredRotation = 0, Rect rect = {{0, 0}, {0, 0}}) {
411     auto fb = FrameBuffer::getFB();
412     if (fb) {
413         return fb->getScreenshot(nChannels, width, height, pixels, cPixels,
414                                  displayId, desiredWidth, desiredHeight,
415                                  desiredRotation, rect);
416     }
417     *cPixels = 0;
418     return -1;
419 }
420 
setMultiDisplay(uint32_t id,int32_t x,int32_t y,uint32_t w,uint32_t h,uint32_t dpi,bool add)421 void RendererImpl::setMultiDisplay(uint32_t id,
422                                    int32_t x,
423                                    int32_t y,
424                                    uint32_t w,
425                                    uint32_t h,
426                                    uint32_t dpi,
427                                    bool add) {
428     auto fb = FrameBuffer::getFB();
429     if (fb) {
430         if (add) {
431             fb->createDisplay(&id);
432             fb->setDisplayPose(id, x, y, w, h, dpi);
433         } else {
434             fb->destroyDisplay(id);
435         }
436     }
437 }
438 
setMultiDisplayColorBuffer(uint32_t id,uint32_t cb)439 void RendererImpl::setMultiDisplayColorBuffer(uint32_t id, uint32_t cb) {
440     auto fb = FrameBuffer::getFB();
441     if (fb) {
442         fb->setDisplayColorBuffer(id, cb);
443     }
444 }
445 
getHardwareStrings()446 RendererImpl::HardwareStrings RendererImpl::getHardwareStrings() {
447     assert(mRenderWindow);
448 
449     const char* vendor = nullptr;
450     const char* renderer = nullptr;
451     const char* version = nullptr;
452     if (!mRenderWindow->getHardwareStrings(&vendor, &renderer, &version)) {
453         return {};
454     }
455     HardwareStrings res;
456     res.vendor = vendor ? vendor : "";
457     res.renderer = renderer ? renderer : "";
458     res.version = version ? version : "";
459     return res;
460 }
461 
setPostCallback(RendererImpl::OnPostCallback onPost,void * context,bool useBgraReadback,uint32_t displayId)462 void RendererImpl::setPostCallback(RendererImpl::OnPostCallback onPost,
463                                    void* context,
464                                    bool useBgraReadback,
465                                    uint32_t displayId) {
466     assert(mRenderWindow);
467     mRenderWindow->setPostCallback(onPost, context, displayId, useBgraReadback);
468 }
469 
asyncReadbackSupported()470 bool RendererImpl::asyncReadbackSupported() {
471     assert(mRenderWindow);
472     return mRenderWindow->asyncReadbackSupported();
473 }
474 
475 RendererImpl::ReadPixelsCallback
getReadPixelsCallback()476 RendererImpl::getReadPixelsCallback() {
477     assert(mRenderWindow);
478     return mRenderWindow->getReadPixelsCallback();
479 }
480 
481 RendererImpl::FlushReadPixelPipeline
getFlushReadPixelPipeline()482 RendererImpl::getFlushReadPixelPipeline() {
483     assert(mRenderWindow);
484     return mRenderWindow->getFlushReadPixelPipeline();
485 }
486 
showOpenGLSubwindow(FBNativeWindowType window,int wx,int wy,int ww,int wh,int fbw,int fbh,float dpr,float zRot,bool deleteExisting,bool hideWindow)487 bool RendererImpl::showOpenGLSubwindow(FBNativeWindowType window,
488                                        int wx,
489                                        int wy,
490                                        int ww,
491                                        int wh,
492                                        int fbw,
493                                        int fbh,
494                                        float dpr,
495                                        float zRot,
496                                        bool deleteExisting,
497                                        bool hideWindow) {
498     assert(mRenderWindow);
499     return mRenderWindow->setupSubWindow(window, wx, wy, ww, wh, fbw, fbh, dpr,
500                                          zRot, deleteExisting, hideWindow);
501 }
502 
destroyOpenGLSubwindow()503 bool RendererImpl::destroyOpenGLSubwindow() {
504     assert(mRenderWindow);
505     return mRenderWindow->removeSubWindow();
506 }
507 
setOpenGLDisplayRotation(float zRot)508 void RendererImpl::setOpenGLDisplayRotation(float zRot) {
509     assert(mRenderWindow);
510     mRenderWindow->setRotation(zRot);
511 }
512 
setOpenGLDisplayTranslation(float px,float py)513 void RendererImpl::setOpenGLDisplayTranslation(float px, float py) {
514     assert(mRenderWindow);
515     mRenderWindow->setTranslation(px, py);
516 }
517 
repaintOpenGLDisplay()518 void RendererImpl::repaintOpenGLDisplay() {
519     assert(mRenderWindow);
520     mRenderWindow->repaint();
521 }
522 
hasGuestPostedAFrame()523 bool RendererImpl::hasGuestPostedAFrame() {
524     if (mRenderWindow) {
525         return mRenderWindow->hasGuestPostedAFrame();
526     }
527     return false;
528 }
529 
resetGuestPostedAFrame()530 void RendererImpl::resetGuestPostedAFrame() {
531     if (mRenderWindow) {
532         mRenderWindow->resetGuestPostedAFrame();
533     }
534 }
535 
setScreenMask(int width,int height,const unsigned char * rgbaData)536 void RendererImpl::setScreenMask(int width, int height, const unsigned char* rgbaData) {
537     assert(mRenderWindow);
538     mRenderWindow->setScreenMask(width, height, rgbaData);
539 }
540 
onGuestGraphicsProcessCreate(uint64_t puid)541 void RendererImpl::onGuestGraphicsProcessCreate(uint64_t puid) {
542     FrameBuffer::getFB()->createGraphicsProcessResources(puid);
543 }
544 
cleanupProcGLObjects(uint64_t puid)545 void RendererImpl::cleanupProcGLObjects(uint64_t puid) {
546     std::unique_ptr<ProcessResources> resource =
547         FrameBuffer::getFB()->removeGraphicsProcessResources(puid);
548     mCleanupThread->cleanup(puid, std::move(resource));
549 }
550 
551 static struct AndroidVirtioGpuOps sVirtioGpuOps = {
552     .create_buffer_with_handle =
__anona8dbb0c50402(uint64_t size, uint32_t handle) 553         [](uint64_t size, uint32_t handle) {
554             FrameBuffer::getFB()->createBufferWithHandle(size, handle);
555         },
556     .create_color_buffer_with_handle =
557         [](uint32_t width, uint32_t height, uint32_t format, uint32_t fwkFormat, uint32_t handle,
__anona8dbb0c50502(uint32_t width, uint32_t height, uint32_t format, uint32_t fwkFormat, uint32_t handle, bool linear) 558            bool linear) {
559             FrameBuffer::getFB()->createColorBufferWithHandle(
560                 width, height, (GLenum)format, (FrameworkFormat)fwkFormat, handle, linear);
561         },
__anona8dbb0c50602(uint32_t handle) 562     .open_color_buffer = [](uint32_t handle) { FrameBuffer::getFB()->openColorBuffer(handle); },
__anona8dbb0c50702(uint32_t handle) 563     .close_buffer = [](uint32_t handle) { FrameBuffer::getFB()->closeBuffer(handle); },
__anona8dbb0c50802(uint32_t handle) 564     .close_color_buffer = [](uint32_t handle) { FrameBuffer::getFB()->closeColorBuffer(handle); },
565     .update_buffer =
__anona8dbb0c50902(uint32_t handle, uint64_t offset, uint64_t size, void* bytes) 566         [](uint32_t handle, uint64_t offset, uint64_t size, void* bytes) {
567             FrameBuffer::getFB()->updateBuffer(handle, offset, size, bytes);
568         },
569     .update_color_buffer =
570         [](uint32_t handle, int x, int y, int width, int height, uint32_t format, uint32_t type,
__anona8dbb0c50a02(uint32_t handle, int x, int y, int width, int height, uint32_t format, uint32_t type, void* pixels) 571            void* pixels) {
572             FrameBuffer::getFB()->updateColorBuffer(handle, x, y, width, height, format, type,
573                                                     pixels);
574         },
575     .read_buffer =
__anona8dbb0c50b02(uint32_t handle, uint64_t offset, uint64_t size, void* bytes) 576         [](uint32_t handle, uint64_t offset, uint64_t size, void* bytes) {
577             FrameBuffer::getFB()->readBuffer(handle, offset, size, bytes);
578         },
579     .read_color_buffer =
580         [](uint32_t handle, int x, int y, int width, int height, uint32_t format, uint32_t type,
__anona8dbb0c50c02(uint32_t handle, int x, int y, int width, int height, uint32_t format, uint32_t type, void* pixels) 581            void* pixels) {
582             FrameBuffer::getFB()->readColorBuffer(handle, x, y, width, height, format, type,
583                                                   pixels);
584         },
585     .read_color_buffer2 =
586         [](uint32_t handle, int x, int y, int width, int height, uint32_t format, uint32_t type,
__anona8dbb0c50d02(uint32_t handle, int x, int y, int width, int height, uint32_t format, uint32_t type, void* pixels, uint64_t pixels_size) 587            void* pixels, uint64_t pixels_size) {
588             FrameBuffer::getFB()->readColorBuffer(handle, x, y, width, height, format, type,
589                                                   pixels, pixels_size);
590         },
591     .read_color_buffer_yuv =
592         [](uint32_t handle, int x, int y, int width, int height, void* pixels,
__anona8dbb0c50e02(uint32_t handle, int x, int y, int width, int height, void* pixels, uint32_t pixels_size) 593            uint32_t pixels_size) {
594             FrameBuffer::getFB()->readColorBufferYUV(handle, x, y, width, height, pixels,
595                                                      pixels_size);
596         },
__anona8dbb0c50f02(uint32_t handle) 597     .post_color_buffer = [](uint32_t handle) { FrameBuffer::getFB()->post(handle); },
598     .async_post_color_buffer =
__anona8dbb0c51002(uint32_t handle, CpuCompletionCallback cb) 599         [](uint32_t handle, CpuCompletionCallback cb) {
600             FrameBuffer::getFB()->postWithCallback(handle, cb);
601         },
__anona8dbb0c51102() 602     .repost = []() { FrameBuffer::getFB()->repost(); },
603 #if GFXSTREAM_ENABLE_HOST_GLES
604     .create_yuv_textures =
__anona8dbb0c51202(uint32_t type, uint32_t count, int width, int height, uint32_t* output) 605         [](uint32_t type, uint32_t count, int width, int height, uint32_t* output) {
606             FrameBuffer::getFB()->createYUVTextures(type, count, width, height, output);
607         },
608     .destroy_yuv_textures =
__anona8dbb0c51302(uint32_t type, uint32_t count, uint32_t* textures) 609         [](uint32_t type, uint32_t count, uint32_t* textures) {
610             FrameBuffer::getFB()->destroyYUVTextures(type, count, textures);
611         },
612     .update_yuv_textures =
__anona8dbb0c51402(uint32_t type, uint32_t* textures, void* privData, void* func) 613         [](uint32_t type, uint32_t* textures, void* privData, void* func) {
614             FrameBuffer::getFB()->updateYUVTextures(type, textures, privData, func);
615         },
616     .swap_textures_and_update_color_buffer =
617         [](uint32_t colorbufferhandle, int x, int y, int width, int height, uint32_t format,
__anona8dbb0c51502(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) 618            uint32_t type, uint32_t texture_type, uint32_t* textures, void* metadata) {
619             FrameBuffer::getFB()->swapTexturesAndUpdateColorBuffer(
620                 colorbufferhandle, x, y, width, height, format, type, texture_type, textures);
621         },
622 #endif
623     .get_last_posted_color_buffer =
__anona8dbb0c51602() 624         []() { return FrameBuffer::getFB()->getLastPostedColorBuffer(); },
625 #if GFXSTREAM_ENABLE_HOST_GLES
626     .bind_color_buffer_to_texture =
__anona8dbb0c51702(uint32_t handle) 627         [](uint32_t handle) { FrameBuffer::getFB()->bindColorBufferToTexture2(handle); },
__anona8dbb0c51802() 628     .get_global_egl_context = []() { return FrameBuffer::getFB()->getGlobalEGLContext(); },
629 #endif
630     .set_guest_managed_color_buffer_lifetime =
__anona8dbb0c51902(bool guestManaged) 631         [](bool guestManaged) {
632             FrameBuffer::getFB()->setGuestManagedColorBufferLifetime(guestManaged);
633         },
634 #if GFXSTREAM_ENABLE_HOST_GLES
635     .async_wait_for_gpu_with_cb =
__anona8dbb0c51a02(uint64_t eglsync, FenceCompletionCallback cb) 636         [](uint64_t eglsync, FenceCompletionCallback cb) {
637             FrameBuffer::getFB()->asyncWaitForGpuWithCb(eglsync, cb);
638         },
639 #endif
640     .async_wait_for_gpu_vulkan_with_cb =
__anona8dbb0c51b02(uint64_t device, uint64_t fence, FenceCompletionCallback cb) 641         [](uint64_t device, uint64_t fence, FenceCompletionCallback cb) {
642             FrameBuffer::getFB()->asyncWaitForGpuVulkanWithCb(device, fence, cb);
643         },
644     .async_wait_for_gpu_vulkan_qsri_with_cb =
__anona8dbb0c51c02(uint64_t image, FenceCompletionCallback cb) 645         [](uint64_t image, FenceCompletionCallback cb) {
646             FrameBuffer::getFB()->asyncWaitForGpuVulkanQsriWithCb(image, cb);
647         },
648     .update_color_buffer_from_framework_format =
649         [](uint32_t handle, int x, int y, int width, int height, uint32_t fwkFormat,
__anona8dbb0c51d02(uint32_t handle, int x, int y, int width, int height, uint32_t fwkFormat, uint32_t format, uint32_t type, void* pixels, void* pMetadata) 650            uint32_t format, uint32_t type, void* pixels, void* pMetadata) {
651             FrameBuffer::getFB()->updateColorBufferFromFrameworkFormat(
652                 handle, x, y, width, height, (FrameworkFormat)fwkFormat, format, type, pixels,
653                 pMetadata);
654         },
655 };
656 
getVirtioGpuOps()657 struct AndroidVirtioGpuOps* RendererImpl::getVirtioGpuOps() {
658     return &sVirtioGpuOps;
659 }
660 
snapshotOperationCallback(int op,int stage)661 void RendererImpl::snapshotOperationCallback(int op, int stage) {
662     using namespace android::snapshot;
663     switch (op) {
664         case SNAPSHOTTER_OPERATION_LOAD:
665             if (stage == SNAPSHOTTER_STAGE_START) {
666 #ifdef SNAPSHOT_PROFILE
667              android::base::System::Duration startTime =
668                      android::base::System::get()->getUnixTimeUs();
669 #endif
670                 mRenderWindow->setPaused(true);
671                 cleanupRenderThreads();
672 #ifdef SNAPSHOT_PROFILE
673                 printf("Previous session suspend time: %lld ms\n",
674                        (long long)(android::base::System::get()
675                                            ->getUnixTimeUs() -
676                                    startTime) /
677                                1000);
678 #endif
679             }
680             if (stage == SNAPSHOTTER_STAGE_END) {
681                 mRenderWindow->setPaused(false);
682             }
683             break;
684         default:
685             break;
686     }
687 }
688 
setVsyncHz(int vsyncHz)689 void RendererImpl::setVsyncHz(int vsyncHz) {
690     if (mRenderWindow) {
691         mRenderWindow->setVsyncHz(vsyncHz);
692     }
693 }
694 
setDisplayConfigs(int configId,int w,int h,int dpiX,int dpiY)695 void RendererImpl::setDisplayConfigs(int configId, int w, int h,
696                                      int dpiX, int dpiY) {
697     if (mRenderWindow) {
698         mRenderWindow->setDisplayConfigs(configId, w, h, dpiX, dpiY);
699     }
700 }
701 
setDisplayActiveConfig(int configId)702 void RendererImpl::setDisplayActiveConfig(int configId) {
703     if (mRenderWindow) {
704         mRenderWindow->setDisplayActiveConfig(configId);
705     }
706 }
707 
getEglDispatch()708 const void* RendererImpl::getEglDispatch() {
709 #if GFXSTREAM_ENABLE_HOST_GLES
710     return FrameBuffer::getFB()->getEglDispatch();
711 #else
712     return nullptr;
713 #endif
714 }
715 
getGles2Dispatch()716 const void* RendererImpl::getGles2Dispatch() {
717 #if GFXSTREAM_ENABLE_HOST_GLES
718     return FrameBuffer::getFB()->getGles2Dispatch();
719 #else
720     return nullptr;
721 #endif
722 }
723 
724 }  // namespace gfxstream
725