mesa/st: Remove internal flushes from Mesa state tracker.
[mesa.git] / src / mesa / state_tracker / st_cb_clear.c
index e83b6c92efb7ed340a99df357fefdc86190ca0dc..7e3b87351f1fbdb98dd907a8f22da0ff74cd59f6 100644 (file)
 #include "st_cb_accum.h"
 #include "st_cb_clear.h"
 #include "st_cb_fbo.h"
-#include "st_draw.h"
 #include "st_program.h"
-#include "st_public.h"
-#include "st_mesa_to_tgsi.h"
-#include "st_inlines.h"
 
 #include "pipe/p_context.h"
-#include "pipe/p_inlines.h"
 #include "pipe/p_state.h"
 #include "pipe/p_defines.h"
-#include "util/u_pack_color.h"
+#include "util/u_format.h"
+#include "util/u_inlines.h"
 #include "util/u_simple_shaders.h"
 #include "util/u_draw_quad.h"
 
 #include "cso_cache/cso_context.h"
 
 
+/**
+ * Do per-context initialization for glClear.
+ */
 void
 st_init_clear(struct st_context *st)
 {
    struct pipe_context *pipe = st->pipe;
 
-   memset(&st->clear.raster, 0, sizeof(st->clear.raster));
-   st->clear.raster.gl_rasterization_rules = 1;
+   memset(&st->clear, 0, sizeof(st->clear));
 
-   /* rasterizer state: bypass vertex shader, clipping and viewport */
-   st->clear.raster.bypass_vs_clip_and_viewport = 1;
+   st->clear.raster.gl_rasterization_rules = 1;
 
    /* fragment shader state: color pass-through program */
-   st->clear.fs =
-      util_make_fragment_passthrough_shader(pipe);
+   st->clear.fs = util_make_fragment_passthrough_shader(pipe);
 
    /* vertex shader state: color/position pass-through */
    {
@@ -86,6 +82,9 @@ st_init_clear(struct st_context *st)
 }
 
 
+/**
+ * Free per-context state for glClear.
+ */
 void
 st_destroy_clear(struct st_context *st)
 {
@@ -98,7 +97,7 @@ st_destroy_clear(struct st_context *st)
       st->clear.vs = NULL;
    }
    if (st->clear.vbuf) {
-      pipe_buffer_reference(&st->clear.vbuf, NULL);
+      pipe_resource_reference(&st->clear.vbuf, NULL);
       st->clear.vbuf = NULL;
    }
 }
@@ -106,16 +105,13 @@ st_destroy_clear(struct st_context *st)
 
 /**
  * Draw a screen-aligned quadrilateral.
- * Coords are window coords with y=0=bottom.  These will be passed
- * through unmodified to the rasterizer as we have set
- * rasterizer->bypass_vs_clip_and_viewport.
+ * Coords are clip coords with y=0=bottom.
  */
 static void
