1 /*
2 * Copyright (c) 2018-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 //! \file     encode_buffer_allocator.cpp
24 //! \brief    Defines the interface for buffer allocator
25 //! \details  The allocator manages the buffers with the same type and alloc parameter
26 //!
27 #include "encode_tracked_buffer_queue.h"
28 #include <algorithm>
29 #include "encode_allocator.h"
30 #include "encode_utils.h"
31 #include "mos_os_hw.h"
32 #include "mos_os_specific.h"
33 #include "mos_utilities.h"
34 
35 namespace encode {
36 
BufferQueue(EncodeAllocator * allocator,MOS_ALLOC_GFXRES_PARAMS & param,uint32_t maxCount)37 BufferQueue::BufferQueue(EncodeAllocator *allocator, MOS_ALLOC_GFXRES_PARAMS &param, uint32_t maxCount)
38     : m_maxCount(maxCount),
39       m_allocator(allocator),
40       m_allocParam(param)
41 {
42     m_mutex = MosUtilities::MosCreateMutex();
43 }
44 
~BufferQueue()45 BufferQueue::~BufferQueue()
46 {
47     for (auto resource : m_resources)
48     {
49         DestoryResource(resource);
50     }
51 
52     MosUtilities::MosDestroyMutex(m_mutex);
53 }
54 
AcquireResource()55 void *BufferQueue::AcquireResource()
56 {
57     AutoLock lock(m_mutex);
58 
59     if (m_resourcePool.empty())
60     {
61         if (m_allocCount > m_maxCount)
62         {
63             ENCODE_VERBOSEMESSAGE("Reach max resource count, cannot allocate more");
64             return nullptr;
65         }
66 
67         void *resource = AllocateResource();
68         if (resource != nullptr)
69         {
70             m_allocCount++;
71             m_resources.push_back(resource);
72         }
73         return resource;
74     }
75     else
76     {
77         void *resource = m_resourcePool.back();
78         m_resourcePool.pop_back();
79         return resource;
80     }
81 }
82 
ReleaseResource(void * resource)83 MOS_STATUS BufferQueue::ReleaseResource(void *resource)
84 {
85     AutoLock lock(m_mutex);
86 
87     if (nullptr != resource)
88     {
89         if (std::find(m_resources.begin(), m_resources.end(), resource) == m_resources.end())
90         {
91             // resource not belong to this allocator
92             ENCODE_VERBOSEMESSAGE("resource not belonged to current allocator");
93             return MOS_STATUS_INVALID_PARAMETER;
94         }
95         if (std::find(m_resourcePool.begin(), m_resourcePool.end(), resource) != m_resourcePool.end())
96         {
97             // resource already released
98             ENCODE_VERBOSEMESSAGE("resource already returned");
99             return MOS_STATUS_INVALID_PARAMETER;
100         }
101         m_resourcePool.push_back(resource);
102     }
103     return MOS_STATUS_SUCCESS;
104 }
105 
SafeToDestory()106 bool BufferQueue::SafeToDestory()
107 {
108     AutoLock lock(m_mutex);
109 
110     return m_resourcePool.size() == m_resources.size();
111 }
112 
113 
AllocateResource()114 void *BufferQueue::AllocateResource()
115 {
116     if (m_allocator)
117     {
118         if (m_resourceType == ResourceType::surfaceResource)
119         {
120             MOS_SURFACE* surface = nullptr;
121             surface = m_allocator->AllocateSurface(m_allocParam, false, MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_CACHE);
122             m_allocator->GetSurfaceInfo(surface);
123             return surface;
124         }
125         else if (m_resourceType == ResourceType::bufferResource)
126         {
127             return m_allocator->AllocateResource(m_allocParam, true);
128         }
129         else
130         {
131             return nullptr;
132         }
133 
134     }
135     else
136     {
137         return nullptr;
138     }
139 }
140 
DestoryResource(void * resource)141 MOS_STATUS BufferQueue::DestoryResource(void* resource)
142 {
143     if (nullptr != resource && nullptr != m_allocator)
144     {
145         if (m_resourceType == ResourceType::surfaceResource)
146         {
147             m_allocator->DestroySurface((MOS_SURFACE *)resource);
148         }
149         else if (m_resourceType == ResourceType::bufferResource)
150         {
151             m_allocator->DestroyResource((MOS_RESOURCE *)resource);
152         }
153     }
154     return MOS_STATUS_SUCCESS;
155 }
156 
SetResourceType(ResourceType resType)157 void BufferQueue::SetResourceType(ResourceType resType)
158 {
159     m_resourceType = resType;
160 }
161 
162 }