1 /*
2 * Copyright (c) 2019-2021, 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     sw_filter_pipe.cpp
25 //! \brief    Defines the common interface for vp features manager
26 //! \details  The vp manager is further sub-divided by vp type
27 //!           this file is for the base interface which is shared by all components.
28 //!
29 #include "sw_filter_pipe.h"
30 #include "vp_obj_factories.h"
31 #include "vp_feature_manager.h"
32 #include "sw_filter_handle.h"
33 
34 using namespace vp;
35 
36 /****************************************************************************************************/
37 /*                                      SwFilterSubPipe                                             */
38 /****************************************************************************************************/
39 
SwFilterSubPipe()40 SwFilterSubPipe::SwFilterSubPipe()
41 {
42 }
43 
~SwFilterSubPipe()44 SwFilterSubPipe::~SwFilterSubPipe()
45 {
46     Clean();
47 }
48 
Clean()49 MOS_STATUS SwFilterSubPipe::Clean()
50 {
51     VP_FUNC_CALL();
52 
53     for (auto &filterSet : m_OrderedFilters)
54     {
55         if (filterSet)
56         {
57             // Loop orderred feature set.
58             VP_PUBLIC_CHK_STATUS_RETURN(filterSet->Clean());
59             MOS_Delete(filterSet);
60         }
61     }
62     m_OrderedFilters.clear();
63 
64     // Process remaining unordered features
65     VP_PUBLIC_CHK_STATUS_RETURN(m_UnorderedFilters.Clean());
66 
67     return MOS_STATUS_SUCCESS;
68 }
69 
Update(VP_SURFACE * inputSurf,VP_SURFACE * outputSurf)70 MOS_STATUS SwFilterSubPipe::Update(VP_SURFACE *inputSurf, VP_SURFACE *outputSurf)
71 {
72     VP_FUNC_CALL();
73 
74     for (auto &featureSet : m_OrderedFilters)
75     {
76         if (featureSet)
77         {
78             VP_PUBLIC_CHK_STATUS_RETURN(featureSet->Update(inputSurf, outputSurf, *this));
79         }
80     }
81     VP_PUBLIC_CHK_STATUS_RETURN(m_UnorderedFilters.Update(inputSurf, outputSurf, *this));
82 
83     return MOS_STATUS_SUCCESS;
84 }
85 
AddFeatureGraphRTLog()86 MOS_STATUS SwFilterSubPipe::AddFeatureGraphRTLog()
87 {
88     VP_FUNC_CALL();
89 
90     for (auto &featureSet : m_OrderedFilters)
91     {
92         if (featureSet)
93         {
94             VP_PUBLIC_CHK_STATUS_RETURN(featureSet->AddFeatureGraphRTLog());
95         }
96     }
97     VP_PUBLIC_CHK_STATUS_RETURN(m_UnorderedFilters.AddFeatureGraphRTLog());
98 
99     return MOS_STATUS_SUCCESS;
100 }
101 
GetSwFilter(FeatureType type)102 SwFilter *SwFilterSubPipe::GetSwFilter(FeatureType type)
103 {
104     VP_FUNC_CALL();
105 
106     // Search unordered filters firstly.
107     SwFilter *swFilter = m_UnorderedFilters.GetSwFilter(type);
108 
109     if (swFilter)
110     {
111         return swFilter;
112     }
113 
114     for (auto &swFilterSet : m_OrderedFilters)
115     {
116         swFilter = swFilterSet->GetSwFilter(type);
117         if (swFilter)
118         {
119             return swFilter;
120         }
121     }
122 
123     return nullptr;
124 }
125 
AddSwFilterOrdered(SwFilter * swFilter,bool useNewSwFilterSet)126 MOS_STATUS SwFilterSubPipe::AddSwFilterOrdered(SwFilter *swFilter, bool useNewSwFilterSet)
127 {
128     VP_FUNC_CALL();
129 
130     VP_PUBLIC_CHK_NULL_RETURN(swFilter);
131 
132     MOS_STATUS status = MOS_STATUS_SUCCESS;
133     SwFilterSet *swFilterSet = nullptr;
134     auto &pipe = m_OrderedFilters;
135 
136     if (useNewSwFilterSet || pipe.empty())
137     {
138         swFilterSet = MOS_New(SwFilterSet);
139         useNewSwFilterSet = true;
140     }
141     else
142     {
143         swFilterSet = pipe[pipe.size() - 1];
144     }
145     VP_PUBLIC_CHK_NULL_RETURN(swFilterSet);
146 
147     status = swFilterSet->AddSwFilter(swFilter);
148 
149     if (MOS_FAILED(status))
150     {
151         if (useNewSwFilterSet)
152         {
153             MOS_Delete(swFilterSet);
154         }
155         return status;
156     }
157 
158     pipe.push_back(swFilterSet);
159     swFilterSet->SetLocation(&pipe);
160 
161     return MOS_STATUS_SUCCESS;
162 }
163 
AddSwFilterUnordered(SwFilter * swFilter)164 MOS_STATUS SwFilterSubPipe::AddSwFilterUnordered(SwFilter *swFilter)
165 {
166     VP_FUNC_CALL();
167 
168     VP_PUBLIC_CHK_NULL_RETURN(swFilter);
169     return m_UnorderedFilters.AddSwFilter(swFilter);
170 }
171 
172 /****************************************************************************************************/
173 /*                                      SwFilterPipe                                                */
174 /****************************************************************************************************/
175 
SwFilterPipe(VpInterface & vpInterface)176 SwFilterPipe::SwFilterPipe(VpInterface &vpInterface) : m_vpInterface(vpInterface)
177 {
178     m_surfacesSetting.Clean();
179 }
180 
~SwFilterPipe()181 SwFilterPipe::~SwFilterPipe()
182 {
183     Clean();
184 }
185 
Initialize(VP_PIPELINE_PARAMS & params,FeatureRule & featureRule)186 MOS_STATUS SwFilterPipe::Initialize(VP_PIPELINE_PARAMS &params, FeatureRule &featureRule)
187 {
188     VP_FUNC_CALL();
189 
190     Clean();
191 
192     uint32_t i = 0;
193     for (i = 0; i < params.uSrcCount; ++i)
194     {
195         if (nullptr == params.pSrc[i])
196         {
197             Clean();
198             return MOS_STATUS_INVALID_PARAMETER;
199         }
200         VP_SURFACE *surf = m_vpInterface.GetAllocator().AllocateVpSurface(*params.pSrc[i]);
201         if (nullptr == surf)
202         {
203             Clean();
204             MT_ERR2(MT_VP_HAL_SWWFILTER, MT_CODE_LINE, __LINE__, MT_ERROR_CODE, MOS_STATUS_NULL_POINTER);
205             return MOS_STATUS_NULL_POINTER;
206         }
207 
208         surf->Palette = params.pSrc[i]->Palette;
209 
210         m_InputSurfaces.push_back(surf);
211 
212         // Keep m_pastSurface/m_futureSurface same size as m_InputSurfaces.
213         VP_SURFACE *pastSurface = nullptr;
214         if (params.pSrc[i]->uBwdRefCount > 0 && params.pSrc[i]->pBwdRef &&
215             params.pSrc[i]->FrameID != params.pSrc[i]->pBwdRef->FrameID)
216         {
217             pastSurface = m_vpInterface.GetAllocator().AllocateVpSurface(*params.pSrc[i]->pBwdRef);
218         }
219         VP_SURFACE *futureSurface = nullptr;
220         if (params.pSrc[i]->uFwdRefCount > 0 && params.pSrc[i]->pFwdRef &&
221             params.pSrc[i]->FrameID != params.pSrc[i]->pFwdRef->FrameID)
222         {
223             futureSurface = m_vpInterface.GetAllocator().AllocateVpSurface(*params.pSrc[i]->pFwdRef);
224         }
225         m_pastSurface.push_back(pastSurface);
226         m_futureSurface.push_back(futureSurface);
227         m_linkedLayerIndex.push_back(0);
228 
229         // Initialize m_InputPipes.
230         SwFilterSubPipe *pipe = MOS_New(SwFilterSubPipe);
231         if (nullptr == pipe)
232         {
233             Clean();
234             return MOS_STATUS_NULL_POINTER;
235         }
236         m_InputPipes.push_back(pipe);
237     }
238 
239     for (i = 0; i < params.uDstCount; ++i)
240     {
241         if (nullptr == params.pTarget[i])
242         {
243             Clean();
244             return MOS_STATUS_INVALID_PARAMETER;
245         }
246         VP_SURFACE *surf = m_vpInterface.GetAllocator().AllocateVpSurface(*params.pTarget[i]);
247         if (nullptr == surf)
248         {
249             Clean();
250             MT_ERR2(MT_VP_HAL_SWWFILTER, MT_CODE_LINE, __LINE__, MT_ERROR_CODE, MOS_STATUS_NULL_POINTER);
251             return MOS_STATUS_NULL_POINTER;
252         }
253         m_OutputSurfaces.push_back(surf);
254 
255         // Initialize m_OutputPipes.
256         SwFilterSubPipe *pipe = MOS_New(SwFilterSubPipe);
257         if (nullptr == pipe)
258         {
259             Clean();
260             return MOS_STATUS_NULL_POINTER;
261         }
262         m_OutputPipes.push_back(pipe);
263     }
264 
265     UpdateSwFilterPipeType();
266 
267     MOS_STATUS status = ConfigFeatures(params, featureRule);
268     if (MOS_FAILED(status))
269     {
270         Clean();
271         return status;
272     }
273 
274     return MOS_STATUS_SUCCESS;
275 }
276 
Initialize(VEBOX_SFC_PARAMS & params)277 MOS_STATUS SwFilterPipe::Initialize(VEBOX_SFC_PARAMS &params)
278 {
279     VP_FUNC_CALL();
280 
281     Clean();
282 
283     // Initialize input surface.
284     {
285         if (nullptr == params.input.surface)
286         {
287             Clean();
288             return MOS_STATUS_INVALID_PARAMETER;
289         }
290         // The value of plane offset are different between vp and codec. updatePlaneOffset need be set to true when create vp surface
291         // with mos surface from codec hal.
292         VP_SURFACE *input = m_vpInterface.GetAllocator().AllocateVpSurface(*params.input.surface, params.input.colorSpace,
293                                                                         params.input.chromaSiting, params.input.rcSrc,
294                                                                         params.output.rcDst, SURF_IN_PRIMARY, true);
295         if (nullptr == input)
296         {
297             Clean();
298             return MOS_STATUS_NULL_POINTER;
299         }
300         m_InputSurfaces.push_back(input);
301         // Keep m_PastSurface same size as m_InputSurfaces.
302         m_pastSurface.push_back(nullptr);
303         m_futureSurface.push_back(nullptr);
304         m_linkedLayerIndex.push_back(0);
305 
306         // Initialize m_InputPipes.
307         SwFilterSubPipe *pipe = MOS_New(SwFilterSubPipe);
308         if (nullptr == pipe)
309         {
310             Clean();
311             return MOS_STATUS_NULL_POINTER;
312         }
313         m_InputPipes.push_back(pipe);
314     }
315 
316     // Initialize output surface.
317     {
318         if (nullptr == params.output.surface)
319         {
320             Clean();
321             return MOS_STATUS_INVALID_PARAMETER;
322         }
323 
324         RECT recOutput = {0, 0, (int32_t)params.output.surface->dwWidth, (int32_t)params.output.surface->dwHeight};
325         // The value of plane offset are different between vp and codec. updatePlaneOffset need be set to true when create vp surface
326         // with mos surface from codec hal.
327         VP_SURFACE *output = m_vpInterface.GetAllocator().AllocateVpSurface(*params.output.surface, params.output.colorSpace,
328                                                                         params.output.chromaSiting, recOutput,
329                                                                         recOutput, SURF_OUT_RENDERTARGET, true);
330         if (nullptr == output)
331         {
332             Clean();
333             return MOS_STATUS_NULL_POINTER;
334         }
335         m_OutputSurfaces.push_back(output);
336 
337         // Initialize m_OutputPipes.
338         SwFilterSubPipe *pipe = MOS_New(SwFilterSubPipe);
339         if (nullptr == pipe)
340         {
341             Clean();
342             return MOS_STATUS_NULL_POINTER;
343         }
344         m_OutputPipes.push_back(pipe);
345     }
346 
347     UpdateSwFilterPipeType();
348 
349     MOS_STATUS status = ConfigFeatures(params);
350     if (MOS_FAILED(status))
351     {
352         Clean();
353         return status;
354     }
355 
356     return MOS_STATUS_SUCCESS;
357 }
358 
UpdateSwFilterPipeType()359 void SwFilterPipe::UpdateSwFilterPipeType()
360 {
361     VP_FUNC_CALL();
362 
363     m_swFilterPipeType = SwFilterPipeTypeInvalid;
364 
365     if (1 == m_InputSurfaces.size() && 1 == m_OutputSurfaces.size())
366     {
367         m_swFilterPipeType = SwFilterPipeType1To1;
368     }
369     else if (m_InputSurfaces.size() > 1 && 1 == m_OutputSurfaces.size())
370     {
371         m_swFilterPipeType = SwFilterPipeTypeNTo1;
372     }
373     else if (1 == m_InputSurfaces.size() && m_OutputSurfaces.size() > 1)
374     {
375         m_swFilterPipeType = SwFilterPipeType1ToN;
376     }
377     else if (0 == m_InputSurfaces.size() && 1 == m_OutputSurfaces.size())
378     {
379         m_swFilterPipeType = SwFilterPipeType0To1;
380     }
381 }
382 
Clean()383 MOS_STATUS SwFilterPipe::Clean()
384 {
385     VP_FUNC_CALL();
386 
387     // Do not unregister features in Clean, which will be reused until swFilterPipe being destroyed.
388     m_swFilterPipeType = SwFilterPipeTypeInvalid;
389 
390     CleanFeatures();
391 
392     std::vector<SwFilterSubPipe *> *pipes[] = {&m_InputPipes, &m_OutputPipes};
393     for (auto pipe : pipes)
394     {
395         while (!pipe->empty())
396         {
397             auto p = pipe->back();
398             MOS_Delete(p);
399             pipe->pop_back();
400         }
401     }
402 
403     std::vector<VP_SURFACE *> *surfacesArray[] = {&m_InputSurfaces, &m_OutputSurfaces, &m_pastSurface, &m_futureSurface};
404     for (auto surfaces : surfacesArray)
405     {
406         while (!surfaces->empty())
407         {
408             auto p = surfaces->back();
409             m_vpInterface.GetAllocator().DestroyVpSurface(p);
410             surfaces->pop_back();
411         }
412     }
413     m_linkedLayerIndex.clear();
414 
415     m_isExePipe = false;
416 
417     return MOS_STATUS_SUCCESS;
418 }
419 
IsEmpty()420 bool SwFilterPipe::IsEmpty()
421 {
422     VP_FUNC_CALL();
423 
424     for (auto pipe : m_InputPipes)
425     {
426         if (!pipe->IsEmpty())
427         {
428             return false;
429         }
430     }
431 
432     for (auto pipe : m_OutputPipes)
433     {
434         if (!pipe->IsEmpty())
435         {
436             return false;
437         }
438     }
439 
440     return true;
441 }
442 
IsPrimaryEmpty()443 bool SwFilterPipe::IsPrimaryEmpty()
444 {
445     VP_FUNC_CALL();
446 
447     uint32_t index;
448     auto pipe = GetSwFilterPrimaryPipe(index);
449 
450     if (pipe->IsEmpty())
451     {
452         return true;
453     }
454 
455     return false;
456 }
457 
ConfigFeaturesToPipe(VP_PIPELINE_PARAMS & params,FeatureRule & featureRule,bool isInputPipe)458 MOS_STATUS SwFilterPipe::ConfigFeaturesToPipe(VP_PIPELINE_PARAMS &params, FeatureRule &featureRule, bool isInputPipe)
459 {
460     VP_FUNC_CALL();
461 
462     std::vector<SwFilterSubPipe *>  &pipes = isInputPipe ? m_InputPipes : m_OutputPipes;
463     std::vector<FeatureSubRule>     &rulePipes = isInputPipe ? featureRule.m_InputPipes : featureRule.m_OutputPipes;
464     SwFilter *swFilter = nullptr;
465     // Loop all input surfaces.
466     for (uint32_t pipeIndex = 0; pipeIndex < pipes.size(); ++pipeIndex)
467     {
468         // Get a copy list for feature handler.
469         auto featureHander = *m_vpInterface.GetSwFilterHandlerMap();
470 
471         if (pipeIndex < rulePipes.size())
472         {
473             auto &featurePipe = rulePipes[pipeIndex];
474 
475             for (auto &featureSet : featurePipe.m_Rule)
476             {
477                 // Loop orderred feature set.
478                 bool useNewSwFilterSet = true;
479                 for (auto &feature : featureSet.m_Features)
480                 {
481                     // Loop all features in feature set.
482                     SwFilterFeatureHandler *handler = featureHander.find(feature)->second;
483                     VP_PUBLIC_CHK_NULL_RETURN(handler);
484                     VP_PUBLIC_CHK_STATUS_RETURN(handler->CreateSwFilter(swFilter, params, isInputPipe, pipeIndex, m_swFilterPipeType));
485                     if (swFilter)
486                     {
487                         VP_PUBLIC_CHK_STATUS_RETURN(AddSwFilterOrdered(swFilter, isInputPipe, pipeIndex, useNewSwFilterSet));
488                         featureHander.erase(feature);
489                         useNewSwFilterSet = false;
490                     }
491                     // nullptr == swFilter means no such feature in params, which is also the valid case.
492                 }
493             }
494         }
495 
496         // Process remaining unordered features
497         for (auto &handler : featureHander)
498         {
499             VP_PUBLIC_CHK_STATUS_RETURN(handler.second->CreateSwFilter(swFilter, params, isInputPipe, pipeIndex, m_swFilterPipeType));
500             if (swFilter)
501             {
502                 VP_PUBLIC_CHK_STATUS_RETURN(AddSwFilterUnordered(swFilter, isInputPipe, pipeIndex));
503                 MT_LOG4(MT_VP_HAL_SWWFILTER_ADD, MT_NORMAL, MT_VP_HAL_PIPE_ISINPUT, isInputPipe, MT_VP_HAL_PIPE_INDEX, pipeIndex,
504                     MT_VP_HAL_FEATUERTYPE, swFilter->GetFeatureType(), MT_VP_HAL_ENGINECAPS, int64_t(swFilter->GetFilterEngineCaps().value));
505             }
506         }
507     }
508 
509     return MOS_STATUS_SUCCESS;
510 }
511 
ConfigFeatures(VP_PIPELINE_PARAMS & params,FeatureRule & featureRule)512 MOS_STATUS SwFilterPipe::ConfigFeatures(VP_PIPELINE_PARAMS &params, FeatureRule &featureRule)
513 {
514     VP_FUNC_CALL();
515 
516     MOS_STATUS status1 = ConfigFeaturesToPipe(params, featureRule, true);
517     MOS_STATUS status2 = ConfigFeaturesToPipe(params, featureRule, false);
518 
519     // Return the status for the failure one.
520     return MOS_STATUS_SUCCESS == status1 ? status2 : status1;
521 }
522 
ConfigFeatures(VEBOX_SFC_PARAMS & params)523 MOS_STATUS SwFilterPipe::ConfigFeatures(VEBOX_SFC_PARAMS &params)
524 {
525     VP_FUNC_CALL();
526 
527     std::vector<SwFilterSubPipe *>  &pipes = m_InputPipes;
528 
529     SwFilter *swFilter = nullptr;
530     // Loop all input surfaces.
531     for (uint32_t pipeIndex = 0; pipeIndex < pipes.size(); ++pipeIndex)
532     {
533         auto featureHander = m_vpInterface.GetSwFilterHandlerMap();
534         // Process remaining unordered features
535         if (featureHander)
536         {
537             for (auto handler = featureHander->begin(); handler != featureHander->end(); handler++)
538             {
539                 VP_PUBLIC_CHK_STATUS_RETURN(handler->second->CreateSwFilter(swFilter, params));
540                 if (swFilter)
541                 {
542                     VP_PUBLIC_CHK_STATUS_RETURN(AddSwFilterUnordered(swFilter, true, 0));
543                 }
544             }
545         }
546         else
547         {
548             VP_PUBLIC_ASSERTMESSAGE("No VP Feature Manager Created");
549             return MOS_STATUS_UNIMPLEMENTED;
550         }
551     }
552 
553     return MOS_STATUS_SUCCESS;
554 }
555 
UpdateFeatures(bool isInputPipe,uint32_t pipeIndex,VP_EXECUTE_CAPS * caps)556 MOS_STATUS SwFilterPipe::UpdateFeatures(bool isInputPipe, uint32_t pipeIndex, VP_EXECUTE_CAPS *caps)
557 {
558     VP_FUNC_CALL();
559 
560     auto &pipes = isInputPipe ? m_InputPipes : m_OutputPipes;
561     auto &surfaces = isInputPipe ? m_InputSurfaces : m_OutputSurfaces;
562 
563     if (pipeIndex >= pipes.size() || pipeIndex >= surfaces.size() || 0 == m_OutputPipes.size() ||
564         m_InputPipes.size() != m_InputSurfaces.size() || m_OutputPipes.size() != m_OutputSurfaces.size())
565     {
566         return MOS_STATUS_INVALID_PARAMETER;
567     }
568 
569     // Always use index 0 for the pipe whose pipeIndex not being specified.
570     auto inputPipe = isInputPipe ? m_InputPipes[pipeIndex] : (m_InputPipes.size() > 0 ? m_InputPipes[0] : nullptr);
571     auto outputPipe = isInputPipe ? m_OutputPipes[0] : m_OutputPipes[pipeIndex];
572 
573     auto inputSurf = isInputPipe ? m_InputSurfaces[pipeIndex] : (m_InputSurfaces.size() > 0 ? m_InputSurfaces[0] : nullptr);
574     auto outputSurf = isInputPipe ? m_OutputSurfaces[0] : m_OutputSurfaces[pipeIndex];
575 
576     if (nullptr == outputPipe || nullptr == outputSurf)
577     {
578         return MOS_STATUS_INVALID_PARAMETER;
579     }
580 
581     // Input surface/pipe may be empty for some feature.
582     if (inputPipe)
583     {
584         if (caps && caps->bComposite)
585         {
586             // Always keep csc filter in fc pipe. The csc filter for multi-pass intermediate surface case will be added here.
587             if (nullptr == inputPipe->GetSwFilter(FeatureTypeCsc))
588             {
589                 auto handler = m_vpInterface.GetSwFilterHandler(FeatureTypeCsc);
590                 VP_PUBLIC_CHK_NULL_RETURN(handler);
591                 SwFilterCsc* swfilter = dynamic_cast<SwFilterCsc *>(handler->CreateSwFilter());
592                 VP_PUBLIC_CHK_NULL_RETURN(swfilter);
593                 swfilter->Configure(inputSurf, outputSurf, *caps);
594                 inputPipe->AddSwFilterUnordered(swfilter);
595             }
596         }
597 
598         VP_PUBLIC_CHK_STATUS_RETURN(inputPipe->Update(inputSurf, outputSurf));
599     }
600 
601     VP_PUBLIC_CHK_STATUS_RETURN(outputPipe->Update(inputSurf, outputSurf));
602 
603     return MOS_STATUS_SUCCESS;
604 }
605 
CleanFeaturesFromPipe(bool isInputPipe,uint32_t index)606 MOS_STATUS SwFilterPipe::CleanFeaturesFromPipe(bool isInputPipe, uint32_t index)
607 {
608     VP_FUNC_CALL();
609 
610     MOS_STATUS status = MOS_STATUS_SUCCESS;
611     std::vector<SwFilterSubPipe *>  &pipes = isInputPipe ? m_InputPipes : m_OutputPipes;
612 
613     if (index < pipes.size() && pipes[index])
614     {
615         return pipes[index]->Clean();
616     }
617 
618     return MOS_STATUS_INVALID_PARAMETER;
619 }
620 
CleanFeaturesFromPipe(bool isInputPipe)621 MOS_STATUS SwFilterPipe::CleanFeaturesFromPipe(bool isInputPipe)
622 {
623     VP_FUNC_CALL();
624 
625     MOS_STATUS status = MOS_STATUS_SUCCESS;
626     std::vector<SwFilterSubPipe *>  &pipes = isInputPipe ? m_InputPipes : m_OutputPipes;
627     for (uint32_t pipeIndex = 0; pipeIndex < pipes.size(); ++pipeIndex)
628     {
629         MOS_STATUS tmpStat = CleanFeaturesFromPipe(isInputPipe, pipeIndex);
630         if (MOS_FAILED(tmpStat))
631         {
632             VP_PUBLIC_ASSERTMESSAGE("CleanFeaturesFromPipe failed for pipe %d with status = %08x.", pipeIndex, tmpStat);
633             // Always record first failure.
634             status = MOS_FAILED(status) ? status : tmpStat;
635         }
636     }
637 
638     // Do not clear pipe here since it should align with m_InputSurfaces/m_OutputSurfaces.
639 
640     return status;
641 }
642 
CleanFeatures()643 MOS_STATUS SwFilterPipe::CleanFeatures()
644 {
645     VP_FUNC_CALL();
646 
647     MOS_STATUS status1 = CleanFeaturesFromPipe(true);
648     MOS_STATUS status2 = CleanFeaturesFromPipe(false);
649 
650     // Return the status for the failure one.
651     return MOS_STATUS_SUCCESS == status1 ? status2 : status1;
652 }
653 
GetSwFilter(bool isInputPipe,int index,FeatureType type)654 SwFilter *SwFilterPipe::GetSwFilter(bool isInputPipe, int index, FeatureType type)
655 {
656     VP_FUNC_CALL();
657 
658     SwFilterSubPipe * pipe = GetSwFilterSubPipe(isInputPipe, index);
659     if (nullptr == pipe)
660     {
661         // May come here for ClearView case.
662         VP_PUBLIC_NORMALMESSAGE("Invalid parameter! No sub pipe exists!");
663         return nullptr;
664     }
665 
666     return pipe->GetSwFilter(type);
667 }
668 
GetSwFilterSubPipe(bool isInputPipe,int index)669 SwFilterSubPipe* SwFilterPipe::GetSwFilterSubPipe(bool isInputPipe, int index)
670 {
671     VP_FUNC_CALL();
672 
673     SwFilterSubPipe* pSubPipe = nullptr;
674     auto& pipes = isInputPipe ? m_InputPipes : m_OutputPipes;
675 
676     if ((uint32_t)index < pipes.size())
677     {
678         pSubPipe = pipes[index];
679     }
680     return pSubPipe;
681 }
682 
GetSwFilterPrimaryPipe(uint32_t & index)683 SwFilterSubPipe* SwFilterPipe::GetSwFilterPrimaryPipe(uint32_t& index)
684 {
685     VP_FUNC_CALL();
686 
687     SwFilterSubPipe* pSubPipe = nullptr;
688 
689     index = 0;
690 
691     if (m_InputPipes.size() == 0)
692     {
693         return nullptr;
694     }
695 
696     for (auto item : m_InputSurfaces)
697     {
698 
699         if (item->SurfType == SURF_IN_PRIMARY)
700         {
701             pSubPipe = m_InputPipes[index];
702             return pSubPipe;
703         }
704         ++index;
705     }
706     return pSubPipe;
707 }
708 
709 // useNewSwFilterSet: true if insert new swFilterSet in pipe, otherwise, reuse the last one in pipe.
AddSwFilterOrdered(SwFilter * swFilter,bool isInputPipe,int index,bool useNewSwFilterSet)710 MOS_STATUS SwFilterPipe::AddSwFilterOrdered(SwFilter *swFilter, bool isInputPipe, int index, bool useNewSwFilterSet)
711 {
712     VP_FUNC_CALL();
713 
714     VP_PUBLIC_CHK_NULL_RETURN(swFilter);
715 
716     SwFilterSubPipe *pSubPipe = GetSwFilterSubPipe(isInputPipe, index);
717     VP_PUBLIC_CHK_NULL_RETURN(pSubPipe);
718 
719     VP_PUBLIC_CHK_STATUS_RETURN(pSubPipe->AddSwFilterOrdered(swFilter, useNewSwFilterSet));
720     swFilter->SetExePipeFlag(m_isExePipe);
721 
722     return MOS_STATUS_SUCCESS;
723 }
724 
AddSwFilterUnordered(SwFilter * swFilter,bool isInputPipe,int index)725 MOS_STATUS SwFilterPipe::AddSwFilterUnordered(SwFilter *swFilter, bool isInputPipe, int index)
726 {
727     VP_FUNC_CALL();
728 
729     VP_PUBLIC_CHK_NULL_RETURN(swFilter);
730 
731     SwFilterSubPipe *pSubPipe = GetSwFilterSubPipe(isInputPipe, index);
732 
733     if (nullptr == pSubPipe && !isInputPipe)
734     {
735         auto& pipes = m_OutputPipes;
736         SwFilterSubPipe *pipe = MOS_New(SwFilterSubPipe);
737         VP_PUBLIC_CHK_NULL_RETURN(pipe);
738         if ((size_t)index <= pipes.size())
739         {
740             for (int32_t i = (int)pipes.size(); i <= index; ++i)
741             {
742                 pipes.push_back(nullptr);
743             }
744         }
745         pipes[index] = pipe;
746         pSubPipe = GetSwFilterSubPipe(isInputPipe, index);
747     }
748 
749     VP_PUBLIC_CHK_NULL_RETURN(pSubPipe);
750 
751     VP_PUBLIC_CHK_STATUS_RETURN(pSubPipe->AddSwFilterUnordered(swFilter));
752     swFilter->SetExePipeFlag(m_isExePipe);
753 
754     return MOS_STATUS_SUCCESS;
755 }
756 
RemoveSwFilter(SwFilter * swFilter)757 MOS_STATUS SwFilterPipe::RemoveSwFilter(SwFilter *swFilter)
758 {
759     VP_FUNC_CALL();
760 
761     VP_PUBLIC_CHK_NULL_RETURN(swFilter);
762 
763     SwFilterSet *swFilterSet = swFilter->GetLocation();
764     VP_PUBLIC_CHK_NULL_RETURN(swFilterSet);
765 
766     VP_PUBLIC_CHK_STATUS_RETURN(swFilterSet->RemoveSwFilter(swFilter));
767 
768     // Delete swFilterSet if needed.
769     auto pipe = swFilterSet->GetLocation();
770     if (pipe && swFilterSet->IsEmpty())
771     {
772         for (auto it = pipe->begin(); it != pipe->end(); ++it)
773         {
774             if (*it == swFilterSet)
775             {
776                 pipe->erase(it);
777                 break;
778             }
779         }
780         swFilterSet->SetLocation(nullptr);
781 
782         MOS_Delete(swFilterSet);
783     }
784     return MOS_STATUS_SUCCESS;
785 }
786 
GetSurface(bool isInputSurface,uint32_t index)787 VP_SURFACE *SwFilterPipe::GetSurface(bool isInputSurface, uint32_t index)
788 {
789     VP_FUNC_CALL();
790 
791     if (isInputSurface)
792     {
793         return index < m_InputSurfaces.size() ? m_InputSurfaces[index] : nullptr;
794     }
795     else
796     {
797         return index < m_OutputSurfaces.size() ? m_OutputSurfaces[index] : nullptr;
798     }
799 }
800 
GetPastSurface(uint32_t index)801 VP_SURFACE *SwFilterPipe::GetPastSurface(uint32_t index)
802 {
803     VP_FUNC_CALL();
804 
805     return index < m_pastSurface.size() ? m_pastSurface[index] : nullptr;
806 }
807 
GetFutureSurface(uint32_t index)808 VP_SURFACE *SwFilterPipe::GetFutureSurface(uint32_t index)
809 {
810     VP_FUNC_CALL();
811 
812     return index < m_futureSurface.size() ? m_futureSurface[index] : nullptr;
813 }
814 
SetPastSurface(uint32_t index,VP_SURFACE * surf)815 MOS_STATUS SwFilterPipe::SetPastSurface(uint32_t index, VP_SURFACE *surf)
816 {
817     VP_FUNC_CALL();
818 
819     if (index >= m_pastSurface.size())
820     {
821         return MOS_STATUS_INVALID_PARAMETER;
822     }
823     m_pastSurface[index] = surf;
824     return MOS_STATUS_SUCCESS;
825 }
826 
SetFutureSurface(uint32_t index,VP_SURFACE * surf)827 MOS_STATUS SwFilterPipe::SetFutureSurface(uint32_t index, VP_SURFACE *surf)
828 {
829     VP_FUNC_CALL();
830 
831     if (index >= m_futureSurface.size())
832     {
833         return MOS_STATUS_INVALID_PARAMETER;
834     }
835     m_futureSurface[index] = surf;
836     return MOS_STATUS_SUCCESS;
837 }
838 
RemovePastSurface(uint32_t index)839 VP_SURFACE *SwFilterPipe::RemovePastSurface(uint32_t index)
840 {
841     VP_FUNC_CALL();
842 
843     if (index >= m_pastSurface.size())
844     {
845         return nullptr;
846     }
847     VP_SURFACE *surf = m_pastSurface[index];
848     m_pastSurface[index] = nullptr;
849     return surf;
850 }
851 
RemoveFutureSurface(uint32_t index)852 VP_SURFACE *SwFilterPipe::RemoveFutureSurface(uint32_t index)
853 {
854     VP_FUNC_CALL();
855 
856     if (index >= m_futureSurface.size())
857     {
858         return nullptr;
859     }
860     VP_SURFACE *surf = m_futureSurface[index];
861     m_futureSurface[index] = nullptr;
862     return surf;
863 }
864 
DestroySurface(bool isInputSurface,uint32_t index)865 MOS_STATUS SwFilterPipe::DestroySurface(bool isInputSurface, uint32_t index)
866 {
867     VP_SURFACE *surf = SwFilterPipe::RemoveSurface(isInputSurface, index);
868     VP_PUBLIC_CHK_NULL_RETURN(surf);
869     m_vpInterface.GetAllocator().DestroyVpSurface(surf);
870     return MOS_STATUS_SUCCESS;
871 }
872 
RemoveSurface(bool isInputSurface,uint32_t index)873 VP_SURFACE *SwFilterPipe::RemoveSurface(bool isInputSurface, uint32_t index)
874 {
875     VP_FUNC_CALL();
876 
877     auto &surfaces = isInputSurface ? m_InputSurfaces : m_OutputSurfaces;
878 
879     if (index < surfaces.size())
880     {
881         VP_SURFACE *surf = surfaces[index];
882         surfaces[index] = nullptr;
883 
884         if (isInputSurface)
885         {
886             // Keep m_pastSurface and m_futureSurface same status as m_InputSurfaces.
887             if (m_pastSurface[index])
888             {
889                 m_vpInterface.GetAllocator().DestroyVpSurface(m_pastSurface[index]);
890             }
891             if (m_futureSurface[index])
892             {
893                 m_vpInterface.GetAllocator().DestroyVpSurface(m_futureSurface[index]);
894             }
895             if (m_linkedLayerIndex[index])
896             {
897                 m_linkedLayerIndex[index] = 0;
898             }
899         }
900 
901         return surf;
902     }
903     return nullptr;
904 }
905 
ReplaceSurface(VP_SURFACE * surf,bool isInputSurface,uint32_t index)906 VP_SURFACE *SwFilterPipe::ReplaceSurface(VP_SURFACE *surf, bool isInputSurface, uint32_t index)
907 {
908     VP_FUNC_CALL();
909 
910     auto &surfaces = isInputSurface ? m_InputSurfaces : m_OutputSurfaces;
911 
912     if (index < surfaces.size())
913     {
914         VP_SURFACE *ret = surfaces[index];
915         surfaces[index] = surf;
916         return ret;
917     }
918     return nullptr;
919 }
920 
AddSurface(VP_SURFACE * & surf,bool isInputSurface,uint32_t index)921 MOS_STATUS SwFilterPipe::AddSurface(VP_SURFACE *&surf, bool isInputSurface, uint32_t index)
922 {
923     VP_FUNC_CALL();
924 
925     auto &surfaces = isInputSurface ? m_InputSurfaces : m_OutputSurfaces;
926     auto &pipes = isInputSurface ? m_InputPipes : m_OutputPipes;
927 
928     for (uint32_t i = surfaces.size(); i <= index; ++i)
929     {
930         surfaces.push_back(nullptr);
931         if (isInputSurface)
932         {
933             // Keep m_PastSurface same size as m_InputSurfaces.
934             m_pastSurface.push_back(nullptr);
935             m_futureSurface.push_back(nullptr);
936             m_linkedLayerIndex.push_back(0);
937         }
938     }
939 
940     if (index >= surfaces.size())
941     {
942         return MOS_STATUS_INVALID_PARAMETER;
943     }
944 
945     if (nullptr != surfaces[index])
946     {
947         return MOS_STATUS_INVALID_PARAMETER;
948     }
949 
950     for (uint32_t i = pipes.size(); i <= index; ++i)
951     {
952         pipes.push_back(nullptr);
953     }
954 
955     if (index >= surfaces.size())
956     {
957         return MOS_STATUS_INVALID_PARAMETER;
958     }
959 
960     if (nullptr == pipes[index])
961     {
962         SwFilterSubPipe *pipe = MOS_New(SwFilterSubPipe);
963         VP_PUBLIC_CHK_NULL_RETURN(pipe);
964         pipes[index] = pipe;
965     }
966 
967     surfaces[index] = surf;
968     return MOS_STATUS_SUCCESS;
969 }
970 
971 template<class T>
RemoveUnusedLayers(std::vector<uint32_t> & indexForRemove,std::vector<T> & layers)972 MOS_STATUS RemoveUnusedLayers(std::vector<uint32_t> &indexForRemove, std::vector<T> &layers)
973 {
974     VP_FUNC_CALL();
975 
976     if (indexForRemove.size() == 0)
977     {
978         return MOS_STATUS_SUCCESS;
979     }
980 
981     if (sizeof(T) < sizeof(int))
982     {
983         VP_PUBLIC_CHK_STATUS_RETURN(MOS_STATUS_INVALID_PARAMETER);
984     }
985     const int keyForDelete = 0xabcdabcd;
986     for (uint32_t index : indexForRemove)
987     {
988         if (index >= layers.size())
989         {
990             VP_PUBLIC_CHK_STATUS_RETURN(MOS_STATUS_INVALID_PARAMETER);
991         }
992         // Mark the items to be removed.
993         *(int *)&layers[index] = keyForDelete;
994     }
995 
996     for (auto it = layers.begin(); it != layers.end();)
997     {
998         if (keyForDelete == *(int *)&(*it))
999         {
1000             it = layers.erase(it);
1001         }
1002         else
1003         {
1004             ++it;
1005         }
1006     }
1007 
1008     return MOS_STATUS_SUCCESS;
1009 }
1010 
1011 template<class T>
RemoveUnusedLayers(std::vector<uint32_t> & indexForRemove,std::vector<T * > & layers,bool freeObj)1012 MOS_STATUS RemoveUnusedLayers(std::vector<uint32_t> &indexForRemove, std::vector<T*> &layers, bool freeObj)
1013 {
1014     VP_FUNC_CALL();
1015 
1016     if (indexForRemove.size() == 0)
1017     {
1018         return MOS_STATUS_SUCCESS;
1019     }
1020 
1021     if (freeObj)
1022     {
1023         std::map<T*, T*> objForRemove;
1024         for (uint32_t index : indexForRemove)
1025         {
1026             if (index >= layers.size())
1027             {
1028                 VP_PUBLIC_CHK_STATUS_RETURN(MOS_STATUS_INVALID_PARAMETER);
1029             }
1030             objForRemove.insert(std::make_pair(layers[index], layers[index]));
1031             layers[index] = nullptr;
1032         }
1033         for (auto it : objForRemove)
1034         {
1035             MOS_Delete(it.second);
1036         }
1037     }
1038 
1039     return RemoveUnusedLayers(indexForRemove, layers);
1040 }
1041 
RemoveUnusedLayers(bool bUpdateInput)1042 MOS_STATUS SwFilterPipe::RemoveUnusedLayers(bool bUpdateInput)
1043 {
1044     VP_FUNC_CALL();
1045 
1046     // If bUpdateInput == true, surfaces1 is input layers, which will be updated, and surfaces2 is output layers,
1047     // otherwise, surfaces1 is output layers, which will be updated, and surfaces2 is input layers.
1048     auto &surfaces1 = bUpdateInput ? m_InputSurfaces : m_OutputSurfaces;
1049     auto &surfaces2 = !bUpdateInput ? m_InputSurfaces : m_OutputSurfaces;
1050     auto &pipes = bUpdateInput ? m_InputPipes : m_OutputPipes;
1051 
1052     std::vector<uint32_t> indexForRemove;
1053     uint32_t i = 0;
1054     bool isInputNullValid = (!bUpdateInput && pipes.size()>0 && !pipes[0]->IsEmpty());
1055 
1056     for (i = 0; i < surfaces1.size(); ++i)
1057     {
1058         if (nullptr == surfaces1[i] || (!isInputNullValid && 0 == surfaces2.size()) ||
1059             1 == surfaces2.size() && nullptr == surfaces2[0])
1060         {
1061             indexForRemove.push_back(i);
1062             CleanFeaturesFromPipe(bUpdateInput, i);
1063         }
1064     }
1065 
1066     VP_PUBLIC_CHK_STATUS_RETURN(::RemoveUnusedLayers(indexForRemove, surfaces1, false));
1067     if (bUpdateInput)
1068     {
1069         // Keep m_pastSurface same size as m_InputSurfaces.
1070         VP_PUBLIC_CHK_STATUS_RETURN(::RemoveUnusedLayers(indexForRemove, m_pastSurface, false));
1071         // Keep m_futureSurface same size as m_InputSurfaces.
1072         VP_PUBLIC_CHK_STATUS_RETURN(::RemoveUnusedLayers(indexForRemove, m_futureSurface, false));
1073         // Keep m_linkedLayerIndex same size as m_InputSurfaces.
1074         VP_PUBLIC_CHK_STATUS_RETURN(::RemoveUnusedLayers(indexForRemove, m_linkedLayerIndex));
1075     }
1076 
1077     VP_PUBLIC_CHK_STATUS_RETURN(::RemoveUnusedLayers(indexForRemove, pipes, true));
1078 
1079     return MOS_STATUS_SUCCESS;
1080 }
1081 
Update(VP_EXECUTE_CAPS * caps)1082 MOS_STATUS SwFilterPipe::Update(VP_EXECUTE_CAPS *caps)
1083 {
1084     VP_FUNC_CALL();
1085 
1086     uint32_t i = 0;
1087 
1088     VP_PUBLIC_CHK_STATUS_RETURN(RemoveUnusedLayers(true));
1089     VP_PUBLIC_CHK_STATUS_RETURN(RemoveUnusedLayers(false));
1090 
1091     for (i = 0; i < m_InputPipes.size(); ++i)
1092     {
1093         VP_PUBLIC_CHK_STATUS_RETURN(UpdateFeatures(true, i, caps));
1094     }
1095 
1096     for (i = 0; i < m_OutputPipes.size(); ++i)
1097     {
1098         VP_PUBLIC_CHK_STATUS_RETURN(UpdateFeatures(false, i));
1099     }
1100 
1101     UpdateSwFilterPipeType();
1102 
1103     return MOS_STATUS_SUCCESS;
1104 }
1105 
GetSurfaceCount(bool isInputSurface)1106 uint32_t SwFilterPipe::GetSurfaceCount(bool isInputSurface)
1107 {
1108     VP_FUNC_CALL();
1109 
1110     return isInputSurface ? m_InputSurfaces.size() : m_OutputSurfaces.size();
1111 }
1112 
IsAllInputPipeEmpty()1113 bool SwFilterPipe::IsAllInputPipeEmpty()
1114 {
1115     for (uint32_t i = 0; i < GetSurfaceCount(true); ++i)
1116     {
1117         SwFilterSubPipe *inputPipe = GetSwFilterSubPipe(true, i);
1118         if (inputPipe && !inputPipe->IsEmpty())
1119         {
1120             return false;
1121         }
1122     }
1123 
1124     return true;
1125 }
1126 
IsAllInputPipeSurfaceFeatureEmpty()1127 bool SwFilterPipe::IsAllInputPipeSurfaceFeatureEmpty()
1128 {
1129     for (uint32_t i = 0; i < GetSurfaceCount(true); ++i)
1130     {
1131         SwFilterSubPipe *inputPipe = GetSwFilterSubPipe(true, i);
1132         if (inputPipe && !inputPipe->IsSurfaceFeatureEmpty())
1133         {
1134             return false;
1135         }
1136     }
1137 
1138     return true;
1139 }
1140 
IsAllInputPipeSurfaceFeatureEmpty(std::vector<int> & layerIndexes)1141 bool SwFilterPipe::IsAllInputPipeSurfaceFeatureEmpty(std::vector<int> &layerIndexes)
1142 {
1143     for (uint32_t i = 0; i < layerIndexes.size(); ++i)
1144     {
1145         uint32_t executedIndex = layerIndexes[i];
1146         SwFilterSubPipe *inputPipe = GetSwFilterSubPipe(true, executedIndex);
1147         if (inputPipe && !inputPipe->IsSurfaceFeatureEmpty())
1148         {
1149             return false;
1150         }
1151     }
1152 
1153     return true;
1154 }
1155 
AddRTLog()1156 MOS_STATUS SwFilterPipe::AddRTLog()
1157 {
1158     VP_FUNC_CALL();
1159 
1160     uint32_t i = 0;
1161     MT_LOG1(MT_VP_FEATURE_GRAPH_GET_RENDERTARGETTYPE, MT_NORMAL, MT_VP_FEATURE_GRAPH_RENDERTARGETTYPE, GetRenderTargetType())
1162     MT_LOG1(MT_VP_FEATURE_GRAPH_INPUTSWFILTER, MT_NORMAL, MT_VP_FEATURE_GRAPH_FILTER_SWFILTERPIPE_COUNT, (int64_t)m_InputPipes.size());
1163     for (i = 0; i < m_InputPipes.size(); ++i)
1164     {
1165         VP_PUBLIC_CHK_STATUS_RETURN(AddFeatureGraphRTLog(true, i));
1166     }
1167     MT_LOG1(MT_VP_FEATURE_GRAPH_OUTPUTSWFILTER, MT_NORMAL, MT_VP_FEATURE_GRAPH_FILTER_SWFILTERPIPE_COUNT, (int64_t)m_OutputPipes.size());
1168     for (i = 0; i < m_OutputPipes.size(); ++i)
1169     {
1170         VP_PUBLIC_CHK_STATUS_RETURN(AddFeatureGraphRTLog(false, i));
1171     }
1172 
1173     return MOS_STATUS_SUCCESS;
1174 }
1175 
AddFeatureGraphRTLog(bool isInputPipe,uint32_t pipeIndex)1176 MOS_STATUS SwFilterPipe::AddFeatureGraphRTLog(bool isInputPipe, uint32_t pipeIndex)
1177 {
1178     VP_FUNC_CALL();
1179 
1180     // Always use index 0 for the pipe whose pipeIndex not being specified.
1181     auto inputPipe  = m_InputPipes.size() > 0 ? (isInputPipe ? m_InputPipes[pipeIndex] : m_InputPipes[0]) : nullptr;
1182     auto outputPipe = m_OutputPipes.size() > 0 ? (isInputPipe ? m_OutputPipes[0] : m_OutputPipes[pipeIndex]) : nullptr;
1183 
1184     // Input surface/pipe may be empty for some feature.
1185     if (isInputPipe)
1186     {
1187         MT_LOG7(MT_VP_FEATURE_GRAPH_INPUT_SURFACE_INFO, MT_NORMAL, MT_VP_FEATURE_GRAPH_SURFACE_WIDTH, m_InputSurfaces[pipeIndex]->osSurface->dwWidth, MT_VP_FEATURE_GRAPH_SURFACE_HEIGHT, m_InputSurfaces[pipeIndex]->osSurface->dwHeight, MT_VP_FEATURE_GRAPH_SURFACE_PITCH, m_InputSurfaces[pipeIndex]->osSurface->dwPitch, MT_VP_FEATURE_GRAPH_SURFACE_RCSRC_LEFT, m_InputSurfaces[pipeIndex]->rcSrc.left, MT_VP_FEATURE_GRAPH_SURFACE_RCSRC_TOP, m_InputSurfaces[pipeIndex]->rcSrc.top, MT_VP_FEATURE_GRAPH_SURFACE_RCSRC_RIGHT, m_InputSurfaces[pipeIndex]->rcSrc.right, MT_VP_FEATURE_GRAPH_SURFACE_RCSRC_BOTTOM, m_InputSurfaces[pipeIndex]->rcSrc.bottom);
1188         MT_LOG7(MT_VP_FEATURE_GRAPH_INPUT_SURFACE_INFO, MT_NORMAL, MT_VP_FEATURE_GRAPH_SURFACE_COLORSPACE, m_InputSurfaces[pipeIndex]->ColorSpace, MT_VP_FEATURE_GRAPH_SURFACE_FORMAT, m_InputSurfaces[pipeIndex]->osSurface->Format, MT_VP_FEATURE_GRAPH_SURFACE_RCDST_LEFT, m_InputSurfaces[pipeIndex]->rcDst.left, MT_VP_FEATURE_GRAPH_SURFACE_RCDST_TOP, m_InputSurfaces[pipeIndex]->rcDst.top, MT_VP_FEATURE_GRAPH_SURFACE_RCDST_RIGHT, m_InputSurfaces[pipeIndex]->rcDst.right, MT_VP_FEATURE_GRAPH_SURFACE_RCDST_BOTTOM, m_InputSurfaces[pipeIndex]->rcDst.bottom, MT_VP_FEATURE_GRAPH_SURFACE_ALLOCATIONHANDLE, static_cast<int64_t>(m_InputSurfaces[pipeIndex]->GetAllocationHandle(m_vpInterface.GetHwInterface()->m_osInterface)));
1189         VP_PUBLIC_NORMALMESSAGE(
1190             "Feature Graph: Input Surface: dwWidth %d, dwHeight %d, dwPitch %d, ColorSpace %d, Format %d, \
1191             rcSrc.left %d, rcSrc.top %d, rcSrc.right %d, rcSrc.bottom %d, \
1192             rcDst.left %d, rcDst.top %d, rcDst.right %d, rcDst.bottom %d, surface allocationhandle %d",
1193             m_InputSurfaces[pipeIndex]->osSurface->dwWidth,
1194             m_InputSurfaces[pipeIndex]->osSurface->dwHeight,
1195             m_InputSurfaces[pipeIndex]->osSurface->dwPitch,
1196             m_InputSurfaces[pipeIndex]->ColorSpace,
1197             m_InputSurfaces[pipeIndex]->osSurface->Format,
1198             m_InputSurfaces[pipeIndex]->rcSrc.left,
1199             m_InputSurfaces[pipeIndex]->rcSrc.top,
1200             m_InputSurfaces[pipeIndex]->rcSrc.right,
1201             m_InputSurfaces[pipeIndex]->rcSrc.bottom,
1202             m_InputSurfaces[pipeIndex]->rcDst.left,
1203             m_InputSurfaces[pipeIndex]->rcDst.top,
1204             m_InputSurfaces[pipeIndex]->rcDst.right,
1205             m_InputSurfaces[pipeIndex]->rcDst.bottom,
1206             m_InputSurfaces[pipeIndex]->GetAllocationHandle(m_vpInterface.GetHwInterface()->m_osInterface));
1207         VP_PUBLIC_CHK_STATUS_RETURN(inputPipe->AddFeatureGraphRTLog());
1208     }
1209     else
1210     {
1211         MT_LOG7(MT_VP_FEATURE_GRAPH_OUTPUT_SURFACE_INFO, MT_NORMAL, MT_VP_FEATURE_GRAPH_SURFACE_WIDTH, m_OutputSurfaces[pipeIndex]->osSurface->dwWidth, MT_VP_FEATURE_GRAPH_SURFACE_HEIGHT, m_OutputSurfaces[pipeIndex]->osSurface->dwHeight, MT_VP_FEATURE_GRAPH_SURFACE_PITCH, m_OutputSurfaces[pipeIndex]->osSurface->dwPitch, MT_VP_FEATURE_GRAPH_SURFACE_RCSRC_LEFT, m_OutputSurfaces[pipeIndex]->rcSrc.left, MT_VP_FEATURE_GRAPH_SURFACE_RCSRC_TOP, m_OutputSurfaces[pipeIndex]->rcSrc.top, MT_VP_FEATURE_GRAPH_SURFACE_RCSRC_RIGHT, m_OutputSurfaces[pipeIndex]->rcSrc.right, MT_VP_FEATURE_GRAPH_SURFACE_RCSRC_BOTTOM, m_OutputSurfaces[pipeIndex]->rcSrc.bottom);
1212         MT_LOG7(MT_VP_FEATURE_GRAPH_OUTPUT_SURFACE_INFO, MT_NORMAL, MT_VP_FEATURE_GRAPH_SURFACE_COLORSPACE, m_OutputSurfaces[pipeIndex]->ColorSpace, MT_VP_FEATURE_GRAPH_SURFACE_FORMAT, m_OutputSurfaces[pipeIndex]->osSurface->Format, MT_VP_FEATURE_GRAPH_SURFACE_RCDST_LEFT, m_OutputSurfaces[pipeIndex]->rcDst.left, MT_VP_FEATURE_GRAPH_SURFACE_RCDST_TOP, m_OutputSurfaces[pipeIndex]->rcDst.top, MT_VP_FEATURE_GRAPH_SURFACE_RCDST_RIGHT, m_OutputSurfaces[pipeIndex]->rcDst.right, MT_VP_FEATURE_GRAPH_SURFACE_RCDST_BOTTOM, m_OutputSurfaces[pipeIndex]->rcDst.bottom, MT_VP_FEATURE_GRAPH_SURFACE_ALLOCATIONHANDLE, static_cast<int64_t>(m_OutputSurfaces[pipeIndex]->GetAllocationHandle(m_vpInterface.GetHwInterface()->m_osInterface)));
1213         VP_PUBLIC_NORMALMESSAGE(
1214             "Feature Graph: Output Surface: dwWidth %d, dwHeight %d, dwPitch %d, ColorSpace %d, Format %d, \
1215             rcSrc.left %d, rcSrc.top %d, rcSrc.right %d, rcSrc.bottom %d, \
1216             rcDst.left %d, rcDst.top %d, rcDst.right %d, rcDst.bottom %d, surface allocationhandle %d",
1217             m_OutputSurfaces[pipeIndex]->osSurface->dwWidth,
1218             m_OutputSurfaces[pipeIndex]->osSurface->dwHeight,
1219             m_OutputSurfaces[pipeIndex]->osSurface->dwPitch,
1220             m_OutputSurfaces[pipeIndex]->ColorSpace,
1221             m_OutputSurfaces[pipeIndex]->osSurface->Format,
1222             m_OutputSurfaces[pipeIndex]->rcSrc.left,
1223             m_OutputSurfaces[pipeIndex]->rcSrc.top,
1224             m_OutputSurfaces[pipeIndex]->rcSrc.right,
1225             m_OutputSurfaces[pipeIndex]->rcSrc.bottom,
1226             m_OutputSurfaces[pipeIndex]->rcDst.left,
1227             m_OutputSurfaces[pipeIndex]->rcDst.top,
1228             m_OutputSurfaces[pipeIndex]->rcDst.right,
1229             m_OutputSurfaces[pipeIndex]->rcDst.bottom,
1230             m_OutputSurfaces[pipeIndex]->GetAllocationHandle(m_vpInterface.GetHwInterface()->m_osInterface));
1231         VP_PUBLIC_CHK_STATUS_RETURN(outputPipe->AddFeatureGraphRTLog());
1232     }
1233 
1234     return MOS_STATUS_SUCCESS;
1235 }
1236