예제 #1
0
/**
 * Polygon stipple offset packet
 */
static void
upload_polygon_stipple_offset(struct brw_context *brw)
{
   struct gl_context *ctx = &brw->ctx;

   /* _NEW_POLYGON */
   if (!ctx->Polygon.StippleFlag)
      return;

   BEGIN_BATCH(2);
   OUT_BATCH(_3DSTATE_POLY_STIPPLE_OFFSET << 16 | (2-2));

   /* _NEW_BUFFERS
    *
    * If we're drawing to a system window we have to invert the Y axis
    * in order to match the OpenGL pixel coordinate system, and our
    * offset must be matched to the window position.  If we're drawing
    * to a user-created FBO then our native pixel coordinate system
    * works just fine, and there's no window system to worry about.
    */
   if (_mesa_is_winsys_fbo(ctx->DrawBuffer))
      OUT_BATCH((32 - (_mesa_geometric_height(ctx->DrawBuffer) & 31)) & 31);
   else
      OUT_BATCH(0);
   ADVANCE_BATCH();
}
예제 #2
0
/**
 * Scissor depends on the scissor box, and the framebuffer dimensions.
 */
static void
update_scissor( struct st_context *st )
{
    struct pipe_scissor_state scissor[PIPE_MAX_VIEWPORTS];
    const struct gl_context *ctx = st->ctx;
    const struct gl_framebuffer *fb = ctx->DrawBuffer;
    const unsigned int fb_width = _mesa_geometric_width(fb);
    const unsigned int fb_height = _mesa_geometric_height(fb);
    GLint miny, maxy;
    unsigned i;
    bool changed = false;

    for (i = 0 ; i < ctx->Const.MaxViewports; i++) {
        scissor[i].minx = 0;
        scissor[i].miny = 0;
        scissor[i].maxx = fb_width;
        scissor[i].maxy = fb_height;

        if (ctx->Scissor.EnableFlags & (1 << i)) {
            /* need to be careful here with xmax or ymax < 0 */
            GLint xmax = MAX2(0, ctx->Scissor.ScissorArray[i].X + ctx->Scissor.ScissorArray[i].Width);
            GLint ymax = MAX2(0, ctx->Scissor.ScissorArray[i].Y + ctx->Scissor.ScissorArray[i].Height);

            if (ctx->Scissor.ScissorArray[i].X > (GLint)scissor[i].minx)
                scissor[i].minx = ctx->Scissor.ScissorArray[i].X;
            if (ctx->Scissor.ScissorArray[i].Y > (GLint)scissor[i].miny)
                scissor[i].miny = ctx->Scissor.ScissorArray[i].Y;

            if (xmax < (GLint) scissor[i].maxx)
                scissor[i].maxx = xmax;
            if (ymax < (GLint) scissor[i].maxy)
                scissor[i].maxy = ymax;

            /* check for null space */
            if (scissor[i].minx >= scissor[i].maxx || scissor[i].miny >= scissor[i].maxy)
                scissor[i].minx = scissor[i].miny = scissor[i].maxx = scissor[i].maxy = 0;
        }

        /* Now invert Y if needed.
         * Gallium drivers use the convention Y=0=top for surfaces.
         */
        if (st_fb_orientation(fb) == Y_0_TOP) {
            miny = fb->Height - scissor[i].maxy;
            maxy = fb->Height - scissor[i].miny;
            scissor[i].miny = miny;
            scissor[i].maxy = maxy;
        }

        if (memcmp(&scissor[i], &st->state.scissor[i], sizeof(scissor[0])) != 0) {
            /* state has changed */
            st->state.scissor[i] = scissor[i];  /* struct copy */
            changed = true;
        }
    }
    if (changed)
        st->pipe->set_scissor_states(st->pipe, 0, ctx->Const.MaxViewports, scissor); /* activate */
}
예제 #3
0
/* Constant single cliprect for framebuffer object or DRI2 drawing */
static void
upload_drawing_rect(struct brw_context *brw)
{
   struct gl_context *ctx = &brw->ctx;
   const struct gl_framebuffer *fb = ctx->DrawBuffer;
   const unsigned int fb_width = _mesa_geometric_width(fb);
   const unsigned int fb_height = _mesa_geometric_height(fb);

   BEGIN_BATCH(4);
   OUT_BATCH(_3DSTATE_DRAWING_RECTANGLE << 16 | (4 - 2));
   OUT_BATCH(0); /* xmin, ymin */
   OUT_BATCH(((fb_width - 1) & 0xffff) | ((fb_height - 1) << 16));
   OUT_BATCH(0);
   ADVANCE_BATCH();
}
예제 #4
0
static void
gen6_upload_sf_vp(struct brw_context *brw)
{
   struct gl_context *ctx = &brw->ctx;
   struct gen6_sf_viewport *sfv;
   GLfloat y_scale, y_bias;
   const bool render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer);

   sfv = brw_state_batch(brw, AUB_TRACE_SF_VP_STATE,
                         sizeof(*sfv) * ctx->Const.MaxViewports,
                         32, &brw->sf.vp_offset);
   memset(sfv, 0, sizeof(*sfv) * ctx->Const.MaxViewports);

   /* _NEW_BUFFERS */
   if (render_to_fbo) {
      y_scale = 1.0;
      y_bias = 0.0;
   } else {
      y_scale = -1.0;
      y_bias = (float)_mesa_geometric_height(ctx->DrawBuffer);
   }

   for (unsigned i = 0; i < ctx->Const.MaxViewports; i++) {
      float scale[3], translate[3];

      /* _NEW_VIEWPORT */
      _mesa_get_viewport_xform(ctx, i, scale, translate);
      sfv[i].m00 = scale[0];
      sfv[i].m11 = scale[1] * y_scale;
      sfv[i].m22 = scale[2];
      sfv[i].m30 = translate[0];
      sfv[i].m31 = translate[1] * y_scale + y_bias;
      sfv[i].m32 = translate[2];

   }

   brw->ctx.NewDriverState |= BRW_NEW_SF_VP;
}
예제 #5
0
static void
gen7_upload_sf_clip_viewport(struct brw_context *brw)
{
   struct gl_context *ctx = &brw->ctx;
   GLfloat y_scale, y_bias;
   const bool render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer);
   struct gen7_sf_clip_viewport *vp;

   /* BRW_NEW_VIEWPORT_COUNT */
   const unsigned viewport_count = brw->clip.viewport_count;

   vp = brw_state_batch(brw, AUB_TRACE_SF_VP_STATE,
                        sizeof(*vp) * viewport_count, 64,
                        &brw->sf.vp_offset);
   /* Also assign to clip.vp_offset in case something uses it. */
   brw->clip.vp_offset = brw->sf.vp_offset;

   /* _NEW_BUFFERS */
   if (render_to_fbo) {
      y_scale = 1.0;
      y_bias = 0.0;
   } else {
      y_scale = -1.0;
      y_bias = (float)_mesa_geometric_height(ctx->DrawBuffer);
   }

   for (unsigned i = 0; i < viewport_count; i++) {
      float scale[3], translate[3];
      _mesa_get_viewport_xform(ctx, i, scale, translate);

      /* According to the "Vertex X,Y Clamping and Quantization" section of
       * the Strips and Fans documentation, objects must not have a
       * screen-space extents of over 8192 pixels, or they may be
       * mis-rasterized.  The maximum screen space coordinates of a small
       * object may larger, but we have no way to enforce the object size
       * other than through clipping.
       *
       * If you're surprised that we set clip to -gbx to +gbx and it seems
       * like we'll end up with 16384 wide, note that for a 8192-wide render
       * target, we'll end up with a normal (-1, 1) clip volume that just
       * covers the drawable.
       */
      const float maximum_guardband_extent = 8192;
      const float gbx = maximum_guardband_extent / ctx->ViewportArray[i].Width;
      const float gby = maximum_guardband_extent / ctx->ViewportArray[i].Height;

      vp[i].guardband.xmin = -gbx;
      vp[i].guardband.xmax = gbx;
      vp[i].guardband.ymin = -gby;
      vp[i].guardband.ymax = gby;

      /* _NEW_VIEWPORT */
      vp[i].viewport.m00 = scale[0];
      vp[i].viewport.m11 = scale[1] * y_scale;
      vp[i].viewport.m22 = scale[2];
      vp[i].viewport.m30 = translate[0];
      vp[i].viewport.m31 = translate[1] * y_scale + y_bias;
      vp[i].viewport.m32 = translate[2];
   }

   BEGIN_BATCH(2);
   OUT_BATCH(_3DSTATE_VIEWPORT_STATE_POINTERS_SF_CL << 16 | (2 - 2));
   OUT_BATCH(brw->sf.vp_offset);
   ADVANCE_BATCH();
}
예제 #6
0
파일: brw_wm.c 프로젝트: aphogat/mesa
static void
brw_wm_populate_key(struct brw_context *brw, struct brw_wm_prog_key *key)
{
   struct gl_context *ctx = &brw->ctx;
   /* BRW_NEW_FRAGMENT_PROGRAM */
   const struct brw_fragment_program *fp =
      (struct brw_fragment_program *) brw->fragment_program;
   const struct gl_program *prog = (struct gl_program *) brw->fragment_program;
   GLuint lookup = 0;
   GLuint line_aa;
   bool program_uses_dfdy = fp->program.UsesDFdy;
   const bool multisample_fbo = _mesa_geometric_samples(ctx->DrawBuffer) > 1;

   memset(key, 0, sizeof(*key));

   /* Build the index for table lookup
    */
   if (brw->gen < 6) {
      /* _NEW_COLOR */
      if (fp->program.UsesKill || ctx->Color.AlphaEnabled)
	 lookup |= IZ_PS_KILL_ALPHATEST_BIT;

      if (fp->program.Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH))
	 lookup |= IZ_PS_COMPUTES_DEPTH_BIT;

      /* _NEW_DEPTH */
      if (ctx->Depth.Test)
	 lookup |= IZ_DEPTH_TEST_ENABLE_BIT;

      if (ctx->Depth.Test && ctx->Depth.Mask) /* ?? */
	 lookup |= IZ_DEPTH_WRITE_ENABLE_BIT;

      /* _NEW_STENCIL | _NEW_BUFFERS */
      if (ctx->Stencil._Enabled) {
	 lookup |= IZ_STENCIL_TEST_ENABLE_BIT;

	 if (ctx->Stencil.WriteMask[0] ||
	     ctx->Stencil.WriteMask[ctx->Stencil._BackFace])
	    lookup |= IZ_STENCIL_WRITE_ENABLE_BIT;
      }
      key->iz_lookup = lookup;
   }

   line_aa = AA_NEVER;

   /* _NEW_LINE, _NEW_POLYGON, BRW_NEW_REDUCED_PRIMITIVE */
   if (ctx->Line.SmoothFlag) {
      if (brw->reduced_primitive == GL_LINES) {
	 line_aa = AA_ALWAYS;
      }
      else if (brw->reduced_primitive == GL_TRIANGLES) {
	 if (ctx->Polygon.FrontMode == GL_LINE) {
	    line_aa = AA_SOMETIMES;

	    if (ctx->Polygon.BackMode == GL_LINE ||
		(ctx->Polygon.CullFlag &&
		 ctx->Polygon.CullFaceMode == GL_BACK))
	       line_aa = AA_ALWAYS;
	 }
	 else if (ctx->Polygon.BackMode == GL_LINE) {
	    line_aa = AA_SOMETIMES;

	    if ((ctx->Polygon.CullFlag &&
		 ctx->Polygon.CullFaceMode == GL_FRONT))
	       line_aa = AA_ALWAYS;
	 }
      }
   }

   key->line_aa = line_aa;

   /* _NEW_HINT */
   key->high_quality_derivatives =
      ctx->Hint.FragmentShaderDerivative == GL_NICEST;

   if (brw->gen < 6)
      key->stats_wm = brw->stats_wm;

   /* _NEW_LIGHT */
   key->flat_shade = (ctx->Light.ShadeModel == GL_FLAT);

   /* _NEW_FRAG_CLAMP | _NEW_BUFFERS */
   key->clamp_fragment_color = ctx->Color._ClampFragmentColor;

   /* _NEW_TEXTURE */
   brw_populate_sampler_prog_key_data(ctx, prog, brw->wm.base.sampler_count,
                                      &key->tex);

   /* _NEW_BUFFERS */
   /*
    * Include the draw buffer origin and height so that we can calculate
    * fragment position values relative to the bottom left of the drawable,
    * from the incoming screen origin relative position we get as part of our
    * payload.
    *
    * This is only needed for the WM_WPOSXY opcode when the fragment program
    * uses the gl_FragCoord input.
    *
    * We could avoid recompiling by including this as a constant referenced by
    * our program, but if we were to do that it would also be nice to handle
    * getting that constant updated at batchbuffer submit time (when we
    * hold the lock and know where the buffer really is) rather than at emit
    * time when we don't hold the lock and are just guessing.  We could also
    * just avoid using this as key data if the program doesn't use
    * fragment.position.
    *
    * For DRI2 the origin_x/y will always be (0,0) but we still need the
    * drawable height in order to invert the Y axis.
    */
   if (fp->program.Base.InputsRead & VARYING_BIT_POS) {
      key->drawable_height = _mesa_geometric_height(ctx->DrawBuffer);
   }

   if ((fp->program.Base.InputsRead & VARYING_BIT_POS) || program_uses_dfdy) {
      key->render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer);
   }

   /* _NEW_BUFFERS */
   key->nr_color_regions = ctx->DrawBuffer->_NumColorDrawBuffers;

   /* _NEW_MULTISAMPLE, _NEW_COLOR, _NEW_BUFFERS */
   key->replicate_alpha = ctx->DrawBuffer->_NumColorDrawBuffers > 1 &&
      (ctx->Multisample.SampleAlphaToCoverage || ctx->Color.AlphaEnabled);

   /* _NEW_BUFFERS _NEW_MULTISAMPLE */
   /* Ignore sample qualifier while computing this flag. */
   key->persample_shading =
      _mesa_get_min_invocations_per_fragment(ctx, &fp->program, true) > 1;
   if (key->persample_shading)
      key->persample_2x = _mesa_geometric_samples(ctx->DrawBuffer) == 2;

   key->compute_pos_offset =
      _mesa_get_min_invocations_per_fragment(ctx, &fp->program, false) > 1 &&
      fp->program.Base.SystemValuesRead & SYSTEM_BIT_SAMPLE_POS;

   key->compute_sample_id =
      multisample_fbo &&
      ctx->Multisample.Enabled &&
      (fp->program.Base.SystemValuesRead & SYSTEM_BIT_SAMPLE_ID);

   /* BRW_NEW_VUE_MAP_GEOM_OUT */
   if (brw->gen < 6 || _mesa_bitcount_64(fp->program.Base.InputsRead &
                                         BRW_FS_VARYING_INPUT_MASK) > 16)
      key->input_slots_valid = brw->vue_map_geom_out.slots_valid;


   /* _NEW_COLOR | _NEW_BUFFERS */
   /* Pre-gen6, the hardware alpha test always used each render
    * target's alpha to do alpha test, as opposed to render target 0's alpha
    * like GL requires.  Fix that by building the alpha test into the
    * shader, and we'll skip enabling the fixed function alpha test.
    */
   if (brw->gen < 6 && ctx->DrawBuffer->_NumColorDrawBuffers > 1 &&
       ctx->Color.AlphaEnabled) {
      key->alpha_test_func = ctx->Color.AlphaFunc;
      key->alpha_test_ref = ctx->Color.AlphaRef;
   }

   /* The unique fragment program ID */
   key->program_string_id = fp->id;
}
예제 #7
0
static void
upload_clip_state(struct brw_context *brw)
{
   struct gl_context *ctx = &brw->ctx;
   /* BRW_NEW_META_IN_PROGRESS */
   uint32_t dw1 = brw->meta_in_progress ? 0 : GEN6_CLIP_STATISTICS_ENABLE;
   uint32_t dw2 = 0;

   /* _NEW_BUFFERS */
   struct gl_framebuffer *fb = ctx->DrawBuffer;

   /* BRW_NEW_FS_PROG_DATA */
   if (brw->wm.prog_data->barycentric_interp_modes &
       BRW_WM_NONPERSPECTIVE_BARYCENTRIC_BITS) {
      dw2 |= GEN6_CLIP_NON_PERSPECTIVE_BARYCENTRIC_ENABLE;
   }

   dw1 |= brw->vs.prog_data->base.cull_distance_mask;

   if (brw->gen >= 7)
      dw1 |= GEN7_CLIP_EARLY_CULL;

   if (brw->gen == 7) {
      /* _NEW_POLYGON */
      if (ctx->Polygon._FrontBit == _mesa_is_user_fbo(fb))
         dw1 |= GEN7_CLIP_WINDING_CCW;

      if (ctx->Polygon.CullFlag) {
         switch (ctx->Polygon.CullFaceMode) {
         case GL_FRONT:
            dw1 |= GEN7_CLIP_CULLMODE_FRONT;
            break;
         case GL_BACK:
            dw1 |= GEN7_CLIP_CULLMODE_BACK;
            break;
         case GL_FRONT_AND_BACK:
            dw1 |= GEN7_CLIP_CULLMODE_BOTH;
            break;
         default:
            unreachable("Should not get here: invalid CullFlag");
         }
      } else {
         dw1 |= GEN7_CLIP_CULLMODE_NONE;
      }
   }

   if (brw->gen < 8 && !ctx->Transform.DepthClamp)
      dw2 |= GEN6_CLIP_Z_TEST;

   /* _NEW_LIGHT */
   if (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION) {
      dw2 |=
	 (0 << GEN6_CLIP_TRI_PROVOKE_SHIFT) |
	 (1 << GEN6_CLIP_TRIFAN_PROVOKE_SHIFT) |
	 (0 << GEN6_CLIP_LINE_PROVOKE_SHIFT);
   } else {
      dw2 |=
	 (2 << GEN6_CLIP_TRI_PROVOKE_SHIFT) |
	 (2 << GEN6_CLIP_TRIFAN_PROVOKE_SHIFT) |
	 (1 << GEN6_CLIP_LINE_PROVOKE_SHIFT);
   }

   /* _NEW_TRANSFORM */
   dw2 |= (ctx->Transform.ClipPlanesEnabled <<
           GEN6_USER_CLIP_CLIP_DISTANCES_SHIFT);
   if (ctx->Transform.ClipDepthMode == GL_ZERO_TO_ONE)
      dw2 |= GEN6_CLIP_API_D3D;
   else
      dw2 |= GEN6_CLIP_API_OGL;

   dw2 |= GEN6_CLIP_GB_TEST;

   /* We need to disable guardband clipping if the guardband (which we always
    * program to the maximum screen-space bounding box of 8K x 8K) will be
    * smaller than the viewport.
    *
    * Closely examining the clip determination formulas in the documentation
    * reveals that objects will be discarded entirely if they're outside the
    * (small) guardband, even if they're within the (large) viewport:
    *
    *     TR = TR_GB || TR_VPXY || TR_VPZ || TR_UC || TR_NEGW
    *     TA   = !TR && TA_GB && TA_VPZ && TA_NEGW
    *     MC = !(TA || TR)
    *
    * (TA is "Trivial Accept", TR is "Trivial Reject", MC is "Must Clip".)
    *
    * Disabling guardband clipping removes the TR_GB condition, which means
    * they'll be considered MC ("Must Clip") unless they're rejected for
    * some other reason.
    *
    * Note that there is no TA_VPXY condition.  If there were, objects entirely
    * inside a 16384x16384 viewport would be trivially accepted, breaking the
    * "objects must have a screenspace bounding box not exceeding 8K in the X
    * or Y direction" restriction.  Instead, they're clipped.
    */
   for (unsigned i = 0; i < ctx->Const.MaxViewports; i++) {
      if (ctx->ViewportArray[i].Width > 8192 ||
          ctx->ViewportArray[i].Height > 8192) {
         dw2 &= ~GEN6_CLIP_GB_TEST;
         break;
      }
   }

   /* If the viewport dimensions are smaller than the drawable dimensions,
    * we have to disable guardband clipping prior to Gen8.  We always program
    * the guardband to a fixed size, which is almost always larger than the
    * viewport.  Any geometry which intersects the viewport but lies within
    * the guardband would bypass the 3D clipping stage, so it wouldn't be
    * clipped to the viewport.  Rendering would happen beyond the viewport,
    * but still inside the drawable.
    *
    * Gen8+ introduces a viewport extents test which restricts rendering to
    * the viewport, so we can ignore this restriction.
    */
   if (brw->gen < 8) {
      const float fb_width = (float)_mesa_geometric_width(fb);
      const float fb_height = (float)_mesa_geometric_height(fb);

      for (unsigned i = 0; i < ctx->Const.MaxViewports; i++) {
         if (ctx->ViewportArray[i].X != 0 ||
             ctx->ViewportArray[i].Y != 0 ||
             ctx->ViewportArray[i].Width != fb_width ||
             ctx->ViewportArray[i].Height != fb_height) {
            dw2 &= ~GEN6_CLIP_GB_TEST;
            break;
         }
      }
   }

   /* BRW_NEW_RASTERIZER_DISCARD */
   if (ctx->RasterDiscard) {
      dw2 |= GEN6_CLIP_MODE_REJECT_ALL;
      if (brw->gen == 6) {
         perf_debug("Rasterizer discard is currently implemented via the "
                    "clipper; having the GS not write primitives would "
                    "likely be faster.\n");
      }
   }

   uint32_t enable;
   if (brw->primitive == _3DPRIM_RECTLIST)
      enable = 0;
   else
      enable = GEN6_CLIP_ENABLE;

   if (!is_drawing_points(brw) && !is_drawing_lines(brw))
      dw2 |= GEN6_CLIP_XY_TEST;

   /* BRW_NEW_VUE_MAP_GEOM_OUT */
   const int max_vp_index =
      (brw->vue_map_geom_out.slots_valid & VARYING_BIT_VIEWPORT) != 0 ?
      ctx->Const.MaxViewports : 1;

   BEGIN_BATCH(4);
   OUT_BATCH(_3DSTATE_CLIP << 16 | (4 - 2));
   OUT_BATCH(dw1);
   OUT_BATCH(enable |
	     GEN6_CLIP_MODE_NORMAL |
	     dw2);
   OUT_BATCH(U_FIXED(0.125, 3) << GEN6_CLIP_MIN_POINT_WIDTH_SHIFT |
             U_FIXED(255.875, 3) << GEN6_CLIP_MAX_POINT_WIDTH_SHIFT |
             (_mesa_geometric_layers(fb) > 0 ? 0 : GEN6_CLIP_FORCE_ZERO_RTAINDEX) |
             ((max_vp_index - 1) & GEN6_CLIP_MAX_VP_INDEX_MASK));
   ADVANCE_BATCH();
}
예제 #8
0
/**
 * Update framebuffer state (color, depth, stencil, etc. buffers)
 */
