Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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/glheader.h"
  37. #include "main/accum.h"
  38. #include "main/formats.h"
  39. #include "main/macros.h"
  40. #include "main/glformats.h"
  41. #include "program/prog_instruction.h"
  42. #include "st_context.h"
  43. #include "st_atom.h"
  44. #include "st_cb_clear.h"
  45. #include "st_cb_fbo.h"
  46. #include "st_format.h"
  47. #include "st_program.h"
  48.  
  49. #include "pipe/p_context.h"
  50. #include "pipe/p_shader_tokens.h"
  51. #include "pipe/p_state.h"
  52. #include "pipe/p_defines.h"
  53. #include "util/u_format.h"
  54. #include "util/u_framebuffer.h"
  55. #include "util/u_inlines.h"
  56. #include "util/u_simple_shaders.h"
  57. #include "util/u_draw_quad.h"
  58. #include "util/u_upload_mgr.h"
  59.  
  60. #include "cso_cache/cso_context.h"
  61.  
  62.  
  63. /**
  64.  * Do per-context initialization for glClear.
  65.  */
  66. void
  67. st_init_clear(struct st_context *st)
  68. {
  69.    memset(&st->clear, 0, sizeof(st->clear));
  70.  
  71.    st->clear.raster.half_pixel_center = 1;
  72.    st->clear.raster.bottom_edge_rule = 1;
  73.    st->clear.raster.depth_clip = 1;
  74. }
  75.  
  76.  
  77. /**
  78.  * Free per-context state for glClear.
  79.  */
  80. void
  81. st_destroy_clear(struct st_context *st)
  82. {
  83.    if (st->clear.fs) {
  84.       cso_delete_fragment_shader(st->cso_context, st->clear.fs);
  85.       st->clear.fs = NULL;
  86.    }
  87.    if (st->clear.vs) {
  88.       cso_delete_vertex_shader(st->cso_context, st->clear.vs);
  89.       st->clear.vs = NULL;
  90.    }
  91.    if (st->clear.vs_layered) {
  92.       cso_delete_vertex_shader(st->cso_context, st->clear.vs_layered);
  93.       st->clear.vs_layered = NULL;
  94.    }
  95.    if (st->clear.gs_layered) {
  96.       cso_delete_geometry_shader(st->cso_context, st->clear.gs_layered);
  97.       st->clear.gs_layered = NULL;
  98.    }
  99. }
  100.  
  101.  
  102. /**
  103.  * Helper function to set the fragment shaders.
  104.  */
  105. static inline void
  106. set_fragment_shader(struct st_context *st)
  107. {
  108.    if (!st->clear.fs)
  109.       st->clear.fs =
  110.          util_make_fragment_passthrough_shader(st->pipe, TGSI_SEMANTIC_GENERIC,
  111.                                                TGSI_INTERPOLATE_CONSTANT,
  112.                                                TRUE);
  113.  
  114.    cso_set_fragment_shader_handle(st->cso_context, st->clear.fs);
  115. }
  116.  
  117.  
  118. /**
  119.  * Helper function to set the vertex shader.
  120.  */
  121. static inline void
  122. set_vertex_shader(struct st_context *st)
  123. {
  124.    /* vertex shader - still required to provide the linkage between
  125.     * fragment shader input semantics and vertex_element/buffers.
  126.     */
  127.    if (!st->clear.vs)
  128.    {
  129.       const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
  130.                                       TGSI_SEMANTIC_GENERIC };
  131.       const uint semantic_indexes[] = { 0, 0 };
  132.       st->clear.vs = util_make_vertex_passthrough_shader(st->pipe, 2,
  133.                                                          semantic_names,
  134.                                                          semantic_indexes,
  135.                                                          FALSE);
  136.    }
  137.  
  138.    cso_set_vertex_shader_handle(st->cso_context, st->clear.vs);
  139.    cso_set_geometry_shader_handle(st->cso_context, NULL);
  140. }
  141.  
  142.  
  143. static void
  144. set_vertex_shader_layered(struct st_context *st)
  145. {
  146.    struct pipe_context *pipe = st->pipe;
  147.  
  148.    if (!pipe->screen->get_param(pipe->screen, PIPE_CAP_TGSI_INSTANCEID)) {
  149.       assert(!"Got layered clear, but VS instancing is unsupported");
  150.       set_vertex_shader(st);
  151.       return;
  152.    }
  153.  
  154.    if (!st->clear.vs_layered) {
  155.       bool vs_layer =
  156.          pipe->screen->get_param(pipe->screen, PIPE_CAP_TGSI_VS_LAYER_VIEWPORT);
  157.       if (vs_layer) {
  158.          st->clear.vs_layered = util_make_layered_clear_vertex_shader(pipe);
  159.       } else {
  160.          st->clear.vs_layered = util_make_layered_clear_helper_vertex_shader(pipe);
  161.          st->clear.gs_layered = util_make_layered_clear_geometry_shader(pipe);
  162.       }
  163.    }
  164.  
  165.    cso_set_vertex_shader_handle(st->cso_context, st->clear.vs_layered);
  166.    cso_set_geometry_shader_handle(st->cso_context, st->clear.gs_layered);
  167. }
  168.  
  169.  
  170. /**
  171.  * Draw a screen-aligned quadrilateral.
  172.  * Coords are clip coords with y=0=bottom.
  173.  */
  174. static void
  175. draw_quad(struct st_context *st,
  176.           float x0, float y0, float x1, float y1, GLfloat z,
  177.           unsigned num_instances,
  178.           const union pipe_color_union *color)
  179. {
  180.    struct cso_context *cso = st->cso_context;
  181.    struct pipe_vertex_buffer vb = {0};
  182.    GLuint i;
  183.    float (*vertices)[2][4];  /**< vertex pos + color */
  184.  
  185.    vb.stride = 8 * sizeof(float);
  186.  
  187.    if (u_upload_alloc(st->uploader, 0, 4 * sizeof(vertices[0]),
  188.                       &vb.buffer_offset, &vb.buffer,
  189.                       (void **) &vertices) != PIPE_OK) {
  190.       return;
  191.    }
  192.  
  193.    /* Convert Z from [0,1] to [-1,1] range */
  194.    z = z * 2.0f - 1.0f;
  195.  
  196.    /* positions */
  197.    vertices[0][0][0] = x0;
  198.    vertices[0][0][1] = y0;
  199.  
  200.    vertices[1][0][0] = x1;
  201.    vertices[1][0][1] = y0;
  202.  
  203.    vertices[2][0][0] = x1;
  204.    vertices[2][0][1] = y1;
  205.  
  206.    vertices[3][0][0] = x0;
  207.    vertices[3][0][1] = y1;
  208.  
  209.    /* same for all verts: */
  210.    for (i = 0; i < 4; i++) {
  211.       vertices[i][0][2] = z;
  212.       vertices[i][0][3] = 1.0;
  213.       vertices[i][1][0] = color->f[0];
  214.       vertices[i][1][1] = color->f[1];
  215.       vertices[i][1][2] = color->f[2];
  216.       vertices[i][1][3] = color->f[3];
  217.    }
  218.  
  219.    u_upload_unmap(st->uploader);
  220.  
  221.    /* draw */
  222.    cso_set_vertex_buffers(cso, cso_get_aux_vertex_buffer_slot(cso), 1, &vb);
  223.    cso_draw_arrays_instanced(cso, PIPE_PRIM_TRIANGLE_FAN, 0, 4,
  224.                              0, num_instances);
  225.    pipe_resource_reference(&vb.buffer, NULL);
  226. }
  227.  
  228.  
  229.  
  230. /**
  231.  * Do glClear by drawing a quadrilateral.
  232.  * The vertices of the quad will be computed from the
  233.  * ctx->DrawBuffer->_X/Ymin/max fields.
  234.  */
  235. static void
  236. clear_with_quad(struct gl_context *ctx, unsigned clear_buffers)
  237. {
  238.    struct st_context *st = st_context(ctx);
  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.    const GLfloat x0 = (GLfloat) ctx->DrawBuffer->_Xmin / fb_width * 2.0f - 1.0f;
  243.    const GLfloat x1 = (GLfloat) ctx->DrawBuffer->_Xmax / fb_width * 2.0f - 1.0f;
  244.    const GLfloat y0 = (GLfloat) ctx->DrawBuffer->_Ymin / fb_height * 2.0f - 1.0f;
  245.    const GLfloat y1 = (GLfloat) ctx->DrawBuffer->_Ymax / fb_height * 2.0f - 1.0f;
  246.    unsigned num_layers =
  247.       util_framebuffer_get_num_layers(&st->state.framebuffer);
  248.  
  249.    /*
  250.    printf("%s %s%s%s %f,%f %f,%f\n", __func__,
  251.           color ? "color, " : "",
  252.           depth ? "depth, " : "",
  253.           stencil ? "stencil" : "",
  254.           x0, y0,
  255.           x1, y1);
  256.    */
  257.  
  258.    cso_save_blend(st->cso_context);
  259.    cso_save_stencil_ref(st->cso_context);
  260.    cso_save_depth_stencil_alpha(st->cso_context);
  261.    cso_save_rasterizer(st->cso_context);
  262.    cso_save_sample_mask(st->cso_context);
  263.    cso_save_min_samples(st->cso_context);
  264.    cso_save_viewport(st->cso_context);
  265.    cso_save_fragment_shader(st->cso_context);
  266.    cso_save_stream_outputs(st->cso_context);
  267.    cso_save_vertex_shader(st->cso_context);
  268.    cso_save_tessctrl_shader(st->cso_context);
  269.    cso_save_tesseval_shader(st->cso_context);
  270.    cso_save_geometry_shader(st->cso_context);
  271.    cso_save_vertex_elements(st->cso_context);
  272.    cso_save_aux_vertex_buffer_slot(st->cso_context);
  273.  
  274.    /* blend state: RGBA masking */
  275.    {
  276.       struct pipe_blend_state blend;
  277.       memset(&blend, 0, sizeof(blend));
  278.       if (clear_buffers & PIPE_CLEAR_COLOR) {
  279.          int num_buffers = ctx->Extensions.EXT_draw_buffers2 ?
  280.                            ctx->DrawBuffer->_NumColorDrawBuffers : 1;
  281.          int i;
  282.  
  283.          blend.independent_blend_enable = num_buffers > 1;
  284.  
  285.          for (i = 0; i < num_buffers; i++) {
  286.             if (!(clear_buffers & (PIPE_CLEAR_COLOR0 << i)))
  287.                continue;
  288.  
  289.             if (ctx->Color.ColorMask[i][0])
  290.                blend.rt[i].colormask |= PIPE_MASK_R;
  291.             if (ctx->Color.ColorMask[i][1])
  292.                blend.rt[i].colormask |= PIPE_MASK_G;
  293.             if (ctx->Color.ColorMask[i][2])
  294.                blend.rt[i].colormask |= PIPE_MASK_B;
  295.             if (ctx->Color.ColorMask[i][3])
  296.                blend.rt[i].colormask |= PIPE_MASK_A;
  297.          }
  298.  
  299.          if (st->ctx->Color.DitherFlag)
  300.             blend.dither = 1;
  301.       }
  302.       cso_set_blend(st->cso_context, &blend);
  303.    }
  304.  
  305.    /* depth_stencil state: always pass/set to ref value */
  306.    {
  307.       struct pipe_depth_stencil_alpha_state depth_stencil;
  308.       memset(&depth_stencil, 0, sizeof(depth_stencil));
  309.       if (clear_buffers & PIPE_CLEAR_DEPTH) {
  310.          depth_stencil.depth.enabled = 1;
  311.          depth_stencil.depth.writemask = 1;
  312.          depth_stencil.depth.func = PIPE_FUNC_ALWAYS;
  313.       }
  314.  
  315.       if (clear_buffers & PIPE_CLEAR_STENCIL) {
  316.          struct pipe_stencil_ref stencil_ref;
  317.          memset(&stencil_ref, 0, sizeof(stencil_ref));
  318.          depth_stencil.stencil[0].enabled = 1;
  319.          depth_stencil.stencil[0].func = PIPE_FUNC_ALWAYS;
  320.          depth_stencil.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
  321.          depth_stencil.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
  322.          depth_stencil.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
  323.          depth_stencil.stencil[0].valuemask = 0xff;
  324.          depth_stencil.stencil[0].writemask = ctx->Stencil.WriteMask[0] & 0xff;
  325.          stencil_ref.ref_value[0] = ctx->Stencil.Clear;
  326.          cso_set_stencil_ref(st->cso_context, &stencil_ref);
  327.       }
  328.  
  329.       cso_set_depth_stencil_alpha(st->cso_context, &depth_stencil);
  330.    }
  331.  
  332.    cso_set_vertex_elements(st->cso_context, 2, st->velems_util_draw);
  333.    cso_set_stream_outputs(st->cso_context, 0, NULL, NULL);
  334.    cso_set_sample_mask(st->cso_context, ~0);
  335.    cso_set_min_samples(st->cso_context, 1);
  336.    cso_set_rasterizer(st->cso_context, &st->clear.raster);
  337.  
  338.    /* viewport state: viewport matching window dims */
  339.    {
  340.       const GLboolean invert = (st_fb_orientation(fb) == Y_0_TOP);
  341.       struct pipe_viewport_state vp;
  342.       vp.scale[0] = 0.5f * fb_width;
  343.       vp.scale[1] = fb_height * (invert ? -0.5f : 0.5f);
  344.       vp.scale[2] = 0.5f;
  345.       vp.translate[0] = 0.5f * fb_width;
  346.       vp.translate[1] = 0.5f * fb_height;
  347.       vp.translate[2] = 0.5f;
  348.       cso_set_viewport(st->cso_context, &vp);
  349.    }
  350.  
  351.    set_fragment_shader(st);
  352.    cso_set_tessctrl_shader_handle(st->cso_context, NULL);
  353.    cso_set_tesseval_shader_handle(st->cso_context, NULL);
  354.  
  355.    if (num_layers > 1)
  356.       set_vertex_shader_layered(st);
  357.    else
  358.       set_vertex_shader(st);
  359.  
  360.    /* We can't translate the clear color to the colorbuffer format,
  361.     * because different colorbuffers may have different formats.
  362.     */
  363.  
  364.    /* draw quad matching scissor rect */
  365.    draw_quad(st, x0, y0, x1, y1, (GLfloat) ctx->Depth.Clear, num_layers,
  366.              (union pipe_color_union*)&ctx->Color.ClearColor);
  367.  
  368.    /* Restore pipe state */
  369.    cso_restore_blend(st->cso_context);
  370.    cso_restore_stencil_ref(st->cso_context);
  371.    cso_restore_depth_stencil_alpha(st->cso_context);
  372.    cso_restore_rasterizer(st->cso_context);
  373.    cso_restore_sample_mask(st->cso_context);
  374.    cso_restore_min_samples(st->cso_context);
  375.    cso_restore_viewport(st->cso_context);
  376.    cso_restore_fragment_shader(st->cso_context);
  377.    cso_restore_vertex_shader(st->cso_context);
  378.    cso_restore_tessctrl_shader(st->cso_context);
  379.    cso_restore_tesseval_shader(st->cso_context);
  380.    cso_restore_geometry_shader(st->cso_context);
  381.    cso_restore_vertex_elements(st->cso_context);
  382.    cso_restore_aux_vertex_buffer_slot(st->cso_context);
  383.    cso_restore_stream_outputs(st->cso_context);
  384. }
  385.  
  386.  
  387. /**
  388.  * Return if the scissor must be enabled during the clear.
  389.  */
  390. static inline GLboolean
  391. is_scissor_enabled(struct gl_context *ctx, struct gl_renderbuffer *rb)
  392. {
  393.    return (ctx->Scissor.EnableFlags & 1) &&
  394.           (ctx->Scissor.ScissorArray[0].X > 0 ||
  395.            ctx->Scissor.ScissorArray[0].Y > 0 ||
  396.            (unsigned) ctx->Scissor.ScissorArray[0].Width < rb->Width ||
  397.            (unsigned) ctx->Scissor.ScissorArray[0].Height < rb->Height);
  398. }
  399.  
  400.  
  401. /**
  402.  * Return if all of the color channels are masked.
  403.  */
  404. static inline GLboolean
  405. is_color_disabled(struct gl_context *ctx, int i)
  406. {
  407.    return !ctx->Color.ColorMask[i][0] &&
  408.           !ctx->Color.ColorMask[i][1] &&
  409.           !ctx->Color.ColorMask[i][2] &&
  410.           !ctx->Color.ColorMask[i][3];
  411. }
  412.  
  413.  
  414. /**
  415.  * Return if any of the color channels are masked.
  416.  */
  417. static inline GLboolean
  418. is_color_masked(struct gl_context *ctx, int i)
  419. {
  420.    return !ctx->Color.ColorMask[i][0] ||
  421.           !ctx->Color.ColorMask[i][1] ||
  422.           !ctx->Color.ColorMask[i][2] ||
  423.           !ctx->Color.ColorMask[i][3];
  424. }
  425.  
  426.  
  427. /**
  428.  * Return if all of the stencil bits are masked.
  429.  */
  430. static inline GLboolean
  431. is_stencil_disabled(struct gl_context *ctx, struct gl_renderbuffer *rb)
  432. {
  433.    const GLuint stencilMax = 0xff;
  434.  
  435.    assert(_mesa_get_format_bits(rb->Format, GL_STENCIL_BITS) > 0);
  436.    return (ctx->Stencil.WriteMask[0] & stencilMax) == 0;
  437. }
  438.  
  439.  
  440. /**
  441.  * Return if any of the stencil bits are masked.
  442.  */
  443. static inline GLboolean
  444. is_stencil_masked(struct gl_context *ctx, struct gl_renderbuffer *rb)
  445. {
  446.    const GLuint stencilMax = 0xff;
  447.  
  448.    assert(_mesa_get_format_bits(rb->Format, GL_STENCIL_BITS) > 0);
  449.    return (ctx->Stencil.WriteMask[0] & stencilMax) != stencilMax;
  450. }
  451.  
  452.  
  453. /**
  454.  * Called via ctx->Driver.Clear()
  455.  */
  456. static void
  457. st_Clear(struct gl_context *ctx, GLbitfield mask)
  458. {
  459.    struct st_context *st = st_context(ctx);
  460.    struct gl_renderbuffer *depthRb
  461.       = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
  462.    struct gl_renderbuffer *stencilRb
  463.       = ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
  464.    GLbitfield quad_buffers = 0x0;
  465.    GLbitfield clear_buffers = 0x0;
  466.    GLuint i;
  467.  
  468.    /* This makes sure the pipe has the latest scissor, etc values */
  469.    st_validate_state( st );
  470.  
  471.    if (mask & BUFFER_BITS_COLOR) {
  472.       for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
  473.          GLint b = ctx->DrawBuffer->_ColorDrawBufferIndexes[i];
  474.  
  475.          if (b >= 0 && mask & (1 << b)) {
  476.             struct gl_renderbuffer *rb
  477.                = ctx->DrawBuffer->Attachment[b].Renderbuffer;
  478.             struct st_renderbuffer *strb = st_renderbuffer(rb);
  479.             int colormask_index = ctx->Extensions.EXT_draw_buffers2 ? i : 0;
  480.  
  481.             if (!strb || !strb->surface)
  482.                continue;
  483.  
  484.             if (is_color_disabled(ctx, colormask_index))
  485.                continue;
  486.  
  487.             if (is_scissor_enabled(ctx, rb) ||
  488.                 is_color_masked(ctx, colormask_index))
  489.                quad_buffers |= PIPE_CLEAR_COLOR0 << i;
  490.             else
  491.                clear_buffers |= PIPE_CLEAR_COLOR0 << i;
  492.          }
  493.       }
  494.    }
  495.  
  496.    if (mask & BUFFER_BIT_DEPTH) {
  497.       struct st_renderbuffer *strb = st_renderbuffer(depthRb);
  498.  
  499.       if (strb->surface && ctx->Depth.Mask) {
  500.          if (is_scissor_enabled(ctx, depthRb))
  501.             quad_buffers |= PIPE_CLEAR_DEPTH;
  502.          else
  503.             clear_buffers |= PIPE_CLEAR_DEPTH;
  504.       }
  505.    }
  506.    if (mask & BUFFER_BIT_STENCIL) {
  507.       struct st_renderbuffer *strb = st_renderbuffer(stencilRb);
  508.  
  509.       if (strb->surface && !is_stencil_disabled(ctx, stencilRb)) {
  510.          if (is_scissor_enabled(ctx, stencilRb) ||
  511.              is_stencil_masked(ctx, stencilRb))
  512.             quad_buffers |= PIPE_CLEAR_STENCIL;
  513.          else
  514.             clear_buffers |= PIPE_CLEAR_STENCIL;
  515.       }
  516.    }
  517.  
  518.    /* Always clear depth and stencil together.
  519.     * This can only happen when the stencil writemask is not a full mask.
  520.     */
  521.    if (quad_buffers & PIPE_CLEAR_DEPTHSTENCIL &&
  522.        clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) {
  523.       quad_buffers |= clear_buffers & PIPE_CLEAR_DEPTHSTENCIL;
  524.       clear_buffers &= ~PIPE_CLEAR_DEPTHSTENCIL;
  525.    }
  526.  
  527.    /* Only use quad-based clearing for the renderbuffers which cannot
  528.     * use pipe->clear. We want to always use pipe->clear for the other
  529.     * renderbuffers, because it's likely to be faster.
  530.     */
  531.    if (quad_buffers) {
  532.       clear_with_quad(ctx, quad_buffers);
  533.    }
  534.    if (clear_buffers) {
  535.       /* We can't translate the clear color to the colorbuffer format,
  536.        * because different colorbuffers may have different formats.
  537.        */
  538.       st->pipe->clear(st->pipe, clear_buffers,
  539.                       (union pipe_color_union*)&ctx->Color.ClearColor,
  540.                       ctx->Depth.Clear, ctx->Stencil.Clear);
  541.    }
  542.    if (mask & BUFFER_BIT_ACCUM)
  543.       _mesa_clear_accum_buffer(ctx);
  544. }
  545.  
  546.  
  547. void
  548. st_init_clear_functions(struct dd_function_table *functions)
  549. {
  550.    functions->Clear = st_Clear;
  551. }
  552.