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