1 /*
2 * Copyright (c) 2014-2017, 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 //!
24 //! \file     codechal_decode_vc1_g8.cpp
25 //! \brief    Implements the decode interface extension for Gen8 VC1.
26 //! \details  Implements all functions required by CodecHal for Gen8 VC1 decoding.
27 //!
28 
29 #include "codeckrnheader.h"
30 #include "igcodeckrn_g8.h"
31 #include "codechal_decode_vc1_g8.h"
32 
33 const CODECHAL_DECODE_VC1_OLP_STATIC_DATA_G8 g_cInit_CODECHAL_DECODE_VC1_OLP_STATIC_DATA_G8 =
34 {
35     // uint32_t 0
36     {
37         { 0 }
38     },
39 
40     // uint32_t 1
41     {
42         {
43             16,     // BlockWidth in Byte
44             16      // BlockHeight in Byte
45         }
46     },
47 
48     // uint32_t 2
49     {
50         {
51             0,      // Profile
52             0,      // RangeExpansionFlag
53             0,      // UpsamplingFlag
54             0,      // InterlaceFieldFlag
55             0,      // RangeMapUV
56             0,      // RangeMapUVFlag
57             0,      // RangeMapY
58             0,      // RangeMapYFlag
59             0       // ComponentFlag
60         }
61     },
62 
63     // uint32_t 3
64     {
65         { 0 }       // Reserved
66     },
67 
68     // uint32_t 4
69     {
70         { 0 }       // Reserved
71     },
72 
73     // uint32_t 5
74     {
75         { 0 }       // Reserved
76     },
77 
78     // uint32_t 6
79     {
80         { 0 }       // Reserved
81     },
82 
83     // uint32_t 7
84     {
85         { 0 }       // Reserved
86     }
87 };
88 
89 const CODECHAL_DECODE_VC1_OLP_INLINE_DATA_G8  g_cInit_CODECHAL_DECODE_VC1_OLP_INLINE_DATA_G8 =
90 {
91     // uint32_t 0
92     {
93         {
94             0,      // BlockOriginY
95             0       // BlockOriginX
96         }
97     },
98 
99     // uint32_t 1
100     {
101         { 0 }       // ComponentFlag
102     },
103 
104     // uint32_t 2
105     {
106         {
107             0,      // SourceDataBindingIndex
108             0       // DestDataBindingIndex
109         }
110     },
111 
112     // uint32_t 3 - 7
113     {
114         0           // Reserved
115     },
116 };
117 
SetCurbeOlp()118 MOS_STATUS CodechalDecodeVc1G8::SetCurbeOlp()
119 {
120     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
121 
122     CODECHAL_DECODE_CHK_NULL_RETURN(m_hwInterface->GetRenderInterface());
123     CODECHAL_DECODE_CHK_NULL_RETURN(m_hwInterface->GetRenderInterface()->m_stateHeapInterface);
124 
125     CODECHAL_DECODE_VC1_OLP_STATIC_DATA_G8 cmd = g_cInit_CODECHAL_DECODE_VC1_OLP_STATIC_DATA_G8;
126 
127     cmd.DW2.InterlaceFieldFlag    = CodecHal_PictureIsField(m_vc1PicParams->CurrPic);
128     cmd.DW2.PictureUpsamplingFlag = m_vc1PicParams->UpsamplingFlag;
129     cmd.DW2.RangeExpansionFlag    = (m_vc1PicParams->range_mapping_fields.range_mapping_enabled != 0);
130     cmd.DW2.Profile               = m_vc1PicParams->sequence_fields.AdvancedProfileFlag;
131 
132     if (m_vc1PicParams->sequence_fields.AdvancedProfileFlag)
133     {
134         cmd.DW2.RangeMapUV     = m_vc1PicParams->range_mapping_fields.chroma;
135         cmd.DW2.RangeMapUVFlag = m_vc1PicParams->range_mapping_fields.chroma_flag;
136         cmd.DW2.RangeMapY      = m_vc1PicParams->range_mapping_fields.luma;
137         cmd.DW2.RangeMapYFlag  = m_vc1PicParams->range_mapping_fields.luma_flag;
138     }
139 
140     CODECHAL_DECODE_CHK_STATUS_RETURN(m_olpKernelState.m_dshRegion.AddData(
141         &cmd,
142         m_olpKernelState.dwCurbeOffset,
143         sizeof(cmd)));
144 
145     return eStatus;
146 }
147 
AddVc1OlpMediaObjectsBB(PMHW_BATCH_BUFFER batchBuffer)148 MOS_STATUS CodechalDecodeVc1G8::AddVc1OlpMediaObjectsBB(
149     PMHW_BATCH_BUFFER               batchBuffer)
150 {
151     MOS_STATUS                             eStatus = MOS_STATUS_SUCCESS;
152 
153     CODECHAL_DECODE_FUNCTION_ENTER;
154 
155     CODECHAL_DECODE_CHK_NULL_RETURN(m_hwInterface->GetRenderInterface());
156 
157     uint16_t surfaceWidthInBlock  = m_olpPicWidthInMb;
158     uint16_t surfaceHeightInBlock = m_olpPicHeightInMb;
159 
160     CODECHAL_DECODE_VC1_OLP_INLINE_DATA_G8 inlineData = g_cInit_CODECHAL_DECODE_VC1_OLP_INLINE_DATA_G8;
161 
162     MHW_MEDIA_OBJECT_PARAMS                mediaObjectParams;
163     MOS_ZeroMemory(&mediaObjectParams, sizeof(mediaObjectParams));
164     mediaObjectParams.dwInterfaceDescriptorOffset = m_olpKernelState.dwIdOffset;
165     mediaObjectParams.dwInlineDataSize = sizeof(CODECHAL_DECODE_VC1_OLP_INLINE_DATA_G8);
166     mediaObjectParams.pInlineData = &inlineData;
167 
168     // Process each Block (16x16) for Y surface
169     inlineData.DW1.ComponentFlag = 0;
170     inlineData.DW2.DestDataBindingIndex = 3;
171     inlineData.DW2.SourceDataBindingIndex = 0;
172 
173     uint32_t tileX = 0, tileY = 0;
174     for (tileY = 0; tileY < surfaceHeightInBlock; tileY++)
175     {
176         for (tileX = 0; tileX < surfaceWidthInBlock; tileX++)
177         {
178             inlineData.DW0.BlockOriginX = tileX * 16;
179             inlineData.DW0.BlockOriginY = tileY * 16;
180 
181             CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->GetRenderInterface()->AddMediaObject(nullptr, batchBuffer, &mediaObjectParams));
182         }
183     }
184 
185     surfaceHeightInBlock                  = MOS_ALIGN_CEIL(m_olpPicHeightInMb, 2) / 2;
186     inlineData.DW1.ComponentFlag = 1;
187     inlineData.DW2.DestDataBindingIndex = 4;
188     inlineData.DW2.SourceDataBindingIndex = 1;
189 
190     for (tileY = 0; tileY < surfaceHeightInBlock; tileY++)
191     {
192         for (tileX = 0; tileX < surfaceWidthInBlock; tileX++)
193         {
194             inlineData.DW0.BlockOriginX = tileX * 16;
195             inlineData.DW0.BlockOriginY = tileY * 16;
196             mediaObjectParams.pInlineData = &inlineData;
197 
198             CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->GetRenderInterface()->AddMediaObject(nullptr, batchBuffer, &mediaObjectParams));
199         }
200     }
201 
202     return eStatus;
203 }
204 
UpdateVc1KernelState()205 MOS_STATUS CodechalDecodeVc1G8::UpdateVc1KernelState()
206 {
207     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
208 
209     CODECHAL_DECODE_FUNCTION_ENTER;
210 
211     PMHW_STATE_HEAP_INTERFACE stateHeapInterface = m_hwInterface->GetRenderInterface()->m_stateHeapInterface;
212     PCODECHAL_DECODE_VC1_KERNEL_HEADER decodeKernel;
213     PMHW_KERNEL_STATE                  kernelState = &m_olpKernelState;
214 
215     decodeKernel = (PCODECHAL_DECODE_VC1_KERNEL_HEADER)kernelState->KernelParams.pBinary;
216     kernelState->dwKernelBinaryOffset =
217         decodeKernel->OLP.KernelStartPointer << MHW_KERNEL_OFFSET_SHIFT;
218     kernelState->KernelParams.iInlineDataLength = sizeof(CODECHAL_DECODE_VC1_OLP_INLINE_DATA_G8);
219 
220     m_olpDshSize =
221         stateHeapInterface->pStateHeapInterface->GetSizeofCmdInterfaceDescriptorData() +
222         MOS_ALIGN_CEIL(m_olpCurbeStaticDataLength, stateHeapInterface->pStateHeapInterface->GetCurbeAlignment());
223 
224     return eStatus;
225 }
226 
AllocateResources()227 MOS_STATUS CodechalDecodeVc1G8::AllocateResources()
228 {
229     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
230 
231     CODECHAL_DECODE_FUNCTION_ENTER;
232 
233     CODECHAL_DECODE_CHK_STATUS_RETURN(CodechalDecodeVc1::AllocateResources());
234 
235     // Second level batch buffer for OLP
236     {
237         MOS_ZeroMemory(&m_olpBatchBuffer, sizeof(m_olpBatchBuffer));
238         uint32_t u32Size = m_hwInterface->GetMediaObjectBufferSize(
239             (m_numMacroblocks + m_numMacroblocksUv),
240             sizeof(CODECHAL_DECODE_VC1_OLP_INLINE_DATA_G8));
241         CODECHAL_DECODE_CHK_STATUS_RETURN(Mhw_AllocateBb(
242             m_osInterface,
243             &m_olpBatchBuffer,
244             nullptr,
245             u32Size));
246         m_olpBatchBuffer.bSecondLevel = true;
247     }
248 
249     return eStatus;
250 }
251 
AddVc1OlpCmd(PCODECHAL_DECODE_VC1_OLP_PARAMS vc1OlpParams)252 MOS_STATUS CodechalDecodeVc1G8::AddVc1OlpCmd(
253     PCODECHAL_DECODE_VC1_OLP_PARAMS vc1OlpParams)
254 {
255     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
256 
257     CODECHAL_DECODE_FUNCTION_ENTER;
258 
259     CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferStartCmd(vc1OlpParams->pCmdBuffer, &m_olpBatchBuffer));
260 
261     // check if we need to reset the batch buffer
262     if ((m_picWidthInMb - m_olpPicWidthInMb) ||
263         (m_picHeightInMb - m_olpPicHeightInMb))
264     {
265         CODECHAL_DECODE_CHK_STATUS_RETURN(Mhw_LockBb(m_osInterface, &m_olpBatchBuffer));
266         m_olpPicWidthInMb  = m_picWidthInMb;
267         m_olpPicHeightInMb = m_picHeightInMb;
268 
269         CODECHAL_DECODE_CHK_STATUS_RETURN(AddVc1OlpMediaObjectsBB(
270             &m_olpBatchBuffer));
271 
272         CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(nullptr, &m_olpBatchBuffer));
273 
274         CODECHAL_DECODE_CHK_STATUS_RETURN(Mhw_UnlockBb(m_osInterface, &m_olpBatchBuffer, true));
275     }
276 
277     CODECHAL_DEBUG_TOOL(
278         CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->Dump2ndLvlBatch(
279             &m_olpBatchBuffer,
280             CODECHAL_MEDIA_STATE_OLP,
281             "_DEC"));)
282 
283     return eStatus;
284 }
285 
CodechalDecodeVc1G8(CodechalHwInterface * hwInterface,CodechalDebugInterface * debugInterface,PCODECHAL_STANDARD_INFO standardInfo)286 CodechalDecodeVc1G8::CodechalDecodeVc1G8(
287     CodechalHwInterface   *hwInterface,
288     CodechalDebugInterface* debugInterface,
289     PCODECHAL_STANDARD_INFO standardInfo) :
290     CodechalDecodeVc1(hwInterface, debugInterface, standardInfo)
291 {
292     MOS_ZeroMemory(&m_olpBatchBuffer, sizeof(m_olpBatchBuffer));
293 
294     CODECHAL_DECODE_CHK_NULL_NO_STATUS_RETURN(hwInterface);
295 
296     m_olpCurbeStaticDataLength = CODECHAL_DECODE_VC1_CURBE_SIZE_OLP_G8;
297 
298     MOS_STATUS eStatus = CodecHalGetKernelBinaryAndSize(
299         (uint8_t *)IGCODECKRN_G8,
300         IDR_CODEC_AllVC1_NV12,
301         &m_olpKernelBase,
302         &m_olpKernelSize);
303 
304     CODECHAL_DECODE_ASSERT(eStatus == MOS_STATUS_SUCCESS);
305 
306     hwInterface->GetStateHeapSettings()->dwNumSyncTags = CODECHAL_DECODE_VC1_NUM_SYNC_TAGS;
307     hwInterface->GetStateHeapSettings()->dwIshSize =
308         MOS_ALIGN_CEIL(m_olpKernelSize, (1 << MHW_KERNEL_OFFSET_SHIFT));
309     hwInterface->GetStateHeapSettings()->dwDshSize = CODECHAL_DECODE_VC1_INITIAL_DSH_SIZE;
310 }
311 
~CodechalDecodeVc1G8()312 CodechalDecodeVc1G8::~CodechalDecodeVc1G8()
313 {
314     Mhw_FreeBb(m_osInterface, &m_olpBatchBuffer, nullptr);
315 };
316