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