From 749043c80971536279768e2dcb2d442cf491262f Mon Sep 17 00:00:00 2001
From: Subv <subv2112@gmail.com>
Date: Sun, 21 Jan 2018 11:13:47 -0500
Subject: [PATCH] VI: Implement the Query transaction of IHOSBinderDriver, and
 stubbed some results.

---
 src/core/hle/service/vi/vi.cpp | 51 ++++++++++++++++++++++++++++++++++
 src/core/hle/service/vi/vi.h   |  7 +++++
 2 files changed, 58 insertions(+)

diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index c624e734e3..3f2fd72b2d 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -356,6 +356,35 @@ private:
     Data data{};
 };
 
+class IGBPQueryRequestParcel : public Parcel {
+public:
+    explicit IGBPQueryRequestParcel(const std::vector<u8>& buffer) : Parcel(buffer) {
+        Deserialize();
+    }
+    ~IGBPQueryRequestParcel() override = default;
+
+    void DeserializeData() override {
+        std::u16string token = ReadInterfaceToken();
+        type = Read<u32_le>();
+    }
+
+    u32 type;
+};
+
+class IGBPQueryResponseParcel : public Parcel {
+public:
+    explicit IGBPQueryResponseParcel(u32 value) : Parcel(), value(value) {}
+    ~IGBPQueryResponseParcel() override = default;
+
+protected:
+    void SerializeData() override {
+        Write(value);
+    }
+
+private:
+    u32_le value;
+};
+
 class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> {
 public:
     explicit IHOSBinderDriver(std::shared_ptr<NVFlinger> nv_flinger)
@@ -445,6 +474,15 @@ private:
             auto response_buffer = response.Serialize();
             Memory::WriteBlock(output_buffer.Address(), response_buffer.data(),
                                output_buffer.Size());
+        } else if (transaction == TransactionId::Query) {
+            IGBPQueryRequestParcel request{input_data};
+
+            u32 value = buffer_queue->Query(static_cast<BufferQueue::QueryType>(request.type));
+
+            IGBPQueryResponseParcel response{value};
+            auto response_buffer = response.Serialize();
+            Memory::WriteBlock(output_buffer.Address(), response_buffer.data(),
+                               output_buffer.Size());
         } else {
             ASSERT_MSG(false, "Unimplemented");
         }
@@ -918,6 +956,19 @@ void BufferQueue::ReleaseBuffer(u32 slot) {
     itr->status = Buffer::Status::Free;
 }
 
+u32 BufferQueue::Query(QueryType type) {
+    LOG_WARNING(Service, "(STUBBED) called type=%u", static_cast<u32>(type));
+    switch (type) {
+    case QueryType::NativeWindowFormat:
+        // TODO(Subv): Use an enum for this
+        static constexpr u32 FormatABGR8 = 1;
+        return FormatABGR8;
+    }
+
+    UNIMPLEMENTED();
+    return 0;
+}
+
 Layer::Layer(u64 id, std::shared_ptr<BufferQueue> queue) : id(id), buffer_queue(std::move(queue)) {}
 
 Display::Display(u64 id, std::string name) : id(id), name(std::move(name)) {
diff --git a/src/core/hle/service/vi/vi.h b/src/core/hle/service/vi/vi.h
index 81d4f3daa0..4dd4d17833 100644
--- a/src/core/hle/service/vi/vi.h
+++ b/src/core/hle/service/vi/vi.h
@@ -37,6 +37,12 @@ static_assert(sizeof(IGBPBuffer) == 0x16C, "IGBPBuffer has wrong size");
 
 class BufferQueue {
 public:
+    enum class QueryType {
+        NativeWindowWidth = 0,
+        NativeWindowHeight = 1,
+        NativeWindowFormat = 2,
+    };
+
     BufferQueue(u32 id, u64 layer_id);
     ~BufferQueue() = default;
 
@@ -54,6 +60,7 @@ public:
     void QueueBuffer(u32 slot);
     boost::optional<const Buffer&> AcquireBuffer();
     void ReleaseBuffer(u32 slot);
+    u32 Query(QueryType type);
 
     u32 GetId() const {
         return id;