aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Gpu/Window.cs
blob: d5494aa4f7a4f1f735174b29f62258b5cd0c4506 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Gpu.Image;
using System;
using System.Collections.Concurrent;

namespace Ryujinx.Graphics.Gpu
{
    using Texture = Image.Texture;

    public class Window
    {
        private readonly GpuContext _context;

        private struct PresentationTexture
        {
            public TextureInfo    Info     { get; }
            public ImageCrop      Crop     { get; }
            public Action<object> Callback { get; }
            public object         UserObj  { get; }

            public PresentationTexture(
                TextureInfo    info,
                ImageCrop      crop,
                Action<object> callback,
                object         userObj)
            {
                Info     = info;
                Crop     = crop;
                Callback = callback;
                UserObj  = userObj;
            }
        }

        private readonly ConcurrentQueue<PresentationTexture> _frameQueue;

        public Window(GpuContext context)
        {
            _context = context;

            _frameQueue = new ConcurrentQueue<PresentationTexture>();
        }

        public void EnqueueFrameThreadSafe(
            ulong          address,
            int            width,
            int            height,
            int            stride,
            bool           isLinear,
            int            gobBlocksInY,
            Format         format,
            int            bytesPerPixel,
            ImageCrop      crop,
            Action<object> callback,
            object         userObj)
        {
            FormatInfo formatInfo = new FormatInfo(format, 1, 1, bytesPerPixel);

            TextureInfo info = new TextureInfo(
                address,
                width,
                height,
                1,
                1,
                1,
                1,
                stride,
                isLinear,
                gobBlocksInY,
                1,
                1,
                Target.Texture2D,
                formatInfo);

            _frameQueue.Enqueue(new PresentationTexture(info, crop, callback, userObj));
        }

        public void Present(Action swapBuffersCallback)
        {
            _context.AdvanceSequence();

            if (_frameQueue.TryDequeue(out PresentationTexture pt))
            {
                Texture texture = _context.Methods.TextureManager.FindOrCreateTexture(pt.Info);

                texture.SynchronizeMemory();

                _context.Renderer.Window.Present(texture.HostTexture, pt.Crop);

                swapBuffersCallback();

                pt.Callback(pt.UserObj);
            }
        }
    }
}