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