Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / gallium / drivers / i965 / brw_resource_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_batchbuffer.h"
41 #include "brw_context.h"
42 #include "brw_resource.h"
43
44
45 /**
46  * Subclass of pipe_transfer
47  */
48 struct brw_transfer
49 {
50    struct pipe_transfer base;
51
52    unsigned offset;
53 };
54
55 static INLINE struct brw_transfer *
56 brw_transfer(struct pipe_transfer *transfer)
57 {
58    return (struct brw_transfer *)transfer;
59 }
60
61
62 static GLuint translate_tex_target( unsigned target )
63 {
64    switch (target) {
65    case PIPE_TEXTURE_1D: 
66       return BRW_SURFACE_1D;
67
68    case PIPE_TEXTURE_2D: 
69    case PIPE_TEXTURE_RECT:
70       return BRW_SURFACE_2D;
71
72    case PIPE_TEXTURE_3D: 
73       return BRW_SURFACE_3D;
74
75    case PIPE_TEXTURE_CUBE:
76       return BRW_SURFACE_CUBE;
77
78    default: 
79       assert(0); 
80       return BRW_SURFACE_1D;
81    }
82 }
83
84
85 static GLuint translate_tex_format( enum pipe_format pf )
86 {
87    switch( pf ) {
88    case PIPE_FORMAT_L8_UNORM:
89       return BRW_SURFACEFORMAT_L8_UNORM;
90
91    case PIPE_FORMAT_I8_UNORM:
92       return BRW_SURFACEFORMAT_I8_UNORM;
93
94    case PIPE_FORMAT_A8_UNORM:
95       return BRW_SURFACEFORMAT_A8_UNORM; 
96
97    case PIPE_FORMAT_L16_UNORM:
98       return BRW_SURFACEFORMAT_L16_UNORM;
99
100       /* XXX: Add these to gallium
101    case PIPE_FORMAT_I16_UNORM:
102       return BRW_SURFACEFORMAT_I16_UNORM;
103
104    case PIPE_FORMAT_A16_UNORM:
105       return BRW_SURFACEFORMAT_A16_UNORM; 
106       */
107
108    case PIPE_FORMAT_L8A8_UNORM:
109       return BRW_SURFACEFORMAT_L8A8_UNORM;
110
111    case PIPE_FORMAT_B5G6R5_UNORM:
112       return BRW_SURFACEFORMAT_B5G6R5_UNORM;
113
114    case PIPE_FORMAT_B5G5R5A1_UNORM:
115       return BRW_SURFACEFORMAT_B5G5R5A1_UNORM;
116
117    case PIPE_FORMAT_B4G4R4A4_UNORM:
118       return BRW_SURFACEFORMAT_B4G4R4A4_UNORM;
119
120    case PIPE_FORMAT_B8G8R8X8_UNORM:
121       return BRW_SURFACEFORMAT_R8G8B8X8_UNORM;
122
123    case PIPE_FORMAT_B8G8R8A8_UNORM:
124       return BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
125
126    /*
127     * Video formats
128     */
129
130    case PIPE_FORMAT_YUYV:
131       return BRW_SURFACEFORMAT_YCRCB_NORMAL;
132
133    case PIPE_FORMAT_UYVY:
134       return BRW_SURFACEFORMAT_YCRCB_SWAPUVY;
135
136    /*
137     * Compressed formats.
138     */
139       /* XXX: Add FXT to gallium?
140    case PIPE_FORMAT_FXT1_RGBA:
141       return BRW_SURFACEFORMAT_FXT1;
142       */
143
144    case PIPE_FORMAT_DXT1_RGB:
145        return BRW_SURFACEFORMAT_DXT1_RGB;
146
147    case PIPE_FORMAT_DXT1_RGBA:
148        return BRW_SURFACEFORMAT_BC1_UNORM;
149        
150    case PIPE_FORMAT_DXT3_RGBA:
151        return BRW_SURFACEFORMAT_BC2_UNORM;
152        
153    case PIPE_FORMAT_DXT5_RGBA:
154        return BRW_SURFACEFORMAT_BC3_UNORM;
155
156    /*
157     * sRGB formats
158     */
159
160    case PIPE_FORMAT_A8B8G8R8_SRGB:
161       return BRW_SURFACEFORMAT_B8G8R8A8_UNORM_SRGB;
162
163    case PIPE_FORMAT_L8A8_SRGB:
164       return BRW_SURFACEFORMAT_L8A8_UNORM_SRGB;
165
166    case PIPE_FORMAT_L8_SRGB:
167       return BRW_SURFACEFORMAT_L8_UNORM_SRGB;
168
169    case PIPE_FORMAT_DXT1_SRGB:
170       return BRW_SURFACEFORMAT_BC1_UNORM_SRGB;
171
172    /*
173     * Depth formats
174     */
175
176    case PIPE_FORMAT_Z16_UNORM:
177          return BRW_SURFACEFORMAT_I16_UNORM;
178
179    case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
180    case PIPE_FORMAT_Z24X8_UNORM:
181          return BRW_SURFACEFORMAT_I24X8_UNORM;
182
183    case PIPE_FORMAT_Z32_FLOAT:
184          return BRW_SURFACEFORMAT_I32_FLOAT;
185
186       /* XXX: presumably for bump mapping.  Add this to mesa state
187        * tracker?
188        *
189        * XXX: Add flipped versions of these formats to Gallium.
190        */
191    case PIPE_FORMAT_R8G8_SNORM:
192       return BRW_SURFACEFORMAT_R8G8_SNORM;
193
194    case PIPE_FORMAT_R8G8B8A8_SNORM:
195       return BRW_SURFACEFORMAT_R8G8B8A8_SNORM;
196
197    default:
198       return BRW_SURFACEFORMAT_INVALID;
199    }
200 }
201
202
203 static boolean
204 brw_texture_get_handle(struct pipe_screen *screen,
205                        struct pipe_resource *texture,
206                        struct winsys_handle *whandle)
207 {
208    struct brw_screen *bscreen = brw_screen(screen);
209    struct brw_texture *tex = brw_texture(texture);
210    unsigned stride;
211
212    stride = tex->pitch * tex->cpp;
213
214    return bscreen->sws->bo_get_handle(tex->bo, whandle, stride) == PIPE_OK;
215 }
216
217
218
219 static void brw_texture_destroy(struct pipe_screen *screen,
220                                 struct pipe_resource *pt)
221 {
222    struct brw_texture *tex = brw_texture(pt);
223    bo_reference(&tex->bo, NULL);
224    FREE(pt);
225 }
226
227
228 /*
229  * Transfer functions
230  */
231
232
233 static struct pipe_transfer * 
234 brw_texture_get_transfer(struct pipe_context *context,
235                          struct pipe_resource *resource,
236                          unsigned level,
237                          unsigned usage,
238                          const struct pipe_box *box)
239 {
240    struct brw_texture *tex = brw_texture(resource);
241    struct pipe_transfer *transfer = CALLOC_STRUCT(pipe_transfer);
242    if (transfer == NULL)
243       return NULL;
244
245    transfer->resource = resource;
246    transfer->level = level;
247    transfer->usage = usage;
248    transfer->box = *box;
249    transfer->stride = tex->pitch * tex->cpp;
250    /* FIXME: layer_stride */
251
252    return transfer;
253 }
254
255
256 static void *
257 brw_texture_transfer_map(struct pipe_context *pipe,
258                  struct pipe_transfer *transfer)
259 {
260    struct pipe_resource *resource = transfer->resource;
261    struct brw_texture *tex = brw_texture(transfer->resource);
262    struct brw_winsys_screen *sws = brw_screen(pipe->screen)->sws;
263    struct pipe_box *box = &transfer->box;
264    enum pipe_format format = resource->format;
265    unsigned usage = transfer->usage;
266    unsigned offset;
267    char *map;
268
269    if (resource->target != PIPE_TEXTURE_3D &&
270        resource->target != PIPE_TEXTURE_CUBE)
271       assert(box->z == 0);
272    offset = tex->image_offset[transfer->level][box->z];
273
274    map = sws->bo_map(tex->bo, 
275                      BRW_DATA_OTHER,
276                      0,
277                      tex->bo->size,
278                      (usage & PIPE_TRANSFER_WRITE) ? TRUE : FALSE,
279                      (usage & 0) ? TRUE : FALSE,
280                      (usage & 0) ? TRUE : FALSE);
281
282    if (!map)
283       return NULL;
284
285    return map + offset +
286       box->y / util_format_get_blockheight(format) * transfer->stride +
287       box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
288 }
289
290 static void
291 brw_texture_transfer_unmap(struct pipe_context *pipe,
292                    struct pipe_transfer *transfer)
293 {
294    struct brw_texture *tex = brw_texture(transfer->resource);
295    struct brw_winsys_screen *sws = brw_screen(pipe->screen)->sws;
296
297    sws->bo_unmap(tex->bo);
298 }
299
300
301
302
303
304 struct u_resource_vtbl brw_texture_vtbl = 
305 {
306    brw_texture_get_handle,            /* get_handle */
307    brw_texture_destroy,       /* resource_destroy */
308    brw_texture_get_transfer,          /* get_transfer */
309    u_default_transfer_destroy,        /* transfer_destroy */
310    brw_texture_transfer_map,          /* transfer_map */
311    u_default_transfer_flush_region,   /* transfer_flush_region */
312    brw_texture_transfer_unmap,        /* transfer_unmap */
313    u_default_transfer_inline_write    /* transfer_inline_write */
314 };
315
316
317
318
319
320 struct pipe_resource *
321 brw_texture_create( struct pipe_screen *screen,
322                     const struct pipe_resource *template )
323 {  
324    struct brw_screen *bscreen = brw_screen(screen);
325    struct brw_texture *tex;
326    enum brw_buffer_type buffer_type;
327    enum pipe_error ret;
328    GLuint format;
329    
330    tex = CALLOC_STRUCT(brw_texture);
331    if (tex == NULL)
332       return NULL;
333
334    tex->b.b = *template;
335    tex->b.vtbl = &brw_texture_vtbl;
336    pipe_reference_init(&tex->b.b.reference, 1);
337    tex->b.b.screen = screen;
338
339    /* XXX: compressed textures need special treatment here
340     */
341    tex->cpp = util_format_get_blocksize(tex->b.b.format);
342    tex->compressed = util_format_is_s3tc(tex->b.b.format);
343
344    make_empty_list(&tex->views[0]);
345    make_empty_list(&tex->views[1]);
346
347    /* XXX: No tiling with compressed textures??
348     */
349    if (tex->compressed == 0 &&
350        !bscreen->no_tiling) 
351    {
352       if (bscreen->gen < 5 &&
353           util_format_is_depth_or_stencil(template->format))
354          tex->tiling = BRW_TILING_Y;
355       else
356          tex->tiling = BRW_TILING_X;
357    } 
358    else {
359       tex->tiling = BRW_TILING_NONE;
360    }
361
362
363    if (!brw_texture_layout( bscreen, tex ))
364       goto fail;
365
366    
367    if (template->bind & (PIPE_BIND_SCANOUT |
368                            PIPE_BIND_SHARED)) {
369       buffer_type = BRW_BUFFER_TYPE_SCANOUT;
370    }
371    else {
372       buffer_type = BRW_BUFFER_TYPE_TEXTURE;
373    }
374
375    ret = bscreen->sws->bo_alloc( bscreen->sws,
376                                  buffer_type,
377                                  tex->pitch * tex->total_height * tex->cpp,
378                                  64,
379                                  &tex->bo );
380    if (ret)
381       goto fail;
382
383    tex->ss.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW;
384    tex->ss.ss0.surface_type = translate_tex_target(tex->b.b.target);
385
386    format = translate_tex_format(tex->b.b.format);
387    assert(format != BRW_SURFACEFORMAT_INVALID);
388    tex->ss.ss0.surface_format = format;
389
390    /* This is ok for all textures with channel width 8bit or less:
391     */
392 /*    tex->ss.ss0.data_return_format = BRW_SURFACERETURNFORMAT_S1; */
393
394
395    /* XXX: what happens when tex->bo->offset changes???
396     */
397    tex->ss.ss1.base_addr = 0; /* reloc */
398    tex->ss.ss2.mip_count = tex->b.b.last_level;
399    tex->ss.ss2.width = tex->b.b.width0 - 1;
400    tex->ss.ss2.height = tex->b.b.height0 - 1;
401
402    switch (tex->tiling) {
403    case BRW_TILING_NONE:
404       tex->ss.ss3.tiled_surface = 0;
405       tex->ss.ss3.tile_walk = 0;
406       break;
407    case BRW_TILING_X:
408       tex->ss.ss3.tiled_surface = 1;
409       tex->ss.ss3.tile_walk = BRW_TILEWALK_XMAJOR;
410       break;
411    case BRW_TILING_Y:
412       tex->ss.ss3.tiled_surface = 1;
413       tex->ss.ss3.tile_walk = BRW_TILEWALK_YMAJOR;
414       break;
415    }
416
417    tex->ss.ss3.pitch = (tex->pitch * tex->cpp) - 1;
418    tex->ss.ss3.depth = tex->b.b.depth0 - 1;
419
420    tex->ss.ss4.min_lod = 0;
421  
422    if (tex->b.b.target == PIPE_TEXTURE_CUBE) {
423       tex->ss.ss0.cube_pos_x = 1;
424       tex->ss.ss0.cube_pos_y = 1;
425       tex->ss.ss0.cube_pos_z = 1;
426       tex->ss.ss0.cube_neg_x = 1;
427       tex->ss.ss0.cube_neg_y = 1;
428       tex->ss.ss0.cube_neg_z = 1;
429    }
430
431    return &tex->b.b;
432
433 fail:
434    bo_reference(&tex->bo, NULL);
435    FREE(tex);
436    return NULL;
437 }
438
439
440 struct pipe_resource * 
441 brw_texture_from_handle(struct pipe_screen *screen,
442                         const struct pipe_resource *template,
443                         struct winsys_handle *whandle)
444 {
445    struct brw_screen *bscreen = brw_screen(screen);
446    struct brw_texture *tex;
447    struct brw_winsys_buffer *buffer;
448    unsigned tiling;
449    unsigned pitch;
450    GLuint format;
451
452    if ((template->target != PIPE_TEXTURE_2D
453          && template->target != PIPE_TEXTURE_RECT)  ||
454        template->last_level != 0 ||
455        template->depth0 != 1)
456       return NULL;
457
458    if (util_format_is_s3tc(template->format))
459       return NULL;
460
461    tex = CALLOC_STRUCT(brw_texture);
462    if (!tex)
463       return NULL;
464
465    if (bscreen->sws->bo_from_handle(bscreen->sws, whandle, &pitch, &tiling, &buffer) != PIPE_OK)
466       goto fail;
467
468    tex->b.b = *template;
469    tex->b.vtbl = &brw_texture_vtbl;
470    pipe_reference_init(&tex->b.b.reference, 1);
471    tex->b.b.screen = screen;
472
473    /* XXX: cpp vs. blocksize
474     */
475    tex->cpp = util_format_get_blocksize(tex->b.b.format);
476    tex->tiling = tiling;
477
478    make_empty_list(&tex->views[0]);
479    make_empty_list(&tex->views[1]);
480
481    if (!brw_texture_layout(bscreen, tex))
482       goto fail;
483
484    /* XXX Maybe some more checks? */
485    if ((pitch / tex->cpp) < tex->pitch)
486       goto fail;
487
488    tex->pitch = pitch / tex->cpp;
489
490    tex->bo = buffer;
491
492    /* fix this warning */
493 #if 0
494    if (tex->size > buffer->size)
495       goto fail;
496 #endif
497
498    tex->ss.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW;
499    tex->ss.ss0.surface_type = translate_tex_target(tex->b.b.target);
500
501    format = translate_tex_format(tex->b.b.format);
502    assert(format != BRW_SURFACEFORMAT_INVALID);
503    tex->ss.ss0.surface_format = format;
504
505    /* This is ok for all textures with channel width 8bit or less:
506     */
507 /*    tex->ss.ss0.data_return_format = BRW_SURFACERETURNFORMAT_S1; */
508
509
510    /* XXX: what happens when tex->bo->offset changes???
511     */
512    tex->ss.ss1.base_addr = 0; /* reloc */
513    tex->ss.ss2.mip_count = tex->b.b.last_level;
514    tex->ss.ss2.width = tex->b.b.width0 - 1;
515    tex->ss.ss2.height = tex->b.b.height0 - 1;
516
517    switch (tex->tiling) {
518    case BRW_TILING_NONE:
519       tex->ss.ss3.tiled_surface = 0;
520       tex->ss.ss3.tile_walk = 0;
521       break;
522    case BRW_TILING_X:
523       tex->ss.ss3.tiled_surface = 1;
524       tex->ss.ss3.tile_walk = BRW_TILEWALK_XMAJOR;
525       break;
526    case BRW_TILING_Y:
527       tex->ss.ss3.tiled_surface = 1;
528       tex->ss.ss3.tile_walk = BRW_TILEWALK_YMAJOR;
529       break;
530    }
531
532    tex->ss.ss3.pitch = (tex->pitch * tex->cpp) - 1;
533    tex->ss.ss3.depth = tex->b.b.depth0 - 1;
534
535    tex->ss.ss4.min_lod = 0;
536
537    return &tex->b.b;
538
539 fail:
540    FREE(tex);
541    return NULL;
542 }
543
544
545 #if 0
546 boolean brw_is_format_supported( struct pipe_screen *screen,
547                                  enum pipe_format format,
548                                  enum pipe_texture_target target,
549                                  unsigned sample_count,
550                                  unsigned tex_usage,
551                                  unsigned geom_flags )
552 {
553    return translate_tex_format(format) != BRW_SURFACEFORMAT_INVALID;
554 }
555 #endif