blob: aaec95e1c4e66bbf437b8ec37378782a7549c08c [file] [log] [blame]
Lingfeng Yangee4aea32020-10-29 08:52:13 -07001// 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
Jason Macnak6402a1b2022-06-02 15:29:05 -070016#include <assert.h>
Lingfeng Yangee4aea32020-10-29 08:52:13 -070017
18#include <algorithm>
19#include <utility>
Kaiyi Li32c361c2022-10-07 11:29:26 -070020#include <variant>
Lingfeng Yangee4aea32020-10-29 08:52:13 -070021
Jason Macnak6402a1b2022-06-02 15:29:05 -070022#include "FrameBuffer.h"
23#include "RenderChannelImpl.h"
24#include "RenderThread.h"
Joshua Duongef2bbc22022-10-05 11:59:15 -070025#include "aemu/base/system/System.h"
Kaiyi Li32c361c2022-10-07 11:29:26 -070026#include "aemu/base/threads/WorkerThread.h"
Jason Macnak6402a1b2022-06-02 15:29:05 -070027#include "host-common/logging.h"
28#include "snapshot/common.h"
Lingfeng Yangee4aea32020-10-29 08:52:13 -070029
Gurchetan Singh95b30dc2024-01-18 18:31:15 -080030#if GFXSTREAM_ENABLE_HOST_GLES
31#include "gl/EmulatedEglFenceSync.h"
32#endif
33
Jason Macnaked0c9e62023-03-30 15:58:24 -070034namespace gfxstream {
Lingfeng Yangee4aea32020-10-29 08:52:13 -070035
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.
56static 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.
61class RendererImpl::ProcessCleanupThread {
62public:
63 ProcessCleanupThread()
Kaiyi Li32c361c2022-10-07 11:29:26 -070064 : mCleanupWorker([](Cmd cmd) {
65 using android::base::WorkerProcessingResult;
66 struct {
67 WorkerProcessingResult operator()(CleanProcessResources resources) {
68 FrameBuffer::getFB()->cleanupProcGLObjects(resources.puid);
Kaiyi Lica6b3932022-10-07 12:29:18 -070069 // resources.resource are destroyed automatically when going out of the scope.
Kaiyi Li32c361c2022-10-07 11:29:26 -070070 return WorkerProcessingResult::Continue;
71 }
72 WorkerProcessingResult operator()(Exit) {
73 return WorkerProcessingResult::Stop;
74 }
75 } visitor;
76 return std::visit(visitor, std::move(cmd));
Lingfeng Yangee4aea32020-10-29 08:52:13 -070077 }) {
Kaiyi Li32c361c2022-10-07 11:29:26 -070078 mCleanupWorker.start();
Lingfeng Yangee4aea32020-10-29 08:52:13 -070079 }
80
81 ~ProcessCleanupThread() {
Kaiyi Li32c361c2022-10-07 11:29:26 -070082 mCleanupWorker.enqueue(Exit{});
Lingfeng Yangee4aea32020-10-29 08:52:13 -070083 }
84
Kaiyi Lica6b3932022-10-07 12:29:18 -070085 void cleanup(uint64_t processId, std::unique_ptr<ProcessResources> resource) {
86 mCleanupWorker.enqueue(CleanProcessResources{
87 .puid = processId,
88 .resource = std::move(resource),
89 });
Lingfeng Yangee4aea32020-10-29 08:52:13 -070090 }
91
92 void stop() {
Kaiyi Li32c361c2022-10-07 11:29:26 -070093 mCleanupWorker.enqueue(Exit{});
Jason Macnak08f53822023-07-27 09:50:27 -070094 mCleanupWorker.join();
Lingfeng Yangee4aea32020-10-29 08:52:13 -070095 }
96
97 void waitForCleanup() {
Kaiyi Li32c361c2022-10-07 11:29:26 -070098 mCleanupWorker.waitQueuedItems();
Lingfeng Yangee4aea32020-10-29 08:52:13 -070099 }
100
101private:
Kaiyi Li32c361c2022-10-07 11:29:26 -0700102 struct CleanProcessResources {
103 uint64_t puid;
Kaiyi Lica6b3932022-10-07 12:29:18 -0700104 std::unique_ptr<ProcessResources> resource;
Kaiyi Li32c361c2022-10-07 11:29:26 -0700105 };
106 struct Exit {};
107 using Cmd = std::variant<CleanProcessResources, Exit>;
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700108 DISALLOW_COPY_AND_ASSIGN(ProcessCleanupThread);
109
Kaiyi Li32c361c2022-10-07 11:29:26 -0700110 android::base::WorkerThread<Cmd> mCleanupWorker;
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700111};
112
113RendererImpl::RendererImpl() {
114 mCleanupThread.reset(new ProcessCleanupThread());
115}
116
117RendererImpl::~RendererImpl() {
118 stop(true);
Andrew Woloszyn0ea01732022-11-23 10:03:13 -0500119 // 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 }
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700124 mRenderWindow.reset();
125}
126
Jason Macnak26872122024-02-23 10:46:09 -0800127bool RendererImpl::initialize(int width, int height, gfxstream::host::FeatureSet features,
128 bool useSubWindow, bool egl2egl) {
Gurchetan Singhae7c7012024-06-27 09:09:51 -0700129#ifdef CONFIG_AEMU
Lingfeng Yangbfe3c722020-10-29 10:33:18 -0700130 if (android::base::getEnvironmentVariable("ANDROID_EMUGL_VERBOSE") == "1") {
Serdar Kocdemir47d2bcc2024-06-26 14:03:04 +0100131 set_gfxstream_enable_verbose_logs();
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700132 }
Gurchetan Singhae7c7012024-06-27 09:09:51 -0700133#endif
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700134
135 if (mRenderWindow) {
136 return false;
137 }
138
139 std::unique_ptr<RenderWindow> renderWindow(new RenderWindow(
Jason Macnak26872122024-02-23 10:46:09 -0800140 width, height, features, kUseSubwindowThread, useSubWindow, egl2egl));
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700141 if (!renderWindow) {
142 ERR("Could not create rendering window class\n");
143 GL_LOG("Could not create rendering window class");
144 return false;
145 }
146 if (!renderWindow->isValid()) {
147 ERR("Could not initialize emulated framebuffer\n");
148 return false;
149 }
150
151 mRenderWindow = std::move(renderWindow);
152 GL_LOG("OpenGL renderer initialized successfully");
153
154 // This render thread won't do anything but will only preload resources
155 // for the real threads to start faster.
156 mLoaderRenderThread.reset(new RenderThread(nullptr));
157 mLoaderRenderThread->start();
158
159 return true;
160}
161
162void RendererImpl::stop(bool wait) {
163 android::base::AutoLock lock(mChannelsLock);
164 mStopped = true;
165 auto channels = std::move(mChannels);
166 lock.unlock();
167
168 if (const auto fb = FrameBuffer::getFB()) {
169 fb->setShuttingDown();
170 }
171 for (const auto& c : channels) {
172 c->stopFromHost();
173 }
174 // We're stopping the renderer, so there's no need to clean up resources
175 // of some pending processes: we'll destroy everything soon.
176 mCleanupThread->stop();
177
178 mStoppedChannels.insert(mStoppedChannels.end(),
179 std::make_move_iterator(channels.begin()),
180 std::make_move_iterator(channels.end()));
181
182 if (!wait) {
183 return;
184 }
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()->wait();
192 }
Kaiyi Li3a894ad2024-01-02 11:14:38 -0800193 mCleanupThread->waitForCleanup();
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700194 mStoppedChannels.clear();
195}
196
197void RendererImpl::finish() {
198 {
199 android::base::AutoLock lock(mChannelsLock);
200 mRenderWindow->setPaused(true);
201 }
202 cleanupRenderThreads();
203 {
204 android::base::AutoLock lock(mChannelsLock);
205 mRenderWindow->setPaused(false);
206 }
207}
208
209void RendererImpl::cleanupRenderThreads() {
210 android::base::AutoLock lock(mChannelsLock);
211 const auto channels = std::move(mChannels);
212 assert(mChannels.empty());
213 lock.unlock();
214 for (const auto& c : channels) {
215 // Please DO NOT notify the guest about this event (DO NOT call
216 // stopFromHost() ), because this is used to kill old threads when
217 // loading from a snapshot, and the newly loaded guest should not
218 // be notified for those behavior.
219 c->stop();
220 }
221 for (const auto& c : channels) {
222 c->renderThread()->wait();
223 }
224}
225
226void RendererImpl::waitForProcessCleanup() {
227 mCleanupThread->waitForCleanup();
228 // Recreate it to make sure we've started from scratch and that we've
229 // finished all in-progress cleanups as well.
230 mCleanupThread.reset(new ProcessCleanupThread());
231}
232
233RenderChannelPtr RendererImpl::createRenderChannel(
Jason Macnak1220d962023-11-21 16:53:21 -0800234 android::base::Stream* loadStream, uint32_t virtioGpuContextId) {
235 const auto channel =
236 std::make_shared<RenderChannelImpl>(loadStream, virtioGpuContextId);
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700237 {
238 android::base::AutoLock lock(mChannelsLock);
239
240 if (mStopped) {
241 return nullptr;
242 }
243
244 // Clean up the stopped channels.
245 mChannels.erase(
246 std::remove_if(mChannels.begin(), mChannels.end(),
247 [](const std::shared_ptr<RenderChannelImpl>& c) {
248 return c->renderThread()->isFinished();
249 }),
250 mChannels.end());
251 mChannels.emplace_back(channel);
252
253 // Take the time to check if our loader thread is done as well.
254 if (mLoaderRenderThread && mLoaderRenderThread->isFinished()) {
255 mLoaderRenderThread->wait();
256 mLoaderRenderThread.reset();
257 }
258
Jason Macnake43e3a02021-10-14 10:35:33 -0700259 GL_LOG("Started new RenderThread (total %" PRIu64 ") @%p",
260 static_cast<uint64_t>(mChannels.size()), channel->renderThread());
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700261 }
262
263 return channel;
264}
265
Joshua Duonge3b2c5c2022-05-31 08:27:47 -0700266void RendererImpl::addListener(FrameBufferChangeEventListener* listener) {
Erwin Jansen6d8804e2021-02-06 17:25:08 -0800267 mRenderWindow->addListener(listener);
Joshua Duonge3b2c5c2022-05-31 08:27:47 -0700268}
269
270void RendererImpl::removeListener(FrameBufferChangeEventListener* listener) {
Erwin Jansen6d8804e2021-02-06 17:25:08 -0800271 mRenderWindow->removeListener(listener);
Joshua Duonge3b2c5c2022-05-31 08:27:47 -0700272}
273
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700274void* RendererImpl::addressSpaceGraphicsConsumerCreate(
275 struct asg_context context,
Doug Horn05386c52021-01-08 13:51:36 -0800276 android::base::Stream* loadStream,
Gurchetan Singhf60b2b72022-08-22 17:01:02 -0700277 android::emulation::asg::ConsumerCallbacks callbacks,
278 uint32_t contextId, uint32_t capsetId,
279 std::optional<std::string> nameOpt) {
280 auto thread = new RenderThread(context, loadStream, callbacks, contextId,
281 capsetId, std::move(nameOpt));
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700282 thread->start();
Yahan Zhoud1c7e1e2023-11-09 14:59:26 -0800283 android::base::AutoLock lock(mAddressSpaceRenderThreadLock);
284 mAddressSpaceRenderThreads.emplace(thread);
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700285 return (void*)thread;
286}
287
288void RendererImpl::addressSpaceGraphicsConsumerDestroy(void* consumer) {
289 RenderThread* thread = (RenderThread*)consumer;
Yahan Zhoud1c7e1e2023-11-09 14:59:26 -0800290 {
291 android::base::AutoLock lock(mAddressSpaceRenderThreadLock);
292 mAddressSpaceRenderThreads.erase(thread);
293 }
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700294 thread->wait();
295 delete thread;
296}
297
Doug Horn05386c52021-01-08 13:51:36 -0800298void RendererImpl::addressSpaceGraphicsConsumerPreSave(void* consumer) {
299 RenderThread* thread = (RenderThread*)consumer;
300 thread->pausePreSnapshot();
301}
302
303void RendererImpl::addressSpaceGraphicsConsumerSave(void* consumer, android::base::Stream* stream) {
304 RenderThread* thread = (RenderThread*)consumer;
305 thread->save(stream);
306}
307
308void RendererImpl::addressSpaceGraphicsConsumerPostSave(void* consumer) {
309 RenderThread* thread = (RenderThread*)consumer;
Yahan Zhoud1c7e1e2023-11-09 14:59:26 -0800310 thread->resume(true);
Doug Horn05386c52021-01-08 13:51:36 -0800311}
312
313void RendererImpl::addressSpaceGraphicsConsumerRegisterPostLoadRenderThread(void* consumer) {
314 RenderThread* thread = (RenderThread*)consumer;
315 mAdditionalPostLoadRenderThreads.push_back(thread);
316}
317
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700318void RendererImpl::pauseAllPreSave() {
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700319 {
320 android::base::AutoLock lock(mChannelsLock);
321 if (mStopped) {
322 return;
323 }
324 for (const auto& c : mChannels) {
Yahan Zhoud1c7e1e2023-11-09 14:59:26 -0800325 c->renderThread()->pausePreSnapshot();
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700326 }
Yahan Zhoud1c7e1e2023-11-09 14:59:26 -0800327 }
328 {
329 android::base::AutoLock lock(mAddressSpaceRenderThreadLock);
330 for (const auto& thread : mAddressSpaceRenderThreads) {
331 thread->pausePreSnapshot();
332 }
333 }
334 waitForProcessCleanup();
335}
Doug Horn05386c52021-01-08 13:51:36 -0800336
Yahan Zhoud1c7e1e2023-11-09 14:59:26 -0800337void RendererImpl::resumeAll(bool waitForSave) {
338 {
339 android::base::AutoLock lock(mAddressSpaceRenderThreadLock);
340 for (const auto t : mAdditionalPostLoadRenderThreads) {
341 t->resume(waitForSave);
342 }
343 }
344 {
345 android::base::AutoLock lock(mChannelsLock);
346 if (mStopped) {
347 return;
348 }
349 for (const auto& c : mChannels) {
350 c->renderThread()->resume(waitForSave);
351 }
352 for (const auto& thread : mAddressSpaceRenderThreads) {
353 thread->resume(waitForSave);
Doug Horn05386c52021-01-08 13:51:36 -0800354 }
355 mAdditionalPostLoadRenderThreads.clear();
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700356 }
357
358 repaintOpenGLDisplay();
359}
360
361void RendererImpl::save(android::base::Stream* stream,
362 const android::snapshot::ITextureSaverPtr& textureSaver) {
363 stream->putByte(mStopped);
364 if (mStopped) {
365 return;
366 }
367 auto fb = FrameBuffer::getFB();
368 assert(fb);
369 fb->onSave(stream, textureSaver);
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700370}
371
372bool RendererImpl::load(android::base::Stream* stream,
373 const android::snapshot::ITextureLoaderPtr& textureLoader) {
374
375#ifdef SNAPSHOT_PROFILE
376 android::base::System::Duration startTime =
377 android::base::System::get()->getUnixTimeUs();
378#endif
379 waitForProcessCleanup();
380#ifdef SNAPSHOT_PROFILE
381 printf("Previous session cleanup time: %lld ms\n",
382 (long long)(android::base::System::get()
383 ->getUnixTimeUs() -
384 startTime) /
385 1000);
386#endif
387
388 mStopped = stream->getByte();
389 if (mStopped) {
390 return true;
391 }
392 auto fb = FrameBuffer::getFB();
393 assert(fb);
394
395 bool res = true;
396
Yahan Zhoub1365372022-12-20 11:29:56 -0800397 res = fb->onLoad(stream, textureLoader);
Gurchetan Singh95b30dc2024-01-18 18:31:15 -0800398#if GFXSTREAM_ENABLE_HOST_GLES
Jason Macnaked0c9e62023-03-30 15:58:24 -0700399 gl::EmulatedEglFenceSync::onLoad(stream);
Gurchetan Singh95b30dc2024-01-18 18:31:15 -0800400#endif
Yahan Zhoub1365372022-12-20 11:29:56 -0800401
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700402 return res;
403}
404
405void RendererImpl::fillGLESUsages(android_studio::EmulatorGLESUsages* usages) {
406 auto fb = FrameBuffer::getFB();
Gurchetan Singh95b30dc2024-01-18 18:31:15 -0800407#if GFXSTREAM_ENABLE_HOST_GLES
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700408 if (fb) fb->fillGLESUsages(usages);
Gurchetan Singh95b30dc2024-01-18 18:31:15 -0800409#endif
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700410}
411
Yahan Zhoua774b992022-12-20 14:12:02 -0800412int RendererImpl::getScreenshot(unsigned int nChannels, unsigned int* width, unsigned int* height,
413 uint8_t* pixels, size_t* cPixels, int displayId = 0,
414 int desiredWidth = 0, int desiredHeight = 0,
415 int desiredRotation = 0, Rect rect = {{0, 0}, {0, 0}}) {
Erwin Jansencc105d72021-03-12 17:23:39 -0800416 auto fb = FrameBuffer::getFB();
Erwin Jansen49539e32021-03-15 12:17:46 -0700417 if (fb) {
Erwin Jansencc105d72021-03-12 17:23:39 -0800418 return fb->getScreenshot(nChannels, width, height, pixels, cPixels,
419 displayId, desiredWidth, desiredHeight,
Weilun Duc8dd9172021-03-24 16:06:17 -0700420 desiredRotation, rect);
Erwin Jansen49539e32021-03-15 12:17:46 -0700421 }
Erwin Jansencc105d72021-03-12 17:23:39 -0800422 *cPixels = 0;
423 return -1;
424}
425
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700426void RendererImpl::setMultiDisplay(uint32_t id,
427 int32_t x,
428 int32_t y,
429 uint32_t w,
430 uint32_t h,
431 uint32_t dpi,
432 bool add) {
433 auto fb = FrameBuffer::getFB();
434 if (fb) {
435 if (add) {
436 fb->createDisplay(&id);
437 fb->setDisplayPose(id, x, y, w, h, dpi);
438 } else {
439 fb->destroyDisplay(id);
440 }
441 }
442}
443
444void RendererImpl::setMultiDisplayColorBuffer(uint32_t id, uint32_t cb) {
445 auto fb = FrameBuffer::getFB();
446 if (fb) {
447 fb->setDisplayColorBuffer(id, cb);
448 }
449}
450
451RendererImpl::HardwareStrings RendererImpl::getHardwareStrings() {
452 assert(mRenderWindow);
453
454 const char* vendor = nullptr;
455 const char* renderer = nullptr;
456 const char* version = nullptr;
457 if (!mRenderWindow->getHardwareStrings(&vendor, &renderer, &version)) {
458 return {};
459 }
460 HardwareStrings res;
461 res.vendor = vendor ? vendor : "";
462 res.renderer = renderer ? renderer : "";
463 res.version = version ? version : "";
464 return res;
465}
466
467void RendererImpl::setPostCallback(RendererImpl::OnPostCallback onPost,
468 void* context,
469 bool useBgraReadback,
470 uint32_t displayId) {
471 assert(mRenderWindow);
472 mRenderWindow->setPostCallback(onPost, context, displayId, useBgraReadback);
473}
474
475bool RendererImpl::asyncReadbackSupported() {
476 assert(mRenderWindow);
477 return mRenderWindow->asyncReadbackSupported();
478}
479
480RendererImpl::ReadPixelsCallback
481RendererImpl::getReadPixelsCallback() {
482 assert(mRenderWindow);
483 return mRenderWindow->getReadPixelsCallback();
484}
485
486RendererImpl::FlushReadPixelPipeline
487RendererImpl::getFlushReadPixelPipeline() {
488 assert(mRenderWindow);
489 return mRenderWindow->getFlushReadPixelPipeline();
490}
491
492bool RendererImpl::showOpenGLSubwindow(FBNativeWindowType window,
493 int wx,
494 int wy,
495 int ww,
496 int wh,
497 int fbw,
498 int fbh,
499 float dpr,
500 float zRot,
501 bool deleteExisting,
502 bool hideWindow) {
503 assert(mRenderWindow);
504 return mRenderWindow->setupSubWindow(window, wx, wy, ww, wh, fbw, fbh, dpr,
505 zRot, deleteExisting, hideWindow);
506}
507
508bool RendererImpl::destroyOpenGLSubwindow() {
509 assert(mRenderWindow);
510 return mRenderWindow->removeSubWindow();
511}
512
513void RendererImpl::setOpenGLDisplayRotation(float zRot) {
514 assert(mRenderWindow);
515 mRenderWindow->setRotation(zRot);
516}
517
518void RendererImpl::setOpenGLDisplayTranslation(float px, float py) {
519 assert(mRenderWindow);
520 mRenderWindow->setTranslation(px, py);
521}
522
523void RendererImpl::repaintOpenGLDisplay() {
524 assert(mRenderWindow);
525 mRenderWindow->repaint();
526}
527
528bool RendererImpl::hasGuestPostedAFrame() {
529 if (mRenderWindow) {
530 return mRenderWindow->hasGuestPostedAFrame();
531 }
532 return false;
533}
534
535void RendererImpl::resetGuestPostedAFrame() {
536 if (mRenderWindow) {
537 mRenderWindow->resetGuestPostedAFrame();
538 }
539}
540
541void RendererImpl::setScreenMask(int width, int height, const unsigned char* rgbaData) {
542 assert(mRenderWindow);
543 mRenderWindow->setScreenMask(width, height, rgbaData);
544}
545
Kaiyi Lica6b3932022-10-07 12:29:18 -0700546void RendererImpl::onGuestGraphicsProcessCreate(uint64_t puid) {
547 FrameBuffer::getFB()->createGraphicsProcessResources(puid);
548}
549
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700550void RendererImpl::cleanupProcGLObjects(uint64_t puid) {
Kaiyi Lica6b3932022-10-07 12:29:18 -0700551 std::unique_ptr<ProcessResources> resource =
552 FrameBuffer::getFB()->removeGraphicsProcessResources(puid);
553 mCleanupThread->cleanup(puid, std::move(resource));
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700554}
555
556static struct AndroidVirtioGpuOps sVirtioGpuOps = {
Lingfeng Yang63a26f92021-04-14 13:43:42 -0700557 .create_buffer_with_handle =
558 [](uint64_t size, uint32_t handle) {
559 FrameBuffer::getFB()->createBufferWithHandle(size, handle);
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700560 },
Lingfeng Yang63a26f92021-04-14 13:43:42 -0700561 .create_color_buffer_with_handle =
Aaron Ruby550b6bd2024-05-27 15:26:24 -0400562 [](uint32_t width, uint32_t height, uint32_t format, uint32_t fwkFormat, uint32_t handle,
563 bool linear) {
564 FrameBuffer::getFB()->createColorBufferWithHandle(
565 width, height, (GLenum)format, (FrameworkFormat)fwkFormat, handle, linear);
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700566 },
Lingfeng Yang63a26f92021-04-14 13:43:42 -0700567 .open_color_buffer = [](uint32_t handle) { FrameBuffer::getFB()->openColorBuffer(handle); },
568 .close_buffer = [](uint32_t handle) { FrameBuffer::getFB()->closeBuffer(handle); },
569 .close_color_buffer = [](uint32_t handle) { FrameBuffer::getFB()->closeColorBuffer(handle); },
570 .update_buffer =
571 [](uint32_t handle, uint64_t offset, uint64_t size, void* bytes) {
572 FrameBuffer::getFB()->updateBuffer(handle, offset, size, bytes);
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700573 },
Lingfeng Yang63a26f92021-04-14 13:43:42 -0700574 .update_color_buffer =
575 [](uint32_t handle, int x, int y, int width, int height, uint32_t format, uint32_t type,
576 void* pixels) {
577 FrameBuffer::getFB()->updateColorBuffer(handle, x, y, width, height, format, type,
578 pixels);
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700579 },
Lingfeng Yang63a26f92021-04-14 13:43:42 -0700580 .read_buffer =
581 [](uint32_t handle, uint64_t offset, uint64_t size, void* bytes) {
582 FrameBuffer::getFB()->readBuffer(handle, offset, size, bytes);
583 },
584 .read_color_buffer =
585 [](uint32_t handle, int x, int y, int width, int height, uint32_t format, uint32_t type,
586 void* pixels) {
587 FrameBuffer::getFB()->readColorBuffer(handle, x, y, width, height, format, type,
588 pixels);
589 },
590 .read_color_buffer_yuv =
591 [](uint32_t handle, int x, int y, int width, int height, void* pixels,
592 uint32_t pixels_size) {
593 FrameBuffer::getFB()->readColorBufferYUV(handle, x, y, width, height, pixels,
594 pixels_size);
595 },
596 .post_color_buffer = [](uint32_t handle) { FrameBuffer::getFB()->post(handle); },
597 .async_post_color_buffer =
598 [](uint32_t handle, CpuCompletionCallback cb) {
599 FrameBuffer::getFB()->postWithCallback(handle, cb);
600 },
601 .repost = []() { FrameBuffer::getFB()->repost(); },
Gurchetan Singh95b30dc2024-01-18 18:31:15 -0800602#if GFXSTREAM_ENABLE_HOST_GLES
Lingfeng Yang63a26f92021-04-14 13:43:42 -0700603 .create_yuv_textures =
604 [](uint32_t type, uint32_t count, int width, int height, uint32_t* output) {
605 FrameBuffer::getFB()->createYUVTextures(type, count, width, height, output);
606 },
607 .destroy_yuv_textures =
608 [](uint32_t type, uint32_t count, uint32_t* textures) {
609 FrameBuffer::getFB()->destroyYUVTextures(type, count, textures);
610 },
611 .update_yuv_textures =
612 [](uint32_t type, uint32_t* textures, void* privData, void* func) {
613 FrameBuffer::getFB()->updateYUVTextures(type, textures, privData, func);
614 },
615 .swap_textures_and_update_color_buffer =
616 [](uint32_t colorbufferhandle, int x, int y, int width, int height, uint32_t format,
617 uint32_t type, uint32_t texture_type, uint32_t* textures, void* metadata) {
Lingfeng Yang63a26f92021-04-14 13:43:42 -0700618 FrameBuffer::getFB()->swapTexturesAndUpdateColorBuffer(
619 colorbufferhandle, x, y, width, height, format, type, texture_type, textures);
620 },
Gurchetan Singh95b30dc2024-01-18 18:31:15 -0800621#endif
Lingfeng Yang63a26f92021-04-14 13:43:42 -0700622 .get_last_posted_color_buffer =
623 []() { return FrameBuffer::getFB()->getLastPostedColorBuffer(); },
Gurchetan Singh95b30dc2024-01-18 18:31:15 -0800624#if GFXSTREAM_ENABLE_HOST_GLES
Lingfeng Yang63a26f92021-04-14 13:43:42 -0700625 .bind_color_buffer_to_texture =
626 [](uint32_t handle) { FrameBuffer::getFB()->bindColorBufferToTexture2(handle); },
627 .get_global_egl_context = []() { return FrameBuffer::getFB()->getGlobalEGLContext(); },
628 .wait_for_gpu = [](uint64_t eglsync) { FrameBuffer::getFB()->waitForGpu(eglsync); },
Gurchetan Singh95b30dc2024-01-18 18:31:15 -0800629#endif
Lingfeng Yang63a26f92021-04-14 13:43:42 -0700630 .wait_for_gpu_vulkan =
631 [](uint64_t device, uint64_t fence) {
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700632 FrameBuffer::getFB()->waitForGpuVulkan(device, fence);
633 },
Lingfeng Yang63a26f92021-04-14 13:43:42 -0700634 .set_guest_managed_color_buffer_lifetime =
635 [](bool guestManaged) {
Huan Songf42409f2022-06-15 12:31:11 -0700636 FrameBuffer::getFB()->setGuestManagedColorBufferLifetime(guestManaged);
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700637 },
Gurchetan Singh95b30dc2024-01-18 18:31:15 -0800638#if GFXSTREAM_ENABLE_HOST_GLES
Lingfeng Yang63a26f92021-04-14 13:43:42 -0700639 .async_wait_for_gpu_with_cb =
640 [](uint64_t eglsync, FenceCompletionCallback cb) {
Lingfeng Yang0a63dfd2021-07-14 13:27:56 -0700641 FrameBuffer::getFB()->asyncWaitForGpuWithCb(eglsync, cb);
642 },
Gurchetan Singh95b30dc2024-01-18 18:31:15 -0800643#endif
Lingfeng Yang63a26f92021-04-14 13:43:42 -0700644 .async_wait_for_gpu_vulkan_with_cb =
645 [](uint64_t device, uint64_t fence, FenceCompletionCallback cb) {
Lingfeng Yang0a63dfd2021-07-14 13:27:56 -0700646 FrameBuffer::getFB()->asyncWaitForGpuVulkanWithCb(device, fence, cb);
647 },
Lingfeng Yang63a26f92021-04-14 13:43:42 -0700648 .async_wait_for_gpu_vulkan_qsri_with_cb =
649 [](uint64_t image, FenceCompletionCallback cb) {
Lingfeng Yang9e750252021-07-15 16:50:37 -0700650 FrameBuffer::getFB()->asyncWaitForGpuVulkanQsriWithCb(image, cb);
651 },
Lingfeng Yang63a26f92021-04-14 13:43:42 -0700652 .wait_for_gpu_vulkan_qsri =
653 [](uint64_t image) { FrameBuffer::getFB()->waitForGpuVulkanQsri(image); },
Jason Macnak303479f2023-01-17 15:39:10 -0800654 .update_color_buffer_from_framework_format =
655 [](uint32_t handle, int x, int y, int width, int height, uint32_t fwkFormat,
656 uint32_t format, uint32_t type, void* pixels, void* pMetadata) {
657 FrameBuffer::getFB()->updateColorBufferFromFrameworkFormat(
Bo Hue1a53fa2023-06-27 13:53:46 -0700658 handle, x, y, width, height, (FrameworkFormat)fwkFormat, format, type, pixels,
659 pMetadata);
Jason Macnak303479f2023-01-17 15:39:10 -0800660 },
Lingfeng Yang63a26f92021-04-14 13:43:42 -0700661 .platform_import_resource =
662 [](uint32_t handle, uint32_t info, void* resource) {
Josh Simonota1a29a82022-05-12 12:03:35 -0400663 return FrameBuffer::getFB()->platformImportResource(handle, info, resource);
Lingfeng Yangda09c0b2021-07-22 16:05:38 -0700664 },
Lingfeng Yang63a26f92021-04-14 13:43:42 -0700665 .platform_resource_info =
666 [](uint32_t handle, int32_t* width, int32_t* height, int32_t* internal_format) {
Lingfeng Yangda09c0b2021-07-22 16:05:38 -0700667 return FrameBuffer::getFB()->getColorBufferInfo(handle, width, height, internal_format);
668 },
Gurchetan Singh95b30dc2024-01-18 18:31:15 -0800669#if GFXSTREAM_ENABLE_HOST_GLES
Lingfeng Yang63a26f92021-04-14 13:43:42 -0700670 .platform_create_shared_egl_context =
671 []() { return FrameBuffer::getFB()->platformCreateSharedEglContext(); },
672 .platform_destroy_shared_egl_context =
673 [](void* context) {
Lingfeng Yangda09c0b2021-07-22 16:05:38 -0700674 return FrameBuffer::getFB()->platformDestroySharedEglContext(context);
675 },
Gurchetan Singh95b30dc2024-01-18 18:31:15 -0800676#endif
Gurchetan Singh1cc4e5c2024-06-14 01:24:17 +0000677 .wait_sync_color_buffer =
678 [](uint32_t handle) { return FrameBuffer::getFB()->waitSyncColorBuffer(handle); },
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700679};
680
681struct AndroidVirtioGpuOps* RendererImpl::getVirtioGpuOps() {
682 return &sVirtioGpuOps;
683}
684
Lingfeng Yangbfe3c722020-10-29 10:33:18 -0700685void RendererImpl::snapshotOperationCallback(int op, int stage) {
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700686 using namespace android::snapshot;
687 switch (op) {
Lingfeng Yangbfe3c722020-10-29 10:33:18 -0700688 case SNAPSHOTTER_OPERATION_LOAD:
689 if (stage == SNAPSHOTTER_STAGE_START) {
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700690#ifdef SNAPSHOT_PROFILE
691 android::base::System::Duration startTime =
692 android::base::System::get()->getUnixTimeUs();
693#endif
694 mRenderWindow->setPaused(true);
695 cleanupRenderThreads();
696#ifdef SNAPSHOT_PROFILE
697 printf("Previous session suspend time: %lld ms\n",
698 (long long)(android::base::System::get()
699 ->getUnixTimeUs() -
700 startTime) /
701 1000);
702#endif
703 }
Lingfeng Yangbfe3c722020-10-29 10:33:18 -0700704 if (stage == SNAPSHOTTER_STAGE_END) {
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700705 mRenderWindow->setPaused(false);
706 }
707 break;
708 default:
709 break;
710 }
711}
712
Joshua Duonge3b2c5c2022-05-31 08:27:47 -0700713void RendererImpl::setVsyncHz(int vsyncHz) {
Lingfeng Yang66d96102021-07-30 16:01:15 -0700714 if (mRenderWindow) {
715 mRenderWindow->setVsyncHz(vsyncHz);
716 }
Joshua Duonge3b2c5c2022-05-31 08:27:47 -0700717}
718
719void RendererImpl::setDisplayConfigs(int configId, int w, int h,
720 int dpiX, int dpiY) {
Huan Songc3a1aeb2021-09-22 08:27:19 -0700721 if (mRenderWindow) {
722 mRenderWindow->setDisplayConfigs(configId, w, h, dpiX, dpiY);
723 }
Joshua Duonge3b2c5c2022-05-31 08:27:47 -0700724}
725
726void RendererImpl::setDisplayActiveConfig(int configId) {
Huan Songc3a1aeb2021-09-22 08:27:19 -0700727 if (mRenderWindow) {
728 mRenderWindow->setDisplayActiveConfig(configId);
729 }
Joshua Duonge3b2c5c2022-05-31 08:27:47 -0700730}
Lingfeng Yang66d96102021-07-30 16:01:15 -0700731
Jason Macnake70b8e32023-01-20 13:59:35 -0800732const void* RendererImpl::getEglDispatch() {
Gurchetan Singh95b30dc2024-01-18 18:31:15 -0800733#if GFXSTREAM_ENABLE_HOST_GLES
Jason Macnake70b8e32023-01-20 13:59:35 -0800734 return FrameBuffer::getFB()->getEglDispatch();
Gurchetan Singh95b30dc2024-01-18 18:31:15 -0800735#else
736 return nullptr;
737#endif
Jason Macnake70b8e32023-01-20 13:59:35 -0800738}
739
740const void* RendererImpl::getGles2Dispatch() {
Gurchetan Singh95b30dc2024-01-18 18:31:15 -0800741#if GFXSTREAM_ENABLE_HOST_GLES
Jason Macnake70b8e32023-01-20 13:59:35 -0800742 return FrameBuffer::getFB()->getGles2Dispatch();
Gurchetan Singh95b30dc2024-01-18 18:31:15 -0800743#else
744 return nullptr;
745#endif
Jason Macnake70b8e32023-01-20 13:59:35 -0800746}
747
Jason Macnaked0c9e62023-03-30 15:58:24 -0700748} // namespace gfxstream