mesa: add/update comments in _mesa_copy_buffer_subdata()
[mesa.git] / src / mesa / drivers / dri / i965 / gen6_hiz.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
24 #include "gen6_hiz.h"
25
26 #include <assert.h>
27
28 #include "mesa/drivers/common/meta.h"
29
30 #include "mesa/main/arrayobj.h"
31 #include "mesa/main/bufferobj.h"
32 #include "mesa/main/depth.h"
33 #include "mesa/main/enable.h"
34 #include "mesa/main/fbobject.h"
35 #include "mesa/main/framebuffer.h"
36 #include "mesa/main/get.h"
37 #include "mesa/main/renderbuffer.h"
38 #include "mesa/main/shaderapi.h"
39 #include "mesa/main/varray.h"
40
41 #include "intel_fbo.h"
42 #include "intel_mipmap_tree.h"
43 #include "intel_regions.h"
44 #include "intel_tex.h"
45
46 #include "brw_context.h"
47 #include "brw_defines.h"
48
49 static const uint32_t gen6_hiz_meta_save =
50
51 /* Disable alpha, depth, and stencil test.
52 *
53 * See the following sections of the Sandy Bridge PRM, Volume 1, Part2:
54 * - 7.5.3.1 Depth Buffer Clear
55 * - 7.5.3.2 Depth Buffer Resolve
56 * - 7.5.3.3 Hierarchical Depth Buffer Resolve
57 */
58 MESA_META_ALPHA_TEST |
59 MESA_META_DEPTH_TEST |
60 MESA_META_STENCIL_TEST |
61
62 /* Disable viewport mapping.
63 *
64 * From page 11 of the Sandy Bridge PRM, Volume 2, Part 1, Section 1.3
65 * 3D Primitives Overview:
66 * RECTLIST:
67 * Viewport Mapping must be DISABLED (as is typical with the use of
68 * screen- space coordinates).
69 *
70 * We must also manually disable 3DSTATE_SF.Viewport_Transform_Enable.
71 */
72 MESA_META_VIEWPORT |
73
74 /* Disable clipping.
75 *
76 * From page 11 of the Sandy Bridge PRM, Volume 2, Part 1, Section 1.3
77 * 3D Primitives Overview:
78 * Either the CLIP unit should be DISABLED, or the CLIP unit’s Clip
79 * Mode should be set to a value other than CLIPMODE_NORMAL.
80 */
81 MESA_META_CLIP |
82
83 /* Render a solid rectangle (set 3DSTATE_SF.FrontFace_Fill_Mode).
84 *
85 * From page 249 of the Sandy Bridge PRM, Volume 2, Part 1, Section
86 * 6.4.1.1 3DSTATE_SF, FrontFace_Fill_Mode:
87 * SOLID: Any triangle or rectangle object found to be front-facing
88 * is rendered as a solid object. This setting is required when
89 * (rendering rectangle (RECTLIST) objects.
90 * Also see field BackFace_Fill_Mode.
91 *
92 * Note: MESA_META_RASTERIZAION also disables culling, but that is
93 * irrelevant. See 3DSTATE_SF.Cull_Mode.
94 */
95 MESA_META_RASTERIZATION |
96
97 /* Each HiZ operation uses a vertex shader and VAO. */
98 MESA_META_SHADER |
99 MESA_META_VERTEX |
100
101 /* Disable scissoring.
102 *
103 * Scissoring is disabled for resolves because a resolve operation
104 * should resolve the entire buffer. Scissoring is disabled for depth
105 * clears because, if we are performing a partial depth clear, then we
106 * specify the clear region with the RECTLIST vertices.
107 */
108 MESA_META_SCISSOR |
109
110 MESA_META_SELECT_FEEDBACK;
111
112 /**
113 * Initialize static data needed for HiZ operations.
114 */
115 static void
116 gen6_hiz_init(struct brw_context *brw)
117 {
118 struct gl_context *ctx = &brw->intel.ctx;
119 struct brw_hiz_state *hiz = &brw->hiz;
120
121 if (hiz->fbo != 0)
122 return;
123
124 /* Create depthbuffer.
125 *
126 * Until glRenderbufferStorage is called, the renderbuffer hash table
127 * maps the renderbuffer name to a dummy renderbuffer. We need the
128 * renderbuffer to be registered in the hash table so that framebuffer
129 * validation succeeds, so we hackishly allocate storage then immediately
130 * discard it.
131 */
132 GLuint depth_rb_name;
133 _mesa_GenRenderbuffersEXT(1, &depth_rb_name);
134 _mesa_BindRenderbufferEXT(GL_RENDERBUFFER, depth_rb_name);
135 _mesa_RenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, 32, 32);
136 _mesa_reference_renderbuffer(&hiz->depth_rb,
137 _mesa_lookup_renderbuffer(ctx, depth_rb_name));
138 intel_miptree_release(&((struct intel_renderbuffer*) hiz->depth_rb)->mt);
139
140 /* Setup FBO. */
141 _mesa_GenFramebuffersEXT(1, &hiz->fbo);
142 _mesa_BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, hiz->fbo);
143 _mesa_FramebufferRenderbufferEXT(GL_DRAW_FRAMEBUFFER,
144 GL_DEPTH_ATTACHMENT,
145 GL_RENDERBUFFER,
146 hiz->depth_rb->Name);
147
148 /* Compile vertex shader. */
149 const char *vs_source =
150 "attribute vec4 position;\n"
151 "void main()\n"
152 "{\n"
153 " gl_Position = position;\n"
154 "}\n";
155 GLuint vs = _mesa_CreateShaderObjectARB(GL_VERTEX_SHADER);
156 _mesa_ShaderSourceARB(vs, 1, &vs_source, NULL);
157 _mesa_CompileShaderARB(vs);
158
159 /* Compile fragment shader. */
160 const char *fs_source = "void main() {}";
161 GLuint fs = _mesa_CreateShaderObjectARB(GL_FRAGMENT_SHADER);
162 _mesa_ShaderSourceARB(fs, 1, &fs_source, NULL);
163 _mesa_CompileShaderARB(fs);
164
165 /* Link and use program. */
166 hiz->shader.program = _mesa_CreateProgramObjectARB();
167 _mesa_AttachShader(hiz->shader.program, vs);
168 _mesa_AttachShader(hiz->shader.program, fs);
169 _mesa_LinkProgramARB(hiz->shader.program);
170 _mesa_UseProgramObjectARB(hiz->shader.program);
171
172 /* Create and bind VAO. */
173 _mesa_GenVertexArrays(1, &hiz->vao);
174 _mesa_BindVertexArray(hiz->vao);
175
176 /* Setup VBO for 'position'. */
177 hiz->shader.position_location =
178 _mesa_GetAttribLocationARB(hiz->shader.program, "position");
179 _mesa_GenBuffersARB(1, &hiz->shader.position_vbo);
180 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, hiz->shader.position_vbo);
181 _mesa_VertexAttribPointerARB(hiz->shader.position_location,
182 2, /*components*/
183 GL_FLOAT,
184 GL_FALSE, /*normalized?*/
185 0, /*stride*/
186 NULL);
187 _mesa_EnableVertexAttribArrayARB(hiz->shader.position_location);
188
189 /* Cleanup. */
190 _mesa_DeleteShader(vs);
191 _mesa_DeleteShader(fs);
192 }
193
194 /**
195 * Wrap \c brw->hiz.depth_rb around a miptree.
196 *
197 * \see gen6_hiz_teardown_depth_buffer()
198 */
199 static void
200 gen6_hiz_setup_depth_buffer(struct brw_context *brw,
201 struct intel_mipmap_tree *mt,
202 unsigned int level,
203 unsigned int layer)
204 {
205 struct gl_renderbuffer *rb = brw->hiz.depth_rb;
206 struct intel_renderbuffer *irb = intel_renderbuffer(rb);
207
208 rb->Format = mt->format;
209 rb->_BaseFormat = _mesa_get_format_base_format(rb->Format);
210 rb->DataType = intel_mesa_format_to_rb_datatype(rb->Format);
211 rb->InternalFormat = rb->_BaseFormat;
212 rb->Width = mt->level[level].width;
213 rb->Height = mt->level[level].height;
214
215 irb->mt_level = level;
216 irb->mt_layer = layer;
217
218 intel_miptree_reference(&irb->mt, mt);
219 intel_renderbuffer_set_draw_offset(irb);
220 }
221
222 /**
223 * Release the region from \c brw->hiz.depth_rb.
224 *
225 * \see gen6_hiz_setup_depth_buffer()
226 */
227 static void
228 gen6_hiz_teardown_depth_buffer(struct gl_renderbuffer *rb)
229 {
230 struct intel_renderbuffer *irb = intel_renderbuffer(rb);
231 intel_miptree_release(&irb->mt);
232 }
233
234 static void
235 gen6_resolve_slice(struct intel_context *intel,
236 struct intel_mipmap_tree *mt,
237 unsigned int level,
238 unsigned int layer,
239 enum brw_hiz_op op)
240 {
241 struct gl_context *ctx = &intel->ctx;
242 struct brw_context *brw = brw_context(ctx);
243 struct brw_hiz_state *hiz = &brw->hiz;
244
245 /* Do not recurse. */
246 assert(!brw->hiz.op);
247
248 assert(mt->hiz_mt != NULL);
249 assert(level >= mt->first_level);
250 assert(level <= mt->last_level);
251 assert(layer < mt->level[level].depth);
252
253 /* Save state. */
254 GLint save_drawbuffer;
255 GLint save_renderbuffer;
256 _mesa_meta_begin(ctx, gen6_hiz_meta_save);
257 _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &save_drawbuffer);
258 _mesa_GetIntegerv(GL_RENDERBUFFER_BINDING, &save_renderbuffer);
259
260 /* Initialize context data for HiZ operations. */
261 gen6_hiz_init(brw);
262
263 /* Set depth state. */
264 if (!ctx->Depth.Mask) {
265 /* This sets 3DSTATE_WM.Depth_Buffer_Write_Enable. */
266 _mesa_DepthMask(GL_TRUE);
267 }
268 if (op == BRW_HIZ_OP_DEPTH_RESOLVE) {
269 _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_TRUE);
270 _mesa_DepthFunc(GL_NEVER);
271 }
272
273 /* Setup FBO. */
274 gen6_hiz_setup_depth_buffer(brw, mt, level, layer);
275 _mesa_BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, hiz->fbo);
276
277
278 /* A rectangle primitive (3DPRIM_RECTLIST) consists of only three vertices.
279 * The vertices reside in screen space with DirectX coordinates (this is,
280 * (0, 0) is the upper left corner).
281 *
282 * v2 ------ implied
283 * | |
284 * | |
285 * v0 ----- v1
286 */
287 const int width = hiz->depth_rb->Width;
288 const int height = hiz->depth_rb->Height;
289 const GLfloat positions[] = {
290 0, height,
291 width, height,
292 0, 0,
293 };
294
295 /* Setup program and vertex attributes. */
296 _mesa_UseProgramObjectARB(hiz->shader.program);
297 _mesa_BindVertexArray(hiz->vao);
298 _mesa_BindBufferARB(GL_ARRAY_BUFFER, hiz->shader.position_vbo);
299 _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(positions), positions,
300 GL_DYNAMIC_DRAW_ARB);
301
302 /* Execute the HiZ operation. */
303 brw->hiz.op = op;
304 brw->state.dirty.brw |= BRW_NEW_HIZ;
305 _mesa_DrawArrays(GL_TRIANGLES, 0, 3);
306 brw->state.dirty.brw |= BRW_NEW_HIZ;
307 brw->hiz.op = BRW_HIZ_OP_NONE;
308
309 /* Restore state.
310 *
311 * The order in which state is restored is significant. The draw buffer
312 * used for the HiZ op has no stencil buffer, and glStencilFunc() clamps
313 * the stencil reference value to the range allowed by the draw buffer's
314 * number of stencil bits. So, the draw buffer binding must be restored
315 * before the stencil state, or else the stencil ref will be clamped to 0.
316 */
317 gen6_hiz_teardown_depth_buffer(hiz->depth_rb);
318 _mesa_BindRenderbufferEXT(GL_RENDERBUFFER, save_renderbuffer);
319 _mesa_BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, save_drawbuffer);
320 _mesa_meta_end(ctx);
321 }
322
323 void
324 gen6_resolve_hiz_slice(struct intel_context *intel,
325 struct intel_mipmap_tree *mt,
326 uint32_t level,
327 uint32_t layer)
328 {
329 gen6_resolve_slice(intel, mt, level, layer, BRW_HIZ_OP_HIZ_RESOLVE);
330 }
331
332
333 void
334 gen6_resolve_depth_slice(struct intel_context *intel,
335 struct intel_mipmap_tree *mt,
336 uint32_t level,
337 uint32_t layer)
338 {
339 gen6_resolve_slice(intel, mt, level, layer, BRW_HIZ_OP_DEPTH_RESOLVE);
340 }