2018-01-22 17:54:58 +01:00
|
|
|
// Copyright 2018 yuzu emulator team
|
|
|
|
// Licensed under GPLv2 or any later version
|
|
|
|
// Refer to the license.txt file included.
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
2018-08-02 04:40:00 +02:00
|
|
|
#include "common/assert.h"
|
|
|
|
#include "common/logging/log.h"
|
2018-01-22 17:54:58 +01:00
|
|
|
#include "core/hle/service/nvflinger/buffer_queue.h"
|
|
|
|
|
2018-04-20 22:52:06 +02:00
|
|
|
namespace Service {
|
|
|
|
namespace NVFlinger {
|
2018-01-22 17:54:58 +01:00
|
|
|
|
|
|
|
BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) {
|
2018-07-17 06:05:13 +02:00
|
|
|
buffer_wait_event =
|
|
|
|
Kernel::Event::Create(Kernel::ResetType::Sticky, "BufferQueue NativeHandle");
|
2018-01-22 17:54:58 +01:00
|
|
|
}
|
|
|
|
|
2018-08-09 08:55:59 +02:00
|
|
|
void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer) {
|
2018-01-22 17:54:58 +01:00
|
|
|
Buffer buffer{};
|
|
|
|
buffer.slot = slot;
|
|
|
|
buffer.igbp_buffer = igbp_buffer;
|
|
|
|
buffer.status = Buffer::Status::Free;
|
|
|
|
|
2018-07-02 18:13:26 +02:00
|
|
|
LOG_WARNING(Service, "Adding graphics buffer {}", slot);
|
2018-01-22 17:54:58 +01:00
|
|
|
|
|
|
|
queue.emplace_back(buffer);
|
2018-07-17 06:05:13 +02:00
|
|
|
buffer_wait_event->Signal();
|
2018-01-22 17:54:58 +01:00
|
|
|
}
|
|
|
|
|
2018-03-19 01:27:15 +01:00
|
|
|
boost::optional<u32> BufferQueue::DequeueBuffer(u32 width, u32 height) {
|
2018-01-22 17:54:58 +01:00
|
|
|
auto itr = std::find_if(queue.begin(), queue.end(), [&](const Buffer& buffer) {
|
|
|
|
// Only consider free buffers. Buffers become free once again after they've been Acquired
|
|
|
|
// and Released by the compositor, see the NVFlinger::Compose method.
|
2018-03-19 01:27:15 +01:00
|
|
|
if (buffer.status != Buffer::Status::Free) {
|
2018-01-22 17:54:58 +01:00
|
|
|
return false;
|
2018-03-19 01:27:15 +01:00
|
|
|
}
|
2018-01-22 17:54:58 +01:00
|
|
|
|
|
|
|
// Make sure that the parameters match.
|
2018-03-17 01:11:50 +01:00
|
|
|
return buffer.igbp_buffer.width == width && buffer.igbp_buffer.height == height;
|
2018-01-22 17:54:58 +01:00
|
|
|
});
|
2018-03-19 01:27:15 +01:00
|
|
|
|
2018-02-10 04:17:31 +01:00
|
|
|
if (itr == queue.end()) {
|
2018-03-19 01:27:15 +01:00
|
|
|
return boost::none;
|
2018-02-10 04:17:31 +01:00
|
|
|
}
|
2018-01-22 17:54:58 +01:00
|
|
|
|
|
|
|
itr->status = Buffer::Status::Dequeued;
|
|
|
|
return itr->slot;
|
|
|
|
}
|
|
|
|
|
|
|
|
const IGBPBuffer& BufferQueue::RequestBuffer(u32 slot) const {
|
|
|
|
auto itr = std::find_if(queue.begin(), queue.end(),
|
|
|
|
[&](const Buffer& buffer) { return buffer.slot == slot; });
|
|
|
|
ASSERT(itr != queue.end());
|
|
|
|
ASSERT(itr->status == Buffer::Status::Dequeued);
|
|
|
|
return itr->igbp_buffer;
|
|
|
|
}
|
|
|
|
|
2018-07-18 02:11:41 +02:00
|
|
|
void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform,
|
|
|
|
const MathUtil::Rectangle<int>& crop_rect) {
|
2018-01-22 17:54:58 +01:00
|
|
|
auto itr = std::find_if(queue.begin(), queue.end(),
|
|
|
|
[&](const Buffer& buffer) { return buffer.slot == slot; });
|
|
|
|
ASSERT(itr != queue.end());
|
|
|
|
ASSERT(itr->status == Buffer::Status::Dequeued);
|
|
|
|
itr->status = Buffer::Status::Queued;
|
2018-02-12 01:03:31 +01:00
|
|
|
itr->transform = transform;
|
2018-07-18 02:11:41 +02:00
|
|
|
itr->crop_rect = crop_rect;
|
2018-01-22 17:54:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
boost::optional<const BufferQueue::Buffer&> BufferQueue::AcquireBuffer() {
|
|
|
|
auto itr = std::find_if(queue.begin(), queue.end(), [](const Buffer& buffer) {
|
|
|
|
return buffer.status == Buffer::Status::Queued;
|
|
|
|
});
|
|
|
|
if (itr == queue.end())
|
|
|
|
return boost::none;
|
|
|
|
itr->status = Buffer::Status::Acquired;
|
|
|
|
return *itr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BufferQueue::ReleaseBuffer(u32 slot) {
|
|
|
|
auto itr = std::find_if(queue.begin(), queue.end(),
|
|
|
|
[&](const Buffer& buffer) { return buffer.slot == slot; });
|
|
|
|
ASSERT(itr != queue.end());
|
|
|
|
ASSERT(itr->status == Buffer::Status::Acquired);
|
|
|
|
itr->status = Buffer::Status::Free;
|
2018-03-19 01:27:15 +01:00
|
|
|
|
2018-07-17 06:05:13 +02:00
|
|
|
buffer_wait_event->Signal();
|
2018-01-22 17:54:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
u32 BufferQueue::Query(QueryType type) {
|
2018-07-02 18:13:26 +02:00
|
|
|
LOG_WARNING(Service, "(STUBBED) called type={}", static_cast<u32>(type));
|
2018-01-22 17:54:58 +01:00
|
|
|
switch (type) {
|
|
|
|
case QueryType::NativeWindowFormat:
|
|
|
|
// TODO(Subv): Use an enum for this
|
|
|
|
static constexpr u32 FormatABGR8 = 1;
|
|
|
|
return FormatABGR8;
|
|
|
|
}
|
|
|
|
|
|
|
|
UNIMPLEMENTED();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-04-20 22:52:06 +02:00
|
|
|
} // namespace NVFlinger
|
|
|
|
} // namespace Service
|