Tizen 2.0 Release
[profile/ivi/osmesa.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 "main/texstore.h"
26 #include "program/prog_parameter.h"
27
28 #include "intel_mipmap_tree.h"
29 #include "intel_batchbuffer.h"
30 #include "intel_tex.h"
31 #include "intel_fbo.h"
32
33 #include "brw_context.h"
34 #include "brw_state.h"
35 #include "brw_defines.h"
36 #include "brw_wm.h"
37
38 static 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 static void
58 gen7_update_texture_surface(struct gl_context *ctx, GLuint unit)
59 {
60    struct brw_context *brw = brw_context(ctx);
61    struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current;
62    struct intel_texture_object *intelObj = intel_texture_object(tObj);
63    struct gl_texture_image *firstImage = tObj->Image[0][tObj->BaseLevel];
64    struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit);
65    const GLuint surf_index = SURF_INDEX_TEXTURE(unit);
66    struct gen7_surface_state *surf;
67
68    surf = brw_state_batch(brw, sizeof(*surf), 32,
69                          &brw->wm.surf_offset[surf_index]);
70    memset(surf, 0, sizeof(*surf));
71
72    surf->ss0.surface_type = translate_tex_target(tObj->Target);
73    surf->ss0.surface_format = translate_tex_format(firstImage->TexFormat,
74                                                    firstImage->InternalFormat,
75                                                    sampler->DepthMode,
76                                                    sampler->sRGBDecode);
77    if (tObj->Target == GL_TEXTURE_CUBE_MAP) {
78       surf->ss0.cube_pos_x = 1;
79       surf->ss0.cube_pos_y = 1;
80       surf->ss0.cube_pos_z = 1;
81       surf->ss0.cube_neg_x = 1;
82       surf->ss0.cube_neg_y = 1;
83       surf->ss0.cube_neg_z = 1;
84    }
85
86    gen7_set_surface_tiling(surf, intelObj->mt->region->tiling);
87
88    /* ss0 remaining fields:
89     * - is_array
90     * - vertical_alignment
91     * - horizontal_alignment
92     * - vert_line_stride (exists on gen6 but we ignore it)
93     * - vert_line_stride_ofs (exists on gen6 but we ignore it)
94     * - surface_array_spacing
95     * - render_cache_read_write (exists on gen6 but ignored here)
96     */
97
98    surf->ss1.base_addr = intelObj->mt->region->buffer->offset; /* reloc */
99
100    surf->ss2.width = firstImage->Width - 1;
101    surf->ss2.height = firstImage->Height - 1;
102
103    surf->ss3.pitch = (intelObj->mt->region->pitch * intelObj->mt->cpp) - 1;
104    surf->ss3.depth = firstImage->Depth - 1;
105
106    /* ss4: ignored? */
107
108    surf->ss5.mip_count = intelObj->_MaxLevel - tObj->BaseLevel;
109    surf->ss5.min_lod = 0;
110
111    /* ss5 remaining fields:
112     * - x_offset (N/A for textures?)
113     * - y_offset (ditto)
114     * - cache_control
115     */
116
117    /* Emit relocation to surface contents */
118    drm_intel_bo_emit_reloc(brw->intel.batch.bo,
119                            brw->wm.surf_offset[surf_index] +
120                            offsetof(struct gen7_surface_state, ss1),
121                            intelObj->mt->region->buffer, 0,
122                            I915_GEM_DOMAIN_SAMPLER, 0);
123 }
124
125 /**
126  * Create the constant buffer surface.  Vertex/fragment shader constants will
127  * be read from this buffer with Data Port Read instructions/messages.
128  */
129 void
130 gen7_create_constant_surface(struct brw_context *brw,
131                              drm_intel_bo *bo,
132                              int width,
133                              uint32_t *out_offset)
134 {
135    const GLint w = width - 1;
136    struct gen7_surface_state *surf;
137
138    surf = brw_state_batch(brw, sizeof(*surf), 32, out_offset);
139    memset(surf, 0, sizeof(*surf));
140
141    surf->ss0.surface_type = BRW_SURFACE_BUFFER;
142    surf->ss0.surface_format = BRW_SURFACEFORMAT_R32G32B32A32_FLOAT;
143
144    surf->ss0.render_cache_read_write = 1;
145
146    assert(bo);
147    surf->ss1.base_addr = bo->offset; /* reloc */
148
149    surf->ss2.width = w & 0x7f;            /* bits 6:0 of size or width */
150    surf->ss2.height = (w >> 7) & 0x1fff;  /* bits 19:7 of size or width */
151    surf->ss3.depth = (w >> 20) & 0x7f;    /* bits 26:20 of size or width */
152    surf->ss3.pitch = (width * 16) - 1; /* ignored?? */
153    gen7_set_surface_tiling(surf, I915_TILING_NONE); /* tiling now allowed */
154
155    /* Emit relocation to surface contents.  Section 5.1.1 of the gen4
156     * bspec ("Data Cache") says that the data cache does not exist as
157     * a separate cache and is just the sampler cache.
158     */
159    drm_intel_bo_emit_reloc(brw->intel.batch.bo,
160                            (*out_offset +
161                             offsetof(struct gen7_surface_state, ss1)),
162                            bo, 0,
163                            I915_GEM_DOMAIN_SAMPLER, 0);
164 }
165
166 /**
167  * Updates surface / buffer for fragment shader constant buffer, if
168  * one is required.
169  *
170  * This consumes the state updates for the constant buffer, and produces
171  * BRW_NEW_WM_SURFACES to get picked up by brw_prepare_wm_surfaces for
172  * inclusion in the binding table.
173  */
174 static void upload_wm_constant_surface(struct brw_context *brw)
175 {
176    GLuint surf = SURF_INDEX_FRAG_CONST_BUFFER;
177    struct brw_fragment_program *fp =
178       (struct brw_fragment_program *) brw->fragment_program;
179    const struct gl_program_parameter_list *params =
180       fp->program.Base.Parameters;
181
182    /* If there's no constant buffer, then no surface BO is needed to point at
183     * it.
184     */
185    if (brw->wm.const_bo == 0) {
186       if (brw->wm.surf_offset[surf]) {
187          brw->state.dirty.brw |= BRW_NEW_WM_SURFACES;
188          brw->wm.surf_offset[surf] = 0;
189       }
190       return;
191    }
192
193    gen7_create_constant_surface(brw, brw->wm.const_bo, params->NumParameters,
194                                 &brw->wm.surf_offset[surf]);
195    brw->state.dirty.brw |= BRW_NEW_WM_SURFACES;
196 }
197
198 const struct brw_tracked_state gen7_wm_constant_surface = {
199    .dirty = {
200       .mesa = 0,
201       .brw = (BRW_NEW_WM_CONSTBUF |
202               BRW_NEW_BATCH),
203       .cache = 0
204    },
205    .emit = upload_wm_constant_surface,
206 };
207
208 static void
209 gen7_update_null_renderbuffer_surface(struct brw_context *brw, unsigned unit)
210 {
211    struct gen7_surface_state *surf;
212
213    surf = brw_state_batch(brw, sizeof(*surf), 32,
214                          &brw->wm.surf_offset[unit]);
215    memset(surf, 0, sizeof(*surf));
216
217    surf->ss0.surface_type = BRW_SURFACE_NULL;
218    surf->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
219 }
220
221 /**
222  * Sets up a surface state structure to point at the given region.
223  * While it is only used for the front/back buffer currently, it should be
224  * usable for further buffers when doing ARB_draw_buffer support.
225  */
226 static void
227 gen7_update_renderbuffer_surface(struct brw_context *brw,
228                                  struct gl_renderbuffer *rb,
229                                  unsigned int unit)
230 {
231    struct intel_context *intel = &brw->intel;
232    struct gl_context *ctx = &intel->ctx;
233    struct intel_renderbuffer *irb = intel_renderbuffer(rb);
234    struct intel_region *region = irb->region;
235    struct gen7_surface_state *surf;
236    uint32_t tile_x, tile_y;
237
238    surf = brw_state_batch(brw, sizeof(*surf), 32,
239                           &brw->wm.surf_offset[unit]);
240    memset(surf, 0, sizeof(*surf));
241
242    switch (irb->Base.Format) {
243    case MESA_FORMAT_XRGB8888:
244       /* XRGB is handled as ARGB because the chips in this family
245        * cannot render to XRGB targets.  This means that we have to
246        * mask writes to alpha (ala glColorMask) and reconfigure the
247        * alpha blending hardware to use GL_ONE (or GL_ZERO) for
248        * cases where GL_DST_ALPHA (or GL_ONE_MINUS_DST_ALPHA) is
249        * used.
250        */
251       surf->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
252       break;
253    case MESA_FORMAT_INTENSITY_FLOAT32:
254    case MESA_FORMAT_LUMINANCE_FLOAT32:
255       /* For these formats, we just need to read/write the first
256        * channel into R, which is to say that we just treat them as
257        * GL_RED.
258        */
259       surf->ss0.surface_format = BRW_SURFACEFORMAT_R32_FLOAT;
260       break;
261    case MESA_FORMAT_SARGB8:
262       /* without GL_EXT_framebuffer_sRGB we shouldn't bind sRGB
263          surfaces to the blend/update as sRGB */
264       if (ctx->Color.sRGBEnabled)
265          surf->ss0.surface_format = brw_format_for_mesa_format(irb->Base.Format);
266       else
267          surf->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
268       break;
269    default:
270       assert(brw_render_target_supported(irb->Base.Format));
271       surf->ss0.surface_format = brw_format_for_mesa_format(irb->Base.Format);
272    }
273
274    surf->ss0.surface_type = BRW_SURFACE_2D;
275    /* reloc */
276    surf->ss1.base_addr = intel_renderbuffer_tile_offsets(irb, &tile_x, &tile_y);
277    surf->ss1.base_addr += region->buffer->offset; /* reloc */
278
279    assert(brw->has_surface_tile_offset);
280    /* Note that the low bits of these fields are missing, so
281     * there's the possibility of getting in trouble.
282     */
283    assert(tile_x % 4 == 0);
284    assert(tile_y % 2 == 0);
285    surf->ss5.x_offset = tile_x / 4;
286    surf->ss5.y_offset = tile_y / 2;
287
288    surf->ss2.width = rb->Width - 1;
289    surf->ss2.height = rb->Height - 1;
290    gen7_set_surface_tiling(surf, region->tiling);
291    surf->ss3.pitch = (region->pitch * region->cpp) - 1;
292
293    drm_intel_bo_emit_reloc(brw->intel.batch.bo,
294                            brw->wm.surf_offset[unit] +
295                            offsetof(struct gen7_surface_state, ss1),
296                            region->buffer,
297                            surf->ss1.base_addr - region->buffer->offset,
298                            I915_GEM_DOMAIN_RENDER,
299                            I915_GEM_DOMAIN_RENDER);
300 }
301
302 static void
303 prepare_wm_surfaces(struct brw_context *brw)
304 {
305    struct gl_context *ctx = &brw->intel.ctx;
306    int i;
307    int nr_surfaces = 0;
308
309    if (ctx->DrawBuffer->_NumColorDrawBuffers >= 1) {
310       for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
311          struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[i];
312          struct intel_renderbuffer *irb = intel_renderbuffer(rb);
313          struct intel_region *region = irb ? irb->region : NULL;
314
315          if (region)
316             brw_add_validated_bo(brw, region->buffer);
317          nr_surfaces = SURF_INDEX_DRAW(i) + 1;
318       }
319    }
320
321    if (brw->wm.const_bo) {
322       brw_add_validated_bo(brw, brw->wm.const_bo);
323       nr_surfaces = SURF_INDEX_FRAG_CONST_BUFFER + 1;
324    }
325
326    for (i = 0; i < BRW_MAX_TEX_UNIT; i++) {
327       const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
328       struct gl_texture_object *tObj = texUnit->_Current;
329       struct intel_texture_object *intelObj = intel_texture_object(tObj);
330
331       if (texUnit->_ReallyEnabled) {
332          brw_add_validated_bo(brw, intelObj->mt->region->buffer);
333          nr_surfaces = SURF_INDEX_TEXTURE(i) + 1;
334       }
335    }
336
337    /* Have to update this in our prepare, since the unit's prepare
338     * relies on it.
339     */
340    if (brw->wm.nr_surfaces != nr_surfaces) {
341       brw->wm.nr_surfaces = nr_surfaces;
342       brw->state.dirty.brw |= BRW_NEW_NR_WM_SURFACES;
343    }
344 }
345
346 /**
347  * Constructs the set of surface state objects pointed to by the
348  * binding table.
349  */
350 static void
351 upload_wm_surfaces(struct brw_context *brw)
352 {
353    struct gl_context *ctx = &brw->intel.ctx;
354    GLuint i;
355
356    /* _NEW_BUFFERS | _NEW_COLOR */
357    /* Update surfaces for drawing buffers */
358    if (ctx->DrawBuffer->_NumColorDrawBuffers >= 1) {
359       for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
360          if (intel_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[i])) {
361             gen7_update_renderbuffer_surface(brw,
362                ctx->DrawBuffer->_ColorDrawBuffers[i], i);
363          } else {
364             gen7_update_null_renderbuffer_surface(brw, i);
365          }
366       }
367    } else {
368       gen7_update_null_renderbuffer_surface(brw, 0);
369    }
370
371    /* Update surfaces for textures */
372    for (i = 0; i < BRW_MAX_TEX_UNIT; i++) {
373       const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
374       const GLuint surf = SURF_INDEX_TEXTURE(i);
375
376       /* _NEW_TEXTURE */
377       if (texUnit->_ReallyEnabled) {
378          gen7_update_texture_surface(ctx, i);
379       } else {
380          brw->wm.surf_offset[surf] = 0;
381       }
382    }
383
384    brw->state.dirty.brw |= BRW_NEW_WM_SURFACES;
385 }
386
387 const struct brw_tracked_state gen7_wm_surfaces = {
388    .dirty = {
389       .mesa = (_NEW_COLOR |
390                _NEW_TEXTURE |
391                _NEW_BUFFERS),
392       .brw = BRW_NEW_BATCH,
393       .cache = 0
394    },
395    .prepare = prepare_wm_surfaces,
396    .emit = upload_wm_surfaces,
397 };