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