Skip to content

Commit 3202761

Browse files
LhGuintel-mediadev
authored andcommitted
[Media Common] NVL-S Linux DDI Layer Upstreaming
NVL-S Linux DDI Layer Upstreaming, This patch is just part of NVLS code, it does not officially enable NVLS support. More patches will follow. The availability of NVLS will be announced in the readme.
1 parent 4eaa389 commit 3202761

36 files changed

+3257
-0
lines changed

media_softlet/linux/media_srcs.cmake

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,9 @@ endif()
4141
if(XE3_LPM_SUPPORT)
4242
media_include_subdirectory(xe3_lpm)
4343
media_include_subdirectory(xe3_lpm_r0)
44+
endif()
45+
46+
if(XE3P_LPM_SUPPORT)
47+
media_include_subdirectory(xe3p_lpm)
48+
media_include_subdirectory(xe3p_lpm_r0)
4449
endif()
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright (c) 2025, 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 caps_register_specific_xe3p_lpm.cpp
24+
//! \brief This file register all caps data for xe3p_lpm
25+
//!
26+
27+
// Only for new platforms init, should be removed once new platform caps init done
28+
#include "capstable_data_xe3p_lpm_r0_specific.h"
29+
30+
// Static initialization to register capabilities table for xe3p_lpm_r0 platform
31+
// The return value is intentionally unused - only the registration side effect matters
32+
static bool capsTableXe3p_Lpm_r0Registered = MediaCapsTable<CapsData>::RegisterCaps(plt_Xe3p_Lpm_r0, capsData_Xe3p_Lpm_r0);
Lines changed: 298 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,298 @@
1+
/*
2+
* Copyright (c) 2025, 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 media_sku_wa_nvls.cpp
25+
//!
26+
27+
#include "igfxfmid.h"
28+
#include "linux_system_info.h"
29+
#include "skuwa_factory.h"
30+
#include "linux_skuwa_debug.h"
31+
#include "linux_media_skuwa.h"
32+
#include "media_user_setting_specific.h"
33+
34+
static constexpr uint32_t singleVeboxSubSliceNumMax = 24;
35+
36+
//extern template class DeviceInfoFactory<GfxDeviceInfo>;
37+
typedef DeviceInfoFactory<LinuxDeviceInit> DeviceInit;
38+
39+
static struct LinuxCodecInfo nvlCodecInfo =
40+
{
41+
.avcDecoding = 1,
42+
.mpeg2Decoding = 1,
43+
.vp8Decoding = 1,
44+
.vc1Decoding = 0,
45+
.jpegDecoding = 1,
46+
.avcEncoding = SET_STATUS_BY_FULL_OPEN_SOURCE(1, 0),
47+
.mpeg2Encoding = 0,
48+
.hevcDecoding = 1,
49+
.hevcEncoding = SET_STATUS_BY_FULL_OPEN_SOURCE(1, 0),
50+
.jpegEncoding = 1,
51+
.avcVdenc = 1,
52+
.vp9Decoding = 1,
53+
.hevc10Decoding = 1,
54+
.vp9b10Decoding = 1,
55+
.hevc10Encoding = SET_STATUS_BY_FULL_OPEN_SOURCE(1, 0),
56+
.hevc12Encoding = 0,
57+
.vp8Encoding = 0,
58+
.hevcVdenc = 1,
59+
.vp9Vdenc = 1,
60+
.adv0Decoding = 1,
61+
.adv1Decoding = 1,
62+
};
63+
64+
static bool InitNvlMediaSkuExt(struct GfxDeviceInfo *devInfo,
65+
MediaFeatureTable *skuTable,
66+
struct LinuxDriverInfo *drvInfo,
67+
MediaUserSettingSharedPtr userSettingPtr)
68+
{
69+
if ((devInfo == nullptr) || (skuTable == nullptr) || (drvInfo == nullptr))
70+
{
71+
DEVINFO_ERROR("null ptr is passed\n");
72+
return false;
73+
}
74+
75+
if (drvInfo->hasBsd)
76+
{
77+
LinuxCodecInfo *codecInfo = &nvlCodecInfo;
78+
79+
MEDIA_WR_SKU(skuTable, FtrAVCVLDLongDecoding, codecInfo->avcDecoding);
80+
MEDIA_WR_SKU(skuTable, FtrIntelAVCVLDHigh422Decoding, codecInfo->avcDecoding);
81+
MEDIA_WR_SKU(skuTable, FtrMPEG2VLDDecoding, codecInfo->mpeg2Decoding);
82+
MEDIA_WR_SKU(skuTable, FtrIntelVP8VLDDecoding, codecInfo->vp8Decoding);
83+
MEDIA_WR_SKU(skuTable, FtrVC1VLDDecoding, codecInfo->vc1Decoding);
84+
MEDIA_WR_SKU(skuTable, FtrIntelJPEGDecoding, codecInfo->jpegDecoding);
85+
MEDIA_WR_SKU(skuTable, FtrEncodeAVC, codecInfo->avcEncoding);
86+
MEDIA_WR_SKU(skuTable, FtrEncodeMPEG2, codecInfo->mpeg2Encoding);
87+
MEDIA_WR_SKU(skuTable, FtrIntelHEVCVLDMainDecoding, codecInfo->hevcDecoding);
88+
MEDIA_WR_SKU(skuTable, FtrIntelHEVCVLDMain10Decoding, codecInfo->hevc10Decoding);
89+
MEDIA_WR_SKU(skuTable, FtrIntelVVCVLDDecodingMain10, 1);
90+
MEDIA_WR_SKU(skuTable, FtrIntelVVCVLDDecodingMultilayerMain10, 0);
91+
92+
MEDIA_WR_SKU(skuTable, FtrEncodeHEVC, codecInfo->hevcEncoding);
93+
MEDIA_WR_SKU(skuTable, FtrEncodeHEVC10bit, codecInfo->hevc10Encoding);
94+
MEDIA_WR_SKU(skuTable, FtrEncodeJPEG, codecInfo->jpegEncoding);
95+
MEDIA_WR_SKU(skuTable, FtrEncodeAVCVdenc, codecInfo->avcVdenc);
96+
MEDIA_WR_SKU(skuTable, FtrVP9VLDDecoding, codecInfo->vp9Decoding);
97+
MEDIA_WR_SKU(skuTable, FtrIntelVP9VLDProfile0Decoding8bit420, codecInfo->vp9Decoding);
98+
MEDIA_WR_SKU(skuTable, FtrVP9VLD10bProfile2Decoding, codecInfo->vp9b10Decoding);
99+
MEDIA_WR_SKU(skuTable, FtrIntelVP9VLDProfile2Decoding, codecInfo->vp9b10Decoding);
100+
MEDIA_WR_SKU(skuTable, FtrIntelAV1VLDDecoding8bit420, codecInfo->adv0Decoding);
101+
MEDIA_WR_SKU(skuTable, FtrAV1VLDProfile1Decoding8bit444, codecInfo->adv0Decoding);
102+
MEDIA_WR_SKU(skuTable, FtrIntelAV1VLDDecoding10bit420, codecInfo->adv1Decoding);
103+
MEDIA_WR_SKU(skuTable, FtrAV1VLDProfile1Decoding10bit444, codecInfo->adv1Decoding);
104+
105+
/* HEVC VDENC */
106+
MEDIA_WR_SKU(skuTable, FtrEncodeHEVCVdencMain, codecInfo->hevcVdenc);
107+
MEDIA_WR_SKU(skuTable, FtrEncodeHEVCVdencMain10, codecInfo->hevcVdenc);
108+
109+
/* Vp9 VDENC */
110+
MEDIA_WR_SKU(skuTable, FtrEncodeVP9Vdenc, codecInfo->vp9Vdenc);
111+
112+
/* HEVC Main8/10bit-422/444 Decoding. Currently it is enabled. */
113+
MEDIA_WR_SKU(skuTable, FtrIntelHEVCVLD42210bitDecoding, 1);
114+
MEDIA_WR_SKU(skuTable, FtrIntelHEVCVLD4448bitDecoding, 1);
115+
MEDIA_WR_SKU(skuTable, FtrIntelHEVCVLD44410bitDecoding, 1);
116+
117+
/* SFC Histogram Streamout. */
118+
MEDIA_WR_SKU(skuTable, FtrSFCHistogramStreamOut, 1);
119+
120+
/* Subset buffer for realtile decoding. */
121+
MEDIA_WR_SKU(skuTable, FtrIntelHEVCVLDDecodingSubsetBuffer, 1);
122+
123+
/* HEVC Main8/10bit-420/422/444 Scc Decoding. Currently it is enabled. */
124+
MEDIA_WR_SKU(skuTable, FtrIntelHEVCVLDMain8bit420SCC, 1);
125+
MEDIA_WR_SKU(skuTable, FtrIntelHEVCVLDMain10bit420SCC, 1);
126+
MEDIA_WR_SKU(skuTable, FtrIntelHEVCVLDMain8bit444SCC, 1);
127+
MEDIA_WR_SKU(skuTable, FtrIntelHEVCVLDMain10bit444SCC, 1);
128+
129+
/* HEVC VDENC Main8/10 422/444 Encoding. */
130+
MEDIA_WR_SKU(skuTable, FtrEncodeHEVCVdencMain444, codecInfo->hevcVdenc);
131+
MEDIA_WR_SKU(skuTable, FtrEncodeHEVCVdencMain422, codecInfo->hevcVdenc);
132+
MEDIA_WR_SKU(skuTable, FtrEncodeHEVCVdencMain10bit422, codecInfo->hevcVdenc);
133+
MEDIA_WR_SKU(skuTable, FtrEncodeHEVCVdencMain10bit444, codecInfo->hevcVdenc);
134+
135+
/* HEVC 12bit Decoding. Currently it is enabled */
136+
MEDIA_WR_SKU(skuTable, FtrIntelHEVCVLDMain12bit420Decoding, 1);
137+
MEDIA_WR_SKU(skuTable, FtrIntelHEVCVLDMain12bit422Decoding, 1);
138+
MEDIA_WR_SKU(skuTable, FtrIntelHEVCVLDMain12bit444Decoding, 1);
139+
140+
/* VP9 8 bit 444 */
141+
MEDIA_WR_SKU(skuTable, FtrIntelVP9VLDProfile1Decoding8bit444, 1);
142+
/* VP9 10 Bit 444*/
143+
MEDIA_WR_SKU(skuTable, FtrIntelVP9VLDProfile3Decoding10bit444, 1);
144+
/* VP9 12 bit 420/444 */
145+
MEDIA_WR_SKU(skuTable, FtrIntelVP9VLDProfile2Decoding12bit420, 1);
146+
MEDIA_WR_SKU(skuTable, FtrIntelVP9VLDProfile3Decoding12bit444, 1);
147+
148+
/* VP9 VDENC 8Bit 444 */
149+
MEDIA_WR_SKU(skuTable, FtrEncodeVP9Vdenc8bit444, codecInfo->vp9Vdenc);
150+
/* VP9 VDENC 10Bit 420/444 */
151+
MEDIA_WR_SKU(skuTable, FtrEncodeVP9Vdenc10bit420, codecInfo->vp9Vdenc);
152+
MEDIA_WR_SKU(skuTable, FtrEncodeVP9Vdenc10bit444, codecInfo->vp9Vdenc);
153+
154+
/* AV1 VDENC 8/10Bit 420 */
155+
MEDIA_WR_SKU(skuTable, FtrEncodeAV1Vdenc, 1);
156+
MEDIA_WR_SKU(skuTable, FtrEncodeAV1Vdenc10bit420, 1);
157+
}
158+
159+
MEDIA_WR_SKU(skuTable, FtrEnableProtectedHuc, drvInfo->hasProtectedHuc);
160+
MEDIA_WR_SKU(skuTable, FtrEnableMediaKernels, drvInfo->hasHuc);
161+
MEDIA_WR_SKU(skuTable, FtrVERing, drvInfo->hasVebox);
162+
MEDIA_WR_SKU(skuTable, FtrPPGTT, drvInfo->hasPpgtt);
163+
MEDIA_WR_SKU(skuTable, FtrEDram, devInfo->hasERAM);
164+
MEDIA_WR_SKU(skuTable, FtrPPGTTBasedHuCLoad, 1);
165+
166+
MEDIA_WR_SKU(skuTable, FtrSingleVeboxSlice, 1);
167+
if (devInfo->SubSliceCount >= singleVeboxSubSliceNumMax)
168+
{
169+
MEDIA_WR_SKU(skuTable, FtrSingleVeboxSlice, 0);
170+
}
171+
172+
MEDIA_WR_SKU(skuTable, FtrSFCPipe, 1);
173+
MEDIA_WR_SKU(skuTable, FtrHCP2SFCPipe, 1);
174+
MEDIA_WR_SKU(skuTable, FtrSSEUPowerGating, 1);
175+
MEDIA_WR_SKU(skuTable, FtrSSEUPowerGatingControlByUMD, 1);
176+
177+
MEDIA_WR_SKU(skuTable, FtrPerCtxtPreemptionGranularityControl, 1);
178+
179+
/* It is disabled by default. It can be enabled based on HW */
180+
MEDIA_WR_SKU(skuTable, FtrMemoryCompression, 0);
181+
MEDIA_WR_SKU(skuTable, FtrHcpDecMemoryCompression, 0);
182+
MEDIA_WR_SKU(skuTable, Ftr10bitDecMemoryCompression, 0);
183+
184+
MEDIA_WR_SKU(skuTable, FtrCCSNode, 1);
185+
186+
MEDIA_WR_SKU(skuTable, FtrVpP010Output, 1);
187+
MEDIA_WR_SKU(skuTable, FtrVp10BitSupport, 1);
188+
MEDIA_WR_SKU(skuTable, FtrVp16BitSupport, 1);
189+
190+
MEDIA_WR_SKU(skuTable, FtrContextBasedScheduling, 1);
191+
MEDIA_WR_SKU(skuTable, FtrSfcScalability, 1);
192+
193+
MEDIA_WR_SKU(skuTable, FtrSWMediaReset, 1);
194+
MEDIA_WR_SKU(skuTable, FtrGucSubmission, 1);
195+
196+
MEDIA_WR_SKU(skuTable, FtrTileY, 0);
197+
MEDIA_WR_SKU(skuTable, FtrLinearCCS, 1);
198+
MEDIA_WR_SKU(skuTable, FtrFlatPhysCCS, 1);
199+
200+
MEDIA_WR_SKU(skuTable, FtrWithSlimVdbox, 0);
201+
202+
MEDIA_WR_SKU(skuTable, FtrE2ECompression, 1);
203+
MEDIA_WR_SKU(skuTable, FtrXe2Compression , 1);
204+
MEDIA_WR_SKU(skuTable, FtrHDR, 1);
205+
MEDIA_WR_SKU(skuTable, FtrDisableRenderTargetWidthAdjust, 1);
206+
207+
MOS_USER_FEATURE_VALUE_DATA userFeatureData;
208+
// Disable MMC for all components if set reg key
209+
MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
210+
MOS_UserFeature_ReadValue_ID(
211+
nullptr,
212+
__MEDIA_USER_FEATURE_VALUE_DISABLE_MMC_ID,
213+
&userFeatureData,
214+
(MOS_CONTEXT_HANDLE)nullptr);
215+
if (userFeatureData.bData)
216+
{
217+
MEDIA_WR_SKU(skuTable, FtrE2ECompression, 0);
218+
MEDIA_WR_SKU(skuTable, FtrXe2Compression , 0);
219+
}
220+
221+
// Create uncompressible surface by default
222+
MEDIA_WR_SKU(skuTable, FtrCompressibleSurfaceDefault, 0);
223+
224+
bool compressibleSurfaceEnable = false;
225+
226+
ReadUserSetting(userSettingPtr,
227+
compressibleSurfaceEnable,
228+
"Enable Compressible Surface Creation",
229+
MediaUserSetting::Group::Device);
230+
231+
if (compressibleSurfaceEnable)
232+
{
233+
MEDIA_WR_SKU(skuTable, FtrCompressibleSurfaceDefault, 1);
234+
}
235+
236+
//Disable LocalMemory for all iGraphics
237+
MEDIA_WR_SKU(skuTable, FtrLocalMemory, 0);
238+
239+
MEDIA_WR_SKU(skuTable, FtrConditionalBatchBuffEnd, 1);
240+
MEDIA_WR_SKU(skuTable, FtrUseSwSwizzling, 0);
241+
MEDIA_WR_SKU(skuTable, FtrMemoryRemapSupport, 1);
242+
243+
MEDIA_WR_SKU(skuTable, FtrAV1VLDLSTDecoding, 1);
244+
MEDIA_WR_SKU(skuTable, FtrMediaIPSeparation , 1);
245+
246+
return true;
247+
}
248+
249+
static bool InitNvlMediaWaExt(struct GfxDeviceInfo *devInfo,
250+
MediaWaTable *waTable,
251+
struct LinuxDriverInfo *drvInfo)
252+
{
253+
if ((devInfo == nullptr) || (waTable == nullptr) || (drvInfo == nullptr))
254+
{
255+
DEVINFO_ERROR("null ptr is passed\n");
256+
return false;
257+
}
258+
259+
MEDIA_WR_WA(waTable, WaForceGlobalGTT, !drvInfo->hasPpgtt);
260+
MEDIA_WR_WA(waTable, WaMidBatchPreemption, 0);
261+
MEDIA_WR_WA(waTable, WaArbitraryNumMbsInSlice, 1);
262+
263+
MEDIA_WR_WA(waTable, WaSFC270DegreeRotation, 0);
264+
265+
MEDIA_WR_WA(waTable, WaEnableYV12BugFixInHalfSliceChicken7, 1);
266+
267+
/*software wa to disable calculate the UV offset by gmmlib
268+
CPU blt call will add/remove padding on the platform*/
269+
MEDIA_WR_WA(waTable, WaDisableGmmLibOffsetInDeriveImage, 0);
270+
271+
/* Turn off MMC for codec, need to remove once turn it on */
272+
MEDIA_WR_WA(waTable, WaDisableCodecMmc, 0);
273+
274+
/* Turn off MMC for VPP, need to remove once turn it on */
275+
MEDIA_WR_WA(waTable, WaDisableVPMmc, 0);
276+
277+
MEDIA_WR_WA(waTable, WaDisableSetObjectCapture, 1);
278+
279+
MEDIA_WR_WA(waTable, Wa_Vp9UnalignedHeight, 0);
280+
281+
MEDIA_WR_WA(waTable, Wa_22018691483, 1);
282+
MEDIA_WR_WA(waTable, Wa_15017419530, 1);
283+
MEDIA_WR_WA(waTable, Wa_15017726119, 1);
284+
MEDIA_WR_WA(waTable, Wa_16027316307, 1);
285+
MEDIA_WR_WA(waTable, Wa_16025947269, 1);
286+
287+
return true;
288+
}
289+
290+
static struct LinuxDeviceInit nvlXe3GDeviceInit =
291+
{
292+
.productFamily = IGFX_NVL_XE3G,
293+
.InitMediaFeature = InitNvlMediaSkuExt,
294+
.InitMediaWa = InitNvlMediaWaExt,
295+
};
296+
297+
static bool nvlXe3GDeviceRegister = DeviceInfoFactory<LinuxDeviceInit>::
298+
RegisterDevice(IGFX_NVL_XE3G, &nvlXe3GDeviceInit);
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Copyright (c) 2025, Intel Corporation
2+
#
3+
# Permission is hereby granted, free of charge, to any person obtaining a
4+
# copy of this software and associated documentation files (the "Software"),
5+
# to deal in the Software without restriction, including without limitation
6+
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
7+
# and/or sell copies of the Software, and to permit persons to whom the
8+
# Software is furnished to do so, subject to the following conditions:
9+
#
10+
# The above copyright notice and this permission notice shall be included
11+
# in all copies or substantial portions of the Software.
12+
#
13+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14+
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
16+
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
17+
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
18+
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
19+
# OTHER DEALINGS IN THE SOFTWARE.
20+
21+
set(TMP_SOURCES_
22+
${CMAKE_CURRENT_LIST_DIR}/caps_register_specific_xe3p_lpm.cpp
23+
${CMAKE_CURRENT_LIST_DIR}/media_sysinfo_nvls.cpp
24+
${CMAKE_CURRENT_LIST_DIR}/media_sku_wa_nvls.cpp
25+
)
26+
27+
set(SOFTLET_DDI_SOURCES_
28+
${SOFTLET_DDI_SOURCES_}
29+
${TMP_SOURCES_}
30+
)
31+
32+
set(SOFTLET_DDI_PUBLIC_INCLUDE_DIRS_
33+
${SOFTLET_DDI_PUBLIC_INCLUDE_DIRS_}
34+
${CMAKE_CURRENT_LIST_DIR}
35+
)

0 commit comments

Comments
 (0)