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