r300g: align the height of NPOT textures to POT
[profile/ivi/mesa.git] / src / gallium / drivers / i965 / brw_screen_texture.c
1 /*
2  Copyright (C) Intel Corp.  2006.  All Rights Reserved.
3  Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
4  develop this 3D driver.
5  
6  Permission is hereby granted, free of charge, to any person obtaining
7  a 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, sublicense, 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
16  portions of the Software.
17  
18  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21  IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  
26  **********************************************************************/
27  /*
28   * Authors:
29   *   Keith Whitwell <keith@tungstengraphics.com>
30   */
31
32 #include "util/u_memory.h"
33 #include "util/u_simple_list.h"
34 #include "util/u_format.h"
35
36 #include "brw_screen.h"
37 #include "brw_defines.h"
38 #include "brw_structs.h"
39 #include "brw_winsys.h"
40 #include "brw_context.h"
41
42
43
44
45 static GLuint translate_tex_target( unsigned target )
46 {
47    switch (target) {
48    case PIPE_TEXTURE_1D: 
49       return BRW_SURFACE_1D;
50
51    case PIPE_TEXTURE_2D: 
52       return BRW_SURFACE_2D;
53
54    case PIPE_TEXTURE_3D: 
55       return BRW_SURFACE_3D;
56
57    case PIPE_TEXTURE_CUBE:
58       return BRW_SURFACE_CUBE;
59
60    default: 
61       assert(0); 
62       return BRW_SURFACE_1D;
63    }
64 }
65
66
67 static GLuint translate_tex_format( enum pipe_format pf )
68 {
69    switch( pf ) {
70    case PIPE_FORMAT_L8_UNORM:
71       return BRW_SURFACEFORMAT_L8_UNORM;
72
73    case PIPE_FORMAT_I8_UNORM:
74       return BRW_SURFACEFORMAT_I8_UNORM;
75
76    case PIPE_FORMAT_A8_UNORM:
77       return BRW_SURFACEFORMAT_A8_UNORM; 
78
79    case PIPE_FORMAT_L16_UNORM:
80       return BRW_SURFACEFORMAT_L16_UNORM;
81
82       /* XXX: Add these to gallium
83    case PIPE_FORMAT_I16_UNORM:
84       return BRW_SURFACEFORMAT_I16_UNORM;
85
86    case PIPE_FORMAT_A16_UNORM:
87       return BRW_SURFACEFORMAT_A16_UNORM; 
88       */
89
90    case PIPE_FORMAT_L8A8_UNORM:
91       return BRW_SURFACEFORMAT_L8A8_UNORM;
92
93    case PIPE_FORMAT_B5G6R5_UNORM:
94       return BRW_SURFACEFORMAT_B5G6R5_UNORM;
95
96    case PIPE_FORMAT_B5G5R5A1_UNORM:
97       return BRW_SURFACEFORMAT_B5G5R5A1_UNORM;
98
99    case PIPE_FORMAT_B4G4R4A4_UNORM:
100       return BRW_SURFACEFORMAT_B4G4R4A4_UNORM;
101
102    case PIPE_FORMAT_B8G8R8X8_UNORM:
103       return BRW_SURFACEFORMAT_R8G8B8X8_UNORM;
104
105    case PIPE_FORMAT_B8G8R8A8_UNORM:
106       return BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
107
108    /*
109     * Video formats
110     */
111
112    case PIPE_FORMAT_YUYV:
113       return BRW_SURFACEFORMAT_YCRCB_NORMAL;
114
115    case PIPE_FORMAT_UYVY:
116       return BRW_SURFACEFORMAT_YCRCB_SWAPUVY;
117
118    /*
119     * Compressed formats.
120     */
121       /* XXX: Add FXT to gallium?
122    case PIPE_FORMAT_FXT1_RGBA:
123       return BRW_SURFACEFORMAT_FXT1;
124       */
125
126    case PIPE_FORMAT_DXT1_RGB:
127        return BRW_SURFACEFORMAT_DXT1_RGB;
128
129    case PIPE_FORMAT_DXT1_RGBA:
130        return BRW_SURFACEFORMAT_BC1_UNORM;
131        
132    case PIPE_FORMAT_DXT3_RGBA:
133        return BRW_SURFACEFORMAT_BC2_UNORM;
134        
135    case PIPE_FORMAT_DXT5_RGBA:
136        return BRW_SURFACEFORMAT_BC3_UNORM;
137
138    /*
139     * sRGB formats
140     */
141
142    case PIPE_FORMAT_A8B8G8R8_SRGB:
143       return BRW_SURFACEFORMAT_B8G8R8A8_UNORM_SRGB;
144
145    case PIPE_FORMAT_L8A8_SRGB:
146       return BRW_SURFACEFORMAT_L8A8_UNORM_SRGB;
147
148    case PIPE_FORMAT_L8_SRGB:
149       return BRW_SURFACEFORMAT_L8_UNORM_SRGB;
150
151    case PIPE_FORMAT_DXT1_SRGB:
152       return BRW_SURFACEFORMAT_BC1_UNORM_SRGB;
153
154    /*
155     * Depth formats
156     */
157
158    case PIPE_FORMAT_Z16_UNORM:
159          return BRW_SURFACEFORMAT_I16_UNORM;
160
161    case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
162    case PIPE_FORMAT_Z24X8_UNORM:
163          return BRW_SURFACEFORMAT_I24X8_UNORM;
164
165    case PIPE_FORMAT_Z32_FLOAT:
166          return BRW_SURFACEFORMAT_I32_FLOAT;
167
168       /* XXX: presumably for bump mapping.  Add this to mesa state
169        * tracker?
170        *
171        * XXX: Add flipped versions of these formats to Gallium.
172        */
173    case PIPE_FORMAT_R8G8_SNORM:
174       return BRW_SURFACEFORMAT_R8G8_SNORM;
175
176    case PIPE_FORMAT_R8G8B8A8_SNORM:
177       return BRW_SURFACEFORMAT_R8G8B8A8_SNORM;
178
179    default:
180       return BRW_SURFACEFORMAT_INVALID;
181    }
182 }
183
184
185
186
187
188 static struct pipe_texture *brw_texture_create( struct pipe_screen *screen,
189                                                 const struct pipe_texture *templ )
190
191 {  
192    struct brw_screen *bscreen = brw_screen(screen);
193    struct brw_texture *tex;
194    enum brw_buffer_type buffer_type;
195    enum pipe_error ret;
196    GLuint format;
197    
198    tex = CALLOC_STRUCT(brw_texture);
199    if (tex == NULL)
200       return NULL;
201
202    memcpy(&tex->base, templ, sizeof *templ);
203    pipe_reference_init(&tex->base.reference, 1);
204    tex->base.screen = screen;
205
206    /* XXX: compressed textures need special treatment here
207     */
208    tex->cpp = util_format_get_blocksize(tex->base.format);
209    tex->compressed = util_format_is_s3tc(tex->base.format);
210
211    make_empty_list(&tex->views[0]);
212    make_empty_list(&tex->views[1]);
213
214    /* XXX: No tiling with compressed textures??
215     */
216    if (tex->compressed == 0 &&
217        !bscreen->no_tiling) 
218    {
219       if (bscreen->chipset.is_965 &&
220           util_format_is_depth_or_stencil(templ->format))
221          tex->tiling = BRW_TILING_Y;
222       else
223          tex->tiling = BRW_TILING_X;
224    } 
225    else {
226       tex->tiling = BRW_TILING_NONE;
227    }
228
229
230
231
232    if (!brw_texture_layout( bscreen, tex ))
233       goto fail;
234
235    
236    if (templ->tex_usage & (PIPE_TEXTURE_USAGE_SCANOUT |
237                            PIPE_TEXTURE_USAGE_SHARED)) {
238       buffer_type = BRW_BUFFER_TYPE_SCANOUT;
239    }
240    else {
241       buffer_type = BRW_BUFFER_TYPE_TEXTURE;
242    }
243
244    ret = bscreen->sws->bo_alloc( bscreen->sws,
245                                  buffer_type,
246                                  tex->pitch * tex->total_height * tex->cpp,
247                                  64,
248                                  &tex->bo );
249    if (ret)
250       goto fail;
251
252    tex->ss.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW;
253    tex->ss.ss0.surface_type = translate_tex_target(tex->base.target);
254
255    format = translate_tex_format(tex->base.format);
256    assert(format != BRW_SURFACEFORMAT_INVALID);
257    tex->ss.ss0.surface_format = format;
258
259    /* This is ok for all textures with channel width 8bit or less:
260     */
261 /*    tex->ss.ss0.data_return_format = BRW_SURFACERETURNFORMAT_S1; */
262
263
264    /* XXX: what happens when tex->bo->offset changes???
265     */
266    tex->ss.ss1.base_addr = 0; /* reloc */
267    tex->ss.ss2.mip_count = tex->base.last_level;
268    tex->ss.ss2.width = tex->base.width0 - 1;
269    tex->ss.ss2.height = tex->base.height0 - 1;
270
271    switch (tex->tiling) {
272    case BRW_TILING_NONE:
273       tex->ss.ss3.tiled_surface = 0;
274       tex->ss.ss3.tile_walk = 0;
275       break;
276    case BRW_TILING_X:
277       tex->ss.ss3.tiled_surface = 1;
278       tex->ss.ss3.tile_walk = BRW_TILEWALK_XMAJOR;
279       break;
280    case BRW_TILING_Y:
281       tex->ss.ss3.tiled_surface = 1;
282       tex->ss.ss3.tile_walk = BRW_TILEWALK_YMAJOR;
283       break;
284    }
285
286    tex->ss.ss3.pitch = (tex->pitch * tex->cpp) - 1;
287    tex->ss.ss3.depth = tex->base.depth0 - 1;
288
289    tex->ss.ss4.min_lod = 0;
290  
291    if (tex->base.target == PIPE_TEXTURE_CUBE) {
292       tex->ss.ss0.cube_pos_x = 1;
293       tex->ss.ss0.cube_pos_y = 1;
294       tex->ss.ss0.cube_pos_z = 1;
295       tex->ss.ss0.cube_neg_x = 1;
296       tex->ss.ss0.cube_neg_y = 1;
297       tex->ss.ss0.cube_neg_z = 1;
298    }
299
300    return &tex->base;
301
302 fail:
303    bo_reference(&tex->bo, NULL);
304    FREE(tex);
305    return NULL;
306 }
307
308 static struct pipe_texture * 
309 brw_texture_from_handle(struct pipe_screen *screen,
310                         const struct pipe_texture *templ,
311                         struct winsys_handle *whandle)
312 {
313    struct brw_screen *bscreen = brw_screen(screen);
314    struct brw_texture *tex;
315    struct brw_winsys_buffer *buffer;
316    unsigned tiling;
317    unsigned pitch;
318    GLuint format;
319
320    if (templ->target != PIPE_TEXTURE_2D ||
321        templ->last_level != 0 ||
322        templ->depth0 != 1)
323       return NULL;
324
325    if (util_format_is_s3tc(templ->format))
326       return NULL;
327
328    tex = CALLOC_STRUCT(brw_texture);
329    if (!tex)
330       return NULL;
331
332    if (bscreen->sws->bo_from_handle(bscreen->sws, whandle, &pitch, &tiling, &buffer) != PIPE_OK)
333       goto fail;
334
335    memcpy(&tex->base, templ, sizeof *templ);
336    pipe_reference_init(&tex->base.reference, 1);
337    tex->base.screen = screen;
338
339    /* XXX: cpp vs. blocksize
340     */
341    tex->cpp = util_format_get_blocksize(tex->base.format);
342    tex->tiling = tiling;
343
344    make_empty_list(&tex->views[0]);
345    make_empty_list(&tex->views[1]);
346
347    if (!brw_texture_layout(bscreen, tex))
348       goto fail;
349
350    /* XXX Maybe some more checks? */
351    if ((pitch / tex->cpp) < tex->pitch)
352       goto fail;
353
354    tex->pitch = pitch / tex->cpp;
355
356    tex->bo = buffer;
357
358    /* fix this warning */
359 #if 0
360    if (tex->size > buffer->size)
361       goto fail;
362 #endif
363
364    tex->ss.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW;
365    tex->ss.ss0.surface_type = translate_tex_target(tex->base.target);
366
367    format = translate_tex_format(tex->base.format);
368    assert(format != BRW_SURFACEFORMAT_INVALID);
369    tex->ss.ss0.surface_format = format;
370
371    /* This is ok for all textures with channel width 8bit or less:
372     */
373 /*    tex->ss.ss0.data_return_format = BRW_SURFACERETURNFORMAT_S1; */
374
375
376    /* XXX: what happens when tex->bo->offset changes???
377     */
378    tex->ss.ss1.base_addr = 0; /* reloc */
379    tex->ss.ss2.mip_count = tex->base.last_level;
380    tex->ss.ss2.width = tex->base.width0 - 1;
381    tex->ss.ss2.height = tex->base.height0 - 1;
382
383    switch (tex->tiling) {
384    case BRW_TILING_NONE:
385       tex->ss.ss3.tiled_surface = 0;
386       tex->ss.ss3.tile_walk = 0;
387       break;
388    case BRW_TILING_X:
389       tex->ss.ss3.tiled_surface = 1;
390       tex->ss.ss3.tile_walk = BRW_TILEWALK_XMAJOR;
391       break;
392    case BRW_TILING_Y:
393       tex->ss.ss3.tiled_surface = 1;
394       tex->ss.ss3.tile_walk = BRW_TILEWALK_YMAJOR;
395       break;
396    }
397
398    tex->ss.ss3.pitch = (tex->pitch * tex->cpp) - 1;
399    tex->ss.ss3.depth = tex->base.depth0 - 1;
400
401    tex->ss.ss4.min_lod = 0;
402
403    return &tex->base;
404
405 fail:
406    FREE(tex);
407    return NULL;
408 }
409
410 static boolean
411 brw_texture_get_handle(struct pipe_screen *screen,
412                        struct pipe_texture *texture,
413                        struct winsys_handle *whandle)
414 {
415    struct brw_screen *bscreen = brw_screen(screen);
416    struct brw_texture *tex = brw_texture(texture);
417    unsigned stride;
418
419    stride = tex->pitch * tex->cpp;
420
421    return bscreen->sws->bo_get_handle(tex->bo, whandle, stride);
422 }
423
424
425
426 static void brw_texture_destroy(struct pipe_texture *pt)
427 {
428    struct brw_texture *tex = brw_texture(pt);
429    bo_reference(&tex->bo, NULL);
430    FREE(pt);
431 }
432
433
434 static boolean brw_is_format_supported( struct pipe_screen *screen,
435                                         enum pipe_format format,
436                                         enum pipe_texture_target target,
437                                         unsigned tex_usage, 
438                                         unsigned geom_flags )
439 {
440    return translate_tex_format(format) != BRW_SURFACEFORMAT_INVALID;
441 }
442
443
444 boolean brw_is_texture_referenced_by_bo( struct brw_screen *brw_screen,
445                                       struct pipe_texture *texture,
446                                       unsigned face, 
447                                       unsigned level,
448                                       struct brw_winsys_buffer *bo )
449 {
450    struct brw_texture *tex = brw_texture(texture);
451    struct brw_surface *surf;
452    int i;
453
454    /* XXX: this is subject to false positives if the underlying
455     * texture BO is referenced, we can't tell whether the sub-region
456     * we care about participates in that.
457     */
458    if (brw_screen->sws->bo_references( bo, tex->bo ))
459       return TRUE;
460
461    /* Find any view on this texture for this face/level and see if it
462     * is referenced:
463     */
464    for (i = 0; i < 2; i++) {
465       foreach (surf, &tex->views[i]) {
466          if (surf->bo == tex->bo)
467             continue;
468
469          if (surf->id.bits.face != face ||
470              surf->id.bits.level != level)
471             continue;
472          
473          if (brw_screen->sws->bo_references( bo, surf->bo))
474             return TRUE;
475       }
476    }
477
478    return FALSE;
479 }
480
481
482 /*
483  * Transfer functions
484  */
485
486 static struct pipe_transfer*
487 brw_get_tex_transfer(struct pipe_context *pipe,
488                      struct pipe_texture *texture,
489                      unsigned face, unsigned level, unsigned zslice,
490                      enum pipe_transfer_usage usage, unsigned x, unsigned y,
491                      unsigned w, unsigned h)
492 {
493    struct brw_texture *tex = brw_texture(texture);
494    struct brw_transfer *trans;
495    unsigned offset;  /* in bytes */
496
497    if (texture->target == PIPE_TEXTURE_CUBE) {
498       offset = tex->image_offset[level][face];
499    } else if (texture->target == PIPE_TEXTURE_3D) {
500       offset = tex->image_offset[level][zslice];
501    } else {
502       offset = tex->image_offset[level][0];
503       assert(face == 0);
504       assert(zslice == 0);
505    }
506
507    trans = CALLOC_STRUCT(brw_transfer);
508    if (trans) {
509       pipe_texture_reference(&trans->base.texture, texture);
510       trans->base.x = x;
511       trans->base.y = y;
512       trans->base.width = w;
513       trans->base.height = h;
514       trans->base.stride = tex->pitch * tex->cpp;
515       trans->offset = offset;
516       trans->base.usage = usage;
517    }
518    return &trans->base;
519 }
520
521 static void *
522 brw_transfer_map(struct pipe_context *pipe,
523                  struct pipe_transfer *transfer)
524 {
525    struct brw_texture *tex = brw_texture(transfer->texture);
526    struct brw_winsys_screen *sws = brw_screen(pipe->screen)->sws;
527    char *map;
528    unsigned usage = transfer->usage;
529
530    map = sws->bo_map(tex->bo, 
531                      BRW_DATA_OTHER,
532                      0,
533                      tex->bo->size,
534                      (usage & PIPE_TRANSFER_WRITE) ? TRUE : FALSE,
535                      (usage & 0) ? TRUE : FALSE,
536                      (usage & 0) ? TRUE : FALSE);
537
538    if (!map)
539       return NULL;
540
541    /* XXX: blocksize and compressed textures
542     */
543    return map + brw_transfer(transfer)->offset +
544       transfer->y /* / transfer->block.height */ * transfer->stride +
545       transfer->x /* / transfer->block.width */ * brw_texture(transfer->texture)->cpp;
546 }
547
548 static void
549 brw_transfer_unmap(struct pipe_context *pipe,
550                    struct pipe_transfer *transfer)
551 {
552    struct brw_texture *tex = brw_texture(transfer->texture);
553    struct brw_winsys_screen *sws = brw_screen(pipe->screen)->sws;
554
555    sws->bo_unmap(tex->bo);
556 }
557
558 static void
559 brw_tex_transfer_destroy(struct pipe_context *pipe,
560                          struct pipe_transfer *trans)
561 {
562    pipe_texture_reference(&trans->texture, NULL);
563    FREE(trans);
564 }
565
566
567 void brw_tex_init( struct brw_context *brw )
568 {
569    brw->base.get_tex_transfer = brw_get_tex_transfer;
570    brw->base.transfer_map = brw_transfer_map;
571    brw->base.transfer_unmap = brw_transfer_unmap;
572    brw->base.tex_transfer_destroy = brw_tex_transfer_destroy;
573 }
574
575 void brw_screen_tex_init( struct brw_screen *brw_screen )
576 {
577    brw_screen->base.is_format_supported = brw_is_format_supported;
578    brw_screen->base.texture_create = brw_texture_create;
579    brw_screen->base.texture_from_handle = brw_texture_from_handle;
580    brw_screen->base.texture_get_handle = brw_texture_get_handle;
581    brw_screen->base.texture_destroy = brw_texture_destroy;
582 }