1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 2015-2017 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3  * SPDX-License-Identifier: MIT
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 #ifndef __NVKMS_HEADSURFACE_CONFIG_H__
25 #define __NVKMS_HEADSURFACE_CONFIG_H__
26 
27 #include "nvkms-types.h"
28 #include "nvkms-softfloat.h"          /* NvKmsMatrixF32 */
29 #include "nvidia-headsurface-types.h" /* NvHsStaticWarpMesh */
30 #include "g_shader_names.h"           /* ProgramName */
31 
32 typedef enum {
33     /*
34      * The head config does not need headSurface; there would be
35      * nothing headSurface could do to make the configuration
36      * achievable.
37      */
38     NVKMS_HEAD_SURFACE_CONFIG_STATE_NO_HEAD_SURFACE,
39 
40     /*
41      * The head config might be achievable in hardware, but
42      * headSurface might help if we fail to program it in hardware.
43      */
44     NVKMS_HEAD_SURFACE_CONFIG_STATE_MAYBE_HEAD_SURFACE,
45 
46     /*
47      * HeadSurface is needed, but display hardware should still be used for
48      * ViewPortOut positioning within Raster.  I.e., from a display hardware
49      * standpoint, ViewPortIn == ViewPortOut, but ViewPortOut!=Raster.
50      */
51     NVKMS_HEAD_SURFACE_CONFIG_STATE_PARTIAL_HEAD_SURFACE,
52 
53     /*
54      * HeadSurface is needed, and should also be used for ViewPortOut
55      * scaling.  I.e., from a display hardware standpoint, ViewPortIn
56      * == ViewPortOut, and ViewPortOut == Raster.
57      */
58     NVKMS_HEAD_SURFACE_CONFIG_STATE_FULL_HEAD_SURFACE,
59 } NVHsConfigState;
60 
61 /*
62  * Configuration state to be used by NVHsChannelEvoRec.
63  */
64 typedef struct {
65 
66     NVHsConfigState state;
67 
68     /*
69      * Which eyes are required by this headSurface configuration.  Valid
70      * combinations are:
71      *
72      * NVBIT(NVKMS_LEFT), or
73      * NVBIT(NVKMS_LEFT) | NVBIT(NVKMS_RIGHT)
74      */
75     NvU8 eyeMask;
76 
77     /*
78      * The dimensions of headSurface frames.  This is only assigned if ::state
79      * is PARTIAL_HEAD_SURFACE or FULL_HEAD_SURFACE.
80      *
81      * If state is PARTIAL_HEAD_SURFACE, then frameSize will be the size of the
82      * display engine's viewPortOut.  Any difference between the
83      * client-requested viewPortOut and the active raster region will be
84      * resolved by the display engine.  Also, NVHsChannelConfig::viewPortOut
85      * will equal frameSize.
86      *
87      * If state is FULL_HEAD_SURFACE, then frameSize will be the same size as
88      * the display engine's active raster region.  Any difference between the
89      * client-requested viewPortOut and the active raster region will be
90      * resolved by headSurface.  NVHsChannelConfig::viewPortOut might be smaller
91      * than frameSize.
92      */
93     struct NvKmsSize frameSize;
94 
95     /*
96      * The size of the surface for headSurface.
97      *
98      * Normally, ::surfaceSize will be equal to ::frameSize.  However, when
99      * SwapGroup is enabled, surfaceSize is bloated to twice ::frameSize.
100      *
101      * Note that the actual vidmem surface might be allocated larger than
102      * surfaceSize: the video memory allocation is the maximum of the
103      * surfaceSize for this head across all subdevices.
104      */
105     struct NvKmsSize surfaceSize;
106 
107     /*
108      * When SwapGroup is enabled, we need a staging surface to perform
109      * screen-aligned 2d blits to assemble frames of SwapGroup and non-SwapGroup
110      * content, prior to applying headSurface transformations.
111      *
112      * When SwapGroup is not enabled ::stagingSurfaceSize will be zero size.
113      */
114     struct NvKmsSize stagingSurfaceSize;
115 
116     /* The region within the headSurface surfaces, where the image should be
117        rendered. */
118     struct NvKmsRect viewPortOut;
119 
120     /* The region headSurface will read from. */
121     struct NvKmsRect viewPortIn;
122 
123     NvBool hs10bpcHint;
124     NvBool yuv420;
125     NvBool blendAfterWarp;
126 
127     enum NvKmsPixelShiftMode pixelShift;
128     enum NvKmsResamplingMethod resamplingMethod;
129     struct NvKmsMatrixF32 transform;
130     NvHsStaticWarpMesh staticWarpMesh;
131 
132     /*
133      * Note that any NVSurfaceEvoPtr's stored here require special attention
134      * for reference counting.  See, e.g., HsConfigUpdateSurfaceRefCount().
135      */
136 
137     NVSurfaceEvoPtr pBlendTexSurface;
138     NVSurfaceEvoPtr pOffsetTexSurface;
139 
140     struct {
141         NVSurfaceEvoPtr pSurface;
142         NvU32 vertexCount;
143         enum NvKmsWarpMeshDataType dataType;
144     } warpMesh;
145 
146     NVFlipCursorEvoHwState cursor;
147 
148     /* XXX NVKMS HEADSURFACE TODO: plumb through dvc  */
149     NvS32 dvc;
150 
151     NvBool neededForModeset;
152     NvBool neededForSwapGroup;
153 
154 } NVHsChannelConfig;
155 
156 typedef struct {
157 
158     NVHsChannelEvoPtr pHsChannel;
159     NvBool channelReused;
160 
161     NVHsChannelConfig channelConfig;
162 
163     /* The initial surfaces to read from when initializing headSurface. */
164     struct {
165         NVSurfaceEvoPtr pSurfaceEvo[NVKMS_MAX_EYES];
166     } layer[NVKMS_MAX_LAYERS_PER_HEAD];
167 } NVHsConfigOneHead;
168 
169 typedef struct {
170     /* State that is per-disp, per-api-head. */
171     NVHsConfigOneHead apiHead[NVKMS_MAX_SUBDEVICES][NVKMS_MAX_HEADS_PER_DISP];
172 
173     /* State that is per-head, but spans subdevices. */
174     NVHsStateOneHeadAllDisps apiHeadAllDisps[NVKMS_MAX_HEADS_PER_DISP];
175 
176     /*
177      * Whether apiHeadAllDisps[]::surface[] were reused from the current
178      * configuration.
179      *
180      * surfacesReused[] is indexed by the api heads.
181      */
182     NvBool surfacesReused[NVKMS_MAX_HEADS_PER_DISP];
183 
184     /*
185      * Whether the modeset asked to apply the requested configuration, or only
186      * test if the requested configuration is valid.  I.e.,
187      * NvKmsSetModeParams::request::commit.
188      */
189     NvBool commit;
190 
191 } NVHsConfig;
192 
193 NvBool nvHsConfigInitModeset(
194     NVDevEvoRec *pDevEvo,
195     const struct NvKmsSetModeRequest *pRequest,
196     struct NvKmsSetModeReply *pReply,
197     const struct NvKmsPerOpenDev *pOpenDev,
198     NVHsConfig *pHsConfig);
199 
200 void nvHsConfigInitSwapGroup(
201     const NVDevEvoRec *pDevEvo,
202     const NVSwapGroupRec *pSwapGroup,
203     const NvBool neededForSwapGroup,
204     NVHsConfig *pHsConfig);
205 
206 NvBool nvHsConfigDowngrade(
207     NVDevEvoRec *pDevEvo,
208     const struct NvKmsSetModeRequest *pRequest,
209     NVHsConfig *pHsConfig);
210 
211 NvBool nvHsConfigAllocResources(
212     NVDevEvoRec *pDevEvo,
213     NVHsConfig *pHsConfig);
214 
215 void nvHsConfigFreeResources(
216     NVDevEvoRec *pDevEvo,
217     NVHsConfig *pHsConfig);
218 
219 void nvHsConfigStop(
220     NVDevEvoPtr pDevEvo,
221     const NVHsConfig *pHsConfig);
222 
223 void nvHsConfigStart(
224     NVDevEvoPtr pDevEvo,
225     NVHsConfig *pHsConfig);
226 
227 NvBool nvHsConfigPatchSetModeRequest(const NVDevEvoRec *pDevEvo,
228                                      const NVHsConfig *pHsConfig,
229                                      struct NvKmsPerOpenDev *pOpenDev,
230                                      struct NvKmsSetModeRequest *pRequest,
231                                      NvU32 patchedHeadsMask[NVKMS_MAX_SUBDEVICES]);
232 void
233 nvHsConfigClearPatchedSetModeRequest(const NVDevEvoRec *pDevEvo,
234                                      struct NvKmsPerOpenDev *pOpenDev,
235                                      struct NvKmsSetModeRequest *pRequest,
236                                      const NvU32 patchedHeadsMask[NVKMS_MAX_SUBDEVICES]);
237 
238 #endif /* __NVKMS_HEADSURFACE_CONFIG_H__ */
239