Пример #1
0
/* Compare old and new render states and emit differences between them
 * to hardware.  Simplest implementation would be to emit the whole of
 * the "to" state.
 */
static enum pipe_error
emit_rss(struct svga_context *svga, unsigned dirty)
{
   struct svga_screen *screen = svga_screen(svga->pipe.screen);
   struct rs_queue queue;
   float point_size_min;

   queue.rs_count = 0;

   if (dirty & SVGA_NEW_BLEND) {
      const struct svga_blend_state *curr = svga->curr.blend;

      EMIT_RS( svga, curr->rt[0].writemask, COLORWRITEENABLE, fail );
      EMIT_RS( svga, curr->rt[0].blend_enable, BLENDENABLE, fail );

      if (curr->rt[0].blend_enable) {
         EMIT_RS( svga, curr->rt[0].srcblend, SRCBLEND, fail );
         EMIT_RS( svga, curr->rt[0].dstblend, DSTBLEND, fail );
         EMIT_RS( svga, curr->rt[0].blendeq, BLENDEQUATION, fail );

         EMIT_RS( svga, curr->rt[0].separate_alpha_blend_enable, 
                  SEPARATEALPHABLENDENABLE, fail );

         if (curr->rt[0].separate_alpha_blend_enable) {
            EMIT_RS( svga, curr->rt[0].srcblend_alpha, SRCBLENDALPHA, fail );
            EMIT_RS( svga, curr->rt[0].dstblend_alpha, DSTBLENDALPHA, fail );
            EMIT_RS( svga, curr->rt[0].blendeq_alpha, BLENDEQUATIONALPHA, fail );
         }
      }
   }

   if (dirty & SVGA_NEW_BLEND_COLOR) {
      uint32 color;
      uint32 r = float_to_ubyte(svga->curr.blend_color.color[0]);
      uint32 g = float_to_ubyte(svga->curr.blend_color.color[1]);
      uint32 b = float_to_ubyte(svga->curr.blend_color.color[2]);
      uint32 a = float_to_ubyte(svga->curr.blend_color.color[3]);

      color = (a << 24) | (r << 16) | (g << 8) | b;

      EMIT_RS( svga, color, BLENDCOLOR, fail );
   }

   if (dirty & (SVGA_NEW_DEPTH_STENCIL | SVGA_NEW_RAST)) {
      const struct svga_depth_stencil_state *curr = svga->curr.depth; 
      const struct svga_rasterizer_state *rast = svga->curr.rast; 

      if (!curr->stencil[0].enabled) 
      {
         /* Stencil disabled
          */
         EMIT_RS( svga, FALSE, STENCILENABLE, fail );
         EMIT_RS( svga, FALSE, STENCILENABLE2SIDED, fail );
      }
      else if (curr->stencil[0].enabled && !curr->stencil[1].enabled)
      {
         /* Regular stencil
          */
         EMIT_RS( svga, TRUE, STENCILENABLE, fail );
         EMIT_RS( svga, FALSE, STENCILENABLE2SIDED, fail );

         EMIT_RS( svga, curr->stencil[0].func,  STENCILFUNC, fail );
         EMIT_RS( svga, curr->stencil[0].fail,  STENCILFAIL, fail );
         EMIT_RS( svga, curr->stencil[0].zfail, STENCILZFAIL, fail );
         EMIT_RS( svga, curr->stencil[0].pass,  STENCILPASS, fail );

         EMIT_RS( svga, curr->stencil_mask, STENCILMASK, fail );
         EMIT_RS( svga, curr->stencil_writemask, STENCILWRITEMASK, fail );
      }
      else 
      {
         int cw, ccw;

         /* Hardware frontwinding is always CW, so if ours is also CW,
          * then our definition of front face agrees with hardware.
          * Otherwise need to flip.
          */
         if (rast->templ.front_ccw) {
            ccw = 0;
            cw = 1;
         }
         else {
            ccw = 1;
            cw = 0;
         }

         /* Twoside stencil
          */
         EMIT_RS( svga, TRUE, STENCILENABLE, fail );
         EMIT_RS( svga, TRUE, STENCILENABLE2SIDED, fail );

         EMIT_RS( svga, curr->stencil[cw].func,  STENCILFUNC, fail );
         EMIT_RS( svga, curr->stencil[cw].fail,  STENCILFAIL, fail );
         EMIT_RS( svga, curr->stencil[cw].zfail, STENCILZFAIL, fail );
         EMIT_RS( svga, curr->stencil[cw].pass,  STENCILPASS, fail );

         EMIT_RS( svga, curr->stencil[ccw].func,  CCWSTENCILFUNC, fail );
         EMIT_RS( svga, curr->stencil[ccw].fail,  CCWSTENCILFAIL, fail );
         EMIT_RS( svga, curr->stencil[ccw].zfail, CCWSTENCILZFAIL, fail );
         EMIT_RS( svga, curr->stencil[ccw].pass,  CCWSTENCILPASS, fail );

         EMIT_RS( svga, curr->stencil_mask, STENCILMASK, fail );
         EMIT_RS( svga, curr->stencil_writemask, STENCILWRITEMASK, fail );
      }

      EMIT_RS( svga, curr->zenable, ZENABLE, fail );
      if (curr->zenable) {
         EMIT_RS( svga, curr->zfunc, ZFUNC, fail );
         EMIT_RS( svga, curr->zwriteenable, ZWRITEENABLE, fail );
      }

      EMIT_RS( svga, curr->alphatestenable, ALPHATESTENABLE, fail );
      if (curr->alphatestenable) {
         EMIT_RS( svga, curr->alphafunc, ALPHAFUNC, fail );
         EMIT_RS_FLOAT( svga, curr->alpharef, ALPHAREF, fail );
      }
   }

   if (dirty & SVGA_NEW_STENCIL_REF) {
      EMIT_RS( svga, svga->curr.stencil_ref.ref_value[0], STENCILREF, fail );
   }

   if (dirty & (SVGA_NEW_RAST | SVGA_NEW_NEED_PIPELINE))
   {
      const struct svga_rasterizer_state *curr = svga->curr.rast; 
      unsigned cullmode = curr->cullmode;

      /* Shademode: still need to rearrange index list to move
       * flat-shading PV first vertex.
       */
      EMIT_RS( svga, curr->shademode, SHADEMODE, fail );

      /* Don't do culling while the software pipeline is active.  It
       * does it for us, and additionally introduces potentially
       * back-facing triangles.
       */
      if (svga->state.sw.need_pipeline)
         cullmode = SVGA3D_FACE_NONE;

      point_size_min = util_get_min_point_size(&curr->templ);

      EMIT_RS( svga, cullmode, CULLMODE, fail );
      EMIT_RS( svga, curr->scissortestenable, SCISSORTESTENABLE, fail );
      EMIT_RS( svga, curr->multisampleantialias, MULTISAMPLEANTIALIAS, fail );
      EMIT_RS( svga, curr->lastpixel, LASTPIXEL, fail );
      EMIT_RS( svga, curr->linepattern, LINEPATTERN, fail );
      EMIT_RS_FLOAT( svga, curr->pointsize, POINTSIZE, fail );
      EMIT_RS_FLOAT( svga, point_size_min, POINTSIZEMIN, fail );
      EMIT_RS_FLOAT( svga, screen->maxPointSize, POINTSIZEMAX, fail );
      EMIT_RS( svga, curr->pointsprite, POINTSPRITEENABLE, fail);
   }

   if (dirty & (SVGA_NEW_RAST | SVGA_NEW_FRAME_BUFFER | SVGA_NEW_NEED_PIPELINE))
   {
      const struct svga_rasterizer_state *curr = svga->curr.rast; 
      float slope = 0.0;
      float bias  = 0.0;

      /* Need to modify depth bias according to bound depthbuffer
       * format.  Don't do hardware depthbias while the software
       * pipeline is active.
       */
      if (!svga->state.sw.need_pipeline &&
          svga->curr.framebuffer.zsbuf)
      {
         slope = curr->slopescaledepthbias;
         bias  = svga->curr.depthscale * curr->depthbias;
      }

      EMIT_RS_FLOAT( svga, slope, SLOPESCALEDEPTHBIAS, fail );
      EMIT_RS_FLOAT( svga, bias, DEPTHBIAS, fail );
   }

   if (dirty & SVGA_NEW_FRAME_BUFFER) {
      /* XXX: we only look at the first color buffer's sRGB state */
      float gamma = 1.0f;
      if (svga->curr.framebuffer.cbufs[0] &&
          util_format_is_srgb(svga->curr.framebuffer.cbufs[0]->format)) {
         gamma = 2.2f;
      }
      EMIT_RS_FLOAT(svga, gamma, OUTPUTGAMMA, fail);
   }

   if (dirty & SVGA_NEW_RAST) {
      /* bitmask of the enabled clip planes */
      unsigned enabled = svga->curr.rast->templ.clip_plane_enable;
      EMIT_RS( svga, enabled, CLIPPLANEENABLE, fail );
   }

   if (queue.rs_count) {
      SVGA3dRenderState *rs;

      if (SVGA3D_BeginSetRenderState( svga->swc,
                                      &rs,
                                      queue.rs_count ) != PIPE_OK)
         goto fail;

      memcpy( rs,
              queue.rs,
              queue.rs_count * sizeof queue.rs[0]);

      SVGA_FIFOCommitAll( svga->swc );
   }

   return PIPE_OK;

fail:
   /* XXX: need to poison cached hardware state on failure to ensure
    * dirty state gets re-emitted.  Fix this by re-instating partial
    * FIFOCommit command and only updating cached hw state once the
    * initial allocation has succeeded.
    */
   memset(svga->state.hw_draw.rs, 0xcd, sizeof(svga->state.hw_draw.rs));

   return PIPE_ERROR_OUT_OF_MEMORY;
}
Пример #2
0
void *
fd6_rasterizer_state_create(struct pipe_context *pctx,
		const struct pipe_rasterizer_state *cso)
{
	struct fd_context *ctx = fd_context(pctx);
	struct fd6_rasterizer_stateobj *so;
	float psize_min, psize_max;

	so = CALLOC_STRUCT(fd6_rasterizer_stateobj);
	if (!so)
		return NULL;

	so->base = *cso;

	if (cso->point_size_per_vertex) {
		psize_min = util_get_min_point_size(cso);
		psize_max = 4092;
	} else {
		/* Force the point size to be as if the vertex output was disabled. */
		psize_min = cso->point_size;
		psize_max = cso->point_size;
	}

	so->gras_su_point_minmax =
			A6XX_GRAS_SU_POINT_MINMAX_MIN(psize_min) |
			A6XX_GRAS_SU_POINT_MINMAX_MAX(psize_max);
	so->gras_su_point_size   = A6XX_GRAS_SU_POINT_SIZE(cso->point_size);
	so->gras_su_poly_offset_scale =
			A6XX_GRAS_SU_POLY_OFFSET_SCALE(cso->offset_scale);
	so->gras_su_poly_offset_offset =
			A6XX_GRAS_SU_POLY_OFFSET_OFFSET(cso->offset_units);
	so->gras_su_poly_offset_clamp =
			A6XX_GRAS_SU_POLY_OFFSET_OFFSET_CLAMP(cso->offset_clamp);

	so->gras_su_cntl =
			A6XX_GRAS_SU_CNTL_LINEHALFWIDTH(cso->line_width/2.0) |
			COND(cso->multisample, A6XX_GRAS_SU_CNTL_MSAA_ENABLE);

#if 0
	so->pc_raster_cntl =
		A6XX_PC_RASTER_CNTL_POLYMODE_FRONT_PTYPE(fd_polygon_mode(cso->fill_front)) |
		A6XX_PC_RASTER_CNTL_POLYMODE_BACK_PTYPE(fd_polygon_mode(cso->fill_back));
#endif

#if 0
	if (cso->fill_front != PIPE_POLYGON_MODE_FILL ||
		cso->fill_back != PIPE_POLYGON_MODE_FILL)
		so->pc_raster_cntl |= A6XX_PC_RASTER_CNTL_POLYMODE_ENABLE;
#endif

	if (cso->cull_face & PIPE_FACE_FRONT)
		so->gras_su_cntl |= A6XX_GRAS_SU_CNTL_CULL_FRONT;
	if (cso->cull_face & PIPE_FACE_BACK)
		so->gras_su_cntl |= A6XX_GRAS_SU_CNTL_CULL_BACK;
	if (!cso->front_ccw)
		so->gras_su_cntl |= A6XX_GRAS_SU_CNTL_FRONT_CW;
	if (cso->offset_tri)
		so->gras_su_cntl |= A6XX_GRAS_SU_CNTL_POLY_OFFSET;

	if (!cso->flatshade_first)
		so->pc_primitive_cntl |= A6XX_PC_PRIMITIVE_CNTL_0_PROVOKING_VTX_LAST;

//	if (!cso->depth_clip)
//		so->gras_cl_clip_cntl |= A6XX_GRAS_CL_CLIP_CNTL_ZNEAR_CLIP_DISABLE |
//			A6XX_GRAS_CL_CLIP_CNTL_ZFAR_CLIP_DISABLE;
#if 0
	if (cso->clip_halfz)
		so->gras_cl_clip_cntl |= A6XX_GRAS_CL_CNTL_ZERO_GB_SCALE_Z;
#endif

	so->stateobj = fd_ringbuffer_new_object(ctx->pipe, 15 * 4);
	struct fd_ringbuffer *ring = so->stateobj;

	OUT_PKT4(ring, REG_A6XX_GRAS_UNKNOWN_8000, 1);
	OUT_RING(ring, 0x80);
	OUT_PKT4(ring, REG_A6XX_GRAS_UNKNOWN_8001, 1);
	OUT_RING(ring, 0x0);
	OUT_PKT4(ring, REG_A6XX_GRAS_UNKNOWN_8004, 1);
	OUT_RING(ring, 0x0);

	OUT_PKT4(ring, REG_A6XX_GRAS_SU_CNTL, 1);
	OUT_RING(ring, so->gras_su_cntl);

	OUT_PKT4(ring, REG_A6XX_GRAS_SU_POINT_MINMAX, 2);
	OUT_RING(ring, so->gras_su_point_minmax);
	OUT_RING(ring, so->gras_su_point_size);

	OUT_PKT4(ring, REG_A6XX_GRAS_SU_POLY_OFFSET_SCALE, 3);
	OUT_RING(ring, so->gras_su_poly_offset_scale);
	OUT_RING(ring, so->gras_su_poly_offset_offset);
	OUT_RING(ring, so->gras_su_poly_offset_clamp);

#if 0
	OUT_PKT4(ring, REG_A6XX_PC_RASTER_CNTL, 1);
	OUT_RING(ring, so->pc_raster_cntl);

	OUT_PKT4(ring, REG_A6XX_GRAS_CL_CNTL, 1);
	OUT_RING(ring, so->gras_cl_clip_cntl);
#endif

	return so;
}
Пример #3
0
void *
fd3_rasterizer_state_create(struct pipe_context *pctx,
		const struct pipe_rasterizer_state *cso)
{
	struct fd3_rasterizer_stateobj *so;
	float psize_min, psize_max;

	so = CALLOC_STRUCT(fd3_rasterizer_stateobj);
	if (!so)
		return NULL;

	so->base = *cso;

	if (cso->point_size_per_vertex) {
		psize_min = util_get_min_point_size(cso);
		psize_max = 4092;
	} else {
		/* Force the point size to be as if the vertex output was disabled. */
		psize_min = cso->point_size;
		psize_max = cso->point_size;
	}

/*
	if (cso->line_stipple_enable) {
		??? TODO line stipple
	}
	TODO cso->half_pixel_center
	if (cso->multisample)
		TODO
*/
	so->gras_cl_clip_cntl = A3XX_GRAS_CL_CLIP_CNTL_IJ_PERSP_CENTER /* ??? */ |
		COND(cso->clip_halfz, A3XX_GRAS_CL_CLIP_CNTL_ZERO_GB_SCALE_Z);
	so->gras_su_point_minmax =
			A3XX_GRAS_SU_POINT_MINMAX_MIN(psize_min) |
			A3XX_GRAS_SU_POINT_MINMAX_MAX(psize_max);
	so->gras_su_point_size   = A3XX_GRAS_SU_POINT_SIZE(cso->point_size);
	so->gras_su_poly_offset_scale =
			A3XX_GRAS_SU_POLY_OFFSET_SCALE_VAL(cso->offset_scale);
	so->gras_su_poly_offset_offset =
			A3XX_GRAS_SU_POLY_OFFSET_OFFSET(cso->offset_units * 2.0f);

	so->gras_su_mode_control =
			A3XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH(cso->line_width/2.0);

	so->pc_prim_vtx_cntl =
		A3XX_PC_PRIM_VTX_CNTL_POLYMODE_FRONT_PTYPE(fd_polygon_mode(cso->fill_front)) |
		A3XX_PC_PRIM_VTX_CNTL_POLYMODE_BACK_PTYPE(fd_polygon_mode(cso->fill_back));

	if (cso->fill_front != PIPE_POLYGON_MODE_FILL ||
		cso->fill_back != PIPE_POLYGON_MODE_FILL)
		so->pc_prim_vtx_cntl |= A3XX_PC_PRIM_VTX_CNTL_POLYMODE_ENABLE;

	if (cso->cull_face & PIPE_FACE_FRONT)
		so->gras_su_mode_control |= A3XX_GRAS_SU_MODE_CONTROL_CULL_FRONT;
	if (cso->cull_face & PIPE_FACE_BACK)
		so->gras_su_mode_control |= A3XX_GRAS_SU_MODE_CONTROL_CULL_BACK;
	if (!cso->front_ccw)
		so->gras_su_mode_control |= A3XX_GRAS_SU_MODE_CONTROL_FRONT_CW;
	if (!cso->flatshade_first)
		so->pc_prim_vtx_cntl |= A3XX_PC_PRIM_VTX_CNTL_PROVOKING_VTX_LAST;

	if (cso->offset_tri)
		so->gras_su_mode_control |= A3XX_GRAS_SU_MODE_CONTROL_POLY_OFFSET;
	if (!cso->depth_clip_near)
		so->gras_cl_clip_cntl |= A3XX_GRAS_CL_CLIP_CNTL_CLIP_DISABLE;

	return so;
}
Пример #4
0
static void *
fd_rasterizer_state_create(struct pipe_context *pctx,
		const struct pipe_rasterizer_state *cso)
{
	struct fd_rasterizer_stateobj *so;
	float psize_min, psize_max;

	so = CALLOC_STRUCT(fd_rasterizer_stateobj);
	if (!so)
		return NULL;

	if (cso->point_size_per_vertex) {
		psize_min = util_get_min_point_size(cso);
		psize_max = 8192;
	} else {
		/* Force the point size to be as if the vertex output was disabled. */
		psize_min = cso->point_size;
		psize_max = cso->point_size;
	}

	so->base = *cso;

	so->pa_sc_line_stipple = cso->line_stipple_enable ?
		A2XX_PA_SC_LINE_STIPPLE_LINE_PATTERN(cso->line_stipple_pattern) |
		A2XX_PA_SC_LINE_STIPPLE_REPEAT_COUNT(cso->line_stipple_factor) : 0;

	so->pa_cl_clip_cntl = 0; // TODO

	so->pa_su_vtx_cntl =
		A2XX_PA_SU_VTX_CNTL_PIX_CENTER(cso->gl_rasterization_rules ? PIXCENTER_OGL : PIXCENTER_D3D) |
		A2XX_PA_SU_VTX_CNTL_QUANT_MODE(ONE_SIXTEENTH);

	so->pa_su_point_size =
		A2XX_PA_SU_POINT_SIZE_HEIGHT(cso->point_size/2) |
		A2XX_PA_SU_POINT_SIZE_WIDTH(cso->point_size/2);

	so->pa_su_point_minmax =
		A2XX_PA_SU_POINT_MINMAX_MIN(psize_min/2) |
		A2XX_PA_SU_POINT_MINMAX_MAX(psize_max/2);

	so->pa_su_line_cntl =
		A2XX_PA_SU_LINE_CNTL_WIDTH(cso->line_width/2);

	so->pa_su_sc_mode_cntl =
		A2XX_PA_SU_SC_MODE_CNTL_VTX_WINDOW_OFFSET_ENABLE |
		A2XX_PA_SU_SC_MODE_CNTL_FRONT_PTYPE(polygon_mode(cso->fill_front)) |
		A2XX_PA_SU_SC_MODE_CNTL_BACK_PTYPE(polygon_mode(cso->fill_back));

	if (cso->cull_face & PIPE_FACE_FRONT)
		so->pa_su_sc_mode_cntl |= A2XX_PA_SU_SC_MODE_CNTL_CULL_FRONT;
	if (cso->cull_face & PIPE_FACE_BACK)
		so->pa_su_sc_mode_cntl |= A2XX_PA_SU_SC_MODE_CNTL_CULL_BACK;
	if (!cso->flatshade_first)
		so->pa_su_sc_mode_cntl |= A2XX_PA_SU_SC_MODE_CNTL_PROVOKING_VTX_LAST;
	if (!cso->front_ccw)
		so->pa_su_sc_mode_cntl |= A2XX_PA_SU_SC_MODE_CNTL_FACE;
	if (cso->line_stipple_enable)
		so->pa_su_sc_mode_cntl |= A2XX_PA_SU_SC_MODE_CNTL_LINE_STIPPLE_ENABLE;
	if (cso->multisample)
		so->pa_su_sc_mode_cntl |= A2XX_PA_SU_SC_MODE_CNTL_MSAA_ENABLE;

	if (cso->fill_front != PIPE_POLYGON_MODE_FILL ||
			cso->fill_back != PIPE_POLYGON_MODE_FILL)
		so->pa_su_sc_mode_cntl |= A2XX_PA_SU_SC_MODE_CNTL_POLYMODE(POLY_DUALMODE);
	else
		so->pa_su_sc_mode_cntl |= A2XX_PA_SU_SC_MODE_CNTL_POLYMODE(POLY_DISABLED);

	if (cso->offset_tri)
		so->pa_su_sc_mode_cntl |=
			A2XX_PA_SU_SC_MODE_CNTL_POLY_OFFSET_FRONT_ENABLE |
			A2XX_PA_SU_SC_MODE_CNTL_POLY_OFFSET_BACK_ENABLE |
			A2XX_PA_SU_SC_MODE_CNTL_POLY_OFFSET_PARA_ENABLE;

	return so;
}