Beispiel #1
0
static VGboolean blend_use_shader(struct shader *shader)
{
   struct vg_context *ctx = shader->context;
   VGboolean advanced_blending;

   switch (ctx->state.vg.blend_mode) {
   case VG_BLEND_DST_OVER:
   case VG_BLEND_MULTIPLY:
   case VG_BLEND_SCREEN:
   case VG_BLEND_DARKEN:
   case VG_BLEND_LIGHTEN:
   case VG_BLEND_ADDITIVE:
      advanced_blending = VG_TRUE;
      break;
   case VG_BLEND_SRC_OVER:
      if (util_format_has_alpha(ctx->draw_buffer->strb->format)) {
         /* no blending is required if the paints and the image are opaque */
         advanced_blending = !paint_is_opaque(ctx->state.vg.fill_paint) ||
                             !paint_is_opaque(ctx->state.vg.stroke_paint);
         if (!advanced_blending && shader->drawing_image) {
            advanced_blending =
               util_format_has_alpha(shader->image->sampler_view->format);
         }
         break;
      }
      /* fall through */
   default:
      advanced_blending = VG_FALSE;
      break;
   }

   return advanced_blending;
}
/**
 * Return the base format just like _mesa_base_fbo_format does.
 */
static GLenum
st_pipe_format_to_base_format(enum pipe_format format)
{
   GLenum base_format;

   if (util_format_is_depth_or_stencil(format)) {
      if (util_format_is_depth_and_stencil(format)) {
         base_format = GL_DEPTH_STENCIL;
      }
      else {
         if (format == PIPE_FORMAT_S8_USCALED)
            base_format = GL_STENCIL_INDEX;
         else
            base_format = GL_DEPTH_COMPONENT;
      }
   }
   else {
      /* is this enough? */
      if (util_format_has_alpha(format))
         base_format = GL_RGBA;
      else
         base_format = GL_RGB;
   }

   return base_format;
}
Beispiel #3
0
static void renderer_validate_blend(struct renderer *renderer,
                                     const struct vg_state *state,
                                     enum pipe_format fb_format)
{
   struct pipe_blend_state blend;

   memset(&blend, 0, sizeof(blend));
   blend.rt[0].colormask = PIPE_MASK_RGBA;
   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;

   /* TODO alpha masking happens after blending? */

   switch (state->blend_mode) {
   case VG_BLEND_SRC:
      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;
      break;
   case VG_BLEND_SRC_OVER:
      if (!util_format_has_alpha(fb_format)) {
         blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_SRC_ALPHA;
         blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
         blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
         blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
         blend.rt[0].blend_enable = 1;
      }
      break;
   case VG_BLEND_SRC_IN:
      blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ONE;
      blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_DST_ALPHA;
      blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ZERO;
      blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
      blend.rt[0].blend_enable = 1;
      break;
   case VG_BLEND_DST_IN:
      blend.rt[0].rgb_src_factor   = PIPE_BLENDFACTOR_ZERO;
      blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO;
      blend.rt[0].rgb_dst_factor   = PIPE_BLENDFACTOR_ONE;
      blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
      blend.rt[0].blend_enable = 1;
      break;
   case VG_BLEND_DST_OVER:
   case VG_BLEND_MULTIPLY:
   case VG_BLEND_SCREEN:
   case VG_BLEND_DARKEN:
   case VG_BLEND_LIGHTEN:
   case VG_BLEND_ADDITIVE:
      /* need a shader */
      break;
   default:
      assert(!"not implemented blend mode");
      break;
   }