void
st_update_framebuffer_state( struct st_context *st )
{
   struct pipe_framebuffer_state framebuffer;
   struct gl_framebuffer *fb = st->ctx->DrawBuffer;
   struct st_renderbuffer *strb;
   GLuint i;

   st_flush_bitmap_cache(st);
   st_invalidate_readpix_cache(st);

   st->state.fb_orientation = st_fb_orientation(fb);

   /**
    * Quantize the derived default number of samples:
    *
    * A query to the driver of supported MSAA values the
    * hardware supports is done as to legalize the number
    * of application requested samples, NumSamples.
    * See commit eb9cf3c for more information.
    */
   fb->DefaultGeometry._NumSamples =
      framebuffer_quantize_num_samples(st, fb->DefaultGeometry.NumSamples);

   framebuffer.width  = _mesa_geometric_width(fb);
   framebuffer.height = _mesa_geometric_height(fb);
   framebuffer.samples = _mesa_geometric_samples(fb);
   framebuffer.layers = _mesa_geometric_layers(fb);

   /* Examine Mesa's ctx->DrawBuffer->_ColorDrawBuffers state
    * to determine which surfaces to draw to
    */
   framebuffer.nr_cbufs = fb->_NumColorDrawBuffers;

   for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
      framebuffer.cbufs[i] = NULL;
      strb = st_renderbuffer(fb->_ColorDrawBuffers[i]);

      if (strb) {
         if (strb->is_rtt || (strb->texture &&
             _mesa_get_format_color_encoding(strb->Base.Format) == GL_SRGB)) {
            /* rendering to a GL texture, may have to update surface */
            st_update_renderbuffer_surface(st, strb);
         }

         if (strb->surface) {
            framebuffer.cbufs[i] = strb->surface;
            update_framebuffer_size(&framebuffer, strb->surface);
         }
         strb->defined = GL_TRUE; /* we'll be drawing something */
      }
   }

   for (i = framebuffer.nr_cbufs; i < PIPE_MAX_COLOR_BUFS; i++) {
      framebuffer.cbufs[i] = NULL;
   }

   /* Remove trailing GL_NONE draw buffers. */
   while (framebuffer.nr_cbufs &&
          !framebuffer.cbufs[framebuffer.nr_cbufs-1]) {
      framebuffer.nr_cbufs--;
   }

   /*
    * Depth/Stencil renderbuffer/surface.
    */
   strb = st_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer);
   if (!strb)
      strb = st_renderbuffer(fb->Attachment[BUFFER_STENCIL].Renderbuffer);

   if (strb) {
      if (strb->is_rtt) {
         /* rendering to a GL texture, may have to update surface */
         st_update_renderbuffer_surface(st, strb);
      }
      framebuffer.zsbuf = strb->surface;
      update_framebuffer_size(&framebuffer, strb->surface);
   }
   else
      framebuffer.zsbuf = NULL;

