1848b8605Smrg/**************************************************************************
2848b8605Smrg *
3848b8605Smrg * Copyright 2006 VMware, Inc.
4848b8605Smrg * All Rights Reserved.
5848b8605Smrg *
6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
7848b8605Smrg * copy of this software and associated documentation files (the
8848b8605Smrg * "Software"), to deal in the Software without restriction, including
9848b8605Smrg * without limitation the rights to use, copy, modify, merge, publish,
10848b8605Smrg * distribute, sub license, and/or sell copies of the Software, and to
11848b8605Smrg * permit persons to whom the Software is furnished to do so, subject to
12848b8605Smrg * the following conditions:
13848b8605Smrg *
14848b8605Smrg * The above copyright notice and this permission notice (including the
15848b8605Smrg * next paragraph) shall be included in all copies or substantial portions
16848b8605Smrg * of the Software.
17848b8605Smrg *
18848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20848b8605Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21848b8605Smrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22848b8605Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23848b8605Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24848b8605Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25848b8605Smrg *
26848b8605Smrg **************************************************************************/
27848b8605Smrg /*
28848b8605Smrg  * Authors:
29848b8605Smrg  *   Keith Whitwell <keithw@vmware.com>
30848b8605Smrg  *   Michel Dänzer <daenzer@vmware.com>
31848b8605Smrg  */
32848b8605Smrg
33848b8605Smrg#include <stdio.h>
34848b8605Smrg
35848b8605Smrg#include "pipe/p_context.h"
36848b8605Smrg#include "pipe/p_defines.h"
37848b8605Smrg
38848b8605Smrg#include "util/u_inlines.h"
39848b8605Smrg#include "util/u_cpu_detect.h"
40848b8605Smrg#include "util/u_format.h"
41848b8605Smrg#include "util/u_math.h"
42848b8605Smrg#include "util/u_memory.h"
43b8e80941Smrg#include "util/simple_list.h"
44848b8605Smrg#include "util/u_transfer.h"
45848b8605Smrg
46848b8605Smrg#include "lp_context.h"
47848b8605Smrg#include "lp_flush.h"
48848b8605Smrg#include "lp_screen.h"
49848b8605Smrg#include "lp_texture.h"
50848b8605Smrg#include "lp_setup.h"
51848b8605Smrg#include "lp_state.h"
52848b8605Smrg#include "lp_rast.h"
53848b8605Smrg
54848b8605Smrg#include "state_tracker/sw_winsys.h"
55848b8605Smrg
56848b8605Smrg
57848b8605Smrg#ifdef DEBUG
58848b8605Smrgstatic struct llvmpipe_resource resource_list;
59848b8605Smrg#endif
60848b8605Smrgstatic unsigned id_counter = 0;
61848b8605Smrg
62848b8605Smrg
63848b8605Smrg/**
64848b8605Smrg * Conventional allocation path for non-display textures:
65848b8605Smrg * Compute strides and allocate data (unless asked not to).
66848b8605Smrg */
67848b8605Smrgstatic boolean
68848b8605Smrgllvmpipe_texture_layout(struct llvmpipe_screen *screen,
69848b8605Smrg                        struct llvmpipe_resource *lpr,
70848b8605Smrg                        boolean allocate)
71848b8605Smrg{
72848b8605Smrg   struct pipe_resource *pt = &lpr->base;
73848b8605Smrg   unsigned level;
74848b8605Smrg   unsigned width = pt->width0;
75848b8605Smrg   unsigned height = pt->height0;
76848b8605Smrg   unsigned depth = pt->depth0;
77848b8605Smrg   uint64_t total_size = 0;
78848b8605Smrg   unsigned layers = pt->array_size;
79848b8605Smrg   /* XXX:
80848b8605Smrg    * This alignment here (same for displaytarget) was added for the purpose of
81848b8605Smrg    * ARB_map_buffer_alignment. I am not convinced it's needed for non-buffer
82848b8605Smrg    * resources. Otherwise we'd want the max of cacheline size and 16 (max size
83848b8605Smrg    * of a block for all formats) though this should not be strictly necessary
84848b8605Smrg    * neither. In any case it can only affect compressed or 1d textures.
85848b8605Smrg    */
86848b8605Smrg   unsigned mip_align = MAX2(64, util_cpu_caps.cacheline);
87848b8605Smrg
88848b8605Smrg   assert(LP_MAX_TEXTURE_2D_LEVELS <= LP_MAX_TEXTURE_LEVELS);
89848b8605Smrg   assert(LP_MAX_TEXTURE_3D_LEVELS <= LP_MAX_TEXTURE_LEVELS);
90848b8605Smrg
91848b8605Smrg   for (level = 0; level <= pt->last_level; level++) {
92848b8605Smrg      uint64_t mipsize;
93848b8605Smrg      unsigned align_x, align_y, nblocksx, nblocksy, block_size, num_slices;
94848b8605Smrg
95848b8605Smrg      /* Row stride and image stride */
96848b8605Smrg
97848b8605Smrg      /* For non-compressed formats we need 4x4 pixel alignment
98848b8605Smrg       * so we can read/write LP_RASTER_BLOCK_SIZE when rendering to them.
99848b8605Smrg       * We also want cache line size in x direction,
100848b8605Smrg       * otherwise same cache line could end up in multiple threads.
101848b8605Smrg       * For explicit 1d resources however we reduce this to 4x1 and
102848b8605Smrg       * handle specially in render output code (as we need to do special
103848b8605Smrg       * handling there for buffers in any case).
104848b8605Smrg       */
105848b8605Smrg      if (util_format_is_compressed(pt->format))
106848b8605Smrg         align_x = align_y = 1;
107848b8605Smrg      else {
108848b8605Smrg         align_x = LP_RASTER_BLOCK_SIZE;
109848b8605Smrg         if (llvmpipe_resource_is_1d(&lpr->base))
110848b8605Smrg            align_y = 1;
111848b8605Smrg         else
112848b8605Smrg            align_y = LP_RASTER_BLOCK_SIZE;
113848b8605Smrg      }
114848b8605Smrg
115848b8605Smrg      nblocksx = util_format_get_nblocksx(pt->format,
116848b8605Smrg                                          align(width, align_x));
117848b8605Smrg      nblocksy = util_format_get_nblocksy(pt->format,
118848b8605Smrg                                          align(height, align_y));
119848b8605Smrg      block_size = util_format_get_blocksize(pt->format);
120848b8605Smrg
121848b8605Smrg      if (util_format_is_compressed(pt->format))
122848b8605Smrg         lpr->row_stride[level] = nblocksx * block_size;
123848b8605Smrg      else
124848b8605Smrg         lpr->row_stride[level] = align(nblocksx * block_size, util_cpu_caps.cacheline);
125848b8605Smrg
126848b8605Smrg      /* if row_stride * height > LP_MAX_TEXTURE_SIZE */
127848b8605Smrg      if ((uint64_t)lpr->row_stride[level] * nblocksy > LP_MAX_TEXTURE_SIZE) {
128848b8605Smrg         /* image too large */
129848b8605Smrg         goto fail;
130848b8605Smrg      }
131848b8605Smrg
132848b8605Smrg      lpr->img_stride[level] = lpr->row_stride[level] * nblocksy;
133848b8605Smrg
134848b8605Smrg      /* Number of 3D image slices, cube faces or texture array layers */
135b8e80941Smrg      if (lpr->base.target == PIPE_TEXTURE_CUBE) {
136b8e80941Smrg         assert(layers == 6);
137b8e80941Smrg      }
138b8e80941Smrg
139b8e80941Smrg      if (lpr->base.target == PIPE_TEXTURE_3D)
140848b8605Smrg         num_slices = depth;
141848b8605Smrg      else if (lpr->base.target == PIPE_TEXTURE_1D_ARRAY ||
142848b8605Smrg               lpr->base.target == PIPE_TEXTURE_2D_ARRAY ||
143b8e80941Smrg               lpr->base.target == PIPE_TEXTURE_CUBE ||
144848b8605Smrg               lpr->base.target == PIPE_TEXTURE_CUBE_ARRAY)
145848b8605Smrg         num_slices = layers;
146848b8605Smrg      else
147848b8605Smrg         num_slices = 1;
148848b8605Smrg
149848b8605Smrg      /* if img_stride * num_slices_faces > LP_MAX_TEXTURE_SIZE */
150848b8605Smrg      mipsize = (uint64_t)lpr->img_stride[level] * num_slices;
151848b8605Smrg      if (mipsize > LP_MAX_TEXTURE_SIZE) {
152848b8605Smrg         /* volume too large */
153848b8605Smrg         goto fail;
154848b8605Smrg      }
155848b8605Smrg
156848b8605Smrg      lpr->mip_offsets[level] = total_size;
157848b8605Smrg
158848b8605Smrg      total_size += align((unsigned)mipsize, mip_align);
159848b8605Smrg      if (total_size > LP_MAX_TEXTURE_SIZE) {
160848b8605Smrg         goto fail;
161848b8605Smrg      }
162848b8605Smrg
163848b8605Smrg      /* Compute size of next mipmap level */
164848b8605Smrg      width = u_minify(width, 1);
165848b8605Smrg      height = u_minify(height, 1);
166848b8605Smrg      depth = u_minify(depth, 1);
167848b8605Smrg   }
168848b8605Smrg
169848b8605Smrg   if (allocate) {
170848b8605Smrg      lpr->tex_data = align_malloc(total_size, mip_align);
171848b8605Smrg      if (!lpr->tex_data) {
172848b8605Smrg         return FALSE;
173848b8605Smrg      }
174848b8605Smrg      else {
175848b8605Smrg         memset(lpr->tex_data, 0, total_size);
176848b8605Smrg      }
177848b8605Smrg   }
178848b8605Smrg
179848b8605Smrg   return TRUE;
180848b8605Smrg
181848b8605Smrgfail:
182848b8605Smrg   return FALSE;
183848b8605Smrg}
184848b8605Smrg
185848b8605Smrg
186848b8605Smrg/**
187848b8605Smrg * Check the size of the texture specified by 'res'.
188848b8605Smrg * \return TRUE if OK, FALSE if too large.
189848b8605Smrg */
190848b8605Smrgstatic boolean
191848b8605Smrgllvmpipe_can_create_resource(struct pipe_screen *screen,
192848b8605Smrg                             const struct pipe_resource *res)
193848b8605Smrg{
194848b8605Smrg   struct llvmpipe_resource lpr;
195848b8605Smrg   memset(&lpr, 0, sizeof(lpr));
196848b8605Smrg   lpr.base = *res;
197848b8605Smrg   return llvmpipe_texture_layout(llvmpipe_screen(screen), &lpr, false);
198848b8605Smrg}
199848b8605Smrg
200848b8605Smrg
201848b8605Smrgstatic boolean
202848b8605Smrgllvmpipe_displaytarget_layout(struct llvmpipe_screen *screen,
203b8e80941Smrg                              struct llvmpipe_resource *lpr,
204b8e80941Smrg                              const void *map_front_private)
205848b8605Smrg{
206848b8605Smrg   struct sw_winsys *winsys = screen->winsys;
207848b8605Smrg
208848b8605Smrg   /* Round up the surface size to a multiple of the tile size to
209848b8605Smrg    * avoid tile clipping.
210848b8605Smrg    */
211848b8605Smrg   const unsigned width = MAX2(1, align(lpr->base.width0, TILE_SIZE));
212848b8605Smrg   const unsigned height = MAX2(1, align(lpr->base.height0, TILE_SIZE));
213848b8605Smrg
214848b8605Smrg   lpr->dt = winsys->displaytarget_create(winsys,
215848b8605Smrg                                          lpr->base.bind,
216848b8605Smrg                                          lpr->base.format,
217848b8605Smrg                                          width, height,
218848b8605Smrg                                          64,
219b8e80941Smrg                                          map_front_private,
220848b8605Smrg                                          &lpr->row_stride[0] );
221848b8605Smrg
222848b8605Smrg   if (lpr->dt == NULL)
223848b8605Smrg      return FALSE;
224848b8605Smrg
225b8e80941Smrg   if (!map_front_private) {
226848b8605Smrg      void *map = winsys->displaytarget_map(winsys, lpr->dt,
227848b8605Smrg                                            PIPE_TRANSFER_WRITE);
228848b8605Smrg
229848b8605Smrg      if (map)
230848b8605Smrg         memset(map, 0, height * lpr->row_stride[0]);
231848b8605Smrg
232848b8605Smrg      winsys->displaytarget_unmap(winsys, lpr->dt);
233848b8605Smrg   }
234848b8605Smrg
235848b8605Smrg   return TRUE;
236848b8605Smrg}
237848b8605Smrg
238848b8605Smrg
239848b8605Smrgstatic struct pipe_resource *
240b8e80941Smrgllvmpipe_resource_create_front(struct pipe_screen *_screen,
241b8e80941Smrg                               const struct pipe_resource *templat,
242b8e80941Smrg                               const void *map_front_private)
243848b8605Smrg{
244848b8605Smrg   struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
245848b8605Smrg   struct llvmpipe_resource *lpr = CALLOC_STRUCT(llvmpipe_resource);
246848b8605Smrg   if (!lpr)
247848b8605Smrg      return NULL;
248848b8605Smrg
249848b8605Smrg   lpr->base = *templat;
250848b8605Smrg   pipe_reference_init(&lpr->base.reference, 1);
251848b8605Smrg   lpr->base.screen = &screen->base;
252848b8605Smrg
253848b8605Smrg   /* assert(lpr->base.bind); */
254848b8605Smrg
255848b8605Smrg   if (llvmpipe_resource_is_texture(&lpr->base)) {
256848b8605Smrg      if (lpr->base.bind & (PIPE_BIND_DISPLAY_TARGET |
257848b8605Smrg                            PIPE_BIND_SCANOUT |
258848b8605Smrg                            PIPE_BIND_SHARED)) {
259848b8605Smrg         /* displayable surface */
260b8e80941Smrg         if (!llvmpipe_displaytarget_layout(screen, lpr, map_front_private))
261848b8605Smrg            goto fail;
262848b8605Smrg      }
263848b8605Smrg      else {
264848b8605Smrg         /* texture map */
265848b8605Smrg         if (!llvmpipe_texture_layout(screen, lpr, true))
266848b8605Smrg            goto fail;
267848b8605Smrg      }
268848b8605Smrg   }
269848b8605Smrg   else {
270848b8605Smrg      /* other data (vertex buffer, const buffer, etc) */
271848b8605Smrg      const uint bytes = templat->width0;
272848b8605Smrg      assert(util_format_get_blocksize(templat->format) == 1);
273848b8605Smrg      assert(templat->height0 == 1);
274848b8605Smrg      assert(templat->depth0 == 1);
275848b8605Smrg      assert(templat->last_level == 0);
276848b8605Smrg      /*
277848b8605Smrg       * Reserve some extra storage since if we'd render to a buffer we
278848b8605Smrg       * read/write always LP_RASTER_BLOCK_SIZE pixels, but the element
279848b8605Smrg       * offset doesn't need to be aligned to LP_RASTER_BLOCK_SIZE.
280848b8605Smrg       */
281848b8605Smrg      lpr->data = align_malloc(bytes + (LP_RASTER_BLOCK_SIZE - 1) * 4 * sizeof(float), 64);
282848b8605Smrg
283848b8605Smrg      /*
284848b8605Smrg       * buffers don't really have stride but it's probably safer
285848b8605Smrg       * (for code doing same calculations for buffers and textures)
286848b8605Smrg       * to put something sane in there.
287848b8605Smrg       */
288848b8605Smrg      lpr->row_stride[0] = bytes;
289848b8605Smrg      if (!lpr->data)
290848b8605Smrg         goto fail;
291848b8605Smrg      memset(lpr->data, 0, bytes);
292848b8605Smrg   }
293848b8605Smrg
294848b8605Smrg   lpr->id = id_counter++;
295848b8605Smrg
296848b8605Smrg#ifdef DEBUG
297848b8605Smrg   insert_at_tail(&resource_list, lpr);
298848b8605Smrg#endif
299848b8605Smrg
300848b8605Smrg   return &lpr->base;
301848b8605Smrg
302848b8605Smrg fail:
303848b8605Smrg   FREE(lpr);
304848b8605Smrg   return NULL;
305848b8605Smrg}
306848b8605Smrg
307848b8605Smrg
308b8e80941Smrgstatic struct pipe_resource *
309b8e80941Smrgllvmpipe_resource_create(struct pipe_screen *_screen,
310b8e80941Smrg                         const struct pipe_resource *templat)
311b8e80941Smrg{
312b8e80941Smrg   return llvmpipe_resource_create_front(_screen, templat, NULL);
313b8e80941Smrg}
314b8e80941Smrg
315b8e80941Smrg
316848b8605Smrgstatic void
317848b8605Smrgllvmpipe_resource_destroy(struct pipe_screen *pscreen,
318848b8605Smrg                          struct pipe_resource *pt)
319848b8605Smrg{
320848b8605Smrg   struct llvmpipe_screen *screen = llvmpipe_screen(pscreen);
321848b8605Smrg   struct llvmpipe_resource *lpr = llvmpipe_resource(pt);
322848b8605Smrg
323848b8605Smrg   if (lpr->dt) {
324848b8605Smrg      /* display target */
325848b8605Smrg      struct sw_winsys *winsys = screen->winsys;
326848b8605Smrg      winsys->displaytarget_destroy(winsys, lpr->dt);
327848b8605Smrg   }
328848b8605Smrg   else if (llvmpipe_resource_is_texture(pt)) {
329848b8605Smrg      /* free linear image data */
330848b8605Smrg      if (lpr->tex_data) {
331848b8605Smrg         align_free(lpr->tex_data);
332848b8605Smrg         lpr->tex_data = NULL;
333848b8605Smrg      }
334848b8605Smrg   }
335848b8605Smrg   else if (!lpr->userBuffer) {
336848b8605Smrg      assert(lpr->data);
337848b8605Smrg      align_free(lpr->data);
338848b8605Smrg   }
339848b8605Smrg
340848b8605Smrg#ifdef DEBUG
341848b8605Smrg   if (lpr->next)
342848b8605Smrg      remove_from_list(lpr);
343848b8605Smrg#endif
344848b8605Smrg
345848b8605Smrg   FREE(lpr);
346848b8605Smrg}
347848b8605Smrg
348848b8605Smrg
349848b8605Smrg/**
350848b8605Smrg * Map a resource for read/write.
351848b8605Smrg */
352848b8605Smrgvoid *
353848b8605Smrgllvmpipe_resource_map(struct pipe_resource *resource,
354848b8605Smrg                      unsigned level,
355848b8605Smrg                      unsigned layer,
356848b8605Smrg                      enum lp_texture_usage tex_usage)
357848b8605Smrg{
358848b8605Smrg   struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
359848b8605Smrg   uint8_t *map;
360848b8605Smrg
361848b8605Smrg   assert(level < LP_MAX_TEXTURE_LEVELS);
362848b8605Smrg   assert(layer < (u_minify(resource->depth0, level) + resource->array_size - 1));
363848b8605Smrg
364848b8605Smrg   assert(tex_usage == LP_TEX_USAGE_READ ||
365848b8605Smrg          tex_usage == LP_TEX_USAGE_READ_WRITE ||
366848b8605Smrg          tex_usage == LP_TEX_USAGE_WRITE_ALL);
367848b8605Smrg
368848b8605Smrg   if (lpr->dt) {
369848b8605Smrg      /* display target */
370848b8605Smrg      struct llvmpipe_screen *screen = llvmpipe_screen(resource->screen);
371848b8605Smrg      struct sw_winsys *winsys = screen->winsys;
372848b8605Smrg      unsigned dt_usage;
373848b8605Smrg
374848b8605Smrg      if (tex_usage == LP_TEX_USAGE_READ) {
375848b8605Smrg         dt_usage = PIPE_TRANSFER_READ;
376848b8605Smrg      }
377848b8605Smrg      else {
378848b8605Smrg         dt_usage = PIPE_TRANSFER_READ_WRITE;
379848b8605Smrg      }
380848b8605Smrg
381848b8605Smrg      assert(level == 0);
382848b8605Smrg      assert(layer == 0);
383848b8605Smrg
384848b8605Smrg      /* FIXME: keep map count? */
385848b8605Smrg      map = winsys->displaytarget_map(winsys, lpr->dt, dt_usage);
386848b8605Smrg
387848b8605Smrg      /* install this linear image in texture data structure */
388848b8605Smrg      lpr->tex_data = map;
389848b8605Smrg
390848b8605Smrg      return map;
391848b8605Smrg   }
392848b8605Smrg   else if (llvmpipe_resource_is_texture(resource)) {
393848b8605Smrg
394848b8605Smrg      map = llvmpipe_get_texture_image_address(lpr, layer, level);
395848b8605Smrg      return map;
396848b8605Smrg   }
397848b8605Smrg   else {
398848b8605Smrg      return lpr->data;
399848b8605Smrg   }
400848b8605Smrg}
401848b8605Smrg
402848b8605Smrg
403848b8605Smrg/**
404848b8605Smrg * Unmap a resource.
405848b8605Smrg */
406848b8605Smrgvoid
407848b8605Smrgllvmpipe_resource_unmap(struct pipe_resource *resource,
408848b8605Smrg                       unsigned level,
409848b8605Smrg                       unsigned layer)
410848b8605Smrg{
411848b8605Smrg   struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
412848b8605Smrg
413848b8605Smrg   if (lpr->dt) {
414848b8605Smrg      /* display target */
415848b8605Smrg      struct llvmpipe_screen *lp_screen = llvmpipe_screen(resource->screen);
416848b8605Smrg      struct sw_winsys *winsys = lp_screen->winsys;
417848b8605Smrg
418848b8605Smrg      assert(level == 0);
419848b8605Smrg      assert(layer == 0);
420848b8605Smrg
421848b8605Smrg      winsys->displaytarget_unmap(winsys, lpr->dt);
422848b8605Smrg   }
423848b8605Smrg}
424848b8605Smrg
425848b8605Smrg
426848b8605Smrgvoid *
427848b8605Smrgllvmpipe_resource_data(struct pipe_resource *resource)
428848b8605Smrg{
429848b8605Smrg   struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
430848b8605Smrg
431848b8605Smrg   assert(!llvmpipe_resource_is_texture(resource));
432848b8605Smrg
433848b8605Smrg   return lpr->data;
434848b8605Smrg}
435848b8605Smrg
436848b8605Smrg
437848b8605Smrgstatic struct pipe_resource *
438848b8605Smrgllvmpipe_resource_from_handle(struct pipe_screen *screen,
439848b8605Smrg                              const struct pipe_resource *template,
440b8e80941Smrg                              struct winsys_handle *whandle,
441b8e80941Smrg                              unsigned usage)
442848b8605Smrg{
443848b8605Smrg   struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys;
444848b8605Smrg   struct llvmpipe_resource *lpr;
445848b8605Smrg
446848b8605Smrg   /* XXX Seems like from_handled depth textures doesn't work that well */
447848b8605Smrg
448848b8605Smrg   lpr = CALLOC_STRUCT(llvmpipe_resource);
449848b8605Smrg   if (!lpr) {
450848b8605Smrg      goto no_lpr;
451848b8605Smrg   }
452848b8605Smrg
453848b8605Smrg   lpr->base = *template;
454848b8605Smrg   pipe_reference_init(&lpr->base.reference, 1);
455848b8605Smrg   lpr->base.screen = screen;
456848b8605Smrg
457848b8605Smrg   /*
458848b8605Smrg    * Looks like unaligned displaytargets work just fine,
459848b8605Smrg    * at least sampler/render ones.
460848b8605Smrg    */
461848b8605Smrg#if 0
462848b8605Smrg   assert(lpr->base.width0 == width);
463848b8605Smrg   assert(lpr->base.height0 == height);
464848b8605Smrg#endif
465848b8605Smrg
466848b8605Smrg   lpr->dt = winsys->displaytarget_from_handle(winsys,
467848b8605Smrg                                               template,
468848b8605Smrg                                               whandle,
469848b8605Smrg                                               &lpr->row_stride[0]);
470848b8605Smrg   if (!lpr->dt) {
471848b8605Smrg      goto no_dt;
472848b8605Smrg   }
473848b8605Smrg
474848b8605Smrg   lpr->id = id_counter++;
475848b8605Smrg
476848b8605Smrg#ifdef DEBUG
477848b8605Smrg   insert_at_tail(&resource_list, lpr);
478848b8605Smrg#endif
479848b8605Smrg
480848b8605Smrg   return &lpr->base;
481848b8605Smrg
482848b8605Smrgno_dt:
483848b8605Smrg   FREE(lpr);
484848b8605Smrgno_lpr:
485848b8605Smrg   return NULL;
486848b8605Smrg}
487848b8605Smrg
488848b8605Smrg
489848b8605Smrgstatic boolean
490848b8605Smrgllvmpipe_resource_get_handle(struct pipe_screen *screen,
491b8e80941Smrg                             struct pipe_context *ctx,
492848b8605Smrg                            struct pipe_resource *pt,
493b8e80941Smrg                            struct winsys_handle *whandle,
494b8e80941Smrg                             unsigned usage)
495848b8605Smrg{
496848b8605Smrg   struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys;
497848b8605Smrg   struct llvmpipe_resource *lpr = llvmpipe_resource(pt);
498848b8605Smrg
499848b8605Smrg   assert(lpr->dt);
500848b8605Smrg   if (!lpr->dt)
501848b8605Smrg      return FALSE;
502848b8605Smrg
503848b8605Smrg   return winsys->displaytarget_get_handle(winsys, lpr->dt, whandle);
504848b8605Smrg}
505848b8605Smrg
506848b8605Smrg
507848b8605Smrgstatic void *
508848b8605Smrgllvmpipe_transfer_map( struct pipe_context *pipe,
509848b8605Smrg                       struct pipe_resource *resource,
510848b8605Smrg                       unsigned level,
511848b8605Smrg                       unsigned usage,
512848b8605Smrg                       const struct pipe_box *box,
513848b8605Smrg                       struct pipe_transfer **transfer )
514848b8605Smrg{
515848b8605Smrg   struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
516848b8605Smrg   struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen);
517848b8605Smrg   struct llvmpipe_resource *lpr = llvmpipe_resource(resource);
518848b8605Smrg   struct llvmpipe_transfer *lpt;
519848b8605Smrg   struct pipe_transfer *pt;
520848b8605Smrg   ubyte *map;
521848b8605Smrg   enum pipe_format format;
522848b8605Smrg   enum lp_texture_usage tex_usage;
523848b8605Smrg   const char *mode;
524848b8605Smrg
525848b8605Smrg   assert(resource);
526848b8605Smrg   assert(level <= resource->last_level);
527848b8605Smrg
528848b8605Smrg   /*
529848b8605Smrg    * Transfers, like other pipe operations, must happen in order, so flush the
530848b8605Smrg    * context if necessary.
531848b8605Smrg    */
532848b8605Smrg   if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
533848b8605Smrg      boolean read_only = !(usage & PIPE_TRANSFER_WRITE);
534848b8605Smrg      boolean do_not_block = !!(usage & PIPE_TRANSFER_DONTBLOCK);
535848b8605Smrg      if (!llvmpipe_flush_resource(pipe, resource,
536848b8605Smrg                                   level,
537848b8605Smrg                                   read_only,
538848b8605Smrg                                   TRUE, /* cpu_access */
539848b8605Smrg                                   do_not_block,
540848b8605Smrg                                   __FUNCTION__)) {
541848b8605Smrg         /*
542848b8605Smrg          * It would have blocked, but state tracker requested no to.
543848b8605Smrg          */
544848b8605Smrg         assert(do_not_block);
545848b8605Smrg         return NULL;
546848b8605Smrg      }
547848b8605Smrg   }
548848b8605Smrg
549b8e80941Smrg   /* Check if we're mapping a current constant buffer */
550848b8605Smrg   if ((usage & PIPE_TRANSFER_WRITE) &&
551848b8605Smrg       (resource->bind & PIPE_BIND_CONSTANT_BUFFER)) {
552848b8605Smrg      unsigned i;
553b8e80941Smrg      for (i = 0; i < ARRAY_SIZE(llvmpipe->constants[PIPE_SHADER_FRAGMENT]); ++i) {
554848b8605Smrg         if (resource == llvmpipe->constants[PIPE_SHADER_FRAGMENT][i].buffer) {
555848b8605Smrg            /* constants may have changed */
556b8e80941Smrg            llvmpipe->dirty |= LP_NEW_FS_CONSTANTS;
557848b8605Smrg            break;
558848b8605Smrg         }
559848b8605Smrg      }
560848b8605Smrg   }
561848b8605Smrg
562848b8605Smrg   lpt = CALLOC_STRUCT(llvmpipe_transfer);
563848b8605Smrg   if (!lpt)
564848b8605Smrg      return NULL;
565848b8605Smrg   pt = &lpt->base;
566848b8605Smrg   pipe_resource_reference(&pt->resource, resource);
567848b8605Smrg   pt->box = *box;
568848b8605Smrg   pt->level = level;
569848b8605Smrg   pt->stride = lpr->row_stride[level];
570848b8605Smrg   pt->layer_stride = lpr->img_stride[level];
571848b8605Smrg   pt->usage = usage;
572848b8605Smrg   *transfer = pt;
573848b8605Smrg
574848b8605Smrg   assert(level < LP_MAX_TEXTURE_LEVELS);
575848b8605Smrg
576848b8605Smrg   /*
577848b8605Smrg   printf("tex_transfer_map(%d, %d  %d x %d of %d x %d,  usage %d )\n",
578848b8605Smrg          transfer->x, transfer->y, transfer->width, transfer->height,
579848b8605Smrg          transfer->texture->width0,
580848b8605Smrg          transfer->texture->height0,
581848b8605Smrg          transfer->usage);
582848b8605Smrg   */
583848b8605Smrg
584848b8605Smrg   if (usage == PIPE_TRANSFER_READ) {
585848b8605Smrg      tex_usage = LP_TEX_USAGE_READ;
586848b8605Smrg      mode = "read";
587848b8605Smrg   }
588848b8605Smrg   else {
589848b8605Smrg      tex_usage = LP_TEX_USAGE_READ_WRITE;
590848b8605Smrg      mode = "read/write";
591848b8605Smrg   }
592848b8605Smrg
593848b8605Smrg   if (0) {
594848b8605Smrg      printf("transfer map tex %u  mode %s\n", lpr->id, mode);
595848b8605Smrg   }
596848b8605Smrg
597848b8605Smrg   format = lpr->base.format;
598848b8605Smrg
599848b8605Smrg   map = llvmpipe_resource_map(resource,
600848b8605Smrg                               level,
601848b8605Smrg                               box->z,
602848b8605Smrg                               tex_usage);
603848b8605Smrg
604848b8605Smrg
605848b8605Smrg   /* May want to do different things here depending on read/write nature
606848b8605Smrg    * of the map:
607848b8605Smrg    */
608848b8605Smrg   if (usage & PIPE_TRANSFER_WRITE) {
609848b8605Smrg      /* Do something to notify sharing contexts of a texture change.
610848b8605Smrg       */
611848b8605Smrg      screen->timestamp++;
612848b8605Smrg   }
613848b8605Smrg
614848b8605Smrg   map +=
615848b8605Smrg      box->y / util_format_get_blockheight(format) * pt->stride +
616848b8605Smrg      box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
617848b8605Smrg
618848b8605Smrg   return map;
619848b8605Smrg}
620848b8605Smrg
621848b8605Smrg
622848b8605Smrgstatic void
623848b8605Smrgllvmpipe_transfer_unmap(struct pipe_context *pipe,
624848b8605Smrg                        struct pipe_transfer *transfer)
625848b8605Smrg{
626848b8605Smrg   assert(transfer->resource);
627848b8605Smrg
628848b8605Smrg   llvmpipe_resource_unmap(transfer->resource,
629848b8605Smrg                           transfer->level,
630848b8605Smrg                           transfer->box.z);
631848b8605Smrg
632848b8605Smrg   /* Effectively do the texture_update work here - if texture images
633848b8605Smrg    * needed post-processing to put them into hardware layout, this is
634848b8605Smrg    * where it would happen.  For llvmpipe, nothing to do.
635848b8605Smrg    */
636848b8605Smrg   assert (transfer->resource);
637848b8605Smrg   pipe_resource_reference(&transfer->resource, NULL);
638848b8605Smrg   FREE(transfer);
639848b8605Smrg}
640848b8605Smrg
641848b8605Smrgunsigned int
642848b8605Smrgllvmpipe_is_resource_referenced( struct pipe_context *pipe,
643848b8605Smrg                                 struct pipe_resource *presource,
644848b8605Smrg                                 unsigned level)
645848b8605Smrg{
646848b8605Smrg   struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
647848b8605Smrg   if (!(presource->bind & (PIPE_BIND_DEPTH_STENCIL |
648848b8605Smrg                            PIPE_BIND_RENDER_TARGET |
649848b8605Smrg                            PIPE_BIND_SAMPLER_VIEW)))
650848b8605Smrg      return LP_UNREFERENCED;
651848b8605Smrg
652848b8605Smrg   return lp_setup_is_resource_referenced(llvmpipe->setup, presource);
653848b8605Smrg}
654848b8605Smrg
655848b8605Smrg
656848b8605Smrg/**
657848b8605Smrg * Returns the largest possible alignment for a format in llvmpipe
658848b8605Smrg */
659848b8605Smrgunsigned
660848b8605Smrgllvmpipe_get_format_alignment( enum pipe_format format )
661848b8605Smrg{
662848b8605Smrg   const struct util_format_description *desc = util_format_description(format);
663848b8605Smrg   unsigned size = 0;
664848b8605Smrg   unsigned bytes;
665848b8605Smrg   unsigned i;
666848b8605Smrg
667848b8605Smrg   for (i = 0; i < desc->nr_channels; ++i) {
668848b8605Smrg      size += desc->channel[i].size;
669848b8605Smrg   }
670848b8605Smrg
671848b8605Smrg   bytes = size / 8;
672848b8605Smrg
673b8e80941Smrg   if (!util_is_power_of_two_or_zero(bytes)) {
674848b8605Smrg      bytes /= desc->nr_channels;
675848b8605Smrg   }
676848b8605Smrg
677848b8605Smrg   if (bytes % 2 || bytes < 1) {
678848b8605Smrg      return 1;
679848b8605Smrg   } else {
680848b8605Smrg      return bytes;
681848b8605Smrg   }
682848b8605Smrg}
683848b8605Smrg
684848b8605Smrg
685848b8605Smrg/**
686848b8605Smrg * Create buffer which wraps user-space data.
687b8e80941Smrg * XXX unreachable.
688848b8605Smrg */
689848b8605Smrgstruct pipe_resource *
690848b8605Smrgllvmpipe_user_buffer_create(struct pipe_screen *screen,
691848b8605Smrg                            void *ptr,
692848b8605Smrg                            unsigned bytes,
693848b8605Smrg                            unsigned bind_flags)
694848b8605Smrg{
695848b8605Smrg   struct llvmpipe_resource *buffer;
696848b8605Smrg
697848b8605Smrg   buffer = CALLOC_STRUCT(llvmpipe_resource);
698b8e80941Smrg   if (!buffer)
699848b8605Smrg      return NULL;
700848b8605Smrg
701848b8605Smrg   pipe_reference_init(&buffer->base.reference, 1);
702848b8605Smrg   buffer->base.screen = screen;
703848b8605Smrg   buffer->base.format = PIPE_FORMAT_R8_UNORM; /* ?? */
704848b8605Smrg   buffer->base.bind = bind_flags;
705848b8605Smrg   buffer->base.usage = PIPE_USAGE_IMMUTABLE;
706848b8605Smrg   buffer->base.flags = 0;
707848b8605Smrg   buffer->base.width0 = bytes;
708848b8605Smrg   buffer->base.height0 = 1;
709848b8605Smrg   buffer->base.depth0 = 1;
710848b8605Smrg   buffer->base.array_size = 1;
711848b8605Smrg   buffer->userBuffer = TRUE;
712848b8605Smrg   buffer->data = ptr;
713848b8605Smrg
714848b8605Smrg   return &buffer->base;
715848b8605Smrg}
716848b8605Smrg
717848b8605Smrg
718848b8605Smrg/**
719848b8605Smrg * Compute size (in bytes) need to store a texture image / mipmap level,
720848b8605Smrg * for just one cube face, one array layer or one 3D texture slice
721848b8605Smrg */
722848b8605Smrgstatic unsigned
723848b8605Smrgtex_image_face_size(const struct llvmpipe_resource *lpr, unsigned level)
724848b8605Smrg{
725848b8605Smrg   return lpr->img_stride[level];
726848b8605Smrg}
727848b8605Smrg
728848b8605Smrg
729848b8605Smrg/**
730848b8605Smrg * Return pointer to a 2D texture image/face/slice.
731848b8605Smrg * No tiled/linear conversion is done.
732848b8605Smrg */
733848b8605Smrgubyte *
734848b8605Smrgllvmpipe_get_texture_image_address(struct llvmpipe_resource *lpr,
735848b8605Smrg                                   unsigned face_slice, unsigned level)
736848b8605Smrg{
737848b8605Smrg   unsigned offset;
738848b8605Smrg
739848b8605Smrg   assert(llvmpipe_resource_is_texture(&lpr->base));
740848b8605Smrg
741848b8605Smrg   offset = lpr->mip_offsets[level];
742848b8605Smrg
743848b8605Smrg   if (face_slice > 0)
744848b8605Smrg      offset += face_slice * tex_image_face_size(lpr, level);
745848b8605Smrg
746848b8605Smrg   return (ubyte *) lpr->tex_data + offset;
747848b8605Smrg}
748848b8605Smrg
749848b8605Smrg
750848b8605Smrg/**
751848b8605Smrg * Return size of resource in bytes
752848b8605Smrg */
753848b8605Smrgunsigned
754848b8605Smrgllvmpipe_resource_size(const struct pipe_resource *resource)
755848b8605Smrg{
756848b8605Smrg   const struct llvmpipe_resource *lpr = llvmpipe_resource_const(resource);
757848b8605Smrg   unsigned size = 0;
758848b8605Smrg
759848b8605Smrg   if (llvmpipe_resource_is_texture(resource)) {
760848b8605Smrg      /* Note this will always return 0 for displaytarget resources */
761848b8605Smrg      size = lpr->total_alloc_size;
762848b8605Smrg   }
763848b8605Smrg   else {
764848b8605Smrg      size = resource->width0;
765848b8605Smrg   }
766848b8605Smrg   return size;
767848b8605Smrg}
768848b8605Smrg
769848b8605Smrg
770848b8605Smrg#ifdef DEBUG
771848b8605Smrgvoid
772848b8605Smrgllvmpipe_print_resources(void)
773848b8605Smrg{
774848b8605Smrg   struct llvmpipe_resource *lpr;
775848b8605Smrg   unsigned n = 0, total = 0;
776848b8605Smrg
777848b8605Smrg   debug_printf("LLVMPIPE: current resources:\n");
778848b8605Smrg   foreach(lpr, &resource_list) {
779848b8605Smrg      unsigned size = llvmpipe_resource_size(&lpr->base);
780848b8605Smrg      debug_printf("resource %u at %p, size %ux%ux%u: %u bytes, refcount %u\n",
781848b8605Smrg                   lpr->id, (void *) lpr,
782848b8605Smrg                   lpr->base.width0, lpr->base.height0, lpr->base.depth0,
783848b8605Smrg                   size, lpr->base.reference.count);
784848b8605Smrg      total += size;
785848b8605Smrg      n++;
786848b8605Smrg   }
787848b8605Smrg   debug_printf("LLVMPIPE: total size of %u resources: %u\n", n, total);
788848b8605Smrg}
789848b8605Smrg#endif
790848b8605Smrg
791848b8605Smrg
792848b8605Smrgvoid
793848b8605Smrgllvmpipe_init_screen_resource_funcs(struct pipe_screen *screen)
794848b8605Smrg{
795848b8605Smrg#ifdef DEBUG
796848b8605Smrg   /* init linked list for tracking resources */
797848b8605Smrg   {
798848b8605Smrg      static boolean first_call = TRUE;
799848b8605Smrg      if (first_call) {
800848b8605Smrg         memset(&resource_list, 0, sizeof(resource_list));
801848b8605Smrg         make_empty_list(&resource_list);
802848b8605Smrg         first_call = FALSE;
803848b8605Smrg      }
804848b8605Smrg   }
805848b8605Smrg#endif
806848b8605Smrg
807848b8605Smrg   screen->resource_create = llvmpipe_resource_create;
808b8e80941Smrg/*   screen->resource_create_front = llvmpipe_resource_create_front; */
809848b8605Smrg   screen->resource_destroy = llvmpipe_resource_destroy;
810848b8605Smrg   screen->resource_from_handle = llvmpipe_resource_from_handle;
811848b8605Smrg   screen->resource_get_handle = llvmpipe_resource_get_handle;
812848b8605Smrg   screen->can_create_resource = llvmpipe_can_create_resource;
813848b8605Smrg}
814848b8605Smrg
815848b8605Smrg
816848b8605Smrgvoid
817848b8605Smrgllvmpipe_init_context_resource_funcs(struct pipe_context *pipe)
818848b8605Smrg{
819848b8605Smrg   pipe->transfer_map = llvmpipe_transfer_map;
820848b8605Smrg   pipe->transfer_unmap = llvmpipe_transfer_unmap;
821848b8605Smrg
822848b8605Smrg   pipe->transfer_flush_region = u_default_transfer_flush_region;
823b8e80941Smrg   pipe->buffer_subdata = u_default_buffer_subdata;
824b8e80941Smrg   pipe->texture_subdata = u_default_texture_subdata;
825848b8605Smrg}
826