Просмотр исходного кода

Merge pull request #177 from bunnei/vi-fixes

Several misc. VI fixes
bunnei 8 лет назад
Родитель
Сommit
890e98a33e

+ 4 - 2
src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp

@@ -20,15 +20,17 @@ u32 nvdisp_disp0::ioctl(Ioctl command, const std::vector<u8>& input, std::vector
 }
 
 void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height,
-                        u32 stride) {
+                        u32 stride, NVFlinger::BufferQueue::BufferTransformFlags transform) {
     VAddr addr = nvmap_dev->GetObjectAddress(buffer_handle);
     LOG_WARNING(Service,
                 "Drawing from address %llx offset %08X Width %u Height %u Stride %u Format %u",
                 addr, offset, width, height, stride, format);
 
     using PixelFormat = RendererBase::FramebufferInfo::PixelFormat;
+    using Flags = NVFlinger::BufferQueue::BufferTransformFlags;
+    const bool flip_vertical = static_cast<u32>(transform) & static_cast<u32>(Flags::FlipV);
     const RendererBase::FramebufferInfo framebuffer_info{
-        addr, offset, width, height, stride, static_cast<PixelFormat>(format)};
+        addr, offset, width, height, stride, static_cast<PixelFormat>(format), flip_vertical};
 
     Core::System::GetInstance().perf_stats.EndGameFrame();
     VideoCore::g_renderer->SwapBuffers(framebuffer_info);

+ 3 - 1
src/core/hle/service/nvdrv/devices/nvdisp_disp0.h

@@ -8,6 +8,7 @@
 #include <vector>
 #include "common/common_types.h"
 #include "core/hle/service/nvdrv/devices/nvdevice.h"
+#include "core/hle/service/nvflinger/buffer_queue.h"
 
 namespace Service {
 namespace Nvidia {
@@ -23,7 +24,8 @@ public:
     u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
 
     /// Performs a screen flip, drawing the buffer pointed to by the handle.
-    void flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height, u32 stride);
+    void flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height, u32 stride,
+              NVFlinger::BufferQueue::BufferTransformFlags transform);
 
 private:
     std::shared_ptr<nvmap> nvmap_dev;

+ 2 - 1
src/core/hle/service/nvflinger/buffer_queue.cpp

@@ -58,12 +58,13 @@ const IGBPBuffer& BufferQueue::RequestBuffer(u32 slot) const {
     return itr->igbp_buffer;
 }
 
-void BufferQueue::QueueBuffer(u32 slot) {
+void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform) {
     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;
+    itr->transform = transform;
 }
 
 boost::optional<const BufferQueue::Buffer&> BufferQueue::AcquireBuffer() {

+ 15 - 1
src/core/hle/service/nvflinger/buffer_queue.h

@@ -46,18 +46,32 @@ public:
     BufferQueue(u32 id, u64 layer_id);
     ~BufferQueue() = default;
 
+    enum class BufferTransformFlags : u32 {
+        /// Flip source image horizontally (around the vertical axis)
+        FlipH = 0x01,
+        /// Flip source image vertically (around the horizontal axis)
+        FlipV = 0x02,
+        /// Rotate source image 90 degrees clockwise
+        Rotate90 = 0x04,
+        /// Rotate source image 180 degrees
+        Roate180 = 0x03,
+        /// Rotate source image 270 degrees clockwise
+        Roate270 = 0x07,
+    };
+
     struct Buffer {
         enum class Status { Free = 0, Queued = 1, Dequeued = 2, Acquired = 3 };
 
         u32 slot;
         Status status = Status::Free;
         IGBPBuffer igbp_buffer;
+        BufferTransformFlags transform;
     };
 
     void SetPreallocatedBuffer(u32 slot, IGBPBuffer& buffer);
     u32 DequeueBuffer(u32 pixel_format, u32 width, u32 height);
     const IGBPBuffer& RequestBuffer(u32 slot) const;
-    void QueueBuffer(u32 slot);
+    void QueueBuffer(u32 slot, BufferTransformFlags transform);
     boost::optional<const Buffer&> AcquireBuffer();
     void ReleaseBuffer(u32 slot);
     u32 Query(QueryType type);

+ 1 - 1
src/core/hle/service/nvflinger/nvflinger.cpp

@@ -145,7 +145,7 @@ void NVFlinger::Compose() {
         ASSERT(nvdisp);
 
         nvdisp->flip(igbp_buffer.gpu_buffer_id, igbp_buffer.offset, igbp_buffer.format,
-                     igbp_buffer.width, igbp_buffer.height, igbp_buffer.stride);
+                     igbp_buffer.width, igbp_buffer.height, igbp_buffer.stride, buffer->transform);
 
         buffer_queue->ReleaseBuffer(buffer->slot);
     }

+ 29 - 11
src/core/hle/service/vi/vi.cpp

@@ -3,7 +3,7 @@
 // Refer to the license.txt file included.
 
 #include <algorithm>
-
+#include <array>
 #include "common/alignment.h"
 #include "common/scope_exit.h"
 #include "core/core_timing.h"
@@ -101,8 +101,10 @@ public:
         SerializeData();
 
         Header header{};
-        header.data_offset = sizeof(Header);
         header.data_size = static_cast<u32_le>(write_index - sizeof(Header));
+        header.data_offset = sizeof(Header);
+        header.objects_size = 4;
+        header.objects_offset = sizeof(Header) + header.data_size;
         std::memcpy(buffer.data(), &header, sizeof(Header));
 
         return buffer;
