blob: b26c224d3ba67627f8f7dfe8eb19fb26876e186a [file] [log] [blame] [edit]
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "aemu/base/files/MemStream.h"
#include "aemu/base/Optional.h"
#include "host-common/address_space_graphics_types.h"
#include "aemu/base/synchronization/ConditionVariable.h"
#include "aemu/base/synchronization/Lock.h"
#include "aemu/base/threads/Thread.h"
#include <atomic>
#include <memory>
namespace gfxstream {
class RenderChannelImpl;
class RendererImpl;
class ReadBuffer;
class RingStream;
// A class used to model a thread of the RenderServer. Each one of them
// handles a single guest client / protocol byte stream.
class RenderThread : public android::base::Thread {
using MemStream = android::base::MemStream;
public:
static constexpr uint32_t INVALID_CONTEXT_ID = std::numeric_limits<uint32_t>::max();
// Create a new RenderThread instance.
RenderThread(RenderChannelImpl* channel,
android::base::Stream* loadStream = nullptr,
uint32_t virtioGpuContextId = INVALID_CONTEXT_ID);
// Create a new RenderThread instance tied to the address space device.
RenderThread(
struct asg_context context,
android::base::Stream* loadStream,
android::emulation::asg::ConsumerCallbacks callbacks,
uint32_t contextId, uint32_t capsetId,
std::optional<std::string> nameOpt);
virtual ~RenderThread();
// Returns true iff the thread has finished.
bool isFinished() const { return mFinished.load(std::memory_order_relaxed); }
void waitForFinished();
void pausePreSnapshot();
void resume();
void save(android::base::Stream* stream);
// RenderThreads are blocked from exiting after finished to workaround driver bugs.
// `sendExitSignal` allows us to control when we can allow the thread to exit to synchronize
// between exits and other RenderThreads calling vkDestroyDevice, eglMakeCurrent, etc.
// This must be called after RenderThread has finished (use `waitForFinished`), as a deadlock
// can occur if vulkan commands are still processing.
void sendExitSignal();
private:
virtual intptr_t main();
void setFinished();
void waitForExitSignal();
// Snapshot support.
enum class SnapshotState {
Empty,
StartSaving,
StartLoading,
InProgress,
Finished,
};
// Whether using RenderChannel or a ring buffer.
enum TransportMode {
Channel,
Ring,
};
struct SnapshotObjects;
bool doSnapshotOp(const SnapshotObjects& objects, SnapshotState expectedState,
std::function<void()> op);
bool loadSnapshot(const SnapshotObjects& objects);
bool saveSnapshot(const SnapshotObjects& objects);
void waitForSnapshotCompletion(android::base::AutoLock* lock);
void loadImpl(android::base::AutoLock* lock, const SnapshotObjects& objects);
void saveImpl(android::base::AutoLock* lock, const SnapshotObjects& objects);
bool isPausedForSnapshotLocked() const;
RenderChannelImpl* mChannel = nullptr;
std::unique_ptr<RingStream> mRingStream;
SnapshotState mState = SnapshotState::Empty;
std::atomic<bool> mFinished { false };
android::base::Lock mLock;
android::base::ConditionVariable mSnapshotSignal;
android::base::ConditionVariable mFinishedSignal;
android::base::ConditionVariable mExitSignal;
std::atomic<bool> mCanExit { false };
android::base::Optional<android::base::MemStream> mStream;
bool mRunInLimitedMode = false;
uint32_t mContextId = 0;
uint32_t mCapsetId = 0;
// If we need to reload process resources.
// This happens in snapshot testing where we don't snapshot render threads.
bool mNeedReloadProcessResources = false;
};
} // namespace gfxstream