XMA: Use a threadsafe bitmap to acquire/release contexts
Support Pausing/Resuming
This commit is contained in:
parent
69bb6aacef
commit
f81a99e83a
|
@ -301,6 +301,8 @@ void AudioSystem::Pause() {
|
||||||
// Kind of a hack, but it works.
|
// Kind of a hack, but it works.
|
||||||
shutdown_event_->Set();
|
shutdown_event_->Set();
|
||||||
pause_fence_.Wait();
|
pause_fence_.Wait();
|
||||||
|
|
||||||
|
xma_decoder_->Pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioSystem::Resume() {
|
void AudioSystem::Resume() {
|
||||||
|
@ -310,6 +312,8 @@ void AudioSystem::Resume() {
|
||||||
paused_ = false;
|
paused_ = false;
|
||||||
|
|
||||||
resume_event_->Set();
|
resume_event_->Set();
|
||||||
|
|
||||||
|
xma_decoder_->Resume();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace apu
|
} // namespace apu
|
||||||
|
|
|
@ -115,6 +115,7 @@ X_STATUS XmaDecoder::Setup(kernel::KernelState* kernel_state) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
registers_.next_context = 1;
|
registers_.next_context = 1;
|
||||||
|
context_bitmap_.Resize(kContextCount);
|
||||||
|
|
||||||
worker_running_ = true;
|
worker_running_ = true;
|
||||||
worker_thread_ = kernel::object_ref<kernel::XHostThread>(
|
worker_thread_ = kernel::object_ref<kernel::XHostThread>(
|
||||||
|
@ -141,6 +142,12 @@ void XmaDecoder::WorkerThreadMain() {
|
||||||
// registers_.current_context = n;
|
// registers_.current_context = n;
|
||||||
// registers_.next_context = (n + 1) % kContextCount;
|
// registers_.next_context = (n + 1) % kContextCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (paused_) {
|
||||||
|
pause_fence_.Signal();
|
||||||
|
resume_fence_.Wait();
|
||||||
|
}
|
||||||
|
|
||||||
xe::threading::MaybeYield();
|
xe::threading::MaybeYield();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -150,6 +157,10 @@ void XmaDecoder::Shutdown() {
|
||||||
worker_fence_.Signal();
|
worker_fence_.Signal();
|
||||||
worker_thread_.reset();
|
worker_thread_.reset();
|
||||||
|
|
||||||
|
if (paused_) {
|
||||||
|
Resume();
|
||||||
|
}
|
||||||
|
|
||||||
memory()->SystemHeapFree(registers_.context_array_ptr);
|
memory()->SystemHeapFree(registers_.context_array_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,32 +175,29 @@ int XmaDecoder::GetContextId(uint32_t guest_ptr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t XmaDecoder::AllocateContext() {
|
uint32_t XmaDecoder::AllocateContext() {
|
||||||
std::lock_guard<std::mutex> lock(lock_);
|
size_t index = context_bitmap_.Acquire();
|
||||||
|
if (index == -1) {
|
||||||
for (uint32_t n = 0; n < kContextCount; n++) {
|
// Out of contexts.
|
||||||
XmaContext& context = contexts_[n];
|
return 0;
|
||||||
if (!context.is_allocated()) {
|
|
||||||
context.set_is_allocated(true);
|
|
||||||
return context.guest_ptr();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
XmaContext& context = contexts_[index];
|
||||||
|
assert_false(context.is_allocated());
|
||||||
|
context.set_is_allocated(true);
|
||||||
|
return context.guest_ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
void XmaDecoder::ReleaseContext(uint32_t guest_ptr) {
|
void XmaDecoder::ReleaseContext(uint32_t guest_ptr) {
|
||||||
std::lock_guard<std::mutex> lock(lock_);
|
|
||||||
|
|
||||||
auto context_id = GetContextId(guest_ptr);
|
auto context_id = GetContextId(guest_ptr);
|
||||||
assert_true(context_id >= 0);
|
assert_true(context_id >= 0);
|
||||||
|
|
||||||
XmaContext& context = contexts_[context_id];
|
XmaContext& context = contexts_[context_id];
|
||||||
|
assert_true(context.is_allocated());
|
||||||
context.Release();
|
context.Release();
|
||||||
|
context_bitmap_.Release(context_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool XmaDecoder::BlockOnContext(uint32_t guest_ptr, bool poll) {
|
bool XmaDecoder::BlockOnContext(uint32_t guest_ptr, bool poll) {
|
||||||
std::lock_guard<std::mutex> lock(lock_);
|
|
||||||
|
|
||||||
auto context_id = GetContextId(guest_ptr);
|
auto context_id = GetContextId(guest_ptr);
|
||||||
assert_true(context_id >= 0);
|
assert_true(context_id >= 0);
|
||||||
|
|
||||||
|
@ -283,5 +291,23 @@ void XmaDecoder::WriteRegister(uint32_t addr, uint32_t value) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void XmaDecoder::Pause() {
|
||||||
|
if (paused_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
paused_ = true;
|
||||||
|
|
||||||
|
pause_fence_.Wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
void XmaDecoder::Resume() {
|
||||||
|
if (!paused_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
paused_ = false;
|
||||||
|
|
||||||
|
resume_fence_.Signal();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace apu
|
} // namespace apu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
#include "xenia/apu/xma_context.h"
|
#include "xenia/apu/xma_context.h"
|
||||||
|
#include "xenia/base/bit_map.h"
|
||||||
#include "xenia/kernel/xthread.h"
|
#include "xenia/kernel/xthread.h"
|
||||||
#include "xenia/xbox.h"
|
#include "xenia/xbox.h"
|
||||||
|
|
||||||
|
@ -43,6 +44,10 @@ class XmaDecoder {
|
||||||
uint32_t ReadRegister(uint32_t addr);
|
uint32_t ReadRegister(uint32_t addr);
|
||||||
void WriteRegister(uint32_t addr, uint32_t value);
|
void WriteRegister(uint32_t addr, uint32_t value);
|
||||||
|
|
||||||
|
bool is_paused() const { return paused_; }
|
||||||
|
void Pause();
|
||||||
|
void Resume();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int GetContextId(uint32_t guest_ptr);
|
int GetContextId(uint32_t guest_ptr);
|
||||||
|
|
||||||
|
@ -66,7 +71,9 @@ class XmaDecoder {
|
||||||
kernel::object_ref<kernel::XHostThread> worker_thread_;
|
kernel::object_ref<kernel::XHostThread> worker_thread_;
|
||||||
xe::threading::Fence worker_fence_;
|
xe::threading::Fence worker_fence_;
|
||||||
|
|
||||||
std::mutex lock_;
|
bool paused_ = false;
|
||||||
|
xe::threading::Fence pause_fence_; // Signaled when worker paused.
|
||||||
|
xe::threading::Fence resume_fence_; // Signaled when resume requested.
|
||||||
|
|
||||||
// Stored little endian, accessed through 0x7FEA....
|
// Stored little endian, accessed through 0x7FEA....
|
||||||
union {
|
union {
|
||||||
|
@ -91,6 +98,7 @@ class XmaDecoder {
|
||||||
|
|
||||||
static const uint32_t kContextCount = 320;
|
static const uint32_t kContextCount = 320;
|
||||||
XmaContext contexts_[kContextCount];
|
XmaContext contexts_[kContextCount];
|
||||||
|
BitMap context_bitmap_;
|
||||||
|
|
||||||
uint32_t context_data_first_ptr_ = 0;
|
uint32_t context_data_first_ptr_ = 0;
|
||||||
uint32_t context_data_last_ptr_ = 0;
|
uint32_t context_data_last_ptr_ = 0;
|
||||||
|
|
Loading…
Reference in New Issue