   cso_set_blend(renderer->cso, &blend);
}
Beispiel #4
0
/**
 * Given a user-specified texture base format, the actual gallium texture
 * format and the current GL_DEPTH_MODE, return a texture swizzle.
 *
 * Consider the case where the user requests a GL_RGB internal texture
 * format the driver actually uses an RGBA format.  The A component should
 * be ignored and sampling from the texture should always return (r,g,b,1).
 * But if we rendered to the texture we might have written A values != 1.
 * By sampling the texture with a ".xyz1" swizzle we'll get the expected A=1.
 * This function computes the texture swizzle needed to get the expected
 * values.
 *
 * In the case of depth textures, the GL_DEPTH_MODE state determines the
 * texture swizzle.
 *
 * This result must be composed with the user-specified swizzle to get
 * the final swizzle.
 */
static unsigned
compute_texture_format_swizzle(GLenum baseFormat, GLenum depthMode,
                               enum pipe_format actualFormat)
{
   switch (baseFormat) {
   case GL_RGBA:
      return SWIZZLE_XYZW;
   case GL_RGB:
      if (util_format_has_alpha(actualFormat))
         return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ONE);
      else
         return SWIZZLE_XYZW;
   case GL_RG:
      if (util_format_get_nr_components(actualFormat) > 2)
         return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_ZERO, SWIZZLE_ONE);
      else
         return SWIZZLE_XYZW;
   case GL_RED:
      if (util_format_get_nr_components(actualFormat) > 1)
         return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_ZERO,
                              SWIZZLE_ZERO, SWIZZLE_ONE);
      else
         return SWIZZLE_XYZW;
   case GL_ALPHA:
      if (util_format_get_nr_components(actualFormat) > 1)
         return MAKE_SWIZZLE4(SWIZZLE_ZERO, SWIZZLE_ZERO,
                              SWIZZLE_ZERO, SWIZZLE_W);
      else
         return SWIZZLE_XYZW;
   case GL_LUMINANCE:
      if (util_format_get_nr_components(actualFormat) > 1)
         return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_ONE);
      else
         return SWIZZLE_XYZW;
   case GL_LUMINANCE_ALPHA:
      if (util_format_get_nr_components(actualFormat) > 2)
         return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_W);
      else
         return SWIZZLE_XYZW;
   case GL_INTENSITY:
      if (util_format_get_nr_components(actualFormat) > 1)
         return SWIZZLE_XXXX;
      else
         return SWIZZLE_XYZW;
   case GL_STENCIL_INDEX:
      return SWIZZLE_XYZW;
   case GL_DEPTH_STENCIL:
      /* fall-through */
   case GL_DEPTH_COMPONENT:
      /* Now examine the depth mode */
      switch (depthMode) {
      case GL_LUMINANCE:
         return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_ONE);
      case GL_INTENSITY:
         return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X);
      case GL_ALPHA:
         return MAKE_SWIZZLE4(SWIZZLE_ZERO, SWIZZLE_ZERO,
                              SWIZZLE_ZERO, SWIZZLE_X);
      case GL_RED:
         return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_ZERO,
                              SWIZZLE_ZERO, SWIZZLE_ONE);
      default:
         assert(!"Unexpected depthMode");
         return SWIZZLE_XYZW;
      }
   default:
      assert(!"Unexpected baseFormat");
      return SWIZZLE_XYZW;
   }
}
Beispiel #5
0
static boolean
st_context_teximage(struct st_context_iface *stctxi,
                    enum st_texture_type tex_type,
                    int level, enum pipe_format pipe_format,
                    struct pipe_resource *tex, boolean mipmap)
{
   struct st_context *st = (struct st_context *) stctxi;
   struct gl_context *ctx = st->ctx;
   struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
   struct gl_texture_object *texObj;
   struct gl_texture_image *texImage;
   struct st_texture_object *stObj;
   struct st_texture_image *stImage;
   GLenum internalFormat;
   GLuint width, height, depth;
   GLenum target;

   switch (tex_type) {
   case ST_TEXTURE_1D:
      target = GL_TEXTURE_1D;
      break;
   case ST_TEXTURE_2D:
      target = GL_TEXTURE_2D;
      break;
   case ST_TEXTURE_3D:
      target = GL_TEXTURE_3D;
      break;
   case ST_TEXTURE_RECT:
      target = GL_TEXTURE_RECTANGLE_ARB;
      break;
   default:
      return FALSE;
   }

