1758b4ee8SAndy Ritger /*
2758b4ee8SAndy Ritger * SPDX-FileCopyrightText: Copyright (c) 2017-2020 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3758b4ee8SAndy Ritger * SPDX-License-Identifier: MIT
4758b4ee8SAndy Ritger *
5758b4ee8SAndy Ritger * Permission is hereby granted, free of charge, to any person obtaining a
6758b4ee8SAndy Ritger * copy of this software and associated documentation files (the "Software"),
7758b4ee8SAndy Ritger * to deal in the Software without restriction, including without limitation
8758b4ee8SAndy Ritger * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9758b4ee8SAndy Ritger * and/or sell copies of the Software, and to permit persons to whom the
10758b4ee8SAndy Ritger * Software is furnished to do so, subject to the following conditions:
11758b4ee8SAndy Ritger *
12758b4ee8SAndy Ritger * The above copyright notice and this permission notice shall be included in
13758b4ee8SAndy Ritger * all copies or substantial portions of the Software.
14758b4ee8SAndy Ritger *
15758b4ee8SAndy Ritger * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16758b4ee8SAndy Ritger * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17758b4ee8SAndy Ritger * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18758b4ee8SAndy Ritger * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19758b4ee8SAndy Ritger * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20758b4ee8SAndy Ritger * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21758b4ee8SAndy Ritger * DEALINGS IN THE SOFTWARE.
22758b4ee8SAndy Ritger */
23758b4ee8SAndy Ritger
24758b4ee8SAndy Ritger #ifndef __NVKMS_HEADSURFACE_PRIV_H__
25758b4ee8SAndy Ritger #define __NVKMS_HEADSURFACE_PRIV_H__
26758b4ee8SAndy Ritger
27758b4ee8SAndy Ritger #include "nvkms-types.h"
28758b4ee8SAndy Ritger #include "nvkms-headsurface.h"
29758b4ee8SAndy Ritger #include "nvkms-headsurface-config.h"
30758b4ee8SAndy Ritger #include "nvkms-surface.h"
31758b4ee8SAndy Ritger #include "nvkms-utils.h"
32758b4ee8SAndy Ritger
33758b4ee8SAndy Ritger #include "nvidia-push-init.h"
34758b4ee8SAndy Ritger #include "nvidia-3d.h"
35758b4ee8SAndy Ritger
36758b4ee8SAndy Ritger #include "nv_list.h"
37758b4ee8SAndy Ritger
38758b4ee8SAndy Ritger /*
39758b4ee8SAndy Ritger * This header file defines structures shared by the nvkms-headsurface*.c source
40758b4ee8SAndy Ritger * files. To the rest of nvkms, these structures should be opaque.
41758b4ee8SAndy Ritger */
42758b4ee8SAndy Ritger
43758b4ee8SAndy Ritger #define NVKMS_HEAD_SURFACE_MAX_NOTIFIERS_PER_HEAD 4
44758b4ee8SAndy Ritger #define NVKMS_HEAD_SURFACE_MAX_NOTIFIER_SIZE 16
45758b4ee8SAndy Ritger #define NVKMS_HEAD_SURFACE_NOTIFIER_BYTES_PER_HEAD \
46758b4ee8SAndy Ritger (NVKMS_HEAD_SURFACE_MAX_NOTIFIERS_PER_HEAD * \
47758b4ee8SAndy Ritger NVKMS_HEAD_SURFACE_MAX_NOTIFIER_SIZE)
48758b4ee8SAndy Ritger
49758b4ee8SAndy Ritger #define NVKMS_HEAD_SURFACE_MAX_FRAME_SEMAPHORES 2
50758b4ee8SAndy Ritger
51758b4ee8SAndy Ritger #define NVKMS_HEAD_SURFACE_SEMAPHORE_BYTES_PER_HEAD \
52758b4ee8SAndy Ritger (sizeof(NvGpuSemaphore) * NVKMS_HEAD_SURFACE_MAX_FRAME_SEMAPHORES)
53758b4ee8SAndy Ritger
54758b4ee8SAndy Ritger #define NVKMS_HEAD_SURFACE_FRAME_SEMAPHORE_DISPLAYABLE 0xFFFFFFFF
55758b4ee8SAndy Ritger #define NVKMS_HEAD_SURFACE_FRAME_SEMAPHORE_RENDERABLE 0x11111111
56758b4ee8SAndy Ritger
57758b4ee8SAndy Ritger /*
58758b4ee8SAndy Ritger * XXX NVKMS HEADSURFACE TODO: HeadSurface uses both notifiers and semaphores
59758b4ee8SAndy Ritger * for synchronization:
60758b4ee8SAndy Ritger *
61758b4ee8SAndy Ritger * - Notifiers to ensure the CPU waits until after the previous frame's flip
62758b4ee8SAndy Ritger * completes before starting the next frame.
63758b4ee8SAndy Ritger *
64758b4ee8SAndy Ritger * - Semaphores to ensure the flip to the next frame is not started until the
65758b4ee8SAndy Ritger * rendering for the next frame completes.
66758b4ee8SAndy Ritger *
67758b4ee8SAndy Ritger * We should simplify things by using semaphores for both.
68758b4ee8SAndy Ritger */
69758b4ee8SAndy Ritger typedef struct _NVHsNotifiersOneSdRec {
70758b4ee8SAndy Ritger NvU8 notifier
71758b4ee8SAndy Ritger [NVKMS_MAX_HEADS_PER_DISP][NVKMS_HEAD_SURFACE_NOTIFIER_BYTES_PER_HEAD];
72758b4ee8SAndy Ritger NvU8 semaphore
73758b4ee8SAndy Ritger [NVKMS_MAX_HEADS_PER_DISP][NVKMS_HEAD_SURFACE_SEMAPHORE_BYTES_PER_HEAD];
74758b4ee8SAndy Ritger } NVHsNotifiersOneSdRec;
75758b4ee8SAndy Ritger
76758b4ee8SAndy Ritger #define NVKMS_HEAD_SURFACE_NOTIFIERS_SIZE_IN_BYTES 4096
77758b4ee8SAndy Ritger
78758b4ee8SAndy Ritger ct_assert(NVKMS_HEAD_SURFACE_NOTIFIERS_SIZE_IN_BYTES >=
79758b4ee8SAndy Ritger sizeof(NVHsNotifiersOneSdRec));
80758b4ee8SAndy Ritger
81758b4ee8SAndy Ritger typedef struct _NVHsNotifiersRec {
82758b4ee8SAndy Ritger
83758b4ee8SAndy Ritger NvU32 rmHandle;
84758b4ee8SAndy Ritger NvKmsSurfaceHandle nvKmsHandle;
85758b4ee8SAndy Ritger const NVSurfaceEvoRec *pSurfaceEvo;
86758b4ee8SAndy Ritger
87758b4ee8SAndy Ritger struct {
88758b4ee8SAndy Ritger NVHsNotifiersOneSdRec *ptr;
89758b4ee8SAndy Ritger struct {
90758b4ee8SAndy Ritger NvU8 nextSlot;
91758b4ee8SAndy Ritger } apiHead[NVKMS_MAX_HEADS_PER_DISP];
92758b4ee8SAndy Ritger } sd[NVKMS_MAX_SUBDEVICES];
93758b4ee8SAndy Ritger
94758b4ee8SAndy Ritger enum NvKmsNIsoFormat nIsoFormat;
95758b4ee8SAndy Ritger
96758b4ee8SAndy Ritger } NVHsNotifiersRec;
97758b4ee8SAndy Ritger
98758b4ee8SAndy Ritger typedef struct _NVHsSurfaceRec {
99758b4ee8SAndy Ritger
100758b4ee8SAndy Ritger NvKmsSurfaceHandle nvKmsHandle;
101758b4ee8SAndy Ritger NvU32 rmHandle;
102758b4ee8SAndy Ritger
103758b4ee8SAndy Ritger Nv3dBlockLinearLog2GobsPerBlock gobsPerBlock;
104758b4ee8SAndy Ritger
105758b4ee8SAndy Ritger const NVSurfaceEvoRec *pSurfaceEvo;
106758b4ee8SAndy Ritger
107758b4ee8SAndy Ritger } NVHsSurfaceRec;
108758b4ee8SAndy Ritger
109758b4ee8SAndy Ritger typedef struct _NVHsDeviceEvoRec {
110758b4ee8SAndy Ritger
111758b4ee8SAndy Ritger NVDevEvoRec *pDevEvo;
112758b4ee8SAndy Ritger
113758b4ee8SAndy Ritger NvU32 gpuVASpace;
114758b4ee8SAndy Ritger
115758b4ee8SAndy Ritger struct {
116758b4ee8SAndy Ritger Nv3dDeviceRec device;
117758b4ee8SAndy Ritger } nv3d;
118758b4ee8SAndy Ritger
119758b4ee8SAndy Ritger NVHsNotifiersRec notifiers;
120758b4ee8SAndy Ritger
121758b4ee8SAndy Ritger } NVHsDeviceEvoRec;
122758b4ee8SAndy Ritger
123758b4ee8SAndy Ritger enum NVHsChannelTexInfoEnum {
124758b4ee8SAndy Ritger NVKMS_HEADSURFACE_TEXINFO_SRC = 0,
125758b4ee8SAndy Ritger /* XXX NVKMS HEADSURFACE TODO: enable all the below */
126758b4ee8SAndy Ritger NVKMS_HEADSURFACE_TEXINFO_CURSOR = 1,
127758b4ee8SAndy Ritger NVKMS_HEADSURFACE_TEXINFO_BLEND = 2,
128758b4ee8SAndy Ritger NVKMS_HEADSURFACE_TEXINFO_OFFSET = 3,
129758b4ee8SAndy Ritger NVKMS_HEADSURFACE_TEXINFO_OVERLAY = 4,
130758b4ee8SAndy Ritger /* NVKMS_HEADSURFACE_TEXINFO_LUT = 5, */
131758b4ee8SAndy Ritger NVKMS_HEADSURFACE_TEXINFO_NUM,
132758b4ee8SAndy Ritger };
133758b4ee8SAndy Ritger
134758b4ee8SAndy Ritger typedef struct _NVHsChannelStatisticsOneEyeRec {
135758b4ee8SAndy Ritger /* Running total of the number of frames rendered by headSurface. */
136758b4ee8SAndy Ritger NvU64 nFrames;
137758b4ee8SAndy Ritger
138758b4ee8SAndy Ritger /* Running total of the GPU time spent rendering, in nanoseconds. */
139758b4ee8SAndy Ritger NvU64 gpuTimeSpent;
140758b4ee8SAndy Ritger
141758b4ee8SAndy Ritger /* We compute the FPS for 5 second periods. */
142758b4ee8SAndy Ritger struct {
143758b4ee8SAndy Ritger /*
144758b4ee8SAndy Ritger * Running total of the number of frames rendered by headSurface; reset
145758b4ee8SAndy Ritger * every 5 seconds.
146758b4ee8SAndy Ritger */
147758b4ee8SAndy Ritger NvU64 nFrames;
148758b4ee8SAndy Ritger /*
149758b4ee8SAndy Ritger * The time, in nanoseconds, when this FPS period started, so we know
150758b4ee8SAndy Ritger * when the 5 second period is done.
151758b4ee8SAndy Ritger */
152758b4ee8SAndy Ritger NvU64 startTime;
153758b4ee8SAndy Ritger /*
154758b4ee8SAndy Ritger * Most recently computed FPS for the last 5 second period.
155758b4ee8SAndy Ritger */
156758b4ee8SAndy Ritger NvU64 framesPerMs;
157758b4ee8SAndy Ritger } fps;
158758b4ee8SAndy Ritger } NVHsChannelStatisticsOneEyeRec;
159758b4ee8SAndy Ritger
160758b4ee8SAndy Ritger typedef struct _NVHsChannelFlipQueueEntry {
161758b4ee8SAndy Ritger NVListRec flipQueueEntry;
1624397463eSAndy Ritger NVHsLayerRequestedFlipState hwState;
163758b4ee8SAndy Ritger } NVHsChannelFlipQueueEntry;
164758b4ee8SAndy Ritger
165758b4ee8SAndy Ritger typedef struct _NVHsChannelEvoRec {
166758b4ee8SAndy Ritger
167758b4ee8SAndy Ritger NVDispEvoRec *pDispEvo;
168758b4ee8SAndy Ritger
169758b4ee8SAndy Ritger NvU32 apiHead;
170758b4ee8SAndy Ritger
171758b4ee8SAndy Ritger struct {
172758b4ee8SAndy Ritger NvPushChannelRec channel;
173758b4ee8SAndy Ritger NvU32 handlePool[NV_PUSH_CHANNEL_HANDLE_POOL_NUM];
174758b4ee8SAndy Ritger } nvPush;
175758b4ee8SAndy Ritger
176758b4ee8SAndy Ritger struct {
177758b4ee8SAndy Ritger NvU32 handle;
178758b4ee8SAndy Ritger Nv3dChannelRec channel;
179758b4ee8SAndy Ritger Nv3dRenderTexInfo texInfo[NVKMS_HEADSURFACE_TEXINFO_NUM];
180758b4ee8SAndy Ritger } nv3d;
181758b4ee8SAndy Ritger
182758b4ee8SAndy Ritger struct {
183758b4ee8SAndy Ritger NvU32 handle;
184758b4ee8SAndy Ritger } nv2d;
185758b4ee8SAndy Ritger
186758b4ee8SAndy Ritger /*
1874397463eSAndy Ritger * Flip request parameters are too large to declare on the stack. We
1884397463eSAndy Ritger * preallocate them here so that we don't have to allocate and free them on
1894397463eSAndy Ritger * every headSurface flip.
190758b4ee8SAndy Ritger */
1914397463eSAndy Ritger struct NvKmsFlipRequestOneHead scratchParams;
192758b4ee8SAndy Ritger
193758b4ee8SAndy Ritger /*
194758b4ee8SAndy Ritger * The index into NVDevEvoRec::apiHeadSurfaceAllDisps[apiHead]::surface[] to use
195758b4ee8SAndy Ritger * for the next frame of headSurface.
196758b4ee8SAndy Ritger */
197758b4ee8SAndy Ritger NvU8 nextIndex;
198758b4ee8SAndy Ritger
199758b4ee8SAndy Ritger /*
200758b4ee8SAndy Ritger * When neededForSwapGroup is true, frames of headSurface are rendered to
201758b4ee8SAndy Ritger * alternating offsets within double-sized headSurface surfaces. nextOffset
202758b4ee8SAndy Ritger * is either 0 or 1, to select the offset of the next headSurface frame.
203758b4ee8SAndy Ritger */
204758b4ee8SAndy Ritger NvU8 nextOffset;
205758b4ee8SAndy Ritger
206758b4ee8SAndy Ritger /*
207758b4ee8SAndy Ritger * HeadSurface flips are semaphore interlocked with headSurface rendering.
208758b4ee8SAndy Ritger * We need to use a different semaphore offset for subsequent flips.
209758b4ee8SAndy Ritger * frameSemaphoreIndex is used to alternate between
210758b4ee8SAndy Ritger * NVKMS_HEAD_SURFACE_MAX_FRAME_SEMAPHORES offsets.
211758b4ee8SAndy Ritger */
212758b4ee8SAndy Ritger NvU8 frameSemaphoreIndex;
213758b4ee8SAndy Ritger
214758b4ee8SAndy Ritger NVHsChannelConfig config;
215758b4ee8SAndy Ritger
216758b4ee8SAndy Ritger NVVBlankCallbackPtr vBlankCallback;
217758b4ee8SAndy Ritger
218758b4ee8SAndy Ritger /*
219758b4ee8SAndy Ritger * NVHsChannelEvoRec keeps a list of flip queue entries, and the "current"
220758b4ee8SAndy Ritger * entry. NVHsChannelFlipQueueEntry is a single entry in the flip queue.
221758b4ee8SAndy Ritger *
222758b4ee8SAndy Ritger * Each entry describes a validated flip request. When NVKMS is called to
223758b4ee8SAndy Ritger * build the next frame of headSurface, it inspects if the next entry in the
224758b4ee8SAndy Ritger * queue is ready to flip (e.g., any semaphore acquires have been
225758b4ee8SAndy Ritger * satisfied). If the next flip queue entry is ready, we use it to replace
226758b4ee8SAndy Ritger * the current entry. Otherwise, we continue to use the existing current
227758b4ee8SAndy Ritger * entry.
228758b4ee8SAndy Ritger *
229758b4ee8SAndy Ritger * Surfaces within an NVHsChannelFlipQueueEntry have their reference counts:
230758b4ee8SAndy Ritger *
231758b4ee8SAndy Ritger * - incremented when the NVHsChannelFlipQueueEntry is added to the flip
232758b4ee8SAndy Ritger * queue.
233758b4ee8SAndy Ritger *
234758b4ee8SAndy Ritger * - decremented when the NVHsChannelFlipQueueEntry is removed from current
235758b4ee8SAndy Ritger * (i.e., when we do the equivalent of "flip away").
236758b4ee8SAndy Ritger *
237758b4ee8SAndy Ritger * To simulate EVO/NVDisplay semaphore behavior, if an
238758b4ee8SAndy Ritger * NVHsChannelFlipQueueEntry specifies a semaphore:
239758b4ee8SAndy Ritger *
240758b4ee8SAndy Ritger * - We wait for the semaphore's acquire value to be reached before
241758b4ee8SAndy Ritger * promoting the entry from the flip queue to current.
242758b4ee8SAndy Ritger *
243758b4ee8SAndy Ritger * - We write the semaphore's release value when the
244758b4ee8SAndy Ritger * NVHsChannelFlipQueueEntry is removed from current (i.e., when we do the
245758b4ee8SAndy Ritger * equivalent of "flip away").
246758b4ee8SAndy Ritger */
247758b4ee8SAndy Ritger
248758b4ee8SAndy Ritger struct {
2494397463eSAndy Ritger NVHsLayerRequestedFlipState current;
250758b4ee8SAndy Ritger NVListRec queue;
251758b4ee8SAndy Ritger } flipQueue[NVKMS_MAX_LAYERS_PER_HEAD];
252758b4ee8SAndy Ritger
253758b4ee8SAndy Ritger /*
254758b4ee8SAndy Ritger * This cached main layer surface needed when the main layer transitioning
255758b4ee8SAndy Ritger * out of headSurface due to exiting a swapgroup. I.e. in this path:
256758b4ee8SAndy Ritger * nvHsConfigStop() => HsConfigRestoreMainLayerSurface()
257758b4ee8SAndy Ritger */
258758b4ee8SAndy Ritger struct {
259758b4ee8SAndy Ritger NVSurfaceEvoPtr pSurfaceEvo[NVKMS_MAX_EYES];
260758b4ee8SAndy Ritger } flipQueueMainLayerState;
261758b4ee8SAndy Ritger
262758b4ee8SAndy Ritger NvU64 lastCallbackUSec;
263758b4ee8SAndy Ritger
264758b4ee8SAndy Ritger /*
265758b4ee8SAndy Ritger * For NVKMS headsurface swap groups, at some point after the flip has been
266758b4ee8SAndy Ritger * issued, NVKMS needs to check the notifier associated with that flip to
267758b4ee8SAndy Ritger * see if the flip has been completed and release the deferred request
268758b4ee8SAndy Ritger * fifo entry associated with that flip. This bool reflects whether that
269758b4ee8SAndy Ritger * check is done during the headsurface vblank interrupt callback or later
270758b4ee8SAndy Ritger * during the RG line 1 interrupt callback.
271758b4ee8SAndy Ritger */
272758b4ee8SAndy Ritger NvBool usingRgIntrForSwapGroups;
273758b4ee8SAndy Ritger
274758b4ee8SAndy Ritger /*
2754397463eSAndy Ritger * Pointer to the RG line interrupt callback object. This is needed to
276758b4ee8SAndy Ritger * enabled and disable the RG interrupt callback.
277758b4ee8SAndy Ritger */
2784397463eSAndy Ritger NVRgLine1CallbackPtr pRgIntrCallback;
279758b4ee8SAndy Ritger
280758b4ee8SAndy Ritger #if NVKMS_PROCFS_ENABLE
281758b4ee8SAndy Ritger
282758b4ee8SAndy Ritger /*
283758b4ee8SAndy Ritger * We track statistics differently for SwapGroup and non-SwapGroup
284758b4ee8SAndy Ritger * headSurface; abstract the grouping into "slots". For non-SwapGroup there
285758b4ee8SAndy Ritger * is only one rendered frame (one "slot"). For SwapGroup, there are three
286758b4ee8SAndy Ritger * different rendered frames (so three "slots").
287758b4ee8SAndy Ritger */
288758b4ee8SAndy Ritger #define NVKMS_HEADSURFACE_STATS_MAX_SLOTS 3
289758b4ee8SAndy Ritger
290758b4ee8SAndy Ritger #define NVKMS_HEADSURFACE_STATS_SEMAPHORE_BEFORE 0
291758b4ee8SAndy Ritger #define NVKMS_HEADSURFACE_STATS_SEMAPHORE_AFTER 1
292758b4ee8SAndy Ritger
293758b4ee8SAndy Ritger /*
294758b4ee8SAndy Ritger * One semaphore before the frame, and one semaphore after the frame.
295758b4ee8SAndy Ritger */
296758b4ee8SAndy Ritger #define NVKMS_HEAD_SURFACE_STATS_SEMAPHORE_STAGE_COUNT 2
297758b4ee8SAndy Ritger
298758b4ee8SAndy Ritger /*
299758b4ee8SAndy Ritger * We need semaphores for each stereo eye for each "slot".
300758b4ee8SAndy Ritger */
301758b4ee8SAndy Ritger #define NVKMS_HEADSURFACE_STATS_MAX_SEMAPHORES \
302758b4ee8SAndy Ritger (NVKMS_HEAD_SURFACE_STATS_SEMAPHORE_STAGE_COUNT * \
303758b4ee8SAndy Ritger NVKMS_MAX_EYES * \
304758b4ee8SAndy Ritger NVKMS_HEADSURFACE_STATS_MAX_SLOTS)
305758b4ee8SAndy Ritger
306758b4ee8SAndy Ritger struct {
307758b4ee8SAndy Ritger
308758b4ee8SAndy Ritger NVHsChannelStatisticsOneEyeRec
309758b4ee8SAndy Ritger perEye[NVKMS_MAX_EYES][NVKMS_HEADSURFACE_STATS_MAX_SLOTS];
310758b4ee8SAndy Ritger
311758b4ee8SAndy Ritger /* How often we were called back before the previous frame was done. */
312758b4ee8SAndy Ritger NvU64 nPreviousFrameNotDone;
313758b4ee8SAndy Ritger
314758b4ee8SAndy Ritger /* How often we did not update HS backbuffer with non-sg content. */
315758b4ee8SAndy Ritger NvU64 nOmittedNonSgHsUpdates;
316758b4ee8SAndy Ritger
317758b4ee8SAndy Ritger /* How often did we have fullscreen swapgroup, and didn't. */
318758b4ee8SAndy Ritger NvU64 nFullscreenSgFrames;
319758b4ee8SAndy Ritger NvU64 nNonFullscreenSgFrames;
320758b4ee8SAndy Ritger
321758b4ee8SAndy Ritger /*
322758b4ee8SAndy Ritger * Statistics on which Display Memory Interface (DMI) scanline we are on
323758b4ee8SAndy Ritger * when headSurface is called.
324758b4ee8SAndy Ritger *
325758b4ee8SAndy Ritger * pHistogram is a dynamically allocated array of counts. The array has
326758b4ee8SAndy Ritger * vVisible + 1 elements (the +1 is because the hardware-reported
327758b4ee8SAndy Ritger * scanline values are in the inclusive range [0,vVisible]). Each
328758b4ee8SAndy Ritger * element contains how many times we've been called back while on that
329758b4ee8SAndy Ritger * scanline.
330758b4ee8SAndy Ritger *
331758b4ee8SAndy Ritger * When in the blanking region, there isn't a DMI scanline. We
332758b4ee8SAndy Ritger * increment n{,Not}InBlankingPeriod to keep track of how often we are
333758b4ee8SAndy Ritger * called back while in the blanking region.
334758b4ee8SAndy Ritger */
335758b4ee8SAndy Ritger struct {
336758b4ee8SAndy Ritger NvU64 *pHistogram; /* array with vVisible elements */
337758b4ee8SAndy Ritger NvU16 vVisible;
338758b4ee8SAndy Ritger NvU64 nInBlankingPeriod;
339758b4ee8SAndy Ritger NvU64 nNotInBlankingPeriod;
340758b4ee8SAndy Ritger } scanLine;
341758b4ee8SAndy Ritger
342758b4ee8SAndy Ritger } statistics;
343758b4ee8SAndy Ritger #else
344758b4ee8SAndy Ritger #define NVKMS_HEADSURFACE_STATS_MAX_SEMAPHORES 0
345758b4ee8SAndy Ritger #endif /* NVKMS_PROCFS_ENABLE */
346758b4ee8SAndy Ritger
347758b4ee8SAndy Ritger /*
348758b4ee8SAndy Ritger * We need one semaphore for the non-stall interrupt following rendering to
349758b4ee8SAndy Ritger * the next viewport offset with swapgroups enabled.
350758b4ee8SAndy Ritger */
351758b4ee8SAndy Ritger #define NVKMS_HEADSURFACE_VIEWPORT_OFFSET_SEMAPHORE_INDEX \
352758b4ee8SAndy Ritger NVKMS_HEADSURFACE_STATS_MAX_SEMAPHORES
353758b4ee8SAndy Ritger
354758b4ee8SAndy Ritger #define NVKMS_HEADSURFACE_MAX_SEMAPHORES \
355758b4ee8SAndy Ritger (NVKMS_HEADSURFACE_VIEWPORT_OFFSET_SEMAPHORE_INDEX + 1)
356758b4ee8SAndy Ritger
357758b4ee8SAndy Ritger /*
358758b4ee8SAndy Ritger * Whether this channel has kicked off rendering to a new viewport offset
359758b4ee8SAndy Ritger * for non-swapgroup content updates, but hasn't yet kicked off the
360758b4ee8SAndy Ritger * viewport flip to the new offset. Used to prevent rendering a new
361758b4ee8SAndy Ritger * frame if rendering the previous frame took longer than a full frame of
362758b4ee8SAndy Ritger * scanout.
363758b4ee8SAndy Ritger */
364758b4ee8SAndy Ritger NvBool viewportFlipPending;
365758b4ee8SAndy Ritger
366758b4ee8SAndy Ritger /*
367758b4ee8SAndy Ritger * Recorded timestamp of the last headsurface flip. Used for deciding if
368758b4ee8SAndy Ritger * certain blits to the headsurface can be omitted.
369758b4ee8SAndy Ritger */
370758b4ee8SAndy Ritger NvU64 lastHsClientFlipTimeUs;
371758b4ee8SAndy Ritger
372758b4ee8SAndy Ritger /*
373758b4ee8SAndy Ritger * If this channel has kicked off a real flip while swapgroups were active,
374758b4ee8SAndy Ritger * mark this channel as using real flips instead of blits for swapgroups,
375758b4ee8SAndy Ritger * don't fast forward through headsurface flips (since every flip needs to
376758b4ee8SAndy Ritger * be kicked off with every swapgroup ready event), and skip the part of
377758b4ee8SAndy Ritger * the RG interrupt that would update non-swapgroup content.
378758b4ee8SAndy Ritger */
379758b4ee8SAndy Ritger NvBool swapGroupFlipping;
380758b4ee8SAndy Ritger
381758b4ee8SAndy Ritger } NVHsChannelEvoRec;
382758b4ee8SAndy Ritger
Hs3dStatisticsGetSlot(const NVHsChannelEvoRec * pHsChannel,const NvHsNextFrameRequestType requestType,const NvU8 dstBufferIndex,const NvBool honorSwapGroupClipList)383758b4ee8SAndy Ritger static inline NvU8 Hs3dStatisticsGetSlot(
384758b4ee8SAndy Ritger const NVHsChannelEvoRec *pHsChannel,
385758b4ee8SAndy Ritger const NvHsNextFrameRequestType requestType,
386758b4ee8SAndy Ritger const NvU8 dstBufferIndex,
387758b4ee8SAndy Ritger const NvBool honorSwapGroupClipList)
388758b4ee8SAndy Ritger {
389758b4ee8SAndy Ritger if (pHsChannel->config.neededForSwapGroup) {
390758b4ee8SAndy Ritger switch (requestType) {
391758b4ee8SAndy Ritger case NV_HS_NEXT_FRAME_REQUEST_TYPE_FIRST_FRAME:
392758b4ee8SAndy Ritger /*
393758b4ee8SAndy Ritger * SwapGroup FIRST_FRAME will render to pHsChannel->nextIndex with
394758b4ee8SAndy Ritger * honorSwapGroupClipList==false.
395758b4ee8SAndy Ritger */
396758b4ee8SAndy Ritger nvAssert(dstBufferIndex < 2);
397758b4ee8SAndy Ritger return dstBufferIndex;
398758b4ee8SAndy Ritger case NV_HS_NEXT_FRAME_REQUEST_TYPE_VBLANK:
399758b4ee8SAndy Ritger /*
400758b4ee8SAndy Ritger * SwapGroup VBLANK fully populates the nextIndex buffer
401758b4ee8SAndy Ritger * (honorSwapGroupClipList==false), and only populates the
402758b4ee8SAndy Ritger * non-swapgroup regions of the current index.
403758b4ee8SAndy Ritger */
404758b4ee8SAndy Ritger return honorSwapGroupClipList ? 0 : 1;
405758b4ee8SAndy Ritger case NV_HS_NEXT_FRAME_REQUEST_TYPE_SWAP_GROUP_READY:
406758b4ee8SAndy Ritger return 2;
407758b4ee8SAndy Ritger }
408758b4ee8SAndy Ritger }
409758b4ee8SAndy Ritger
410758b4ee8SAndy Ritger return 0; /* non-SwapGroup always only uses slot 0 */
411758b4ee8SAndy Ritger }
412758b4ee8SAndy Ritger
413758b4ee8SAndy Ritger /*!
414758b4ee8SAndy Ritger * Get the offset, in words, of the frame semaphore within NVHsNotifiersOneSdRec
415758b4ee8SAndy Ritger * that corresponds to (head, frameSemaphoreIndex).
416758b4ee8SAndy Ritger */
HsGetFrameSemaphoreOffsetInWords(const NVHsChannelEvoRec * pHsChannel)417758b4ee8SAndy Ritger static inline NvU16 HsGetFrameSemaphoreOffsetInWords(
418758b4ee8SAndy Ritger const NVHsChannelEvoRec *pHsChannel)
419758b4ee8SAndy Ritger {
420758b4ee8SAndy Ritger const NvU16 semBase =
421758b4ee8SAndy Ritger offsetof(NVHsNotifiersOneSdRec, semaphore[pHsChannel->apiHead]);
422758b4ee8SAndy Ritger const NvU16 semOffset = sizeof(NvGpuSemaphore) *
423758b4ee8SAndy Ritger pHsChannel->frameSemaphoreIndex;
424758b4ee8SAndy Ritger
425758b4ee8SAndy Ritger const NvU16 offsetInBytes = semBase + semOffset;
426758b4ee8SAndy Ritger
427758b4ee8SAndy Ritger /*
428758b4ee8SAndy Ritger * NVHsNotifiersOneSdRec::semaphore should be word-aligned, and
429758b4ee8SAndy Ritger * sizeof(NvGpuSemaphore) is a multiple of words, so the offset to any
430758b4ee8SAndy Ritger * NvGpuSemaphore within the array should be word-aligned.
431758b4ee8SAndy Ritger */
432758b4ee8SAndy Ritger nvAssert((offsetInBytes % 4) == 0);
433758b4ee8SAndy Ritger
434758b4ee8SAndy Ritger return offsetInBytes / 4;
435758b4ee8SAndy Ritger }
436758b4ee8SAndy Ritger
HsIncrementFrameSemaphoreIndex(NVHsChannelEvoRec * pHsChannel)437758b4ee8SAndy Ritger static inline void HsIncrementFrameSemaphoreIndex(
438758b4ee8SAndy Ritger NVHsChannelEvoRec *pHsChannel)
439758b4ee8SAndy Ritger {
440758b4ee8SAndy Ritger pHsChannel->frameSemaphoreIndex++;
441758b4ee8SAndy Ritger pHsChannel->frameSemaphoreIndex %= NVKMS_HEAD_SURFACE_MAX_FRAME_SEMAPHORES;
442758b4ee8SAndy Ritger }
443758b4ee8SAndy Ritger
HsGetPreviousOffset(const NVHsChannelEvoRec * pHsChannel)444758b4ee8SAndy Ritger static inline NvU8 HsGetPreviousOffset(
445758b4ee8SAndy Ritger const NVHsChannelEvoRec *pHsChannel)
446758b4ee8SAndy Ritger {
447758b4ee8SAndy Ritger nvAssert(pHsChannel->config.neededForSwapGroup);
448758b4ee8SAndy Ritger
449758b4ee8SAndy Ritger nvAssert(pHsChannel->config.surfaceSize.height ==
450758b4ee8SAndy Ritger (pHsChannel->config.frameSize.height * 2));
451758b4ee8SAndy Ritger
452758b4ee8SAndy Ritger return A_minus_b_with_wrap_U8(pHsChannel->nextOffset, 1,
453758b4ee8SAndy Ritger NVKMS_HEAD_SURFACE_MAX_BUFFERS);
454758b4ee8SAndy Ritger }
455758b4ee8SAndy Ritger
HsIncrementNextOffset(const NVHsDeviceEvoRec * pHsDevice,NVHsChannelEvoRec * pHsChannel)456758b4ee8SAndy Ritger static inline void HsIncrementNextOffset(
457758b4ee8SAndy Ritger const NVHsDeviceEvoRec *pHsDevice,
458758b4ee8SAndy Ritger NVHsChannelEvoRec *pHsChannel)
459758b4ee8SAndy Ritger {
460758b4ee8SAndy Ritger nvAssert(pHsChannel->config.neededForSwapGroup);
461758b4ee8SAndy Ritger
462758b4ee8SAndy Ritger nvAssert(pHsChannel->config.surfaceSize.height ==
463758b4ee8SAndy Ritger (pHsChannel->config.frameSize.height * 2));
464758b4ee8SAndy Ritger
465758b4ee8SAndy Ritger pHsChannel->nextOffset++;
466758b4ee8SAndy Ritger pHsChannel->nextOffset %= 2;
467758b4ee8SAndy Ritger }
468758b4ee8SAndy Ritger
HsIncrementNextIndex(const NVHsDeviceEvoRec * pHsDevice,NVHsChannelEvoRec * pHsChannel)469758b4ee8SAndy Ritger static inline void HsIncrementNextIndex(
470758b4ee8SAndy Ritger const NVHsDeviceEvoRec *pHsDevice,
471758b4ee8SAndy Ritger NVHsChannelEvoRec *pHsChannel)
472758b4ee8SAndy Ritger {
473758b4ee8SAndy Ritger const NVDevEvoRec *pDevEvo = pHsDevice->pDevEvo;
474758b4ee8SAndy Ritger const NvU32 surfaceCount =
475758b4ee8SAndy Ritger pDevEvo->apiHeadSurfaceAllDisps[pHsChannel->apiHead].surfaceCount;
476758b4ee8SAndy Ritger
477758b4ee8SAndy Ritger nvAssert(surfaceCount > 0);
478758b4ee8SAndy Ritger
479758b4ee8SAndy Ritger pHsChannel->nextIndex++;
480758b4ee8SAndy Ritger pHsChannel->nextIndex %= surfaceCount;
481758b4ee8SAndy Ritger }
482758b4ee8SAndy Ritger
HsChangeSurfaceFlipRefCount(NVDevEvoPtr pDevEvo,NVSurfaceEvoPtr pSurfaceEvo,NvBool increase)483758b4ee8SAndy Ritger static inline void HsChangeSurfaceFlipRefCount(
484*b5bf85a8SAndy Ritger NVDevEvoPtr pDevEvo,
485758b4ee8SAndy Ritger NVSurfaceEvoPtr pSurfaceEvo,
486758b4ee8SAndy Ritger NvBool increase)
487758b4ee8SAndy Ritger {
488758b4ee8SAndy Ritger if (pSurfaceEvo != NULL) {
489758b4ee8SAndy Ritger if (increase) {
490758b4ee8SAndy Ritger nvEvoIncrementSurfaceRefCnts(pSurfaceEvo);
491758b4ee8SAndy Ritger } else {
492*b5bf85a8SAndy Ritger nvEvoDecrementSurfaceRefCnts(pDevEvo, pSurfaceEvo);
493758b4ee8SAndy Ritger }
494758b4ee8SAndy Ritger }
495758b4ee8SAndy Ritger }
496758b4ee8SAndy Ritger
497758b4ee8SAndy Ritger /*!
4984397463eSAndy Ritger * Get the last NVHsLayerRequestedFlipState entry in the pHsChannel's flip queue for
499758b4ee8SAndy Ritger * the specified layer.
500758b4ee8SAndy Ritger *
501758b4ee8SAndy Ritger * If the flip queue is empty, return the 'current' entry. Otherwise, return
502758b4ee8SAndy Ritger * the most recently queued entry.
503758b4ee8SAndy Ritger *
504758b4ee8SAndy Ritger * This function cannot fail.
505758b4ee8SAndy Ritger */
HsGetLastFlipQueueEntry(const NVHsChannelEvoRec * pHsChannel,const NvU8 layer)5064397463eSAndy Ritger static inline const NVHsLayerRequestedFlipState *HsGetLastFlipQueueEntry(
507758b4ee8SAndy Ritger const NVHsChannelEvoRec *pHsChannel,
508758b4ee8SAndy Ritger const NvU8 layer)
509758b4ee8SAndy Ritger {
510758b4ee8SAndy Ritger const NVListRec *pFlipQueue = &pHsChannel->flipQueue[layer].queue;
511758b4ee8SAndy Ritger const NVHsChannelFlipQueueEntry *pEntry;
512758b4ee8SAndy Ritger
513758b4ee8SAndy Ritger /*
514758b4ee8SAndy Ritger * XXX NVKMS HEADSURFACE TODO: use nvListIsEmpty() once bugfix_main is
515758b4ee8SAndy Ritger * updated to make nvListIsEmpty()'s argument const; see changelist
516758b4ee8SAndy Ritger * 23614050.
517758b4ee8SAndy Ritger *
518758b4ee8SAndy Ritger * if (nvListIsEmpty(pFlipQueue)) {
519758b4ee8SAndy Ritger */
520758b4ee8SAndy Ritger if (pFlipQueue->next == pFlipQueue) {
521758b4ee8SAndy Ritger return &pHsChannel->flipQueue[layer].current;
522758b4ee8SAndy Ritger }
523758b4ee8SAndy Ritger
524758b4ee8SAndy Ritger pEntry = nvListLastEntry(pFlipQueue,
525758b4ee8SAndy Ritger NVHsChannelFlipQueueEntry,
526758b4ee8SAndy Ritger flipQueueEntry);
527758b4ee8SAndy Ritger
528758b4ee8SAndy Ritger return &pEntry->hwState;
529758b4ee8SAndy Ritger }
530758b4ee8SAndy Ritger
531758b4ee8SAndy Ritger #endif /* __NVKMS_HEADSURFACE_PRIV_H__ */
532