Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / gallium / drivers / i965 / brw_pipe_surface.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_math.h"
35
36 #include "pipe/p_screen.h"
37 #include "brw_screen.h"
38 #include "brw_context.h"
39 #include "brw_defines.h"
40 #include "brw_resource.h"
41 #include "brw_winsys.h"
42
43 enum {
44    BRW_VIEW_LINEAR,
45    BRW_VIEW_IN_PLACE
46 };
47
48
49 static boolean need_linear_view( struct brw_screen *brw_screen,
50                                  struct brw_texture *brw_texture,
51                                  union brw_surface_id id,
52                                  unsigned usage )
53 {
54 #if 0
55    /* XXX: what about IDGNG?
56     */
57    if (!BRW_IS_G4X(brw->brw_screen->pci_id))
58    {
59       struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[i];
60       struct intel_renderbuffer *irb = intel_renderbuffer(rb);
61
62       /* The original gen4 hardware couldn't set up WM surfaces pointing
63        * at an offset within a tile, which can happen when rendering to
64        * anything but the base level of a texture or the +X face/0 depth.
65        * This was fixed with the 4 Series hardware.
66        *
67        * For these original chips, you would have to make the depth and
68        * color destination surfaces include information on the texture
69        * type, LOD, face, and various limits to use them as a destination.
70        *
71        * This is easy in Gallium as surfaces are all backed by
72        * textures, but there's also a nasty requirement that the depth
73        * and the color surfaces all be of the same LOD, which is
74        * harder to get around as we can't look at a surface in
75        * isolation and decide if it's legal.
76        *
77        * Instead, end up being pessimistic and say that for i965,
78        * ... ??
79        */
80       if (brw_tex->tiling != I915_TILING_NONE &&
81           (brw_tex_image_offset(brw_tex, face, level, zslize) & 4095)) {
82          if (BRW_DEBUG & DEBUG_VIEW)
83             debug_printf("%s: need surface view for non-aligned tex image\n",
84                          __FUNCTION__);
85          return GL_TRUE;
86       }
87    }
88 #endif
89
90    /* Tiled 3d textures don't have subsets that look like 2d surfaces:
91     */
92    
93    /* Everything else should be fine to render to in-place:
94     */
95    return GL_FALSE;
96 }
97
98 /* Look at all texture views and figure out if any of them need to be
99  * back-copied into the texture for sampling
100  */
101 void brw_update_texture( struct brw_screen *brw_screen,
102                          struct brw_texture *tex )
103 {
104    /* currently nothing to do */
105 }
106
107
108 /* Create a new surface with linear layout to serve as a render-target
109  * where it would be illegal (perhaps due to tiling constraints) to do
110  * this in-place.
111  * 
112  * Currently not implemented, not sure if it's needed.
113  */
114 static struct brw_surface *create_linear_view( struct brw_screen *brw_screen,
115                                                struct pipe_context *pipe,
116                                                struct brw_texture *tex,
117                                                union brw_surface_id id,
118                                                unsigned usage )
119 {
120    return NULL;
121 }
122
123
124 /* Create a pipe_surface that just points directly into the existing
125  * texture's storage.
126  */
127 static struct brw_surface *create_in_place_view( struct brw_screen *brw_screen,
128                                                  struct pipe_context *pipe,
129                                                  struct brw_texture *tex,
130                                                  union brw_surface_id id,
131                                                  unsigned usage )
132 {
133    struct brw_surface *surface;
134
135    surface = CALLOC_STRUCT(brw_surface);
136    if (surface == NULL)
137       return NULL;
138
139    pipe_reference_init(&surface->base.reference, 1);
140
141    /* XXX: ignoring render-to-slice-of-3d-texture
142     */
143    assert(tex->b.b.target != PIPE_TEXTURE_3D || id.bits.layer == 0);
144
145    surface->base.context = pipe;
146    surface->base.format = tex->b.b.format;
147    surface->base.width = u_minify(tex->b.b.width0, id.bits.level);
148    surface->base.height = u_minify(tex->b.b.height0, id.bits.level);
149    surface->base.usage = usage;
150    surface->base.u.tex.first_layer = id.bits.layer;
151    surface->base.u.tex.last_layer = surface->base.u.tex.first_layer;
152    surface->base.u.tex.level = id.bits.level;
153    surface->id = id;
154    surface->offset = tex->image_offset[id.bits.level][id.bits.layer];
155    surface->cpp = tex->cpp;
156    surface->pitch = tex->pitch;
157    surface->tiling = tex->tiling;
158
159    bo_reference( &surface->bo, tex->bo );
160    pipe_resource_reference( &surface->base.texture, &tex->b.b );
161
162    surface->ss.ss0.surface_format = tex->ss.ss0.surface_format;
163    surface->ss.ss0.surface_type = BRW_SURFACE_2D;
164
165    if (tex->tiling == BRW_TILING_NONE) {
166       surface->ss.ss1.base_addr = surface->offset;
167    } else {
168       uint32_t tile_offset = surface->offset % 4096;
169
170       surface->ss.ss1.base_addr = surface->offset - tile_offset;
171
172       if (tex->tiling == BRW_TILING_X) {
173         /* Note that the low bits of these fields are missing, so
174          * there's the possibility of getting in trouble.
175          */
176         surface->ss.ss5.x_offset = (tile_offset % 512) / tex->cpp / 4;
177         surface->ss.ss5.y_offset = tile_offset / 512 / 2;
178       } else {
179         surface->ss.ss5.x_offset = (tile_offset % 128) / tex->cpp / 4;
180             surface->ss.ss5.y_offset = tile_offset / 128 / 2;
181       }
182    }
183
184 #if 0
185    if (region_bo != NULL)
186       surface->ss.ss1.base_addr += region_bo->offset; /* reloc */
187 #endif
188
189    surface->ss.ss2.width = surface->base.width - 1;
190    surface->ss.ss2.height = surface->base.height - 1;
191    surface->ss.ss3.tiled_surface = tex->ss.ss3.tiled_surface;
192    surface->ss.ss3.tile_walk = tex->ss.ss3.tile_walk;
193    surface->ss.ss3.pitch = tex->ss.ss3.pitch;
194
195    return surface;
196 }
197
198 /* Get a surface which is view into a texture 
199  */
200 static struct pipe_surface *brw_create_surface(struct pipe_context *pipe,
201                                                struct pipe_resource *pt,
202                                                const struct pipe_surface *surf_tmpl)
203 {
204    struct brw_texture *tex = brw_texture(pt);
205    struct brw_screen *bscreen = brw_screen(pipe->screen);
206    struct brw_surface *surface;
207    union brw_surface_id id;
208    int type;
209
210    assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer);
211    id.bits.level = surf_tmpl->u.tex.level;
212    id.bits.layer = surf_tmpl->u.tex.first_layer;
213
214    if (need_linear_view(bscreen, tex, id, surf_tmpl->usage))
215       type = BRW_VIEW_LINEAR;
216    else
217       type = BRW_VIEW_IN_PLACE;
218
219    
220    foreach (surface, &tex->views[type]) {
221       if (id.value == surface->id.value)
222          return &surface->base;
223    }
224
225    switch (type) {
226    case BRW_VIEW_LINEAR:
227       surface = create_linear_view( bscreen, pipe, tex, id, surf_tmpl->usage );
228       break;
229    case BRW_VIEW_IN_PLACE:
230       surface = create_in_place_view( bscreen, pipe, tex, id, surf_tmpl->usage );
231       break;
232    }
233
234    insert_at_head( &tex->views[type], surface );
235    return &surface->base;
236 }
237
238
239 static void brw_surface_destroy( struct pipe_context *pipe,
240                                  struct pipe_surface *surf )
241 {
242    struct brw_surface *surface = brw_surface(surf);
243
244    /* Unreference texture, shared buffer:
245     */
246    remove_from_list(surface);
247    bo_reference(&surface->bo, NULL);
248    pipe_resource_reference( &surface->base.texture, NULL );
249
250    FREE(surface);
251 }
252
253
254 void brw_pipe_surface_init( struct brw_context *brw )
255 {
256    brw->base.create_surface = brw_create_surface;
257    brw->base.surface_destroy = brw_surface_destroy;
258 }