• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <keithw@vmware.com>
32   *   Brian Paul
33   *   Michel Dänzer
34   */
35 
36 #include "main/errors.h"
37 #include "main/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_cb_fbo.h"
49 #include "st_draw.h"
50 #include "st_format.h"
51 #include "st_nir.h"
52 #include "st_program.h"
53 #include "st_util.h"
54 
55 #include "pipe/p_context.h"
56 #include "pipe/p_shader_tokens.h"
57 #include "pipe/p_state.h"
58 #include "pipe/p_defines.h"
59 #include "util/format/u_format.h"
60 #include "util/u_inlines.h"
61 #include "util/u_simple_shaders.h"
62 
63 #include "cso_cache/cso_context.h"
64 
65 
66 /**
67  * Do per-context initialization for glClear.
68  */
69 void
st_init_clear(struct st_context * st)70 st_init_clear(struct st_context *st)
71 {
72    memset(&st->clear, 0, sizeof(st->clear));
73 
74    st->clear.raster.half_pixel_center = 1;
75    st->clear.raster.bottom_edge_rule = 1;
76    st->clear.raster.depth_clip_near = 1;
77    st->clear.raster.depth_clip_far = 1;
78 }
79 
80 
81 /**
82  * Free per-context state for glClear.
83  */
84 void
st_destroy_clear(struct st_context * st)85 st_destroy_clear(struct st_context *st)
86 {
87    if (st->clear.fs) {
88       st->pipe->delete_fs_state(st->pipe, st->clear.fs);
89       st->clear.fs = NULL;
90    }
91    if (st->clear.vs) {
92       st->pipe->delete_vs_state(st->pipe, st->clear.vs);
93       st->clear.vs = NULL;
94    }
95    if (st->clear.vs_layered) {
96       st->pipe->delete_vs_state(st->pipe, st->clear.vs_layered);
97       st->clear.vs_layered = NULL;
98    }
99    if (st->clear.gs_layered) {
100       st->pipe->delete_gs_state(st->pipe, st->clear.gs_layered);
101       st->clear.gs_layered = NULL;
102    }
103 }
104 
105 
106 /**
107  * Helper function to set the fragment shaders.
108  */
109 static inline void
set_fragment_shader(struct st_context * st)110 set_fragment_shader(struct st_context *st)
111 {
112    struct pipe_screen *pscreen = st->screen;
113    bool use_nir = PIPE_SHADER_IR_NIR ==
114       pscreen->get_shader_param(pscreen, PIPE_SHADER_VERTEX,
115                                 PIPE_SHADER_CAP_PREFERRED_IR);
116 
117    if (!st->clear.fs) {
118       if (use_nir) {
119          unsigned inputs[] = { VARYING_SLOT_VAR0 };
120          unsigned outputs[] = { FRAG_RESULT_COLOR };
121          unsigned interpolation[] = { INTERP_MODE_FLAT };
122          st->clear.fs = st_nir_make_passthrough_shader(st, "clear FS",
123                                                        MESA_SHADER_FRAGMENT,
124                                                        1, inputs, outputs,
125                                                        interpolation, 0);
126       } else {
127          st->clear.fs =
128             util_make_fragment_passthrough_shader(st->pipe,
129                                                   TGSI_SEMANTIC_GENERIC,
130                                                   TGSI_INTERPOLATE_CONSTANT,
131                                                   TRUE);
132       }
133    }
134 
135    cso_set_fragment_shader_handle(st->cso_context, st->clear.fs);
136 }
137 
138 
139 static void *
make_nir_clear_vertex_shader(struct st_context * st,bool layered)140 make_nir_clear_vertex_shader(struct st_context *st, bool layered)
141 {
142    const char *shader_name = layered ? "layered clear VS" : "clear VS";
143    unsigned inputs[] = {
144       VERT_ATTRIB_POS,
145       VERT_ATTRIB_GENERIC0,
146       SYSTEM_VALUE_INSTANCE_ID,
147    };
148    unsigned outputs[] = {
149       VARYING_SLOT_POS,
150       VARYING_SLOT_VAR0,
151       VARYING_SLOT_LAYER
152    };
153 
154    return st_nir_make_passthrough_shader(st, shader_name, MESA_SHADER_VERTEX,
155                                          layered ? 3 : 2, inputs, outputs,
156                                          NULL, (1 << 2));
157 }
158 
159 
160 /**
161  * Helper function to set the vertex shader.
162  */
163 static inline void
set_vertex_shader(struct st_context * st)164 set_vertex_shader(struct st_context *st)
165 {
166    struct pipe_screen *pscreen = st->screen;
167    bool use_nir = PIPE_SHADER_IR_NIR ==
168       pscreen->get_shader_param(pscreen, PIPE_SHADER_VERTEX,
169                                 PIPE_SHADER_CAP_PREFERRED_IR);
170 
171    /* vertex shader - still required to provide the linkage between
172     * fragment shader input semantics and vertex_element/buffers.
173     */
174    if (!st->clear.vs)
175    {
176       if (use_nir) {
177          st->clear.vs = make_nir_clear_vertex_shader(st, false);
178       } else {
179          const enum tgsi_semantic semantic_names[] = {
180             TGSI_SEMANTIC_POSITION,
181             TGSI_SEMANTIC_GENERIC
182          };
183          const uint semantic_indexes[] = { 0, 0 };
184          st->clear.vs = util_make_vertex_passthrough_shader(st->pipe, 2,
185                                                             semantic_names,
186                                                             semantic_indexes,
187                                                             FALSE);
188       }
189    }
190 
191    cso_set_vertex_shader_handle(st->cso_context, st->clear.vs);
192    cso_set_geometry_shader_handle(st->cso_context, NULL);
193 }
194 
195 
196 static void
set_vertex_shader_layered(struct st_context * st)197 set_vertex_shader_layered(struct st_context *st)
198 {
199    struct pipe_context *pipe = st->pipe;
200    struct pipe_screen *pscreen = st->screen;
201    bool use_nir = PIPE_SHADER_IR_NIR ==
202       pscreen->get_shader_param(pscreen, PIPE_SHADER_VERTEX,
203                                 PIPE_SHADER_CAP_PREFERRED_IR);
204 
205    if (!st->screen->get_param(st->screen, PIPE_CAP_TGSI_INSTANCEID)) {
206       assert(!"Got layered clear, but VS instancing is unsupported");
207       set_vertex_shader(st);
208       return;
209    }
210 
211    if (!st->clear.vs_layered) {
212       bool vs_layer =
213          st->screen->get_param(st->screen, PIPE_CAP_TGSI_VS_LAYER_VIEWPORT);
214       if (vs_layer) {
215          st->clear.vs_layered =
216             use_nir ? make_nir_clear_vertex_shader(st, true)
217                     : util_make_layered_clear_vertex_shader(pipe);
218       } else {
219          st->clear.vs_layered = util_make_layered_clear_helper_vertex_shader(pipe);
220          st->clear.gs_layered = util_make_layered_clear_geometry_shader(pipe);
221       }
222    }
223 
224    cso_set_vertex_shader_handle(st->cso_context, st->clear.vs_layered);
225    cso_set_geometry_shader_handle(st->cso_context, st->clear.gs_layered);
226 }
227 
228 
229 /**
230  * Do glClear by drawing a quadrilateral.
231  * The vertices of the quad will be computed from the
232  * ctx->DrawBuffer->_X/Ymin/max fields.
233  */
234 static void
clear_with_quad(struct gl_context * ctx,unsigned clear_buffers)235 clear_with_quad(struct gl_context *ctx, unsigned clear_buffers)
236 {
237    struct st_context *st = st_context(ctx);
238    struct cso_context *cso = st->cso_context;
239    const struct gl_framebuffer *fb = ctx->DrawBuffer;
240    const GLfloat fb_width = (GLfloat) fb->Width;
241    const GLfloat fb_height = (GLfloat) fb->Height;
242 
243    _mesa_update_draw_buffer_bounds(ctx, ctx->DrawBuffer);
244 
245    const GLfloat x0 = (GLfloat) ctx->DrawBuffer->_Xmin / fb_width * 2.0f - 1.0f;
246    const GLfloat x1 = (GLfloat) ctx->DrawBuffer->_Xmax / fb_width * 2.0f - 1.0f;
247    const GLfloat y0 = (GLfloat) ctx->DrawBuffer->_Ymin / fb_height * 2.0f - 1.0f;
248    const GLfloat y1 = (GLfloat) ctx->DrawBuffer->_Ymax / fb_height * 2.0f - 1.0f;
249    unsigned num_layers = st->state.fb_num_layers;
250 
251    /*
252    printf("%s %s%s%s %f,%f %f,%f\n", __func__,
253 	  color ? "color, " : "",
254 	  depth ? "depth, " : "",
255 	  stencil ? "stencil" : "",
256 	  x0, y0,
257 	  x1, y1);
258    */
259 
260    cso_save_state(cso, (CSO_BIT_BLEND |
261                         CSO_BIT_STENCIL_REF |
262                         CSO_BIT_DEPTH_STENCIL_ALPHA |
263                         CSO_BIT_RASTERIZER |
264                         CSO_BIT_SAMPLE_MASK |
265                         CSO_BIT_MIN_SAMPLES |
266                         CSO_BIT_VIEWPORT |
267                         CSO_BIT_STREAM_OUTPUTS |
268                         CSO_BIT_VERTEX_ELEMENTS |
269                         (st->active_queries ? CSO_BIT_PAUSE_QUERIES : 0) |
270                         CSO_BITS_ALL_SHADERS));
271 
272    /* blend state: RGBA masking */
273    {
274       struct pipe_blend_state blend;
275       memset(&blend, 0, sizeof(blend));
276       if (clear_buffers & PIPE_CLEAR_COLOR) {
277          int num_buffers = ctx->Extensions.EXT_draw_buffers2 ?
278                            ctx->DrawBuffer->_NumColorDrawBuffers : 1;
279          int i;
280 
281          blend.independent_blend_enable = num_buffers > 1;
282          blend.max_rt = num_buffers - 1;
283 
284          for (i = 0; i < num_buffers; i++) {
285             if (!(clear_buffers & (PIPE_CLEAR_COLOR0 << i)))
286                continue;
287 
288             blend.rt[i].colormask = GET_COLORMASK(ctx->Color.ColorMask, i);
289          }
290 
291          if (ctx->Color.DitherFlag)
292             blend.dither = 1;
293       }
294       cso_set_blend(cso, &blend);
295    }
296 
297    /* depth_stencil state: always pass/set to ref value */
298    {
299       struct pipe_depth_stencil_alpha_state depth_stencil;
300       memset(&depth_stencil, 0, sizeof(depth_stencil));
301       if (clear_buffers & PIPE_CLEAR_DEPTH) {
302          depth_stencil.depth_enabled = 1;
303          depth_stencil.depth_writemask = 1;
304          depth_stencil.depth_func = PIPE_FUNC_ALWAYS;
305       }
306 
307       if (clear_buffers & PIPE_CLEAR_STENCIL) {
308          struct pipe_stencil_ref stencil_ref;
309          memset(&stencil_ref, 0, sizeof(stencil_ref));
310          depth_stencil.stencil[0].enabled = 1;
311          depth_stencil.stencil[0].func = PIPE_FUNC_ALWAYS;
312          depth_stencil.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
313          depth_stencil.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
314          depth_stencil.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
315          depth_stencil.stencil[0].valuemask = 0xff;
316          depth_stencil.stencil[0].writemask = ctx->Stencil.WriteMask[0] & 0xff;
317          stencil_ref.ref_value[0] = ctx->Stencil.Clear;
318          cso_set_stencil_ref(cso, stencil_ref);
319       }
320 
321       cso_set_depth_stencil_alpha(cso, &depth_stencil);
322    }
323 
324    st->util_velems.count = 2;
325    cso_set_vertex_elements(cso, &st->util_velems);
326 
327    cso_set_stream_outputs(cso, 0, NULL, NULL);
328    cso_set_sample_mask(cso, ~0);
329    cso_set_min_samples(cso, 1);
330    st->clear.raster.multisample = st->state.fb_num_samples > 1;
331    cso_set_rasterizer(cso, &st->clear.raster);
332 
333    /* viewport state: viewport matching window dims */
334    cso_set_viewport_dims(st->cso_context, fb_width, fb_height,
335                          st_fb_orientation(fb) == Y_0_TOP);
336 
337    set_fragment_shader(st);
338    cso_set_tessctrl_shader_handle(cso, NULL);
339    cso_set_tesseval_shader_handle(cso, NULL);
340 
341    if (num_layers > 1)
342       set_vertex_shader_layered(st);
343    else
344       set_vertex_shader(st);
345 
346    /* draw quad matching scissor rect.
347     *
348     * Note: if we're only clearing depth/stencil we still setup vertices
349     * with color, but they'll be ignored.
350     *
351     * We can't translate the clear color to the colorbuffer format,
352     * because different colorbuffers may have different formats.
353     */
354    if (!st_draw_quad(st, x0, y0, x1, y1,
355                      ctx->Depth.Clear * 2.0f - 1.0f,
356                      0.0f, 0.0f, 0.0f, 0.0f,
357                      (const float *) &ctx->Color.ClearColor.f,
358                      num_layers)) {
359       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear");
360    }
361 
362    /* Restore pipe state */
363    cso_restore_state(cso, 0);
364    st->dirty |= ST_NEW_VERTEX_ARRAYS;
365 }
366 
367 
368 /**
369  * Return if the scissor must be enabled during the clear.
370  */
371 static inline GLboolean
is_scissor_enabled(struct gl_context * ctx,struct gl_renderbuffer * rb)372 is_scissor_enabled(struct gl_context *ctx, struct gl_renderbuffer *rb)
373 {
374    const struct gl_scissor_rect *scissor = &ctx->Scissor.ScissorArray[0];
375 
376    return (ctx->Scissor.EnableFlags & 1) &&
377           (scissor->X > 0 ||
378            scissor->Y > 0 ||
379            scissor->X + scissor->Width < (int)rb->Width ||
380            scissor->Y + scissor->Height < (int)rb->Height);
381 }
382 
383 /**
384  * Return if window rectangles must be enabled during the clear.
385  */
386 static inline bool
is_window_rectangle_enabled(struct gl_context * ctx)387 is_window_rectangle_enabled(struct gl_context *ctx)
388 {
389    if (ctx->DrawBuffer == ctx->WinSysDrawBuffer)
390       return false;
391    return ctx->Scissor.NumWindowRects > 0 ||
392       ctx->Scissor.WindowRectMode == GL_INCLUSIVE_EXT;
393 }
394 
395 
396 /**
397  * Return if all of the stencil bits are masked.
398  */
399 static inline GLboolean
is_stencil_disabled(struct gl_context * ctx,struct gl_renderbuffer * rb)400 is_stencil_disabled(struct gl_context *ctx, struct gl_renderbuffer *rb)
401 {
402    const GLuint stencilMax = 0xff;
403 
404    assert(_mesa_get_format_bits(rb->Format, GL_STENCIL_BITS) > 0);
405    return (ctx->Stencil.WriteMask[0] & stencilMax) == 0;
406 }
407 
408 
409 /**
410  * Return if any of the stencil bits are masked.
411  */
412 static inline GLboolean
is_stencil_masked(struct gl_context * ctx,struct gl_renderbuffer * rb)413 is_stencil_masked(struct gl_context *ctx, struct gl_renderbuffer *rb)
414 {
415    const GLuint stencilMax = 0xff;
416 
417    assert(_mesa_get_format_bits(rb->Format, GL_STENCIL_BITS) > 0);
418    return (ctx->Stencil.WriteMask[0] & stencilMax) != stencilMax;
419 }
420 
421 
422 /**
423  * Called via ctx->Driver.Clear()
424  */
425 static void
st_Clear(struct gl_context * ctx,GLbitfield mask)426 st_Clear(struct gl_context *ctx, GLbitfield mask)
427 {
428    struct st_context *st = st_context(ctx);
429    struct gl_renderbuffer *depthRb
430       = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
431    struct gl_renderbuffer *stencilRb
432       = ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
433    GLbitfield quad_buffers = 0x0;
434    GLbitfield clear_buffers = 0x0;
435    bool have_scissor_buffers = false;
436    GLuint i;
437 
438    st_flush_bitmap_cache(st);
439    st_invalidate_readpix_cache(st);
440 
441    /* This makes sure the pipe has the latest scissor, etc values */
442    st_validate_state(st, ST_PIPELINE_CLEAR);
443 
444    if (mask & BUFFER_BITS_COLOR) {
445       for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
446          gl_buffer_index b = ctx->DrawBuffer->_ColorDrawBufferIndexes[i];
447 
448          if (b != BUFFER_NONE && mask & (1 << b)) {
449             struct gl_renderbuffer *rb
450                = ctx->DrawBuffer->Attachment[b].Renderbuffer;
451             struct st_renderbuffer *strb = st_renderbuffer(rb);
452             int colormask_index = ctx->Extensions.EXT_draw_buffers2 ? i : 0;
453 
454             if (!strb || !strb->surface)
455                continue;
456 
457             unsigned colormask =
458                GET_COLORMASK(ctx->Color.ColorMask, colormask_index);
459 
460             if (!colormask)
461                continue;
462 
463             unsigned surf_colormask =
464                util_format_colormask(util_format_description(strb->surface->format));
465 
466             bool scissor = is_scissor_enabled(ctx, rb);
467             if ((scissor && !st->can_scissor_clear) ||
468                 is_window_rectangle_enabled(ctx) ||
469                 ((colormask & surf_colormask) != surf_colormask))
470                quad_buffers |= PIPE_CLEAR_COLOR0 << i;
471             else
472                clear_buffers |= PIPE_CLEAR_COLOR0 << i;
473             have_scissor_buffers |= scissor && st->can_scissor_clear;
474          }
475       }
476    }
477 
478    if (mask & BUFFER_BIT_DEPTH) {
479       struct st_renderbuffer *strb = st_renderbuffer(depthRb);
480 
481       if (strb->surface && ctx->Depth.Mask) {
482          bool scissor = is_scissor_enabled(ctx, depthRb);
483          if ((scissor && !st->can_scissor_clear) ||
484              is_window_rectangle_enabled(ctx))
485             quad_buffers |= PIPE_CLEAR_DEPTH;
486          else
487             clear_buffers |= PIPE_CLEAR_DEPTH;
488          have_scissor_buffers |= scissor && st->can_scissor_clear;
489       }
490    }
491    if (mask & BUFFER_BIT_STENCIL) {
492       struct st_renderbuffer *strb = st_renderbuffer(stencilRb);
493 
494       if (strb->surface && !is_stencil_disabled(ctx, stencilRb)) {
495          bool scissor = is_scissor_enabled(ctx, stencilRb);
496          if ((scissor && !st->can_scissor_clear) ||
497              is_window_rectangle_enabled(ctx) ||
498              is_stencil_masked(ctx, stencilRb))
499             quad_buffers |= PIPE_CLEAR_STENCIL;
500          else
501             clear_buffers |= PIPE_CLEAR_STENCIL;
502          have_scissor_buffers |= scissor && st->can_scissor_clear;
503       }
504    }
505 
506    /* Always clear depth and stencil together.
507     * This can only happen when the stencil writemask is not a full mask.
508     */
509    if (quad_buffers & PIPE_CLEAR_DEPTHSTENCIL &&
510        clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) {
511       quad_buffers |= clear_buffers & PIPE_CLEAR_DEPTHSTENCIL;
512       clear_buffers &= ~PIPE_CLEAR_DEPTHSTENCIL;
513    }
514 
515    /* Only use quad-based clearing for the renderbuffers which cannot
516     * use pipe->clear. We want to always use pipe->clear for the other
517     * renderbuffers, because it's likely to be faster.
518     */
519    if (clear_buffers) {
520       const struct gl_scissor_rect *scissor = &ctx->Scissor.ScissorArray[0];
521       struct pipe_scissor_state scissor_state = {
522          .minx = MAX2(scissor->X, 0),
523          .miny = MAX2(scissor->Y, 0),
524          .maxx = MAX2(scissor->X + scissor->Width, 0),
525          .maxy = MAX2(scissor->Y + scissor->Height, 0),
526 
527       };
528 
529       /* Now invert Y if needed.
530        * Gallium drivers use the convention Y=0=top for surfaces.
531        */
532       if (st->state.fb_orientation == Y_0_TOP) {
533          const struct gl_framebuffer *fb = ctx->DrawBuffer;
534          /* use intermediate variables to avoid uint underflow */
535          GLint miny, maxy;
536          miny = fb->Height - scissor_state.maxy;
537          maxy = fb->Height - scissor_state.miny;
538          scissor_state.miny = MAX2(miny, 0);
539          scissor_state.maxy = MAX2(maxy, 0);
540       }
541       if (have_scissor_buffers) {
542          const struct gl_framebuffer *fb = ctx->DrawBuffer;
543          scissor_state.maxx = MIN2(scissor_state.maxx, fb->Width);
544          scissor_state.maxy = MIN2(scissor_state.maxy, fb->Height);
545          if (scissor_state.minx >= scissor_state.maxx ||
546              scissor_state.miny >= scissor_state.maxy)
547             return;
548       }
549       /* We can't translate the clear color to the colorbuffer format,
550        * because different colorbuffers may have different formats.
551        */
552       st->pipe->clear(st->pipe, clear_buffers, have_scissor_buffers ? &scissor_state : NULL,
553                       (union pipe_color_union*)&ctx->Color.ClearColor,
554                       ctx->Depth.Clear, ctx->Stencil.Clear);
555    }
556    if (quad_buffers) {
557       clear_with_quad(ctx, quad_buffers);
558    }
559    if (mask & BUFFER_BIT_ACCUM)
560       _mesa_clear_accum_buffer(ctx);
561 }
562 
563 
564 void
st_init_clear_functions(struct dd_function_table * functions)565 st_init_clear_functions(struct dd_function_table *functions)
566 {
567    functions->Clear = st_Clear;
568 }
569