Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/i915/i915_resource_texture.c
4570 views
1
/**************************************************************************
2
*
3
* Copyright 2006 VMware, Inc.
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 VMWARE 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 <[email protected]>
30
* Michel Dänzer <[email protected]>
31
*/
32
33
#include "pipe/p_context.h"
34
#include "pipe/p_defines.h"
35
#include "pipe/p_state.h"
36
#include "util/format/u_format.h"
37
#include "util/u_inlines.h"
38
#include "util/u_math.h"
39
#include "util/u_memory.h"
40
#include "util/u_rect.h"
41
42
#include "i915_context.h"
43
#include "i915_debug.h"
44
#include "i915_resource.h"
45
#include "i915_screen.h"
46
#include "i915_winsys.h"
47
48
#define DEBUG_TEXTURES 0
49
50
/*
51
* Helper function and arrays
52
*/
53
54
/**
55
* Initial offset for Cube map.
56
*/
57
static const int initial_offsets[6][2] = {
58
[PIPE_TEX_FACE_POS_X] = {0, 0}, [PIPE_TEX_FACE_POS_Y] = {1, 0},
59
[PIPE_TEX_FACE_POS_Z] = {1, 1}, [PIPE_TEX_FACE_NEG_X] = {0, 2},
60
[PIPE_TEX_FACE_NEG_Y] = {1, 2}, [PIPE_TEX_FACE_NEG_Z] = {1, 3},
61
};
62
63
/**
64
* Step offsets for Cube map.
65
*/
66
static const int step_offsets[6][2] = {
67
[PIPE_TEX_FACE_POS_X] = {0, 2}, [PIPE_TEX_FACE_POS_Y] = {-1, 2},
68
[PIPE_TEX_FACE_POS_Z] = {-1, 1}, [PIPE_TEX_FACE_NEG_X] = {0, 2},
69
[PIPE_TEX_FACE_NEG_Y] = {-1, 2}, [PIPE_TEX_FACE_NEG_Z] = {-1, 1},
70
};
71
72
/**
73
* For compressed level 2
74
*/
75
static const int bottom_offsets[6] = {
76
[PIPE_TEX_FACE_POS_X] = 16 + 0 * 8, [PIPE_TEX_FACE_POS_Y] = 16 + 1 * 8,
77
[PIPE_TEX_FACE_POS_Z] = 16 + 2 * 8, [PIPE_TEX_FACE_NEG_X] = 16 + 3 * 8,
78
[PIPE_TEX_FACE_NEG_Y] = 16 + 4 * 8, [PIPE_TEX_FACE_NEG_Z] = 16 + 5 * 8,
79
};
80
81
static inline unsigned
82
align_nblocksx(enum pipe_format format, unsigned width, unsigned align_to)
83
{
84
return align(util_format_get_nblocksx(format, width), align_to);
85
}
86
87
static inline unsigned
88
align_nblocksy(enum pipe_format format, unsigned width, unsigned align_to)
89
{
90
return align(util_format_get_nblocksy(format, width), align_to);
91
}
92
93
static inline unsigned
94
get_pot_stride(enum pipe_format format, unsigned width)
95
{
96
return util_next_power_of_two(util_format_get_stride(format, width));
97
}
98
99
static inline const char *
100
get_tiling_string(enum i915_winsys_buffer_tile tile)
101
{
102
switch (tile) {
103
case I915_TILE_NONE:
104
return "none";
105
case I915_TILE_X:
106
return "x";
107
case I915_TILE_Y:
108
return "y";
109
default:
110
assert(false);
111
return "?";
112
}
113
}
114
115
/*
116
* More advanced helper funcs
117
*/
118
119
static void
120
i915_texture_set_level_info(struct i915_texture *tex, unsigned level,
121
unsigned nr_images)
122
{
123
assert(level < ARRAY_SIZE(tex->nr_images));
124
assert(nr_images);
125
assert(!tex->image_offset[level]);
126
127
tex->nr_images[level] = nr_images;
128
tex->image_offset[level] = MALLOC(nr_images * sizeof(struct offset_pair));
129
tex->image_offset[level][0].nblocksx = 0;
130
tex->image_offset[level][0].nblocksy = 0;
131
}
132
133
unsigned
134
i915_texture_offset(const struct i915_texture *tex, unsigned level,
135
unsigned layer)
136
{
137
unsigned x, y;
138
x = tex->image_offset[level][layer].nblocksx *
139
util_format_get_blocksize(tex->b.format);
140
y = tex->image_offset[level][layer].nblocksy;
141
142
return y * tex->stride + x;
143
}
144
145
static void
146
i915_texture_set_image_offset(struct i915_texture *tex, unsigned level,
147
unsigned img, unsigned nblocksx,
148
unsigned nblocksy)
149
{
150
/* for the first image and level make sure offset is zero */
151
assert(!(img == 0 && level == 0) || (nblocksx == 0 && nblocksy == 0));
152
assert(img < tex->nr_images[level]);
153
154
tex->image_offset[level][img].nblocksx = nblocksx;
155
tex->image_offset[level][img].nblocksy = nblocksy;
156
157
#if DEBUG_TEXTURES
158
debug_printf("%s: %p level %u, img %u (%u, %u)\n", __FUNCTION__, tex, level,
159
img, x, y);
160
#endif
161
}
162
163
static enum i915_winsys_buffer_tile
164
i915_texture_tiling(struct i915_screen *is, struct i915_texture *tex)
165
{
166
if (!is->debug.tiling)
167
return I915_TILE_NONE;
168
169
if (tex->b.target == PIPE_TEXTURE_1D)
170
return I915_TILE_NONE;
171
172
if (util_format_is_s3tc(tex->b.format))
173
return I915_TILE_X;
174
175
if (is->debug.use_blitter)
176
return I915_TILE_X;
177
else
178
return I915_TILE_Y;
179
}
180
181
/*
182
* Shared layout functions
183
*/
184
185
/**
186
* Special case to deal with scanout textures.
187
*/
188
static bool
189
i9x5_scanout_layout(struct i915_texture *tex)
190
{
191
struct pipe_resource *pt = &tex->b;
192
193
if (pt->last_level > 0 || util_format_get_blocksize(pt->format) != 4)
194
return false;
195
196
i915_texture_set_level_info(tex, 0, 1);
197
i915_texture_set_image_offset(tex, 0, 0, 0, 0);
198
199
if (pt->width0 >= 240) {
200
tex->stride = align(util_format_get_stride(pt->format, pt->width0), 64);
201
tex->total_nblocksy = align_nblocksy(pt->format, pt->height0, 8);
202
tex->tiling = I915_TILE_X;
203
/* special case for cursors */
204
} else if (pt->width0 == 64 && pt->height0 == 64) {
205
tex->stride = get_pot_stride(pt->format, pt->width0);
206
tex->total_nblocksy = align_nblocksy(pt->format, pt->height0, 8);
207
} else {
208
return false;
209
}
210
211
#if DEBUG_TEXTURE
212
debug_printf("%s size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__,
213
pt->width0, pt->height0, util_format_get_blocksize(pt->format),
214
tex->stride, tex->total_nblocksy,
215
tex->stride * tex->total_nblocksy);
216
#endif
217
218
return true;
219
}
220
221
/**
222
* Special case to deal with shared textures.
223
*/
224
static bool
225
i9x5_display_target_layout(struct i915_texture *tex)
226
{
227
struct pipe_resource *pt = &tex->b;
228
229
if (pt->last_level > 0 || util_format_get_blocksize(pt->format) != 4)
230
return false;
231
232
/* fallback to normal textures for small textures */
233
if (pt->width0 < 240)
234
return false;
235
236
i915_texture_set_level_info(tex, 0, 1);
237
i915_texture_set_image_offset(tex, 0, 0, 0, 0);
238
239
tex->stride = align(util_format_get_stride(pt->format, pt->width0), 64);
240
tex->total_nblocksy = align_nblocksy(pt->format, pt->height0, 8);
241
tex->tiling = I915_TILE_X;
242
243
#if DEBUG_TEXTURE
244
debug_printf("%s size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__,
245
pt->width0, pt->height0, util_format_get_blocksize(pt->format),
246
tex->stride, tex->total_nblocksy,
247
tex->stride * tex->total_nblocksy);
248
#endif
249
250
return true;
251
}
252
253
/**
254
* Helper function for special layouts
255
*/
256
static bool
257
i9x5_special_layout(struct i915_texture *tex)
258
{
259
struct pipe_resource *pt = &tex->b;
260
261
/* Scanouts needs special care */
262
if (pt->bind & PIPE_BIND_SCANOUT)
263
if (i9x5_scanout_layout(tex))
264
return true;
265
266
/* Shared buffers needs to be compatible with X servers
267
*
268
* XXX: need a better name than shared for this if it is to be part
269
* of core gallium, and probably move the flag to resource.flags,
270
* rather than bindings.
271
*/
272
if (pt->bind & (PIPE_BIND_SHARED | PIPE_BIND_DISPLAY_TARGET))
273
if (i9x5_display_target_layout(tex))
274
return true;
275
276
return false;
277
}
278
279
/**
280
* Cube layout used on i915 and for non-compressed textures on i945.
281
*
282
* Hardware layout looks like:
283
*
284
* +-------+-------+
285
* | | |
286
* | | |
287
* | | |
288
* | +x | +y |
289
* | | |
290
* | | |
291
* | | |
292
* | | |
293
* +---+---+-------+
294
* | | | |
295
* | +x| +y| |
296
* | | | |
297
* | | | |
298
* +-+-+---+ +z |
299
* | | | | |
300
* +-+-+ +z| |
301
* | | | |
302
* +-+-+---+-------+
303
* | | |
304
* | | |
305
* | | |
306
* | -x | -y |
307
* | | |
308
* | | |
309
* | | |
310
* | | |
311
* +---+---+-------+
312
* | | | |
313
* | -x| -y| |
314
* | | | |
315
* | | | |
316
* +-+-+---+ -z |
317
* | | | | |
318
* +-+-+ -z| |
319
* | | | |
320
* +-+---+-------+
321
*
322
*/
323
static void
324
i9x5_texture_layout_cube(struct i915_texture *tex)
325
{
326
struct pipe_resource *pt = &tex->b;
327
unsigned width = util_next_power_of_two(pt->width0);
328
const unsigned nblocks = util_format_get_nblocksx(pt->format, width);
329
unsigned level;
330
unsigned face;
331
332
assert(pt->width0 == pt->height0); /* cubemap images are square */
333
334
/* double pitch for cube layouts */
335
tex->stride = align(nblocks * util_format_get_blocksize(pt->format) * 2, 4);
336
tex->total_nblocksy = nblocks * 4;
337
338
for (level = 0; level <= pt->last_level; level++)
339
i915_texture_set_level_info(tex, level, 6);
340
341
for (face = 0; face < 6; face++) {
342
unsigned x = initial_offsets[face][0] * nblocks;
343
unsigned y = initial_offsets[face][1] * nblocks;
344
unsigned d = nblocks;
345
346
for (level = 0; level <= pt->last_level; level++) {
347
i915_texture_set_image_offset(tex, level, face, x, y);
348
d >>= 1;
349
x += step_offsets[face][0] * d;
350
y += step_offsets[face][1] * d;
351
}
352
}
353
}
354
355
/*
356
* i915 layout functions
357
*/
358
359
static void
360
i915_texture_layout_2d(struct i915_texture *tex)
361
{
362
struct pipe_resource *pt = &tex->b;
363
unsigned level;
364
unsigned width = util_next_power_of_two(pt->width0);
365
unsigned height = util_next_power_of_two(pt->height0);
366
unsigned nblocksy = util_format_get_nblocksy(pt->format, width);
367
unsigned align_y = 2;
368
369
if (util_format_is_s3tc(pt->format))
370
align_y = 1;
371
372
tex->stride = align(util_format_get_stride(pt->format, width), 4);
373
tex->total_nblocksy = 0;
374
375
for (level = 0; level <= pt->last_level; level++) {
376
i915_texture_set_level_info(tex, level, 1);
377
i915_texture_set_image_offset(tex, level, 0, 0, tex->total_nblocksy);
378
379
tex->total_nblocksy += nblocksy;
380
381
width = u_minify(width, 1);
382
height = u_minify(height, 1);
383
nblocksy = align_nblocksy(pt->format, height, align_y);
384
}
385
}
386
387
static void
388
i915_texture_layout_3d(struct i915_texture *tex)
389
{
390
struct pipe_resource *pt = &tex->b;
391
unsigned level;
392
393
unsigned width = util_next_power_of_two(pt->width0);
394
unsigned height = util_next_power_of_two(pt->height0);
395
unsigned depth = util_next_power_of_two(pt->depth0);
396
unsigned nblocksy = util_format_get_nblocksy(pt->format, height);
397
unsigned stack_nblocksy = 0;
398
399
/* Calculate the size of a single slice.
400
*/
401
tex->stride = align(util_format_get_stride(pt->format, width), 4);
402
403
/* XXX: hardware expects/requires 9 levels at minimum.
404
*/
405
for (level = 0; level <= MAX2(8, pt->last_level); level++) {
406
i915_texture_set_level_info(tex, level, depth);
407
408
stack_nblocksy += MAX2(2, nblocksy);
409
410
width = u_minify(width, 1);
411
height = u_minify(height, 1);
412
nblocksy = util_format_get_nblocksy(pt->format, height);
413
}
414
415
/* Fixup depth image_offsets:
416
*/
417
for (level = 0; level <= pt->last_level; level++) {
418
unsigned i;
419
for (i = 0; i < depth; i++)
420
i915_texture_set_image_offset(tex, level, i, 0, i * stack_nblocksy);
421
422
depth = u_minify(depth, 1);
423
}
424
425
/* Multiply slice size by texture depth for total size. It's
426
* remarkable how wasteful of memory the i915 texture layouts
427
* are. They are largely fixed in the i945.
428
*/
429
tex->total_nblocksy = stack_nblocksy * util_next_power_of_two(pt->depth0);
430
}
431
432
static bool
433
i915_texture_layout(struct i915_texture *tex)
434
{
435
switch (tex->b.target) {
436
case PIPE_TEXTURE_1D:
437
case PIPE_TEXTURE_2D:
438
case PIPE_TEXTURE_RECT:
439
if (!i9x5_special_layout(tex))
440
i915_texture_layout_2d(tex);
441
break;
442
case PIPE_TEXTURE_3D:
443
i915_texture_layout_3d(tex);
444
break;
445
case PIPE_TEXTURE_CUBE:
446
i9x5_texture_layout_cube(tex);
447
break;
448
default:
449
assert(0);
450
return false;
451
}
452
453
return true;
454
}
455
456
/*
457
* i945 layout functions
458
*/
459
460
static void
461
i945_texture_layout_2d(struct i915_texture *tex)
462
{
463
struct pipe_resource *pt = &tex->b;
464
int align_x = 4, align_y = 2;
465
unsigned level;
466
unsigned x = 0;
467
unsigned y = 0;
468
unsigned width = util_next_power_of_two(pt->width0);
469
unsigned height = util_next_power_of_two(pt->height0);
470
unsigned nblocksx = util_format_get_nblocksx(pt->format, width);
471
unsigned nblocksy = util_format_get_nblocksy(pt->format, height);
472
473
if (util_format_is_s3tc(pt->format)) {
474
align_x = 1;
475
align_y = 1;
476
}
477
478
tex->stride = align(util_format_get_stride(pt->format, width), 4);
479
480
/* May need to adjust pitch to accommodate the placement of
481
* the 2nd mipmap level. This occurs when the alignment
482
* constraints of mipmap placement push the right edge of the
483
* 2nd mipmap level out past the width of its parent.
484
*/
485
if (pt->last_level > 0) {
486
unsigned mip1_nblocksx =
487
align_nblocksx(pt->format, u_minify(width, 1), align_x) +
488
util_format_get_nblocksx(pt->format, u_minify(width, 2));
489
490
if (mip1_nblocksx > nblocksx)
491
tex->stride = mip1_nblocksx * util_format_get_blocksize(pt->format);
492
}
493
494
/* Pitch must be a whole number of dwords
495
*/
496
tex->stride = align(tex->stride, 64);
497
tex->total_nblocksy = 0;
498
499
for (level = 0; level <= pt->last_level; level++) {
500
i915_texture_set_level_info(tex, level, 1);
501
i915_texture_set_image_offset(tex, level, 0, x, y);
502
503
/* Because the images are packed better, the final offset
504
* might not be the maximal one:
505
*/
506
tex->total_nblocksy = MAX2(tex->total_nblocksy, y + nblocksy);
507
508
/* Layout_below: step right after second mipmap level.
509
*/
510
if (level == 1) {
511
x += nblocksx;
512
} else {
513
y += nblocksy;
514
}
515
516
width = u_minify(width, 1);
517
height = u_minify(height, 1);
518
nblocksx = align_nblocksx(pt->format, width, align_x);
519
nblocksy = align_nblocksy(pt->format, height, align_y);
520
}
521
}
522
523
static void
524
i945_texture_layout_3d(struct i915_texture *tex)
525
{
526
struct pipe_resource *pt = &tex->b;
527
unsigned width = util_next_power_of_two(pt->width0);
528
unsigned height = util_next_power_of_two(pt->height0);
529
unsigned depth = util_next_power_of_two(pt->depth0);
530
unsigned nblocksy = util_format_get_nblocksy(pt->format, width);
531
unsigned pack_x_pitch, pack_x_nr;
532
unsigned pack_y_pitch;
533
unsigned level;
534
535
tex->stride = align(util_format_get_stride(pt->format, width), 4);
536
tex->total_nblocksy = 0;
537
538
pack_y_pitch = MAX2(nblocksy, 2);
539
pack_x_pitch = tex->stride / util_format_get_blocksize(pt->format);
540
pack_x_nr = 1;
541
542
for (level = 0; level <= pt->last_level; level++) {
543
int x = 0;
544
int y = 0;
545
unsigned q, j;
546
547
i915_texture_set_level_info(tex, level, depth);
548
549
for (q = 0; q < depth;) {
550
for (j = 0; j < pack_x_nr && q < depth; j++, q++) {
551
i915_texture_set_image_offset(tex, level, q, x,
552
y + tex->total_nblocksy);
553
x += pack_x_pitch;
554
}
555
556
x = 0;
557
y += pack_y_pitch;
558
}
559
560
tex->total_nblocksy += y;
561
562
if (pack_x_pitch > 4) {
563
pack_x_pitch >>= 1;
564
pack_x_nr <<= 1;
565
assert(pack_x_pitch * pack_x_nr *
566
util_format_get_blocksize(pt->format) <=
567
tex->stride);
568
}
569
570
if (pack_y_pitch > 2) {
571
pack_y_pitch >>= 1;
572
}
573
574
width = u_minify(width, 1);
575
height = u_minify(height, 1);
576
depth = u_minify(depth, 1);
577
nblocksy = util_format_get_nblocksy(pt->format, height);
578
}
579
}
580
581
/**
582
* Compressed cube texture map layout for i945 and later.
583
*
584
* The hardware layout looks like the 830-915 layout, except for the small
585
* sizes. A zoomed in view of the layout for 945 is:
586
*
587
* +-------+-------+
588
* | 8x8 | 8x8 |
589
* | | |
590
* | | |
591
* | +x | +y |
592
* | | |
593
* | | |
594
* | | |
595
* | | |
596
* +---+---+-------+
597
* |4x4| | 8x8 |
598
* | +x| | |
599
* | | | |
600
* | | | |
601
* +---+ | +z |
602
* |4x4| | |
603
* | +y| | |
604
* | | | |
605
* +---+ +-------+
606
*
607
* ...
608
*
609
* +-------+-------+
610
* | 8x8 | 8x8 |
611
* | | |
612
* | | |
613
* | -x | -y |
614
* | | |
615
* | | |
616
* | | |
617
* | | |
618
* +---+---+-------+
619
* |4x4| | 8x8 |
620
* | -x| | |
621
* | | | |
622
* | | | |
623
* +---+ | -z |
624
* |4x4| | |
625
* | -y| | |
626
* | | | |
627
* +---+ +---+---+---+---+---+---+---+---+---+
628
* |4x4| |4x4| |2x2| |2x2| |2x2| |2x2|
629
* | +z| | -z| | +x| | +y| | +z| | -x| ...
630
* | | | | | | | | | | | |
631
* +---+ +---+ +---+ +---+ +---+ +---+
632
*
633
* The bottom row continues with the remaining 2x2 then the 1x1 mip contents
634
* in order, with each of them aligned to a 8x8 block boundary. Thus, for
635
* 32x32 cube maps and smaller, the bottom row layout is going to dictate the
636
* pitch of the tree. For a tree with 4x4 images, the pitch is at least
637
* 14 * 8 = 112 texels, for 2x2 it is at least 12 * 8 texels, and for 1x1
638
* it is 6 * 8 texels.
639
*/
640
static void
641
i945_texture_layout_cube(struct i915_texture *tex)
642
{
643
struct pipe_resource *pt = &tex->b;
644
unsigned width = util_next_power_of_two(pt->width0);
645
const unsigned nblocks = util_format_get_nblocksx(pt->format, width);
646
const unsigned dim = width;
647
unsigned level;
648
unsigned face;
649
650
assert(pt->width0 == pt->height0); /* cubemap images are square */
651
assert(util_format_is_s3tc(pt->format)); /* compressed only */
652
653
/*
654
* Depending on the size of the largest images, pitch can be
655
* determined either by the old-style packing of cubemap faces,
656
* or the final row of 4x4, 2x2 and 1x1 faces below this.
657
*
658
* 64 * 2 / 4 = 32
659
* 14 * 2 = 28
660
*/
661
if (width >= 64)
662
tex->stride = nblocks * 2 * util_format_get_blocksize(pt->format);
663
else
664
tex->stride = 14 * 2 * util_format_get_blocksize(pt->format);
665
666
/*
667
* Something similary apply for height as well.
668
*/
669
if (width >= 4)
670
tex->total_nblocksy = nblocks * 4 + 1;
671
else
672
tex->total_nblocksy = 1;
673
674
/* Set all the levels to effectively occupy the whole rectangular region */
675
for (level = 0; level <= pt->last_level; level++)
676
i915_texture_set_level_info(tex, level, 6);
677
678
for (face = 0; face < 6; face++) {
679
/* all calculations in pixels */
680
unsigned total_height = tex->total_nblocksy * 4;
681
unsigned x = initial_offsets[face][0] * dim;
682
unsigned y = initial_offsets[face][1] * dim;
683
unsigned d = dim;
684
685
if (dim == 4 && face >= 4) {
686
x = (face - 4) * 8;
687
y = tex->total_nblocksy * 4 - 4; /* 4 = 1 block */
688
} else if (dim < 4 && (face > 0)) {
689
x = face * 8;
690
y = total_height - 4;
691
}
692
693
for (level = 0; level <= pt->last_level; level++) {
694
i915_texture_set_image_offset(tex, level, face,
695
util_format_get_nblocksx(pt->format, x),
696
util_format_get_nblocksy(pt->format, y));
697
698
d >>= 1;
699
700
switch (d) {
701
case 4:
702
switch (face) {
703
case PIPE_TEX_FACE_POS_X:
704
case PIPE_TEX_FACE_NEG_X:
705
x += step_offsets[face][0] * d;
706
y += step_offsets[face][1] * d;
707
break;
708
case PIPE_TEX_FACE_POS_Y:
709
case PIPE_TEX_FACE_NEG_Y:
710
y += 12;
711
x -= 8;
712
break;
713
case PIPE_TEX_FACE_POS_Z:
714
case PIPE_TEX_FACE_NEG_Z:
715
y = total_height - 4;
716
x = (face - 4) * 8;
717
break;
718
}
719
break;
720
case 2:
721
y = total_height - 4;
722
x = bottom_offsets[face];
723
break;
724
case 1:
725
x += 48;
726
break;
727
default:
728
x += step_offsets[face][0] * d;
729
y += step_offsets[face][1] * d;
730
break;
731
}
732
}
733
}
734
}
735
736
static bool
737
i945_texture_layout(struct i915_texture *tex)
738
{
739
switch (tex->b.target) {
740
case PIPE_TEXTURE_1D:
741
case PIPE_TEXTURE_2D:
742
case PIPE_TEXTURE_RECT:
743
if (!i9x5_special_layout(tex))
744
i945_texture_layout_2d(tex);
745
break;
746
case PIPE_TEXTURE_3D:
747
i945_texture_layout_3d(tex);
748
break;
749
case PIPE_TEXTURE_CUBE:
750
if (!util_format_is_s3tc(tex->b.format))
751
i9x5_texture_layout_cube(tex);
752
else
753
i945_texture_layout_cube(tex);
754
break;
755
default:
756
assert(0);
757
return false;
758
}
759
760
return true;
761
}
762
763
/*
764
* Screen texture functions
765
*/
766
767
bool
768
i915_resource_get_handle(struct pipe_screen *screen,
769
struct pipe_context *context,
770
struct pipe_resource *texture,
771
struct winsys_handle *whandle, unsigned usage)
772
{
773
if (texture->target == PIPE_BUFFER)
774
return false;
775
776
struct i915_screen *is = i915_screen(screen);
777
struct i915_texture *tex = i915_texture(texture);
778
struct i915_winsys *iws = is->iws;
779
780
return iws->buffer_get_handle(iws, tex->buffer, whandle, tex->stride);
781
}
782
783
void *
784
i915_texture_transfer_map(struct pipe_context *pipe,
785
struct pipe_resource *resource, unsigned level,
786
unsigned usage, const struct pipe_box *box,
787
struct pipe_transfer **ptransfer)
788
{
789
struct i915_context *i915 = i915_context(pipe);
790
struct i915_texture *tex = i915_texture(resource);
791
struct i915_transfer *transfer = slab_alloc_st(&i915->texture_transfer_pool);
792
bool use_staging_texture = false;
793
struct i915_winsys *iws = i915_screen(pipe->screen)->iws;
794
enum pipe_format format = resource->format;
795
unsigned offset;
796
char *map;
797
798
if (!transfer)
799
return NULL;
800
801
transfer->b.resource = resource;
802
transfer->b.level = level;
803
transfer->b.usage = usage;
804
transfer->b.box = *box;
805
transfer->b.stride = tex->stride;
806
transfer->staging_texture = NULL;
807
/* XXX: handle depth textures everyhwere*/
808
transfer->b.layer_stride = 0;
809
810
/* if we use staging transfers, only support textures we can render to,
811
* because we need that for u_blitter */
812
if (i915->blitter &&
813
util_blitter_is_copy_supported(i915->blitter, resource, resource) &&
814
(usage & PIPE_MAP_WRITE) &&
815
!(usage &
816
(PIPE_MAP_READ | PIPE_MAP_DONTBLOCK | PIPE_MAP_UNSYNCHRONIZED)))
817
use_staging_texture = true;
818
819
use_staging_texture = false;
820
821
if (use_staging_texture) {
822
/*
823
* Allocate the untiled staging texture.
824
* If the alloc fails, transfer->staging_texture is NULL and we fallback
825
* to a map()
826
*/
827
transfer->staging_texture =
828
i915_texture_create(pipe->screen, resource, true);
829
}
830
831
if (resource->target != PIPE_TEXTURE_3D &&
832
resource->target != PIPE_TEXTURE_CUBE)
833
assert(box->z == 0);
834
835
if (transfer->staging_texture) {
836
tex = i915_texture(transfer->staging_texture);
837
} else {
838
/* TODO this is a sledgehammer */
839
tex = i915_texture(resource);
840
pipe->flush(pipe, NULL, 0);
841
}
842
843
offset = i915_texture_offset(tex, transfer->b.level, box->z);
844
845
map = iws->buffer_map(iws, tex->buffer,
846
(transfer->b.usage & PIPE_MAP_WRITE) ? true : false);
847
if (!map) {
848
pipe_resource_reference(&transfer->staging_texture, NULL);
849
FREE(transfer);
850
return NULL;
851
}
852
853
*ptransfer = &transfer->b;
854
855
return map + offset +
856
box->y / util_format_get_blockheight(format) * transfer->b.stride +
857
box->x / util_format_get_blockwidth(format) *
858
util_format_get_blocksize(format);
859
}
860
861
void
862
i915_texture_transfer_unmap(struct pipe_context *pipe,
863
struct pipe_transfer *transfer)
864
{
865
struct i915_context *i915 = i915_context(pipe);
866
struct i915_transfer *itransfer = (struct i915_transfer *)transfer;
867
struct i915_texture *tex = i915_texture(itransfer->b.resource);
868
struct i915_winsys *iws = i915_screen(tex->b.screen)->iws;
869
870
if (itransfer->staging_texture)
871
tex = i915_texture(itransfer->staging_texture);
872
873
iws->buffer_unmap(iws, tex->buffer);
874
875
if ((itransfer->staging_texture) && (transfer->usage & PIPE_MAP_WRITE)) {
876
struct pipe_box sbox;
877
878
u_box_origin_2d(itransfer->b.box.width, itransfer->b.box.height, &sbox);
879
pipe->resource_copy_region(pipe, itransfer->b.resource,
880
itransfer->b.level, itransfer->b.box.x,
881
itransfer->b.box.y, itransfer->b.box.z,
882
itransfer->staging_texture, 0, &sbox);
883
pipe->flush(pipe, NULL, 0);
884
pipe_resource_reference(&itransfer->staging_texture, NULL);
885
}
886
887
slab_free_st(&i915->texture_transfer_pool, itransfer);
888
}
889
890
#if 0
891
static void i915_texture_subdata(struct pipe_context *pipe,
892
struct pipe_resource *resource,
893
unsigned level,
894
unsigned usage,
895
const struct pipe_box *box,
896
const void *data,
897
unsigned stride,
898
unsigned layer_stride)
899
{
900
struct pipe_transfer *transfer = NULL;
901
struct i915_transfer *itransfer = NULL;
902
const uint8_t *src_data = data;
903
unsigned i;
904
905
transfer = pipe->transfer_get(pipe,
906
resource,
907
level,
908
usage,
909
box );
910
if (transfer == NULL)
911
goto out;
912
913
itransfer = (struct i915_transfer*)transfer;
914
915
if (itransfer->staging_texture) {
916
struct i915_texture *tex = i915_texture(itransfer->staging_texture);
917
enum pipe_format format = tex->b.format;
918
struct i915_winsys *iws = i915_screen(tex->b.screen)->iws;
919
size_t offset;
920
size_t size;
921
922
offset = i915_texture_offset(tex, transfer->level, transfer->box.z);
923
924
for (i = 0; i < box->depth; i++) {
925
if (!tex->b.last_level &&
926
tex->b.width0 == transfer->box.width) {
927
unsigned nby = util_format_get_nblocksy(format, transfer->box.y);
928
assert(!offset);
929
assert(!transfer->box.x);
930
assert(tex->stride == transfer->stride);
931
932
offset += tex->stride * nby;
933
size = util_format_get_2d_size(format, transfer->stride,
934
transfer->box.height);
935
iws->buffer_write(iws, tex->buffer, offset, size, transfer->data);
936
937
} else {
938
unsigned nby = util_format_get_nblocksy(format, transfer->box.y);
939
int i;
940
offset += util_format_get_stride(format, transfer->box.x);
941
size = transfer->stride;
942
943
for (i = 0; i < nby; i++) {
944
iws->buffer_write(iws, tex->buffer, offset, size, transfer->data);
945
offset += tex->stride;
946
}
947
}
948
offset += layer_stride;
949
}
950
} else {
951
uint8_t *map = pipe_transfer_map(pipe, &itransfer->b);
952
if (map == NULL)
953
goto nomap;
954
955
for (i = 0; i < box->depth; i++) {
956
util_copy_rect(map,
957
resource->format,
958
itransfer->b.stride, /* bytes */
959
0, 0,
960
box->width,
961
box->height,
962
src_data,
963
stride, /* bytes */
964
0, 0);
965
map += itransfer->b.layer_stride;
966
src_data += layer_stride;
967
}
968
nomap:
969
if (map)
970
pipe_transfer_unmap(pipe, &itransfer->b);
971
}
972
973
out:
974
if (itransfer)
975
pipe_transfer_destroy(pipe, &itransfer->b);
976
}
977
#endif
978
979
struct pipe_resource *
980
i915_texture_create(struct pipe_screen *screen,
981
const struct pipe_resource *template, bool force_untiled)
982
{
983
struct i915_screen *is = i915_screen(screen);
984
struct i915_winsys *iws = is->iws;
985
struct i915_texture *tex = CALLOC_STRUCT(i915_texture);
986
unsigned buf_usage = 0;
987
988
if (!tex)
989
return NULL;
990
991
tex->b = *template;
992
pipe_reference_init(&tex->b.reference, 1);
993
tex->b.screen = screen;
994
995
if ((force_untiled) || (template->usage == PIPE_USAGE_STREAM))
996
tex->tiling = I915_TILE_NONE;
997
else
998
tex->tiling = i915_texture_tiling(is, tex);
999
1000
if (is->is_i945) {
1001
if (!i945_texture_layout(tex))
1002
goto fail;
1003
} else {
1004
if (!i915_texture_layout(tex))
1005
goto fail;
1006
}
1007
1008
/* for scanouts and cursors, cursors arn't scanouts */
1009
1010
/* XXX: use a custom flag for cursors, don't rely on magically
1011
* guessing that this is Xorg asking for a cursor
1012
*/
1013
if ((template->bind & PIPE_BIND_SCANOUT) && template->width0 != 64)
1014
buf_usage = I915_NEW_SCANOUT;
1015
else
1016
buf_usage = I915_NEW_TEXTURE;
1017
1018
tex->buffer = iws->buffer_create_tiled(
1019
iws, &tex->stride, tex->total_nblocksy, &tex->tiling, buf_usage);
1020
if (!tex->buffer)
1021
goto fail;
1022
1023
I915_DBG(DBG_TEXTURE, "%s: %p stride %u, blocks (%u, %u) tiling %s\n",
1024
__func__, tex, tex->stride,
1025
tex->stride / util_format_get_blocksize(tex->b.format),
1026
tex->total_nblocksy, get_tiling_string(tex->tiling));
1027
1028
return &tex->b;
1029
1030
fail:
1031
FREE(tex);
1032
return NULL;
1033
}
1034
1035
struct pipe_resource *
1036
i915_texture_from_handle(struct pipe_screen *screen,
1037
const struct pipe_resource *template,
1038
struct winsys_handle *whandle)
1039
{
1040
struct i915_screen *is = i915_screen(screen);
1041
struct i915_texture *tex;
1042
struct i915_winsys *iws = is->iws;
1043
struct i915_winsys_buffer *buffer;
1044
unsigned stride;
1045
enum i915_winsys_buffer_tile tiling;
1046
1047
assert(screen);
1048
1049
buffer = iws->buffer_from_handle(iws, whandle, template->height0, &tiling,
1050
&stride);
1051
1052
/* Only supports one type */
1053
if ((template->target != PIPE_TEXTURE_2D &&
1054
template->target != PIPE_TEXTURE_RECT) ||
1055
template->last_level != 0 || template->depth0 != 1) {
1056
return NULL;
1057
}
1058
1059
tex = CALLOC_STRUCT(i915_texture);
1060
if (!tex)
1061
return NULL;
1062
1063
tex->b = *template;
1064
pipe_reference_init(&tex->b.reference, 1);
1065
tex->b.screen = screen;
1066
1067
tex->stride = stride;
1068
tex->tiling = tiling;
1069
tex->total_nblocksy = align_nblocksy(tex->b.format, tex->b.height0, 8);
1070
1071
i915_texture_set_level_info(tex, 0, 1);
1072
i915_texture_set_image_offset(tex, 0, 0, 0, 0);
1073
1074
tex->buffer = buffer;
1075
1076
I915_DBG(DBG_TEXTURE, "%s: %p stride %u, blocks (%u, %u) tiling %s\n",
1077
__func__, tex, tex->stride,
1078
tex->stride / util_format_get_blocksize(tex->b.format),
1079
tex->total_nblocksy, get_tiling_string(tex->tiling));
1080
1081
return &tex->b;
1082
}
1083
1084