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