1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 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 #include "nvidia-3d.h"
25 #include "nvidia-3d-types-priv.h"
26 #include "nvos.h"
27 #include "nvidia-3d-fermi.h"
28 #include "nvidia-3d-kepler.h"
29 #include "nvidia-push-utils.h"
30 
nv3dAllocChannelObject(const Nv3dAllocChannelObjectParams * pParams,Nv3dChannelPtr p3dChannel)31 NvBool nv3dAllocChannelObject(
32     const Nv3dAllocChannelObjectParams *pParams,
33     Nv3dChannelPtr p3dChannel)
34 {
35     NvPushChannelPtr pPushChannel = pParams->pPushChannel;
36     NvPushDevicePtr pPushDevice = pPushChannel->pDevice;
37     const NvU32 classNumber = p3dChannel->p3dDevice->classNumber;
38     const NvU32 numChannels =
39         pPushDevice->clientSli ? pPushDevice->numSubDevices : 1;
40     int sd;
41 
42     /*
43      * nv3dAllocChannel() should have been called to assign p3dDevice.
44      */
45     nvAssert(p3dChannel->p3dDevice != NULL);
46     nvAssert(p3dChannel->p3dDevice->pPushDevice ==
47              pParams->pPushChannel->pDevice);
48 
49     for (sd = 0; sd < numChannels; sd++) {
50 
51         if (nvPushIsAModel(pPushDevice)) {
52             nvAssert(sd == 0);
53         } else {
54             const NvPushImports *pImports = pPushDevice->pImports;
55             nvAssert(pPushChannel->channelHandle[sd] != 0);
56             nvAssert(pParams->handle[sd] != 0);
57             NvU32 ret = pImports->rmApiAlloc(pPushDevice,
58                                              pPushChannel->channelHandle[sd],
59                                              pParams->handle[sd],
60                                              classNumber,
61                                              NULL);
62             if (ret != NVOS_STATUS_SUCCESS) {
63                 return FALSE;
64             }
65         }
66 
67         p3dChannel->handle[sd] = pParams->handle[sd];
68     }
69 
70     p3dChannel->pPushChannel = pPushChannel;
71 
72     return TRUE;
73 }
74 
nv3dFreeChannelObject(Nv3dChannelPtr p3dChannel)75 void nv3dFreeChannelObject(Nv3dChannelPtr p3dChannel)
76 {
77     int sd;
78 
79     p3dChannel->pPushChannel = NULL;
80 
81     // No need to actually free the object here.  It gets destroyed during
82     // channel teardown.
83     for (sd = 0; sd < ARRAY_LEN(p3dChannel->handle); sd++) {
84         p3dChannel->handle[sd] = 0;
85     }
86 }
87 
nv3dUploadDataInline(Nv3dChannelRec * p3dChannel,NvU64 gpuBaseAddress,size_t offset,const void * data,size_t bytes)88 void nv3dUploadDataInline(
89     Nv3dChannelRec *p3dChannel,
90     NvU64 gpuBaseAddress,
91     size_t offset,
92     const void *data,
93     size_t bytes)
94 {
95     const Nv3dHal *pHal = p3dChannel->p3dDevice->hal;
96 
97     pHal->uploadDataInline(p3dChannel, gpuBaseAddress, offset, data, bytes);
98 }
99 
nv3dClearProgramCache(Nv3dChannelRec * p3dChannel)100 void nv3dClearProgramCache(Nv3dChannelRec *p3dChannel)
101 {
102     Nv3dShaderStage stage;
103 
104     for (stage = 0;
105          stage < ARRAY_LEN(p3dChannel->currentProgramIndex);
106          stage++) {
107         p3dChannel->currentProgramIndex[stage] = -1;
108     }
109 }
110 
nv3dLoadTextures(Nv3dChannelRec * p3dChannel,int firstTex,const Nv3dRenderTexInfo * texInfo,int numTex)111 void nv3dLoadTextures(
112     Nv3dChannelRec *p3dChannel,
113     int firstTex,
114     const Nv3dRenderTexInfo *texInfo,
115     int numTex)
116 {
117     /* Limit number of texture/samplers on the stack to 4 (256 bytes) */
118 #define MAX_TEX_CHUNK 4
119     Nv3dTexture textures[MAX_TEX_CHUNK];
120     const Nv3dHal *pHal = p3dChannel->p3dDevice->hal;
121     const NvU64 gpuBaseAddress = nv3dGetTextureGpuAddress(p3dChannel, 0);
122 
123     nvAssert(numTex >= 1);
124 
125     // Invalidate the texture/sampler caches.  This will cause a wait for idle
126     // if there's rendering still in progress.  This is necessary in case the
127     // texture parameters we're about to overwrite are in use.
128     _nv3dInvalidateTexturesFermi(p3dChannel);
129 
130     while (numTex) {
131         const NvU32 chunkNumTex = NV_MIN(numTex, MAX_TEX_CHUNK);
132         const size_t startOffset = sizeof(Nv3dTexture) * firstTex;
133         const size_t bytes = sizeof(Nv3dTexture) * chunkNumTex;
134         int i;
135 
136         NVMISC_MEMSET(textures, 0, sizeof(textures));
137 
138         nvAssert(firstTex + numTex <= p3dChannel->numTextures);
139 
140         // Write texture header to HW format
141         for (i = 0; i < chunkNumTex; i++) {
142             pHal->assignNv3dTexture(texInfo[i], &textures[i]);
143         }
144 
145         nv3dUploadDataInline(p3dChannel, gpuBaseAddress, startOffset,
146                              textures, bytes);
147 
148         numTex -= chunkNumTex;
149         firstTex += chunkNumTex;
150         texInfo += chunkNumTex;
151     }
152 }
153 
nv3dBindTextures(Nv3dChannelPtr p3dChannel,int programIndex,const int * textureBindingIndices)154 void nv3dBindTextures(
155     Nv3dChannelPtr p3dChannel,
156     int programIndex,
157     const int *textureBindingIndices)
158 {
159     nvAssert(programIndex < p3dChannel->programs.num);
160 
161     _nv3dBindTexturesKepler(p3dChannel, programIndex, textureBindingIndices);
162 }
163