   texObj = _mesa_select_tex_object(ctx, texUnit, target);
   _mesa_lock_texture(ctx, texObj);

   stObj = st_texture_object(texObj);
   /* switch to surface based */
   if (!stObj->surface_based) {
      _mesa_clear_texture_object(ctx, texObj);
      stObj->surface_based = GL_TRUE;
   }

   texImage = _mesa_get_tex_image(ctx, texObj, target, level);
   stImage = st_texture_image(texImage);
   if (tex) {
      gl_format texFormat = st_pipe_format_to_mesa_format(pipe_format);

      if (util_format_has_alpha(tex->format))
         internalFormat = GL_RGBA;
      else
         internalFormat = GL_RGB;

      _mesa_init_teximage_fields(ctx, texImage,
                                 tex->width0, tex->height0, 1, 0,
                                 internalFormat, texFormat);

      width = tex->width0;
      height = tex->height0;
      depth = tex->depth0;

      /* grow the image size until we hit level = 0 */
      while (level > 0) {
         if (width != 1)
            width <<= 1;
         if (height != 1)
            height <<= 1;
         if (depth != 1)
            depth <<= 1;
         level--;
      }
   }
   else {
      _mesa_clear_texture_image(ctx, texImage);
      width = height = depth = 0;
   }

   pipe_resource_reference(&stImage->pt, tex);
   stObj->width0 = width;
   stObj->height0 = height;
   stObj->depth0 = depth;
   stObj->surface_format = pipe_format;

   _mesa_dirty_texobj(ctx, texObj, GL_TRUE);
   _mesa_unlock_texture(ctx, texObj);
   
   return TRUE;
}
Beispiel #6
0
/**
 * Given a user-specified texture base format, the actual gallium texture
 * format and the current GL_DEPTH_MODE, return a texture swizzle.
 *
 * Consider the case where the user requests a GL_RGB internal texture
 * format the driver actually uses an RGBA format.  The A component should
 * be ignored and sampling from the texture should always return (r,g,b,1).
 * But if we rendered to the texture we might have written A values != 1.
 * By sampling the texture with a ".xyz1" swizzle we'll get the expected A=1.
 * This function computes the texture swizzle needed to get the expected
 * values.
 *
 * In the case of depth textures, the GL_DEPTH_MODE state determines the
 * texture swizzle.
 *
 * This result must be composed with the user-specified swizzle to get
 * the final swizzle.
 */