-draw_quad(GLcontext *ctx,
+draw_quad(struct st_context *st,
           float x0, float y0, float x1, float y1, GLfloat z,
           const GLfloat color[4])
 {
-   struct st_context *st = ctx->st;
    struct pipe_context *pipe = st->pipe;
 
    /* XXX: Need to improve buffer_write to allow NO_WAIT (as well as
@@ -132,12 +128,13 @@ draw_quad(GLcontext *ctx,
    GLuint i;
 
    if (st->clear.vbuf_slot >= max_slots) {
-      pipe_buffer_reference(&st->clear.vbuf, NULL);
+      pipe_resource_reference(&st->clear.vbuf, NULL);
       st->clear.vbuf_slot = 0;
    }
 
    if (!st->clear.vbuf) {
-      st->clear.vbuf = pipe_buffer_create(pipe->screen, 32, PIPE_BUFFER_USAGE_VERTEX,
+      st->clear.vbuf = pipe_buffer_create(pipe->screen,
+                                          PIPE_BIND_VERTEX_BUFFER,
                                           max_slots * sizeof(st->clear.vertices));
    }
 
@@ -165,10 +162,11 @@ draw_quad(GLcontext *ctx,
    }
 
    /* put vertex data into vbuf */
-   st_no_flush_pipe_buffer_write(st, st->clear.vbuf,
-                                st->clear.vbuf_slot * sizeof(st->clear.vertices),
-                                sizeof(st->clear.vertices),
-                                st->clear.vertices);
+   pipe_buffer_write_nooverlap(st->pipe, st->clear.vbuf,
+                                           st->clear.vbuf_slot
+                                             * sizeof(st->clear.vertices),
+                                           sizeof(st->clear.vertices),
+                                           st->clear.vertices);
 
    /* draw */
    util_draw_vertex_buffer(pipe, 
@@ -193,19 +191,14 @@ static void
 clear_with_quad(GLcontext *ctx,
                 GLboolean color, GLboolean depth, GLboolean stencil)
 {
-   struct st_context *st = ctx->st;
-   const GLfloat x0 = (GLfloat) ctx->DrawBuffer->_Xmin;
-   const GLfloat x1 = (GLfloat) ctx->DrawBuffer->_Xmax;
-   GLfloat y0, y1;
-
-   if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
-      y0 = (GLfloat) (ctx->DrawBuffer->Height - ctx->DrawBuffer->_Ymax);
-      y1 = (GLfloat) (ctx->DrawBuffer->Height - ctx->DrawBuffer->_Ymin);
-   }
-   else {
-      y0 = (GLfloat) ctx->DrawBuffer->_Ymin;
-      y1 = (GLfloat) ctx->DrawBuffer->_Ymax;
-   }
+   struct st_context *st = st_context(ctx);
+   const struct gl_framebuffer *fb = ctx->DrawBuffer;
+   const GLfloat fb_width = (GLfloat) fb->Width;
+   const GLfloat fb_height = (GLfloat) fb->Height;
+   const GLfloat x0 = (GLfloat) ctx->DrawBuffer->_Xmin / fb_width * 2.0f - 1.0f;
+   const GLfloat x1 = (GLfloat) ctx->DrawBuffer->_Xmax / fb_width * 2.0f - 1.0f;
+   const GLfloat y0 = (GLfloat) ctx->DrawBuffer->_Ymin / fb_height * 2.0f - 1.0f;
+   const GLfloat y1 = (GLfloat) ctx->DrawBuffer->_Ymax / fb_height * 2.0f - 1.0f;
 
    /*
    printf("%s %s%s%s %f,%f %f,%f\n", __FUNCTION__, 
@@ -217,28 +210,32 @@ clear_with_quad(GLcontext *ctx,
    */
 
    cso_save_blend(st->cso_context);
+   cso_save_stencil_ref(st->cso_context);
    cso_save_depth_stencil_alpha(st->cso_context);
    cso_save_rasterizer(st->cso_context);
+   cso_save_viewport(st->cso_context);
+   cso_save_clip(st->cso_context);
    cso_save_fragment_shader(st->cso_context);
    cso_save_vertex_shader(st->cso_context);
+   cso_save_vertex_elements(st->cso_context);
 
    /* blend state: RGBA masking */
    {
       struct pipe_blend_state blend;
       memset(&blend, 0, sizeof(blend));
-      blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
-      blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
-      blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
-      blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
+      blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+      blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+      blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
+      blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
       if (color) {
-         if (ctx->Color.ColorMask[0])
-            blend.colormask |= PIPE_MASK_R;
-         if (ctx->Color.ColorMask[1])
-            blend.colormask |= PIPE_MASK_G;
-         if (ctx->Color.ColorMask[2])
-            blend.colormask |= PIPE_MASK_B;
-         if (ctx->Color.ColorMask[3])
-            blend.colormask |= PIPE_MASK_A;
+         if (ctx->Color.ColorMask[0][0])
+            blend.rt[0].colormask |= PIPE_MASK_R;
+         if (ctx->Color.ColorMask[0][1])
+            blend.rt[0].colormask |= PIPE_MASK_G;
+         if (ctx->Color.ColorMask[0][2])
+            blend.rt[0].colormask |= PIPE_MASK_B;
+         if (ctx->Color.ColorMask[0][3])
+            blend.rt[0].colormask |= PIPE_MASK_A;
          if (st->ctx->Color.DitherFlag)
             blend.dither = 1;
       }
@@ -256,33 +253,59 @@ clear_with_quad(GLcontext *ctx,
       }
 
       if (stencil) {
+         struct pipe_stencil_ref stencil_ref;
+         memset(&stencil_ref, 0, sizeof(stencil_ref));
          depth_stencil.stencil[0].enabled = 1;
          depth_stencil.stencil[0].func = PIPE_FUNC_ALWAYS;
          depth_stencil.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
          depth_stencil.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
          depth_stencil.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
-         depth_stencil.stencil[0].ref_value = ctx->Stencil.Clear;
          depth_stencil.stencil[0].valuemask = 0xff;
          depth_stencil.stencil[0].writemask = ctx->Stencil.WriteMask[0] & 0xff;
+         stencil_ref.ref_value[0] = ctx->Stencil.Clear;
+         cso_set_stencil_ref(st->cso_context, &stencil_ref);
       }
 
       cso_set_depth_stencil_alpha(st->cso_context, &depth_stencil);
    }
 
+   cso_set_vertex_elements(st->cso_context, 2, st->velems_util_draw);
+
    cso_set_rasterizer(st->cso_context, &st->clear.raster);
 
+   /* viewport state: viewport matching window dims */
+   {
+      const GLboolean invert = (st_fb_orientation(fb) == Y_0_TOP);
+      struct pipe_viewport_state vp;
+      vp.scale[0] = 0.5f * fb_width;
+      vp.scale[1] = fb_height * (invert ? -0.5f : 0.5f);
+      vp.scale[2] = 1.0f;
+      vp.scale[3] = 1.0f;
+      vp.translate[0] = 0.5f * fb_width;
+      vp.translate[1] = 0.5f * fb_height;
+      vp.translate[2] = 0.0f;
+      vp.translate[3] = 0.0f;
+      cso_set_viewport(st->cso_context, &vp);
+   }
+
+   cso_set_clip(st->cso_context, &st->clear.clip);
    cso_set_fragment_shader_handle(st->cso_context, st->clear.fs);
    cso_set_vertex_shader_handle(st->cso_context, st->clear.vs);
 
    /* draw quad matching scissor rect (XXX verify coord round-off) */
-   draw_quad(ctx, x0, y0, x1, y1, (GLfloat) ctx->Depth.Clear, ctx->Color.ClearColor);
+   draw_quad(st, x0, y0, x1, y1,
+             (GLfloat) ctx->Depth.Clear, ctx->Color.ClearColor);
 
    /* Restore pipe state */
    cso_restore_blend(st->cso_context);
+   cso_restore_stencil_ref(st->cso_context);
    cso_restore_depth_stencil_alpha(st->cso_context);
    cso_restore_rasterizer(st->cso_context);
+   cso_restore_viewport(st->cso_context);
+   cso_restore_clip(st->cso_context);
    cso_restore_fragment_shader(st->cso_context);
    cso_restore_vertex_shader(st->cso_context);
+   cso_restore_vertex_elements(st->cso_context);
 }
 
 
@@ -297,18 +320,22 @@ check_clear_color_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb)
         ctx->Scissor.Y != 0 ||
         ctx->Scissor.Width < rb->Width ||
         ctx->Scissor.Height < rb->Height))
