1 /**************************************************************************
2 *
3 * Copyright 2007 VMware, Inc.
4 * All Rights Reserved.
5 * Copyright 2009 VMware, Inc. All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sub license, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
17 * of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 *
27 **************************************************************************/
28
29 /*
30 * Authors:
31 * Keith Whitwell <[email protected]>
32 * Brian Paul
33 * Michel Dänzer
34 */
35
36 #include "main/errors.h"
37 #include "util/glheader.h"
38 #include "main/accum.h"
39 #include "main/formats.h"
40 #include "main/framebuffer.h"
41 #include "main/macros.h"
42 #include "main/glformats.h"
43 #include "program/prog_instruction.h"
44 #include "st_context.h"
45 #include "st_atom.h"
46 #include "st_cb_bitmap.h"
47 #include "st_cb_clear.h"
48 #include "st_draw.h"
49 #include "st_format.h"
50 #include "st_nir.h"
51 #include "st_program.h"
52 #include "st_util.h"
53
54 #include "pipe/p_context.h"
55 #include "pipe/p_shader_tokens.h"
56 #include "pipe/p_state.h"
57 #include "pipe/p_defines.h"
58 #include "util/format/u_format.h"
59 #include "util/u_inlines.h"
60 #include "util/u_simple_shaders.h"
61
62 #include "cso_cache/cso_context.h"
63
64
65 /**
66 * Do per-context initialization for glClear.
67 */
68 void
st_init_clear(struct st_context * st)69 st_init_clear(struct st_context *st)
70 {
71 memset(&st->clear, 0, sizeof(st->clear));
72
73 st->clear.raster.half_pixel_center = 1;
74 st->clear.raster.bottom_edge_rule = 1;
75 st->clear.raster.depth_clip_near = 1;
76 st->clear.raster.depth_clip_far = 1;
77 }
78
79
80 /**
81 * Free per-context state for glClear.
82 */
83 void
st_destroy_clear(struct st_context * st)84 st_destroy_clear(struct st_context *st)
85 {
86 if (st->clear.fs) {
87 st->pipe->delete_fs_state(st->pipe, st->clear.fs);
88 st->clear.fs = NULL;
89 }
90 if (st->clear.vs) {
91 st->pipe->delete_vs_state(st->pipe, st->clear.vs);
92 st->clear.vs = NULL;
93 }
94 if (st->clear.vs_layered) {
95 st->pipe->delete_vs_state(st->pipe, st->clear.vs_layered);
96 st->clear.vs_layered = NULL;
97 }
98 if (st->clear.gs_layered) {
99 st->pipe->delete_gs_state(st->pipe, st->clear.gs_layered);
100 st->clear.gs_layered = NULL;
101 }
102 }
103
104
105 /**
106 * Helper function to set the clear color fragment shader.
107 */
108 static void
set_clearcolor_fs(struct st_context * st,union pipe_color_union * color)109 set_clearcolor_fs(struct st_context *st, union pipe_color_union *color)
110 {
111 struct pipe_constant_buffer cb = {
112 .user_buffer = color->f,
113 .buffer_size = 4 * sizeof(float),
114 };
115 st->pipe->set_constant_buffer(st->pipe, PIPE_SHADER_FRAGMENT, 0,
116 false, &cb);
117
118 if (!st->clear.fs) {
119 st->clear.fs = st_nir_make_clearcolor_shader(st);
120 }
121
122 cso_set_fragment_shader_handle(st->cso_context, st->clear.fs);
123 }
124
125 static void *
make_nir_clear_vertex_shader(struct st_context * st,bool layered)126 make_nir_clear_vertex_shader(struct st_context *st, bool layered)
127 {
128 const char *shader_name = layered ? "layered clear VS" : "clear VS";
129 unsigned inputs[] = {
130 VERT_ATTRIB_POS,
131 SYSTEM_VALUE_INSTANCE_ID,
132 };
133 gl_varying_slot outputs[] = {
134 VARYING_SLOT_POS,
135 VARYING_SLOT_LAYER
136 };
137
138 return st_nir_make_passthrough_shader(st, shader_name, MESA_SHADER_VERTEX,
139 layered ? 2 : 1, inputs, outputs,
140 NULL, (1 << 1));
141 }
142
143
144 /**
145 * Helper function to set the vertex shader.
146 */
147 static inline void
set_vertex_shader(struct st_context * st)148 set_vertex_shader(struct st_context *st)
149 {
150 /* vertex shader - still required to provide the linkage between
151 * fragment shader input semantics and vertex_element/buffers.
152 */
153 if (!st->clear.vs)
154 st->clear.vs = make_nir_clear_vertex_shader(st, false);
155
156 cso_set_vertex_shader_handle(st->cso_context, st->clear.vs);
157 cso_set_geometry_shader_handle(st->cso_context, NULL);
158 }
159
160
161 static void
set_vertex_shader_layered(struct st_context * st)162 set_vertex_shader_layered(struct st_context *st)
163 {
164 struct pipe_context *pipe = st->pipe;
165
166 if (!st->screen->get_param(st->screen, PIPE_CAP_VS_INSTANCEID)) {
167 assert(!"Got layered clear, but VS instancing is unsupported");
168 set_vertex_shader(st);
169 return;
170 }
171
172 if (!st->clear.vs_layered) {
173 bool vs_layer =
174 st->screen->get_param(st->screen, PIPE_CAP_VS_LAYER_VIEWPORT);
175 if (vs_layer) {
176 st->clear.vs_layered = make_nir_clear_vertex_shader(st, true);
177 } else {
178 st->clear.vs_layered = util_make_layered_clear_helper_vertex_shader(pipe);
179 st->clear.gs_layered = util_make_layered_clear_geometry_shader(pipe);
180 }
181 }
182
183 cso_set_vertex_shader_handle(st->cso_context, st->clear.vs_layered);
184 cso_set_geometry_shader_handle(st->cso_context, st->clear.gs_layered);
185 }
186
187
188 /**
189 * Do glClear by drawing a quadrilateral.
190 * The vertices of the quad will be computed from the
191 * ctx->DrawBuffer->_X/Ymin/max fields.
192 */
193 static void
clear_with_quad(struct gl_context * ctx,unsigned clear_buffers)194 clear_with_quad(struct gl_context *ctx, unsigned clear_buffers)
195 {
196 struct st_context *st = st_context(ctx);
197 struct cso_context *cso = st->cso_context;
198 const struct gl_framebuffer *fb = ctx->DrawBuffer;
199 const GLfloat fb_width = (GLfloat) fb->Width;
200 const GLfloat fb_height = (GLfloat) fb->Height;
201
202 _mesa_update_draw_buffer_bounds(ctx, ctx->DrawBuffer);
203
204 const GLfloat x0 = (GLfloat) ctx->DrawBuffer->_Xmin / fb_width * 2.0f - 1.0f;
205 const GLfloat x1 = (GLfloat) ctx->DrawBuffer->_Xmax / fb_width * 2.0f - 1.0f;
206 const GLfloat y0 = (GLfloat) ctx->DrawBuffer->_Ymin / fb_height * 2.0f - 1.0f;
207 const GLfloat y1 = (GLfloat) ctx->DrawBuffer->_Ymax / fb_height * 2.0f - 1.0f;
208 unsigned num_layers = st->state.fb_num_layers;
209
210 /*
211 printf("%s %s%s%s %f,%f %f,%f\n", __func__,
212 color ? "color, " : "",
213 depth ? "depth, " : "",
214 stencil ? "stencil" : "",
215 x0, y0,
216 x1, y1);
217 */
218
219 cso_save_state(cso, (CSO_BIT_BLEND |
220 CSO_BIT_STENCIL_REF |
221 CSO_BIT_DEPTH_STENCIL_ALPHA |
222 CSO_BIT_RASTERIZER |
223 CSO_BIT_SAMPLE_MASK |
224 CSO_BIT_MIN_SAMPLES |
225 CSO_BIT_VIEWPORT |
226 CSO_BIT_STREAM_OUTPUTS |
227 CSO_BIT_VERTEX_ELEMENTS |
228 (st->active_queries ? CSO_BIT_PAUSE_QUERIES : 0) |
229 CSO_BITS_ALL_SHADERS));
230
231 /* blend state: RGBA masking */
232 {
233 struct pipe_blend_state blend;
234 memset(&blend, 0, sizeof(blend));
235 if (clear_buffers & PIPE_CLEAR_COLOR) {
236 int num_buffers = ctx->Extensions.EXT_draw_buffers2 ?
237 ctx->DrawBuffer->_NumColorDrawBuffers : 1;
238 int i;
239
240 blend.independent_blend_enable = num_buffers > 1;
241 blend.max_rt = num_buffers - 1;
242
243 for (i = 0; i < num_buffers; i++) {
244 if (!(clear_buffers & (PIPE_CLEAR_COLOR0 << i)))
245 continue;
246
247 blend.rt[i].colormask = GET_COLORMASK(ctx->Color.ColorMask, i);
248 }
249
250 if (ctx->Color.DitherFlag)
251 blend.dither = 1;
252 }
253 cso_set_blend(cso, &blend);
254 }
255
256 /* depth_stencil state: always pass/set to ref value */
257 {
258 struct pipe_depth_stencil_alpha_state depth_stencil;
259 memset(&depth_stencil, 0, sizeof(depth_stencil));
260 if (clear_buffers & PIPE_CLEAR_DEPTH) {
261 depth_stencil.depth_enabled = 1;
262 depth_stencil.depth_writemask = 1;
263 depth_stencil.depth_func = PIPE_FUNC_ALWAYS;
264 }
265
266 if (clear_buffers & PIPE_CLEAR_STENCIL) {
267 struct pipe_stencil_ref stencil_ref;
268 memset(&stencil_ref, 0, sizeof(stencil_ref));
269 depth_stencil.stencil[0].enabled = 1;
270 depth_stencil.stencil[0].func = PIPE_FUNC_ALWAYS;
271 depth_stencil.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
272 depth_stencil.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
273 depth_stencil.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
274 depth_stencil.stencil[0].valuemask = 0xff;
275 depth_stencil.stencil[0].writemask = ctx->Stencil.WriteMask[0] & 0xff;
276 stencil_ref.ref_value[0] = ctx->Stencil.Clear;
277 cso_set_stencil_ref(cso, stencil_ref);
278 }
279
280 cso_set_depth_stencil_alpha(cso, &depth_stencil);
281 }
282
283 st->util_velems.count = 1;
284 cso_set_vertex_elements(cso, &st->util_velems);
285
286 cso_set_stream_outputs(cso, 0, NULL, NULL);
287 cso_set_sample_mask(cso, ~0);
288 cso_set_min_samples(cso, 1);
289 st->clear.raster.multisample = st->state.fb_num_samples > 1;
290 cso_set_rasterizer(cso, &st->clear.raster);
291
292 /* viewport state: viewport matching window dims */
293 cso_set_viewport_dims(st->cso_context, fb_width, fb_height,
294 _mesa_fb_orientation(fb) == Y_0_TOP);
295
296 /* Set constant buffer */
297 set_clearcolor_fs(st, (union pipe_color_union*)&ctx->Color.ClearColor);
298 cso_set_tessctrl_shader_handle(cso, NULL);
299 cso_set_tesseval_shader_handle(cso, NULL);
300
301 if (num_layers > 1)
302 set_vertex_shader_layered(st);
303 else
304 set_vertex_shader(st);
305
306 /* draw quad matching scissor rect.
307 *
308 * Note: if we're only clearing depth/stencil we still setup vertices
309 * with color, but they'll be ignored.
310 *
311 * We can't translate the clear color to the colorbuffer format,
312 * because different colorbuffers may have different formats.
313 */
314 if (!st_draw_quad(st, x0, y0, x1, y1,
315 ctx->Depth.Clear * 2.0f - 1.0f,
316 0.0f, 0.0f, 0.0f, 0.0f,
317 (const float *) &ctx->Color.ClearColor.f,
318 num_layers)) {
319 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear");
320 }
321
322 /* Restore pipe state */
323 cso_restore_state(cso, 0);
324 ctx->Array.NewVertexElements = true;
325 ctx->NewDriverState |= ST_NEW_VERTEX_ARRAYS |
326 ST_NEW_FS_CONSTANTS;
327 }
328
329
330 /**
331 * Return if the scissor must be enabled during the clear.
332 */
333 static inline GLboolean
is_scissor_enabled(struct gl_context * ctx,struct gl_renderbuffer * rb)334 is_scissor_enabled(struct gl_context *ctx, struct gl_renderbuffer *rb)
335 {
336 const struct gl_scissor_rect *scissor = &ctx->Scissor.ScissorArray[0];
337
338 return (ctx->Scissor.EnableFlags & 1) &&
339 (scissor->X > 0 ||
340 scissor->Y > 0 ||
341 scissor->X + scissor->Width < (int)rb->Width ||
342 scissor->Y + scissor->Height < (int)rb->Height);
343 }
344
345 /**
346 * Return if window rectangles must be enabled during the clear.
347 */
348 static inline bool
is_window_rectangle_enabled(struct gl_context * ctx)349 is_window_rectangle_enabled(struct gl_context *ctx)
350 {
351 if (ctx->DrawBuffer == ctx->WinSysDrawBuffer)
352 return false;
353 return ctx->Scissor.NumWindowRects > 0 ||
354 ctx->Scissor.WindowRectMode == GL_INCLUSIVE_EXT;
355 }
356
357
358 /**
359 * Return if all of the stencil bits are masked.
360 */
361 static inline GLboolean
is_stencil_disabled(struct gl_context * ctx,struct gl_renderbuffer * rb)362 is_stencil_disabled(struct gl_context *ctx, struct gl_renderbuffer *rb)
363 {
364 const GLuint stencilMax = 0xff;
365
366 assert(_mesa_get_format_bits(rb->Format, GL_STENCIL_BITS) > 0);
367 return (ctx->Stencil.WriteMask[0] & stencilMax) == 0;
368 }
369
370
371 /**
372 * Return if any of the stencil bits are masked.
373 */
374 static inline GLboolean
is_stencil_masked(struct gl_context * ctx,struct gl_renderbuffer * rb)375 is_stencil_masked(struct gl_context *ctx, struct gl_renderbuffer *rb)
376 {
377 const GLuint stencilMax = 0xff;
378
379 assert(_mesa_get_format_bits(rb->Format, GL_STENCIL_BITS) > 0);
380 return (ctx->Stencil.WriteMask[0] & stencilMax) != stencilMax;
381 }
382
383 void
st_Clear(struct gl_context * ctx,GLbitfield mask)384 st_Clear(struct gl_context *ctx, GLbitfield mask)
385 {
386 struct st_context *st = st_context(ctx);
387 struct gl_renderbuffer *depthRb
388 = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
389 struct gl_renderbuffer *stencilRb
390 = ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
391 GLbitfield quad_buffers = 0x0;
392 GLbitfield clear_buffers = 0x0;
393 bool have_scissor_buffers = false;
394 GLuint i;
395
396 st_flush_bitmap_cache(st);
397 st_invalidate_readpix_cache(st);
398
399 /* This makes sure the pipe has the latest scissor, etc values */
400 st_validate_state(st, ST_PIPELINE_CLEAR_STATE_MASK);
401
402 if (mask & BUFFER_BITS_COLOR) {
403 for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
404 gl_buffer_index b = ctx->DrawBuffer->_ColorDrawBufferIndexes[i];
405
406 if (b != BUFFER_NONE && mask & (1 << b)) {
407 struct gl_renderbuffer *rb
408 = ctx->DrawBuffer->Attachment[b].Renderbuffer;
409 int colormask_index = ctx->Extensions.EXT_draw_buffers2 ? i : 0;
410
411 if (!rb || !rb->surface)
412 continue;
413
414 unsigned colormask =
415 GET_COLORMASK(ctx->Color.ColorMask, colormask_index);
416
417 if (!colormask)
418 continue;
419
420 unsigned surf_colormask =
421 util_format_colormask(util_format_description(rb->surface->format));
422
423 bool scissor = is_scissor_enabled(ctx, rb);
424 if ((scissor && !st->can_scissor_clear) ||
425 is_window_rectangle_enabled(ctx) ||
426 ((colormask & surf_colormask) != surf_colormask))
427 quad_buffers |= PIPE_CLEAR_COLOR0 << i;
428 else
429 clear_buffers |= PIPE_CLEAR_COLOR0 << i;
430 have_scissor_buffers |= scissor && st->can_scissor_clear;
431 }
432 }
433 }
434
435 if (mask & BUFFER_BIT_DEPTH) {
436 if (depthRb->surface && ctx->Depth.Mask) {
437 bool scissor = is_scissor_enabled(ctx, depthRb);
438 if ((scissor && !st->can_scissor_clear) ||
439 is_window_rectangle_enabled(ctx))
440 quad_buffers |= PIPE_CLEAR_DEPTH;
441 else
442 clear_buffers |= PIPE_CLEAR_DEPTH;
443 have_scissor_buffers |= scissor && st->can_scissor_clear;
444 }
445 }
446 if (mask & BUFFER_BIT_STENCIL) {
447 if (stencilRb->surface && !is_stencil_disabled(ctx, stencilRb)) {
448 bool scissor = is_scissor_enabled(ctx, stencilRb);
449 if ((scissor && !st->can_scissor_clear) ||
450 is_window_rectangle_enabled(ctx) ||
451 is_stencil_masked(ctx, stencilRb))
452 quad_buffers |= PIPE_CLEAR_STENCIL;
453 else
454 clear_buffers |= PIPE_CLEAR_STENCIL;
455 have_scissor_buffers |= scissor && st->can_scissor_clear;
456 }
457 }
458
459 /* Always clear depth and stencil together.
460 * This can only happen when the stencil writemask is not a full mask.
461 */
462 if (quad_buffers & PIPE_CLEAR_DEPTHSTENCIL &&
463 clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) {
464 quad_buffers |= clear_buffers & PIPE_CLEAR_DEPTHSTENCIL;
465 clear_buffers &= ~PIPE_CLEAR_DEPTHSTENCIL;
466 }
467
468 /* Only use quad-based clearing for the renderbuffers which cannot
469 * use pipe->clear. We want to always use pipe->clear for the other
470 * renderbuffers, because it's likely to be faster.
471 */
472 if (clear_buffers) {
473 const struct gl_scissor_rect *scissor = &ctx->Scissor.ScissorArray[0];
474 struct pipe_scissor_state scissor_state = {
475 .minx = MAX2(scissor->X, 0),
476 .miny = MAX2(scissor->Y, 0),
477 .maxx = MAX2(scissor->X + scissor->Width, 0),
478 .maxy = MAX2(scissor->Y + scissor->Height, 0),
479
480 };
481
482 /* Now invert Y if needed.
483 * Gallium drivers use the convention Y=0=top for surfaces.
484 */
485 if (st->state.fb_orientation == Y_0_TOP) {
486 const struct gl_framebuffer *fb = ctx->DrawBuffer;
487 /* use intermediate variables to avoid uint underflow */
488 GLint miny, maxy;
489 miny = fb->Height - scissor_state.maxy;
490 maxy = fb->Height - scissor_state.miny;
491 scissor_state.miny = MAX2(miny, 0);
492 scissor_state.maxy = MAX2(maxy, 0);
493 }
494 if (have_scissor_buffers) {
495 const struct gl_framebuffer *fb = ctx->DrawBuffer;
496 scissor_state.maxx = MIN2(scissor_state.maxx, fb->Width);
497 scissor_state.maxy = MIN2(scissor_state.maxy, fb->Height);
498 if (scissor_state.minx >= scissor_state.maxx ||
499 scissor_state.miny >= scissor_state.maxy)
500 return;
501 }
502 /* We can't translate the clear color to the colorbuffer format,
503 * because different colorbuffers may have different formats.
504 */
505 st->pipe->clear(st->pipe, clear_buffers, have_scissor_buffers ? &scissor_state : NULL,
506 (union pipe_color_union*)&ctx->Color.ClearColor,
507 ctx->Depth.Clear, ctx->Stencil.Clear);
508 }
509 if (quad_buffers) {
510 clear_with_quad(ctx, quad_buffers);
511 }
512 if (mask & BUFFER_BIT_ACCUM)
513 _mesa_clear_accum_buffer(ctx);
514 }
515
516