1bf215546Sopenharmony_ci/**************************************************************************
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright 2006 VMware, Inc.
4bf215546Sopenharmony_ci * All Rights Reserved.
5bf215546Sopenharmony_ci *
6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the
8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
12bf215546Sopenharmony_ci * the following conditions:
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the
15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
16bf215546Sopenharmony_ci * of the Software.
17bf215546Sopenharmony_ci *
18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25bf215546Sopenharmony_ci *
26bf215546Sopenharmony_ci **************************************************************************/
27bf215546Sopenharmony_ci /*
28bf215546Sopenharmony_ci  * Authors:
29bf215546Sopenharmony_ci  *   Keith Whitwell <keithw@vmware.com>
30bf215546Sopenharmony_ci  *   Michel Dänzer <daenzer@vmware.com>
31bf215546Sopenharmony_ci  */
32bf215546Sopenharmony_ci
33bf215546Sopenharmony_ci#include <stdio.h>
34bf215546Sopenharmony_ci
35bf215546Sopenharmony_ci#include "pipe/p_context.h"
36bf215546Sopenharmony_ci#include "pipe/p_defines.h"
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_ci#include "util/u_inlines.h"
39bf215546Sopenharmony_ci#include "util/u_cpu_detect.h"
40bf215546Sopenharmony_ci#include "util/format/u_format.h"
41bf215546Sopenharmony_ci#include "util/u_math.h"
42bf215546Sopenharmony_ci#include "util/u_memory.h"
43bf215546Sopenharmony_ci#include "util/u_transfer.h"
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_ci#include "lp_context.h"
46bf215546Sopenharmony_ci#include "lp_flush.h"
47bf215546Sopenharmony_ci#include "lp_screen.h"
48bf215546Sopenharmony_ci#include "lp_texture.h"
49bf215546Sopenharmony_ci#include "lp_setup.h"
50bf215546Sopenharmony_ci#include "lp_state.h"
51bf215546Sopenharmony_ci#include "lp_rast.h"
52bf215546Sopenharmony_ci
53bf215546Sopenharmony_ci#include "frontend/sw_winsys.h"
54bf215546Sopenharmony_ci#include "git_sha1.h"
55bf215546Sopenharmony_ci
56bf215546Sopenharmony_ci#ifndef _WIN32
57bf215546Sopenharmony_ci#include "drm-uapi/drm_fourcc.h"
58bf215546Sopenharmony_ci#endif
59bf215546Sopenharmony_ci
60bf215546Sopenharmony_ci
61bf215546Sopenharmony_ci#ifdef DEBUG
62bf215546Sopenharmony_cistatic struct llvmpipe_resource resource_list;
63bf215546Sopenharmony_cistatic mtx_t resource_list_mutex = _MTX_INITIALIZER_NP;
64bf215546Sopenharmony_ci#endif
65bf215546Sopenharmony_cistatic unsigned id_counter = 0;
66bf215546Sopenharmony_ci
67bf215546Sopenharmony_ci
68bf215546Sopenharmony_ci/**
69bf215546Sopenharmony_ci * Conventional allocation path for non-display textures:
70bf215546Sopenharmony_ci * Compute strides and allocate data (unless asked not to).
71bf215546Sopenharmony_ci */
72bf215546Sopenharmony_cistatic boolean
73bf215546Sopenharmony_cillvmpipe_texture_layout(struct llvmpipe_screen *screen,
74bf215546Sopenharmony_ci                        struct llvmpipe_resource *lpr,
75bf215546Sopenharmony_ci                        boolean allocate)
76bf215546Sopenharmony_ci{
77bf215546Sopenharmony_ci   struct pipe_resource *pt = &lpr->base;
78bf215546Sopenharmony_ci   unsigned level;
79bf215546Sopenharmony_ci   unsigned width = pt->width0;
80bf215546Sopenharmony_ci   unsigned height = pt->height0;
81bf215546Sopenharmony_ci   unsigned depth = pt->depth0;
82bf215546Sopenharmony_ci   uint64_t total_size = 0;
83bf215546Sopenharmony_ci   unsigned layers = pt->array_size;
84bf215546Sopenharmony_ci   unsigned num_samples = util_res_sample_count(pt);
85bf215546Sopenharmony_ci
86bf215546Sopenharmony_ci   /* XXX:
87bf215546Sopenharmony_ci    * This alignment here (same for displaytarget) was added for the purpose of
88bf215546Sopenharmony_ci    * ARB_map_buffer_alignment. I am not convinced it's needed for non-buffer
89bf215546Sopenharmony_ci    * resources. Otherwise we'd want the max of cacheline size and 16 (max size
90bf215546Sopenharmony_ci    * of a block for all formats) though this should not be strictly necessary
91bf215546Sopenharmony_ci    * neither. In any case it can only affect compressed or 1d textures.
92bf215546Sopenharmony_ci    */
93bf215546Sopenharmony_ci   unsigned mip_align = MAX2(64, util_get_cpu_caps()->cacheline);
94bf215546Sopenharmony_ci
95bf215546Sopenharmony_ci   assert(LP_MAX_TEXTURE_2D_LEVELS <= LP_MAX_TEXTURE_LEVELS);
96bf215546Sopenharmony_ci   assert(LP_MAX_TEXTURE_3D_LEVELS <= LP_MAX_TEXTURE_LEVELS);
97bf215546Sopenharmony_ci
98bf215546Sopenharmony_ci   for (level = 0; level <= pt->last_level; level++) {
99bf215546Sopenharmony_ci      uint64_t mipsize;
100bf215546Sopenharmony_ci      unsigned align_x, align_y, nblocksx, nblocksy, block_size, num_slices;
101bf215546Sopenharmony_ci
102bf215546Sopenharmony_ci      /* Row stride and image stride */
103bf215546Sopenharmony_ci
104bf215546Sopenharmony_ci      /* For non-compressed formats we need 4x4 pixel alignment
105bf215546Sopenharmony_ci       * so we can read/write LP_RASTER_BLOCK_SIZE when rendering to them.
106bf215546Sopenharmony_ci       * We also want cache line size in x direction,
107bf215546Sopenharmony_ci       * otherwise same cache line could end up in multiple threads.
108bf215546Sopenharmony_ci       * For explicit 1d resources however we reduce this to 4x1 and
109bf215546Sopenharmony_ci       * handle specially in render output code (as we need to do special
110bf215546Sopenharmony_ci       * handling there for buffers in any case).
111bf215546Sopenharmony_ci       */
112bf215546Sopenharmony_ci      if (util_format_is_compressed(pt->format))
113bf215546Sopenharmony_ci         align_x = align_y = 1;
114bf215546Sopenharmony_ci      else {
115bf215546Sopenharmony_ci         align_x = LP_RASTER_BLOCK_SIZE;
116bf215546Sopenharmony_ci         if (llvmpipe_resource_is_1d(&lpr->base))
117bf215546Sopenharmony_ci            align_y = 1;
118bf215546Sopenharmony_ci         else
119bf215546Sopenharmony_ci            align_y = LP_RASTER_BLOCK_SIZE;
120bf215546Sopenharmony_ci      }
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_ci      nblocksx = util_format_get_nblocksx(pt->format,
123bf215546Sopenharmony_ci                                          align(width, align_x));
124bf215546Sopenharmony_ci      nblocksy = util_format_get_nblocksy(pt->format,
125bf215546Sopenharmony_ci                                          align(height, align_y));
126bf215546Sopenharmony_ci      block_size = util_format_get_blocksize(pt->format);
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_ci      if (util_format_is_compressed(pt->format))
129bf215546Sopenharmony_ci         lpr->row_stride[level] = nblocksx * block_size;
130bf215546Sopenharmony_ci      else
131bf215546Sopenharmony_ci         lpr->row_stride[level] = align(nblocksx * block_size, util_get_cpu_caps()->cacheline);
132bf215546Sopenharmony_ci
133bf215546Sopenharmony_ci      lpr->img_stride[level] = (uint64_t)lpr->row_stride[level] * nblocksy;
134bf215546Sopenharmony_ci
135bf215546Sopenharmony_ci      /* Number of 3D image slices, cube faces or texture array layers */
136bf215546Sopenharmony_ci      if (lpr->base.target == PIPE_TEXTURE_CUBE) {
137bf215546Sopenharmony_ci         assert(layers == 6);
138bf215546Sopenharmony_ci      }
139bf215546Sopenharmony_ci
140bf215546Sopenharmony_ci      if (lpr->base.target == PIPE_TEXTURE_3D)
141bf215546Sopenharmony_ci         num_slices = depth;
142bf215546Sopenharmony_ci      else if (lpr->base.target == PIPE_TEXTURE_1D_ARRAY ||
143bf215546Sopenharmony_ci               lpr->base.target == PIPE_TEXTURE_2D_ARRAY ||
144bf215546Sopenharmony_ci               lpr->base.target == PIPE_TEXTURE_CUBE ||
145bf215546Sopenharmony_ci               lpr->base.target == PIPE_TEXTURE_CUBE_ARRAY)
146bf215546Sopenharmony_ci         num_slices = layers;
147bf215546Sopenharmony_ci      else
148bf215546Sopenharmony_ci         num_slices = 1;
149bf215546Sopenharmony_ci
150bf215546Sopenharmony_ci      mipsize = lpr->img_stride[level] * num_slices;
151bf215546Sopenharmony_ci      lpr->mip_offsets[level] = total_size;
152bf215546Sopenharmony_ci
153bf215546Sopenharmony_ci      total_size += align64(mipsize, mip_align);
154bf215546Sopenharmony_ci
155bf215546Sopenharmony_ci      /* Compute size of next mipmap level */
156bf215546Sopenharmony_ci      width = u_minify(width, 1);
157bf215546Sopenharmony_ci      height = u_minify(height, 1);
158bf215546Sopenharmony_ci      depth = u_minify(depth, 1);
159bf215546Sopenharmony_ci   }
160bf215546Sopenharmony_ci
161bf215546Sopenharmony_ci   lpr->sample_stride = total_size;
162bf215546Sopenharmony_ci   total_size *= num_samples;
163bf215546Sopenharmony_ci
164bf215546Sopenharmony_ci   lpr->size_required = total_size;
165bf215546Sopenharmony_ci   if (allocate) {
166bf215546Sopenharmony_ci      if (total_size > LP_MAX_TEXTURE_SIZE)
167bf215546Sopenharmony_ci         goto fail;
168bf215546Sopenharmony_ci
169bf215546Sopenharmony_ci      lpr->tex_data = align_malloc(total_size, mip_align);
170bf215546Sopenharmony_ci      if (!lpr->tex_data) {
171bf215546Sopenharmony_ci         return FALSE;
172bf215546Sopenharmony_ci      }
173bf215546Sopenharmony_ci      else {
174bf215546Sopenharmony_ci         memset(lpr->tex_data, 0, total_size);
175bf215546Sopenharmony_ci      }
176bf215546Sopenharmony_ci   }
177bf215546Sopenharmony_ci
178bf215546Sopenharmony_ci   return TRUE;
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_cifail:
181bf215546Sopenharmony_ci   return FALSE;
182bf215546Sopenharmony_ci}
183bf215546Sopenharmony_ci
184bf215546Sopenharmony_ci
185bf215546Sopenharmony_ci/**
186bf215546Sopenharmony_ci * Check the size of the texture specified by 'res'.
187bf215546Sopenharmony_ci * \return TRUE if OK, FALSE if too large.
188bf215546Sopenharmony_ci */
189bf215546Sopenharmony_cistatic bool
190bf215546Sopenharmony_cillvmpipe_can_create_resource(struct pipe_screen *screen,
191bf215546Sopenharmony_ci                             const struct pipe_resource *res)
192bf215546Sopenharmony_ci{
193bf215546Sopenharmony_ci   struct llvmpipe_resource lpr;
194bf215546Sopenharmony_ci   memset(&lpr, 0, sizeof(lpr));
195bf215546Sopenharmony_ci   lpr.base = *res;
196bf215546Sopenharmony_ci   if (!llvmpipe_texture_layout(llvmpipe_screen(screen), &lpr, false))
197bf215546Sopenharmony_ci      return false;
198bf215546Sopenharmony_ci
199bf215546Sopenharmony_ci   return lpr.size_required <= LP_MAX_TEXTURE_SIZE;
200bf215546Sopenharmony_ci}
201bf215546Sopenharmony_ci
202bf215546Sopenharmony_ci
203bf215546Sopenharmony_cistatic boolean
204bf215546Sopenharmony_cillvmpipe_displaytarget_layout(struct llvmpipe_screen *screen,
205bf215546Sopenharmony_ci                              struct llvmpipe_resource *lpr,
206bf215546Sopenharmony_ci                              const void *map_front_private)
207bf215546Sopenharmony_ci{
208bf215546Sopenharmony_ci   struct sw_winsys *winsys = screen->winsys;
209bf215546Sopenharmony_ci
210bf215546Sopenharmony_ci   /* Round up the surface size to a multiple of the tile size to
211bf215546Sopenharmony_ci    * avoid tile clipping.
212bf215546Sopenharmony_ci    */
213bf215546Sopenharmony_ci   const unsigned width = MAX2(1, align(lpr->base.width0, TILE_SIZE));
214bf215546Sopenharmony_ci   const unsigned height = MAX2(1, align(lpr->base.height0, TILE_SIZE));
215bf215546Sopenharmony_ci
216bf215546Sopenharmony_ci   lpr->dt = winsys->displaytarget_create(winsys,
217bf215546Sopenharmony_ci                                          lpr->base.bind,
218bf215546Sopenharmony_ci                                          lpr->base.format,
219bf215546Sopenharmony_ci                                          width, height,
220bf215546Sopenharmony_ci                                          64,
221bf215546Sopenharmony_ci                                          map_front_private,
222bf215546Sopenharmony_ci                                          &lpr->row_stride[0] );
223bf215546Sopenharmony_ci
224bf215546Sopenharmony_ci   return lpr->dt != NULL;
225bf215546Sopenharmony_ci}
226bf215546Sopenharmony_ci
227bf215546Sopenharmony_ci
228bf215546Sopenharmony_cistatic struct pipe_resource *
229bf215546Sopenharmony_cillvmpipe_resource_create_all(struct pipe_screen *_screen,
230bf215546Sopenharmony_ci                             const struct pipe_resource *templat,
231bf215546Sopenharmony_ci                             const void *map_front_private, bool alloc_backing)
232bf215546Sopenharmony_ci{
233bf215546Sopenharmony_ci   struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
234bf215546Sopenharmony_ci   struct llvmpipe_resource *lpr = CALLOC_STRUCT(llvmpipe_resource);
235bf215546Sopenharmony_ci   if (!lpr)
236bf215546Sopenharmony_ci      return NULL;
237bf215546Sopenharmony_ci
238bf215546Sopenharmony_ci   lpr->base = *templat;
239bf215546Sopenharmony_ci   lpr->screen = screen;
240bf215546Sopenharmony_ci   pipe_reference_init(&lpr->base.reference, 1);
241bf215546Sopenharmony_ci   lpr->base.screen = &screen->base;
242bf215546Sopenharmony_ci
243bf215546Sopenharmony_ci   /* assert(lpr->base.bind); */
244bf215546Sopenharmony_ci
245bf215546Sopenharmony_ci   if (llvmpipe_resource_is_texture(&lpr->base)) {
246bf215546Sopenharmony_ci      if (lpr->base.bind & (PIPE_BIND_DISPLAY_TARGET |
247bf215546Sopenharmony_ci                            PIPE_BIND_SCANOUT |
248bf215546Sopenharmony_ci                            PIPE_BIND_SHARED)) {
249bf215546Sopenharmony_ci         /* displayable surface */
250bf215546Sopenharmony_ci         if (!llvmpipe_displaytarget_layout(screen, lpr, map_front_private))
251bf215546Sopenharmony_ci            goto fail;
252bf215546Sopenharmony_ci      }
253bf215546Sopenharmony_ci      else {
254bf215546Sopenharmony_ci         /* texture map */
255bf215546Sopenharmony_ci         if (!llvmpipe_texture_layout(screen, lpr, alloc_backing))
256bf215546Sopenharmony_ci            goto fail;
257bf215546Sopenharmony_ci      }
258bf215546Sopenharmony_ci   }
259bf215546Sopenharmony_ci   else {
260bf215546Sopenharmony_ci      /* other data (vertex buffer, const buffer, etc) */
261bf215546Sopenharmony_ci      const uint bytes = templat->width0;
262bf215546Sopenharmony_ci      assert(util_format_get_blocksize(templat->format) == 1);
263bf215546Sopenharmony_ci      assert(templat->height0 == 1);
264bf215546Sopenharmony_ci      assert(templat->depth0 == 1);
265bf215546Sopenharmony_ci      assert(templat->last_level == 0);
266bf215546Sopenharmony_ci      /*
267bf215546Sopenharmony_ci       * Reserve some extra storage since if we'd render to a buffer we
268bf215546Sopenharmony_ci       * read/write always LP_RASTER_BLOCK_SIZE pixels, but the element
269bf215546Sopenharmony_ci       * offset doesn't need to be aligned to LP_RASTER_BLOCK_SIZE.
270bf215546Sopenharmony_ci       */
271bf215546Sopenharmony_ci      /*
272bf215546Sopenharmony_ci       * buffers don't really have stride but it's probably safer
273bf215546Sopenharmony_ci       * (for code doing same calculations for buffers and textures)
274bf215546Sopenharmony_ci       * to put something sane in there.
275bf215546Sopenharmony_ci       */
276bf215546Sopenharmony_ci      lpr->row_stride[0] = bytes;
277bf215546Sopenharmony_ci
278bf215546Sopenharmony_ci      lpr->size_required = bytes;
279bf215546Sopenharmony_ci      if (!(templat->flags & PIPE_RESOURCE_FLAG_DONT_OVER_ALLOCATE))
280bf215546Sopenharmony_ci         lpr->size_required += (LP_RASTER_BLOCK_SIZE - 1) * 4 * sizeof(float);
281bf215546Sopenharmony_ci
282bf215546Sopenharmony_ci      if (alloc_backing) {
283bf215546Sopenharmony_ci         lpr->data = align_malloc(lpr->size_required, 64);
284bf215546Sopenharmony_ci
285bf215546Sopenharmony_ci         if (!lpr->data)
286bf215546Sopenharmony_ci            goto fail;
287bf215546Sopenharmony_ci         memset(lpr->data, 0, bytes);
288bf215546Sopenharmony_ci      }
289bf215546Sopenharmony_ci   }
290bf215546Sopenharmony_ci
291bf215546Sopenharmony_ci   lpr->id = id_counter++;
292bf215546Sopenharmony_ci
293bf215546Sopenharmony_ci#ifdef DEBUG
294bf215546Sopenharmony_ci   mtx_lock(&resource_list_mutex);
295bf215546Sopenharmony_ci   list_addtail(&lpr->list, &resource_list.list);
296bf215546Sopenharmony_ci   mtx_unlock(&resource_list_mutex);
297bf215546Sopenharmony_ci#endif
298bf215546Sopenharmony_ci
299bf215546Sopenharmony_ci   return &lpr->base;
300bf215546Sopenharmony_ci
301bf215546Sopenharmony_ci fail:
302bf215546Sopenharmony_ci   FREE(lpr);
303bf215546Sopenharmony_ci   return NULL;
304bf215546Sopenharmony_ci}
305bf215546Sopenharmony_ci
306bf215546Sopenharmony_cistatic struct pipe_resource *
307bf215546Sopenharmony_cillvmpipe_resource_create_front(struct pipe_screen *_screen,
308bf215546Sopenharmony_ci                               const struct pipe_resource *templat,
309bf215546Sopenharmony_ci                               const void *map_front_private)
310bf215546Sopenharmony_ci{
311bf215546Sopenharmony_ci   return llvmpipe_resource_create_all(_screen, templat, map_front_private, true);
312bf215546Sopenharmony_ci}
313bf215546Sopenharmony_ci
314bf215546Sopenharmony_cistatic struct pipe_resource *
315bf215546Sopenharmony_cillvmpipe_resource_create(struct pipe_screen *_screen,
316bf215546Sopenharmony_ci                         const struct pipe_resource *templat)
317bf215546Sopenharmony_ci{
318bf215546Sopenharmony_ci   return llvmpipe_resource_create_front(_screen, templat, NULL);
319bf215546Sopenharmony_ci}
320bf215546Sopenharmony_ci
321bf215546Sopenharmony_cistatic struct pipe_resource *
322bf215546Sopenharmony_cillvmpipe_resource_create_unbacked(struct pipe_screen *_screen,
323bf215546Sopenharmony_ci                                  const struct pipe_resource *templat,
324bf215546Sopenharmony_ci                                  uint64_t *size_required)
325bf215546Sopenharmony_ci{
326bf215546Sopenharmony_ci   struct pipe_resource *pt;
327bf215546Sopenharmony_ci   struct llvmpipe_resource *lpr;
328bf215546Sopenharmony_ci   pt = llvmpipe_resource_create_all(_screen, templat, NULL, false);
329bf215546Sopenharmony_ci   if (!pt)
330bf215546Sopenharmony_ci      return pt;
331bf215546Sopenharmony_ci   lpr = llvmpipe_resource(pt);
332bf215546Sopenharmony_ci   lpr->backable = true;
333bf215546Sopenharmony_ci   *size_required = lpr->size_required;
334bf215546Sopenharmony_ci   return pt;
335bf215546Sopenharmony_ci}
336bf215546Sopenharmony_ci
337bf215546Sopenharmony_cistatic struct pipe_memory_object *
338bf215546Sopenharmony_cillvmpipe_memobj_create_from_handle(struct pipe_screen *pscreen,
339bf215546Sopenharmony_ci                                   struct winsys_handle *handle,
340bf215546Sopenharmony_ci                                   bool dedicated)
341bf215546Sopenharmony_ci{
342bf215546Sopenharmony_ci#ifdef PIPE_MEMORY_FD
343bf215546Sopenharmony_ci   struct llvmpipe_memory_object *memobj = CALLOC_STRUCT(llvmpipe_memory_object);
344bf215546Sopenharmony_ci
345bf215546Sopenharmony_ci   if (handle->type == WINSYS_HANDLE_TYPE_FD &&
346bf215546Sopenharmony_ci       pscreen->import_memory_fd(pscreen, handle->handle, &memobj->data, &memobj->size)) {
347bf215546Sopenharmony_ci      return &memobj->b;
348bf215546Sopenharmony_ci   }
349bf215546Sopenharmony_ci   free(memobj);
350bf215546Sopenharmony_ci#endif
351bf215546Sopenharmony_ci   return NULL;
352bf215546Sopenharmony_ci}
353bf215546Sopenharmony_ci
354bf215546Sopenharmony_cistatic void
355bf215546Sopenharmony_cillvmpipe_memobj_destroy(struct pipe_screen *pscreen,
356bf215546Sopenharmony_ci                        struct pipe_memory_object *memobj)
357bf215546Sopenharmony_ci{
358bf215546Sopenharmony_ci   if (!memobj)
359bf215546Sopenharmony_ci      return;
360bf215546Sopenharmony_ci   struct llvmpipe_memory_object *lpmo = llvmpipe_memory_object(memobj);
361bf215546Sopenharmony_ci#ifdef PIPE_MEMORY_FD
362bf215546Sopenharmony_ci   pscreen->free_memory_fd(pscreen, lpmo->data);
363bf215546Sopenharmony_ci#endif
364bf215546Sopenharmony_ci   free(lpmo);
365bf215546Sopenharmony_ci}
366bf215546Sopenharmony_ci
367bf215546Sopenharmony_cistatic struct pipe_resource *
368bf215546Sopenharmony_cillvmpipe_resource_from_memobj(struct pipe_screen *pscreen,
369bf215546Sopenharmony_ci                              const struct pipe_resource *templat,
370bf215546Sopenharmony_ci                              struct pipe_memory_object *memobj,
371bf215546Sopenharmony_ci                              uint64_t offset)
372bf215546Sopenharmony_ci{
373bf215546Sopenharmony_ci   if (!memobj)
374bf215546Sopenharmony_ci      return NULL;
375bf215546Sopenharmony_ci   struct llvmpipe_screen *screen = llvmpipe_screen(pscreen);
376bf215546Sopenharmony_ci   struct llvmpipe_memory_object *lpmo = llvmpipe_memory_object(memobj);
377bf215546Sopenharmony_ci   struct llvmpipe_resource *lpr = CALLOC_STRUCT(llvmpipe_resource);
378bf215546Sopenharmony_ci   lpr->base = *templat;
379bf215546Sopenharmony_ci
380bf215546Sopenharmony_ci   lpr->screen = screen;
381bf215546Sopenharmony_ci   pipe_reference_init(&lpr->base.reference, 1);
382bf215546Sopenharmony_ci   lpr->base.screen = &screen->base;
383bf215546Sopenharmony_ci
384bf215546Sopenharmony_ci   if (llvmpipe_resource_is_texture(&lpr->base)) {
385bf215546Sopenharmony_ci      /* texture map */
386bf215546Sopenharmony_ci      if (!llvmpipe_texture_layout(screen, lpr, false))
387bf215546Sopenharmony_ci         goto fail;
388bf215546Sopenharmony_ci      if(lpmo->size < lpr->size_required)
389bf215546Sopenharmony_ci         goto fail;
390bf215546Sopenharmony_ci      lpr->tex_data = lpmo->data;
391bf215546Sopenharmony_ci   }
392bf215546Sopenharmony_ci   else {
393bf215546Sopenharmony_ci      /* other data (vertex buffer, const buffer, etc) */
394bf215546Sopenharmony_ci      const uint bytes = templat->width0;
395bf215546Sopenharmony_ci      assert(util_format_get_blocksize(templat->format) == 1);
396bf215546Sopenharmony_ci      assert(templat->height0 == 1);
397bf215546Sopenharmony_ci      assert(templat->depth0 == 1);
398bf215546Sopenharmony_ci      assert(templat->last_level == 0);
399bf215546Sopenharmony_ci      /*
400bf215546Sopenharmony_ci       * Reserve some extra storage since if we'd render to a buffer we
401bf215546Sopenharmony_ci       * read/write always LP_RASTER_BLOCK_SIZE pixels, but the element
402bf215546Sopenharmony_ci       * offset doesn't need to be aligned to LP_RASTER_BLOCK_SIZE.
403bf215546Sopenharmony_ci       */
404bf215546Sopenharmony_ci      /*
405bf215546Sopenharmony_ci       * buffers don't really have stride but it's probably safer
406bf215546Sopenharmony_ci       * (for code doing same calculations for buffers and textures)
407bf215546Sopenharmony_ci       * to put something reasonable in there.
408bf215546Sopenharmony_ci       */
409bf215546Sopenharmony_ci      lpr->row_stride[0] = bytes;
410bf215546Sopenharmony_ci
411bf215546Sopenharmony_ci      lpr->size_required = bytes;
412bf215546Sopenharmony_ci      if (!(templat->flags & PIPE_RESOURCE_FLAG_DONT_OVER_ALLOCATE))
413bf215546Sopenharmony_ci         lpr->size_required += (LP_RASTER_BLOCK_SIZE - 1) * 4 * sizeof(float);
414bf215546Sopenharmony_ci
415bf215546Sopenharmony_ci      if(lpmo->size < lpr->size_required)
416bf215546Sopenharmony_ci         goto fail;
417bf215546Sopenharmony_ci      lpr->data = lpmo->data;
418bf215546Sopenharmony_ci   }
419bf215546Sopenharmony_ci   lpr->id = id_counter++;
420bf215546Sopenharmony_ci   lpr->imported_memory = true;
421bf215546Sopenharmony_ci
422bf215546Sopenharmony_ci#ifdef DEBUG
423bf215546Sopenharmony_ci   mtx_lock(&resource_list_mutex);
424bf215546Sopenharmony_ci   list_addtail(&lpr->list, &resource_list.list);
425bf215546Sopenharmony_ci   mtx_unlock(&resource_list_mutex);
426bf215546Sopenharmony_ci#endif
427bf215546Sopenharmony_ci
428bf215546Sopenharmony_ci   return &lpr->base;
429bf215546Sopenharmony_ci
430bf215546Sopenharmony_cifail:
431bf215546Sopenharmony_ci   free(lpr);
432bf215546Sopenharmony_ci   return NULL;
433bf215546Sopenharmony_ci}
434bf215546Sopenharmony_ci
435bf215546Sopenharmony_cistatic void
436bf215546Sopenharmony_cillvmpipe_resource_destroy(struct pipe_screen *pscreen,
437bf215546Sopenharmony_ci                          struct pipe_resource *pt)
438bf215546Sopenharmony_ci{
439bf215546Sopenharmony_ci   struct llvmpipe_screen *screen = llvmpipe_screen(pscreen);
440bf215546Sopenharmony_ci   struct llvmpipe_resource *lpr = llvmpipe_resource(pt);
441bf215546Sopenharmony_ci
442bf215546Sopenharmony_ci   if (!lpr->backable && !lpr->user_ptr) {
443bf215546Sopenharmony_ci      if (lpr->dt) {
444bf215546Sopenharmony_ci         /* display target */
445bf215546Sopenharmony_ci         struct sw_winsys *winsys = screen->winsys;
446bf215546Sopenharmony_ci         winsys->displaytarget_destroy(winsys, lpr->dt);
447bf215546Sopenharmony_ci      }
448bf215546Sopenharmony_ci      else if (llvmpipe_resource_is_texture(pt)) {
449bf215546Sopenharmony_ci         /* free linear image data */
450bf215546Sopenharmony_ci         if (lpr->tex_data) {
451bf215546Sopenharmony_ci            if (!lpr->imported_memory)
452bf215546Sopenharmony_ci               align_free(lpr->tex_data);
453bf215546Sopenharmony_ci            lpr->tex_data = NULL;
454bf215546Sopenharmony_ci         }
455bf215546Sopenharmony_ci      }
456bf215546Sopenharmony_ci      else if (lpr->data) {
457bf215546Sopenharmony_ci            if (!lpr->imported_memory)
458bf215546Sopenharmony_ci               align_free(lpr->data);
459bf215546Sopenharmony_ci      }
460bf215546Sopenharmony_ci   }
461bf215546Sopenharmony_ci#ifdef DEBUG
462bf215546Sopenharmony_ci   mtx_lock(&resource_list_mutex);
463bf215546Sopenharmony_ci   if (!list_is_empty(&lpr->list))
464bf215546Sopenharmony_ci      list_del(&lpr->list);
465bf215546Sopenharmony_ci   mtx_unlock(&resource_list_mutex);
466bf215546Sopenharmony_ci#endif
467bf215546Sopenharmony_ci
468bf215546Sopenharmony_ci   FREE(lpr);
469bf215546Sopenharmony_ci}
470bf215546Sopenharmony_ci
471bf215546Sopenharmony_ci
472bf215546Sopenharmony_ci/**
473bf215546Sopenharmony_ci * Map a resource for read/write.
474bf215546Sopenharmony_ci */
475bf215546Sopenharmony_civoid *
476bf215546Sopenharmony_cillvmpipe_resource_map(struct pipe_resource *resource,
477bf215546Sopenharmony_ci                      unsigned level,
478bf215546Sopenharmony_ci                      unsigned layer,
479bf215546Sopenharmony_ci                      enum lp_texture_usage tex_usage)
480bf215546Sopenharmony_ci{
481bf215546Sopenharmony_ci   struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
482bf215546Sopenharmony_ci   uint8_t *map;
483bf215546Sopenharmony_ci
484bf215546Sopenharmony_ci   assert(level < LP_MAX_TEXTURE_LEVELS);
485bf215546Sopenharmony_ci   assert(layer < (u_minify(resource->depth0, level) + resource->array_size - 1));
486bf215546Sopenharmony_ci
487bf215546Sopenharmony_ci   assert(tex_usage == LP_TEX_USAGE_READ ||
488bf215546Sopenharmony_ci          tex_usage == LP_TEX_USAGE_READ_WRITE ||
489bf215546Sopenharmony_ci          tex_usage == LP_TEX_USAGE_WRITE_ALL);
490bf215546Sopenharmony_ci
491bf215546Sopenharmony_ci   if (lpr->dt) {
492bf215546Sopenharmony_ci      /* display target */
493bf215546Sopenharmony_ci      struct llvmpipe_screen *screen = lpr->screen;
494bf215546Sopenharmony_ci      struct sw_winsys *winsys = screen->winsys;
495bf215546Sopenharmony_ci      unsigned dt_usage;
496bf215546Sopenharmony_ci
497bf215546Sopenharmony_ci      if (tex_usage == LP_TEX_USAGE_READ) {
498bf215546Sopenharmony_ci         dt_usage = PIPE_MAP_READ;
499bf215546Sopenharmony_ci      }
500bf215546Sopenharmony_ci      else {
501bf215546Sopenharmony_ci         dt_usage = PIPE_MAP_READ_WRITE;
502bf215546Sopenharmony_ci      }
503bf215546Sopenharmony_ci
504bf215546Sopenharmony_ci      assert(level == 0);
505bf215546Sopenharmony_ci      assert(layer == 0);
506bf215546Sopenharmony_ci
507bf215546Sopenharmony_ci      /* FIXME: keep map count? */
508bf215546Sopenharmony_ci      map = winsys->displaytarget_map(winsys, lpr->dt, dt_usage);
509bf215546Sopenharmony_ci
510bf215546Sopenharmony_ci      /* install this linear image in texture data structure */
511bf215546Sopenharmony_ci      lpr->tex_data = map;
512bf215546Sopenharmony_ci
513bf215546Sopenharmony_ci      return map;
514bf215546Sopenharmony_ci   }
515bf215546Sopenharmony_ci   else if (llvmpipe_resource_is_texture(resource)) {
516bf215546Sopenharmony_ci
517bf215546Sopenharmony_ci      map = llvmpipe_get_texture_image_address(lpr, layer, level);
518bf215546Sopenharmony_ci      return map;
519bf215546Sopenharmony_ci   }
520bf215546Sopenharmony_ci   else {
521bf215546Sopenharmony_ci      return lpr->data;
522bf215546Sopenharmony_ci   }
523bf215546Sopenharmony_ci}
524bf215546Sopenharmony_ci
525bf215546Sopenharmony_ci
526bf215546Sopenharmony_ci/**
527bf215546Sopenharmony_ci * Unmap a resource.
528bf215546Sopenharmony_ci */
529bf215546Sopenharmony_civoid
530bf215546Sopenharmony_cillvmpipe_resource_unmap(struct pipe_resource *resource,
531bf215546Sopenharmony_ci                       unsigned level,
532bf215546Sopenharmony_ci                       unsigned layer)
533bf215546Sopenharmony_ci{
534bf215546Sopenharmony_ci   struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
535bf215546Sopenharmony_ci
536bf215546Sopenharmony_ci   if (lpr->dt) {
537bf215546Sopenharmony_ci      /* display target */
538bf215546Sopenharmony_ci      struct llvmpipe_screen *lp_screen = lpr->screen;
539bf215546Sopenharmony_ci      struct sw_winsys *winsys = lp_screen->winsys;
540bf215546Sopenharmony_ci
541bf215546Sopenharmony_ci      assert(level == 0);
542bf215546Sopenharmony_ci      assert(layer == 0);
543bf215546Sopenharmony_ci
544bf215546Sopenharmony_ci      winsys->displaytarget_unmap(winsys, lpr->dt);
545bf215546Sopenharmony_ci   }
546bf215546Sopenharmony_ci}
547bf215546Sopenharmony_ci
548bf215546Sopenharmony_ci
549bf215546Sopenharmony_civoid *
550bf215546Sopenharmony_cillvmpipe_resource_data(struct pipe_resource *resource)
551bf215546Sopenharmony_ci{
552bf215546Sopenharmony_ci   struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
553bf215546Sopenharmony_ci
554bf215546Sopenharmony_ci   assert(!llvmpipe_resource_is_texture(resource));
555bf215546Sopenharmony_ci
556bf215546Sopenharmony_ci   return lpr->data;
557bf215546Sopenharmony_ci}
558bf215546Sopenharmony_ci
559bf215546Sopenharmony_ci
560bf215546Sopenharmony_cistatic struct pipe_resource *
561bf215546Sopenharmony_cillvmpipe_resource_from_handle(struct pipe_screen *_screen,
562bf215546Sopenharmony_ci                              const struct pipe_resource *template,
563bf215546Sopenharmony_ci                              struct winsys_handle *whandle,
564bf215546Sopenharmony_ci                              unsigned usage)
565bf215546Sopenharmony_ci{
566bf215546Sopenharmony_ci   struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
567bf215546Sopenharmony_ci   struct sw_winsys *winsys = screen->winsys;
568bf215546Sopenharmony_ci   struct llvmpipe_resource *lpr;
569bf215546Sopenharmony_ci
570bf215546Sopenharmony_ci   /* XXX Seems like from_handled depth textures doesn't work that well */
571bf215546Sopenharmony_ci
572bf215546Sopenharmony_ci   lpr = CALLOC_STRUCT(llvmpipe_resource);
573bf215546Sopenharmony_ci   if (!lpr) {
574bf215546Sopenharmony_ci      goto no_lpr;
575bf215546Sopenharmony_ci   }
576bf215546Sopenharmony_ci
577bf215546Sopenharmony_ci   lpr->base = *template;
578bf215546Sopenharmony_ci   lpr->screen = screen;
579bf215546Sopenharmony_ci   pipe_reference_init(&lpr->base.reference, 1);
580bf215546Sopenharmony_ci   lpr->base.screen = _screen;
581bf215546Sopenharmony_ci
582bf215546Sopenharmony_ci   /*
583bf215546Sopenharmony_ci    * Looks like unaligned displaytargets work just fine,
584bf215546Sopenharmony_ci    * at least sampler/render ones.
585bf215546Sopenharmony_ci    */
586bf215546Sopenharmony_ci#if 0
587bf215546Sopenharmony_ci   assert(lpr->base.width0 == width);
588bf215546Sopenharmony_ci   assert(lpr->base.height0 == height);
589bf215546Sopenharmony_ci#endif
590bf215546Sopenharmony_ci
591bf215546Sopenharmony_ci   lpr->dt = winsys->displaytarget_from_handle(winsys,
592bf215546Sopenharmony_ci                                               template,
593bf215546Sopenharmony_ci                                               whandle,
594bf215546Sopenharmony_ci                                               &lpr->row_stride[0]);
595bf215546Sopenharmony_ci   if (!lpr->dt) {
596bf215546Sopenharmony_ci      goto no_dt;
597bf215546Sopenharmony_ci   }
598bf215546Sopenharmony_ci
599bf215546Sopenharmony_ci   lpr->id = id_counter++;
600bf215546Sopenharmony_ci
601bf215546Sopenharmony_ci#ifdef DEBUG
602bf215546Sopenharmony_ci   mtx_lock(&resource_list_mutex);
603bf215546Sopenharmony_ci   list_addtail(&lpr->list, &resource_list.list);
604bf215546Sopenharmony_ci   mtx_unlock(&resource_list_mutex);
605bf215546Sopenharmony_ci#endif
606bf215546Sopenharmony_ci
607bf215546Sopenharmony_ci   return &lpr->base;
608bf215546Sopenharmony_ci
609bf215546Sopenharmony_cino_dt:
610bf215546Sopenharmony_ci   FREE(lpr);
611bf215546Sopenharmony_cino_lpr:
612bf215546Sopenharmony_ci   return NULL;
613bf215546Sopenharmony_ci}
614bf215546Sopenharmony_ci
615bf215546Sopenharmony_ci
616bf215546Sopenharmony_cistatic bool
617bf215546Sopenharmony_cillvmpipe_resource_get_handle(struct pipe_screen *screen,
618bf215546Sopenharmony_ci                             struct pipe_context *ctx,
619bf215546Sopenharmony_ci                            struct pipe_resource *pt,
620bf215546Sopenharmony_ci                            struct winsys_handle *whandle,
621bf215546Sopenharmony_ci                             unsigned usage)
622bf215546Sopenharmony_ci{
623bf215546Sopenharmony_ci   struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys;
624bf215546Sopenharmony_ci   struct llvmpipe_resource *lpr = llvmpipe_resource(pt);
625bf215546Sopenharmony_ci
626bf215546Sopenharmony_ci   assert(lpr->dt);
627bf215546Sopenharmony_ci   if (!lpr->dt)
628bf215546Sopenharmony_ci      return false;
629bf215546Sopenharmony_ci
630bf215546Sopenharmony_ci   return winsys->displaytarget_get_handle(winsys, lpr->dt, whandle);
631bf215546Sopenharmony_ci}
632bf215546Sopenharmony_ci
633bf215546Sopenharmony_cistatic struct pipe_resource *
634bf215546Sopenharmony_cillvmpipe_resource_from_user_memory(struct pipe_screen *_screen,
635bf215546Sopenharmony_ci				   const struct pipe_resource *resource,
636bf215546Sopenharmony_ci				   void *user_memory)
637bf215546Sopenharmony_ci{
638bf215546Sopenharmony_ci   struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
639bf215546Sopenharmony_ci   struct llvmpipe_resource *lpr;
640bf215546Sopenharmony_ci
641bf215546Sopenharmony_ci   lpr = CALLOC_STRUCT(llvmpipe_resource);
642bf215546Sopenharmony_ci   if (!lpr) {
643bf215546Sopenharmony_ci      return NULL;
644bf215546Sopenharmony_ci   }
645bf215546Sopenharmony_ci
646bf215546Sopenharmony_ci   lpr->base = *resource;
647bf215546Sopenharmony_ci   lpr->screen = screen;
648bf215546Sopenharmony_ci   pipe_reference_init(&lpr->base.reference, 1);
649bf215546Sopenharmony_ci   lpr->base.screen = _screen;
650bf215546Sopenharmony_ci
651bf215546Sopenharmony_ci   if (llvmpipe_resource_is_texture(&lpr->base)) {
652bf215546Sopenharmony_ci      if (!llvmpipe_texture_layout(screen, lpr, false))
653bf215546Sopenharmony_ci         goto fail;
654bf215546Sopenharmony_ci
655bf215546Sopenharmony_ci      lpr->tex_data = user_memory;
656bf215546Sopenharmony_ci   } else
657bf215546Sopenharmony_ci      lpr->data = user_memory;
658bf215546Sopenharmony_ci   lpr->user_ptr = true;
659bf215546Sopenharmony_ci#ifdef DEBUG
660bf215546Sopenharmony_ci   mtx_lock(&resource_list_mutex);
661bf215546Sopenharmony_ci   list_addtail(&lpr->list, &resource_list.list);
662bf215546Sopenharmony_ci   mtx_unlock(&resource_list_mutex);
663bf215546Sopenharmony_ci#endif
664bf215546Sopenharmony_ci   return &lpr->base;
665bf215546Sopenharmony_cifail:
666bf215546Sopenharmony_ci   FREE(lpr);
667bf215546Sopenharmony_ci   return NULL;
668bf215546Sopenharmony_ci}
669bf215546Sopenharmony_ci
670bf215546Sopenharmony_civoid *
671bf215546Sopenharmony_cillvmpipe_transfer_map_ms( struct pipe_context *pipe,
672bf215546Sopenharmony_ci                          struct pipe_resource *resource,
673bf215546Sopenharmony_ci                          unsigned level,
674bf215546Sopenharmony_ci                          unsigned usage,
675bf215546Sopenharmony_ci                          unsigned sample,
676bf215546Sopenharmony_ci                          const struct pipe_box *box,
677bf215546Sopenharmony_ci                          struct pipe_transfer **transfer )
678bf215546Sopenharmony_ci{
679bf215546Sopenharmony_ci   struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
680bf215546Sopenharmony_ci   struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen);
681bf215546Sopenharmony_ci   struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
682bf215546Sopenharmony_ci   struct llvmpipe_transfer *lpt;
683bf215546Sopenharmony_ci   struct pipe_transfer *pt;
684bf215546Sopenharmony_ci   ubyte *map;
685bf215546Sopenharmony_ci   enum pipe_format format;
686bf215546Sopenharmony_ci   enum lp_texture_usage tex_usage;
687bf215546Sopenharmony_ci   const char *mode;
688bf215546Sopenharmony_ci
689bf215546Sopenharmony_ci   assert(resource);
690bf215546Sopenharmony_ci   assert(level <= resource->last_level);
691bf215546Sopenharmony_ci
692bf215546Sopenharmony_ci   /*
693bf215546Sopenharmony_ci    * Transfers, like other pipe operations, must happen in order, so flush the
694bf215546Sopenharmony_ci    * context if necessary.
695bf215546Sopenharmony_ci    */
696bf215546Sopenharmony_ci   if (!(usage & PIPE_MAP_UNSYNCHRONIZED)) {
697bf215546Sopenharmony_ci      boolean read_only = !(usage & PIPE_MAP_WRITE);
698bf215546Sopenharmony_ci      boolean do_not_block = !!(usage & PIPE_MAP_DONTBLOCK);
699bf215546Sopenharmony_ci      if (!llvmpipe_flush_resource(pipe, resource,
700bf215546Sopenharmony_ci                                   level,
701bf215546Sopenharmony_ci                                   read_only,
702bf215546Sopenharmony_ci                                   TRUE, /* cpu_access */
703bf215546Sopenharmony_ci                                   do_not_block,
704bf215546Sopenharmony_ci                                   __FUNCTION__)) {
705bf215546Sopenharmony_ci         /*
706bf215546Sopenharmony_ci          * It would have blocked, but gallium frontend requested no to.
707bf215546Sopenharmony_ci          */
708bf215546Sopenharmony_ci         assert(do_not_block);
709bf215546Sopenharmony_ci         return NULL;
710bf215546Sopenharmony_ci      }
711bf215546Sopenharmony_ci   }
712bf215546Sopenharmony_ci
713bf215546Sopenharmony_ci   /* Check if we're mapping a current constant buffer */
714bf215546Sopenharmony_ci   if ((usage & PIPE_MAP_WRITE) &&
715bf215546Sopenharmony_ci       (resource->bind & PIPE_BIND_CONSTANT_BUFFER)) {
716bf215546Sopenharmony_ci      unsigned i;
717bf215546Sopenharmony_ci      for (i = 0; i < ARRAY_SIZE(llvmpipe->constants[PIPE_SHADER_FRAGMENT]); ++i) {
718bf215546Sopenharmony_ci         if (resource == llvmpipe->constants[PIPE_SHADER_FRAGMENT][i].buffer) {
719bf215546Sopenharmony_ci            /* constants may have changed */
720bf215546Sopenharmony_ci            llvmpipe->dirty |= LP_NEW_FS_CONSTANTS;
721bf215546Sopenharmony_ci            break;
722bf215546Sopenharmony_ci         }
723bf215546Sopenharmony_ci      }
724bf215546Sopenharmony_ci   }
725bf215546Sopenharmony_ci
726bf215546Sopenharmony_ci   lpt = CALLOC_STRUCT(llvmpipe_transfer);
727bf215546Sopenharmony_ci   if (!lpt)
728bf215546Sopenharmony_ci      return NULL;
729bf215546Sopenharmony_ci   pt = &lpt->base;
730bf215546Sopenharmony_ci   pipe_resource_reference(&pt->resource, resource);
731bf215546Sopenharmony_ci   pt->box = *box;
732bf215546Sopenharmony_ci   pt->level = level;
733bf215546Sopenharmony_ci   pt->stride = lpr->row_stride[level];
734bf215546Sopenharmony_ci   pt->layer_stride = lpr->img_stride[level];
735bf215546Sopenharmony_ci   pt->usage = usage;
736bf215546Sopenharmony_ci   *transfer = pt;
737bf215546Sopenharmony_ci
738bf215546Sopenharmony_ci   assert(level < LP_MAX_TEXTURE_LEVELS);
739bf215546Sopenharmony_ci
740bf215546Sopenharmony_ci   /*
741bf215546Sopenharmony_ci   printf("tex_transfer_map(%d, %d  %d x %d of %d x %d,  usage %d )\n",
742bf215546Sopenharmony_ci          transfer->x, transfer->y, transfer->width, transfer->height,
743bf215546Sopenharmony_ci          transfer->texture->width0,
744bf215546Sopenharmony_ci          transfer->texture->height0,
745bf215546Sopenharmony_ci          transfer->usage);
746bf215546Sopenharmony_ci   */
747bf215546Sopenharmony_ci
748bf215546Sopenharmony_ci   if (usage == PIPE_MAP_READ) {
749bf215546Sopenharmony_ci      tex_usage = LP_TEX_USAGE_READ;
750bf215546Sopenharmony_ci      mode = "read";
751bf215546Sopenharmony_ci   }
752bf215546Sopenharmony_ci   else {
753bf215546Sopenharmony_ci      tex_usage = LP_TEX_USAGE_READ_WRITE;
754bf215546Sopenharmony_ci      mode = "read/write";
755bf215546Sopenharmony_ci   }
756bf215546Sopenharmony_ci
757bf215546Sopenharmony_ci   if (0) {
758bf215546Sopenharmony_ci      printf("transfer map tex %u  mode %s\n", lpr->id, mode);
759bf215546Sopenharmony_ci   }
760bf215546Sopenharmony_ci
761bf215546Sopenharmony_ci   format = lpr->base.format;
762bf215546Sopenharmony_ci
763bf215546Sopenharmony_ci   map = llvmpipe_resource_map(resource,
764bf215546Sopenharmony_ci                               level,
765bf215546Sopenharmony_ci                               box->z,
766bf215546Sopenharmony_ci                               tex_usage);
767bf215546Sopenharmony_ci
768bf215546Sopenharmony_ci
769bf215546Sopenharmony_ci   /* May want to do different things here depending on read/write nature
770bf215546Sopenharmony_ci    * of the map:
771bf215546Sopenharmony_ci    */
772bf215546Sopenharmony_ci   if (usage & PIPE_MAP_WRITE) {
773bf215546Sopenharmony_ci      /* Do something to notify sharing contexts of a texture change.
774bf215546Sopenharmony_ci       */
775bf215546Sopenharmony_ci      screen->timestamp++;
776bf215546Sopenharmony_ci   }
777bf215546Sopenharmony_ci
778bf215546Sopenharmony_ci   map +=
779bf215546Sopenharmony_ci      box->y / util_format_get_blockheight(format) * pt->stride +
780bf215546Sopenharmony_ci      box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
781bf215546Sopenharmony_ci
782bf215546Sopenharmony_ci   map += sample * lpr->sample_stride;
783bf215546Sopenharmony_ci   return map;
784bf215546Sopenharmony_ci}
785bf215546Sopenharmony_ci
786bf215546Sopenharmony_cistatic void *
787bf215546Sopenharmony_cillvmpipe_transfer_map( struct pipe_context *pipe,
788bf215546Sopenharmony_ci                       struct pipe_resource *resource,
789bf215546Sopenharmony_ci                       unsigned level,
790bf215546Sopenharmony_ci                       unsigned usage,
791bf215546Sopenharmony_ci                       const struct pipe_box *box,
792bf215546Sopenharmony_ci                       struct pipe_transfer **transfer )
793bf215546Sopenharmony_ci{
794bf215546Sopenharmony_ci   return llvmpipe_transfer_map_ms(pipe, resource, level, usage, 0, box, transfer);
795bf215546Sopenharmony_ci}
796bf215546Sopenharmony_ci
797bf215546Sopenharmony_cistatic void
798bf215546Sopenharmony_cillvmpipe_transfer_unmap(struct pipe_context *pipe,
799bf215546Sopenharmony_ci                        struct pipe_transfer *transfer)
800bf215546Sopenharmony_ci{
801bf215546Sopenharmony_ci   assert(transfer->resource);
802bf215546Sopenharmony_ci
803bf215546Sopenharmony_ci   llvmpipe_resource_unmap(transfer->resource,
804bf215546Sopenharmony_ci                           transfer->level,
805bf215546Sopenharmony_ci                           transfer->box.z);
806bf215546Sopenharmony_ci
807bf215546Sopenharmony_ci   /* Effectively do the texture_update work here - if texture images
808bf215546Sopenharmony_ci    * needed post-processing to put them into hardware layout, this is
809bf215546Sopenharmony_ci    * where it would happen.  For llvmpipe, nothing to do.
810bf215546Sopenharmony_ci    */
811bf215546Sopenharmony_ci   assert (transfer->resource);
812bf215546Sopenharmony_ci   pipe_resource_reference(&transfer->resource, NULL);
813bf215546Sopenharmony_ci   FREE(transfer);
814bf215546Sopenharmony_ci}
815bf215546Sopenharmony_ci
816bf215546Sopenharmony_ciunsigned int
817bf215546Sopenharmony_cillvmpipe_is_resource_referenced( struct pipe_context *pipe,
818bf215546Sopenharmony_ci                                 struct pipe_resource *presource,
819bf215546Sopenharmony_ci                                 unsigned level)
820bf215546Sopenharmony_ci{
821bf215546Sopenharmony_ci   struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
822bf215546Sopenharmony_ci   if (!(presource->bind & (PIPE_BIND_DEPTH_STENCIL |
823bf215546Sopenharmony_ci                            PIPE_BIND_RENDER_TARGET |
824bf215546Sopenharmony_ci                            PIPE_BIND_SAMPLER_VIEW |
825bf215546Sopenharmony_ci                            PIPE_BIND_SHADER_BUFFER |
826bf215546Sopenharmony_ci                            PIPE_BIND_SHADER_IMAGE)))
827bf215546Sopenharmony_ci      return LP_UNREFERENCED;
828bf215546Sopenharmony_ci
829bf215546Sopenharmony_ci   return lp_setup_is_resource_referenced(llvmpipe->setup, presource);
830bf215546Sopenharmony_ci}
831bf215546Sopenharmony_ci
832bf215546Sopenharmony_ci
833bf215546Sopenharmony_ci/**
834bf215546Sopenharmony_ci * Returns the largest possible alignment for a format in llvmpipe
835bf215546Sopenharmony_ci */
836bf215546Sopenharmony_ciunsigned
837bf215546Sopenharmony_cillvmpipe_get_format_alignment( enum pipe_format format )
838bf215546Sopenharmony_ci{
839bf215546Sopenharmony_ci   const struct util_format_description *desc = util_format_description(format);
840bf215546Sopenharmony_ci   unsigned size = 0;
841bf215546Sopenharmony_ci   unsigned bytes;
842bf215546Sopenharmony_ci   unsigned i;
843bf215546Sopenharmony_ci
844bf215546Sopenharmony_ci   for (i = 0; i < desc->nr_channels; ++i) {
845bf215546Sopenharmony_ci      size += desc->channel[i].size;
846bf215546Sopenharmony_ci   }
847bf215546Sopenharmony_ci
848bf215546Sopenharmony_ci   bytes = size / 8;
849bf215546Sopenharmony_ci
850bf215546Sopenharmony_ci   if (!util_is_power_of_two_or_zero(bytes)) {
851bf215546Sopenharmony_ci      bytes /= desc->nr_channels;
852bf215546Sopenharmony_ci   }
853bf215546Sopenharmony_ci
854bf215546Sopenharmony_ci   if (bytes % 2 || bytes < 1) {
855bf215546Sopenharmony_ci      return 1;
856bf215546Sopenharmony_ci   } else {
857bf215546Sopenharmony_ci      return bytes;
858bf215546Sopenharmony_ci   }
859bf215546Sopenharmony_ci}
860bf215546Sopenharmony_ci
861bf215546Sopenharmony_ci
862bf215546Sopenharmony_ci/**
863bf215546Sopenharmony_ci * Create buffer which wraps user-space data.
864bf215546Sopenharmony_ci * XXX unreachable.
865bf215546Sopenharmony_ci */
866bf215546Sopenharmony_cistruct pipe_resource *
867bf215546Sopenharmony_cillvmpipe_user_buffer_create(struct pipe_screen *screen,
868bf215546Sopenharmony_ci                            void *ptr,
869bf215546Sopenharmony_ci                            unsigned bytes,
870bf215546Sopenharmony_ci                            unsigned bind_flags)
871bf215546Sopenharmony_ci{
872bf215546Sopenharmony_ci   struct llvmpipe_resource *buffer;
873bf215546Sopenharmony_ci
874bf215546Sopenharmony_ci   buffer = CALLOC_STRUCT(llvmpipe_resource);
875bf215546Sopenharmony_ci   if (!buffer)
876bf215546Sopenharmony_ci      return NULL;
877bf215546Sopenharmony_ci
878bf215546Sopenharmony_ci   buffer->screen = llvmpipe_screen(screen);
879bf215546Sopenharmony_ci   pipe_reference_init(&buffer->base.reference, 1);
880bf215546Sopenharmony_ci   buffer->base.screen = screen;
881bf215546Sopenharmony_ci   buffer->base.format = PIPE_FORMAT_R8_UNORM; /* ?? */
882bf215546Sopenharmony_ci   buffer->base.bind = bind_flags;
883bf215546Sopenharmony_ci   buffer->base.usage = PIPE_USAGE_IMMUTABLE;
884bf215546Sopenharmony_ci   buffer->base.flags = 0;
885bf215546Sopenharmony_ci   buffer->base.width0 = bytes;
886bf215546Sopenharmony_ci   buffer->base.height0 = 1;
887bf215546Sopenharmony_ci   buffer->base.depth0 = 1;
888bf215546Sopenharmony_ci   buffer->base.array_size = 1;
889bf215546Sopenharmony_ci   buffer->user_ptr = true;
890bf215546Sopenharmony_ci   buffer->data = ptr;
891bf215546Sopenharmony_ci
892bf215546Sopenharmony_ci   return &buffer->base;
893bf215546Sopenharmony_ci}
894bf215546Sopenharmony_ci
895bf215546Sopenharmony_ci
896bf215546Sopenharmony_ci/**
897bf215546Sopenharmony_ci * Compute size (in bytes) need to store a texture image / mipmap level,
898bf215546Sopenharmony_ci * for just one cube face, one array layer or one 3D texture slice
899bf215546Sopenharmony_ci */
900bf215546Sopenharmony_cistatic unsigned
901bf215546Sopenharmony_citex_image_face_size(const struct llvmpipe_resource *lpr, unsigned level)
902bf215546Sopenharmony_ci{
903bf215546Sopenharmony_ci   return lpr->img_stride[level];
904bf215546Sopenharmony_ci}
905bf215546Sopenharmony_ci
906bf215546Sopenharmony_ci
907bf215546Sopenharmony_ci/**
908bf215546Sopenharmony_ci * Return pointer to a 2D texture image/face/slice.
909bf215546Sopenharmony_ci * No tiled/linear conversion is done.
910bf215546Sopenharmony_ci */
911bf215546Sopenharmony_ciubyte *
912bf215546Sopenharmony_cillvmpipe_get_texture_image_address(struct llvmpipe_resource *lpr,
913bf215546Sopenharmony_ci                                   unsigned face_slice, unsigned level)
914bf215546Sopenharmony_ci{
915bf215546Sopenharmony_ci   unsigned offset;
916bf215546Sopenharmony_ci
917bf215546Sopenharmony_ci   assert(llvmpipe_resource_is_texture(&lpr->base));
918bf215546Sopenharmony_ci
919bf215546Sopenharmony_ci   offset = lpr->mip_offsets[level];
920bf215546Sopenharmony_ci
921bf215546Sopenharmony_ci   if (face_slice > 0)
922bf215546Sopenharmony_ci      offset += face_slice * tex_image_face_size(lpr, level);
923bf215546Sopenharmony_ci
924bf215546Sopenharmony_ci   return (ubyte *) lpr->tex_data + offset;
925bf215546Sopenharmony_ci}
926bf215546Sopenharmony_ci
927bf215546Sopenharmony_ci
928bf215546Sopenharmony_ci/**
929bf215546Sopenharmony_ci * Return size of resource in bytes
930bf215546Sopenharmony_ci */
931bf215546Sopenharmony_ciunsigned
932bf215546Sopenharmony_cillvmpipe_resource_size(const struct pipe_resource *resource)
933bf215546Sopenharmony_ci{
934bf215546Sopenharmony_ci   const struct llvmpipe_resource *lpr = llvmpipe_resource_const(resource);
935bf215546Sopenharmony_ci   unsigned size = 0;
936bf215546Sopenharmony_ci
937bf215546Sopenharmony_ci   if (llvmpipe_resource_is_texture(resource)) {
938bf215546Sopenharmony_ci      /* Note this will always return 0 for displaytarget resources */
939bf215546Sopenharmony_ci      size = lpr->total_alloc_size;
940bf215546Sopenharmony_ci   }
941bf215546Sopenharmony_ci   else {
942bf215546Sopenharmony_ci      size = resource->width0;
943bf215546Sopenharmony_ci   }
944bf215546Sopenharmony_ci   return size;
945bf215546Sopenharmony_ci}
946bf215546Sopenharmony_ci
947bf215546Sopenharmony_cistatic void
948bf215546Sopenharmony_cillvmpipe_memory_barrier(struct pipe_context *pipe,
949bf215546Sopenharmony_ci			unsigned flags)
950bf215546Sopenharmony_ci{
951bf215546Sopenharmony_ci   /* this may be an overly large hammer for this nut. */
952bf215546Sopenharmony_ci   llvmpipe_finish(pipe, "barrier");
953bf215546Sopenharmony_ci}
954bf215546Sopenharmony_ci
955bf215546Sopenharmony_cistatic struct pipe_memory_allocation *llvmpipe_allocate_memory(struct pipe_screen *screen, uint64_t size)
956bf215546Sopenharmony_ci{
957bf215546Sopenharmony_ci   uint64_t alignment;
958bf215546Sopenharmony_ci   if (!os_get_page_size(&alignment))
959bf215546Sopenharmony_ci      alignment = 256;
960bf215546Sopenharmony_ci   return os_malloc_aligned(size, alignment);
961bf215546Sopenharmony_ci}
962bf215546Sopenharmony_ci
963bf215546Sopenharmony_cistatic void llvmpipe_free_memory(struct pipe_screen *screen,
964bf215546Sopenharmony_ci                                 struct pipe_memory_allocation *pmem)
965bf215546Sopenharmony_ci{
966bf215546Sopenharmony_ci   os_free_aligned(pmem);
967bf215546Sopenharmony_ci}
968bf215546Sopenharmony_ci
969bf215546Sopenharmony_ci#ifdef PIPE_MEMORY_FD
970bf215546Sopenharmony_ci
971bf215546Sopenharmony_cistatic const char *driver_id = "llvmpipe" MESA_GIT_SHA1;
972bf215546Sopenharmony_ci
973bf215546Sopenharmony_cistatic struct pipe_memory_allocation *llvmpipe_allocate_memory_fd(struct pipe_screen *screen, uint64_t size, int *fd)
974bf215546Sopenharmony_ci{
975bf215546Sopenharmony_ci   uint64_t alignment;
976bf215546Sopenharmony_ci   if (!os_get_page_size(&alignment))
977bf215546Sopenharmony_ci      alignment = 256;
978bf215546Sopenharmony_ci   return os_malloc_aligned_fd(size, alignment, fd, "llvmpipe memory fd", driver_id);
979bf215546Sopenharmony_ci}
980bf215546Sopenharmony_ci
981bf215546Sopenharmony_cistatic bool llvmpipe_import_memory_fd(struct pipe_screen *screen, int fd, struct pipe_memory_allocation **ptr, uint64_t *size)
982bf215546Sopenharmony_ci{
983bf215546Sopenharmony_ci   return os_import_memory_fd(fd, (void**)ptr, size, driver_id);
984bf215546Sopenharmony_ci}
985bf215546Sopenharmony_ci
986bf215546Sopenharmony_cistatic void llvmpipe_free_memory_fd(struct pipe_screen *screen,
987bf215546Sopenharmony_ci                                    struct pipe_memory_allocation *pmem)
988bf215546Sopenharmony_ci{
989bf215546Sopenharmony_ci   os_free_fd(pmem);
990bf215546Sopenharmony_ci}
991bf215546Sopenharmony_ci
992bf215546Sopenharmony_ci#endif
993bf215546Sopenharmony_ci
994bf215546Sopenharmony_cistatic bool llvmpipe_resource_bind_backing(struct pipe_screen *screen,
995bf215546Sopenharmony_ci                                           struct pipe_resource *pt,
996bf215546Sopenharmony_ci                                           struct pipe_memory_allocation *pmem,
997bf215546Sopenharmony_ci                                           uint64_t offset)
998bf215546Sopenharmony_ci{
999bf215546Sopenharmony_ci   struct llvmpipe_resource *lpr = llvmpipe_resource(pt);
1000bf215546Sopenharmony_ci
1001bf215546Sopenharmony_ci   if (!lpr->backable)
1002bf215546Sopenharmony_ci      return FALSE;
1003bf215546Sopenharmony_ci
1004bf215546Sopenharmony_ci   if (llvmpipe_resource_is_texture(&lpr->base)) {
1005bf215546Sopenharmony_ci      if (lpr->size_required > LP_MAX_TEXTURE_SIZE)
1006bf215546Sopenharmony_ci         return FALSE;
1007bf215546Sopenharmony_ci
1008bf215546Sopenharmony_ci      lpr->tex_data = (char *)pmem + offset;
1009bf215546Sopenharmony_ci   } else
1010bf215546Sopenharmony_ci      lpr->data = (char *)pmem + offset;
1011bf215546Sopenharmony_ci   lpr->backing_offset = offset;
1012bf215546Sopenharmony_ci
1013bf215546Sopenharmony_ci   return TRUE;
1014bf215546Sopenharmony_ci}
1015bf215546Sopenharmony_ci
1016bf215546Sopenharmony_cistatic void *llvmpipe_map_memory(struct pipe_screen *screen,
1017bf215546Sopenharmony_ci                                 struct pipe_memory_allocation *pmem)
1018bf215546Sopenharmony_ci{
1019bf215546Sopenharmony_ci   return pmem;
1020bf215546Sopenharmony_ci}
1021bf215546Sopenharmony_ci
1022bf215546Sopenharmony_cistatic void llvmpipe_unmap_memory(struct pipe_screen *screen,
1023bf215546Sopenharmony_ci                                  struct pipe_memory_allocation *pmem)
1024bf215546Sopenharmony_ci{
1025bf215546Sopenharmony_ci}
1026bf215546Sopenharmony_ci
1027bf215546Sopenharmony_ci#ifdef DEBUG
1028bf215546Sopenharmony_civoid
1029bf215546Sopenharmony_cillvmpipe_print_resources(void)
1030bf215546Sopenharmony_ci{
1031bf215546Sopenharmony_ci   struct llvmpipe_resource *lpr;
1032bf215546Sopenharmony_ci   unsigned n = 0, total = 0;
1033bf215546Sopenharmony_ci
1034bf215546Sopenharmony_ci   debug_printf("LLVMPIPE: current resources:\n");
1035bf215546Sopenharmony_ci   mtx_lock(&resource_list_mutex);
1036bf215546Sopenharmony_ci   LIST_FOR_EACH_ENTRY(lpr, &resource_list.list, list) {
1037bf215546Sopenharmony_ci      unsigned size = llvmpipe_resource_size(&lpr->base);
1038bf215546Sopenharmony_ci      debug_printf("resource %u at %p, size %ux%ux%u: %u bytes, refcount %u\n",
1039bf215546Sopenharmony_ci                   lpr->id, (void *) lpr,
1040bf215546Sopenharmony_ci                   lpr->base.width0, lpr->base.height0, lpr->base.depth0,
1041bf215546Sopenharmony_ci                   size, lpr->base.reference.count);
1042bf215546Sopenharmony_ci      total += size;
1043bf215546Sopenharmony_ci      n++;
1044bf215546Sopenharmony_ci   }
1045bf215546Sopenharmony_ci   mtx_unlock(&resource_list_mutex);
1046bf215546Sopenharmony_ci   debug_printf("LLVMPIPE: total size of %u resources: %u\n", n, total);
1047bf215546Sopenharmony_ci}
1048bf215546Sopenharmony_ci#endif
1049bf215546Sopenharmony_ci
1050bf215546Sopenharmony_cistatic void
1051bf215546Sopenharmony_cillvmpipe_get_resource_info(struct pipe_screen *screen,
1052bf215546Sopenharmony_ci			   struct pipe_resource *resource,
1053bf215546Sopenharmony_ci			   unsigned *stride,
1054bf215546Sopenharmony_ci			   unsigned *offset)
1055bf215546Sopenharmony_ci{
1056bf215546Sopenharmony_ci   struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
1057bf215546Sopenharmony_ci
1058bf215546Sopenharmony_ci   *stride = lpr->row_stride[0];
1059bf215546Sopenharmony_ci   *offset = 0;
1060bf215546Sopenharmony_ci}
1061bf215546Sopenharmony_ci
1062bf215546Sopenharmony_cistatic bool
1063bf215546Sopenharmony_cillvmpipe_resource_get_param(struct pipe_screen *screen,
1064bf215546Sopenharmony_ci                            struct pipe_context *context,
1065bf215546Sopenharmony_ci                            struct pipe_resource *resource,
1066bf215546Sopenharmony_ci                            unsigned plane,
1067bf215546Sopenharmony_ci                            unsigned layer,
1068bf215546Sopenharmony_ci                            unsigned level,
1069bf215546Sopenharmony_ci                            enum pipe_resource_param param,
1070bf215546Sopenharmony_ci                            unsigned handle_usage,
1071bf215546Sopenharmony_ci                            uint64_t *value)
1072bf215546Sopenharmony_ci{
1073bf215546Sopenharmony_ci   struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
1074bf215546Sopenharmony_ci   struct winsys_handle whandle;
1075bf215546Sopenharmony_ci
1076bf215546Sopenharmony_ci   switch (param) {
1077bf215546Sopenharmony_ci   case PIPE_RESOURCE_PARAM_NPLANES:
1078bf215546Sopenharmony_ci      *value = 1;
1079bf215546Sopenharmony_ci      return true;
1080bf215546Sopenharmony_ci   case PIPE_RESOURCE_PARAM_STRIDE:
1081bf215546Sopenharmony_ci      *value = lpr->row_stride[level];
1082bf215546Sopenharmony_ci      return true;
1083bf215546Sopenharmony_ci   case PIPE_RESOURCE_PARAM_OFFSET:
1084bf215546Sopenharmony_ci      *value = lpr->mip_offsets[level] + (lpr->img_stride[level] * layer);
1085bf215546Sopenharmony_ci      return true;
1086bf215546Sopenharmony_ci   case PIPE_RESOURCE_PARAM_LAYER_STRIDE:
1087bf215546Sopenharmony_ci      *value = lpr->img_stride[level];
1088bf215546Sopenharmony_ci      return true;
1089bf215546Sopenharmony_ci#ifndef _WIN32
1090bf215546Sopenharmony_ci   case PIPE_RESOURCE_PARAM_MODIFIER:
1091bf215546Sopenharmony_ci      *value = DRM_FORMAT_MOD_INVALID;
1092bf215546Sopenharmony_ci      return true;
1093bf215546Sopenharmony_ci#endif
1094bf215546Sopenharmony_ci   case PIPE_RESOURCE_PARAM_HANDLE_TYPE_SHARED:
1095bf215546Sopenharmony_ci   case PIPE_RESOURCE_PARAM_HANDLE_TYPE_KMS:
1096bf215546Sopenharmony_ci   case PIPE_RESOURCE_PARAM_HANDLE_TYPE_FD:
1097bf215546Sopenharmony_ci      if (!lpr->dt)
1098bf215546Sopenharmony_ci         return false;
1099bf215546Sopenharmony_ci
1100bf215546Sopenharmony_ci      memset(&whandle, 0, sizeof(whandle));
1101bf215546Sopenharmony_ci      if (param == PIPE_RESOURCE_PARAM_HANDLE_TYPE_SHARED)
1102bf215546Sopenharmony_ci         whandle.type = WINSYS_HANDLE_TYPE_SHARED;
1103bf215546Sopenharmony_ci      else if (param == PIPE_RESOURCE_PARAM_HANDLE_TYPE_KMS)
1104bf215546Sopenharmony_ci         whandle.type = WINSYS_HANDLE_TYPE_KMS;
1105bf215546Sopenharmony_ci      else if (param == PIPE_RESOURCE_PARAM_HANDLE_TYPE_FD)
1106bf215546Sopenharmony_ci         whandle.type = WINSYS_HANDLE_TYPE_FD;
1107bf215546Sopenharmony_ci
1108bf215546Sopenharmony_ci      if (!llvmpipe_resource_get_handle(screen, context, resource, &whandle, handle_usage))
1109bf215546Sopenharmony_ci         return false;
1110bf215546Sopenharmony_ci      *value = (uint64_t)(uintptr_t)whandle.handle;
1111bf215546Sopenharmony_ci      return true;
1112bf215546Sopenharmony_ci   default:
1113bf215546Sopenharmony_ci      break;
1114bf215546Sopenharmony_ci   }
1115bf215546Sopenharmony_ci   assert(0);
1116bf215546Sopenharmony_ci   *value = 0;
1117bf215546Sopenharmony_ci   return false;
1118bf215546Sopenharmony_ci}
1119bf215546Sopenharmony_ci
1120bf215546Sopenharmony_civoid
1121bf215546Sopenharmony_cillvmpipe_init_screen_resource_funcs(struct pipe_screen *screen)
1122bf215546Sopenharmony_ci{
1123bf215546Sopenharmony_ci#ifdef DEBUG
1124bf215546Sopenharmony_ci   /* init linked list for tracking resources */
1125bf215546Sopenharmony_ci   {
1126bf215546Sopenharmony_ci      static boolean first_call = TRUE;
1127bf215546Sopenharmony_ci      if (first_call) {
1128bf215546Sopenharmony_ci         memset(&resource_list, 0, sizeof(resource_list));
1129bf215546Sopenharmony_ci         list_inithead(&resource_list.list);
1130bf215546Sopenharmony_ci         first_call = FALSE;
1131bf215546Sopenharmony_ci      }
1132bf215546Sopenharmony_ci   }
1133bf215546Sopenharmony_ci#endif
1134bf215546Sopenharmony_ci
1135bf215546Sopenharmony_ci   screen->resource_create = llvmpipe_resource_create;
1136bf215546Sopenharmony_ci/*   screen->resource_create_front = llvmpipe_resource_create_front; */
1137bf215546Sopenharmony_ci   screen->resource_destroy = llvmpipe_resource_destroy;
1138bf215546Sopenharmony_ci   screen->resource_from_handle = llvmpipe_resource_from_handle;
1139bf215546Sopenharmony_ci   screen->resource_from_memobj = llvmpipe_resource_from_memobj;
1140bf215546Sopenharmony_ci   screen->resource_get_handle = llvmpipe_resource_get_handle;
1141bf215546Sopenharmony_ci   screen->can_create_resource = llvmpipe_can_create_resource;
1142bf215546Sopenharmony_ci
1143bf215546Sopenharmony_ci   screen->resource_create_unbacked = llvmpipe_resource_create_unbacked;
1144bf215546Sopenharmony_ci
1145bf215546Sopenharmony_ci   screen->memobj_create_from_handle = llvmpipe_memobj_create_from_handle;
1146bf215546Sopenharmony_ci   screen->memobj_destroy = llvmpipe_memobj_destroy;
1147bf215546Sopenharmony_ci
1148bf215546Sopenharmony_ci   screen->resource_get_info = llvmpipe_get_resource_info;
1149bf215546Sopenharmony_ci   screen->resource_get_param = llvmpipe_resource_get_param;
1150bf215546Sopenharmony_ci   screen->resource_from_user_memory = llvmpipe_resource_from_user_memory;
1151bf215546Sopenharmony_ci   screen->allocate_memory = llvmpipe_allocate_memory;
1152bf215546Sopenharmony_ci   screen->free_memory = llvmpipe_free_memory;
1153bf215546Sopenharmony_ci#ifdef PIPE_MEMORY_FD
1154bf215546Sopenharmony_ci   screen->allocate_memory_fd = llvmpipe_allocate_memory_fd;
1155bf215546Sopenharmony_ci   screen->import_memory_fd = llvmpipe_import_memory_fd;
1156bf215546Sopenharmony_ci   screen->free_memory_fd = llvmpipe_free_memory_fd;
1157bf215546Sopenharmony_ci#endif
1158bf215546Sopenharmony_ci   screen->map_memory = llvmpipe_map_memory;
1159bf215546Sopenharmony_ci   screen->unmap_memory = llvmpipe_unmap_memory;
1160bf215546Sopenharmony_ci
1161bf215546Sopenharmony_ci   screen->resource_bind_backing = llvmpipe_resource_bind_backing;
1162bf215546Sopenharmony_ci}
1163bf215546Sopenharmony_ci
1164bf215546Sopenharmony_ci
1165bf215546Sopenharmony_civoid
1166bf215546Sopenharmony_cillvmpipe_init_context_resource_funcs(struct pipe_context *pipe)
1167bf215546Sopenharmony_ci{
1168bf215546Sopenharmony_ci   pipe->buffer_map = llvmpipe_transfer_map;
1169bf215546Sopenharmony_ci   pipe->buffer_unmap = llvmpipe_transfer_unmap;
1170bf215546Sopenharmony_ci   pipe->texture_map = llvmpipe_transfer_map;
1171bf215546Sopenharmony_ci   pipe->texture_unmap = llvmpipe_transfer_unmap;
1172bf215546Sopenharmony_ci
1173bf215546Sopenharmony_ci   pipe->transfer_flush_region = u_default_transfer_flush_region;
1174bf215546Sopenharmony_ci   pipe->buffer_subdata = u_default_buffer_subdata;
1175bf215546Sopenharmony_ci   pipe->texture_subdata = u_default_texture_subdata;
1176bf215546Sopenharmony_ci
1177bf215546Sopenharmony_ci   pipe->memory_barrier = llvmpipe_memory_barrier;
1178bf215546Sopenharmony_ci}
1179