st_cb_clear.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  * 
00003  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
00004  * All Rights Reserved.
00005  * 
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  * 
00014  * The above copyright notice and this permission notice (including the
00015  * next paragraph) shall be included in all copies or substantial portions
00016  * of the Software.
00017  * 
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
00021  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
00022  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00023  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00024  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00025  * 
00026  **************************************************************************/
00027 
00028  /*
00029   * Authors:
00030   *   Keith Whitwell <keith@tungstengraphics.com>
00031   *   Brian Paul
00032   */
00033 
00034 #include "main/glheader.h"
00035 #include "main/macros.h"
00036 #include "shader/prog_instruction.h"
00037 #include "st_context.h"
00038 #include "st_atom.h"
00039 #include "st_cb_accum.h"
00040 #include "st_cb_clear.h"
00041 #include "st_cb_fbo.h"
00042 #include "st_draw.h"
00043 #include "st_program.h"
00044 #include "st_public.h"
00045 #include "st_mesa_to_tgsi.h"
00046 
00047 #include "pipe/p_context.h"
00048 #include "pipe/p_inlines.h"
00049 #include "pipe/p_state.h"
00050 #include "pipe/p_defines.h"
00051 #include "util/u_pack_color.h"
00052 #include "util/u_simple_shaders.h"
00053 #include "util/u_draw_quad.h"
00054 
00055 #include "cso_cache/cso_context.h"
00056 
00057 
00058 void
00059 st_init_clear(struct st_context *st)
00060 {
00061    struct pipe_context *pipe = st->pipe;
00062 
00063    /* rasterizer state: bypass clipping */
00064    memset(&st->clear.raster, 0, sizeof(st->clear.raster));
00065    st->clear.raster.gl_rasterization_rules = 1;
00066    st->clear.raster.bypass_clipping = 1;
00067 
00068    /* viewport state: identity since we're drawing in window coords */
00069    st->clear.viewport.scale[0] = 1.0;
00070    st->clear.viewport.scale[1] = 1.0;
00071    st->clear.viewport.scale[2] = 1.0;
00072    st->clear.viewport.scale[3] = 1.0;
00073    st->clear.viewport.translate[0] = 0.0;
00074    st->clear.viewport.translate[1] = 0.0;
00075    st->clear.viewport.translate[2] = 0.0;
00076    st->clear.viewport.translate[3] = 0.0;
00077 
00078    /* fragment shader state: color pass-through program */
00079    st->clear.fs =
00080       util_make_fragment_passthrough_shader(pipe, &st->clear.frag_shader);
00081 
00082    /* vertex shader state: color/position pass-through */
00083    {
00084       const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
00085                                       TGSI_SEMANTIC_COLOR };
00086       const uint semantic_indexes[] = { 0, 0 };
00087       st->clear.vs = util_make_vertex_passthrough_shader(pipe, 2,
00088                                                          semantic_names,
00089                                                          semantic_indexes,
00090                                                          &st->clear.vert_shader);
00091    }
00092 }
00093 
00094 
00095 void
00096 st_destroy_clear(struct st_context *st)
00097 {
00098    struct pipe_context *pipe = st->pipe;
00099 
00100    if (st->clear.vert_shader.tokens) {
00101       util_free_shader(&st->clear.vert_shader);
00102       st->clear.vert_shader.tokens = NULL;
00103    }
00104 
00105    if (st->clear.frag_shader.tokens) {
00106       util_free_shader(&st->clear.frag_shader);
00107       st->clear.frag_shader.tokens = NULL;
00108    }
00109 
00110    if (st->clear.fs) {
00111       cso_delete_fragment_shader(st->cso_context, st->clear.fs);
00112       st->clear.fs = NULL;
00113    }
00114    if (st->clear.vs) {
00115       cso_delete_vertex_shader(st->cso_context, st->clear.vs);
00116       st->clear.vs = NULL;
00117    }
00118    if (st->clear.vbuf) {
00119       pipe_buffer_reference(pipe->screen, &st->clear.vbuf, NULL);
00120       st->clear.vbuf = NULL;
00121    }
00122 }
00123 
00124 
00125 static GLboolean
00126 is_depth_stencil_format(enum pipe_format pipeFormat)
00127 {
00128    switch (pipeFormat) {
00129    case PIPE_FORMAT_S8Z24_UNORM:
00130    case PIPE_FORMAT_Z24S8_UNORM:
00131       return GL_TRUE;
00132    default:
00133       return GL_FALSE;
00134    }
00135 }
00136 
00137 
00138 
00144 static void
00145 draw_quad(GLcontext *ctx,
00146           float x0, float y0, float x1, float y1, GLfloat z,
00147           const GLfloat color[4])
00148 {
00149    struct st_context *st = ctx->st;
00150    struct pipe_context *pipe = st->pipe;
00151    const GLuint max_slots = 1024 / sizeof(st->clear.vertices);
00152    GLuint i;
00153    void *buf;
00154 
00155    if (st->clear.vbuf_slot >= max_slots) {
00156       pipe_buffer_reference(pipe->screen, &st->clear.vbuf, NULL);
00157       st->clear.vbuf_slot = 0;
00158    }
00159 
00160    if (!st->clear.vbuf) {
00161       st->clear.vbuf = pipe_buffer_create(pipe->screen, 32, PIPE_BUFFER_USAGE_VERTEX,
00162                                           max_slots * sizeof(st->clear.vertices));
00163    }
00164 
00165    /* positions */
00166    st->clear.vertices[0][0][0] = x0;
00167    st->clear.vertices[0][0][1] = y0;
00168 
00169    st->clear.vertices[1][0][0] = x1;
00170    st->clear.vertices[1][0][1] = y0;
00171 
00172    st->clear.vertices[2][0][0] = x1;
00173    st->clear.vertices[2][0][1] = y1;
00174 
00175    st->clear.vertices[3][0][0] = x0;
00176    st->clear.vertices[3][0][1] = y1;
00177 
00178    /* same for all verts: */
00179    for (i = 0; i < 4; i++) {
00180       st->clear.vertices[i][0][2] = z;
00181       st->clear.vertices[i][0][3] = 1.0;
00182       st->clear.vertices[i][1][0] = color[0];
00183       st->clear.vertices[i][1][1] = color[1];
00184       st->clear.vertices[i][1][2] = color[2];
00185       st->clear.vertices[i][1][3] = color[3];
00186    }
00187 
00188    /* put vertex data into vbuf */
00189    buf = pipe_buffer_map(pipe->screen, st->clear.vbuf, PIPE_BUFFER_USAGE_CPU_WRITE);
00190 
00191    memcpy((char *)buf + st->clear.vbuf_slot * sizeof(st->clear.vertices), 
00192           st->clear.vertices, 
00193           sizeof(st->clear.vertices));
00194 
00195    pipe_buffer_unmap(pipe->screen, st->clear.vbuf);
00196 
00197    /* draw */
00198    util_draw_vertex_buffer(pipe, 
00199                            st->clear.vbuf, 
00200                            st->clear.vbuf_slot * sizeof(st->clear.vertices),
00201                            PIPE_PRIM_TRIANGLE_FAN,
00202                            4,  /* verts */
00203                            2); /* attribs/vert */
00204 
00205    /* Increment slot */
00206    st->clear.vbuf_slot++;
00207 }
00208 
00209 
00210 
00216 static void
00217 clear_with_quad(GLcontext *ctx,
00218                 GLboolean color, GLboolean depth, GLboolean stencil)
00219 {
00220    struct st_context *st = ctx->st;
00221    const GLfloat x0 = (GLfloat) ctx->DrawBuffer->_Xmin;
00222    const GLfloat x1 = (GLfloat) ctx->DrawBuffer->_Xmax;
00223    GLfloat y0, y1;
00224 
00225    if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
00226       y0 = (GLfloat) (ctx->DrawBuffer->Height - ctx->DrawBuffer->_Ymax);
00227       y1 = (GLfloat) (ctx->DrawBuffer->Height - ctx->DrawBuffer->_Ymin);
00228    }
00229    else {
00230       y0 = (GLfloat) ctx->DrawBuffer->_Ymin;
00231       y1 = (GLfloat) ctx->DrawBuffer->_Ymax;
00232    }
00233 
00234    /*
00235    printf("%s %s%s%s %f,%f %f,%f\n", __FUNCTION__, 
00236           color ? "color, " : "",
00237           depth ? "depth, " : "",
00238           stencil ? "stencil" : "",
00239           x0, y0,
00240           x1, y1);
00241    */
00242 
00243    cso_save_blend(st->cso_context);
00244    cso_save_depth_stencil_alpha(st->cso_context);
00245    cso_save_rasterizer(st->cso_context);
00246    cso_save_viewport(st->cso_context);
00247    cso_save_fragment_shader(st->cso_context);
00248    cso_save_vertex_shader(st->cso_context);
00249 
00250    /* blend state: RGBA masking */
00251    {
00252       struct pipe_blend_state blend;
00253       memset(&blend, 0, sizeof(blend));
00254       blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
00255       blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
00256       blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
00257       blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
00258       if (color) {
00259          if (ctx->Color.ColorMask[0])
00260             blend.colormask |= PIPE_MASK_R;
00261          if (ctx->Color.ColorMask[1])
00262             blend.colormask |= PIPE_MASK_G;
00263          if (ctx->Color.ColorMask[2])
00264             blend.colormask |= PIPE_MASK_B;
00265          if (ctx->Color.ColorMask[3])
00266             blend.colormask |= PIPE_MASK_A;
00267          if (st->ctx->Color.DitherFlag)
00268             blend.dither = 1;
00269       }
00270       cso_set_blend(st->cso_context, &blend);
00271    }
00272 
00273    /* depth_stencil state: always pass/set to ref value */
00274    {
00275       struct pipe_depth_stencil_alpha_state depth_stencil;
00276       memset(&depth_stencil, 0, sizeof(depth_stencil));
00277       if (depth) {
00278          depth_stencil.depth.enabled = 1;
00279          depth_stencil.depth.writemask = 1;
00280          depth_stencil.depth.func = PIPE_FUNC_ALWAYS;
00281       }
00282 
00283       if (stencil) {
00284          depth_stencil.stencil[0].enabled = 1;
00285          depth_stencil.stencil[0].func = PIPE_FUNC_ALWAYS;
00286          depth_stencil.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
00287          depth_stencil.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
00288          depth_stencil.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
00289          depth_stencil.stencil[0].ref_value = ctx->Stencil.Clear;
00290          depth_stencil.stencil[0].value_mask = 0xff;
00291          depth_stencil.stencil[0].write_mask = ctx->Stencil.WriteMask[0] & 0xff;
00292       }
00293 
00294       cso_set_depth_stencil_alpha(st->cso_context, &depth_stencil);
00295    }
00296 
00297    cso_set_rasterizer(st->cso_context, &st->clear.raster);
00298    cso_set_viewport(st->cso_context, &st->clear.viewport);
00299 
00300    cso_set_fragment_shader_handle(st->cso_context, st->clear.fs);
00301    cso_set_vertex_shader_handle(st->cso_context, st->clear.vs);
00302 
00303    /* draw quad matching scissor rect (XXX verify coord round-off) */
00304    draw_quad(ctx, x0, y0, x1, y1, (GLfloat) ctx->Depth.Clear, ctx->Color.ClearColor);
00305 
00306    /* Restore pipe state */
00307    cso_restore_blend(st->cso_context);
00308    cso_restore_depth_stencil_alpha(st->cso_context);
00309    cso_restore_rasterizer(st->cso_context);
00310    cso_restore_viewport(st->cso_context);
00311    cso_restore_fragment_shader(st->cso_context);
00312    cso_restore_vertex_shader(st->cso_context);
00313 }
00314 
00315 
00319 static INLINE GLboolean
00320 check_clear_color_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb)
00321 {
00322    const struct st_renderbuffer *strb = st_renderbuffer(rb);
00323 
00324    if (strb->surface->status == PIPE_SURFACE_STATUS_UNDEFINED)
00325       return FALSE;
00326 
00327    if (ctx->Scissor.Enabled)
00328       return TRUE;
00329 
00330    if (!ctx->Color.ColorMask[0] ||
00331        !ctx->Color.ColorMask[1] ||
00332        !ctx->Color.ColorMask[2] ||
00333        !ctx->Color.ColorMask[3])
00334       return TRUE;
00335 
00336    return FALSE;
00337 }
00338 
00339 
00340 static INLINE GLboolean
00341 check_clear_depth_stencil_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb)
00342 {
00343    const struct st_renderbuffer *strb = st_renderbuffer(rb);
00344    const GLuint stencilMax = (1 << rb->StencilBits) - 1;
00345    GLboolean maskStencil
00346       = (ctx->Stencil.WriteMask[0] & stencilMax) != stencilMax;
00347 
00348    if (strb->surface->status == PIPE_SURFACE_STATUS_UNDEFINED)
00349       return FALSE;
00350 
00351    if (ctx->Scissor.Enabled)
00352       return TRUE;
00353 
00354    if (maskStencil)
00355       return TRUE;
00356 
00357    return FALSE;
00358 }
00359 
00360 
00364 static INLINE GLboolean
00365 check_clear_depth_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb)
00366 {
00367    const struct st_renderbuffer *strb = st_renderbuffer(rb);
00368    const GLboolean isDS = is_depth_stencil_format(strb->surface->format);
00369 
00370    if (strb->surface->status == PIPE_SURFACE_STATUS_UNDEFINED)
00371       return FALSE;
00372 
00373    if (ctx->Scissor.Enabled)
00374       return TRUE;
00375 
00376    if (isDS && 
00377        strb->surface->status == PIPE_SURFACE_STATUS_DEFINED &&
00378        ctx->DrawBuffer->Visual.stencilBits > 0)
00379       return TRUE;
00380 
00381    return FALSE;
00382 }
00383 
00384 
00388 static INLINE GLboolean
00389 check_clear_stencil_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb)
00390 {
00391    const struct st_renderbuffer *strb = st_renderbuffer(rb);
00392    const GLboolean isDS = is_depth_stencil_format(strb->surface->format);
00393    const GLuint stencilMax = (1 << rb->StencilBits) - 1;
00394    const GLboolean maskStencil
00395       = (ctx->Stencil.WriteMask[0] & stencilMax) != stencilMax;
00396 
00397    if (strb->surface->status == PIPE_SURFACE_STATUS_UNDEFINED)
00398       return FALSE;
00399 
00400    if (maskStencil) 
00401       return TRUE;
00402 
00403    if (ctx->Scissor.Enabled)
00404       return TRUE;
00405 
00406    /* This is correct, but it is necessary to look at the depth clear
00407     * value held in the surface when it comes time to issue the clear,
00408     * rather than taking depth and stencil clear values from the
00409     * current state.
00410     */
00411    if (isDS && 
00412        strb->surface->status == PIPE_SURFACE_STATUS_DEFINED &&
00413        ctx->DrawBuffer->Visual.depthBits > 0)
00414       return TRUE;
00415 
00416    return FALSE;
00417 }
00418 
00419 
00420 
00421 static void
00422 clear_color_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
00423 {
00424    struct st_renderbuffer *strb = st_renderbuffer(rb);
00425 
00426    if (!strb->surface)
00427       return;
00428 
00429    if (check_clear_color_with_quad( ctx, rb )) {
00430       /* masking or scissoring */
00431       clear_with_quad(ctx, GL_TRUE, GL_FALSE, GL_FALSE);
00432    }
00433    else {
00434       /* clear whole buffer w/out masking */
00435       uint clearValue;
00436       /* NOTE: we always pass the clear color as PIPE_FORMAT_A8R8G8B8_UNORM
00437        * at this time!
00438        */
00439       util_pack_color(ctx->Color.ClearColor, PIPE_FORMAT_A8R8G8B8_UNORM, &clearValue);
00440       ctx->st->pipe->clear(ctx->st->pipe, strb->surface, clearValue);
00441    }
00442 }
00443 
00444 
00445 static void
00446 clear_depth_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
00447 {
00448    struct st_renderbuffer *strb = st_renderbuffer(rb);
00449 
00450    if (!strb->surface)
00451       return;
00452 
00453    if (check_clear_depth_with_quad(ctx, rb)) {
00454       /* scissoring or we have a combined depth/stencil buffer */
00455       clear_with_quad(ctx, GL_FALSE, GL_TRUE, GL_FALSE);
00456    }
00457    else {
00458       /* simple clear of whole buffer */
00459       uint clearValue = util_pack_z(strb->surface->format, ctx->Depth.Clear);
00460       ctx->st->pipe->clear(ctx->st->pipe, strb->surface, clearValue);
00461    }
00462 }
00463 
00464 
00465 static void
00466 clear_stencil_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
00467 {
00468    struct st_renderbuffer *strb = st_renderbuffer(rb);
00469 
00470    if (!strb->surface)
00471       return;
00472 
00473    if (check_clear_stencil_with_quad(ctx, rb)) {
00474       /* masking or scissoring or combined depth/stencil buffer */
00475       clear_with_quad(ctx, GL_FALSE, GL_FALSE, GL_TRUE);
00476    }
00477    else {
00478       /* simple clear of whole buffer */
00479       GLuint clearValue = ctx->Stencil.Clear;
00480 
00481       switch (strb->surface->format) {
00482       case PIPE_FORMAT_S8Z24_UNORM:
00483          clearValue <<= 24;
00484          break;
00485       default:
00486          ; /* no-op, stencil value is in least significant bits */
00487       }  
00488 
00489       ctx->st->pipe->clear(ctx->st->pipe, strb->surface, clearValue);
00490    }
00491 }
00492 
00493 
00494 static void
00495 clear_depth_stencil_buffer(GLcontext *ctx, struct gl_renderbuffer *rb)
00496 {
00497    struct st_renderbuffer *strb = st_renderbuffer(rb);
00498 
00499    if (!strb->surface)
00500       return;
00501 
00502    if (check_clear_depth_stencil_with_quad(ctx, rb)) {
00503       /* masking or scissoring */
00504       clear_with_quad(ctx, GL_FALSE, GL_TRUE, GL_TRUE);
00505    }
00506    else {
00507       /* clear whole buffer w/out masking */
00508       GLuint clearValue = util_pack_z(strb->surface->format, ctx->Depth.Clear);
00509 
00510       switch (strb->surface->format) {
00511       case PIPE_FORMAT_S8Z24_UNORM:
00512          clearValue |= ctx->Stencil.Clear << 24;
00513          break;
00514       case PIPE_FORMAT_Z24S8_UNORM:
00515          clearValue |= ctx->Stencil.Clear;
00516          break;
00517       default:
00518          assert(0);
00519       }  
00520 
00521       ctx->st->pipe->clear(ctx->st->pipe, strb->surface, clearValue);
00522    }
00523 }
00524 
00525 
00526 void st_flush_clear( struct st_context *st )
00527 {
00528    /* Release vertex buffer to avoid synchronous rendering if we were
00529     * to map it in the next frame.
00530     */
00531    pipe_buffer_reference(st->pipe->screen, &st->clear.vbuf, NULL);
00532    st->clear.vbuf_slot = 0;
00533 }
00534  
00535 
00536 
00542 static void st_clear(GLcontext *ctx, GLbitfield mask)
00543 {
00544    static const GLbitfield BUFFER_BITS_DS
00545       = (BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL);
00546    struct st_context *st = ctx->st;
00547    struct gl_renderbuffer *depthRb
00548       = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
00549    struct gl_renderbuffer *stencilRb
00550       = ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
00551    GLbitfield cmask = mask & BUFFER_BITS_COLOR;
00552 
00553    /* This makes sure the softpipe has the latest scissor, etc values */
00554    st_validate_state( st );
00555 
00556    /*
00557     * XXX TO-DO:
00558     * If we're going to use clear_with_quad() for any reason, use it to
00559     * clear as many other buffers as possible.
00560     * As it is now, we sometimes call clear_with_quad() three times to clear
00561     * color/depth/stencil individually...
00562     */
00563 
00564    if (cmask) {
00565       GLuint b;
00566       for (b = 0; cmask; b++) {
00567          if (cmask & (1 << b)) {
00568             struct gl_renderbuffer *rb
00569                = ctx->DrawBuffer->Attachment[b].Renderbuffer;
00570             assert(rb);
00571             clear_color_buffer(ctx, rb);
00572             cmask &= ~(1 << b); /* turn off bit */
00573          }
00574          assert(b < BUFFER_COUNT);
00575       }
00576    }
00577 
00578    if (mask & BUFFER_BIT_ACCUM) {
00579       st_clear_accum_buffer(ctx,
00580                        ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer);
00581    }
00582 
00583    if ((mask & BUFFER_BITS_DS) == BUFFER_BITS_DS && depthRb == stencilRb) {
00584       /* clearing combined depth + stencil */
00585       clear_depth_stencil_buffer(ctx, depthRb);
00586    }
00587    else {
00588       /* separate depth/stencil clears */
00589       if (mask & BUFFER_BIT_DEPTH) {
00590          clear_depth_buffer(ctx, depthRb);
00591       }
00592       if (mask & BUFFER_BIT_STENCIL) {
00593          clear_stencil_buffer(ctx, stencilRb);
00594       }
00595    }
00596 }
00597 
00598 
00599 void st_init_clear_functions(struct dd_function_table *functions)
00600 {
00601    functions->Clear = st_clear;
00602 }

Generated on Tue Sep 29 06:25:18 2009 for Gallium3D by  doxygen 1.5.4