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