1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright 2018 Chromium.
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub
8bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom
9bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#include "util/u_box.h"
25bf215546Sopenharmony_ci#include "util/u_inlines.h"
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ci#include "virtio-gpu/virgl_protocol.h"
28bf215546Sopenharmony_ci#include "virgl_context.h"
29bf215546Sopenharmony_ci#include "virgl_screen.h"
30bf215546Sopenharmony_ci#include "virgl_encode.h"
31bf215546Sopenharmony_ci#include "virgl_resource.h"
32bf215546Sopenharmony_ci#include "virgl_transfer_queue.h"
33bf215546Sopenharmony_ci
34bf215546Sopenharmony_cistruct list_action_args
35bf215546Sopenharmony_ci{
36bf215546Sopenharmony_ci   void *data;
37bf215546Sopenharmony_ci   struct virgl_transfer *queued;
38bf215546Sopenharmony_ci   struct virgl_transfer *current;
39bf215546Sopenharmony_ci};
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_citypedef bool (*compare_transfers_t)(struct virgl_transfer *queued,
42bf215546Sopenharmony_ci                                    struct virgl_transfer *current);
43bf215546Sopenharmony_ci
44bf215546Sopenharmony_citypedef void (*list_action_t)(struct virgl_transfer_queue *queue,
45bf215546Sopenharmony_ci                              struct list_action_args *args);
46bf215546Sopenharmony_ci
47bf215546Sopenharmony_cistruct list_iteration_args
48bf215546Sopenharmony_ci{
49bf215546Sopenharmony_ci   void *data;
50bf215546Sopenharmony_ci   list_action_t action;
51bf215546Sopenharmony_ci   compare_transfers_t compare;
52bf215546Sopenharmony_ci   struct virgl_transfer *current;
53bf215546Sopenharmony_ci};
54bf215546Sopenharmony_ci
55bf215546Sopenharmony_cistatic int
56bf215546Sopenharmony_citransfer_dim(const struct virgl_transfer *xfer)
57bf215546Sopenharmony_ci{
58bf215546Sopenharmony_ci   switch (xfer->base.resource->target) {
59bf215546Sopenharmony_ci   case PIPE_BUFFER:
60bf215546Sopenharmony_ci   case PIPE_TEXTURE_1D:
61bf215546Sopenharmony_ci      return 1;
62bf215546Sopenharmony_ci   case PIPE_TEXTURE_2D:
63bf215546Sopenharmony_ci   case PIPE_TEXTURE_RECT:
64bf215546Sopenharmony_ci      return 2;
65bf215546Sopenharmony_ci   default:
66bf215546Sopenharmony_ci      return 3;
67bf215546Sopenharmony_ci   }
68bf215546Sopenharmony_ci}
69bf215546Sopenharmony_ci
70bf215546Sopenharmony_cistatic void
71bf215546Sopenharmony_cibox_min_max(const struct pipe_box *box, int dim, int *min, int *max)
72bf215546Sopenharmony_ci{
73bf215546Sopenharmony_ci   switch (dim) {
74bf215546Sopenharmony_ci   case 0:
75bf215546Sopenharmony_ci      if (box->width > 0) {
76bf215546Sopenharmony_ci         *min = box->x;
77bf215546Sopenharmony_ci         *max = box->x + box->width;
78bf215546Sopenharmony_ci      } else {
79bf215546Sopenharmony_ci         *max = box->x;
80bf215546Sopenharmony_ci         *min = box->x + box->width;
81bf215546Sopenharmony_ci      }
82bf215546Sopenharmony_ci      break;
83bf215546Sopenharmony_ci   case 1:
84bf215546Sopenharmony_ci      if (box->height > 0) {
85bf215546Sopenharmony_ci         *min = box->y;
86bf215546Sopenharmony_ci         *max = box->y + box->height;
87bf215546Sopenharmony_ci      } else {
88bf215546Sopenharmony_ci         *max = box->y;
89bf215546Sopenharmony_ci         *min = box->y + box->height;
90bf215546Sopenharmony_ci      }
91bf215546Sopenharmony_ci      break;
92bf215546Sopenharmony_ci   default:
93bf215546Sopenharmony_ci      if (box->depth > 0) {
94bf215546Sopenharmony_ci         *min = box->z;
95bf215546Sopenharmony_ci         *max = box->z + box->depth;
96bf215546Sopenharmony_ci      } else {
97bf215546Sopenharmony_ci         *max = box->z;
98bf215546Sopenharmony_ci         *min = box->z + box->depth;
99bf215546Sopenharmony_ci      }
100bf215546Sopenharmony_ci      break;
101bf215546Sopenharmony_ci   }
102bf215546Sopenharmony_ci}
103bf215546Sopenharmony_ci
104bf215546Sopenharmony_cistatic bool
105bf215546Sopenharmony_citransfer_overlap(const struct virgl_transfer *xfer,
106bf215546Sopenharmony_ci                 const struct virgl_hw_res *hw_res,
107bf215546Sopenharmony_ci                 unsigned level,
108bf215546Sopenharmony_ci                 const struct pipe_box *box,
109bf215546Sopenharmony_ci                 bool include_touching)
110bf215546Sopenharmony_ci{
111bf215546Sopenharmony_ci   const int dim_count = transfer_dim(xfer);
112bf215546Sopenharmony_ci
113bf215546Sopenharmony_ci   if (xfer->hw_res != hw_res || xfer->base.level != level)
114bf215546Sopenharmony_ci      return false;
115bf215546Sopenharmony_ci
116bf215546Sopenharmony_ci   for (int dim = 0; dim < dim_count; dim++) {
117bf215546Sopenharmony_ci      int xfer_min;
118bf215546Sopenharmony_ci      int xfer_max;
119bf215546Sopenharmony_ci      int box_min;
120bf215546Sopenharmony_ci      int box_max;
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_ci      box_min_max(&xfer->base.box, dim, &xfer_min, &xfer_max);
123bf215546Sopenharmony_ci      box_min_max(box, dim, &box_min, &box_max);
124bf215546Sopenharmony_ci
125bf215546Sopenharmony_ci      if (include_touching) {
126bf215546Sopenharmony_ci         /* touching is considered overlapping */
127bf215546Sopenharmony_ci         if (xfer_min > box_max || xfer_max < box_min)
128bf215546Sopenharmony_ci            return false;
129bf215546Sopenharmony_ci      } else {
130bf215546Sopenharmony_ci         /* touching is not considered overlapping */
131bf215546Sopenharmony_ci         if (xfer_min >= box_max || xfer_max <= box_min)
132bf215546Sopenharmony_ci            return false;
133bf215546Sopenharmony_ci      }
134bf215546Sopenharmony_ci   }
135bf215546Sopenharmony_ci
136bf215546Sopenharmony_ci   return true;
137bf215546Sopenharmony_ci}
138bf215546Sopenharmony_ci
139bf215546Sopenharmony_cistatic struct virgl_transfer *
140bf215546Sopenharmony_civirgl_transfer_queue_find_overlap(const struct virgl_transfer_queue *queue,
141bf215546Sopenharmony_ci                                  const struct virgl_hw_res *hw_res,
142bf215546Sopenharmony_ci                                  unsigned level,
143bf215546Sopenharmony_ci                                  const struct pipe_box *box,
144bf215546Sopenharmony_ci                                  bool include_touching)
145bf215546Sopenharmony_ci{
146bf215546Sopenharmony_ci   struct virgl_transfer *xfer;
147bf215546Sopenharmony_ci   LIST_FOR_EACH_ENTRY(xfer, &queue->transfer_list, queue_link) {
148bf215546Sopenharmony_ci      if (transfer_overlap(xfer, hw_res, level, box, include_touching))
149bf215546Sopenharmony_ci         return xfer;
150bf215546Sopenharmony_ci   }
151bf215546Sopenharmony_ci
152bf215546Sopenharmony_ci   return NULL;
153bf215546Sopenharmony_ci}
154bf215546Sopenharmony_ci
155bf215546Sopenharmony_cistatic bool transfers_intersect(struct virgl_transfer *queued,
156bf215546Sopenharmony_ci                                struct virgl_transfer *current)
157bf215546Sopenharmony_ci{
158bf215546Sopenharmony_ci   return transfer_overlap(queued, current->hw_res, current->base.level,
159bf215546Sopenharmony_ci         &current->base.box, true);
160bf215546Sopenharmony_ci}
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_cistatic void remove_transfer(struct virgl_transfer_queue *queue,
163bf215546Sopenharmony_ci                            struct virgl_transfer *queued)
164bf215546Sopenharmony_ci{
165bf215546Sopenharmony_ci   list_del(&queued->queue_link);
166bf215546Sopenharmony_ci   virgl_resource_destroy_transfer(queue->vctx, queued);
167bf215546Sopenharmony_ci}
168bf215546Sopenharmony_ci
169bf215546Sopenharmony_cistatic void replace_unmapped_transfer(struct virgl_transfer_queue *queue,
170bf215546Sopenharmony_ci                                      struct list_action_args *args)
171bf215546Sopenharmony_ci{
172bf215546Sopenharmony_ci   struct virgl_transfer *current = args->current;
173bf215546Sopenharmony_ci   struct virgl_transfer *queued = args->queued;
174bf215546Sopenharmony_ci
175bf215546Sopenharmony_ci   u_box_union_2d(&current->base.box, &current->base.box, &queued->base.box);
176bf215546Sopenharmony_ci   current->offset = current->base.box.x;
177bf215546Sopenharmony_ci
178bf215546Sopenharmony_ci   remove_transfer(queue, queued);
179bf215546Sopenharmony_ci   queue->num_dwords -= (VIRGL_TRANSFER3D_SIZE + 1);
180bf215546Sopenharmony_ci}
181bf215546Sopenharmony_ci
182bf215546Sopenharmony_cistatic void transfer_put(struct virgl_transfer_queue *queue,
183bf215546Sopenharmony_ci                         struct list_action_args *args)
184bf215546Sopenharmony_ci{
185bf215546Sopenharmony_ci   struct virgl_transfer *queued = args->queued;
186bf215546Sopenharmony_ci
187bf215546Sopenharmony_ci   queue->vs->vws->transfer_put(queue->vs->vws, queued->hw_res,
188bf215546Sopenharmony_ci                                &queued->base.box,
189bf215546Sopenharmony_ci                                queued->base.stride, queued->l_stride,
190bf215546Sopenharmony_ci                                queued->offset, queued->base.level);
191bf215546Sopenharmony_ci
192bf215546Sopenharmony_ci   remove_transfer(queue, queued);
193bf215546Sopenharmony_ci}
194bf215546Sopenharmony_ci
195bf215546Sopenharmony_cistatic void transfer_write(struct virgl_transfer_queue *queue,
196bf215546Sopenharmony_ci                           struct list_action_args *args)
197bf215546Sopenharmony_ci{
198bf215546Sopenharmony_ci   struct virgl_transfer *queued = args->queued;
199bf215546Sopenharmony_ci   struct virgl_cmd_buf *buf = args->data;
200bf215546Sopenharmony_ci
201bf215546Sopenharmony_ci   // Takes a reference on the HW resource, which is released after
202bf215546Sopenharmony_ci   // the exec buffer command.
203bf215546Sopenharmony_ci   virgl_encode_transfer(queue->vs, buf, queued, VIRGL_TRANSFER_TO_HOST);
204bf215546Sopenharmony_ci
205bf215546Sopenharmony_ci   remove_transfer(queue, queued);
206bf215546Sopenharmony_ci}
207bf215546Sopenharmony_ci
208bf215546Sopenharmony_cistatic void compare_and_perform_action(struct virgl_transfer_queue *queue,
209bf215546Sopenharmony_ci                                       struct list_iteration_args *iter)
210bf215546Sopenharmony_ci{
211bf215546Sopenharmony_ci   struct list_action_args args;
212bf215546Sopenharmony_ci   struct virgl_transfer *queued, *tmp;
213bf215546Sopenharmony_ci
214bf215546Sopenharmony_ci   memset(&args, 0, sizeof(args));
215bf215546Sopenharmony_ci   args.current = iter->current;
216bf215546Sopenharmony_ci   args.data = iter->data;
217bf215546Sopenharmony_ci
218bf215546Sopenharmony_ci   LIST_FOR_EACH_ENTRY_SAFE(queued, tmp, &queue->transfer_list, queue_link) {
219bf215546Sopenharmony_ci      if (iter->compare(queued, iter->current)) {
220bf215546Sopenharmony_ci         args.queued = queued;
221bf215546Sopenharmony_ci         iter->action(queue, &args);
222bf215546Sopenharmony_ci      }
223bf215546Sopenharmony_ci   }
224bf215546Sopenharmony_ci}
225bf215546Sopenharmony_ci
226bf215546Sopenharmony_cistatic void perform_action(struct virgl_transfer_queue *queue,
227bf215546Sopenharmony_ci                           struct list_iteration_args *iter)
228bf215546Sopenharmony_ci{
229bf215546Sopenharmony_ci   struct list_action_args args;
230bf215546Sopenharmony_ci   struct virgl_transfer *queued, *tmp;
231bf215546Sopenharmony_ci
232bf215546Sopenharmony_ci   memset(&args, 0, sizeof(args));
233bf215546Sopenharmony_ci   args.data = iter->data;
234bf215546Sopenharmony_ci
235bf215546Sopenharmony_ci   LIST_FOR_EACH_ENTRY_SAFE(queued, tmp, &queue->transfer_list, queue_link) {
236bf215546Sopenharmony_ci      args.queued = queued;
237bf215546Sopenharmony_ci      iter->action(queue, &args);
238bf215546Sopenharmony_ci   }
239bf215546Sopenharmony_ci}
240bf215546Sopenharmony_ci
241bf215546Sopenharmony_cistatic void add_internal(struct virgl_transfer_queue *queue,
242bf215546Sopenharmony_ci                         struct virgl_transfer *transfer)
243bf215546Sopenharmony_ci{
244bf215546Sopenharmony_ci   uint32_t dwords = VIRGL_TRANSFER3D_SIZE + 1;
245bf215546Sopenharmony_ci   if (queue->tbuf) {
246bf215546Sopenharmony_ci      if (queue->num_dwords + dwords >= VIRGL_MAX_TBUF_DWORDS) {
247bf215546Sopenharmony_ci         struct list_iteration_args iter;
248bf215546Sopenharmony_ci         struct virgl_winsys *vws = queue->vs->vws;
249bf215546Sopenharmony_ci
250bf215546Sopenharmony_ci         memset(&iter, 0, sizeof(iter));
251bf215546Sopenharmony_ci         iter.action = transfer_write;
252bf215546Sopenharmony_ci         iter.data = queue->tbuf;
253bf215546Sopenharmony_ci         perform_action(queue, &iter);
254bf215546Sopenharmony_ci
255bf215546Sopenharmony_ci         vws->submit_cmd(vws, queue->tbuf, NULL);
256bf215546Sopenharmony_ci         queue->num_dwords = 0;
257bf215546Sopenharmony_ci      }
258bf215546Sopenharmony_ci   }
259bf215546Sopenharmony_ci
260bf215546Sopenharmony_ci   list_addtail(&transfer->queue_link, &queue->transfer_list);
261bf215546Sopenharmony_ci   queue->num_dwords += dwords;
262bf215546Sopenharmony_ci}
263bf215546Sopenharmony_ci
264bf215546Sopenharmony_civoid virgl_transfer_queue_init(struct virgl_transfer_queue *queue,
265bf215546Sopenharmony_ci                               struct virgl_context *vctx)
266bf215546Sopenharmony_ci{
267bf215546Sopenharmony_ci   struct virgl_screen *vs = virgl_screen(vctx->base.screen);
268bf215546Sopenharmony_ci
269bf215546Sopenharmony_ci   queue->vs = vs;
270bf215546Sopenharmony_ci   queue->vctx = vctx;
271bf215546Sopenharmony_ci   queue->num_dwords = 0;
272bf215546Sopenharmony_ci
273bf215546Sopenharmony_ci   list_inithead(&queue->transfer_list);
274bf215546Sopenharmony_ci
275bf215546Sopenharmony_ci   if ((vs->caps.caps.v2.capability_bits & VIRGL_CAP_TRANSFER) &&
276bf215546Sopenharmony_ci        vs->vws->supports_encoded_transfers)
277bf215546Sopenharmony_ci      queue->tbuf = vs->vws->cmd_buf_create(vs->vws, VIRGL_MAX_TBUF_DWORDS);
278bf215546Sopenharmony_ci   else
279bf215546Sopenharmony_ci      queue->tbuf = NULL;
280bf215546Sopenharmony_ci}
281bf215546Sopenharmony_ci
282bf215546Sopenharmony_civoid virgl_transfer_queue_fini(struct virgl_transfer_queue *queue)
283bf215546Sopenharmony_ci{
284bf215546Sopenharmony_ci   struct virgl_winsys *vws = queue->vs->vws;
285bf215546Sopenharmony_ci   struct list_iteration_args iter;
286bf215546Sopenharmony_ci
287bf215546Sopenharmony_ci   memset(&iter, 0, sizeof(iter));
288bf215546Sopenharmony_ci
289bf215546Sopenharmony_ci   iter.action = transfer_put;
290bf215546Sopenharmony_ci   perform_action(queue, &iter);
291bf215546Sopenharmony_ci
292bf215546Sopenharmony_ci   if (queue->tbuf)
293bf215546Sopenharmony_ci      vws->cmd_buf_destroy(queue->tbuf);
294bf215546Sopenharmony_ci
295bf215546Sopenharmony_ci   queue->vs = NULL;
296bf215546Sopenharmony_ci   queue->vctx = NULL;
297bf215546Sopenharmony_ci   queue->tbuf = NULL;
298bf215546Sopenharmony_ci   queue->num_dwords = 0;
299bf215546Sopenharmony_ci}
300bf215546Sopenharmony_ci
301bf215546Sopenharmony_ciint virgl_transfer_queue_unmap(struct virgl_transfer_queue *queue,
302bf215546Sopenharmony_ci                               struct virgl_transfer *transfer)
303bf215546Sopenharmony_ci{
304bf215546Sopenharmony_ci   struct list_iteration_args iter;
305bf215546Sopenharmony_ci
306bf215546Sopenharmony_ci   /* We don't support copy transfers in the transfer queue. */
307bf215546Sopenharmony_ci   assert(!transfer->copy_src_hw_res);
308bf215546Sopenharmony_ci
309bf215546Sopenharmony_ci   /* Attempt to merge multiple intersecting transfers into a single one. */
310bf215546Sopenharmony_ci   if (transfer->base.resource->target == PIPE_BUFFER) {
311bf215546Sopenharmony_ci      memset(&iter, 0, sizeof(iter));
312bf215546Sopenharmony_ci      iter.current = transfer;
313bf215546Sopenharmony_ci      iter.compare = transfers_intersect;
314bf215546Sopenharmony_ci      iter.action = replace_unmapped_transfer;
315bf215546Sopenharmony_ci      compare_and_perform_action(queue, &iter);
316bf215546Sopenharmony_ci   }
317bf215546Sopenharmony_ci
318bf215546Sopenharmony_ci   add_internal(queue, transfer);
319bf215546Sopenharmony_ci   return 0;
320bf215546Sopenharmony_ci}
321bf215546Sopenharmony_ci
322bf215546Sopenharmony_ciint virgl_transfer_queue_clear(struct virgl_transfer_queue *queue,
323bf215546Sopenharmony_ci                               struct virgl_cmd_buf *cbuf)
324bf215546Sopenharmony_ci{
325bf215546Sopenharmony_ci   struct list_iteration_args iter;
326bf215546Sopenharmony_ci
327bf215546Sopenharmony_ci   memset(&iter, 0, sizeof(iter));
328bf215546Sopenharmony_ci   if (queue->tbuf) {
329bf215546Sopenharmony_ci      uint32_t prior_num_dwords = cbuf->cdw;
330bf215546Sopenharmony_ci      cbuf->cdw = 0;
331bf215546Sopenharmony_ci
332bf215546Sopenharmony_ci      iter.action = transfer_write;
333bf215546Sopenharmony_ci      iter.data = cbuf;
334bf215546Sopenharmony_ci      perform_action(queue, &iter);
335bf215546Sopenharmony_ci
336bf215546Sopenharmony_ci      virgl_encode_end_transfers(cbuf);
337bf215546Sopenharmony_ci      cbuf->cdw = prior_num_dwords;
338bf215546Sopenharmony_ci   } else {
339bf215546Sopenharmony_ci      iter.action = transfer_put;
340bf215546Sopenharmony_ci      perform_action(queue, &iter);
341bf215546Sopenharmony_ci   }
342bf215546Sopenharmony_ci
343bf215546Sopenharmony_ci   queue->num_dwords = 0;
344bf215546Sopenharmony_ci
345bf215546Sopenharmony_ci   return 0;
346bf215546Sopenharmony_ci}
347bf215546Sopenharmony_ci
348bf215546Sopenharmony_cibool virgl_transfer_queue_is_queued(struct virgl_transfer_queue *queue,
349bf215546Sopenharmony_ci                                    struct virgl_transfer *transfer)
350bf215546Sopenharmony_ci{
351bf215546Sopenharmony_ci   return virgl_transfer_queue_find_overlap(queue,
352bf215546Sopenharmony_ci                                            transfer->hw_res,
353bf215546Sopenharmony_ci                                            transfer->base.level,
354bf215546Sopenharmony_ci                                            &transfer->base.box,
355bf215546Sopenharmony_ci                                            false);
356bf215546Sopenharmony_ci}
357bf215546Sopenharmony_ci
358bf215546Sopenharmony_cibool
359bf215546Sopenharmony_civirgl_transfer_queue_extend_buffer(struct virgl_transfer_queue *queue,
360bf215546Sopenharmony_ci                                   const struct virgl_hw_res *hw_res,
361bf215546Sopenharmony_ci                                   unsigned offset, unsigned size,
362bf215546Sopenharmony_ci                                   const void *data)
363bf215546Sopenharmony_ci{
364bf215546Sopenharmony_ci   struct virgl_transfer *queued;
365bf215546Sopenharmony_ci   struct pipe_box box;
366bf215546Sopenharmony_ci
367bf215546Sopenharmony_ci   u_box_1d(offset, size, &box);
368bf215546Sopenharmony_ci   queued = virgl_transfer_queue_find_overlap(queue, hw_res, 0, &box, true);
369bf215546Sopenharmony_ci   if (!queued)
370bf215546Sopenharmony_ci      return false;
371bf215546Sopenharmony_ci
372bf215546Sopenharmony_ci   assert(queued->base.resource->target == PIPE_BUFFER);
373bf215546Sopenharmony_ci   assert(queued->hw_res_map);
374bf215546Sopenharmony_ci
375bf215546Sopenharmony_ci   memcpy(queued->hw_res_map + offset, data, size);
376bf215546Sopenharmony_ci   u_box_union_2d(&queued->base.box, &queued->base.box, &box);
377bf215546Sopenharmony_ci   queued->offset = queued->base.box.x;
378bf215546Sopenharmony_ci
379bf215546Sopenharmony_ci   return true;
380bf215546Sopenharmony_ci}
381