1 /*
2 * Copyright (c) 2017-2022, 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_renderer_g12_tgllp.cpp
24 //! \brief VPHAL top level rendering component and the entry to low level renderers
25 //! \details The top renderer is responsible for coordinating the sequence of calls to low level renderers, e.g. DNDI or Comp
26 //!
27 #include "vphal_renderer_g12_tgllp.h"
28 #include "vp_debug.h"
29 #if defined(ENABLE_KERNELS)
30 #include "igvpkrn_g12_tgllp_cmfc.h"
31 #include "igvpkrn_g12_tgllp_cmfcpatch.h"
32 #endif
33
34 extern const Kdll_RuleEntry g_KdllRuleTable_g12lp[];
35 extern const Kdll_RuleEntry g_KdllRuleTable_g12lpcmfc[];
36
InitKdllParam()37 MOS_STATUS VphalRendererG12Tgllp::InitKdllParam()
38 {
39 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
40
41 // Override kernel binary for CMFC/SWSB
42 if (bEnableCMFC)
43 {
44 #if defined(ENABLE_KERNELS)
45 pKernelDllRules = g_KdllRuleTable_g12lpcmfc;
46 pcKernelBin = (const void *)IGVPKRN_G12_TGLLP_CMFC;
47 dwKernelBinSize = IGVPKRN_G12_TGLLP_CMFC_SIZE;
48 pcFcPatchBin = (const void *)IGVPKRN_G12_TGLLP_CMFCPATCH;
49 dwFcPatchBinSize = IGVPKRN_G12_TGLLP_CMFCPATCH_SIZE;
50 #endif
51 }
52
53 if ((NULL == pcFcPatchBin) || (0 == dwFcPatchBinSize))
54 {
55 bEnableCMFC = false;
56 }
57
58 if (bEnableCMFC && (NULL != pcFcPatchBin) && (0 != dwFcPatchBinSize))
59 {
60 m_pRenderHal->bEnableP010SinglePass = true;
61 }
62 else
63 {
64 m_pRenderHal->bEnableP010SinglePass = false;
65 }
66
67 return eStatus;
68 }
69
70 //!
71 //! \brief Main render function
72 //! \details The top level renderer function, which may contain multiple
73 //! passes of rendering
74 //! \param [in] pcRenderParams
75 //! Const pointer to VPHAL render parameter
76 //! \return MOS_STATUS
77 //! Return MOS_STATUS_SUCCESS if successful, otherwise failed
78 //!
Render(PCVPHAL_RENDER_PARAMS pcRenderParams)79 MOS_STATUS VphalRendererG12Tgllp::Render(
80 PCVPHAL_RENDER_PARAMS pcRenderParams)
81 {
82 MOS_STATUS eStatus;
83 PMOS_INTERFACE pOsInterface;
84 PRENDERHAL_INTERFACE pRenderHal;
85 VPHAL_RENDER_PARAMS RenderParams; // Make a copy of render params
86 PVPHAL_SURFACE pSrcLeft[VPHAL_MAX_SOURCES]; // Array of sources referring to left view stereo content
87 PVPHAL_SURFACE pSrcRight[VPHAL_MAX_SOURCES]; // Array of sources referring to right view stereo content
88 uint32_t uiRenderPasses; // Number of rendering passes in this one call to VpHal_RndrRender()
89 uint32_t uiCurrentRenderPass; // Current render pass
90 uint32_t uiDst;
91 VPHAL_GET_SURFACE_INFO Info;
92
93 //--------------------------------------------
94 VPHAL_RENDER_ASSERT(pcRenderParams);
95 VPHAL_RENDER_ASSERT(m_pOsInterface);
96 VPHAL_RENDER_ASSERT(m_pRenderHal);
97 VPHAL_RENDER_ASSERT(pKernelDllState);
98 VPHAL_RENDER_ASSERT(pRender[VPHAL_RENDER_ID_COMPOSITE]);
99 //--------------------------------------------
100
101 eStatus = MOS_STATUS_SUCCESS;
102 pOsInterface = m_pOsInterface;
103 pRenderHal = m_pRenderHal;
104
105 // Validate render target
106 if (pcRenderParams->pTarget[0] == nullptr ||
107 Mos_ResourceIsNull(&(pcRenderParams->pTarget[0]->OsResource)))
108 {
109 VPHAL_RENDER_ASSERTMESSAGE("Invalid Render Target.");
110 eStatus = MOS_STATUS_UNKNOWN;
111 goto finish;
112 }
113
114 // Protection mechanism, Only SKL+ support P010 output.
115 if (IsFormatSupported(pcRenderParams) == false)
116 {
117 VPHAL_RENDER_ASSERTMESSAGE("Invalid Render Target Output Format.");
118 eStatus = MOS_STATUS_UNKNOWN;
119 goto finish;
120 }
121
122 VPHAL_DBG_STATE_DUMP_SET_CURRENT_FRAME_COUNT(uiFrameCounter);
123
124 // Validate max number sources
125 if (pcRenderParams->uSrcCount > VPHAL_MAX_SOURCES)
126 {
127 VPHAL_RENDER_ASSERTMESSAGE("Invalid number of samples.");
128 eStatus = MOS_STATUS_UNKNOWN;
129 goto finish;
130 }
131
132 // Validate max number targets
133 if (pcRenderParams->uDstCount > VPHAL_MAX_TARGETS)
134 {
135 VPHAL_RENDER_ASSERTMESSAGE("Invalid number of targets.");
136 eStatus = MOS_STATUS_UNKNOWN;
137 goto finish;
138 }
139
140 // Copy the Render Params structure (so we can update it)
141 RenderParams = *pcRenderParams;
142
143 VPHAL_DBG_PARAMETERS_DUMPPER_DUMP_XML(&RenderParams);
144 VPHAL_DBG_OCA_DUMPER_SET_RENDER_PARAM(pRenderHal, &RenderParams);
145
146 // Get resource information for render target
147 MOS_ZeroMemory(&Info, sizeof(VPHAL_GET_SURFACE_INFO));
148
149 for (uiDst = 0; uiDst < RenderParams.uDstCount; uiDst++)
150 {
151 VPHAL_RENDER_CHK_STATUS(VpHal_GetSurfaceInfo(
152 m_pOsInterface,
153 &Info,
154 RenderParams.pTarget[uiDst]));
155 }
156
157 // Set the component info
158 m_pOsInterface->Component = pcRenderParams->Component;
159
160 // Init component(DDI entry point) info for perf measurement
161 m_pOsInterface->pfnSetPerfTag(m_pOsInterface, VPHAL_NONE);
162
163 // Increment frame ID for performance measurement
164 m_pOsInterface->pfnIncPerfFrameID(m_pOsInterface);
165
166 // Enable Turbo mode if sku present and DDI requests it
167 if (m_pSkuTable && MEDIA_IS_SKU(m_pSkuTable, FtrMediaTurboMode))
168 {
169 m_pRenderHal->bTurboMode = RenderParams.bTurboMode;
170 }
171
172 // Reset feature reporting
173 m_reporting->InitReportValue();
174
175 MOS_ZeroMemory(pSrcLeft, sizeof(PVPHAL_SURFACE) * VPHAL_MAX_SOURCES);
176 MOS_ZeroMemory(pSrcRight, sizeof(PVPHAL_SURFACE) * VPHAL_MAX_SOURCES);
177
178 VPHAL_RENDER_CHK_STATUS(PrepareSources(
179 &RenderParams,
180 pSrcLeft,
181 pSrcRight,
182 &uiRenderPasses));
183
184 //set GpuContext
185 VPHAL_RENDER_CHK_STATUS(SetRenderGpuContext(RenderParams));
186
187 // align rectangle and source surface
188 for (uiDst = 0; uiDst < RenderParams.uDstCount; uiDst++)
189 {
190 VPHAL_RENDER_CHK_STATUS(VpHal_RndrRectSurfaceAlignment(RenderParams.pTarget[uiDst], RenderParams.pTarget[uiDst]->Format));
191 }
192
193 for (uiCurrentRenderPass = 0;
194 uiCurrentRenderPass < uiRenderPasses;
195 uiCurrentRenderPass++)
196 {
197 // Assign source surfaces for current rendering pass
198 MOS_SecureMemcpy(
199 RenderParams.pSrc,
200 sizeof(PVPHAL_SURFACE) * VPHAL_MAX_SOURCES,
201 (uiCurrentRenderPass == 0) ? pSrcLeft : pSrcRight,
202 sizeof(PVPHAL_SURFACE) * VPHAL_MAX_SOURCES);
203
204 MOS_ZeroMemory(&Info, sizeof(VPHAL_GET_SURFACE_INFO));
205
206 for (uiDst = 0; uiDst < RenderParams.uDstCount; uiDst++)
207 {
208 Info.S3dChannel = RenderParams.pTarget[uiDst]->Channel;
209 Info.ArraySlice = uiCurrentRenderPass;
210
211 VPHAL_RENDER_CHK_STATUS(VpHal_GetSurfaceInfo(
212 m_pOsInterface,
213 &Info,
214 RenderParams.pTarget[uiDst]));
215 }
216
217 // Update channel. 0 = mono or stereo left, 1 = stereo right
218 uiCurrentChannel = uiCurrentRenderPass;
219
220 VPHAL_RENDER_CHK_STATUS(RenderScaling(&RenderParams));
221
222 VPHAL_RENDER_CHK_STATUS(RenderPass(&RenderParams));
223 }
224
225 finish:
226 uiFrameCounter++;
227 return eStatus;
228 }
229
230 //!
231 //! \brief set Render Gpu Context
232 //! \details set Render Gpu Context based on lumakey and CCS status.
233 //! \param [in] RenderParams
234 //! VPHAL render parameter
235 //! \return MOS_STATUS
236 //! Return MOS_STATUS_SUCCESS if successful, otherwise failed
237 //!
SetRenderGpuContext(VPHAL_RENDER_PARAMS & RenderParams)238 MOS_STATUS VphalRendererG12Tgllp::SetRenderGpuContext(VPHAL_RENDER_PARAMS& RenderParams)
239 {
240 MOS_GPU_CONTEXT currentGpuContext = m_pOsInterface->pfnGetGpuContext(m_pOsInterface);
241 bool bLumaKeyEnabled = false;
242
243 for (uint32_t uiSources = 0; uiSources < RenderParams.uSrcCount; uiSources++)
244 {
245 VPHAL_SURFACE* pSrc = (VPHAL_SURFACE*)RenderParams.pSrc[uiSources];
246 bLumaKeyEnabled = (pSrc && pSrc->pLumaKeyParams) ? true : false;
247 if (bLumaKeyEnabled)
248 {
249 break;
250 }
251 }
252 if (bLumaKeyEnabled)
253 {
254 currentGpuContext = MOS_GPU_CONTEXT_RENDER;
255 }
256 UpdateRenderGpuContext(currentGpuContext);
257
258 return MOS_STATUS_SUCCESS;
259 }
260
261 //!
262 //! \brief Scaling function
263 //! \details The scaling function is only for scaling without other VP features.
264 //! Down scaling needs 2 pass if scaling ratio is >2 for better quality.
265 //! Pass#1 DS to 1/2 target resolution; Pass #2: DS from 1/2 target resolution to target resolution
266 //! \param [in,out] pRenderParams
267 //! Pointer to VPHAL render parameter
268 //! \return MOS_STATUS
269 //! Return MOS_STATUS_SUCCESS if successful, otherwise failed
270 //!
RenderScaling(PVPHAL_RENDER_PARAMS pRenderParams)271 MOS_STATUS VphalRendererG12Tgllp::RenderScaling(
272 PVPHAL_RENDER_PARAMS pRenderParams)
273 {
274 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
275 PVPHAL_SURFACE pSource = nullptr; // Pointer to the primary and original source surface
276 PVPHAL_SURFACE pTarget = nullptr; // Pointer to the target surface
277 float fScaleX = 0.0; // The original scaling ratio in X axis
278 float fScaleY = 0.0; // the original scaling ratio in Y axis
279 PLATFORM Platform = {};
280 bool bScalingFirst = false; // Need to scaling first or not?
281 bool b2PassScaling = false; // 2 Pass scaling
282 uint32_t dwAllocatedWidth = 1280; // The width of intermediate surfaces
283 uint32_t dwAllocatedHeight = 720; // The height of intermediate surfaces
284 RECT rectScalingRegion = {0, 0, 1280, 720}; // Scaling region of down scaling
285 VPHAL_RENDER_PARAMS renderParams = {};
286 VPHAL_SURFACE inputSurface = {};
287 PVPHAL_3DLUT_PARAMS p3DLutParams = nullptr;
288 PVPHAL_SURFACE pDSSurface = nullptr; // Always point to the down scaled surface
289 uint32_t dwHalfInWidth = 1280; // Half of the processed input width
290 uint32_t dwHalfInHeight = 720; // Half of the processed input height
291 RECT rectHalfInRegion = {0, 0, 1280, 720}; // Half of the processed input region
292
293 VPHAL_RENDER_CHK_NULL(pRenderParams);
294 VPHAL_RENDER_CHK_NULL(pRenderParams->pSrc);
295 VPHAL_RENDER_CHK_NULL(pRenderParams->pTarget);
296 VPHAL_RENDER_CHK_NULL(m_pSkuTable);
297 VPHAL_RENDER_CHK_NULL(m_pOsInterface);
298
299 // Limited to 1 input and 1 output. If not 1->1, fall back to the typical video processing path.
300 if ((pRenderParams->uSrcCount != 1) || (pRenderParams->uDstCount != 1))
301 {
302 VPHAL_RENDER_NORMALMESSAGE(" Source Count %d, Destination Count %d", pRenderParams->uSrcCount, pRenderParams->uDstCount);
303 eStatus = MOS_STATUS_SUCCESS;
304 goto finish;
305 }
306
307 pSource = pRenderParams->pSrc[0];
308 pTarget = pRenderParams->pTarget[0];
309 VPHAL_RENDER_CHK_NULL(pSource);
310 VPHAL_RENDER_CHK_NULL(pTarget);
311
312 // Calculating the scaling ratio
313 fScaleX = (float)(pSource->rcDst.right - pSource->rcDst.left) /
314 (float)(pSource->rcSrc.right - pSource->rcSrc.left);
315 fScaleY = (float)(pSource->rcDst.bottom - pSource->rcDst.top) /
316 (float)(pSource->rcSrc.bottom - pSource->rcSrc.top);
317 b2PassScaling = (fScaleX < 0.5f) && (fScaleY < 0.5f);
318
319 // Scaling first, then other VP features. It is only enabled on DG1 with 3DLUT enabled if down scaling as of now.
320 m_pOsInterface->pfnGetPlatform(m_pOsInterface, &Platform);
321 bScalingFirst = MEDIA_IS_SKU(m_pSkuTable, FtrScalingFirst) &&
322 ((Platform.usDeviceID == 0x4905) ||
323 (Platform.usDeviceID == 0x4906) ||
324 (Platform.usDeviceID == 0x4907) ||
325 (Platform.usDeviceID == 0x4908)) &&
326 (pSource->p3DLutParams != nullptr) &&
327 (fScaleX < 1.0f && fScaleY < 1.0f);
328
329 // If no need to scaling firstly, fall back to the typical video processing path.
330 if (!bScalingFirst)
331 {
332 eStatus = MOS_STATUS_SUCCESS;
333 goto finish;
334 }
335
336 // Do the down scaling firstly, then 3DLUT VEBOX features.
337 // Allocate down scaling surfaces
338 for (uint32_t nIndex = 0; nIndex < VPHAL_MAX_NUM_DS_SURFACES; nIndex++)
339 {
340 if (m_pDSSurface[nIndex] == nullptr)
341 {
342 m_pDSSurface[nIndex] = (PVPHAL_SURFACE)MOS_AllocAndZeroMemory(sizeof(VPHAL_SURFACE));
343 VPHAL_RENDER_CHK_NULL(m_pDSSurface[nIndex]);
344 }
345 }
346
347 // Calculate the size of processing region for 2 pass downscaling
348 dwHalfInWidth = (uint32_t)((0.5) * (float)(pSource->rcSrc.right - pSource->rcSrc.left));
349 dwHalfInHeight = (uint32_t)((0.5) * (float)(pSource->rcSrc.bottom- pSource->rcSrc.top));
350 dwHalfInWidth = MOS_ALIGN_CEIL(dwHalfInWidth, 4);
351 dwHalfInHeight = MOS_ALIGN_CEIL(dwHalfInHeight, 4);
352 rectHalfInRegion.top = 0;
353 rectHalfInRegion.left = 0;
354 rectHalfInRegion.right = dwHalfInWidth;
355 rectHalfInRegion.bottom = dwHalfInHeight;
356
357 // Allocate intermediate surface for the first pass
358 dwAllocatedWidth = MOS_MAX(dwHalfInWidth, pTarget->dwWidth);
359 dwAllocatedHeight = MOS_MAX(dwHalfInHeight, pTarget->dwHeight);
360 VPHAL_RENDER_CHK_STATUS(AllocateSurface(pRenderParams, pSource, m_pDSSurface[0], dwAllocatedWidth, dwAllocatedHeight, pSource->Format));
361 // First pass scaling
362 {
363 // Use inputSurface instead of the pointer of the original input to keep it unchanged.
364 rectScalingRegion = (b2PassScaling) ? rectHalfInRegion : pSource->rcDst;
365 p3DLutParams = pSource->p3DLutParams;
366 renderParams = *pRenderParams;
367 inputSurface = *pSource;
368 inputSurface.p3DLutParams = nullptr;
369 inputSurface.rcDst = rectScalingRegion;
370 m_pDSSurface[0]->rcSrc = rectScalingRegion;
371 m_pDSSurface[0]->rcDst = rectScalingRegion;
372 m_pDSSurface[0]->rcMaxSrc = rectScalingRegion;
373 renderParams.pSrc[0] = &inputSurface;
374 renderParams.pTarget[0] = m_pDSSurface[0];
375 VPHAL_RENDER_CHK_STATUS(RenderPass(&renderParams));
376 m_pDSSurface[0]->rcSrc = m_pDSSurface[0]->rcDst;
377 m_pDSSurface[0]->rcMaxSrc = m_pDSSurface[0]->rcDst;
378 m_pDSSurface[0]->rcDst = pSource->rcDst;
379 pDSSurface = m_pDSSurface[0];
380 }
381
382 // Second pass scaling
383 if (b2PassScaling)
384 {
385 dwAllocatedWidth = pTarget->dwWidth;
386 dwAllocatedHeight = pTarget->dwHeight;
387 VPHAL_RENDER_CHK_STATUS(AllocateSurface(pRenderParams, pSource, m_pDSSurface[1], dwAllocatedWidth, dwAllocatedHeight, pSource->Format));
388 rectScalingRegion = pSource->rcDst;
389 m_pDSSurface[0]->rcDst = rectScalingRegion;
390 m_pDSSurface[1]->rcDst = rectScalingRegion;
391
392 inputSurface = *m_pDSSurface[0];
393 inputSurface.p3DLutParams = nullptr;
394 renderParams.pSrc[0] = &inputSurface;
395 renderParams.pTarget[0] = m_pDSSurface[1];
396 VPHAL_RENDER_CHK_STATUS(RenderPass(&renderParams));
397 m_pDSSurface[1]->rcSrc = m_pDSSurface[1]->rcDst;
398 m_pDSSurface[1]->rcMaxSrc = m_pDSSurface[1]->rcDst;
399 m_pDSSurface[1]->rcDst = pSource->rcDst;
400 pDSSurface = m_pDSSurface[1];
401 }
402
403 // Attach 3DLUT parameters to the down scaled surface.
404 if (pSource->p3DLutParams)
405 {
406 if (pDSSurface->p3DLutParams == nullptr)
407 {
408 pDSSurface->p3DLutParams = (PVPHAL_3DLUT_PARAMS)MOS_AllocAndZeroMemory(sizeof(VPHAL_3DLUT_PARAMS));
409 VPHAL_RENDER_CHK_NULL(pDSSurface->p3DLutParams);
410 }
411 MOS_SecureMemcpy(pDSSurface->p3DLutParams, sizeof(VPHAL_3DLUT_PARAMS), pSource->p3DLutParams, sizeof(VPHAL_3DLUT_PARAMS));
412 }
413 else
414 {
415 MOS_FreeMemory(pDSSurface->p3DLutParams);
416 pDSSurface->p3DLutParams = nullptr;
417 }
418
419 pRenderParams->pSrc[0] = pDSSurface;
420
421 finish:
422 return eStatus;
423 }
424