#ifdef DEBUG
   /* Make sure the resource binding flags were set properly */
   for (i = 0; i < framebuffer.nr_cbufs; i++) {
      assert(!framebuffer.cbufs[i] ||
             framebuffer.cbufs[i]->texture->bind & PIPE_BIND_RENDER_TARGET);
   }
   if (framebuffer.zsbuf) {
      assert(framebuffer.zsbuf->texture->bind & PIPE_BIND_DEPTH_STENCIL);
   }
#endif

   if (framebuffer.width == USHRT_MAX)
      framebuffer.width = 0;
   if (framebuffer.height == USHRT_MAX)
      framebuffer.height = 0;

   cso_set_framebuffer(st->cso_context, &framebuffer);

   st->state.fb_width = framebuffer.width;
   st->state.fb_height = framebuffer.height;
   st->state.fb_num_samples = util_framebuffer_get_num_samples(&framebuffer);
   st->state.fb_num_layers = util_framebuffer_get_num_layers(&framebuffer);
   st->state.fb_num_cb = framebuffer.nr_cbufs;
}
예제 #9
0
static void
st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z,
           GLfloat width, GLfloat height)
{
   struct st_context *st = ctx->st;
   struct pipe_context *pipe = st->pipe;
   struct cso_context *cso = st->cso_context;
   struct pipe_resource *vbuffer = NULL;
   GLuint i, numTexCoords, numAttribs;
   GLboolean emitColor;
   uint semantic_names[2 + MAX_TEXTURE_UNITS];
   uint semantic_indexes[2 + MAX_TEXTURE_UNITS];
   struct pipe_vertex_element velements[2 + MAX_TEXTURE_UNITS];
   unsigned offset;

   st_flush_bitmap_cache(st);
   st_invalidate_readpix_cache(st);

   st_validate_state(st, ST_PIPELINE_RENDER);

   /* determine if we need vertex color */
   if (ctx->FragmentProgram._Current->info.inputs_read & VARYING_BIT_COL0)
      emitColor = GL_TRUE;
   else
      emitColor = GL_FALSE;

   /* determine how many enabled sets of texcoords */
   numTexCoords = 0;
   for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
      if (ctx->Texture.Unit[i]._Current &&
          ctx->Texture.Unit[i]._Current->Target == GL_TEXTURE_2D) {
         numTexCoords++;
      }
   }

   /* total number of attributes per vertex */
   numAttribs = 1 + emitColor + numTexCoords;

   /* load vertex buffer */
   {
#define SET_ATTRIB(VERT, ATTR, X, Y, Z, W)                              \
      do {                                                              \
         GLuint k = (((VERT) * numAttribs + (ATTR)) * 4);               \
         assert(k < 4 * 4 * numAttribs);                                \
         vbuf[k + 0] = X;                                               \
         vbuf[k + 1] = Y;                                               \
         vbuf[k + 2] = Z;                                               \
         vbuf[k + 3] = W;                                               \
      } while (0)

      const GLfloat x0 = x, y0 = y, x1 = x + width, y1 = y + height;
      GLfloat *vbuf = NULL;
      GLuint tex_attr;

      u_upload_alloc(pipe->stream_uploader, 0,
                     numAttribs * 4 * 4 * sizeof(GLfloat), 4,
                     &offset, &vbuffer, (void **) &vbuf);
      if (!vbuffer) {
         return;
      }

      z = CLAMP(z, 0.0f, 1.0f);

      /* positions (in clip coords) */
      {
         const struct gl_framebuffer *fb = ctx->DrawBuffer;
         const GLfloat fb_width = (GLfloat)_mesa_geometric_width(fb);
         const GLfloat fb_height = (GLfloat)_mesa_geometric_height(fb);

         const GLfloat clip_x0 = (GLfloat)(x0 / fb_width * 2.0 - 1.0);
         const GLfloat clip_y0 = (GLfloat)(y0 / fb_height * 2.0 - 1.0);
         const GLfloat clip_x1 = (GLfloat)(x1 / fb_width * 2.0 - 1.0);
         const GLfloat clip_y1 = (GLfloat)(y1 / fb_height * 2.0 - 1.0);

         SET_ATTRIB(0, 0, clip_x0, clip_y0, z, 1.0f);   /* lower left */
         SET_ATTRIB(1, 0, clip_x1, clip_y0, z, 1.0f);   /* lower right */
         SET_ATTRIB(2, 0, clip_x1, clip_y1, z, 1.0f);   /* upper right */
         SET_ATTRIB(3, 0, clip_x0, clip_y1, z, 1.0f);   /* upper left */

         semantic_names[0] = TGSI_SEMANTIC_POSITION;
         semantic_indexes[0] = 0;
      }

      /* colors */
      if (emitColor) {
         const GLfloat *c = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
         SET_ATTRIB(0, 1, c[0], c[1], c[2], c[3]);
         SET_ATTRIB(1, 1, c[0], c[1], c[2], c[3]);
         SET_ATTRIB(2, 1, c[0], c[1], c[2], c[3]);
         SET_ATTRIB(3, 1, c[0], c[1], c[2], c[3]);
         semantic_names[1] = TGSI_SEMANTIC_COLOR;
         semantic_indexes[1] = 0;
         tex_attr = 2;
      }
      else {
         tex_attr = 1;
      }

      /* texcoords */
      for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
         if (ctx->Texture.Unit[i]._Current &&
             ctx->Texture.Unit[i]._Current->Target == GL_TEXTURE_2D) {
            struct gl_texture_object *obj = ctx->Texture.Unit[i]._Current;
            const struct gl_texture_image *img = _mesa_base_tex_image(obj);
            const GLfloat wt = (GLfloat) img->Width;
            const GLfloat ht = (GLfloat) img->Height;
            const GLfloat s0 = obj->CropRect[0] / wt;
            const GLfloat t0 = obj->CropRect[1] / ht;
            const GLfloat s1 = (obj->CropRect[0] + obj->CropRect[2]) / wt;
            const GLfloat t1 = (obj->CropRect[1] + obj->CropRect[3]) / ht;

            /*printf("crop texcoords: %g, %g .. %g, %g\n", s0, t0, s1, t1);*/
            SET_ATTRIB(0, tex_attr, s0, t0, 0.0f, 1.0f);  /* lower left */
            SET_ATTRIB(1, tex_attr, s1, t0, 0.0f, 1.0f);  /* lower right */
            SET_ATTRIB(2, tex_attr, s1, t1, 0.0f, 1.0f);  /* upper right */
            SET_ATTRIB(3, tex_attr, s0, t1, 0.0f, 1.0f);  /* upper left */

            semantic_names[tex_attr] = st->needs_texcoord_semantic ?
               TGSI_SEMANTIC_TEXCOORD : TGSI_SEMANTIC_GENERIC;
            /* XXX: should this use semantic index i instead of 0 ? */
            semantic_indexes[tex_attr] = 0;

            tex_attr++;
         }
      }

      u_upload_unmap(pipe->stream_uploader);