-      return TRUE;
+      return GL_TRUE;
 
-   if (!ctx->Color.ColorMask[0] ||
-       !ctx->Color.ColorMask[1] ||
-       !ctx->Color.ColorMask[2] ||
-       !ctx->Color.ColorMask[3])
-      return TRUE;
+   if (!ctx->Color.ColorMask[0][0] ||
+       !ctx->Color.ColorMask[0][1] ||
+       !ctx->Color.ColorMask[0][2] ||
+       !ctx->Color.ColorMask[0][3])
+      return GL_TRUE;
 
-   return FALSE;
+   return GL_FALSE;
 }
 
 
+/**
+ * Determine if we need to clear the combiend depth/stencil buffer by
+ * drawing a quad.
+ */
 static INLINE GLboolean
 check_clear_depth_stencil_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb)
 {
@@ -325,12 +352,12 @@ check_clear_depth_stencil_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb)
         ctx->Scissor.Y != 0 ||
         ctx->Scissor.Width < rb->Width ||
         ctx->Scissor.Height < rb->Height))
-      return TRUE;
+      return GL_TRUE;
 
    if (maskStencil)
-      return TRUE;
+      return GL_TRUE;
 
-   return FALSE;
+   return GL_FALSE;
 }
 
 
@@ -341,20 +368,19 @@ static INLINE GLboolean
 check_clear_depth_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb)
 {
    const struct st_renderbuffer *strb = st_renderbuffer(rb);
-   const GLboolean isDS = pf_is_depth_and_stencil(strb->surface->format);
+   const GLboolean isDS = util_format_is_depth_and_stencil(strb->surface->format);
 
    if (ctx->Scissor.Enabled &&
        (ctx->Scissor.X != 0 ||
         ctx->Scissor.Y != 0 ||
         ctx->Scissor.Width < rb->Width ||
         ctx->Scissor.Height < rb->Height))
-      return TRUE;
+      return GL_TRUE;
 
-   if (isDS && 
-       ctx->DrawBuffer->Visual.stencilBits > 0)
-      return TRUE;
+   if (isDS && ctx->DrawBuffer->Visual.stencilBits > 0)
+      return GL_TRUE;
 
-   return FALSE;
+   return GL_FALSE;
 }
 
 
