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