#undef SET_ATTRIB
   }

   cso_save_state(cso, (CSO_BIT_VIEWPORT |
                        CSO_BIT_STREAM_OUTPUTS |
                        CSO_BIT_VERTEX_SHADER |
                        CSO_BIT_TESSCTRL_SHADER |
                        CSO_BIT_TESSEVAL_SHADER |
                        CSO_BIT_GEOMETRY_SHADER |
                        CSO_BIT_VERTEX_ELEMENTS |
                        CSO_BIT_AUX_VERTEX_BUFFER_SLOT));

   {
      void *vs = lookup_shader(pipe, numAttribs,
                               semantic_names, semantic_indexes);
      cso_set_vertex_shader_handle(cso, vs);
   }
   cso_set_tessctrl_shader_handle(cso, NULL);
   cso_set_tesseval_shader_handle(cso, NULL);
   cso_set_geometry_shader_handle(cso, NULL);

   for (i = 0; i < numAttribs; i++) {
      velements[i].src_offset = i * 4 * sizeof(float);
      velements[i].instance_divisor = 0;
      velements[i].vertex_buffer_index = 0;
      velements[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
   }
   cso_set_vertex_elements(cso, numAttribs, velements);
   cso_set_stream_outputs(cso, 0, NULL, NULL);

   /* viewport state: viewport matching window dims */
   {
      const struct gl_framebuffer *fb = ctx->DrawBuffer;
      const GLboolean invert = (st_fb_orientation(fb) == Y_0_TOP);
      const GLfloat width = (GLfloat)_mesa_geometric_width(fb);
      const GLfloat height = (GLfloat)_mesa_geometric_height(fb);
      struct pipe_viewport_state vp;
      vp.scale[0] =  0.5f * width;
      vp.scale[1] = height * (invert ? -0.5f : 0.5f);
      vp.scale[2] = 1.0f;
      vp.translate[0] = 0.5f * width;
      vp.translate[1] = 0.5f * height;
      vp.translate[2] = 0.0f;
      cso_set_viewport(cso, &vp);
   }

   util_draw_vertex_buffer(pipe, cso, vbuffer,
			   cso_get_aux_vertex_buffer_slot(cso),
                           offset,  /* offset */
                           PIPE_PRIM_TRIANGLE_FAN,
                           4,  /* verts */
                           numAttribs); /* attribs/vert */

   pipe_resource_reference(&vbuffer, NULL);

   /* restore state */
   cso_restore_state(cso);
}
예제 #10
0
static void
brw_upload_clip_unit(struct brw_context *brw)
{
   struct gl_context *ctx = &brw->ctx;
   struct brw_clip_unit_state *clip;

   /* _NEW_BUFFERS */
   const struct gl_framebuffer *fb = ctx->DrawBuffer;
   const float fb_width = (float)_mesa_geometric_width(fb);
   const float fb_height = (float)_mesa_geometric_height(fb);

   upload_clip_vp(brw);

   clip = brw_state_batch(brw, AUB_TRACE_CLIP_STATE,
			  sizeof(*clip), 32, &brw->clip.state_offset);
   memset(clip, 0, sizeof(*clip));

   /* BRW_NEW_PROGRAM_CACHE | BRW_NEW_CLIP_PROG_DATA */
   clip->thread0.grf_reg_count = (ALIGN(brw->clip.prog_data->total_grf, 16) /
				 16 - 1);
   clip->thread0.kernel_start_pointer =
      brw_program_reloc(brw,
			brw->clip.state_offset +
			offsetof(struct brw_clip_unit_state, thread0),
			brw->clip.prog_offset +
			(clip->thread0.grf_reg_count << 1)) >> 6;

   clip->thread1.floating_point_mode = BRW_FLOATING_POINT_NON_IEEE_754;
   clip->thread1.single_program_flow = 1;

   clip->thread3.urb_entry_read_length = brw->clip.prog_data->urb_read_length;
   clip->thread3.const_urb_entry_read_length =
      brw->clip.prog_data->curb_read_length;

   /* BRW_NEW_CURBE_OFFSETS */
   clip->thread3.const_urb_entry_read_offset = brw->curbe.clip_start * 2;
   clip->thread3.dispatch_grf_start_reg = 1;
   clip->thread3.urb_entry_read_offset = 0;

   /* BRW_NEW_URB_FENCE */
   clip->thread4.nr_urb_entries = brw->urb.nr_clip_entries;
   clip->thread4.urb_entry_allocation_size = brw->urb.vsize - 1;
   /* If we have enough clip URB entries to run two threads, do so.
    */
   if (brw->urb.nr_clip_entries >= 10) {
      /* Half of the URB entries go to each thread, and it has to be an
       * even number.
       */
      assert(brw->urb.nr_clip_entries % 2 == 0);

      /* Although up to 16 concurrent Clip threads are allowed on Ironlake,
       * only 2 threads can output VUEs at a time.
       */
      if (brw->gen == 5)
         clip->thread4.max_threads = 16 - 1;
      else
         clip->thread4.max_threads = 2 - 1;
   } else {
      assert(brw->urb.nr_clip_entries >= 5);
      clip->thread4.max_threads = 1 - 1;
   }

   if (unlikely(INTEL_DEBUG & DEBUG_STATS))
      clip->thread4.stats_enable = 1;

   /* _NEW_TRANSFORM */
   if (brw->gen == 5 || brw->is_g4x)
      clip->clip5.userclip_enable_flags = ctx->Transform.ClipPlanesEnabled;
   else
      /* Up to 6 actual clip flags, plus the 7th for negative RHW workaround. */
      clip->clip5.userclip_enable_flags = (ctx->Transform.ClipPlanesEnabled & 0x3f) | 0x40;

   clip->clip5.userclip_must_clip = 1;

   /* enable guardband clipping if we can */
   if (ctx->ViewportArray[0].X == 0 &&
       ctx->ViewportArray[0].Y == 0 &&
       ctx->ViewportArray[0].Width == fb_width &&
       ctx->ViewportArray[0].Height == fb_height)
   {
      clip->clip5.guard_band_enable = 1;
      clip->clip6.clipper_viewport_state_ptr =
         (brw->batch.bo->offset64 + brw->clip.vp_offset) >> 5;

      /* emit clip viewport relocation */
      drm_intel_bo_emit_reloc(brw->batch.bo,
                              (brw->clip.state_offset +
                               offsetof(struct brw_clip_unit_state, clip6)),
                              brw->batch.bo, brw->clip.vp_offset,
                              I915_GEM_DOMAIN_INSTRUCTION, 0);
   }