mesa: replace ctx->Const.{Vertex,Fragment,Geomtery}Program with an array.
[mesa.git] / src / mesa / state_tracker / st_cb_clear.c
index b8e2fad25d7a8ed35ed4585e9ae57899337fbb65..887e58bd9b6840b538a40feb048550e21cf28351 100644 (file)
@@ -51,6 +51,7 @@
 #include "pipe/p_state.h"
 #include "pipe/p_defines.h"
 #include "util/u_format.h"
+#include "util/u_framebuffer.h"
 #include "util/u_inlines.h"
 #include "util/u_simple_shaders.h"
 #include "util/u_draw_quad.h"
@@ -129,6 +130,26 @@ set_vertex_shader(struct st_context *st)
 }
 
 
+static void
+set_vertex_shader_layered(struct st_context *st)
+{
+   struct pipe_context *pipe = st->pipe;
+
+   if (!pipe->screen->get_param(pipe->screen, PIPE_CAP_TGSI_INSTANCEID) ||
+       !pipe->screen->get_param(pipe->screen, PIPE_CAP_TGSI_VS_LAYER)) {
+      assert(!"Got layered clear, but the VS layer output is unsupported");
+      set_vertex_shader(st);
+      return;
+   }
+
+   if (!st->clear.vs_layered) {
+      st->clear.vs_layered = util_make_layered_clear_vertex_shader(pipe);
+   }
+
+   cso_set_vertex_shader_handle(st->cso_context, st->clear.vs_layered);
+}
+
+
 /**
  * Draw a screen-aligned quadrilateral.
  * Coords are clip coords with y=0=bottom.
@@ -136,15 +157,19 @@ set_vertex_shader(struct st_context *st)
 static void
 draw_quad(struct st_context *st,
           float x0, float y0, float x1, float y1, GLfloat z,
+          unsigned num_instances,
           const union pipe_color_union *color)
 {
-   struct pipe_context *pipe = st->pipe;
-   struct pipe_resource *vbuf = NULL;
-   GLuint i, offset;
+   struct cso_context *cso = st->cso_context;
+   struct pipe_vertex_buffer vb = {0};
+   GLuint i;
    float (*vertices)[2][4];  /**< vertex pos + color */
 
+   vb.stride = 8 * sizeof(float);
+
    if (u_upload_alloc(st->uploader, 0, 4 * sizeof(vertices[0]),
-                      &offset, &vbuf, (void **) &vertices) != PIPE_OK) {
+                      &vb.buffer_offset, &vb.buffer,
+                      (void **) &vertices) != PIPE_OK) {
       return;
    }
 
@@ -174,16 +199,10 @@ draw_quad(struct st_context *st,
    u_upload_unmap(st->uploader);
 
    /* draw */
-   util_draw_vertex_buffer(pipe,
-                           st->cso_context,
-                           vbuf,
-                           cso_get_aux_vertex_buffer_slot(st->cso_context),
-                           offset,
-                           PIPE_PRIM_TRIANGLE_FAN,
-                           4,  /* verts */
-                           2); /* attribs/vert */
-
-   pipe_resource_reference(&vbuf, NULL);
+   cso_set_vertex_buffers(cso, cso_get_aux_vertex_buffer_slot(cso), 1, &vb);
+   cso_draw_arrays_instanced(cso, PIPE_PRIM_TRIANGLE_FAN, 0, 4,
+                             0, num_instances);
+   pipe_resource_reference(&vb.buffer, NULL);
 }
 
 
