r300g: align the height of NPOT textures to POT
[profile/ivi/mesa.git] / src / gallium / drivers / i915 / i915_resource_texture.c
1 /**************************************************************************
2  * 
3  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
4  * All Rights Reserved.
5  * 
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  * 
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  * 
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  * 
26  **************************************************************************/
27  /*
28   * Authors:
29   *   Keith Whitwell <keith@tungstengraphics.com>
30   *   Michel Dänzer <michel@tungstengraphics.com>
31   */
32
33 #include "pipe/p_state.h"
34 #include "pipe/p_context.h"
35 #include "pipe/p_defines.h"
36 #include "util/u_inlines.h"
37 #include "util/u_format.h"
38 #include "util/u_math.h"
39 #include "util/u_memory.h"
40
41 #include "i915_context.h"
42 #include "i915_resource.h"
43 #include "i915_screen.h"
44 #include "i915_winsys.h"
45
46
47 /*
48  * Helper function and arrays
49  */
50
51
52 /**
53  * Initial offset for Cube map.
54  */
55 static const int initial_offsets[6][2] = {
56    {0, 0},
57    {0, 2},
58    {1, 0},
59    {1, 2},
60    {1, 1},
61    {1, 3}
62 };
63
64 /**
65  * Step offsets for Cube map.
66  */
67 static const int step_offsets[6][2] = {
68    {0, 2},
69    {0, 2},
70    {-1, 2},
71    {-1, 2},
72    {-1, 1},
73    {-1, 1}
74 };
75
76 /* XXX really need twice the size if x is already pot?
77    Otherwise just use util_next_power_of_two?
78 */
79 static unsigned
80 power_of_two(unsigned x)
81 {
82    unsigned value = 1;
83    while (value < x)
84       value = value << 1;
85    return value;
86 }
87
88 /*
89  * More advanced helper funcs
90  */
91
92
93 static void
94 i915_texture_set_level_info(struct i915_texture *tex,
95                              unsigned level,
96                              unsigned nr_images,
97                              unsigned w, unsigned h, unsigned d)
98 {
99    assert(level < Elements(tex->nr_images));
100
101    tex->nr_images[level] = nr_images;
102
103    /*
104    DBG("%s level %d size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__,
105        level, w, h, d, x, y, tex->level_offset[level]);
106    */
107
108    /* Not sure when this would happen, but anyway: 
109     */
110    if (tex->image_offset[level]) {
111       FREE(tex->image_offset[level]);
112       tex->image_offset[level] = NULL;
113    }
114
115    assert(nr_images);
116    assert(!tex->image_offset[level]);
117
118    tex->image_offset[level] = (unsigned *) MALLOC(nr_images * sizeof(unsigned));
119    tex->image_offset[level][0] = 0;
120 }
121
122 static void
123 i915_texture_set_image_offset(struct i915_texture *tex,
124                               unsigned level, unsigned img, unsigned x, unsigned y)
125 {
126    if (img == 0 && level == 0)
127       assert(x == 0 && y == 0);
128
129    assert(img < tex->nr_images[level]);
130
131    tex->image_offset[level][img] = y * tex->stride + x * util_format_get_blocksize(tex->b.b.format);
132
133    /*
134    printf("%s level %d img %d pos %d,%d image_offset %x\n",
135        __FUNCTION__, level, img, x, y, tex->image_offset[level][img]);
136    */
137 }
138
139
140 /*
141  * i915 layout functions, some used by i945
142  */
143
144
145 /**
146  * Special case to deal with scanout textures.
147  */
148 static boolean
149 i915_scanout_layout(struct i915_texture *tex)
150 {
151    struct pipe_resource *pt = &tex->b.b;
152
153    if (pt->last_level > 0 || util_format_get_blocksize(pt->format) != 4)
154       return FALSE;
155
156    i915_texture_set_level_info(tex, 0, 1,
157                                pt->width0,
158                                pt->height0,
159                                1);
160    i915_texture_set_image_offset(tex, 0, 0, 0, 0);
161
162    if (pt->width0 >= 240) {
163       tex->stride = power_of_two(util_format_get_stride(pt->format, pt->width0));
164       tex->total_nblocksy = align(util_format_get_nblocksy(pt->format, pt->height0), 8);
165       tex->hw_tiled = I915_TILE_X;
166    } else if (pt->width0 == 64 && pt->height0 == 64) {
167       tex->stride = power_of_two(util_format_get_stride(pt->format, pt->width0));
168       tex->total_nblocksy = align(util_format_get_nblocksy(pt->format, pt->height0), 8);
169    } else {
170       return FALSE;
171    }
172
173    debug_printf("%s size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__,
174       pt->width0, pt->height0, util_format_get_blocksize(pt->format),
175       tex->stride, tex->total_nblocksy, tex->stride * tex->total_nblocksy);
176
177    return TRUE;
178 }
179
180 /**
181  * Special case to deal with shared textures.
182  */
183 static boolean
184 i915_display_target_layout(struct i915_texture *tex)
185 {
186    struct pipe_resource *pt = &tex->b.b;
187
188    if (pt->last_level > 0 || util_format_get_blocksize(pt->format) != 4)
189       return FALSE;
190
191    /* fallback to normal textures for small textures */
192    if (pt->width0 < 240)
193       return FALSE;
194
195    i915_texture_set_level_info(tex, 0, 1,
196                                pt->width0,
197                                pt->height0,
198                                1);
199    i915_texture_set_image_offset(tex, 0, 0, 0, 0);
200
201    tex->stride = power_of_two(util_format_get_stride(pt->format, pt->width0));
202    tex->total_nblocksy = align(util_format_get_nblocksy(pt->format, pt->height0), 8);
203    tex->hw_tiled = I915_TILE_X;
204
205    debug_printf("%s size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__,
206       pt->width0, pt->height0, util_format_get_blocksize(pt->format),
207       tex->stride, tex->total_nblocksy, tex->stride * tex->total_nblocksy);
208
209    return TRUE;
210 }
211
212 static void
213 i915_texture_layout_2d(struct i915_texture *tex)
214 {
215    struct pipe_resource *pt = &tex->b.b;
216    unsigned level;
217    unsigned width = pt->width0;
218    unsigned height = pt->height0;
219    unsigned nblocksy = util_format_get_nblocksy(pt->format, pt->width0);
220
221    /* used for scanouts that need special layouts */
222    if (pt->bind & PIPE_BIND_SCANOUT)
223       if (i915_scanout_layout(tex))
224          return;
225
226    /* shared buffers needs to be compatible with X servers 
227     * 
228     * XXX: need a better name than shared for this if it is to be part
229     * of core gallium, and probably move the flag to resource.flags,
230     * rather than bindings.
231     */
232    if (pt->bind & PIPE_BIND_SHARED)
233       if (i915_display_target_layout(tex))
234          return;
235
236    tex->stride = align(util_format_get_stride(pt->format, pt->width0), 4);
237    tex->total_nblocksy = 0;
238
239    for (level = 0; level <= pt->last_level; level++) {
240       i915_texture_set_level_info(tex, level, 1, width, height, 1);
241       i915_texture_set_image_offset(tex, level, 0, 0, tex->total_nblocksy);
242
243       nblocksy = align(MAX2(2, nblocksy), 2);
244
245       tex->total_nblocksy += nblocksy;
246
247       width = u_minify(width, 1);
248       height = u_minify(height, 1);
249       nblocksy = util_format_get_nblocksy(pt->format, height);
250    }
251 }
252
253 static void
254 i915_texture_layout_3d(struct i915_texture *tex)
255 {
256    struct pipe_resource *pt = &tex->b.b;
257    unsigned level;
258
259    unsigned width = pt->width0;
260    unsigned height = pt->height0;
261    unsigned depth = pt->depth0;
262    unsigned nblocksy = util_format_get_nblocksy(pt->format, pt->height0);
263    unsigned stack_nblocksy = 0;
264
265    /* Calculate the size of a single slice. 
266     */
267    tex->stride = align(util_format_get_stride(pt->format, pt->width0), 4);
268
269    /* XXX: hardware expects/requires 9 levels at minimum.
270     */
271    for (level = 0; level <= MAX2(8, pt->last_level); level++) {
272       i915_texture_set_level_info(tex, level, depth, width, height, depth);
273
274       stack_nblocksy += MAX2(2, nblocksy);
275
276       width = u_minify(width, 1);
277       height = u_minify(height, 1);
278       nblocksy = util_format_get_nblocksy(pt->format, height);
279    }
280
281    /* Fixup depth image_offsets: 
282     */
283    for (level = 0; level <= pt->last_level; level++) {
284       unsigned i;
285       for (i = 0; i < depth; i++) 
286          i915_texture_set_image_offset(tex, level, i, 0, i * stack_nblocksy);
287
288       depth = u_minify(depth, 1);
289    }
290
291    /* Multiply slice size by texture depth for total size.  It's
292     * remarkable how wasteful of memory the i915 texture layouts
293     * are.  They are largely fixed in the i945.
294     */
295    tex->total_nblocksy = stack_nblocksy * pt->depth0;
296 }
297
298 static void
299 i915_texture_layout_cube(struct i915_texture *tex)
300 {
301    struct pipe_resource *pt = &tex->b.b;
302    unsigned width = pt->width0, height = pt->height0;
303    const unsigned nblocks = util_format_get_nblocksx(pt->format, pt->width0);
304    unsigned level;
305    unsigned face;
306
307    assert(width == height); /* cubemap images are square */
308
309    /* double pitch for cube layouts */
310    tex->stride = align(nblocks * util_format_get_blocksize(pt->format) * 2, 4);
311    tex->total_nblocksy = nblocks * 4;
312
313    for (level = 0; level <= pt->last_level; level++) {
314       i915_texture_set_level_info(tex, level, 6, width, height, 1);
315       width /= 2;
316       height /= 2;
317    }
318
319    for (face = 0; face < 6; face++) {
320       unsigned x = initial_offsets[face][0] * nblocks;
321       unsigned y = initial_offsets[face][1] * nblocks;
322       unsigned d = nblocks;
323
324       for (level = 0; level <= pt->last_level; level++) {
325          i915_texture_set_image_offset(tex, level, face, x, y);
326          d >>= 1;
327          x += step_offsets[face][0] * d;
328          y += step_offsets[face][1] * d;
329       }
330    }
331 }
332
333 static boolean
334 i915_texture_layout(struct i915_texture * tex)
335 {
336    struct pipe_resource *pt = &tex->b.b;
337
338    switch (pt->target) {
339    case PIPE_TEXTURE_1D:
340    case PIPE_TEXTURE_2D:
341       i915_texture_layout_2d(tex);
342       break;
343    case PIPE_TEXTURE_3D:
344       i915_texture_layout_3d(tex);
345       break;
346    case PIPE_TEXTURE_CUBE:
347       i915_texture_layout_cube(tex);
348       break;
349    default:
350       assert(0);
351       return FALSE;
352    }
353
354    return TRUE;
355 }
356
357
358 /*
359  * i945 layout functions
360  */
361
362
363 static void
364 i945_texture_layout_2d(struct i915_texture *tex)
365 {
366    struct pipe_resource *pt = &tex->b.b;
367    const int align_x = 2, align_y = 4;
368    unsigned level;
369    unsigned x = 0;
370    unsigned y = 0;
371    unsigned width = pt->width0;
372    unsigned height = pt->height0;
373    unsigned nblocksx = util_format_get_nblocksx(pt->format, pt->width0);
374    unsigned nblocksy = util_format_get_nblocksy(pt->format, pt->height0);
375
376    /* used for scanouts that need special layouts */
377    if (tex->b.b.bind & PIPE_BIND_SCANOUT)
378       if (i915_scanout_layout(tex))
379          return;
380
381    /* shared buffers needs to be compatible with X servers */
382    if (tex->b.b.bind & PIPE_BIND_SHARED)
383       if (i915_display_target_layout(tex))
384          return;
385
386    tex->stride = align(util_format_get_stride(pt->format, pt->width0), 4);
387
388    /* May need to adjust pitch to accomodate the placement of
389     * the 2nd mipmap level.  This occurs when the alignment
390     * constraints of mipmap placement push the right edge of the
391     * 2nd mipmap level out past the width of its parent.
392     */
393    if (pt->last_level > 0) {
394       unsigned mip1_nblocksx 
395          = align(util_format_get_nblocksx(pt->format, u_minify(width, 1)), align_x)
396          + util_format_get_nblocksx(pt->format, u_minify(width, 2));
397
398       if (mip1_nblocksx > nblocksx)
399          tex->stride = mip1_nblocksx * util_format_get_blocksize(pt->format);
400    }
401
402    /* Pitch must be a whole number of dwords
403     */
404    tex->stride = align(tex->stride, 64);
405    tex->total_nblocksy = 0;
406
407    for (level = 0; level <= pt->last_level; level++) {
408       i915_texture_set_level_info(tex, level, 1, width, height, 1);
409       i915_texture_set_image_offset(tex, level, 0, x, y);
410
411       nblocksy = align(nblocksy, align_y);
412
413       /* Because the images are packed better, the final offset
414        * might not be the maximal one:
415        */
416       tex->total_nblocksy = MAX2(tex->total_nblocksy, y + nblocksy);
417
418       /* Layout_below: step right after second mipmap level.
419        */
420       if (level == 1) {
421          x += align(nblocksx, align_x);
422       }
423       else {
424          y += nblocksy;
425       }
426
427       width  = u_minify(width, 1);
428       height = u_minify(height, 1);
429       nblocksx = util_format_get_nblocksx(pt->format, width);
430       nblocksy = util_format_get_nblocksy(pt->format, height);
431    }
432 }
433
434 static void
435 i945_texture_layout_3d(struct i915_texture *tex)
436 {
437    struct pipe_resource *pt = &tex->b.b;
438    unsigned width = pt->width0;
439    unsigned height = pt->height0;
440    unsigned depth = pt->depth0;
441    unsigned nblocksy = util_format_get_nblocksy(pt->format, pt->width0);
442    unsigned pack_x_pitch, pack_x_nr;
443    unsigned pack_y_pitch;
444    unsigned level;
445
446    tex->stride = align(util_format_get_stride(pt->format, pt->width0), 4);
447    tex->total_nblocksy = 0;
448
449    pack_y_pitch = MAX2(nblocksy, 2);
450    pack_x_pitch = tex->stride / util_format_get_blocksize(pt->format);
451    pack_x_nr = 1;
452
453    for (level = 0; level <= pt->last_level; level++) {
454       int x = 0;
455       int y = 0;
456       unsigned q, j;
457
458       i915_texture_set_level_info(tex, level, depth, width, height, depth);
459
460       for (q = 0; q < depth;) {
461          for (j = 0; j < pack_x_nr && q < depth; j++, q++) {
462             i915_texture_set_image_offset(tex, level, q, x, y + tex->total_nblocksy);
463             x += pack_x_pitch;
464          }
465
466          x = 0;
467          y += pack_y_pitch;
468       }
469
470       tex->total_nblocksy += y;
471
472       if (pack_x_pitch > 4) {
473          pack_x_pitch >>= 1;
474          pack_x_nr <<= 1;
475          assert(pack_x_pitch * pack_x_nr * util_format_get_blocksize(pt->format) <= tex->stride);
476       }
477
478       if (pack_y_pitch > 2) {
479          pack_y_pitch >>= 1;
480       }
481
482       width = u_minify(width, 1);
483       height = u_minify(height, 1);
484       depth = u_minify(depth, 1);
485       nblocksy = util_format_get_nblocksy(pt->format, height);
486    }
487 }
488
489 static void
490 i945_texture_layout_cube(struct i915_texture *tex)
491 {
492    struct pipe_resource *pt = &tex->b.b;
493    unsigned level;
494
495    const unsigned nblocks = util_format_get_nblocksx(pt->format, pt->width0);
496    unsigned face;
497    unsigned width = pt->width0;
498    unsigned height = pt->height0;
499
500    /*
501    printf("%s %i, %i\n", __FUNCTION__, pt->width0, pt->height0);
502    */
503
504    assert(width == height); /* cubemap images are square */
505
506    /*
507     * XXX Should only be used for compressed formats. But lets
508     * keep this code active just in case.
509     *
510     * Depending on the size of the largest images, pitch can be
511     * determined either by the old-style packing of cubemap faces,
512     * or the final row of 4x4, 2x2 and 1x1 faces below this.
513     */
514    if (nblocks > 32)
515       tex->stride = align(nblocks * util_format_get_blocksize(pt->format) * 2, 4);
516    else
517       tex->stride = 14 * 8 * util_format_get_blocksize(pt->format);
518
519    tex->total_nblocksy = nblocks * 4;
520
521    /* Set all the levels to effectively occupy the whole rectangular region.
522    */
523    for (level = 0; level <= pt->last_level; level++) {
524       i915_texture_set_level_info(tex, level, 6, width, height, 1);
525       width /= 2;
526       height /= 2;
527    }
528
529    for (face = 0; face < 6; face++) {
530       unsigned x = initial_offsets[face][0] * nblocks;
531       unsigned y = initial_offsets[face][1] * nblocks;
532       unsigned d = nblocks;
533
534 #if 0 /* Fix and enable this code for compressed formats */
535       if (nblocks == 4 && face >= 4) {
536          y = tex->total_height - 4;
537          x = (face - 4) * 8;
538       }
539       else if (nblocks < 4 && (face > 0)) {
540          y = tex->total_height - 4;
541          x = face * 8;
542       }
543 #endif
544
545       for (level = 0; level <= pt->last_level; level++) {
546          i915_texture_set_image_offset(tex, level, face, x, y);
547
548          d >>= 1;
549
550 #if 0 /* Fix and enable this code for compressed formats */
551          switch (d) {
552             case 4:
553                switch (face) {
554                   case PIPE_TEX_FACE_POS_X:
555                   case PIPE_TEX_FACE_NEG_X:
556                      x += step_offsets[face][0] * d;
557                      y += step_offsets[face][1] * d;
558                      break;
559                   case PIPE_TEX_FACE_POS_Y:
560                   case PIPE_TEX_FACE_NEG_Y:
561                      y += 12;
562                      x -= 8;
563                      break;
564                   case PIPE_TEX_FACE_POS_Z:
565                   case PIPE_TEX_FACE_NEG_Z:
566                      y = tex->total_height - 4;
567                      x = (face - 4) * 8;
568                      break;
569                }
570             case 2:
571                y = tex->total_height - 4;
572                x = 16 + face * 8;
573                break;
574
575             case 1:
576                x += 48;
577                break;
578             default:
579 #endif
580                x += step_offsets[face][0] * d;
581                y += step_offsets[face][1] * d;
582 #if 0
583                break;
584          }
585 #endif
586       }
587    }
588 }
589
590 static boolean
591 i945_texture_layout(struct i915_texture * tex)
592 {
593    struct pipe_resource *pt = &tex->b.b;
594
595    switch (pt->target) {
596    case PIPE_TEXTURE_1D:
597    case PIPE_TEXTURE_2D:
598       i945_texture_layout_2d(tex);
599       break;
600    case PIPE_TEXTURE_3D:
601       i945_texture_layout_3d(tex);
602       break;
603    case PIPE_TEXTURE_CUBE:
604       i945_texture_layout_cube(tex);
605       break;
606    default:
607       assert(0);
608       return FALSE;
609    }
610
611    return TRUE;
612 }
613
614
615
616 /*
617  * Screen texture functions
618  */
619
620
621
622 static boolean
623 i915_texture_get_handle(struct pipe_screen * screen,
624                         struct pipe_resource *texture,
625                         struct winsys_handle *whandle)
626 {
627    struct i915_screen *is = i915_screen(screen);
628    struct i915_texture *tex = i915_texture(texture);
629    struct i915_winsys *iws = is->iws;
630
631    return iws->buffer_get_handle(iws, tex->buffer, whandle, tex->stride);
632 }
633
634
635 static void
636 i915_texture_destroy(struct pipe_screen *screen,
637                      struct pipe_resource *pt)
638 {
639    struct i915_texture *tex = i915_texture(pt);
640    struct i915_winsys *iws = i915_screen(screen)->iws;
641    uint i;
642
643    /*
644      DBG("%s deleting %p\n", __FUNCTION__, (void *) tex);
645    */
646
647    iws->buffer_destroy(iws, tex->buffer);
648
649    for (i = 0; i < Elements(tex->image_offset); i++)
650       if (tex->image_offset[i])
651          FREE(tex->image_offset[i]);
652
653    FREE(tex);
654 }
655
656 static struct pipe_transfer * 
657 i915_texture_get_transfer(struct pipe_context *context,
658                           struct pipe_resource *resource,
659                           struct pipe_subresource sr,
660                           unsigned usage,
661                           const struct pipe_box *box)
662 {
663    struct i915_texture *tex = i915_texture(resource);
664    struct pipe_transfer *transfer = CALLOC_STRUCT(pipe_transfer);
665    if (transfer == NULL)
666       return NULL;
667
668    transfer->resource = resource;
669    transfer->sr = sr;
670    transfer->usage = usage;
671    transfer->box = *box;
672    transfer->stride = tex->stride;
673
674    return transfer;
675 }
676
677
678 static void *
679 i915_texture_transfer_map(struct pipe_context *pipe,
680                           struct pipe_transfer *transfer)
681 {
682    struct pipe_resource *resource = transfer->resource;
683    struct i915_texture *tex = i915_texture(resource);
684    struct i915_winsys *iws = i915_screen(pipe->screen)->iws;
685    struct pipe_subresource sr = transfer->sr;
686    struct pipe_box *box = &transfer->box;
687    enum pipe_format format = resource->format;
688    unsigned offset;
689    char *map;
690
691    if (resource->target == PIPE_TEXTURE_CUBE) {
692       offset = tex->image_offset[sr.level][sr.face];
693    }
694    else if (resource->target == PIPE_TEXTURE_3D) {
695       offset = tex->image_offset[sr.level][box->z];
696    }
697    else {
698       offset = tex->image_offset[sr.level][0];
699       assert(sr.face == 0);
700       assert(box->z == 0);
701    }
702
703    map = iws->buffer_map(iws,
704                          tex->buffer,
705                          (transfer->usage & PIPE_TRANSFER_WRITE) ? TRUE : FALSE);
706    if (map == NULL)
707       return NULL;
708
709    return map + offset +
710       box->y / util_format_get_blockheight(format) * transfer->stride +
711       box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
712 }
713
714 static void
715 i915_texture_transfer_unmap(struct pipe_context *pipe,
716                             struct pipe_transfer *transfer)
717 {
718    struct i915_texture *tex = i915_texture(transfer->resource);
719    struct i915_winsys *iws = i915_screen(tex->b.b.screen)->iws;
720    iws->buffer_unmap(iws, tex->buffer);
721 }
722
723
724
725 struct u_resource_vtbl i915_texture_vtbl = 
726 {
727    i915_texture_get_handle,           /* get_handle */
728    i915_texture_destroy,              /* resource_destroy */
729    NULL,                              /* is_resource_referenced */
730    i915_texture_get_transfer,         /* get_transfer */
731    u_default_transfer_destroy,        /* transfer_destroy */
732    i915_texture_transfer_map,         /* transfer_map */
733    u_default_transfer_flush_region,   /* transfer_flush_region */
734    i915_texture_transfer_unmap,       /* transfer_unmap */
735    u_default_transfer_inline_write    /* transfer_inline_write */
736 };
737
738
739
740
741 struct pipe_resource *
742 i915_texture_create(struct pipe_screen *screen,
743                     const struct pipe_resource *template)
744 {
745    struct i915_screen *is = i915_screen(screen);
746    struct i915_winsys *iws = is->iws;
747    struct i915_texture *tex = CALLOC_STRUCT(i915_texture);
748    size_t tex_size;
749    unsigned buf_usage = 0;
750
751    if (!tex)
752       return NULL;
753
754    tex->b.b = *template;
755    tex->b.vtbl = &i915_texture_vtbl;
756    pipe_reference_init(&tex->b.b.reference, 1);
757    tex->b.b.screen = screen;
758
759    if (is->is_i945) {
760       if (!i945_texture_layout(tex))
761          goto fail;
762    } else {
763       if (!i915_texture_layout(tex))
764          goto fail;
765    }
766
767    tex_size = tex->stride * tex->total_nblocksy;
768
769    /* for scanouts and cursors, cursors arn't scanouts */
770
771    /* XXX: use a custom flag for cursors, don't rely on magically
772     * guessing that this is Xorg asking for a cursor
773     */
774    if ((template->bind & PIPE_BIND_SCANOUT) && template->width0 != 64)
775       buf_usage = I915_NEW_SCANOUT;
776    else
777       buf_usage = I915_NEW_TEXTURE;
778
779    tex->buffer = iws->buffer_create(iws, tex_size, 64, buf_usage);
780    if (!tex->buffer)
781       goto fail;
782
783    /* setup any hw fences */
784    if (tex->hw_tiled) {
785       assert(tex->sw_tiled == I915_TILE_NONE);
786       iws->buffer_set_fence_reg(iws, tex->buffer, tex->stride, tex->hw_tiled);
787    }
788
789    
790 #if 0
791    void *ptr = ws->buffer_map(ws, tex->buffer,
792       PIPE_BUFFER_USAGE_CPU_WRITE);
793    memset(ptr, 0x80, tex_size);
794    ws->buffer_unmap(ws, tex->buffer);
795 #endif
796
797    return &tex->b.b;
798
799 fail:
800    FREE(tex);
801    return NULL;
802 }
803
804 struct pipe_resource *
805 i915_texture_from_handle(struct pipe_screen * screen,
806                           const struct pipe_resource *template,
807                           struct winsys_handle *whandle)
808 {
809    struct i915_screen *is = i915_screen(screen);
810    struct i915_texture *tex;
811    struct i915_winsys *iws = is->iws;
812    struct i915_winsys_buffer *buffer;
813    unsigned stride;
814
815    assert(screen);
816
817    buffer = iws->buffer_from_handle(iws, whandle, &stride);
818
819    /* Only supports one type */
820    if (template->target != PIPE_TEXTURE_2D ||
821        template->last_level != 0 ||
822        template->depth0 != 1) {
823       return NULL;
824    }
825
826    tex = CALLOC_STRUCT(i915_texture);
827    if (!tex)
828       return NULL;
829
830    tex->b.b = *template;
831    tex->b.vtbl = &i915_texture_vtbl;
832    pipe_reference_init(&tex->b.b.reference, 1);
833    tex->b.b.screen = screen;
834
835    tex->stride = stride;
836
837    i915_texture_set_level_info(tex, 0, 1, template->width0, template->height0, 1);
838    i915_texture_set_image_offset(tex, 0, 0, 0, 0);
839
840    tex->buffer = buffer;
841
842    return &tex->b.b;
843 }
844