radeon/r200/r300: cleanup some of the renderbuffer code
[mesa.git] / src / gallium / drivers / i915simple / i915_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 "pipe/p_inlines.h"
37 #include "pipe/internal/p_winsys_screen.h"
38 #include "util/u_math.h"
39 #include "util/u_memory.h"
40
41 #include "i915_context.h"
42 #include "i915_texture.h"
43 #include "i915_debug.h"
44 #include "i915_screen.h"
45
46 /*
47 * Helper function and arrays
48 */
49
50 /**
51 * Initial offset for Cube map.
52 */
53 static const int initial_offsets[6][2] = {
54 {0, 0},
55 {0, 2},
56 {1, 0},
57 {1, 2},
58 {1, 1},
59 {1, 3}
60 };
61
62 /**
63 * Step offsets for Cube map.
64 */
65 static const int step_offsets[6][2] = {
66 {0, 2},
67 {0, 2},
68 {-1, 2},
69 {-1, 2},
70 {-1, 1},
71 {-1, 1}
72 };
73
74 static unsigned minify( unsigned d )
75 {
76 return MAX2(1, d>>1);
77 }
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 static unsigned
89 round_up(unsigned n, unsigned multiple)
90 {
91 return (n + multiple - 1) & ~(multiple - 1);
92 }
93
94
95 /*
96 * More advanced helper funcs
97 */
98
99
100 static void
101 i915_miptree_set_level_info(struct i915_texture *tex,
102 unsigned level,
103 unsigned nr_images,
104 unsigned w, unsigned h, unsigned d)
105 {
106 struct pipe_texture *pt = &tex->base;
107
108 assert(level < PIPE_MAX_TEXTURE_LEVELS);
109
110 pt->width[level] = w;
111 pt->height[level] = h;
112 pt->depth[level] = d;
113
114 pt->nblocksx[level] = pf_get_nblocksx(&pt->block, w);
115 pt->nblocksy[level] = pf_get_nblocksy(&pt->block, h);
116
117 tex->nr_images[level] = nr_images;
118
119 /*
120 DBG("%s level %d size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__,
121 level, w, h, d, x, y, tex->level_offset[level]);
122 */
123
124 /* Not sure when this would happen, but anyway:
125 */
126 if (tex->image_offset[level]) {
127 FREE(tex->image_offset[level]);
128 tex->image_offset[level] = NULL;
129 }
130
131 assert(nr_images);
132 assert(!tex->image_offset[level]);
133
134 tex->image_offset[level] = (unsigned *) MALLOC(nr_images * sizeof(unsigned));
135 tex->image_offset[level][0] = 0;
136 }
137
138 static void
139 i915_miptree_set_image_offset(struct i915_texture *tex,
140 unsigned level, unsigned img, unsigned x, unsigned y)
141 {
142 if (img == 0 && level == 0)
143 assert(x == 0 && y == 0);
144
145 assert(img < tex->nr_images[level]);
146
147 tex->image_offset[level][img] = y * tex->stride + x * tex->base.block.size;
148
149 /*
150 printf("%s level %d img %d pos %d,%d image_offset %x\n",
151 __FUNCTION__, level, img, x, y, tex->image_offset[level][img]);
152 */
153 }
154
155
156 /*
157 * Layout functions
158 */
159
160
161 /**
162 * Special case to deal with display targets.
163 */
164 static boolean
165 i915_displaytarget_layout(struct i915_texture *tex)
166 {
167 struct pipe_texture *pt = &tex->base;
168
169 if (pt->last_level > 0 || pt->block.size != 4)
170 return 0;
171
172 i915_miptree_set_level_info( tex, 0, 1,
173 tex->base.width[0],
174 tex->base.height[0],
175 1 );
176 i915_miptree_set_image_offset( tex, 0, 0, 0, 0 );
177
178 if (tex->base.width[0] >= 128) {
179 tex->stride = power_of_two(tex->base.nblocksx[0] * pt->block.size);
180 tex->total_nblocksy = round_up(tex->base.nblocksy[0], 8);
181 #if 0 /* used for tiled display targets */
182 tex->tiled = 1;
183 #endif
184 } else {
185 tex->stride = round_up(tex->base.nblocksx[0] * pt->block.size, 64);
186 tex->total_nblocksy = tex->base.nblocksy[0];
187 }
188
189 /*
190 printf("%s size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__,
191 tex->base.width[0], tex->base.height[0], pt->block.size,
192 tex->stride, tex->total_nblocksy, tex->stride * tex->total_nblocksy);
193 */
194
195 return 1;
196 }
197
198 static void
199 i945_miptree_layout_2d( struct i915_texture *tex )
200 {
201 struct pipe_texture *pt = &tex->base;
202 const int align_x = 2, align_y = 4;
203 unsigned level;
204 unsigned x = 0;
205 unsigned y = 0;
206 unsigned width = pt->width[0];
207 unsigned height = pt->height[0];
208 unsigned nblocksx = pt->nblocksx[0];
209 unsigned nblocksy = pt->nblocksy[0];
210
211 /* used for tiled display targets */
212 if (0)
213 if (i915_displaytarget_layout(tex))
214 return;
215
216 tex->stride = round_up(pt->nblocksx[0] * pt->block.size, 4);
217
218 /* May need to adjust pitch to accomodate the placement of
219 * the 2nd mipmap level. This occurs when the alignment
220 * constraints of mipmap placement push the right edge of the
221 * 2nd mipmap level out past the width of its parent.
222 */
223 if (pt->last_level > 0) {
224 unsigned mip1_nblocksx
225 = align(pf_get_nblocksx(&pt->block, minify(width)), align_x)
226 + pf_get_nblocksx(&pt->block, minify(minify(width)));
227
228 if (mip1_nblocksx > nblocksx)
229 tex->stride = mip1_nblocksx * pt->block.size;
230 }
231
232 /* Pitch must be a whole number of dwords
233 */
234 tex->stride = align(tex->stride, 64);
235 tex->total_nblocksy = 0;
236
237 for (level = 0; level <= pt->last_level; level++) {
238 i915_miptree_set_level_info(tex, level, 1, width, height, 1);
239 i915_miptree_set_image_offset(tex, level, 0, x, y);
240
241 nblocksy = align(nblocksy, align_y);
242
243 /* Because the images are packed better, the final offset
244 * might not be the maximal one:
245 */
246 tex->total_nblocksy = MAX2(tex->total_nblocksy, y + nblocksy);
247
248 /* Layout_below: step right after second mipmap level.
249 */
250 if (level == 1) {
251 x += align(nblocksx, align_x);
252 }
253 else {
254 y += nblocksy;
255 }
256
257 width = minify(width);
258 height = minify(height);
259 nblocksx = pf_get_nblocksx(&pt->block, width);
260 nblocksy = pf_get_nblocksy(&pt->block, height);
261 }
262 }
263
264 static void
265 i945_miptree_layout_cube(struct i915_texture *tex)
266 {
267 struct pipe_texture *pt = &tex->base;
268 unsigned level;
269
270 const unsigned nblocks = pt->nblocksx[0];
271 unsigned face;
272 unsigned width = pt->width[0];
273 unsigned height = pt->height[0];
274
275 /*
276 printf("%s %i, %i\n", __FUNCTION__, pt->width[0], pt->height[0]);
277 */
278
279 assert(width == height); /* cubemap images are square */
280
281 /*
282 * XXX Should only be used for compressed formats. But lets
283 * keep this code active just in case.
284 *
285 * Depending on the size of the largest images, pitch can be
286 * determined either by the old-style packing of cubemap faces,
287 * or the final row of 4x4, 2x2 and 1x1 faces below this.
288 */
289 if (nblocks > 32)
290 tex->stride = round_up(nblocks * pt->block.size * 2, 4);
291 else
292 tex->stride = 14 * 8 * pt->block.size;
293
294 tex->total_nblocksy = nblocks * 4;
295
296 /* Set all the levels to effectively occupy the whole rectangular region.
297 */
298 for (level = 0; level <= pt->last_level; level++) {
299 i915_miptree_set_level_info(tex, level, 6, width, height, 1);
300 width /= 2;
301 height /= 2;
302 }
303
304 for (face = 0; face < 6; face++) {
305 unsigned x = initial_offsets[face][0] * nblocks;
306 unsigned y = initial_offsets[face][1] * nblocks;
307 unsigned d = nblocks;
308
309 #if 0 /* Fix and enable this code for compressed formats */
310 if (nblocks == 4 && face >= 4) {
311 y = tex->total_height - 4;
312 x = (face - 4) * 8;
313 }
314 else if (nblocks < 4 && (face > 0)) {
315 y = tex->total_height - 4;
316 x = face * 8;
317 }
318 #endif
319
320 for (level = 0; level <= pt->last_level; level++) {
321 i915_miptree_set_image_offset(tex, level, face, x, y);
322
323 d >>= 1;
324
325 #if 0 /* Fix and enable this code for compressed formats */
326 switch (d) {
327 case 4:
328 switch (face) {
329 case PIPE_TEX_FACE_POS_X:
330 case PIPE_TEX_FACE_NEG_X:
331 x += step_offsets[face][0] * d;
332 y += step_offsets[face][1] * d;
333 break;
334 case PIPE_TEX_FACE_POS_Y:
335 case PIPE_TEX_FACE_NEG_Y:
336 y += 12;
337 x -= 8;
338 break;
339 case PIPE_TEX_FACE_POS_Z:
340 case PIPE_TEX_FACE_NEG_Z:
341 y = tex->total_height - 4;
342 x = (face - 4) * 8;
343 break;
344 }
345 case 2:
346 y = tex->total_height - 4;
347 x = 16 + face * 8;
348 break;
349
350 case 1:
351 x += 48;
352 break;
353 default:
354 #endif
355 x += step_offsets[face][0] * d;
356 y += step_offsets[face][1] * d;
357 #if 0
358 break;
359 }
360 #endif
361 }
362 }
363 }
364
365 static boolean
366 i915_miptree_layout(struct i915_texture * tex)
367 {
368 struct pipe_texture *pt = &tex->base;
369 unsigned level;
370
371 switch (pt->target) {
372 case PIPE_TEXTURE_CUBE: {
373 const unsigned nblocks = pt->nblocksx[0];
374 unsigned face;
375 unsigned width = pt->width[0], height = pt->height[0];
376
377 assert(width == height); /* cubemap images are square */
378
379 /* double pitch for cube layouts */
380 tex->stride = round_up(nblocks * pt->block.size * 2, 4);
381 tex->total_nblocksy = nblocks * 4;
382
383 for (level = 0; level <= pt->last_level; level++) {
384 i915_miptree_set_level_info(tex, level, 6,
385 width, height,
386 1);
387 width /= 2;
388 height /= 2;
389 }
390
391 for (face = 0; face < 6; face++) {
392 unsigned x = initial_offsets[face][0] * nblocks;
393 unsigned y = initial_offsets[face][1] * nblocks;
394 unsigned d = nblocks;
395
396 for (level = 0; level <= pt->last_level; level++) {
397 i915_miptree_set_image_offset(tex, level, face, x, y);
398 d >>= 1;
399 x += step_offsets[face][0] * d;
400 y += step_offsets[face][1] * d;
401 }
402 }
403 break;
404 }
405 case PIPE_TEXTURE_3D:{
406 unsigned width = pt->width[0];
407 unsigned height = pt->height[0];
408 unsigned depth = pt->depth[0];
409 unsigned nblocksx = pt->nblocksx[0];
410 unsigned nblocksy = pt->nblocksy[0];
411 unsigned stack_nblocksy = 0;
412
413 /* Calculate the size of a single slice.
414 */
415 tex->stride = round_up(pt->nblocksx[0] * pt->block.size, 4);
416
417 /* XXX: hardware expects/requires 9 levels at minimum.
418 */
419 for (level = 0; level <= MAX2(8, pt->last_level);
420 level++) {
421 i915_miptree_set_level_info(tex, level, depth,
422 width, height, depth);
423
424
425 stack_nblocksy += MAX2(2, nblocksy);
426
427 width = minify(width);
428 height = minify(height);
429 depth = minify(depth);
430 nblocksx = pf_get_nblocksx(&pt->block, width);
431 nblocksy = pf_get_nblocksy(&pt->block, height);
432 }
433
434 /* Fixup depth image_offsets:
435 */
436 depth = pt->depth[0];
437 for (level = 0; level <= pt->last_level; level++) {
438 unsigned i;
439 for (i = 0; i < depth; i++)
440 i915_miptree_set_image_offset(tex, level, i,
441 0, i * stack_nblocksy);
442
443 depth = minify(depth);
444 }
445
446
447 /* Multiply slice size by texture depth for total size. It's
448 * remarkable how wasteful of memory the i915 texture layouts
449 * are. They are largely fixed in the i945.
450 */
451 tex->total_nblocksy = stack_nblocksy * pt->depth[0];
452 break;
453 }
454
455 default:{
456 unsigned width = pt->width[0];
457 unsigned height = pt->height[0];
458 unsigned nblocksx = pt->nblocksx[0];
459 unsigned nblocksy = pt->nblocksy[0];
460
461 tex->stride = round_up(pt->nblocksx[0] * pt->block.size, 4);
462 tex->total_nblocksy = 0;
463
464 for (level = 0; level <= pt->last_level; level++) {
465 i915_miptree_set_level_info(tex, level, 1,
466 width, height, 1);
467 i915_miptree_set_image_offset(tex, level, 0,
468 0, tex->total_nblocksy);
469
470 nblocksy = round_up(MAX2(2, nblocksy), 2);
471
472 tex->total_nblocksy += nblocksy;
473
474 width = minify(width);
475 height = minify(height);
476 nblocksx = pf_get_nblocksx(&pt->block, width);
477 nblocksy = pf_get_nblocksy(&pt->block, height);
478 }
479 break;
480 }
481 }
482 /*
483 DBG("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__,
484 tex->pitch,
485 tex->total_nblocksy, pt->block.size, tex->stride * tex->total_nblocksy);
486 */
487
488 return TRUE;
489 }
490
491
492 static boolean
493 i945_miptree_layout(struct i915_texture * tex)
494 {
495 struct pipe_texture *pt = &tex->base;
496 unsigned level;
497
498 switch (pt->target) {
499 case PIPE_TEXTURE_CUBE:
500 i945_miptree_layout_cube(tex);
501 break;
502 case PIPE_TEXTURE_3D:{
503 unsigned width = pt->width[0];
504 unsigned height = pt->height[0];
505 unsigned depth = pt->depth[0];
506 unsigned nblocksx = pt->nblocksx[0];
507 unsigned nblocksy = pt->nblocksy[0];
508 unsigned pack_x_pitch, pack_x_nr;
509 unsigned pack_y_pitch;
510
511 tex->stride = round_up(pt->nblocksx[0] * pt->block.size, 4);
512 tex->total_nblocksy = 0;
513
514 pack_y_pitch = MAX2(pt->nblocksy[0], 2);
515 pack_x_pitch = tex->stride / pt->block.size;
516 pack_x_nr = 1;
517
518 for (level = 0; level <= pt->last_level; level++) {
519 unsigned nr_images = pt->target == PIPE_TEXTURE_3D ? depth : 6;
520 int x = 0;
521 int y = 0;
522 unsigned q, j;
523
524 i915_miptree_set_level_info(tex, level, nr_images,
525 width, height, depth);
526
527 for (q = 0; q < nr_images;) {
528 for (j = 0; j < pack_x_nr && q < nr_images; j++, q++) {
529 i915_miptree_set_image_offset(tex, level, q, x, y + tex->total_nblocksy);
530 x += pack_x_pitch;
531 }
532
533 x = 0;
534 y += pack_y_pitch;
535 }
536
537
538 tex->total_nblocksy += y;
539
540 if (pack_x_pitch > 4) {
541 pack_x_pitch >>= 1;
542 pack_x_nr <<= 1;
543 assert(pack_x_pitch * pack_x_nr * pt->block.size <= tex->stride);
544 }
545
546 if (pack_y_pitch > 2) {
547 pack_y_pitch >>= 1;
548 }
549
550 width = minify(width);
551 height = minify(height);
552 depth = minify(depth);
553 nblocksx = pf_get_nblocksx(&pt->block, width);
554 nblocksy = pf_get_nblocksy(&pt->block, height);
555 }
556 break;
557 }
558
559 case PIPE_TEXTURE_1D:
560 case PIPE_TEXTURE_2D:
561 // case PIPE_TEXTURE_RECTANGLE:
562 i945_miptree_layout_2d(tex);
563 break;
564 default:
565 assert(0);
566 return FALSE;
567 }
568
569 /*
570 DBG("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__,
571 tex->pitch,
572 tex->total_nblocksy, pt->block.size, tex->stride * tex->total_nblocksy);
573 */
574
575 return TRUE;
576 }
577
578
579 static struct pipe_texture *
580 i915_texture_create(struct pipe_screen *screen,
581 const struct pipe_texture *templat)
582 {
583 struct i915_screen *i915screen = i915_screen(screen);
584 struct pipe_winsys *ws = screen->winsys;
585 struct i915_texture *tex = CALLOC_STRUCT(i915_texture);
586 size_t tex_size;
587
588 if (!tex)
589 return NULL;
590
591 tex->base = *templat;
592 tex->base.refcount = 1;
593 tex->base.screen = screen;
594
595 tex->base.nblocksx[0] = pf_get_nblocksx(&tex->base.block, tex->base.width[0]);
596 tex->base.nblocksy[0] = pf_get_nblocksy(&tex->base.block, tex->base.height[0]);
597
598 if (i915screen->is_i945) {
599 if (!i945_miptree_layout(tex))
600 goto fail;
601 } else {
602 if (!i915_miptree_layout(tex))
603 goto fail;
604 }
605
606 tex_size = tex->stride * tex->total_nblocksy;
607
608 tex->buffer = ws->buffer_create(ws, 64,
609 PIPE_BUFFER_USAGE_PIXEL,
610 tex_size);
611
612 if (!tex->buffer)
613 goto fail;
614
615 #if 0
616 void *ptr = ws->buffer_map(ws, tex->buffer,
617 PIPE_BUFFER_USAGE_CPU_WRITE);
618 memset(ptr, 0x80, tex_size);
619 ws->buffer_unmap(ws, tex->buffer);
620 #endif
621
622 return &tex->base;
623
624 fail:
625 FREE(tex);
626 return NULL;
627 }
628
629
630 static void
631 i915_texture_release(struct pipe_screen *screen,
632 struct pipe_texture **pt)
633 {
634 if (!*pt)
635 return;
636
637 /*
638 DBG("%s %p refcount will be %d\n",
639 __FUNCTION__, (void *) *pt, (*pt)->refcount - 1);
640 */
641 if (--(*pt)->refcount <= 0) {
642 struct i915_texture *tex = (struct i915_texture *)*pt;
643 uint i;
644
645 /*
646 DBG("%s deleting %p\n", __FUNCTION__, (void *) tex);
647 */
648
649 pipe_buffer_reference(screen, &tex->buffer, NULL);
650
651 for (i = 0; i < PIPE_MAX_TEXTURE_LEVELS; i++)
652 if (tex->image_offset[i])
653 FREE(tex->image_offset[i]);
654
655 FREE(tex);
656 }
657 *pt = NULL;
658 }
659
660 static struct pipe_surface *
661 i915_get_tex_surface(struct pipe_screen *screen,
662 struct pipe_texture *pt,
663 unsigned face, unsigned level, unsigned zslice,
664 unsigned flags)
665 {
666 struct i915_texture *tex = (struct i915_texture *)pt;
667 struct pipe_surface *ps;
668 unsigned offset; /* in bytes */
669
670 if (pt->target == PIPE_TEXTURE_CUBE) {
671 offset = tex->image_offset[level][face];
672 }
673 else if (pt->target == PIPE_TEXTURE_3D) {
674 offset = tex->image_offset[level][zslice];
675 }
676 else {
677 offset = tex->image_offset[level][0];
678 assert(face == 0);
679 assert(zslice == 0);
680 }
681
682 ps = CALLOC_STRUCT(pipe_surface);
683 if (ps) {
684 ps->refcount = 1;
685 pipe_texture_reference(&ps->texture, pt);
686 ps->format = pt->format;
687 ps->width = pt->width[level];
688 ps->height = pt->height[level];
689 ps->block = pt->block;
690 ps->nblocksx = pt->nblocksx[level];
691 ps->nblocksy = pt->nblocksy[level];
692 ps->stride = tex->stride;
693 ps->offset = offset;
694 ps->usage = flags;
695 ps->status = PIPE_SURFACE_STATUS_DEFINED;
696 }
697 return ps;
698 }
699
700 static struct pipe_texture *
701 i915_texture_blanket(struct pipe_screen * screen,
702 const struct pipe_texture *base,
703 const unsigned *stride,
704 struct pipe_buffer *buffer)
705 {
706 struct i915_texture *tex;
707 assert(screen);
708
709 /* Only supports one type */
710 if (base->target != PIPE_TEXTURE_2D ||
711 base->last_level != 0 ||
712 base->depth[0] != 1) {
713 return NULL;
714 }
715
716 tex = CALLOC_STRUCT(i915_texture);
717 if (!tex)
718 return NULL;
719
720 tex->base = *base;
721 tex->base.refcount = 1;
722 tex->base.screen = screen;
723
724 tex->stride = stride[0];
725
726 i915_miptree_set_level_info(tex, 0, 1, base->width[0], base->height[0], 1);
727 i915_miptree_set_image_offset(tex, 0, 0, 0, 0);
728
729 pipe_buffer_reference(screen, &tex->buffer, buffer);
730
731 return &tex->base;
732 }
733
734 void
735 i915_init_texture_functions(struct i915_context *i915)
736 {
737 // i915->pipe.texture_update = i915_texture_update;
738 }
739
740 static void
741 i915_tex_surface_release(struct pipe_screen *screen,
742 struct pipe_surface **surface)
743 {
744 struct pipe_surface *surf = *surface;
745
746 if (--surf->refcount == 0) {
747
748 /* This really should not be possible, but it's actually
749 * happening quite a bit... Will fix.
750 */
751 if (surf->status == PIPE_SURFACE_STATUS_CLEAR) {
752 debug_printf("XXX destroying a surface with pending clears...\n");
753 assert(0);
754 }
755
756 pipe_texture_reference(&surf->texture, NULL);
757 FREE(surf);
758 }
759
760 *surface = NULL;
761 }
762
763 void
764 i915_init_screen_texture_functions(struct pipe_screen *screen)
765 {
766 screen->texture_create = i915_texture_create;
767 screen->texture_release = i915_texture_release;
768 screen->get_tex_surface = i915_get_tex_surface;
769 screen->texture_blanket = i915_texture_blanket;
770 screen->tex_surface_release = i915_tex_surface_release;
771 }