xref: /aosp_15_r20/external/mesa3d/src/imagination/vulkan/pvr_csb.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2022 Imagination Technologies Ltd.
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * based in part on anv driver which is:
5*61046927SAndroid Build Coastguard Worker  * Copyright © 2015 Intel Corporation
6*61046927SAndroid Build Coastguard Worker  *
7*61046927SAndroid Build Coastguard Worker  * based in part on v3dv_cl.h which is:
8*61046927SAndroid Build Coastguard Worker  * Copyright © 2019 Raspberry Pi
9*61046927SAndroid Build Coastguard Worker  *
10*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a copy
11*61046927SAndroid Build Coastguard Worker  * of this software and associated documentation files (the "Software"), to deal
12*61046927SAndroid Build Coastguard Worker  * in the Software without restriction, including without limitation the rights
13*61046927SAndroid Build Coastguard Worker  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14*61046927SAndroid Build Coastguard Worker  * copies of the Software, and to permit persons to whom the Software is
15*61046927SAndroid Build Coastguard Worker  * furnished to do so, subject to the following conditions:
16*61046927SAndroid Build Coastguard Worker  *
17*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
18*61046927SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
19*61046927SAndroid Build Coastguard Worker  * Software.
20*61046927SAndroid Build Coastguard Worker  *
21*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22*61046927SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24*61046927SAndroid Build Coastguard Worker  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25*61046927SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26*61046927SAndroid Build Coastguard Worker  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27*61046927SAndroid Build Coastguard Worker  * SOFTWARE.
28*61046927SAndroid Build Coastguard Worker  */
29*61046927SAndroid Build Coastguard Worker 
30*61046927SAndroid Build Coastguard Worker #ifndef PVR_CSB_H
31*61046927SAndroid Build Coastguard Worker #define PVR_CSB_H
32*61046927SAndroid Build Coastguard Worker 
33*61046927SAndroid Build Coastguard Worker #include <assert.h>
34*61046927SAndroid Build Coastguard Worker #include <stdbool.h>
35*61046927SAndroid Build Coastguard Worker #include <stdint.h>
36*61046927SAndroid Build Coastguard Worker #include <vulkan/vulkan.h>
37*61046927SAndroid Build Coastguard Worker 
38*61046927SAndroid Build Coastguard Worker #include "pvr_bo.h"
39*61046927SAndroid Build Coastguard Worker #include "pvr_types.h"
40*61046927SAndroid Build Coastguard Worker #include "pvr_winsys.h"
41*61046927SAndroid Build Coastguard Worker #include "util/list.h"
42*61046927SAndroid Build Coastguard Worker #include "util/macros.h"
43*61046927SAndroid Build Coastguard Worker #include "util/u_dynarray.h"
44*61046927SAndroid Build Coastguard Worker 
45*61046927SAndroid Build Coastguard Worker #define __pvr_address_type pvr_dev_addr_t
46*61046927SAndroid Build Coastguard Worker #define __pvr_get_address(pvr_dev_addr) (pvr_dev_addr).addr
47*61046927SAndroid Build Coastguard Worker /* clang-format off */
48*61046927SAndroid Build Coastguard Worker #define __pvr_make_address(addr_u64) PVR_DEV_ADDR(addr_u64)
49*61046927SAndroid Build Coastguard Worker /* clang-format on */
50*61046927SAndroid Build Coastguard Worker 
51*61046927SAndroid Build Coastguard Worker #include "csbgen/rogue_hwdefs.h"
52*61046927SAndroid Build Coastguard Worker 
53*61046927SAndroid Build Coastguard Worker /**
54*61046927SAndroid Build Coastguard Worker  * \brief Size of the individual csb buffer object.
55*61046927SAndroid Build Coastguard Worker  */
56*61046927SAndroid Build Coastguard Worker #define PVR_CMD_BUFFER_CSB_BO_SIZE 4096
57*61046927SAndroid Build Coastguard Worker 
58*61046927SAndroid Build Coastguard Worker struct pvr_device;
59*61046927SAndroid Build Coastguard Worker 
60*61046927SAndroid Build Coastguard Worker enum pvr_cmd_stream_type {
61*61046927SAndroid Build Coastguard Worker    PVR_CMD_STREAM_TYPE_INVALID = 0, /* explicitly treat 0 as invalid */
62*61046927SAndroid Build Coastguard Worker    PVR_CMD_STREAM_TYPE_GRAPHICS,
63*61046927SAndroid Build Coastguard Worker    PVR_CMD_STREAM_TYPE_GRAPHICS_DEFERRED,
64*61046927SAndroid Build Coastguard Worker    PVR_CMD_STREAM_TYPE_COMPUTE,
65*61046927SAndroid Build Coastguard Worker };
66*61046927SAndroid Build Coastguard Worker 
67*61046927SAndroid Build Coastguard Worker struct pvr_csb {
68*61046927SAndroid Build Coastguard Worker    struct pvr_device *device;
69*61046927SAndroid Build Coastguard Worker 
70*61046927SAndroid Build Coastguard Worker    /* Pointer to current csb buffer object */
71*61046927SAndroid Build Coastguard Worker    struct pvr_bo *pvr_bo;
72*61046927SAndroid Build Coastguard Worker 
73*61046927SAndroid Build Coastguard Worker    /* pointers to current bo memory */
74*61046927SAndroid Build Coastguard Worker    void *start;
75*61046927SAndroid Build Coastguard Worker    void *end;
76*61046927SAndroid Build Coastguard Worker    void *next;
77*61046927SAndroid Build Coastguard Worker 
78*61046927SAndroid Build Coastguard Worker    /* When extending the control stream we can't break state updates across bos.
79*61046927SAndroid Build Coastguard Worker     * This indicates where the current state update starts, so that it can be
80*61046927SAndroid Build Coastguard Worker     * be relocated into the new bo without breaking the update.
81*61046927SAndroid Build Coastguard Worker     */
82*61046927SAndroid Build Coastguard Worker    void *relocation_mark;
83*61046927SAndroid Build Coastguard Worker #if MESA_DEBUG
84*61046927SAndroid Build Coastguard Worker    /* Used to track the state of the `relocation_mark` and to catch cases where
85*61046927SAndroid Build Coastguard Worker     * the driver might have emitted to the cs without using the
86*61046927SAndroid Build Coastguard Worker     * `relocation_mark`. Doing so is mostly harmless but will waste memory in
87*61046927SAndroid Build Coastguard Worker     * case the cs is extended while an untracked state update is emitted, as
88*61046927SAndroid Build Coastguard Worker     * we'll have to relocate the cs contents from the last tracked state update
89*61046927SAndroid Build Coastguard Worker     * instead of just the one currently being emitted.
90*61046927SAndroid Build Coastguard Worker     */
91*61046927SAndroid Build Coastguard Worker    enum pvr_csb_relocation_mark_status {
92*61046927SAndroid Build Coastguard Worker       PVR_CSB_RELOCATION_MARK_UNINITIALIZED,
93*61046927SAndroid Build Coastguard Worker       PVR_CSB_RELOCATION_MARK_SET,
94*61046927SAndroid Build Coastguard Worker       PVR_CSB_RELOCATION_MARK_SET_AND_CONSUMED,
95*61046927SAndroid Build Coastguard Worker       PVR_CSB_RELOCATION_MARK_CLEARED,
96*61046927SAndroid Build Coastguard Worker    } relocation_mark_status;
97*61046927SAndroid Build Coastguard Worker #endif
98*61046927SAndroid Build Coastguard Worker 
99*61046927SAndroid Build Coastguard Worker    /* List of csb buffer objects */
100*61046927SAndroid Build Coastguard Worker    struct list_head pvr_bo_list;
101*61046927SAndroid Build Coastguard Worker 
102*61046927SAndroid Build Coastguard Worker    struct util_dynarray deferred_cs_mem;
103*61046927SAndroid Build Coastguard Worker 
104*61046927SAndroid Build Coastguard Worker    enum pvr_cmd_stream_type stream_type;
105*61046927SAndroid Build Coastguard Worker 
106*61046927SAndroid Build Coastguard Worker    /* Current error status of the command buffer. Used to track inconsistent
107*61046927SAndroid Build Coastguard Worker     * or incomplete command buffer states that are the consequence of run-time
108*61046927SAndroid Build Coastguard Worker     * errors such as out of memory scenarios. We want to track this in the
109*61046927SAndroid Build Coastguard Worker     * csb because the command buffer object is not visible to some parts
110*61046927SAndroid Build Coastguard Worker     * of the driver.
111*61046927SAndroid Build Coastguard Worker     */
112*61046927SAndroid Build Coastguard Worker    VkResult status;
113*61046927SAndroid Build Coastguard Worker };
114*61046927SAndroid Build Coastguard Worker 
115*61046927SAndroid Build Coastguard Worker /**
116*61046927SAndroid Build Coastguard Worker  * \brief Gets the status of the csb.
117*61046927SAndroid Build Coastguard Worker  *
118*61046927SAndroid Build Coastguard Worker  * \param[in] csb Control Stream Builder object.
119*61046927SAndroid Build Coastguard Worker  * \return VK_SUCCESS if the csb hasn't encountered any error or error code
120*61046927SAndroid Build Coastguard Worker  *         otherwise.
121*61046927SAndroid Build Coastguard Worker  */
pvr_csb_get_status(const struct pvr_csb * csb)122*61046927SAndroid Build Coastguard Worker static inline VkResult pvr_csb_get_status(const struct pvr_csb *csb)
123*61046927SAndroid Build Coastguard Worker {
124*61046927SAndroid Build Coastguard Worker    return csb->status;
125*61046927SAndroid Build Coastguard Worker }
126*61046927SAndroid Build Coastguard Worker 
127*61046927SAndroid Build Coastguard Worker /**
128*61046927SAndroid Build Coastguard Worker  * \brief Checks if the control stream is empty or not.
129*61046927SAndroid Build Coastguard Worker  *
130*61046927SAndroid Build Coastguard Worker  * \param[in] csb Control Stream Builder object.
131*61046927SAndroid Build Coastguard Worker  * \return true if csb is empty false otherwise.
132*61046927SAndroid Build Coastguard Worker  */
pvr_csb_is_empty(const struct pvr_csb * csb)133*61046927SAndroid Build Coastguard Worker static inline bool pvr_csb_is_empty(const struct pvr_csb *csb)
134*61046927SAndroid Build Coastguard Worker {
135*61046927SAndroid Build Coastguard Worker    return list_is_empty(&csb->pvr_bo_list);
136*61046927SAndroid Build Coastguard Worker }
137*61046927SAndroid Build Coastguard Worker 
138*61046927SAndroid Build Coastguard Worker static inline pvr_dev_addr_t
pvr_csb_get_start_address(const struct pvr_csb * csb)139*61046927SAndroid Build Coastguard Worker pvr_csb_get_start_address(const struct pvr_csb *csb)
140*61046927SAndroid Build Coastguard Worker {
141*61046927SAndroid Build Coastguard Worker    if (!pvr_csb_is_empty(csb)) {
142*61046927SAndroid Build Coastguard Worker       struct pvr_bo *pvr_bo =
143*61046927SAndroid Build Coastguard Worker          list_first_entry(&csb->pvr_bo_list, struct pvr_bo, link);
144*61046927SAndroid Build Coastguard Worker 
145*61046927SAndroid Build Coastguard Worker       return pvr_bo->vma->dev_addr;
146*61046927SAndroid Build Coastguard Worker    }
147*61046927SAndroid Build Coastguard Worker 
148*61046927SAndroid Build Coastguard Worker    return PVR_DEV_ADDR_INVALID;
149*61046927SAndroid Build Coastguard Worker }
150*61046927SAndroid Build Coastguard Worker 
151*61046927SAndroid Build Coastguard Worker /** \defgroup CSB relocation marking.
152*61046927SAndroid Build Coastguard Worker  * Functions and macros related to relocation marking for control stream words.
153*61046927SAndroid Build Coastguard Worker  *
154*61046927SAndroid Build Coastguard Worker  * When there is no more space left in the current bo, csb needs has to extend
155*61046927SAndroid Build Coastguard Worker  * the control stream by allocating a new bo and emitting a link to it. State
156*61046927SAndroid Build Coastguard Worker  * updates have to be contiguous so cannot be broken by a link. Thus csb copies
157*61046927SAndroid Build Coastguard Worker  * the current, in construction, state update into the new bo and emits a link
158*61046927SAndroid Build Coastguard Worker  * in its place in the old bo. To do so however, it needs a hint from the driver
159*61046927SAndroid Build Coastguard Worker  * to determine where the current state update started from, so a relocation
160*61046927SAndroid Build Coastguard Worker  * mark is used.
161*61046927SAndroid Build Coastguard Worker  *
162*61046927SAndroid Build Coastguard Worker  * List of words demarking the beginning of state updates (i.e. state update
163*61046927SAndroid Build Coastguard Worker  * headers):
164*61046927SAndroid Build Coastguard Worker  *  - ROGUE_VDMCTRL_PPP_STATE0
165*61046927SAndroid Build Coastguard Worker  *  - ROGUE_VDMCTRL_PDS_STATE0
166*61046927SAndroid Build Coastguard Worker  *  - ROGUE_VDMCTRL_VDM_STATE0
167*61046927SAndroid Build Coastguard Worker  *  - ROGUE_VDMCTRL_INDEX_LIST0
168*61046927SAndroid Build Coastguard Worker  *  - ROGUE_VDMCTRL_STREAM_LINK0
169*61046927SAndroid Build Coastguard Worker  *  - ROGUE_VDMCTRL_STREAM_RETURN
170*61046927SAndroid Build Coastguard Worker  *  - ROGUE_VDMCTRL_STREAM_TERMINATE
171*61046927SAndroid Build Coastguard Worker  *
172*61046927SAndroid Build Coastguard Worker  *  - ROGUE_CDMCTRL_KERNEL0
173*61046927SAndroid Build Coastguard Worker  *  - ROGUE_CDMCTRL_STREAM_LINK0
174*61046927SAndroid Build Coastguard Worker  *  - ROGUE_CDMCTRL_STREAM_TERMINATE
175*61046927SAndroid Build Coastguard Worker  *
176*61046927SAndroid Build Coastguard Worker  * The driver should set the relocation mark whenever a new state update is
177*61046927SAndroid Build Coastguard Worker  * started. And clear it when the state update is fully formed.
178*61046927SAndroid Build Coastguard Worker  *
179*61046927SAndroid Build Coastguard Worker  * PVR_CSB_RELOCATION_MARK state machine:
180*61046927SAndroid Build Coastguard Worker  *
181*61046927SAndroid Build Coastguard Worker  *    UNINITIALIZED
182*61046927SAndroid Build Coastguard Worker  *         ↓
183*61046927SAndroid Build Coastguard Worker  * ┌─── → SET ─────────┐
184*61046927SAndroid Build Coastguard Worker  * │       ↓           │
185*61046927SAndroid Build Coastguard Worker  * │ SET_AND_CONSUMED  │
186*61046927SAndroid Build Coastguard Worker  * │       ↓           │
187*61046927SAndroid Build Coastguard Worker  * │    CLEARED ← ─────┘
188*61046927SAndroid Build Coastguard Worker  * └───────┘
189*61046927SAndroid Build Coastguard Worker  *
190*61046927SAndroid Build Coastguard Worker  * @{
191*61046927SAndroid Build Coastguard Worker  */
192*61046927SAndroid Build Coastguard Worker /* TODO: Add in the IPF transfer control stream state updates to the list once
193*61046927SAndroid Build Coastguard Worker  * csb gets used for it
194*61046927SAndroid Build Coastguard Worker  */
195*61046927SAndroid Build Coastguard Worker 
196*61046927SAndroid Build Coastguard Worker /**
197*61046927SAndroid Build Coastguard Worker  * \brief Set the relocation mark.
198*61046927SAndroid Build Coastguard Worker  *
199*61046927SAndroid Build Coastguard Worker  * Indicates to csb that on cs extension it should relocate all words, starting
200*61046927SAndroid Build Coastguard Worker  * from now, into the new bo.
201*61046927SAndroid Build Coastguard Worker  */
pvr_csb_set_relocation_mark(struct pvr_csb * csb)202*61046927SAndroid Build Coastguard Worker static inline void pvr_csb_set_relocation_mark(struct pvr_csb *csb)
203*61046927SAndroid Build Coastguard Worker {
204*61046927SAndroid Build Coastguard Worker #if MESA_DEBUG
205*61046927SAndroid Build Coastguard Worker    assert(csb->relocation_mark_status ==
206*61046927SAndroid Build Coastguard Worker              PVR_CSB_RELOCATION_MARK_UNINITIALIZED ||
207*61046927SAndroid Build Coastguard Worker           csb->relocation_mark_status == PVR_CSB_RELOCATION_MARK_CLEARED);
208*61046927SAndroid Build Coastguard Worker 
209*61046927SAndroid Build Coastguard Worker    csb->relocation_mark_status = PVR_CSB_RELOCATION_MARK_SET;
210*61046927SAndroid Build Coastguard Worker #endif
211*61046927SAndroid Build Coastguard Worker 
212*61046927SAndroid Build Coastguard Worker    csb->relocation_mark = csb->next;
213*61046927SAndroid Build Coastguard Worker }
214*61046927SAndroid Build Coastguard Worker 
215*61046927SAndroid Build Coastguard Worker /**
216*61046927SAndroid Build Coastguard Worker  * \brief Clear the relocation mark.
217*61046927SAndroid Build Coastguard Worker  *
218*61046927SAndroid Build Coastguard Worker  * Indicate to csb that the state update is fully formed so it doesn't need to
219*61046927SAndroid Build Coastguard Worker  * relocate it in case of cs extension.
220*61046927SAndroid Build Coastguard Worker  */
pvr_csb_clear_relocation_mark(UNUSED struct pvr_csb * csb)221*61046927SAndroid Build Coastguard Worker static inline void pvr_csb_clear_relocation_mark(UNUSED struct pvr_csb *csb)
222*61046927SAndroid Build Coastguard Worker {
223*61046927SAndroid Build Coastguard Worker #if MESA_DEBUG
224*61046927SAndroid Build Coastguard Worker    assert(csb->relocation_mark_status == PVR_CSB_RELOCATION_MARK_SET ||
225*61046927SAndroid Build Coastguard Worker           csb->relocation_mark_status ==
226*61046927SAndroid Build Coastguard Worker              PVR_CSB_RELOCATION_MARK_SET_AND_CONSUMED);
227*61046927SAndroid Build Coastguard Worker 
228*61046927SAndroid Build Coastguard Worker    csb->relocation_mark_status = PVR_CSB_RELOCATION_MARK_CLEARED;
229*61046927SAndroid Build Coastguard Worker #endif
230*61046927SAndroid Build Coastguard Worker }
231*61046927SAndroid Build Coastguard Worker 
232*61046927SAndroid Build Coastguard Worker /** @} */
233*61046927SAndroid Build Coastguard Worker /* End of \defgroup CSB relocation marking. */
234*61046927SAndroid Build Coastguard Worker 
235*61046927SAndroid Build Coastguard Worker void pvr_csb_init(struct pvr_device *device,
236*61046927SAndroid Build Coastguard Worker                   enum pvr_cmd_stream_type stream_type,
237*61046927SAndroid Build Coastguard Worker                   struct pvr_csb *csb);
238*61046927SAndroid Build Coastguard Worker void pvr_csb_finish(struct pvr_csb *csb);
239*61046927SAndroid Build Coastguard Worker VkResult pvr_csb_bake(struct pvr_csb *csb, struct list_head *bo_list_out);
240*61046927SAndroid Build Coastguard Worker void *pvr_csb_alloc_dwords(struct pvr_csb *csb, uint32_t num_dwords);
241*61046927SAndroid Build Coastguard Worker VkResult pvr_csb_copy(struct pvr_csb *csb_dst, struct pvr_csb *csb_src);
242*61046927SAndroid Build Coastguard Worker void pvr_csb_emit_link(struct pvr_csb *csb, pvr_dev_addr_t addr, bool ret);
243*61046927SAndroid Build Coastguard Worker VkResult pvr_csb_emit_return(struct pvr_csb *csb);
244*61046927SAndroid Build Coastguard Worker VkResult pvr_csb_emit_terminate(struct pvr_csb *csb);
245*61046927SAndroid Build Coastguard Worker 
246*61046927SAndroid Build Coastguard Worker void pvr_csb_dump(const struct pvr_csb *csb,
247*61046927SAndroid Build Coastguard Worker                   uint32_t frame_num,
248*61046927SAndroid Build Coastguard Worker                   uint32_t job_num);
249*61046927SAndroid Build Coastguard Worker 
250*61046927SAndroid Build Coastguard Worker #define PVRX(x) ROGUE_##x
251*61046927SAndroid Build Coastguard Worker #define pvr_cmd_length(x) PVRX(x##_length)
252*61046927SAndroid Build Coastguard Worker #define pvr_cmd_header(x) PVRX(x##_header)
253*61046927SAndroid Build Coastguard Worker #define pvr_cmd_pack(x) PVRX(x##_pack)
254*61046927SAndroid Build Coastguard Worker #define pvr_cmd_unpack(x) PVRX(x##_unpack)
255*61046927SAndroid Build Coastguard Worker #define pvr_cmd_enum_to_str(x) PVRX(x##_to_str)
256*61046927SAndroid Build Coastguard Worker 
257*61046927SAndroid Build Coastguard Worker /**
258*61046927SAndroid Build Coastguard Worker  * \brief Merges dwords0 and dwords1 arrays and stores the result into the
259*61046927SAndroid Build Coastguard Worker  * control stream pointed by the csb object.
260*61046927SAndroid Build Coastguard Worker  *
261*61046927SAndroid Build Coastguard Worker  * \param[in] csb     Control Stream Builder object.
262*61046927SAndroid Build Coastguard Worker  * \param[in] dwords0 Dwords0 array.
263*61046927SAndroid Build Coastguard Worker  * \param[in] dwords1 Dwords1 array.
264*61046927SAndroid Build Coastguard Worker  */
265*61046927SAndroid Build Coastguard Worker #define pvr_csb_emit_merge(csb, dwords0, dwords1)                \
266*61046927SAndroid Build Coastguard Worker    do {                                                          \
267*61046927SAndroid Build Coastguard Worker       uint32_t *dw;                                              \
268*61046927SAndroid Build Coastguard Worker       STATIC_ASSERT(ARRAY_SIZE(dwords0) == ARRAY_SIZE(dwords1)); \
269*61046927SAndroid Build Coastguard Worker       dw = pvr_csb_alloc_dwords(csb, ARRAY_SIZE(dwords0));       \
270*61046927SAndroid Build Coastguard Worker       if (!dw)                                                   \
271*61046927SAndroid Build Coastguard Worker          break;                                                  \
272*61046927SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < ARRAY_SIZE(dwords0); i++)         \
273*61046927SAndroid Build Coastguard Worker          dw[i] = (dwords0)[i] | (dwords1)[i];                    \
274*61046927SAndroid Build Coastguard Worker    } while (0)
275*61046927SAndroid Build Coastguard Worker 
276*61046927SAndroid Build Coastguard Worker /**
277*61046927SAndroid Build Coastguard Worker  * \brief Packs a command/state into one or more dwords and stores them into
278*61046927SAndroid Build Coastguard Worker  * the control stream pointed by the csb object.
279*61046927SAndroid Build Coastguard Worker  *
280*61046927SAndroid Build Coastguard Worker  * \param[in] csb      Control Stream Builder object.
281*61046927SAndroid Build Coastguard Worker  * \param[in] cmd      Command/state type.
282*61046927SAndroid Build Coastguard Worker  * \param[in,out] name Name to give to the command/state structure variable,
283*61046927SAndroid Build Coastguard Worker  *                     which contains the information to be packed. This can be
284*61046927SAndroid Build Coastguard Worker  *                     used by the caller to modify the command or state
285*61046927SAndroid Build Coastguard Worker  *                     information before it's packed.
286*61046927SAndroid Build Coastguard Worker  */
287*61046927SAndroid Build Coastguard Worker #define pvr_csb_emit(csb, cmd, name)                               \
288*61046927SAndroid Build Coastguard Worker    for (struct PVRX(cmd)                                           \
289*61046927SAndroid Build Coastguard Worker            name = { pvr_cmd_header(cmd) },                         \
290*61046927SAndroid Build Coastguard Worker            *_dst = pvr_csb_alloc_dwords(csb, pvr_cmd_length(cmd)); \
291*61046927SAndroid Build Coastguard Worker         __builtin_expect(_dst != NULL, 1);                         \
292*61046927SAndroid Build Coastguard Worker         ({                                                         \
293*61046927SAndroid Build Coastguard Worker            pvr_cmd_pack(cmd)(_dst, &name);                         \
294*61046927SAndroid Build Coastguard Worker            _dst = NULL;                                            \
295*61046927SAndroid Build Coastguard Worker         }))
296*61046927SAndroid Build Coastguard Worker 
297*61046927SAndroid Build Coastguard Worker /**
298*61046927SAndroid Build Coastguard Worker  * \brief Stores dword into the control stream pointed by the csb object.
299*61046927SAndroid Build Coastguard Worker  *
300*61046927SAndroid Build Coastguard Worker  * \param[in] csb   Control Stream Builder object.
301*61046927SAndroid Build Coastguard Worker  * \param[in] dword Dword to store into control stream.
302*61046927SAndroid Build Coastguard Worker  */
303*61046927SAndroid Build Coastguard Worker #define pvr_csb_emit_dword(csb, dword)                  \
304*61046927SAndroid Build Coastguard Worker    do {                                                 \
305*61046927SAndroid Build Coastguard Worker       uint32_t *dw;                                     \
306*61046927SAndroid Build Coastguard Worker       STATIC_ASSERT(sizeof(dword) == sizeof(uint32_t)); \
307*61046927SAndroid Build Coastguard Worker       dw = pvr_csb_alloc_dwords(csb, 1U);               \
308*61046927SAndroid Build Coastguard Worker       if (!dw)                                          \
309*61046927SAndroid Build Coastguard Worker          break;                                         \
310*61046927SAndroid Build Coastguard Worker       *dw = dword;                                      \
311*61046927SAndroid Build Coastguard Worker    } while (0)
312*61046927SAndroid Build Coastguard Worker 
313*61046927SAndroid Build Coastguard Worker /**
314*61046927SAndroid Build Coastguard Worker  * \name Raw command/state buffer helpers.
315*61046927SAndroid Build Coastguard Worker  * These provide functionality to read or write control/state words from/to a
316*61046927SAndroid Build Coastguard Worker  * raw buffer, accessed through a pointer, with some extra checks.
317*61046927SAndroid Build Coastguard Worker  *
318*61046927SAndroid Build Coastguard Worker  * The raw buffer doesn't have to be related to a control stream builder object
319*61046927SAndroid Build Coastguard Worker  * so these can be used with any cpu accessible buffer.
320*61046927SAndroid Build Coastguard Worker  */
321*61046927SAndroid Build Coastguard Worker /**@{*/
322*61046927SAndroid Build Coastguard Worker 
323*61046927SAndroid Build Coastguard Worker /**
324*61046927SAndroid Build Coastguard Worker  * \brief Packs a command/state into one or more dwords and stores them in the
325*61046927SAndroid Build Coastguard Worker  * memory pointed to by _dst.
326*61046927SAndroid Build Coastguard Worker  *
327*61046927SAndroid Build Coastguard Worker  * \param[out] _dst    Pointer to store the packed command/state.
328*61046927SAndroid Build Coastguard Worker  * \param[in] cmd      Command/state type.
329*61046927SAndroid Build Coastguard Worker  * \param[in,out] name Name to give to the command/state structure variable,
330*61046927SAndroid Build Coastguard Worker  *                     which contains the information to be packed and emitted.
331*61046927SAndroid Build Coastguard Worker  *                     This can be used by the caller to modify the command or
332*61046927SAndroid Build Coastguard Worker  *                     state information before it's packed.
333*61046927SAndroid Build Coastguard Worker  */
334*61046927SAndroid Build Coastguard Worker #define pvr_csb_pack(_dst, cmd, name)                           \
335*61046927SAndroid Build Coastguard Worker    for (struct PVRX(cmd) name = { pvr_cmd_header(cmd) },        \
336*61046927SAndroid Build Coastguard Worker                          *_loop_terminate = &name;              \
337*61046927SAndroid Build Coastguard Worker         __builtin_expect(_loop_terminate != NULL, 1);           \
338*61046927SAndroid Build Coastguard Worker         ({                                                      \
339*61046927SAndroid Build Coastguard Worker            STATIC_ASSERT(sizeof(*(_dst)) ==                     \
340*61046927SAndroid Build Coastguard Worker                          PVR_DW_TO_BYTES(pvr_cmd_length(cmd))); \
341*61046927SAndroid Build Coastguard Worker            pvr_cmd_pack(cmd)((_dst), &name);                    \
342*61046927SAndroid Build Coastguard Worker            _loop_terminate = NULL;                              \
343*61046927SAndroid Build Coastguard Worker         }))
344*61046927SAndroid Build Coastguard Worker 
345*61046927SAndroid Build Coastguard Worker /**
346*61046927SAndroid Build Coastguard Worker  * \brief Unpacks one or more dwords into a command/state struct.
347*61046927SAndroid Build Coastguard Worker  *
348*61046927SAndroid Build Coastguard Worker  * Unlike pvr_csb_pack, this returns the stack-allocated struct directly
349*61046927SAndroid Build Coastguard Worker  * since it is not needed afterwards.
350*61046927SAndroid Build Coastguard Worker  *
351*61046927SAndroid Build Coastguard Worker  * \param[in] _src     Pointer to read the packed command/state from.
352*61046927SAndroid Build Coastguard Worker  * \param[in] cmd      Command/state type.
353*61046927SAndroid Build Coastguard Worker  */
354*61046927SAndroid Build Coastguard Worker #define pvr_csb_unpack(_src, cmd)                                             \
355*61046927SAndroid Build Coastguard Worker    ({                                                                         \
356*61046927SAndroid Build Coastguard Worker       struct PVRX(cmd) _name;                                                 \
357*61046927SAndroid Build Coastguard Worker       STATIC_ASSERT(sizeof(*(_src)) == PVR_DW_TO_BYTES(pvr_cmd_length(cmd))); \
358*61046927SAndroid Build Coastguard Worker       pvr_cmd_unpack(cmd)((_src), &_name);                                    \
359*61046927SAndroid Build Coastguard Worker       _name;                                                                  \
360*61046927SAndroid Build Coastguard Worker    })
361*61046927SAndroid Build Coastguard Worker 
362*61046927SAndroid Build Coastguard Worker /**
363*61046927SAndroid Build Coastguard Worker  * \brief Writes a command/state word value into a raw buffer and advance.
364*61046927SAndroid Build Coastguard Worker  *
365*61046927SAndroid Build Coastguard Worker  * The buffer pointer is incremented appropriately based on the control stream
366*61046927SAndroid Build Coastguard Worker  * word length.
367*61046927SAndroid Build Coastguard Worker  *
368*61046927SAndroid Build Coastguard Worker  * \param[in,out] dst Raw buffer pointer for writing.
369*61046927SAndroid Build Coastguard Worker  * \param[in]     cmd Command/state type.
370*61046927SAndroid Build Coastguard Worker  * \param[in]     val Pre-packed value to write.
371*61046927SAndroid Build Coastguard Worker  */
372*61046927SAndroid Build Coastguard Worker #define pvr_csb_write_value(dst, cmd, val)                                  \
373*61046927SAndroid Build Coastguard Worker    do {                                                                     \
374*61046927SAndroid Build Coastguard Worker       static_assert(sizeof(*(dst)) == PVR_DW_TO_BYTES(pvr_cmd_length(cmd)), \
375*61046927SAndroid Build Coastguard Worker                     "Size mismatch");                                       \
376*61046927SAndroid Build Coastguard Worker       static_assert(sizeof(*(dst)) == sizeof(val), "Size mismatch");        \
377*61046927SAndroid Build Coastguard Worker       *(dst) = (val);                                                       \
378*61046927SAndroid Build Coastguard Worker       (dst)++;                                                              \
379*61046927SAndroid Build Coastguard Worker    } while (0)
380*61046927SAndroid Build Coastguard Worker 
381*61046927SAndroid Build Coastguard Worker /**
382*61046927SAndroid Build Coastguard Worker  * \brief Packs a command/state word struct and writes the value into a raw
383*61046927SAndroid Build Coastguard Worker  * buffer and advance.
384*61046927SAndroid Build Coastguard Worker  *
385*61046927SAndroid Build Coastguard Worker  * The buffer pointer is incremented appropriately based on the control stream
386*61046927SAndroid Build Coastguard Worker  * word length.
387*61046927SAndroid Build Coastguard Worker  *
388*61046927SAndroid Build Coastguard Worker  * \param[in,out] dst Raw buffer pointer for writing.
389*61046927SAndroid Build Coastguard Worker  * \param[in]     cmd Command/state type.
390*61046927SAndroid Build Coastguard Worker  * \param[in]     val Command/state struct to pack and write.
391*61046927SAndroid Build Coastguard Worker  */
392*61046927SAndroid Build Coastguard Worker #define pvr_csb_write_struct(dst, cmd, val)                                 \
393*61046927SAndroid Build Coastguard Worker    do {                                                                     \
394*61046927SAndroid Build Coastguard Worker       static_assert(sizeof(*(dst)) == PVR_DW_TO_BYTES(pvr_cmd_length(cmd)), \
395*61046927SAndroid Build Coastguard Worker                     "Size mismatch");                                       \
396*61046927SAndroid Build Coastguard Worker       pvr_cmd_pack(cmd)((dst), (val));                                      \
397*61046927SAndroid Build Coastguard Worker       (dst)++;                                                              \
398*61046927SAndroid Build Coastguard Worker    } while (0)
399*61046927SAndroid Build Coastguard Worker 
400*61046927SAndroid Build Coastguard Worker /**@}*/
401*61046927SAndroid Build Coastguard Worker /* End of \name Raw command/state buffer helpers. */
402*61046927SAndroid Build Coastguard Worker 
403*61046927SAndroid Build Coastguard Worker #endif /* PVR_CSB_H */
404