@@ -365,7 +391,7 @@ static INLINE GLboolean
 check_clear_stencil_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb)
 {
    const struct st_renderbuffer *strb = st_renderbuffer(rb);
-   const GLboolean isDS = pf_is_depth_and_stencil(strb->surface->format);
+   const GLboolean isDS = util_format_is_depth_and_stencil(strb->surface->format);
    const GLuint stencilMax = 0xff;
    const GLboolean maskStencil
       = (ctx->Stencil.WriteMask[0] & stencilMax) != stencilMax;
@@ -375,35 +401,38 @@ check_clear_stencil_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb)
           rb->Format == MESA_FORMAT_S8_Z24);
 
    if (maskStencil) 
-      return TRUE;
+      return GL_TRUE;
 
    if (ctx->Scissor.Enabled &&
        (ctx->Scissor.X != 0 ||
         ctx->Scissor.Y != 0 ||
         ctx->Scissor.Width < rb->Width ||
         ctx->Scissor.Height < rb->Height))
-      return TRUE;
+      return GL_TRUE;
 
    /* This is correct, but it is necessary to look at the depth clear
     * value held in the surface when it comes time to issue the clear,
     * rather than taking depth and stencil clear values from the
     * current state.
     */
-   if (isDS && 
-       ctx->DrawBuffer->Visual.depthBits > 0)
-      return TRUE;
+   if (isDS && ctx->DrawBuffer->Visual.depthBits > 0)
+      return GL_TRUE;
 
-   return FALSE;
+   return GL_FALSE;
 }
 
 
 
-void st_flush_clear( struct st_context *st )
+/**
+ * Called when we need to flush.
+ */
+void
+st_flush_clear(struct st_context *st)
 {
    /* Release vertex buffer to avoid synchronous rendering if we were
     * to map it in the next frame.
     */
-   pipe_buffer_reference(&st->clear.vbuf, NULL);
+   pipe_resource_reference(&st->clear.vbuf, NULL);
    st->clear.vbuf_slot = 0;
 }
  
@@ -411,20 +440,19 @@ void st_flush_clear( struct st_context *st )
 
 /**
  * Called via ctx->Driver.Clear()
- * XXX: doesn't pick up the differences between front/back/left/right
- * clears.  Need to sort that out...
  */
-static void st_clear(GLcontext *ctx, GLbitfield mask)
+static void
+st_Clear(GLcontext *ctx, GLbitfield mask)
 {
    static const GLbitfield BUFFER_BITS_DS
       = (BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL);
-   struct st_context *st = ctx->st;
+   struct st_context *st = st_context(ctx);
    struct gl_renderbuffer *depthRb
       = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
    struct gl_renderbuffer *stencilRb
       = ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
-   GLbitfield quad_buffers = 0;
-   GLbitfield clear_buffers = 0;
+   GLbitfield quad_buffers = 0x0;
+   GLbitfield clear_buffers = 0x0;
    GLuint i;
 
    /* This makes sure the pipe has the latest scissor, etc values */
@@ -500,8 +528,8 @@ static void st_clear(GLcontext *ctx, GLbitfield mask)
                       mask & BUFFER_BIT_DEPTH,
                       mask & BUFFER_BIT_STENCIL);
    } else if (clear_buffers)
-      ctx->st->pipe->clear(ctx->st->pipe, clear_buffers, ctx->Color.ClearColor,
-                           ctx->Depth.Clear, ctx->Stencil.Clear);
+      st->pipe->clear(st->pipe, clear_buffers, ctx->Color.ClearColor,
+                      ctx->Depth.Clear, ctx->Stencil.Clear);
 
    if (mask & BUFFER_BIT_ACCUM)
       st_clear_accum_buffer(ctx,
@@ -509,7 +537,8 @@ static void st_clear(GLcontext *ctx, GLbitfield mask)
 }
 
 
-void st_init_clear_functions(struct dd_function_table *functions)
+void
+st_init_clear_functions(struct dd_function_table *functions)
 {
-   functions->Clear = st_clear;
+   functions->Clear = st_Clear;
 }