@@ -194,8 +213,7 @@ draw_quad(struct st_context *st,
  * ctx->DrawBuffer->_X/Ymin/max fields.
  */
 static void
-clear_with_quad(struct gl_context *ctx,
-                GLboolean color, GLboolean depth, GLboolean stencil)
+clear_with_quad(struct gl_context *ctx, unsigned clear_buffers)
 {
    struct st_context *st = st_context(ctx);
    const struct gl_framebuffer *fb = ctx->DrawBuffer;
@@ -205,7 +223,8 @@ clear_with_quad(struct gl_context *ctx,
    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;
-   union pipe_color_union clearColor;
+   unsigned num_layers =
+      util_framebuffer_get_num_layers(&st->state.framebuffer);
 
    /*
    printf("%s %s%s%s %f,%f %f,%f\n", __FUNCTION__, 
@@ -233,7 +252,7 @@ clear_with_quad(struct gl_context *ctx,
    {
       struct pipe_blend_state blend;
       memset(&blend, 0, sizeof(blend));
-      if (color) {
+      if (clear_buffers & PIPE_CLEAR_COLOR) {
          int num_buffers = ctx->Extensions.EXT_draw_buffers2 ?
                            ctx->DrawBuffer->_NumColorDrawBuffers : 1;
          int i;
@@ -241,6 +260,9 @@ clear_with_quad(struct gl_context *ctx,
          blend.independent_blend_enable = num_buffers > 1;
 
          for (i = 0; i < num_buffers; i++) {
+            if (!(clear_buffers & (PIPE_CLEAR_COLOR0 << i)))
+               continue;
+
             if (ctx->Color.ColorMask[i][0])
                blend.rt[i].colormask |= PIPE_MASK_R;
             if (ctx->Color.ColorMask[i][1])
@@ -261,13 +283,13 @@ clear_with_quad(struct gl_context *ctx,
    {
       struct pipe_depth_stencil_alpha_state depth_stencil;
       memset(&depth_stencil, 0, sizeof(depth_stencil));
-      if (depth) {
+      if (clear_buffers & PIPE_CLEAR_DEPTH) {
          depth_stencil.depth.enabled = 1;
          depth_stencil.depth.writemask = 1;
          depth_stencil.depth.func = PIPE_FUNC_ALWAYS;
       }
 
-      if (stencil) {
+      if (clear_buffers & PIPE_CLEAR_STENCIL) {
          struct pipe_stencil_ref stencil_ref;
          memset(&stencil_ref, 0, sizeof(stencil_ref));
          depth_stencil.stencil[0].enabled = 1;
@@ -305,21 +327,20 @@ clear_with_quad(struct gl_context *ctx,
    }
 
    set_fragment_shader(st);
-   set_vertex_shader(st);
    cso_set_geometry_shader_handle(st->cso_context, NULL);
 
-   if (ctx->DrawBuffer->_ColorDrawBuffers[0]) {
-      struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];
-      GLboolean is_integer = _mesa_is_enum_format_integer(rb->InternalFormat);
+   if (num_layers > 1)
+      set_vertex_shader_layered(st);
+   else
+      set_vertex_shader(st);
 
-      st_translate_color(&ctx->Color.ClearColor,
-                         &clearColor,
-                         ctx->DrawBuffer->_ColorDrawBuffers[0]->_BaseFormat,
-                         is_integer);
-   }
+   /* We can't translate the clear color to the colorbuffer format,
+    * because different colorbuffers may have different formats.
+    */
 
    /* draw quad matching scissor rect */
-   draw_quad(st, x0, y0, x1, y1, (GLfloat) ctx->Depth.Clear, &clearColor);
+   draw_quad(st, x0, y0, x1, y1, (GLfloat) ctx->Depth.Clear, num_layers,
+             (union pipe_color_union*)&ctx->Color.ClearColor);
 
    /* Restore pipe state */
    cso_restore_blend(st->cso_context);
@@ -346,8 +367,21 @@ is_scissor_enabled(struct gl_context *ctx, struct gl_renderbuffer *rb)
    return ctx->Scissor.Enabled &&
           (ctx->Scissor.X > 0 ||
            ctx->Scissor.Y > 0 ||
-           ctx->Scissor.Width < rb->Width ||
-           ctx->Scissor.Height < rb->Height);
+           (unsigned) ctx->Scissor.Width < rb->Width ||
+           (unsigned) ctx->Scissor.Height < rb->Height);
+}
+
+
+/**
+ * Return if all of the color channels are masked.
+ */
+static INLINE GLboolean
+is_color_disabled(struct gl_context *ctx, int i)
+{
+   return !ctx->Color.ColorMask[i][0] &&
+          !ctx->Color.ColorMask[i][1] &&
+          !ctx->Color.ColorMask[i][2] &&
+          !ctx->Color.ColorMask[i][3];
 }
 
 
@@ -408,11 +442,14 @@ st_Clear(struct gl_context *ctx, GLbitfield mask)
             if (!strb || !strb->surface)
                continue;
 
+            if (is_color_disabled(ctx, colormask_index))
+               continue;
+
             if (is_scissor_enabled(ctx, rb) ||
                 is_color_masked(ctx, colormask_index))
-               quad_buffers |= PIPE_CLEAR_COLOR;
+               quad_buffers |= PIPE_CLEAR_COLOR0 << i;
             else
-               clear_buffers |= PIPE_CLEAR_COLOR;
+               clear_buffers |= PIPE_CLEAR_COLOR0 << i;
          }
       }
    }
@@ -445,24 +482,13 @@ st_Clear(struct gl_context *ctx, GLbitfield mask)
     */
    if (quad_buffers) {
       quad_buffers |= clear_buffers;
-      clear_with_quad(ctx,
-                      quad_buffers & PIPE_CLEAR_COLOR,
-                      quad_buffers & PIPE_CLEAR_DEPTH,
-                      quad_buffers & PIPE_CLEAR_STENCIL);
+      clear_with_quad(ctx, quad_buffers);
    } else if (clear_buffers) {
-      union pipe_color_union clearColor;
-
-      if (ctx->DrawBuffer->_ColorDrawBuffers[0]) {
-         struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];
-         GLboolean is_integer = _mesa_is_enum_format_integer(rb->InternalFormat);
-
-         st_translate_color(&ctx->Color.ClearColor,
-                            &clearColor,
-                           ctx->DrawBuffer->_ColorDrawBuffers[0]->_BaseFormat,
-                           is_integer);
-      }
-
-      st->pipe->clear(st->pipe, clear_buffers, &clearColor,
+      /* We can't translate the clear color to the colorbuffer format,
+       * because different colorbuffers may have different formats.
+       */
+      st->pipe->clear(st->pipe, clear_buffers,
+                      (union pipe_color_union*)&ctx->Color.ClearColor,
                       ctx->Depth.Clear, ctx->Stencil.Clear);
    }
    if (mask & BUFFER_BIT_ACCUM)