2 * Copyright © 2011 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23 #include "main/mtypes.h"
24 #include "main/samplerobj.h"
25 #include "program/prog_parameter.h"
27 #include "intel_mipmap_tree.h"
28 #include "intel_batchbuffer.h"
29 #include "intel_tex.h"
30 #include "intel_fbo.h"
31 #include "intel_buffer_objects.h"
33 #include "brw_context.h"
34 #include "brw_state.h"
35 #include "brw_defines.h"
39 gen7_set_surface_tiling(struct gen7_surface_state
*surf
, uint32_t tiling
)
42 case I915_TILING_NONE
:
43 surf
->ss0
.tiled_surface
= 0;
44 surf
->ss0
.tile_walk
= 0;
47 surf
->ss0
.tiled_surface
= 1;
48 surf
->ss0
.tile_walk
= BRW_TILEWALK_XMAJOR
;
51 surf
->ss0
.tiled_surface
= 1;
52 surf
->ss0
.tile_walk
= BRW_TILEWALK_YMAJOR
;
59 gen7_set_surface_num_multisamples(struct gen7_surface_state
*surf
,
63 surf
->ss4
.num_multisamples
= GEN7_SURFACE_MULTISAMPLECOUNT_8
;
64 else if (num_samples
> 0)
65 surf
->ss4
.num_multisamples
= GEN7_SURFACE_MULTISAMPLECOUNT_4
;
67 surf
->ss4
.num_multisamples
= GEN7_SURFACE_MULTISAMPLECOUNT_1
;
72 gen7_check_surface_setup(struct gen7_surface_state
*surf
,
73 bool is_render_target
)
75 bool is_multisampled
=
76 surf
->ss4
.num_multisamples
!= GEN7_SURFACE_MULTISAMPLECOUNT_1
;
77 /* From the Graphics BSpec: vol5c Shared Functions [SNB+] > State >
78 * SURFACE_STATE > SURFACE_STATE for most messages [DevIVB]: Surface Array
81 * If Multisampled Surface Storage Format is MSFMT_MSS and Number of
82 * Multisamples is not MULTISAMPLECOUNT_1, this field must be set to
85 if (surf
->ss4
.multisampled_surface_storage_format
== GEN7_SURFACE_MSFMT_MSS
87 assert(surf
->ss0
.surface_array_spacing
== GEN7_SURFACE_ARYSPC_LOD0
);
89 /* From the Graphics BSpec: vol5c Shared Functions [SNB+] > State >
90 * SURFACE_STATE > SURFACE_STATE for most messages [DevIVB]: Multisampled
91 * Surface Storage Format:
93 * All multisampled render target surfaces must have this field set to
98 * This field is ignored if Number of Multisamples is MULTISAMPLECOUNT_1.
100 if (is_render_target
&& is_multisampled
) {
101 assert(surf
->ss4
.multisampled_surface_storage_format
==
102 GEN7_SURFACE_MSFMT_MSS
);
105 /* From the Graphics BSpec: vol5c Shared Functions [SNB+] > State >
106 * SURFACE_STATE > SURFACE_STATE for most messages [DevIVB]: Multisampled
107 * Surface Storage Format:
109 * If the surface’s Number of Multisamples is MULTISAMPLECOUNT_8, Width
110 * is >= 8192 (meaning the actual surface width is >= 8193 pixels), this
111 * field must be set to MSFMT_MSS.
113 if (surf
->ss4
.num_multisamples
== GEN7_SURFACE_MULTISAMPLECOUNT_8
&&
114 surf
->ss2
.width
>= 8192) {
115 assert(surf
->ss4
.multisampled_surface_storage_format
==
116 GEN7_SURFACE_MSFMT_MSS
);
119 /* From the Graphics BSpec: vol5c Shared Functions [SNB+] > State >
120 * SURFACE_STATE > SURFACE_STATE for most messages [DevIVB]: Multisampled
121 * Surface Storage Format:
123 * If the surface’s Number of Multisamples is MULTISAMPLECOUNT_8,
124 * ((Depth+1) * (Height+1)) is > 4,194,304, OR if the surface’s Number of
125 * Multisamples is MULTISAMPLECOUNT_4, ((Depth+1) * (Height+1)) is >
126 * 8,388,608, this field must be set to MSFMT_DEPTH_STENCIL.This field
127 * must be set to MSFMT_DEPTH_STENCIL if Surface Format is one of the
128 * following: I24X8_UNORM, L24X8_UNORM, A24X8_UNORM, or
129 * R24_UNORM_X8_TYPELESS.
133 * This field is ignored if Number of Multisamples is MULTISAMPLECOUNT_1.
135 uint32_t depth
= surf
->ss3
.depth
+ 1;
136 uint32_t height
= surf
->ss2
.height
+ 1;
137 if (surf
->ss4
.num_multisamples
== GEN7_SURFACE_MULTISAMPLECOUNT_8
&&
138 depth
* height
> 4194304) {
139 assert(surf
->ss4
.multisampled_surface_storage_format
==
140 GEN7_SURFACE_MSFMT_DEPTH_STENCIL
);
142 if (surf
->ss4
.num_multisamples
== GEN7_SURFACE_MULTISAMPLECOUNT_4
&&
143 depth
* height
> 8388608) {
144 assert(surf
->ss4
.multisampled_surface_storage_format
==
145 GEN7_SURFACE_MSFMT_DEPTH_STENCIL
);
147 if (is_multisampled
) {
148 switch (surf
->ss0
.surface_format
) {
149 case BRW_SURFACEFORMAT_I24X8_UNORM
:
150 case BRW_SURFACEFORMAT_L24X8_UNORM
:
151 case BRW_SURFACEFORMAT_A24X8_UNORM
:
152 case BRW_SURFACEFORMAT_R24_UNORM_X8_TYPELESS
:
153 assert(surf
->ss4
.multisampled_surface_storage_format
==
154 GEN7_SURFACE_MSFMT_DEPTH_STENCIL
);
161 gen7_update_buffer_texture_surface(struct gl_context
*ctx
, GLuint unit
)
163 struct brw_context
*brw
= brw_context(ctx
);
164 struct gl_texture_object
*tObj
= ctx
->Texture
.Unit
[unit
]._Current
;
165 const GLuint surf_index
= SURF_INDEX_TEXTURE(unit
);
166 struct gen7_surface_state
*surf
;
167 struct intel_buffer_object
*intel_obj
=
168 intel_buffer_object(tObj
->BufferObject
);
169 drm_intel_bo
*bo
= intel_obj
? intel_obj
->buffer
: NULL
;
170 gl_format format
= tObj
->_BufferObjectFormat
;
171 int texel_size
= _mesa_get_format_bytes(format
);
173 surf
= brw_state_batch(brw
, AUB_TRACE_SURFACE_STATE
,
174 sizeof(*surf
), 32, &brw
->wm
.surf_offset
[surf_index
]);
175 memset(surf
, 0, sizeof(*surf
));
177 surf
->ss0
.surface_type
= BRW_SURFACE_BUFFER
;
178 surf
->ss0
.surface_format
= brw_format_for_mesa_format(format
);
180 surf
->ss0
.render_cache_read_write
= 1;
182 if (surf
->ss0
.surface_format
== 0 && format
!= MESA_FORMAT_RGBA_FLOAT32
) {
183 _mesa_problem(NULL
, "bad format %s for texture buffer\n",
184 _mesa_get_format_name(format
));
188 surf
->ss1
.base_addr
= bo
->offset
; /* reloc */
190 /* Emit relocation to surface contents. Section 5.1.1 of the gen4
191 * bspec ("Data Cache") says that the data cache does not exist as
192 * a separate cache and is just the sampler cache.
194 drm_intel_bo_emit_reloc(brw
->intel
.batch
.bo
,
195 (brw
->wm
.surf_offset
[surf_index
] +
196 offsetof(struct gen7_surface_state
, ss1
)),
198 I915_GEM_DOMAIN_SAMPLER
, 0);
200 int w
= intel_obj
->Base
.Size
/ texel_size
;
201 surf
->ss2
.width
= w
& 0x7f; /* bits 6:0 of size or width */
202 surf
->ss2
.height
= (w
>> 7) & 0x1fff; /* bits 19:7 of size or width */
203 surf
->ss3
.depth
= (w
>> 20) & 0x7f; /* bits 26:20 of size or width */
204 surf
->ss3
.pitch
= texel_size
- 1;
206 surf
->ss1
.base_addr
= 0;
208 surf
->ss2
.height
= 0;
213 gen7_set_surface_tiling(surf
, I915_TILING_NONE
);
215 gen7_check_surface_setup(surf
, false /* is_render_target */);
219 gen7_update_texture_surface(struct gl_context
*ctx
, GLuint unit
)
221 struct brw_context
*brw
= brw_context(ctx
);
222 struct gl_texture_object
*tObj
= ctx
->Texture
.Unit
[unit
]._Current
;
223 struct intel_texture_object
*intelObj
= intel_texture_object(tObj
);
224 struct intel_mipmap_tree
*mt
= intelObj
->mt
;
225 struct gl_texture_image
*firstImage
= tObj
->Image
[0][tObj
->BaseLevel
];
226 struct gl_sampler_object
*sampler
= _mesa_get_samplerobj(ctx
, unit
);
227 const GLuint surf_index
= SURF_INDEX_TEXTURE(unit
);
228 struct gen7_surface_state
*surf
;
229 int width
, height
, depth
;
231 if (tObj
->Target
== GL_TEXTURE_BUFFER
) {
232 gen7_update_buffer_texture_surface(ctx
, unit
);
236 /* We don't support MSAA for textures. */
237 assert(!mt
->array_spacing_lod0
);
238 assert(mt
->num_samples
== 0);
240 intel_miptree_get_dimensions_for_image(firstImage
, &width
, &height
, &depth
);
242 surf
= brw_state_batch(brw
, AUB_TRACE_SURFACE_STATE
,
243 sizeof(*surf
), 32, &brw
->wm
.surf_offset
[surf_index
]);
244 memset(surf
, 0, sizeof(*surf
));
246 if (mt
->align_h
== 4)
247 surf
->ss0
.vertical_alignment
= 1;
248 if (mt
->align_w
== 8)
249 surf
->ss0
.horizontal_alignment
= 1;
251 surf
->ss0
.surface_type
= translate_tex_target(tObj
->Target
);
252 surf
->ss0
.surface_format
= translate_tex_format(mt
->format
,
253 firstImage
->InternalFormat
,
255 sampler
->sRGBDecode
);
256 if (tObj
->Target
== GL_TEXTURE_CUBE_MAP
) {
257 surf
->ss0
.cube_pos_x
= 1;
258 surf
->ss0
.cube_pos_y
= 1;
259 surf
->ss0
.cube_pos_z
= 1;
260 surf
->ss0
.cube_neg_x
= 1;
261 surf
->ss0
.cube_neg_y
= 1;
262 surf
->ss0
.cube_neg_z
= 1;
265 surf
->ss0
.is_array
= depth
> 1 && tObj
->Target
!= GL_TEXTURE_3D
;
267 gen7_set_surface_tiling(surf
, intelObj
->mt
->region
->tiling
);
269 /* ss0 remaining fields:
270 * - vert_line_stride (exists on gen6 but we ignore it)
271 * - vert_line_stride_ofs (exists on gen6 but we ignore it)
272 * - surface_array_spacing
273 * - render_cache_read_write (exists on gen6 but ignored here)
276 surf
->ss1
.base_addr
=
277 intelObj
->mt
->region
->bo
->offset
+ intelObj
->mt
->offset
; /* reloc */
279 surf
->ss2
.width
= width
- 1;
280 surf
->ss2
.height
= height
- 1;
282 surf
->ss3
.pitch
= (intelObj
->mt
->region
->pitch
* intelObj
->mt
->cpp
) - 1;
283 surf
->ss3
.depth
= depth
- 1;
287 surf
->ss5
.mip_count
= intelObj
->_MaxLevel
- tObj
->BaseLevel
;
288 surf
->ss5
.min_lod
= 0;
290 /* ss5 remaining fields:
291 * - x_offset (N/A for textures?)
296 if (brw
->intel
.is_haswell
) {
297 surf
->ss7
.shader_chanel_select_r
= HSW_SCS_RED
;
298 surf
->ss7
.shader_chanel_select_g
= HSW_SCS_GREEN
;
299 surf
->ss7
.shader_chanel_select_b
= HSW_SCS_BLUE
;
300 surf
->ss7
.shader_chanel_select_a
= HSW_SCS_ALPHA
;
303 /* Emit relocation to surface contents */
304 drm_intel_bo_emit_reloc(brw
->intel
.batch
.bo
,
305 brw
->wm
.surf_offset
[surf_index
] +
306 offsetof(struct gen7_surface_state
, ss1
),
307 intelObj
->mt
->region
->bo
, intelObj
->mt
->offset
,
308 I915_GEM_DOMAIN_SAMPLER
, 0);
310 gen7_check_surface_setup(surf
, false /* is_render_target */);
314 * Create the constant buffer surface. Vertex/fragment shader constants will
315 * be read from this buffer with Data Port Read instructions/messages.
318 gen7_create_constant_surface(struct brw_context
*brw
,
321 uint32_t *out_offset
)
323 const GLint w
= width
- 1;
324 struct gen7_surface_state
*surf
;
326 surf
= brw_state_batch(brw
, AUB_TRACE_SURFACE_STATE
,
327 sizeof(*surf
), 32, out_offset
);
328 memset(surf
, 0, sizeof(*surf
));
330 surf
->ss0
.surface_type
= BRW_SURFACE_BUFFER
;
331 surf
->ss0
.surface_format
= BRW_SURFACEFORMAT_R32G32B32A32_FLOAT
;
333 surf
->ss0
.render_cache_read_write
= 1;
336 surf
->ss1
.base_addr
= bo
->offset
; /* reloc */
338 surf
->ss2
.width
= w
& 0x7f; /* bits 6:0 of size or width */
339 surf
->ss2
.height
= (w
>> 7) & 0x1fff; /* bits 19:7 of size or width */
340 surf
->ss3
.depth
= (w
>> 20) & 0x7f; /* bits 26:20 of size or width */
341 surf
->ss3
.pitch
= (16 - 1); /* stride between samples */
342 gen7_set_surface_tiling(surf
, I915_TILING_NONE
); /* tiling now allowed */
344 if (brw
->intel
.is_haswell
) {
345 surf
->ss7
.shader_chanel_select_r
= HSW_SCS_RED
;
346 surf
->ss7
.shader_chanel_select_g
= HSW_SCS_GREEN
;
347 surf
->ss7
.shader_chanel_select_b
= HSW_SCS_BLUE
;
348 surf
->ss7
.shader_chanel_select_a
= HSW_SCS_ALPHA
;
351 /* Emit relocation to surface contents. Section 5.1.1 of the gen4
352 * bspec ("Data Cache") says that the data cache does not exist as
353 * a separate cache and is just the sampler cache.
355 drm_intel_bo_emit_reloc(brw
->intel
.batch
.bo
,
357 offsetof(struct gen7_surface_state
, ss1
)),
359 I915_GEM_DOMAIN_SAMPLER
, 0);
361 gen7_check_surface_setup(surf
, false /* is_render_target */);
365 gen7_update_null_renderbuffer_surface(struct brw_context
*brw
, unsigned unit
)
367 struct gen7_surface_state
*surf
;
369 surf
= brw_state_batch(brw
, AUB_TRACE_SURFACE_STATE
,
370 sizeof(*surf
), 32, &brw
->wm
.surf_offset
[unit
]);
371 memset(surf
, 0, sizeof(*surf
));
373 surf
->ss0
.surface_type
= BRW_SURFACE_NULL
;
374 surf
->ss0
.surface_format
= BRW_SURFACEFORMAT_B8G8R8A8_UNORM
;
376 gen7_check_surface_setup(surf
, true /* is_render_target */);
380 * Sets up a surface state structure to point at the given region.
381 * While it is only used for the front/back buffer currently, it should be
382 * usable for further buffers when doing ARB_draw_buffer support.
385 gen7_update_renderbuffer_surface(struct brw_context
*brw
,
386 struct gl_renderbuffer
*rb
,
389 struct intel_context
*intel
= &brw
->intel
;
390 struct gl_context
*ctx
= &intel
->ctx
;
391 struct intel_renderbuffer
*irb
= intel_renderbuffer(rb
);
392 struct intel_region
*region
= irb
->mt
->region
;
393 struct gen7_surface_state
*surf
;
394 uint32_t tile_x
, tile_y
;
395 gl_format rb_format
= intel_rb_format(irb
);
397 surf
= brw_state_batch(brw
, AUB_TRACE_SURFACE_STATE
,
398 sizeof(*surf
), 32, &brw
->wm
.surf_offset
[unit
]);
399 memset(surf
, 0, sizeof(*surf
));
401 /* Render targets can't use MSAA interleaved layout */
402 assert(!irb
->mt
->msaa_is_interleaved
);
404 if (irb
->mt
->align_h
== 4)
405 surf
->ss0
.vertical_alignment
= 1;
406 if (irb
->mt
->align_w
== 8)
407 surf
->ss0
.horizontal_alignment
= 1;
410 case MESA_FORMAT_SARGB8
:
413 * Without GL_EXT_framebuffer_sRGB we shouldn't bind sRGB surfaces to the
414 * blend/update as sRGB.
416 if (ctx
->Color
.sRGBEnabled
)
417 surf
->ss0
.surface_format
= brw_format_for_mesa_format(rb_format
);
419 surf
->ss0
.surface_format
= BRW_SURFACEFORMAT_B8G8R8A8_UNORM
;
422 assert(brw_render_target_supported(intel
, rb
));
423 surf
->ss0
.surface_format
= brw
->render_target_format
[rb_format
];
424 if (unlikely(!brw
->format_supported_as_render_target
[rb_format
])) {
425 _mesa_problem(ctx
, "%s: renderbuffer format %s unsupported\n",
426 __FUNCTION__
, _mesa_get_format_name(rb_format
));
431 surf
->ss0
.surface_type
= BRW_SURFACE_2D
;
432 surf
->ss0
.surface_array_spacing
= irb
->mt
->array_spacing_lod0
?
433 GEN7_SURFACE_ARYSPC_LOD0
: GEN7_SURFACE_ARYSPC_FULL
;
436 surf
->ss1
.base_addr
= intel_renderbuffer_tile_offsets(irb
, &tile_x
, &tile_y
);
437 surf
->ss1
.base_addr
+= region
->bo
->offset
; /* reloc */
439 assert(brw
->has_surface_tile_offset
);
440 /* Note that the low bits of these fields are missing, so
441 * there's the possibility of getting in trouble.
443 assert(tile_x
% 4 == 0);
444 assert(tile_y
% 2 == 0);
445 surf
->ss5
.x_offset
= tile_x
/ 4;
446 surf
->ss5
.y_offset
= tile_y
/ 2;
448 surf
->ss2
.width
= rb
->Width
- 1;
449 surf
->ss2
.height
= rb
->Height
- 1;
450 gen7_set_surface_tiling(surf
, region
->tiling
);
451 surf
->ss3
.pitch
= (region
->pitch
* region
->cpp
) - 1;
453 gen7_set_surface_num_multisamples(surf
, irb
->mt
->num_samples
);
455 if (intel
->is_haswell
) {
456 surf
->ss7
.shader_chanel_select_r
= HSW_SCS_RED
;
457 surf
->ss7
.shader_chanel_select_g
= HSW_SCS_GREEN
;
458 surf
->ss7
.shader_chanel_select_b
= HSW_SCS_BLUE
;
459 surf
->ss7
.shader_chanel_select_a
= HSW_SCS_ALPHA
;
462 drm_intel_bo_emit_reloc(brw
->intel
.batch
.bo
,
463 brw
->wm
.surf_offset
[unit
] +
464 offsetof(struct gen7_surface_state
, ss1
),
466 surf
->ss1
.base_addr
- region
->bo
->offset
,
467 I915_GEM_DOMAIN_RENDER
,
468 I915_GEM_DOMAIN_RENDER
);
470 gen7_check_surface_setup(surf
, true /* is_render_target */);
474 gen7_init_vtable_surface_functions(struct brw_context
*brw
)
476 struct intel_context
*intel
= &brw
->intel
;
478 intel
->vtbl
.update_texture_surface
= gen7_update_texture_surface
;
479 intel
->vtbl
.update_renderbuffer_surface
= gen7_update_renderbuffer_surface
;
480 intel
->vtbl
.update_null_renderbuffer_surface
=
481 gen7_update_null_renderbuffer_surface
;
482 intel
->vtbl
.create_constant_surface
= gen7_create_constant_surface
;