1/*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 2012-2013 LunarG, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 *    Chia-I Wu <olv@lunarg.com>
26 */
27
28#include "core/ilo_state_vf.h"
29#include "core/ilo_state_sol.h"
30#include "core/ilo_state_surface.h"
31
32#include "ilo_screen.h"
33#include "ilo_format.h"
34#include "ilo_resource.h"
35
36/*
37 * From the Ivy Bridge PRM, volume 1 part 1, page 105:
38 *
39 *     "In addition to restrictions on maximum height, width, and depth,
40 *      surfaces are also restricted to a maximum size in bytes. This
41 *      maximum is 2 GB for all products and all surface types."
42 */
43static const size_t ilo_max_resource_size = 1u << 31;
44
45static const char *
46resource_get_bo_name(const struct pipe_resource *templ)
47{
48   static const char *target_names[PIPE_MAX_TEXTURE_TYPES] = {
49      [PIPE_BUFFER] = "buf",
50      [PIPE_TEXTURE_1D] = "tex-1d",
51      [PIPE_TEXTURE_2D] = "tex-2d",
52      [PIPE_TEXTURE_3D] = "tex-3d",
53      [PIPE_TEXTURE_CUBE] = "tex-cube",
54      [PIPE_TEXTURE_RECT] = "tex-rect",
55      [PIPE_TEXTURE_1D_ARRAY] = "tex-1d-array",
56      [PIPE_TEXTURE_2D_ARRAY] = "tex-2d-array",
57      [PIPE_TEXTURE_CUBE_ARRAY] = "tex-cube-array",
58   };
59   const char *name = target_names[templ->target];
60
61   if (templ->target == PIPE_BUFFER) {
62      switch (templ->bind) {
63      case PIPE_BIND_VERTEX_BUFFER:
64         name = "buf-vb";
65         break;
66      case PIPE_BIND_INDEX_BUFFER:
67         name = "buf-ib";
68         break;
69      case PIPE_BIND_CONSTANT_BUFFER:
70         name = "buf-cb";
71         break;
72      case PIPE_BIND_STREAM_OUTPUT:
73         name = "buf-so";
74         break;
75      default:
76         break;
77      }
78   }
79
80   return name;
81}
82
83static bool
84resource_get_cpu_init(const struct pipe_resource *templ)
85{
86   return (templ->bind & (PIPE_BIND_DEPTH_STENCIL |
87                          PIPE_BIND_RENDER_TARGET |
88                          PIPE_BIND_STREAM_OUTPUT)) ? false : true;
89}
90
91static enum gen_surface_type
92get_surface_type(enum pipe_texture_target target)
93{
94   switch (target) {
95   case PIPE_TEXTURE_1D:
96   case PIPE_TEXTURE_1D_ARRAY:
97      return GEN6_SURFTYPE_1D;
98   case PIPE_TEXTURE_2D:
99   case PIPE_TEXTURE_RECT:
100   case PIPE_TEXTURE_2D_ARRAY:
101      return GEN6_SURFTYPE_2D;
102   case PIPE_TEXTURE_3D:
103      return GEN6_SURFTYPE_3D;
104   case PIPE_TEXTURE_CUBE:
105   case PIPE_TEXTURE_CUBE_ARRAY:
106      return GEN6_SURFTYPE_CUBE;
107   default:
108      assert(!"unknown texture target");
109      return GEN6_SURFTYPE_NULL;
110   }
111}
112
113static enum pipe_format
114resource_get_image_format(const struct pipe_resource *templ,
115                          const struct ilo_dev *dev,
116                          bool *separate_stencil_ret)
117{
118   enum pipe_format format = templ->format;
119   bool separate_stencil;
120
121   /* silently promote ETC1 */
122   if (templ->format == PIPE_FORMAT_ETC1_RGB8)
123      format = PIPE_FORMAT_R8G8B8X8_UNORM;
124
125   /* separate stencil buffers */
126   separate_stencil = false;
127   if ((templ->bind & PIPE_BIND_DEPTH_STENCIL) &&
128       util_format_is_depth_and_stencil(templ->format)) {
129      switch (templ->format) {
130      case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
131         /* Gen6 requires HiZ to be available for all levels */
132         if (ilo_dev_gen(dev) >= ILO_GEN(7) || templ->last_level == 0) {
133            format = PIPE_FORMAT_Z32_FLOAT;
134            separate_stencil = true;
135         }
136         break;
137      case PIPE_FORMAT_Z24_UNORM_S8_UINT:
138         format = PIPE_FORMAT_Z24X8_UNORM;
139         separate_stencil = true;
140         break;
141      default:
142         break;
143      }
144   }
145
146   if (separate_stencil_ret)
147      *separate_stencil_ret = separate_stencil;
148
149   return format;
150}
151
152static inline enum gen_surface_format
153pipe_to_surface_format(const struct ilo_dev *dev, enum pipe_format format)
154{
155   switch (format) {
156   case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
157      return GEN6_FORMAT_R32_FLOAT_X8X24_TYPELESS;
158   case PIPE_FORMAT_Z32_FLOAT:
159      return GEN6_FORMAT_R32_FLOAT;
160   case PIPE_FORMAT_Z24_UNORM_S8_UINT:
161   case PIPE_FORMAT_Z24X8_UNORM:
162      return GEN6_FORMAT_R24_UNORM_X8_TYPELESS;
163   case PIPE_FORMAT_Z16_UNORM:
164      return GEN6_FORMAT_R16_UNORM;
165   case PIPE_FORMAT_S8_UINT:
166      return GEN6_FORMAT_R8_UINT;
167   default:
168      return ilo_format_translate_color(dev, format);
169   }
170}
171
172static void
173resource_get_image_info(const struct pipe_resource *templ,
174                        const struct ilo_dev *dev,
175                        enum pipe_format image_format,
176                        struct ilo_image_info *info)
177{
178   memset(info, 0, sizeof(*info));
179
180   info->type = get_surface_type(templ->target);
181
182   info->format = pipe_to_surface_format(dev, image_format);
183   info->interleaved_stencil = util_format_is_depth_and_stencil(image_format);
184   info->is_integer = util_format_is_pure_integer(image_format);
185   info->compressed = util_format_is_compressed(image_format);
186   info->block_width = util_format_get_blockwidth(image_format);
187   info->block_height = util_format_get_blockheight(image_format);
188   info->block_size = util_format_get_blocksize(image_format);
189
190   info->width = templ->width0;
191   info->height = templ->height0;
192   info->depth = templ->depth0;
193   info->array_size = templ->array_size;
194   info->level_count = templ->last_level + 1;
195   info->sample_count = (templ->nr_samples) ? templ->nr_samples : 1;
196
197   info->aux_disable = (templ->usage == PIPE_USAGE_STAGING);
198
199   if (templ->bind & PIPE_BIND_LINEAR)
200      info->valid_tilings = 1 << GEN6_TILING_NONE;
201
202   /*
203    * Tiled images must be mapped via GTT to get a linear view.  Prefer linear
204    * images when the image size is greater than one-fourth of the mappable
205    * aperture.
206    */
207   if (templ->usage == PIPE_USAGE_STAGING)
208      info->prefer_linear_threshold = dev->aperture_mappable / 4;
209
210   info->bind_surface_sampler = (templ->bind & PIPE_BIND_SAMPLER_VIEW);
211   info->bind_surface_dp_render = (templ->bind & PIPE_BIND_RENDER_TARGET);
212   info->bind_surface_dp_typed = (templ->bind &
213         (PIPE_BIND_SHADER_IMAGE | PIPE_BIND_COMPUTE_RESOURCE));
214   info->bind_zs = (templ->bind & PIPE_BIND_DEPTH_STENCIL);
215   info->bind_scanout = (templ->bind & PIPE_BIND_SCANOUT);
216   info->bind_cursor = (templ->bind & PIPE_BIND_CURSOR);
217}
218
219static enum gen_surface_tiling
220winsys_to_surface_tiling(enum intel_tiling_mode tiling)
221{
222   switch (tiling) {
223   case INTEL_TILING_NONE:
224      return GEN6_TILING_NONE;
225   case INTEL_TILING_X:
226      return GEN6_TILING_X;
227   case INTEL_TILING_Y:
228      return GEN6_TILING_Y;
229   default:
230      assert(!"unknown tiling");
231      return GEN6_TILING_NONE;
232   }
233}
234
235static inline enum intel_tiling_mode
236surface_to_winsys_tiling(enum gen_surface_tiling tiling)
237{
238   switch (tiling) {
239   case GEN6_TILING_NONE:
240      return INTEL_TILING_NONE;
241   case GEN6_TILING_X:
242      return INTEL_TILING_X;
243   case GEN6_TILING_Y:
244      return INTEL_TILING_Y;
245   default:
246      assert(!"unknown tiling");
247      return GEN6_TILING_NONE;
248   }
249}
250
251static void
252tex_free_slices(struct ilo_texture *tex)
253{
254   FREE(tex->slices[0]);
255}
256
257static bool
258tex_alloc_slices(struct ilo_texture *tex)
259{
260   const struct pipe_resource *templ = &tex->base;
261   struct ilo_texture_slice *slices;
262   int depth, lv;
263
264   /* sum the depths of all levels */
265   depth = 0;
266   for (lv = 0; lv <= templ->last_level; lv++)
267      depth += u_minify(templ->depth0, lv);
268
269   /*
270    * There are (depth * tex->base.array_size) slices in total.  Either depth
271    * is one (non-3D) or templ->array_size is one (non-array), but it does
272    * not matter.
273    */
274   slices = CALLOC(depth * templ->array_size, sizeof(*slices));
275   if (!slices)
276      return false;
277
278   tex->slices[0] = slices;
279
280   /* point to the respective positions in the buffer */
281   for (lv = 1; lv <= templ->last_level; lv++) {
282      tex->slices[lv] = tex->slices[lv - 1] +
283         u_minify(templ->depth0, lv - 1) * templ->array_size;
284   }
285
286   return true;
287}
288
289static bool
290tex_create_bo(struct ilo_texture *tex)
291{
292   struct ilo_screen *is = ilo_screen(tex->base.screen);
293   const char *name = resource_get_bo_name(&tex->base);
294   const bool cpu_init = resource_get_cpu_init(&tex->base);
295   struct intel_bo *bo;
296
297   bo = intel_winsys_alloc_bo(is->dev.winsys, name,
298         tex->image.bo_stride * tex->image.bo_height, cpu_init);
299
300   /* set the tiling for transfer and export */
301   if (bo && (tex->image.tiling == GEN6_TILING_X ||
302              tex->image.tiling == GEN6_TILING_Y)) {
303      const enum intel_tiling_mode tiling =
304         surface_to_winsys_tiling(tex->image.tiling);
305
306      if (intel_bo_set_tiling(bo, tiling, tex->image.bo_stride)) {
307         intel_bo_unref(bo);
308         bo = NULL;
309      }
310   }
311   if (!bo)
312      return false;
313
314   intel_bo_unref(tex->vma.bo);
315   ilo_vma_set_bo(&tex->vma, &is->dev, bo, 0);
316
317   return true;
318}
319
320static bool
321tex_create_separate_stencil(struct ilo_texture *tex)
322{
323   struct pipe_resource templ = tex->base;
324   struct pipe_resource *s8;
325
326   /*
327    * Unless PIPE_BIND_DEPTH_STENCIL is set, the resource may have other
328    * tilings.  But that should be fine since it will never be bound as the
329    * stencil buffer, and our transfer code can handle all tilings.
330    */
331   templ.format = PIPE_FORMAT_S8_UINT;
332
333   /* no stencil texturing */
334   templ.bind &= ~PIPE_BIND_SAMPLER_VIEW;
335
336   s8 = tex->base.screen->resource_create(tex->base.screen, &templ);
337   if (!s8)
338      return false;
339
340   tex->separate_s8 = ilo_texture(s8);
341
342   assert(tex->separate_s8->image_format == PIPE_FORMAT_S8_UINT);
343
344   return true;
345}
346
347static bool
348tex_create_hiz(struct ilo_texture *tex)
349{
350   const struct pipe_resource *templ = &tex->base;
351   const uint32_t size = tex->image.aux.bo_stride * tex->image.aux.bo_height;
352   struct ilo_screen *is = ilo_screen(tex->base.screen);
353   struct intel_bo *bo;
354
355   bo = intel_winsys_alloc_bo(is->dev.winsys, "hiz texture", size, false);
356   if (!bo)
357      return false;
358
359   ilo_vma_init(&tex->aux_vma, &is->dev, size, 4096);
360   ilo_vma_set_bo(&tex->aux_vma, &is->dev, bo, 0);
361
362   if (tex->imported) {
363      unsigned lv;
364
365      for (lv = 0; lv <= templ->last_level; lv++) {
366         if (tex->image.aux.enables & (1 << lv)) {
367            const unsigned num_slices = (templ->target == PIPE_TEXTURE_3D) ?
368               u_minify(templ->depth0, lv) : templ->array_size;
369            /* this will trigger HiZ resolves */
370            const unsigned flags = ILO_TEXTURE_CPU_WRITE;
371
372            ilo_texture_set_slice_flags(tex, lv, 0, num_slices, flags, flags);
373         }
374      }
375   }
376
377   return true;
378}
379
380static bool
381tex_create_mcs(struct ilo_texture *tex)
382{
383   const uint32_t size = tex->image.aux.bo_stride * tex->image.aux.bo_height;
384   struct ilo_screen *is = ilo_screen(tex->base.screen);
385   struct intel_bo *bo;
386
387   assert(tex->image.aux.enables == (1 << (tex->base.last_level + 1)) - 1);
388
389   bo = intel_winsys_alloc_bo(is->dev.winsys, "mcs texture", size, false);
390   if (!bo)
391      return false;
392
393   ilo_vma_init(&tex->aux_vma, &is->dev, size, 4096);
394   ilo_vma_set_bo(&tex->aux_vma, &is->dev, bo, 0);
395
396   return true;
397}
398
399static void
400tex_destroy(struct ilo_texture *tex)
401{
402   if (tex->separate_s8)
403      tex_destroy(tex->separate_s8);
404
405   intel_bo_unref(tex->vma.bo);
406   intel_bo_unref(tex->aux_vma.bo);
407
408   tex_free_slices(tex);
409   FREE(tex);
410}
411
412static bool
413tex_alloc_bos(struct ilo_texture *tex)
414{
415   if (!tex->imported && !tex_create_bo(tex))
416      return false;
417
418   switch (tex->image.aux.type) {
419   case ILO_IMAGE_AUX_HIZ:
420      if (!tex_create_hiz(tex))
421         return false;
422      break;
423   case ILO_IMAGE_AUX_MCS:
424      if (!tex_create_mcs(tex))
425         return false;
426      break;
427   default:
428      break;
429   }
430
431   return true;
432}
433
434static struct intel_bo *
435tex_import_handle(struct ilo_texture *tex,
436                  const struct winsys_handle *handle,
437                  struct ilo_image_info *info)
438{
439   struct ilo_screen *is = ilo_screen(tex->base.screen);
440   const struct pipe_resource *templ = &tex->base;
441   const char *name = resource_get_bo_name(&tex->base);
442   enum intel_tiling_mode tiling;
443   unsigned long pitch;
444   struct intel_bo *bo;
445
446   bo = intel_winsys_import_handle(is->dev.winsys, name, handle,
447         tex->image.bo_height, &tiling, &pitch);
448   /* modify image info */
449   if (bo) {
450      const uint8_t valid_tilings = 1 << winsys_to_surface_tiling(tiling);
451
452      if (info->valid_tilings && !(info->valid_tilings & valid_tilings)) {
453         intel_bo_unref(bo);
454         return NULL;
455      }
456
457      info->valid_tilings = valid_tilings;
458      info->force_bo_stride = pitch;
459
460      /* assume imported RTs are also scanouts */
461      if (!info->bind_scanout)
462         info->bind_scanout = (templ->usage & PIPE_BIND_RENDER_TARGET);
463   }
464
465   return bo;
466}
467
468static bool
469tex_init_image(struct ilo_texture *tex,
470               const struct winsys_handle *handle,
471               bool *separate_stencil)
472{
473   struct ilo_screen *is = ilo_screen(tex->base.screen);
474   const struct pipe_resource *templ = &tex->base;
475   struct ilo_image *img = &tex->image;
476   struct intel_bo *imported_bo = NULL;
477   struct ilo_image_info info;
478
479   tex->image_format = resource_get_image_format(templ,
480         &is->dev, separate_stencil);
481   resource_get_image_info(templ, &is->dev, tex->image_format, &info);
482
483   if (handle) {
484      imported_bo = tex_import_handle(tex, handle, &info);
485      if (!imported_bo)
486         return false;
487   }
488
489   if (!ilo_image_init(img, &is->dev, &info)) {
490      intel_bo_unref(imported_bo);
491      return false;
492   }
493
494   /*
495    * HiZ requires 8x4 alignment and some levels might need HiZ disabled.  It
496    * is generally fine except on Gen6, where HiZ and separate stencil must be
497    * enabled together.  For PIPE_FORMAT_Z24X8_UNORM with separate stencil, we
498    * can live with stencil values being interleaved for levels where HiZ is
499    * disabled.  But it is not the case for PIPE_FORMAT_Z32_FLOAT with
500    * separate stencil.  If HiZ was disabled for a level, we had to change the
501    * format to PIPE_FORMAT_Z32_FLOAT_S8X24_UINT for the level and that format
502    * had a different bpp.  In other words, HiZ has to be available for all
503    * levels.
504    */
505   if (ilo_dev_gen(&is->dev) == ILO_GEN(6) &&
506       templ->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT &&
507       tex->image_format == PIPE_FORMAT_Z32_FLOAT &&
508       img->aux.enables != (1 << templ->last_level)) {
509      tex->image_format = templ->format;
510      info.format = pipe_to_surface_format(&is->dev, tex->image_format);
511      info.interleaved_stencil = true;
512
513      memset(img, 0, sizeof(*img));
514      if (!ilo_image_init(img, &is->dev, &info)) {
515         intel_bo_unref(imported_bo);
516         return false;
517      }
518   }
519
520   if (img->bo_height > ilo_max_resource_size / img->bo_stride ||
521       !ilo_vma_init(&tex->vma, &is->dev, img->bo_stride * img->bo_height,
522          4096)) {
523      intel_bo_unref(imported_bo);
524      return false;
525   }
526
527   if (imported_bo) {
528      ilo_vma_set_bo(&tex->vma, &is->dev, imported_bo, 0);
529      tex->imported = true;
530   }
531
532   if (templ->flags & PIPE_RESOURCE_FLAG_MAP_PERSISTENT) {
533      /* require on-the-fly tiling/untiling or format conversion */
534      if (img->tiling == GEN8_TILING_W || *separate_stencil ||
535          tex->image_format != templ->format)
536         return false;
537   }
538
539   if (!tex_alloc_slices(tex))
540      return false;
541
542   return true;
543}
544
545static struct pipe_resource *
546tex_create(struct pipe_screen *screen,
547           const struct pipe_resource *templ,
548           const struct winsys_handle *handle)
549{
550   struct ilo_texture *tex;
551   bool separate_stencil;
552
553   tex = CALLOC_STRUCT(ilo_texture);
554   if (!tex)
555      return NULL;
556
557   tex->base = *templ;
558   tex->base.screen = screen;
559   pipe_reference_init(&tex->base.reference, 1);
560
561   if (!tex_init_image(tex, handle, &separate_stencil)) {
562      FREE(tex);
563      return NULL;
564   }
565
566   if (!tex_alloc_bos(tex) ||
567       (separate_stencil && !tex_create_separate_stencil(tex))) {
568      tex_destroy(tex);
569      return NULL;
570   }
571
572   return &tex->base;
573}
574
575static bool
576tex_get_handle(struct ilo_texture *tex, struct winsys_handle *handle)
577{
578   struct ilo_screen *is = ilo_screen(tex->base.screen);
579   enum intel_tiling_mode tiling;
580   int err;
581
582   /* must match what tex_create_bo() sets */
583   if (tex->image.tiling == GEN8_TILING_W)
584      tiling = INTEL_TILING_NONE;
585   else
586      tiling = surface_to_winsys_tiling(tex->image.tiling);
587
588   err = intel_winsys_export_handle(is->dev.winsys, tex->vma.bo, tiling,
589         tex->image.bo_stride, tex->image.bo_height, handle);
590
591   return !err;
592}
593
594static bool
595buf_create_bo(struct ilo_buffer_resource *buf)
596{
597   struct ilo_screen *is = ilo_screen(buf->base.screen);
598   const char *name = resource_get_bo_name(&buf->base);
599   const bool cpu_init = resource_get_cpu_init(&buf->base);
600   struct intel_bo *bo;
601
602   bo = intel_winsys_alloc_bo(is->dev.winsys, name, buf->bo_size, cpu_init);
603   if (!bo)
604      return false;
605
606   intel_bo_unref(buf->vma.bo);
607   ilo_vma_set_bo(&buf->vma, &is->dev, bo, 0);
608
609   return true;
610}
611
612static void
613buf_destroy(struct ilo_buffer_resource *buf)
614{
615   intel_bo_unref(buf->vma.bo);
616   FREE(buf);
617}
618
619static struct pipe_resource *
620buf_create(struct pipe_screen *screen, const struct pipe_resource *templ)
621{
622   const struct ilo_screen *is = ilo_screen(screen);
623   struct ilo_buffer_resource *buf;
624   uint32_t alignment;
625   unsigned size;
626
627   buf = CALLOC_STRUCT(ilo_buffer_resource);
628   if (!buf)
629      return NULL;
630
631   buf->base = *templ;
632   buf->base.screen = screen;
633   pipe_reference_init(&buf->base.reference, 1);
634
635   size = templ->width0;
636
637   /*
638    * As noted in ilo_format_translate(), we treat some 3-component formats as
639    * 4-component formats to work around hardware limitations.  Imagine the
640    * case where the vertex buffer holds a single PIPE_FORMAT_R16G16B16_FLOAT
641    * vertex, and buf->bo_size is 6.  The hardware would fail to fetch it at
642    * boundary check because the vertex buffer is expected to hold a
643    * PIPE_FORMAT_R16G16B16A16_FLOAT vertex and that takes at least 8 bytes.
644    *
645    * For the workaround to work, we should add 2 to the bo size.  But that
646    * would waste a page when the bo size is already page aligned.  Let's
647    * round it to page size for now and revisit this when needed.
648    */
649   if ((templ->bind & PIPE_BIND_VERTEX_BUFFER) &&
650       ilo_dev_gen(&is->dev) < ILO_GEN(7.5))
651      size = align(size, 4096);
652
653   if (templ->bind & PIPE_BIND_VERTEX_BUFFER)
654      size = ilo_state_vertex_buffer_size(&is->dev, size, &alignment);
655   if (templ->bind & PIPE_BIND_INDEX_BUFFER)
656      size = ilo_state_index_buffer_size(&is->dev, size, &alignment);
657   if (templ->bind & PIPE_BIND_STREAM_OUTPUT)
658      size = ilo_state_sol_buffer_size(&is->dev, size, &alignment);
659
660   buf->bo_size = size;
661   ilo_vma_init(&buf->vma, &is->dev, buf->bo_size, 4096);
662
663   if (buf->bo_size < templ->width0 || buf->bo_size > ilo_max_resource_size ||
664       !buf_create_bo(buf)) {
665      FREE(buf);
666      return NULL;
667   }
668
669   return &buf->base;
670}
671
672static boolean
673ilo_can_create_resource(struct pipe_screen *screen,
674                        const struct pipe_resource *templ)
675{
676   struct ilo_screen *is = ilo_screen(screen);
677   enum pipe_format image_format;
678   struct ilo_image_info info;
679   struct ilo_image img;
680
681   if (templ->target == PIPE_BUFFER)
682      return (templ->width0 <= ilo_max_resource_size);
683
684   image_format = resource_get_image_format(templ, &is->dev, NULL);
685   resource_get_image_info(templ, &is->dev, image_format, &info);
686
687   memset(&img, 0, sizeof(img));
688   ilo_image_init(&img, &ilo_screen(screen)->dev, &info);
689
690   /* as in tex_init_image() */
691   if (ilo_dev_gen(&is->dev) == ILO_GEN(6) &&
692       templ->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT &&
693       image_format == PIPE_FORMAT_Z32_FLOAT &&
694       img.aux.enables != (1 << templ->last_level)) {
695      info.format = pipe_to_surface_format(&is->dev, templ->format);
696      info.interleaved_stencil = true;
697      memset(&img, 0, sizeof(img));
698      ilo_image_init(&img, &ilo_screen(screen)->dev, &info);
699   }
700
701   return (img.bo_height <= ilo_max_resource_size / img.bo_stride);
702}
703
704static struct pipe_resource *
705ilo_resource_create(struct pipe_screen *screen,
706                    const struct pipe_resource *templ)
707{
708   if (templ->target == PIPE_BUFFER)
709      return buf_create(screen, templ);
710   else
711      return tex_create(screen, templ, NULL);
712}
713
714static struct pipe_resource *
715ilo_resource_from_handle(struct pipe_screen *screen,
716                         const struct pipe_resource *templ,
717                         struct winsys_handle *handle,
718                         unsigned usage)
719{
720   if (templ->target == PIPE_BUFFER)
721      return NULL;
722   else
723      return tex_create(screen, templ, handle);
724}
725
726static boolean
727ilo_resource_get_handle(struct pipe_screen *screen,
728                        struct pipe_context *ctx,
729                        struct pipe_resource *res,
730                        struct winsys_handle *handle,
731                        unsigned usage)
732{
733   if (res->target == PIPE_BUFFER)
734      return false;
735   else
736      return tex_get_handle(ilo_texture(res), handle);
737
738}
739
740static void
741ilo_resource_destroy(struct pipe_screen *screen,
742                     struct pipe_resource *res)
743{
744   if (res->target == PIPE_BUFFER)
745      buf_destroy((struct ilo_buffer_resource *) res);
746   else
747      tex_destroy(ilo_texture(res));
748}
749
750/**
751 * Initialize resource-related functions.
752 */
753void
754ilo_init_resource_functions(struct ilo_screen *is)
755{
756   is->base.can_create_resource = ilo_can_create_resource;
757   is->base.resource_create = ilo_resource_create;
758   is->base.resource_from_handle = ilo_resource_from_handle;
759   is->base.resource_get_handle = ilo_resource_get_handle;
760   is->base.resource_destroy = ilo_resource_destroy;
761}
762
763bool
764ilo_resource_rename_bo(struct pipe_resource *res)
765{
766   if (res->target == PIPE_BUFFER) {
767      return buf_create_bo((struct ilo_buffer_resource *) res);
768   } else {
769      struct ilo_texture *tex = ilo_texture(res);
770
771      /* an imported texture cannot be renamed */
772      if (tex->imported)
773         return false;
774
775      return tex_create_bo(tex);
776   }
777}
778