static unsigned
compute_texture_format_swizzle(GLenum baseFormat, GLenum depthMode,
                               enum pipe_format actualFormat,
                               unsigned glsl_version)
{
    switch (baseFormat) {
    case GL_RGBA:
        return SWIZZLE_XYZW;
    case GL_RGB:
        if (util_format_has_alpha(actualFormat))
            return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ONE);
        else
            return SWIZZLE_XYZW;
    case GL_RG:
        if (util_format_get_nr_components(actualFormat) > 2)
            return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_ZERO, SWIZZLE_ONE);
        else
            return SWIZZLE_XYZW;
    case GL_RED:
        if (util_format_get_nr_components(actualFormat) > 1)
            return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_ZERO,
                                 SWIZZLE_ZERO, SWIZZLE_ONE);
        else
            return SWIZZLE_XYZW;
    case GL_ALPHA:
        if (util_format_get_nr_components(actualFormat) > 1)
            return MAKE_SWIZZLE4(SWIZZLE_ZERO, SWIZZLE_ZERO,
                                 SWIZZLE_ZERO, SWIZZLE_W);
        else
            return SWIZZLE_XYZW;
    case GL_LUMINANCE:
        if (util_format_get_nr_components(actualFormat) > 1)
            return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_ONE);
        else
            return SWIZZLE_XYZW;
    case GL_LUMINANCE_ALPHA:
        if (util_format_get_nr_components(actualFormat) > 2)
            return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_W);
        else
            return SWIZZLE_XYZW;
    case GL_INTENSITY:
        if (util_format_get_nr_components(actualFormat) > 1)
            return SWIZZLE_XXXX;
        else
            return SWIZZLE_XYZW;
    case GL_STENCIL_INDEX:
    case GL_DEPTH_STENCIL:
    case GL_DEPTH_COMPONENT:
        /* Now examine the depth mode */
        switch (depthMode) {
        case GL_LUMINANCE:
            return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_ONE);
        case GL_INTENSITY:
            return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X);
        case GL_ALPHA:
            /* The texture(sampler*Shadow) functions from GLSL 1.30 ignore
             * the depth mode and return float, while older shadow* functions
             * and ARB_fp instructions return vec4 according to the depth mode.
             *
             * The problem with the GLSL 1.30 functions is that GL_ALPHA forces
             * them to return 0, breaking them completely.
             *
             * A proper fix would increase code complexity and that's not worth
             * it for a rarely used feature such as the GL_ALPHA depth mode
             * in GL3. Therefore, change GL_ALPHA to GL_INTENSITY for all
             * shaders that use GLSL 1.30 or later.
             *
             * BTW, it's required that sampler views are updated when
             * shaders change (check_sampler_swizzle takes care of that).
             */
            if (glsl_version && glsl_version >= 130)
                return SWIZZLE_XXXX;
            else
                return MAKE_SWIZZLE4(SWIZZLE_ZERO, SWIZZLE_ZERO,
                                     SWIZZLE_ZERO, SWIZZLE_X);
        case GL_RED:
            return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_ZERO,
                                 SWIZZLE_ZERO, SWIZZLE_ONE);
        default:
            assert(!"Unexpected depthMode");
            return SWIZZLE_XYZW;
        }
    default:
        assert(!"Unexpected baseFormat");
        return SWIZZLE_XYZW;
    }
}
Beispiel #7
0
void
fd2_emit_state(struct fd_context *ctx, const enum fd_dirty_3d_state dirty)
{
	struct fd2_blend_stateobj *blend = fd2_blend_stateobj(ctx->blend);
	struct fd2_zsa_stateobj *zsa = fd2_zsa_stateobj(ctx->zsa);
	struct fd_ringbuffer *ring = ctx->batch->draw;

	/* NOTE: we probably want to eventually refactor this so each state
	 * object handles emitting it's own state..  although the mapping of
	 * state to registers is not always orthogonal, sometimes a single
	 * register contains bitfields coming from multiple state objects,
	 * so not sure the best way to deal with that yet.
	 */

	if (dirty & FD_DIRTY_SAMPLE_MASK) {
		OUT_PKT3(ring, CP_SET_CONSTANT, 2);
		OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_AA_MASK));
		OUT_RING(ring, ctx->sample_mask);
	}

	if (dirty & (FD_DIRTY_ZSA | FD_DIRTY_STENCIL_REF)) {
		struct pipe_stencil_ref *sr = &ctx->stencil_ref;

		OUT_PKT3(ring, CP_SET_CONSTANT, 2);
		OUT_RING(ring, CP_REG(REG_A2XX_RB_DEPTHCONTROL));
		OUT_RING(ring, zsa->rb_depthcontrol);

		OUT_PKT3(ring, CP_SET_CONSTANT, 4);
		OUT_RING(ring, CP_REG(REG_A2XX_RB_STENCILREFMASK_BF));
		OUT_RING(ring, zsa->rb_stencilrefmask_bf |
				A2XX_RB_STENCILREFMASK_STENCILREF(sr->ref_value[1]));
		OUT_RING(ring, zsa->rb_stencilrefmask |
				A2XX_RB_STENCILREFMASK_STENCILREF(sr->ref_value[0]));
		OUT_RING(ring, zsa->rb_alpha_ref);
	}

	if (ctx->rasterizer && dirty & FD_DIRTY_RASTERIZER) {
		struct fd2_rasterizer_stateobj *rasterizer =
				fd2_rasterizer_stateobj(ctx->rasterizer);
		OUT_PKT3(ring, CP_SET_CONSTANT, 3);
		OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_CLIP_CNTL));
		OUT_RING(ring, rasterizer->pa_cl_clip_cntl);
		OUT_RING(ring, rasterizer->pa_su_sc_mode_cntl |
				A2XX_PA_SU_SC_MODE_CNTL_VTX_WINDOW_OFFSET_ENABLE);

		OUT_PKT3(ring, CP_SET_CONSTANT, 5);
		OUT_RING(ring, CP_REG(REG_A2XX_PA_SU_POINT_SIZE));
		OUT_RING(ring, rasterizer->pa_su_point_size);
		OUT_RING(ring, rasterizer->pa_su_point_minmax);
		OUT_RING(ring, rasterizer->pa_su_line_cntl);
		OUT_RING(ring, rasterizer->pa_sc_line_stipple);

		OUT_PKT3(ring, CP_SET_CONSTANT, 6);
		OUT_RING(ring, CP_REG(REG_A2XX_PA_SU_VTX_CNTL));
		OUT_RING(ring, rasterizer->pa_su_vtx_cntl);
		OUT_RING(ring, fui(1.0));                /* PA_CL_GB_VERT_CLIP_ADJ */
		OUT_RING(ring, fui(1.0));                /* PA_CL_GB_VERT_DISC_ADJ */
		OUT_RING(ring, fui(1.0));                /* PA_CL_GB_HORZ_CLIP_ADJ */
		OUT_RING(ring, fui(1.0));                /* PA_CL_GB_HORZ_DISC_ADJ */
	}

	/* NOTE: scissor enabled bit is part of rasterizer state: */
	if (dirty & (FD_DIRTY_SCISSOR | FD_DIRTY_RASTERIZER)) {
		struct pipe_scissor_state *scissor = fd_context_get_scissor(ctx);

		OUT_PKT3(ring, CP_SET_CONSTANT, 3);
		OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_WINDOW_SCISSOR_TL));
		OUT_RING(ring, xy2d(scissor->minx,       /* PA_SC_WINDOW_SCISSOR_TL */
				scissor->miny));
		OUT_RING(ring, xy2d(scissor->maxx,       /* PA_SC_WINDOW_SCISSOR_BR */
				scissor->maxy));

		ctx->batch->max_scissor.minx = MIN2(ctx->batch->max_scissor.minx, scissor->minx);
		ctx->batch->max_scissor.miny = MIN2(ctx->batch->max_scissor.miny, scissor->miny);
		ctx->batch->max_scissor.maxx = MAX2(ctx->batch->max_scissor.maxx, scissor->maxx);
		ctx->batch->max_scissor.maxy = MAX2(ctx->batch->max_scissor.maxy, scissor->maxy);
	}

	if (dirty & FD_DIRTY_VIEWPORT) {
		OUT_PKT3(ring, CP_SET_CONSTANT, 7);
		OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_VPORT_XSCALE));
		OUT_RING(ring, fui(ctx->viewport.scale[0]));       /* PA_CL_VPORT_XSCALE */
		OUT_RING(ring, fui(ctx->viewport.translate[0]));   /* PA_CL_VPORT_XOFFSET */
		OUT_RING(ring, fui(ctx->viewport.scale[1]));       /* PA_CL_VPORT_YSCALE */
		OUT_RING(ring, fui(ctx->viewport.translate[1]));   /* PA_CL_VPORT_YOFFSET */
		OUT_RING(ring, fui(ctx->viewport.scale[2]));       /* PA_CL_VPORT_ZSCALE */
		OUT_RING(ring, fui(ctx->viewport.translate[2]));   /* PA_CL_VPORT_ZOFFSET */

		OUT_PKT3(ring, CP_SET_CONSTANT, 2);
		OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_VTE_CNTL));
		OUT_RING(ring, A2XX_PA_CL_VTE_CNTL_VTX_W0_FMT |
				A2XX_PA_CL_VTE_CNTL_VPORT_X_SCALE_ENA |
				A2XX_PA_CL_VTE_CNTL_VPORT_X_OFFSET_ENA |
				A2XX_PA_CL_VTE_CNTL_VPORT_Y_SCALE_ENA |
				A2XX_PA_CL_VTE_CNTL_VPORT_Y_OFFSET_ENA |
				A2XX_PA_CL_VTE_CNTL_VPORT_Z_SCALE_ENA |
				A2XX_PA_CL_VTE_CNTL_VPORT_Z_OFFSET_ENA);
	}

	if (dirty & (FD_DIRTY_PROG | FD_DIRTY_VTXSTATE | FD_DIRTY_TEXSTATE)) {
		fd2_program_validate(ctx);
		fd2_program_emit(ring, &ctx->prog);
	}

	if (dirty & (FD_DIRTY_PROG | FD_DIRTY_CONST)) {
		emit_constants(ring,  VS_CONST_BASE * 4,
				&ctx->constbuf[PIPE_SHADER_VERTEX],
				(dirty & FD_DIRTY_PROG) ? ctx->prog.vp : NULL);
		emit_constants(ring, PS_CONST_BASE * 4,
				&ctx->constbuf[PIPE_SHADER_FRAGMENT],
				(dirty & FD_DIRTY_PROG) ? ctx->prog.fp : NULL);
	}

	if (dirty & (FD_DIRTY_BLEND | FD_DIRTY_ZSA)) {
		OUT_PKT3(ring, CP_SET_CONSTANT, 2);
		OUT_RING(ring, CP_REG(REG_A2XX_RB_COLORCONTROL));
		OUT_RING(ring, blend ? zsa->rb_colorcontrol | blend->rb_colorcontrol : 0);
	}

	if (dirty & (FD_DIRTY_BLEND | FD_DIRTY_FRAMEBUFFER)) {
		enum pipe_format format =
			pipe_surface_format(ctx->batch->framebuffer.cbufs[0]);
		bool has_alpha = util_format_has_alpha(format);

		OUT_PKT3(ring, CP_SET_CONSTANT, 2);
		OUT_RING(ring, CP_REG(REG_A2XX_RB_BLEND_CONTROL));
		OUT_RING(ring, blend ? blend->rb_blendcontrol_alpha |
			COND(has_alpha, blend->rb_blendcontrol_rgb) |
			COND(!has_alpha, blend->rb_blendcontrol_no_alpha_rgb) : 0);

		OUT_PKT3(ring, CP_SET_CONSTANT, 2);
		OUT_RING(ring, CP_REG(REG_A2XX_RB_COLOR_MASK));
		OUT_RING(ring, blend ? blend->rb_colormask : 0xf);
	}

	if (dirty & FD_DIRTY_BLEND_COLOR) {
		OUT_PKT3(ring, CP_SET_CONSTANT, 5);
		OUT_RING(ring, CP_REG(REG_A2XX_RB_BLEND_RED));
		OUT_RING(ring, float_to_ubyte(ctx->blend_color.color[0]));
		OUT_RING(ring, float_to_ubyte(ctx->blend_color.color[1]));
		OUT_RING(ring, float_to_ubyte(ctx->blend_color.color[2]));
		OUT_RING(ring, float_to_ubyte(ctx->blend_color.color[3]));
	}

	if (dirty & (FD_DIRTY_TEX | FD_DIRTY_PROG))
		emit_textures(ring, ctx);
}