1 /*
2 * Copyright (c) 2019, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 //!
23 //! \file     vphal_render_vebox_memdecomp_g12.cpp
24 //! \brief    Defines data structures and interfaces for media memory decompression.
25 //! \details
26 //!
27 
28 #include "vphal_render_vebox_memdecomp_g12.h"
29 #include "mhw_vebox_hwcmd_g12_X.h"
30 #include "mhw_vebox_g12_X.h"
31 #include "hal_oca_interface.h"
32 
MediaVeboxDecompStateG12()33 MediaVeboxDecompStateG12::MediaVeboxDecompStateG12() :
34     MediaVeboxDecompState()
35 {
36 }
37 
RenderDecompCMD(PMOS_SURFACE surface)38 MOS_STATUS MediaVeboxDecompStateG12::RenderDecompCMD(PMOS_SURFACE surface)
39 {
40     MOS_STATUS                          eStatus = MOS_STATUS_SUCCESS;
41     MHW_VEBOX_STATE_CMD_PARAMS          veboxStateCmdParams;
42     MOS_COMMAND_BUFFER                  cmdBuffer;
43     PMHW_VEBOX_INTERFACE                veboxInterface;
44     MHW_VEBOX_SURFACE_STATE_CMD_PARAMS  mhwVeboxSurfaceStateCmdParams;
45     MHW_MI_FLUSH_DW_PARAMS              flushDwParams;
46     uint32_t                            streamID = 0;
47     const MHW_VEBOX_HEAP                *veboxHeap = nullptr;
48     MOS_CONTEXT *                       pOsContext     = nullptr;
49     PMHW_MI_MMIOREGISTERS               pMmioRegisters = nullptr;
50 
51     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(surface);
52     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(m_osInterface);
53     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(pOsContext = m_osInterface->pOsContext);
54     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(m_mhwMiInterface);
55     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(pMmioRegisters = m_mhwMiInterface->GetMmioRegisters());
56 
57     if (surface->CompressionMode                &&
58         surface->CompressionMode != MOS_MMC_MC  &&
59         surface->CompressionMode != MOS_MMC_RC)
60     {
61         VPHAL_MEMORY_DECOMP_NORMALMESSAGE("Input surface is uncompressed, In_Place resolve is not needed");
62         return eStatus;
63     }
64 
65     if (!IsDecompressionFormatSupported(surface))
66     {
67         VPHAL_MEMORY_DECOMP_NORMALMESSAGE("Input surface is not supported by Vebox, In_Place resolve can't be done");
68         return eStatus;
69     }
70 
71     veboxInterface = m_veboxInterface;
72 
73     m_osInterface->pfnSetGpuContext(m_osInterface, MOS_GPU_CONTEXT_VEBOX);
74 
75     // Reset allocation list and house keeping
76     m_osInterface->pfnResetOsStates(m_osInterface);
77 
78     VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(veboxInterface->GetVeboxHeapInfo(&veboxHeap));
79     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(&surface->OsResource);
80     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(m_osInterface->osCpInterface);
81 
82     // Check whether surface is ready for write
83     m_osInterface->pfnSyncOnResource(
84         m_osInterface,
85         &surface->OsResource,
86         MOS_GPU_CONTEXT_VEBOX,
87         true);
88 
89     // preprocess in cp first
90     m_osInterface->osCpInterface->PrepareResources((void **)&surface, 1, nullptr, 0);
91 
92     // initialize the command buffer struct
93     MOS_ZeroMemory(&cmdBuffer, sizeof(MOS_COMMAND_BUFFER));
94 
95     VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0));
96 
97     HalOcaInterface::On1stLevelBBStart(cmdBuffer, *pOsContext, m_osInterface->CurrentGpuContextHandle, *m_mhwMiInterface, *pMmioRegisters);
98 
99     VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(InitCommandBuffer(&cmdBuffer));
100 
101     // Prepare Vebox_Surface_State, surface input/and output are the same but the compressed status.
102     VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(SetupVeboxSurfaceState(&mhwVeboxSurfaceStateCmdParams, surface, nullptr));
103 
104     //---------------------------------
105     // Send Pvt MMCD CMD
106     //---------------------------------
107     MhwVeboxInterfaceG12 *pVeboxInterfaceExt12;
108     pVeboxInterfaceExt12 = (MhwVeboxInterfaceG12 *)veboxInterface;
109 
110     VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(pVeboxInterfaceExt12->setVeboxPrologCmd(
111         m_mhwMiInterface,
112         &cmdBuffer));
113 
114     //---------------------------------
115     // Send CMD: Vebox_Surface_State
116     //---------------------------------
117     VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(veboxInterface->AddVeboxSurfaces(
118         &cmdBuffer,
119         &mhwVeboxSurfaceStateCmdParams));
120 
121     HalOcaInterface::OnDispatch(cmdBuffer, *pOsContext, *m_mhwMiInterface, *pMmioRegisters);
122 
123     //---------------------------------
124     // Send CMD: Vebox_Tiling_Convert
125     //---------------------------------
126     VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(VeboxSendVeboxTileConvertCMD(&cmdBuffer, surface, nullptr, streamID));
127 
128     MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
129 
130     VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(m_mhwMiInterface->AddMiFlushDwCmd(
131         &cmdBuffer,
132         &flushDwParams));
133 
134     if (!m_osInterface->bEnableKmdMediaFrameTracking && veboxHeap)
135     {
136         MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
137         flushDwParams.pOsResource      = (PMOS_RESOURCE)&veboxHeap->DriverResource;
138         flushDwParams.dwResourceOffset = veboxHeap->uiOffsetSync;
139         flushDwParams.dwDataDW1        = veboxHeap->dwNextTag;
140         VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(m_mhwMiInterface->AddMiFlushDwCmd(
141             &cmdBuffer,
142             &flushDwParams));
143     }
144 
145     if (m_osInterface->osCpInterface->IsHMEnabled())
146     {
147         HalOcaInterface::DumpCpParam(cmdBuffer, *pOsContext, m_osInterface->osCpInterface->GetOcaDumper());
148     }
149 
150     HalOcaInterface::On1stLevelBBEnd(cmdBuffer, *pOsContext);
151 
152     VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(m_mhwMiInterface->AddMiBatchBufferEnd(
153         &cmdBuffer,
154         nullptr));
155 
156     // Return unused command buffer space to OS
157     m_osInterface->pfnReturnCommandBuffer(
158         m_osInterface,
159         &cmdBuffer,
160         0);
161 
162     // Flush the command buffer
163     VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(
164         m_osInterface,
165         &cmdBuffer,
166         false));
167 
168     veboxInterface->UpdateVeboxSync();
169 
170     return eStatus;
171 }
172 
IsVeboxDecompressionEnabled()173 MOS_STATUS MediaVeboxDecompStateG12::IsVeboxDecompressionEnabled()
174 {
175     MOS_USER_FEATURE_VALUE_DATA         UserFeatureData;
176     MOS_STATUS                          eStatus = MOS_STATUS_SUCCESS;
177 
178     MOS_ZeroMemory(&UserFeatureData, sizeof(UserFeatureData));
179     UserFeatureData.i32DataFlag = MOS_USER_FEATURE_VALUE_DATA_FLAG_CUSTOM_DEFAULT_VALUE_TYPE;
180 
181 #ifdef LINUX
182     UserFeatureData.bData = false; // disable VE Decompress on Linux
183 #else
184     UserFeatureData.bData = true;
185 #endif
186 
187     MOS_USER_FEATURE_INVALID_KEY_ASSERT(MOS_UserFeature_ReadValue_ID(
188         nullptr,
189         __VPHAL_ENABLE_VEBOX_MMC_DECOMPRESS_ID,
190         &UserFeatureData));
191 
192     m_veboxMMCResolveEnabled = UserFeatureData.bData ? true: false;
193 
194     return eStatus;
195 }
196 
RenderDoubleBufferDecompCMD(PMOS_SURFACE inputSurface,PMOS_SURFACE outputSurface)197 MOS_STATUS MediaVeboxDecompStateG12::RenderDoubleBufferDecompCMD(
198     PMOS_SURFACE inputSurface,
199     PMOS_SURFACE outputSurface)
200 {
201     MOS_STATUS                          eStatus = MOS_STATUS_SUCCESS;
202     MHW_VEBOX_STATE_CMD_PARAMS          veboxStateCmdParams;
203     MOS_COMMAND_BUFFER                  cmdBuffer;
204     PMHW_VEBOX_INTERFACE                veboxInterface;
205     MHW_VEBOX_SURFACE_STATE_CMD_PARAMS  mhwVeboxSurfaceStateCmdParams;
206     MHW_MI_FLUSH_DW_PARAMS              flushDwParams;
207     uint32_t                            streamID = 0;
208     const MHW_VEBOX_HEAP                *veboxHeap = nullptr;
209 
210     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(inputSurface);
211     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(outputSurface);
212 
213     veboxInterface = m_veboxInterface;
214 
215     m_osInterface->pfnSetGpuContext(m_osInterface, MOS_GPU_CONTEXT_VEBOX);
216 
217     // Reset allocation list and house keeping
218     m_osInterface->pfnResetOsStates(m_osInterface);
219 
220     VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(veboxInterface->GetVeboxHeapInfo(&veboxHeap));
221     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(&inputSurface->OsResource);
222     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(&outputSurface->OsResource);
223     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(m_osInterface->osCpInterface);
224 
225     //there is a new usage that input surface is clear and output surface is secure.
226     //replace Huc Copy by DoubleBuffer resolve to update ccs data.
227     //So need consolidate both input/output surface information to decide cp context.
228      PMOS_SURFACE surfaceArray[2];
229      surfaceArray[0] = inputSurface;
230      surfaceArray[1] = outputSurface;
231 
232     // preprocess in cp first
233     m_osInterface->osCpInterface->PrepareResources((void **)&surfaceArray, sizeof(surfaceArray) / sizeof(PMOS_SURFACE), nullptr, 0);
234 
235     // initialize the command buffer struct
236     MOS_ZeroMemory(&cmdBuffer, sizeof(MOS_COMMAND_BUFFER));
237 
238     VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0));
239     VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(InitCommandBuffer(&cmdBuffer));
240 
241     // Prepare Vebox_Surface_State, surface input/and output are the same but the compressed status.
242     VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(SetupVeboxSurfaceState(&mhwVeboxSurfaceStateCmdParams, inputSurface, outputSurface));
243 
244     //---------------------------------
245     // Send Pvt MMCD CMD
246     //---------------------------------
247     MediaVeboxDecompStateG12 *pVeboxInterfaceExt12;
248     pVeboxInterfaceExt12 = (MediaVeboxDecompStateG12 *)veboxInterface;
249 
250     //---------------------------------
251     // Send CMD: Vebox_Surface_State
252     //---------------------------------
253     VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(veboxInterface->AddVeboxSurfaces(
254         &cmdBuffer,
255         &mhwVeboxSurfaceStateCmdParams));
256 
257     //---------------------------------
258     // Send CMD: Vebox_Tiling_Convert
259     //---------------------------------
260     VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(VeboxSendVeboxTileConvertCMD(&cmdBuffer, inputSurface, outputSurface, streamID));
261 
262     MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
263 
264     VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(m_mhwMiInterface->AddMiFlushDwCmd(
265         &cmdBuffer,
266         &flushDwParams));
267 
268     if (!m_osInterface->bEnableKmdMediaFrameTracking && veboxHeap)
269     {
270         MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
271         flushDwParams.pOsResource = (PMOS_RESOURCE)&veboxHeap->DriverResource;
272         flushDwParams.dwResourceOffset = veboxHeap->uiOffsetSync;
273         flushDwParams.dwDataDW1 = veboxHeap->dwNextTag;
274         VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(m_mhwMiInterface->AddMiFlushDwCmd(
275             &cmdBuffer,
276             &flushDwParams));
277     }
278 
279     VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(m_mhwMiInterface->AddMiBatchBufferEnd(
280         &cmdBuffer,
281         nullptr));
282 
283     // Return unused command buffer space to OS
284     m_osInterface->pfnReturnCommandBuffer(
285         m_osInterface,
286         &cmdBuffer,
287         0);
288 
289     // Flush the command buffer
290     VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(
291         m_osInterface,
292         &cmdBuffer,
293         false));
294 
295     veboxInterface->UpdateVeboxSync();
296 
297     return eStatus;
298 }
299 
VeboxSendVeboxTileConvertCMD(PMOS_COMMAND_BUFFER cmdBuffer,PMOS_SURFACE inputSurface,PMOS_SURFACE outputSurface,uint32_t streamID)300 MOS_STATUS MediaVeboxDecompStateG12::VeboxSendVeboxTileConvertCMD(
301     PMOS_COMMAND_BUFFER cmdBuffer,
302     PMOS_SURFACE        inputSurface,
303     PMOS_SURFACE        outputSurface,
304     uint32_t            streamID)
305 {
306     MOS_STATUS                      eStatus = MOS_STATUS_SUCCESS;
307     PMOS_SURFACE                    surface = nullptr;
308     mhw_vebox_g12_X::VEB_DI_IECP_COMMAND_SURFACE_CONTROL_BITS_CMD veboxInputSurfCtrlBits, veboxOutputSurfCtrlBits;
309 
310     mhw_vebox_g12_X::VEBOX_TILING_CONVERT_CMD cmd;
311     MHW_RESOURCE_PARAMS ResourceParams = {0};
312 
313     MOS_UNUSED(streamID);
314     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(cmdBuffer);
315     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(inputSurface);
316     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(m_osInterface);
317     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(m_veboxInterface);
318     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(m_veboxInterface->pfnAddResourceToCmd);
319 
320     // Set up VEB_DI_IECP_COMMAND_SURFACE_CONTROL_BITS
321     MOS_ZeroMemory(&veboxInputSurfCtrlBits, sizeof(veboxInputSurfCtrlBits));
322     MOS_ZeroMemory(&veboxOutputSurfCtrlBits, sizeof(veboxOutputSurfCtrlBits));
323 
324     // Set Input surface compression status
325     if (inputSurface->CompressionMode != MOS_MMC_DISABLED)
326     {
327         veboxInputSurfCtrlBits.DW0.MemoryCompressionEnable = true;
328 
329         if (inputSurface->CompressionMode == MOS_MMC_RC)
330         {
331             veboxInputSurfCtrlBits.DW0.CompressionType = 1;
332         }
333         else
334         {
335             veboxInputSurfCtrlBits.DW0.CompressionType = 0;
336         }
337     }
338 
339     switch (inputSurface->TileType)
340     {
341     case MOS_TILE_YF:
342         veboxInputSurfCtrlBits.DW0.TiledResourceModeForOutputFrameSurfaceBaseAddress = TRMODE_TILEYF;
343         break;
344     case MOS_TILE_YS:
345         veboxInputSurfCtrlBits.DW0.TiledResourceModeForOutputFrameSurfaceBaseAddress = TRMODE_TILEYS;
346         break;
347     default:
348         veboxInputSurfCtrlBits.DW0.TiledResourceModeForOutputFrameSurfaceBaseAddress = TRMODE_NONE;
349         break;
350     }
351 
352     // Set Output surface compression status
353     if (outputSurface)
354     {
355         // Double Buffer copy
356         surface = outputSurface;
357 
358         if (outputSurface->CompressionMode == MOS_MMC_MC)
359         {
360             veboxOutputSurfCtrlBits.DW0.MemoryCompressionEnable = true;
361             veboxOutputSurfCtrlBits.DW0.CompressionType         = 0;
362         }
363         else if (outputSurface->CompressionMode == MOS_MMC_RC)
364         {
365             veboxOutputSurfCtrlBits.DW0.MemoryCompressionEnable = true;
366             veboxOutputSurfCtrlBits.DW0.CompressionType         = 1;
367         }
368         else
369         {
370             veboxOutputSurfCtrlBits.DW0.MemoryCompressionEnable = false;
371             veboxOutputSurfCtrlBits.DW0.CompressionType         = 0;
372         }
373 
374     }
375     else
376     {
377         // In-Place Resolve
378         surface = inputSurface;
379         veboxOutputSurfCtrlBits.DW0.MemoryCompressionEnable = true;
380         veboxOutputSurfCtrlBits.DW0.CompressionType         = 1;
381     }
382 
383     switch (surface->TileType)
384     {
385     case MOS_TILE_YF:
386         veboxOutputSurfCtrlBits.DW0.TiledResourceModeForOutputFrameSurfaceBaseAddress = TRMODE_TILEYF;
387         break;
388     case MOS_TILE_YS:
389         veboxOutputSurfCtrlBits.DW0.TiledResourceModeForOutputFrameSurfaceBaseAddress = TRMODE_TILEYS;
390         break;
391     default:
392         veboxOutputSurfCtrlBits.DW0.TiledResourceModeForOutputFrameSurfaceBaseAddress = TRMODE_NONE;
393         break;
394     }
395 
396     ResourceParams.presResource = &inputSurface->OsResource;
397     ResourceParams.HwCommandType = MOS_VEBOX_TILING_CONVERT;
398 
399     // set up DW[2:1], input graphics address
400     ResourceParams.dwLocationInCmd = 1;
401     ResourceParams.pdwCmd          = &(cmd.DW1_2.Value[0]);
402     ResourceParams.bIsWritable     = false;
403     ResourceParams.dwOffset        = inputSurface->dwOffset + veboxInputSurfCtrlBits.DW0.Value;
404     m_veboxInterface->pfnAddResourceToCmd(m_osInterface, cmdBuffer, &ResourceParams);
405 
406     MOS_ZeroMemory(&ResourceParams, sizeof(MHW_RESOURCE_PARAMS));
407 
408     if (outputSurface)
409     {
410         ResourceParams.presResource = &outputSurface->OsResource;
411     }
412     else
413     {
414         ResourceParams.presResource = &inputSurface->OsResource;
415     }
416 
417     ResourceParams.HwCommandType = MOS_VEBOX_TILING_CONVERT;
418 
419     // set up DW[4:3], output graphics address
420     ResourceParams.dwLocationInCmd = 3;
421     ResourceParams.pdwCmd          = &(cmd.DW3_4.Value[0]);
422     ResourceParams.bIsWritable     = true;
423     ResourceParams.dwOffset        =
424         (outputSurface != nullptr ? outputSurface->dwOffset : inputSurface->dwOffset) + veboxOutputSurfCtrlBits.DW0.Value;
425     m_veboxInterface->pfnAddResourceToCmd(m_osInterface, cmdBuffer, &ResourceParams);
426 
427     Mos_AddCommand(cmdBuffer, &cmd, cmd.byteSize);
428 
429     return eStatus;
430 }
431