f0370268be8c383a278050cac38825114551a8d2
[profile/ivi/mesa.git] / src / mesa / drivers / dri / i965 / gen7_wm_surface_state.c
1 /*
2  * Copyright © 2011 Intel Corporation
3  *
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:
10  *
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
13  * Software.
14  *
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
21  * IN THE SOFTWARE.
22  */
23 #include "main/mtypes.h"
24 #include "main/samplerobj.h"
25 #include "program/prog_parameter.h"
26
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"
32
33 #include "brw_context.h"
34 #include "brw_state.h"
35 #include "brw_defines.h"
36 #include "brw_wm.h"
37
38 void
39 gen7_set_surface_tiling(struct gen7_surface_state *surf, uint32_t tiling)
40 {
41    switch (tiling) {
42    case I915_TILING_NONE:
43       surf->ss0.tiled_surface = 0;
44       surf->ss0.tile_walk = 0;
45       break;
46    case I915_TILING_X:
47       surf->ss0.tiled_surface = 1;
48       surf->ss0.tile_walk = BRW_TILEWALK_XMAJOR;
49       break;
50    case I915_TILING_Y:
51       surf->ss0.tiled_surface = 1;
52       surf->ss0.tile_walk = BRW_TILEWALK_YMAJOR;
53       break;
54    }
55 }
56
57
58 void
59 gen7_set_surface_num_multisamples(struct gen7_surface_state *surf,
60                                   unsigned num_samples)
61 {
62    if (num_samples > 4)
63       surf->ss4.num_multisamples = GEN7_SURFACE_MULTISAMPLECOUNT_8;
64    else if (num_samples > 0)
65       surf->ss4.num_multisamples = GEN7_SURFACE_MULTISAMPLECOUNT_4;
66    else
67       surf->ss4.num_multisamples = GEN7_SURFACE_MULTISAMPLECOUNT_1;
68 }
69
70
71 void
72 gen7_set_surface_mcs_info(struct brw_context *brw,
73                           struct gen7_surface_state *surf,
74                           uint32_t surf_offset,
75                           const struct intel_mipmap_tree *mcs_mt,
76                           bool is_render_target)
77 {
78    /* From the Ivy Bridge PRM, Vol4 Part1 p76, "MCS Base Address":
79     *
80     *     "The MCS surface must be stored as Tile Y."
81     */
82    assert(mcs_mt->region->tiling == I915_TILING_Y);
83
84    /* Compute the pitch in units of tiles.  To do this we need to divide the
85     * pitch in bytes by 128, since a single Y-tile is 128 bytes wide.
86     */
87    unsigned pitch_bytes = mcs_mt->region->pitch * mcs_mt->cpp;
88    unsigned pitch_tiles = pitch_bytes / 128;
89
90    /* The upper 20 bits of surface state DWORD 6 are the upper 20 bits of the
91     * GPU address of the MCS buffer; the lower 12 bits contain other control
92     * information.  Since buffer addresses are always on 4k boundaries (and
93     * thus have their lower 12 bits zero), we can use an ordinary reloc to do
94     * the necessary address translation.
95     */
96    assert ((mcs_mt->region->bo->offset & 0xfff) == 0);
97    surf->ss6.mcs_enabled.mcs_enable = 1;
98    surf->ss6.mcs_enabled.mcs_surface_pitch = pitch_tiles - 1;
99    surf->ss6.mcs_enabled.mcs_base_address = mcs_mt->region->bo->offset >> 12;
100    drm_intel_bo_emit_reloc(brw->intel.batch.bo,
101                            surf_offset +
102                            offsetof(struct gen7_surface_state, ss6),
103                            mcs_mt->region->bo,
104                            surf->ss6.raw_data & 0xfff,
105                            is_render_target ? I915_GEM_DOMAIN_RENDER
106                            : I915_GEM_DOMAIN_SAMPLER,
107                            is_render_target ? I915_GEM_DOMAIN_RENDER : 0);
108 }
109
110
111 void
112 gen7_check_surface_setup(struct gen7_surface_state *surf,
113                          bool is_render_target)
114 {
115    bool is_multisampled =
116       surf->ss4.num_multisamples != GEN7_SURFACE_MULTISAMPLECOUNT_1;
117    /* From the Graphics BSpec: vol5c Shared Functions [SNB+] > State >
118     * SURFACE_STATE > SURFACE_STATE for most messages [DevIVB]: Surface Array
119     * Spacing:
120     *
121     *   If Multisampled Surface Storage Format is MSFMT_MSS and Number of
122     *   Multisamples is not MULTISAMPLECOUNT_1, this field must be set to
123     *   ARYSPC_LOD0.
124     */
125    if (surf->ss4.multisampled_surface_storage_format == GEN7_SURFACE_MSFMT_MSS
126        && is_multisampled)
127       assert(surf->ss0.surface_array_spacing == GEN7_SURFACE_ARYSPC_LOD0);
128
129    /* From the Graphics BSpec: vol5c Shared Functions [SNB+] > State >
130     * SURFACE_STATE > SURFACE_STATE for most messages [DevIVB]: Multisampled
131     * Surface Storage Format:
132     *
133     *   All multisampled render target surfaces must have this field set to
134     *   MSFMT_MSS.
135     *
136     * But also:
137     *
138     *   This field is ignored if Number of Multisamples is MULTISAMPLECOUNT_1.
139     */
140    if (is_render_target && is_multisampled) {
141       assert(surf->ss4.multisampled_surface_storage_format ==
142              GEN7_SURFACE_MSFMT_MSS);
143    }
144
145    /* From the Graphics BSpec: vol5c Shared Functions [SNB+] > State >
146     * SURFACE_STATE > SURFACE_STATE for most messages [DevIVB]: Multisampled
147     * Surface Storage Format:
148     *
149     *   If the surface’s Number of Multisamples is MULTISAMPLECOUNT_8, Width
150     *   is >= 8192 (meaning the actual surface width is >= 8193 pixels), this
151     *   field must be set to MSFMT_MSS.
152     */
153    if (surf->ss4.num_multisamples == GEN7_SURFACE_MULTISAMPLECOUNT_8 &&
154        surf->ss2.width >= 8192) {
155       assert(surf->ss4.multisampled_surface_storage_format ==
156              GEN7_SURFACE_MSFMT_MSS);
157    }
158
159    /* From the Graphics BSpec: vol5c Shared Functions [SNB+] > State >
160     * SURFACE_STATE > SURFACE_STATE for most messages [DevIVB]: Multisampled
161     * Surface Storage Format:
162     *
163     *   If the surface’s Number of Multisamples is MULTISAMPLECOUNT_8,
164     *   ((Depth+1) * (Height+1)) is > 4,194,304, OR if the surface’s Number of
165     *   Multisamples is MULTISAMPLECOUNT_4, ((Depth+1) * (Height+1)) is >
166     *   8,388,608, this field must be set to MSFMT_DEPTH_STENCIL.This field
167     *   must be set to MSFMT_DEPTH_STENCIL if Surface Format is one of the
168     *   following: I24X8_UNORM, L24X8_UNORM, A24X8_UNORM, or
169     *   R24_UNORM_X8_TYPELESS.
170     *
171     * But also:
172     *
173     *   This field is ignored if Number of Multisamples is MULTISAMPLECOUNT_1.
174     */
175    uint32_t depth = surf->ss3.depth + 1;
176    uint32_t height = surf->ss2.height + 1;
177    if (surf->ss4.num_multisamples == GEN7_SURFACE_MULTISAMPLECOUNT_8 &&
178        depth * height > 4194304) {
179       assert(surf->ss4.multisampled_surface_storage_format ==
180              GEN7_SURFACE_MSFMT_DEPTH_STENCIL);
181    }
182    if (surf->ss4.num_multisamples == GEN7_SURFACE_MULTISAMPLECOUNT_4 &&
183        depth * height > 8388608) {
184       assert(surf->ss4.multisampled_surface_storage_format ==
185              GEN7_SURFACE_MSFMT_DEPTH_STENCIL);
186    }
187    if (is_multisampled) {
188       switch (surf->ss0.surface_format) {
189       case BRW_SURFACEFORMAT_I24X8_UNORM:
190       case BRW_SURFACEFORMAT_L24X8_UNORM:
191       case BRW_SURFACEFORMAT_A24X8_UNORM:
192       case BRW_SURFACEFORMAT_R24_UNORM_X8_TYPELESS:
193          assert(surf->ss4.multisampled_surface_storage_format ==
194                 GEN7_SURFACE_MSFMT_DEPTH_STENCIL);
195       }
196    }
197 }
198
199
200 static void
201 gen7_update_buffer_texture_surface(struct gl_context *ctx, GLuint unit)
202 {
203    struct brw_context *brw = brw_context(ctx);
204    struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current;
205    const GLuint surf_index = SURF_INDEX_TEXTURE(unit);
206    struct gen7_surface_state *surf;
207    struct intel_buffer_object *intel_obj =
208       intel_buffer_object(tObj->BufferObject);
209    drm_intel_bo *bo = intel_obj ? intel_obj->buffer : NULL;
210    gl_format format = tObj->_BufferObjectFormat;
211    int texel_size = _mesa_get_format_bytes(format);
212
213    surf = brw_state_batch(brw, AUB_TRACE_SURFACE_STATE,
214                           sizeof(*surf), 32, &brw->wm.surf_offset[surf_index]);
215    memset(surf, 0, sizeof(*surf));
216
217    surf->ss0.surface_type = BRW_SURFACE_BUFFER;
218    surf->ss0.surface_format = brw_format_for_mesa_format(format);
219
220    surf->ss0.render_cache_read_write = 1;
221
222    if (surf->ss0.surface_format == 0 && format != MESA_FORMAT_RGBA_FLOAT32) {
223       _mesa_problem(NULL, "bad format %s for texture buffer\n",
224                     _mesa_get_format_name(format));
225    }
226
227    if (bo) {
228       surf->ss1.base_addr = bo->offset; /* reloc */
229
230       /* Emit relocation to surface contents.  Section 5.1.1 of the gen4
231        * bspec ("Data Cache") says that the data cache does not exist as
232        * a separate cache and is just the sampler cache.
233        */
234       drm_intel_bo_emit_reloc(brw->intel.batch.bo,
235                               (brw->wm.surf_offset[surf_index] +
236                                offsetof(struct gen7_surface_state, ss1)),
237                               bo, 0,
238                               I915_GEM_DOMAIN_SAMPLER, 0);
239
240       int w = intel_obj->Base.Size / texel_size;
241       surf->ss2.width = w & 0x7f;            /* bits 6:0 of size or width */
242       surf->ss2.height = (w >> 7) & 0x1fff;  /* bits 19:7 of size or width */
243       surf->ss3.depth = (w >> 20) & 0x7f;    /* bits 26:20 of size or width */
244       surf->ss3.pitch = texel_size - 1;
245 } else {
246       surf->ss1.base_addr = 0;
247       surf->ss2.width = 0;
248       surf->ss2.height = 0;
249       surf->ss3.depth = 0;
250       surf->ss3.pitch = 0;
251    }
252
253    gen7_set_surface_tiling(surf, I915_TILING_NONE);
254
255    gen7_check_surface_setup(surf, false /* is_render_target */);
256 }
257
258 static void
259 gen7_update_texture_surface(struct gl_context *ctx, GLuint unit)
260 {
261    struct brw_context *brw = brw_context(ctx);
262    struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current;
263    struct intel_texture_object *intelObj = intel_texture_object(tObj);
264    struct intel_mipmap_tree *mt = intelObj->mt;
265    struct gl_texture_image *firstImage = tObj->Image[0][tObj->BaseLevel];
266    struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit);
267    const GLuint surf_index = SURF_INDEX_TEXTURE(unit);
268    struct gen7_surface_state *surf;
269    int width, height, depth;
270
271    if (tObj->Target == GL_TEXTURE_BUFFER) {
272       gen7_update_buffer_texture_surface(ctx, unit);
273       return;
274    }
275
276    /* We don't support MSAA for textures. */
277    assert(!mt->array_spacing_lod0);
278    assert(mt->num_samples == 0);
279
280    intel_miptree_get_dimensions_for_image(firstImage, &width, &height, &depth);
281
282    surf = brw_state_batch(brw, AUB_TRACE_SURFACE_STATE,
283                           sizeof(*surf), 32, &brw->wm.surf_offset[surf_index]);
284    memset(surf, 0, sizeof(*surf));
285
286    if (mt->align_h == 4)
287       surf->ss0.vertical_alignment = 1;
288    if (mt->align_w == 8)
289       surf->ss0.horizontal_alignment = 1;
290
291    surf->ss0.surface_type = translate_tex_target(tObj->Target);
292    surf->ss0.surface_format = translate_tex_format(mt->format,
293                                                    firstImage->InternalFormat,
294                                                    sampler->DepthMode,
295                                                    sampler->sRGBDecode);
296    if (tObj->Target == GL_TEXTURE_CUBE_MAP) {
297       surf->ss0.cube_pos_x = 1;
298       surf->ss0.cube_pos_y = 1;
299       surf->ss0.cube_pos_z = 1;
300       surf->ss0.cube_neg_x = 1;
301       surf->ss0.cube_neg_y = 1;
302       surf->ss0.cube_neg_z = 1;
303    }
304
305    surf->ss0.is_array = depth > 1 && tObj->Target != GL_TEXTURE_3D;
306
307    gen7_set_surface_tiling(surf, intelObj->mt->region->tiling);
308
309    /* ss0 remaining fields:
310     * - vert_line_stride (exists on gen6 but we ignore it)
311     * - vert_line_stride_ofs (exists on gen6 but we ignore it)
312     * - surface_array_spacing
313     * - render_cache_read_write (exists on gen6 but ignored here)
314     */
315
316    surf->ss1.base_addr =
317       intelObj->mt->region->bo->offset + intelObj->mt->offset; /* reloc */
318
319    surf->ss2.width = width - 1;
320    surf->ss2.height = height - 1;
321
322    surf->ss3.pitch = (intelObj->mt->region->pitch * intelObj->mt->cpp) - 1;
323    surf->ss3.depth = depth - 1;
324
325    /* ss4: ignored? */
326
327    surf->ss5.mip_count = intelObj->_MaxLevel - tObj->BaseLevel;
328    surf->ss5.min_lod = 0;
329
330    /* ss5 remaining fields:
331     * - x_offset (N/A for textures?)
332     * - y_offset (ditto)
333     * - cache_control
334     */
335
336    if (brw->intel.is_haswell) {
337       surf->ss7.shader_chanel_select_r = HSW_SCS_RED;
338       surf->ss7.shader_chanel_select_g = HSW_SCS_GREEN;
339       surf->ss7.shader_chanel_select_b = HSW_SCS_BLUE;
340       surf->ss7.shader_chanel_select_a = HSW_SCS_ALPHA;
341    }
342
343    /* Emit relocation to surface contents */
344    drm_intel_bo_emit_reloc(brw->intel.batch.bo,
345                            brw->wm.surf_offset[surf_index] +
346                            offsetof(struct gen7_surface_state, ss1),
347                            intelObj->mt->region->bo, intelObj->mt->offset,
348                            I915_GEM_DOMAIN_SAMPLER, 0);
349
350    gen7_check_surface_setup(surf, false /* is_render_target */);
351 }
352
353 /**
354  * Create the constant buffer surface.  Vertex/fragment shader constants will
355  * be read from this buffer with Data Port Read instructions/messages.
356  */
357 void
358 gen7_create_constant_surface(struct brw_context *brw,
359                              drm_intel_bo *bo,
360                              int width,
361                              uint32_t *out_offset)
362 {
363    const GLint w = width - 1;
364    struct gen7_surface_state *surf;
365
366    surf = brw_state_batch(brw, AUB_TRACE_SURFACE_STATE,
367                           sizeof(*surf), 32, out_offset);
368    memset(surf, 0, sizeof(*surf));
369
370    surf->ss0.surface_type = BRW_SURFACE_BUFFER;
371    surf->ss0.surface_format = BRW_SURFACEFORMAT_R32G32B32A32_FLOAT;
372
373    surf->ss0.render_cache_read_write = 1;
374
375    assert(bo);
376    surf->ss1.base_addr = bo->offset; /* reloc */
377
378    surf->ss2.width = w & 0x7f;            /* bits 6:0 of size or width */
379    surf->ss2.height = (w >> 7) & 0x1fff;  /* bits 19:7 of size or width */
380    surf->ss3.depth = (w >> 20) & 0x7f;    /* bits 26:20 of size or width */
381    surf->ss3.pitch = (16 - 1); /* stride between samples */
382    gen7_set_surface_tiling(surf, I915_TILING_NONE); /* tiling now allowed */
383
384    if (brw->intel.is_haswell) {
385       surf->ss7.shader_chanel_select_r = HSW_SCS_RED;
386       surf->ss7.shader_chanel_select_g = HSW_SCS_GREEN;
387       surf->ss7.shader_chanel_select_b = HSW_SCS_BLUE;
388       surf->ss7.shader_chanel_select_a = HSW_SCS_ALPHA;
389    }
390
391    /* Emit relocation to surface contents.  Section 5.1.1 of the gen4
392     * bspec ("Data Cache") says that the data cache does not exist as
393     * a separate cache and is just the sampler cache.
394     */
395    drm_intel_bo_emit_reloc(brw->intel.batch.bo,
396                            (*out_offset +
397                             offsetof(struct gen7_surface_state, ss1)),
398                            bo, 0,
399                            I915_GEM_DOMAIN_SAMPLER, 0);
400
401    gen7_check_surface_setup(surf, false /* is_render_target */);
402 }
403
404 static void
405 gen7_update_null_renderbuffer_surface(struct brw_context *brw, unsigned unit)
406 {
407    struct gen7_surface_state *surf;
408
409    surf = brw_state_batch(brw, AUB_TRACE_SURFACE_STATE,
410                           sizeof(*surf), 32, &brw->wm.surf_offset[unit]);
411    memset(surf, 0, sizeof(*surf));
412
413    surf->ss0.surface_type = BRW_SURFACE_NULL;
414    surf->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
415
416    gen7_check_surface_setup(surf, true /* is_render_target */);
417 }
418
419 /**
420  * Sets up a surface state structure to point at the given region.
421  * While it is only used for the front/back buffer currently, it should be
422  * usable for further buffers when doing ARB_draw_buffer support.
423  */
424 static void
425 gen7_update_renderbuffer_surface(struct brw_context *brw,
426                                  struct gl_renderbuffer *rb,
427                                  unsigned int unit)
428 {
429    struct intel_context *intel = &brw->intel;
430    struct gl_context *ctx = &intel->ctx;
431    struct intel_renderbuffer *irb = intel_renderbuffer(rb);
432    struct intel_region *region = irb->mt->region;
433    struct gen7_surface_state *surf;
434    uint32_t tile_x, tile_y;
435    gl_format rb_format = intel_rb_format(irb);
436
437    surf = brw_state_batch(brw, AUB_TRACE_SURFACE_STATE,
438                           sizeof(*surf), 32, &brw->wm.surf_offset[unit]);
439    memset(surf, 0, sizeof(*surf));
440
441    /* Render targets can't use IMS layout */
442    assert(irb->mt->msaa_layout != INTEL_MSAA_LAYOUT_IMS);
443
444    if (irb->mt->align_h == 4)
445       surf->ss0.vertical_alignment = 1;
446    if (irb->mt->align_w == 8)
447       surf->ss0.horizontal_alignment = 1;
448
449    switch (rb_format) {
450    case MESA_FORMAT_SARGB8:
451       /* _NEW_BUFFERS
452        *
453        * Without GL_EXT_framebuffer_sRGB we shouldn't bind sRGB surfaces to the
454        * blend/update as sRGB.
455        */
456       if (ctx->Color.sRGBEnabled)
457          surf->ss0.surface_format = brw_format_for_mesa_format(rb_format);
458       else
459          surf->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
460       break;
461    default:
462       assert(brw_render_target_supported(intel, rb));
463       surf->ss0.surface_format = brw->render_target_format[rb_format];
464       if (unlikely(!brw->format_supported_as_render_target[rb_format])) {
465          _mesa_problem(ctx, "%s: renderbuffer format %s unsupported\n",
466                        __FUNCTION__, _mesa_get_format_name(rb_format));
467       }
468        break;
469    }
470
471    surf->ss0.surface_type = BRW_SURFACE_2D;
472    surf->ss0.surface_array_spacing = irb->mt->array_spacing_lod0 ?
473       GEN7_SURFACE_ARYSPC_LOD0 : GEN7_SURFACE_ARYSPC_FULL;
474
475    /* reloc */
476    surf->ss1.base_addr = intel_renderbuffer_tile_offsets(irb, &tile_x, &tile_y);
477    surf->ss1.base_addr += region->bo->offset; /* reloc */
478
479    assert(brw->has_surface_tile_offset);
480    /* Note that the low bits of these fields are missing, so
481     * there's the possibility of getting in trouble.
482     */
483    assert(tile_x % 4 == 0);
484    assert(tile_y % 2 == 0);
485    surf->ss5.x_offset = tile_x / 4;
486    surf->ss5.y_offset = tile_y / 2;
487
488    surf->ss2.width = rb->Width - 1;
489    surf->ss2.height = rb->Height - 1;
490    gen7_set_surface_tiling(surf, region->tiling);
491    surf->ss3.pitch = (region->pitch * region->cpp) - 1;
492
493    gen7_set_surface_num_multisamples(surf, irb->mt->num_samples);
494
495    if (irb->mt->msaa_layout == INTEL_MSAA_LAYOUT_CMS) {
496       gen7_set_surface_mcs_info(brw, surf, brw->wm.surf_offset[unit],
497                                 irb->mt->mcs_mt, true /* is_render_target */);
498    }
499
500    if (intel->is_haswell) {
501       surf->ss7.shader_chanel_select_r = HSW_SCS_RED;
502       surf->ss7.shader_chanel_select_g = HSW_SCS_GREEN;
503       surf->ss7.shader_chanel_select_b = HSW_SCS_BLUE;
504       surf->ss7.shader_chanel_select_a = HSW_SCS_ALPHA;
505    }
506
507    drm_intel_bo_emit_reloc(brw->intel.batch.bo,
508                            brw->wm.surf_offset[unit] +
509                            offsetof(struct gen7_surface_state, ss1),
510                            region->bo,
511                            surf->ss1.base_addr - region->bo->offset,
512                            I915_GEM_DOMAIN_RENDER,
513                            I915_GEM_DOMAIN_RENDER);
514
515    gen7_check_surface_setup(surf, true /* is_render_target */);
516 }
517
518 void
519 gen7_init_vtable_surface_functions(struct brw_context *brw)
520 {
521    struct intel_context *intel = &brw->intel;
522
523    intel->vtbl.update_texture_surface = gen7_update_texture_surface;
524    intel->vtbl.update_renderbuffer_surface = gen7_update_renderbuffer_surface;
525    intel->vtbl.update_null_renderbuffer_surface =
526       gen7_update_null_renderbuffer_surface;
527    intel->vtbl.create_constant_surface = gen7_create_constant_surface;
528 }