|
|
@ -21,6 +21,7 @@ |
|
|
#include "core/hle/kernel/readable_event.h"
|
|
|
#include "core/hle/kernel/readable_event.h"
|
|
|
#include "core/hle/kernel/thread.h"
|
|
|
#include "core/hle/kernel/thread.h"
|
|
|
#include "core/hle/kernel/writable_event.h"
|
|
|
#include "core/hle/kernel/writable_event.h"
|
|
|
|
|
|
#include "core/hle/service/nvdrv/nvdata.h"
|
|
|
#include "core/hle/service/nvdrv/nvdrv.h"
|
|
|
#include "core/hle/service/nvdrv/nvdrv.h"
|
|
|
#include "core/hle/service/nvflinger/buffer_queue.h"
|
|
|
#include "core/hle/service/nvflinger/buffer_queue.h"
|
|
|
#include "core/hle/service/nvflinger/nvflinger.h"
|
|
|
#include "core/hle/service/nvflinger/nvflinger.h"
|
|
|
@ -328,32 +329,22 @@ public: |
|
|
Data data; |
|
|
Data data; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
struct BufferProducerFence { |
|
|
|
|
|
u32 is_valid; |
|
|
|
|
|
std::array<Nvidia::IoctlFence, 4> fences; |
|
|
|
|
|
}; |
|
|
|
|
|
static_assert(sizeof(BufferProducerFence) == 36, "BufferProducerFence has wrong size"); |
|
|
|
|
|
|
|
|
|
|
|
class IGBPDequeueBufferResponseParcel : public Parcel { |
|
|
class IGBPDequeueBufferResponseParcel : public Parcel { |
|
|
public: |
|
|
public: |
|
|
explicit IGBPDequeueBufferResponseParcel(u32 slot) : slot(slot) {} |
|
|
|
|
|
|
|
|
explicit IGBPDequeueBufferResponseParcel(u32 slot, Service::Nvidia::MultiFence& multi_fence) |
|
|
|
|
|
: slot(slot), multi_fence(multi_fence) {} |
|
|
~IGBPDequeueBufferResponseParcel() override = default; |
|
|
~IGBPDequeueBufferResponseParcel() override = default; |
|
|
|
|
|
|
|
|
protected: |
|
|
protected: |
|
|
void SerializeData() override { |
|
|
void SerializeData() override { |
|
|
// TODO(Subv): Find out how this Fence is used.
|
|
|
|
|
|
BufferProducerFence fence = {}; |
|
|
|
|
|
fence.is_valid = 1; |
|
|
|
|
|
for (auto& fence_ : fence.fences) |
|
|
|
|
|
fence_.id = -1; |
|
|
|
|
|
|
|
|
|
|
|
Write(slot); |
|
|
Write(slot); |
|
|
Write<u32_le>(1); |
|
|
Write<u32_le>(1); |
|
|
WriteObject(fence); |
|
|
|
|
|
|
|
|
WriteObject(multi_fence); |
|
|
Write<u32_le>(0); |
|
|
Write<u32_le>(0); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
u32_le slot; |
|
|
u32_le slot; |
|
|
|
|
|
Service::Nvidia::MultiFence multi_fence; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
class IGBPRequestBufferRequestParcel : public Parcel { |
|
|
class IGBPRequestBufferRequestParcel : public Parcel { |
|
|
@ -400,12 +391,6 @@ public: |
|
|
data = Read<Data>(); |
|
|
data = Read<Data>(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
struct Fence { |
|
|
|
|
|
u32_le id; |
|
|
|
|
|
u32_le value; |
|
|
|
|
|
}; |
|
|
|
|
|
static_assert(sizeof(Fence) == 8, "Fence has wrong size"); |
|
|
|
|
|
|
|
|
|
|
|
struct Data { |
|
|
struct Data { |
|
|
u32_le slot; |
|
|
u32_le slot; |
|
|
INSERT_PADDING_WORDS(3); |
|
|
INSERT_PADDING_WORDS(3); |
|
|
@ -420,14 +405,13 @@ public: |
|
|
u32_le sticky_transform; |
|
|
u32_le sticky_transform; |
|
|
INSERT_PADDING_WORDS(1); |
|
|
INSERT_PADDING_WORDS(1); |
|
|
u32_le swap_interval; |
|
|
u32_le swap_interval; |
|
|
u32_le fence_is_valid; |
|
|
|
|
|
std::array<Fence, 2> fences; |
|
|
|
|
|
|
|
|
Service::Nvidia::MultiFence multi_fence; |
|
|
|
|
|
|
|
|
Common::Rectangle<int> GetCropRect() const { |
|
|
Common::Rectangle<int> GetCropRect() const { |
|
|
return {crop_left, crop_top, crop_right, crop_bottom}; |
|
|
return {crop_left, crop_top, crop_right, crop_bottom}; |
|
|
} |
|
|
} |
|
|
}; |
|
|
}; |
|
|
static_assert(sizeof(Data) == 80, "ParcelData has wrong size"); |
|
|
|
|
|
|
|
|
static_assert(sizeof(Data) == 96, "ParcelData has wrong size"); |
|
|
|
|
|
|
|
|
Data data; |
|
|
Data data; |
|
|
}; |
|
|
}; |
|
|
@ -548,11 +532,11 @@ private: |
|
|
IGBPDequeueBufferRequestParcel request{ctx.ReadBuffer()}; |
|
|
IGBPDequeueBufferRequestParcel request{ctx.ReadBuffer()}; |
|
|
const u32 width{request.data.width}; |
|
|
const u32 width{request.data.width}; |
|
|
const u32 height{request.data.height}; |
|
|
const u32 height{request.data.height}; |
|
|
std::optional<u32> slot = buffer_queue.DequeueBuffer(width, height); |
|
|
|
|
|
|
|
|
auto result = buffer_queue.DequeueBuffer(width, height); |
|
|
|
|
|
|
|
|
if (slot) { |
|
|
|
|
|
|
|
|
if (result) { |
|
|
// Buffer is available
|
|
|
// Buffer is available
|
|
|
IGBPDequeueBufferResponseParcel response{*slot}; |
|
|
|
|
|
|
|
|
IGBPDequeueBufferResponseParcel response{(*result).first, *(*result).second}; |
|
|
ctx.WriteBuffer(response.Serialize()); |
|
|
ctx.WriteBuffer(response.Serialize()); |
|
|
} else { |
|
|
} else { |
|
|
// Wait the current thread until a buffer becomes available
|
|
|
// Wait the current thread until a buffer becomes available
|
|
|
@ -562,10 +546,11 @@ private: |
|
|
Kernel::ThreadWakeupReason reason) { |
|
|
Kernel::ThreadWakeupReason reason) { |
|
|
// Repeat TransactParcel DequeueBuffer when a buffer is available
|
|
|
// Repeat TransactParcel DequeueBuffer when a buffer is available
|
|
|
auto& buffer_queue = nv_flinger->FindBufferQueue(id); |
|
|
auto& buffer_queue = nv_flinger->FindBufferQueue(id); |
|
|
std::optional<u32> slot = buffer_queue.DequeueBuffer(width, height); |
|
|
|
|
|
ASSERT_MSG(slot != std::nullopt, "Could not dequeue buffer."); |
|
|
|
|
|
|
|
|
auto result = buffer_queue.DequeueBuffer(width, height); |
|
|
|
|
|
ASSERT_MSG(result != std::nullopt, "Could not dequeue buffer."); |
|
|
|
|
|
|
|
|
IGBPDequeueBufferResponseParcel response{*slot}; |
|
|
|
|
|
|
|
|
IGBPDequeueBufferResponseParcel response{(*result).first, |
|
|
|
|
|
*(*result).second}; |
|
|
ctx.WriteBuffer(response.Serialize()); |
|
|
ctx.WriteBuffer(response.Serialize()); |
|
|
IPC::ResponseBuilder rb{ctx, 2}; |
|
|
IPC::ResponseBuilder rb{ctx, 2}; |
|
|
rb.Push(RESULT_SUCCESS); |
|
|
rb.Push(RESULT_SUCCESS); |
|
|
@ -583,7 +568,8 @@ private: |
|
|
IGBPQueueBufferRequestParcel request{ctx.ReadBuffer()}; |
|
|
IGBPQueueBufferRequestParcel request{ctx.ReadBuffer()}; |
|
|
|
|
|
|
|
|
buffer_queue.QueueBuffer(request.data.slot, request.data.transform, |
|
|
buffer_queue.QueueBuffer(request.data.slot, request.data.transform, |
|
|
request.data.GetCropRect(), request.data.swap_interval); |
|
|
|
|
|
|
|
|
request.data.GetCropRect(), request.data.swap_interval, |
|
|
|
|
|
request.data.multi_fence); |
|
|
|
|
|
|
|
|
IGBPQueueBufferResponseParcel response{1280, 720}; |
|
|
IGBPQueueBufferResponseParcel response{1280, 720}; |
|
|
ctx.WriteBuffer(response.Serialize()); |
|
|
ctx.WriteBuffer(response.Serialize()); |
|
|
|