@@ -142,11 +144,11 @@ protected:
 private:
     struct Data {
         u32_le magic = 2;
-        u32_le process_id;
+        u32_le process_id = 1;
         u32_le id;
-        INSERT_PADDING_BYTES(0xC);
+        INSERT_PADDING_WORDS(3);
         std::array<u8, 8> dispdrv = {'d', 'i', 's', 'p', 'd', 'r', 'v', '\0'};
-        INSERT_PADDING_BYTES(8);
+        INSERT_PADDING_WORDS(2);
     };
     static_assert(sizeof(Data) == 0x28, "ParcelData has wrong size");
 
@@ -323,13 +325,29 @@ public:
         data = Read<Data>();
     }
 
+    struct Fence {
+        u32_le id;
+        u32_le value;
+    };
+    static_assert(sizeof(Fence) == 8, "Fence has wrong size");
+
     struct Data {
         u32_le slot;
-        INSERT_PADDING_WORDS(2);
+        INSERT_PADDING_WORDS(3);
         u32_le timestamp;
-        INSERT_PADDING_WORDS(20);
+        s32_le is_auto_timestamp;
+        s32_le crop_left;
+        s32_le crop_top;
+        s32_le crop_right;
+        s32_le crop_bottom;
+        s32_le scaling_mode;
+        NVFlinger::BufferQueue::BufferTransformFlags transform;
+        u32_le sticky_transform;
+        INSERT_PADDING_WORDS(2);
+        u32_le fence_is_valid;
+        std::array<Fence, 2> fences;
     };
-    static_assert(sizeof(Data) == 96, "ParcelData has wrong size");
+    static_assert(sizeof(Data) == 80, "ParcelData has wrong size");
 
     Data data;
 };
@@ -454,7 +472,7 @@ private:
         } else if (transaction == TransactionId::QueueBuffer) {
             IGBPQueueBufferRequestParcel request{input_data};
 
-            buffer_queue->QueueBuffer(request.data.slot);
+            buffer_queue->QueueBuffer(request.data.slot, request.data.transform);
 
             IGBPQueueBufferResponseParcel response{1280, 720};
             response_buffer = response.Serialize();
@@ -672,7 +690,7 @@ void IApplicationDisplayService::CloseDisplay(Kernel::HLERequestContext& ctx) {
 }
 
 void IApplicationDisplayService::OpenLayer(Kernel::HLERequestContext& ctx) {
-    LOG_WARNING(Service_VI, "(STUBBED) called");
+    LOG_DEBUG(Service_VI, "called");
     IPC::RequestParser rp{ctx};
     auto name_buf = rp.PopRaw<std::array<u8, 0x40>>();
     auto end = std::find(name_buf.begin(), name_buf.end(), '\0');
@@ -697,7 +715,7 @@ void IApplicationDisplayService::OpenLayer(Kernel::HLERequestContext& ctx) {
 }
 
 void IApplicationDisplayService::CreateStrayLayer(Kernel::HLERequestContext& ctx) {
-    LOG_WARNING(Service, "(STUBBED) called");
+    LOG_DEBUG(Service_VI, "called");
 
     IPC::RequestParser rp{ctx};
     u32 flags = rp.Pop<u32>();

+ 1 - 0
src/video_core/renderer_base.h

@@ -43,6 +43,7 @@ public:
         u32 height;
         u32 stride;
         PixelFormat pixel_format;
+        bool flip_vertical;
     };
 
     virtual ~RendererBase() {}

+ 9 - 5
src/video_core/renderer_opengl/renderer_opengl.cpp

@@ -262,6 +262,8 @@ void RendererOpenGL::LoadFBToScreenInfo(const FramebufferInfo& framebuffer_info,
     // only allows rows to have a memory alignement of 4.
     ASSERT(framebuffer_info.stride % 4 == 0);
 
+    framebuffer_flip_vertical = framebuffer_info.flip_vertical;
+
     // Reset the screen info's display texture to its own permanent texture
     screen_info.display_texture = screen_info.texture.resource.handle;
     screen_info.display_texcoords = MathUtil::Rectangle<float>(0.f, 0.f, 1.f, 1.f);
@@ -401,13 +403,15 @@ void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,
 
 void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float x, float y, float w,
                                       float h) {
-    auto& texcoords = screen_info.display_texcoords;
+    const auto& texcoords = screen_info.display_texcoords;
+    const auto& left = framebuffer_flip_vertical ? texcoords.right : texcoords.left;
+    const auto& right = framebuffer_flip_vertical ? texcoords.left : texcoords.right;
 
     std::array<ScreenRectVertex, 4> vertices = {{
-        ScreenRectVertex(x, y, texcoords.top, texcoords.right),
-        ScreenRectVertex(x + w, y, texcoords.bottom, texcoords.right),
-        ScreenRectVertex(x, y + h, texcoords.top, texcoords.left),
-        ScreenRectVertex(x + w, y + h, texcoords.bottom, texcoords.left),
+        ScreenRectVertex(x, y, texcoords.top, right),
+        ScreenRectVertex(x + w, y, texcoords.bottom, right),
+        ScreenRectVertex(x, y + h, texcoords.top, left),
+        ScreenRectVertex(x + w, y + h, texcoords.bottom, left),
     }};
 
     state.texture_units[0].texture_2d = screen_info.display_texture;

+ 3 - 0
src/video_core/renderer_opengl/renderer_opengl.h

@@ -86,4 +86,7 @@ private:
     // Shader attribute input indices
     GLuint attrib_position;
     GLuint attrib_tex_coord;
+
+    /// Flips the framebuffer vertically when true
+    bool framebuffer_flip_vertical;
 };