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