示例#1
0
static void *
nv50_blend_state_create(struct pipe_context *pipe,
			const struct pipe_blend_state *cso)
{
	struct nouveau_stateobj *so = so_new(64, 0);
	struct nouveau_grobj *tesla = nv50_context(pipe)->screen->tesla;
	struct nv50_blend_stateobj *bso = CALLOC_STRUCT(nv50_blend_stateobj);
	unsigned cmask = 0, i;

	/*XXX ignored:
	 * 	- dither
	 */

	if (cso->blend_enable == 0) {
		so_method(so, tesla, NV50TCL_BLEND_ENABLE(0), 8);
		for (i = 0; i < 8; i++)
			so_data(so, 0);
	} else {
		so_method(so, tesla, NV50TCL_BLEND_ENABLE(0), 8);
		for (i = 0; i < 8; i++)
			so_data(so, 1);
		so_method(so, tesla, NV50TCL_BLEND_EQUATION_RGB, 5);
		so_data  (so, nvgl_blend_eqn(cso->rgb_func));
		so_data  (so, 0x4000 | nvgl_blend_func(cso->rgb_src_factor));
		so_data  (so, 0x4000 | nvgl_blend_func(cso->rgb_dst_factor));
		so_data  (so, nvgl_blend_eqn(cso->alpha_func));
		so_data  (so, 0x4000 | nvgl_blend_func(cso->alpha_src_factor));
		so_method(so, tesla, NV50TCL_BLEND_FUNC_DST_ALPHA, 1);
		so_data  (so, 0x4000 | nvgl_blend_func(cso->alpha_dst_factor));
	}

	if (cso->logicop_enable == 0 ) {
		so_method(so, tesla, NV50TCL_LOGIC_OP_ENABLE, 1);
		so_data  (so, 0);
	} else {
		so_method(so, tesla, NV50TCL_LOGIC_OP_ENABLE, 2);
		so_data  (so, 1);
		so_data  (so, nvgl_logicop_func(cso->logicop_func));
	}

	if (cso->colormask & PIPE_MASK_R)
		cmask |= (1 << 0);
	if (cso->colormask & PIPE_MASK_G)
		cmask |= (1 << 4);
	if (cso->colormask & PIPE_MASK_B)
		cmask |= (1 << 8);
	if (cso->colormask & PIPE_MASK_A)
		cmask |= (1 << 12);
	so_method(so, tesla, NV50TCL_COLOR_MASK(0), 8);
	for (i = 0; i < 8; i++)
		so_data(so, cmask);

	bso->pipe = *cso;
	so_ref(so, &bso->so);
	so_ref(NULL, &so);
	return (void *)bso;
}
示例#2
0
static void *
nv40_blend_state_create(struct pipe_context *pipe,
			const struct pipe_blend_state *cso)
{
	struct nv40_context *nv40 = nv40_context(pipe);
	struct nouveau_grobj *curie = nv40->screen->curie;
	struct nv40_blend_state *bso = CALLOC(1, sizeof(*bso));
	struct nouveau_stateobj *so = so_new(16, 0);

	if (cso->blend_enable) {
		so_method(so, curie, NV40TCL_BLEND_ENABLE, 3);
		so_data  (so, 1);
		so_data  (so, (nvgl_blend_func(cso->alpha_src_factor) << 16) |
			       nvgl_blend_func(cso->rgb_src_factor));
		so_data  (so, nvgl_blend_func(cso->alpha_dst_factor) << 16 |
			      nvgl_blend_func(cso->rgb_dst_factor));
		so_method(so, curie, NV40TCL_BLEND_EQUATION, 1);
		so_data  (so, nvgl_blend_eqn(cso->alpha_func) << 16 |
			      nvgl_blend_eqn(cso->rgb_func));
	} else {
		so_method(so, curie, NV40TCL_BLEND_ENABLE, 1);
		so_data  (so, 0);
	}

	so_method(so, curie, NV40TCL_COLOR_MASK, 1);
	so_data  (so, (((cso->colormask & PIPE_MASK_A) ? (0x01 << 24) : 0) |
		       ((cso->colormask & PIPE_MASK_R) ? (0x01 << 16) : 0) |
		       ((cso->colormask & PIPE_MASK_G) ? (0x01 <<  8) : 0) |
		       ((cso->colormask & PIPE_MASK_B) ? (0x01 <<  0) : 0)));

	if (cso->logicop_enable) {
		so_method(so, curie, NV40TCL_COLOR_LOGIC_OP_ENABLE, 2);
		so_data  (so, 1);
		so_data  (so, nvgl_logicop_func(cso->logicop_func));
	} else {
		so_method(so, curie, NV40TCL_COLOR_LOGIC_OP_ENABLE, 1);
		so_data  (so, 0);
	}

	so_method(so, curie, NV40TCL_DITHER_ENABLE, 1);
	so_data  (so, cso->dither ? 1 : 0);

	so_ref(so, &bso->so);
	so_ref(NULL, &so);
	bso->pipe = *cso;
	return (void *)bso;
}
void
nv10_emit_blend_equation(struct gl_context *ctx, int emit)
{
	struct nouveau_pushbuf *push = context_push(ctx);

	BEGIN_NV04(push, NV10_3D(BLEND_FUNC_ENABLE), 1);
	PUSH_DATAb(push, ctx->Color.BlendEnabled);

	BEGIN_NV04(push, NV10_3D(BLEND_EQUATION), 1);
	PUSH_DATA (push, nvgl_blend_eqn(ctx->Color.Blend[0].EquationRGB));
}
static void *
nv50_blend_state_create(struct pipe_context *pipe,
                        const struct pipe_blend_state *cso)
{
   struct nv50_blend_stateobj *so = CALLOC_STRUCT(nv50_blend_stateobj);
   int i;
   boolean emit_common_func = cso->rt[0].blend_enable;
   uint32_t ms;

   if (nv50_context(pipe)->screen->tesla->oclass >= NVA3_3D_CLASS) {
      SB_BEGIN_3D(so, BLEND_INDEPENDENT, 1);
      SB_DATA    (so, cso->independent_blend_enable);
   }

   so->pipe = *cso;

   SB_BEGIN_3D(so, COLOR_MASK_COMMON, 1);
   SB_DATA    (so, !cso->independent_blend_enable);

   SB_BEGIN_3D(so, BLEND_ENABLE_COMMON, 1);
   SB_DATA    (so, !cso->independent_blend_enable);

   if (cso->independent_blend_enable) {
      SB_BEGIN_3D(so, BLEND_ENABLE(0), 8);
      for (i = 0; i < 8; ++i) {
         SB_DATA(so, cso->rt[i].blend_enable);
         if (cso->rt[i].blend_enable)
            emit_common_func = TRUE;
      }

      if (nv50_context(pipe)->screen->tesla->oclass >= NVA3_3D_CLASS) {
         emit_common_func = FALSE;

         for (i = 0; i < 8; ++i) {
            if (!cso->rt[i].blend_enable)
               continue;
            SB_BEGIN_3D_(so, NVA3_3D_IBLEND_EQUATION_RGB(i), 6);
            SB_DATA     (so, nvgl_blend_eqn(cso->rt[i].rgb_func));
            SB_DATA     (so, nv50_blend_fac(cso->rt[i].rgb_src_factor));
            SB_DATA     (so, nv50_blend_fac(cso->rt[i].rgb_dst_factor));
            SB_DATA     (so, nvgl_blend_eqn(cso->rt[i].alpha_func));
            SB_DATA     (so, nv50_blend_fac(cso->rt[i].alpha_src_factor));
            SB_DATA     (so, nv50_blend_fac(cso->rt[i].alpha_dst_factor));
         }
      }
   } else {
      SB_BEGIN_3D(so, BLEND_ENABLE(0), 1);
      SB_DATA    (so, cso->rt[0].blend_enable);
   }

   if (emit_common_func) {
      SB_BEGIN_3D(so, BLEND_EQUATION_RGB, 5);
      SB_DATA    (so, nvgl_blend_eqn(cso->rt[0].rgb_func));
      SB_DATA    (so, nv50_blend_fac(cso->rt[0].rgb_src_factor));
      SB_DATA    (so, nv50_blend_fac(cso->rt[0].rgb_dst_factor));
      SB_DATA    (so, nvgl_blend_eqn(cso->rt[0].alpha_func));
      SB_DATA    (so, nv50_blend_fac(cso->rt[0].alpha_src_factor));
      SB_BEGIN_3D(so, BLEND_FUNC_DST_ALPHA, 1);
      SB_DATA    (so, nv50_blend_fac(cso->rt[0].alpha_dst_factor));
   }

   if (cso->logicop_enable) {
      SB_BEGIN_3D(so, LOGIC_OP_ENABLE, 2);
      SB_DATA    (so, 1);
      SB_DATA    (so, nvgl_logicop_func(cso->logicop_func));
   } else {
      SB_BEGIN_3D(so, LOGIC_OP_ENABLE, 1);
      SB_DATA    (so, 0);
   }

   if (cso->independent_blend_enable) {
      SB_BEGIN_3D(so, COLOR_MASK(0), 8);
      for (i = 0; i < 8; ++i)
         SB_DATA(so, nv50_colormask(cso->rt[i].colormask));
   } else {
      SB_BEGIN_3D(so, COLOR_MASK(0), 1);
      SB_DATA    (so, nv50_colormask(cso->rt[0].colormask));
   }

   ms = 0;
   if (cso->alpha_to_coverage)
      ms |= NV50_3D_MULTISAMPLE_CTRL_ALPHA_TO_COVERAGE;
   if (cso->alpha_to_one)
      ms |= NV50_3D_MULTISAMPLE_CTRL_ALPHA_TO_ONE;

   SB_BEGIN_3D(so, MULTISAMPLE_CTRL, 1);
   SB_DATA    (so, ms);

   assert(so->size <= (sizeof(so->state) / sizeof(so->state[0])));
   return so;
}
示例#5
0
static void *
nvc0_blend_state_create(struct pipe_context *pipe,
                        const struct pipe_blend_state *cso)
{
   struct nvc0_blend_stateobj *so = CALLOC_STRUCT(nvc0_blend_stateobj);
   int i;
   int r; /* reference */
   uint8_t blend_en = 0;
   bool indep_masks = false;
   bool indep_funcs = false;

   so->pipe = *cso;

   /* check which states actually have differing values */
   if (cso->independent_blend_enable) {
      for (r = 0; r < 8 && !cso->rt[r].blend_enable; ++r);
      blend_en |= 1 << r;
      for (i = r + 1; i < 8; ++i) {
         if (!cso->rt[i].blend_enable)
            continue;
         blend_en |= 1 << i;
         if (cso->rt[i].rgb_func != cso->rt[r].rgb_func ||
             cso->rt[i].rgb_src_factor != cso->rt[r].rgb_src_factor ||
             cso->rt[i].rgb_dst_factor != cso->rt[r].rgb_dst_factor ||
             cso->rt[i].alpha_func != cso->rt[r].alpha_func ||
             cso->rt[i].alpha_src_factor != cso->rt[r].alpha_src_factor ||
             cso->rt[i].alpha_dst_factor != cso->rt[r].alpha_dst_factor) {
            indep_funcs = true;
            break;
         }
      }
      for (; i < 8; ++i)
         blend_en |= (cso->rt[i].blend_enable ? 1 : 0) << i;

      for (i = 1; i < 8; ++i) {
         if (cso->rt[i].colormask != cso->rt[0].colormask) {
            indep_masks = true;
            break;
         }
      }
   } else {
      r = 0;
      if (cso->rt[0].blend_enable)
         blend_en = 0xff;
   }

   if (cso->logicop_enable) {
      SB_BEGIN_3D(so, LOGIC_OP_ENABLE, 2);
      SB_DATA    (so, 1);
      SB_DATA    (so, nvgl_logicop_func(cso->logicop_func));

      SB_IMMED_3D(so, MACRO_BLEND_ENABLES, 0);
   } else {
      SB_IMMED_3D(so, LOGIC_OP_ENABLE, 0);

      SB_IMMED_3D(so, BLEND_INDEPENDENT, indep_funcs);
      SB_IMMED_3D(so, MACRO_BLEND_ENABLES, blend_en);
      if (indep_funcs) {
         for (i = 0; i < 8; ++i) {
            if (cso->rt[i].blend_enable) {
               SB_BEGIN_3D(so, IBLEND_EQUATION_RGB(i), 6);
               SB_DATA    (so, nvgl_blend_eqn(cso->rt[i].rgb_func));
               SB_DATA    (so, nvc0_blend_fac(cso->rt[i].rgb_src_factor));
               SB_DATA    (so, nvc0_blend_fac(cso->rt[i].rgb_dst_factor));
               SB_DATA    (so, nvgl_blend_eqn(cso->rt[i].alpha_func));
               SB_DATA    (so, nvc0_blend_fac(cso->rt[i].alpha_src_factor));
               SB_DATA    (so, nvc0_blend_fac(cso->rt[i].alpha_dst_factor));
            }
         }
      } else
      if (blend_en) {
         SB_BEGIN_3D(so, BLEND_EQUATION_RGB, 5);
         SB_DATA    (so, nvgl_blend_eqn(cso->rt[r].rgb_func));
         SB_DATA    (so, nvc0_blend_fac(cso->rt[r].rgb_src_factor));
         SB_DATA    (so, nvc0_blend_fac(cso->rt[r].rgb_dst_factor));
         SB_DATA    (so, nvgl_blend_eqn(cso->rt[r].alpha_func));
         SB_DATA    (so, nvc0_blend_fac(cso->rt[r].alpha_src_factor));
         SB_BEGIN_3D(so, BLEND_FUNC_DST_ALPHA, 1);
         SB_DATA    (so, nvc0_blend_fac(cso->rt[r].alpha_dst_factor));
      }

      SB_IMMED_3D(so, COLOR_MASK_COMMON, !indep_masks);
      if (indep_masks) {
         SB_BEGIN_3D(so, COLOR_MASK(0), 8);
         for (i = 0; i < 8; ++i)
            SB_DATA(so, nvc0_colormask(cso->rt[i].colormask));
      } else {
         SB_BEGIN_3D(so, COLOR_MASK(0), 1);
         SB_DATA    (so, nvc0_colormask(cso->rt[0].colormask));
      }
   }

   assert(so->size <= ARRAY_SIZE(so->state));
   return so;
}
示例#6
0
static void *
nv50_blend_state_create(struct pipe_context *pipe,
                        const struct pipe_blend_state *cso)
{
   struct nv50_blend_stateobj *so = CALLOC_STRUCT(nv50_blend_stateobj);
   int i;
   bool emit_common_func = cso->rt[0].blend_enable;

   if (nv50_context(pipe)->screen->tesla->oclass >= NVA3_3D_CLASS) {
      SB_BEGIN_3D(so, BLEND_INDEPENDENT, 1);
      SB_DATA    (so, cso->independent_blend_enable);
   }

   so->pipe = *cso;

   SB_BEGIN_3D(so, COLOR_MASK_COMMON, 1);
   SB_DATA    (so, !cso->independent_blend_enable);

   SB_BEGIN_3D(so, BLEND_ENABLE_COMMON, 1);
   SB_DATA    (so, !cso->independent_blend_enable);

   if (cso->independent_blend_enable) {
      SB_BEGIN_3D(so, BLEND_ENABLE(0), 8);
      for (i = 0; i < 8; ++i) {
         SB_DATA(so, cso->rt[i].blend_enable);
         if (cso->rt[i].blend_enable)
            emit_common_func = true;
      }

      if (nv50_context(pipe)->screen->tesla->oclass >= NVA3_3D_CLASS) {
         emit_common_func = false;

         for (i = 0; i < 8; ++i) {
            if (!cso->rt[i].blend_enable)
               continue;
            SB_BEGIN_3D_(so, NVA3_3D_IBLEND_EQUATION_RGB(i), 6);
            SB_DATA     (so, nvgl_blend_eqn(cso->rt[i].rgb_func));
            SB_DATA     (so, nv50_blend_fac(cso->rt[i].rgb_src_factor));
            SB_DATA     (so, nv50_blend_fac(cso->rt[i].rgb_dst_factor));
            SB_DATA     (so, nvgl_blend_eqn(cso->rt[i].alpha_func));
            SB_DATA     (so, nv50_blend_fac(cso->rt[i].alpha_src_factor));
            SB_DATA     (so, nv50_blend_fac(cso->rt[i].alpha_dst_factor));
         }
      }
   } else {
      SB_BEGIN_3D(so, BLEND_ENABLE(0), 1);
      SB_DATA    (so, cso->rt[0].blend_enable);
   }

   if (emit_common_func) {
      SB_BEGIN_3D(so, BLEND_EQUATION_RGB, 5);
      SB_DATA    (so, nvgl_blend_eqn(cso->rt[0].rgb_func));
      SB_DATA    (so, nv50_blend_fac(cso->rt[0].rgb_src_factor));
      SB_DATA    (so, nv50_blend_fac(cso->rt[0].rgb_dst_factor));
      SB_DATA    (so, nvgl_blend_eqn(cso->rt[0].alpha_func));
      SB_DATA    (so, nv50_blend_fac(cso->rt[0].alpha_src_factor));
      SB_BEGIN_3D(so, BLEND_FUNC_DST_ALPHA, 1);
      SB_DATA    (so, nv50_blend_fac(cso->rt[0].alpha_dst_factor));
   }

   if (cso->logicop_enable) {
      SB_BEGIN_3D(so, LOGIC_OP_ENABLE, 2);
      SB_DATA    (so, 1);
      SB_DATA    (so, nvgl_logicop_func(cso->logicop_func));
   } else {
      SB_BEGIN_3D(so, LOGIC_OP_ENABLE, 1);
      SB_DATA    (so, 0);
   }

   if (cso->independent_blend_enable) {
      SB_BEGIN_3D(so, COLOR_MASK(0), 8);
      for (i = 0; i < 8; ++i)
         SB_DATA(so, nv50_colormask(cso->rt[i].colormask));
   } else {
      SB_BEGIN_3D(so, COLOR_MASK(0), 1);
      SB_DATA    (so, nv50_colormask(cso->rt[0].colormask));
   }

   assert(so->size <= ARRAY_SIZE(so->state));
   return so;
}
示例#7
0
static void *
nv50_blend_state_create(struct pipe_context *pipe,
                        const struct pipe_blend_state *cso)
{
    struct nouveau_stateobj *so = so_new(5, 24, 0);
    struct nouveau_grobj *tesla = nv50_context(pipe)->screen->tesla;
    struct nv50_blend_stateobj *bso = CALLOC_STRUCT(nv50_blend_stateobj);
    unsigned i, blend_enabled = 0;

    /*XXX ignored:
     * 	- dither
     */

    so_method(so, tesla, NV50TCL_BLEND_ENABLE(0), 8);
    if (cso->independent_blend_enable) {
        for (i = 0; i < 8; ++i) {
            so_data(so, cso->rt[i].blend_enable);
            if (cso->rt[i].blend_enable)
                blend_enabled = 1;
        }
    } else if (cso->rt[0].blend_enable) {
        blend_enabled = 1;
        for (i = 0; i < 8; i++)
            so_data(so, 1);
    } else {
        for (i = 0; i < 8; i++)
            so_data(so, 0);
    }
    if (blend_enabled) {
        so_method(so, tesla, NV50TCL_BLEND_EQUATION_RGB, 5);
        so_data  (so, nvgl_blend_eqn(cso->rt[0].rgb_func));
        so_data  (so, 0x4000 | nvgl_blend_func(cso->rt[0].rgb_src_factor));
        so_data  (so, 0x4000 | nvgl_blend_func(cso->rt[0].rgb_dst_factor));
        so_data  (so, nvgl_blend_eqn(cso->rt[0].alpha_func));
        so_data  (so, 0x4000 | nvgl_blend_func(cso->rt[0].alpha_src_factor));
        so_method(so, tesla, NV50TCL_BLEND_FUNC_DST_ALPHA, 1);
        so_data  (so, 0x4000 | nvgl_blend_func(cso->rt[0].alpha_dst_factor));
    }

    if (cso->logicop_enable == 0 ) {
        so_method(so, tesla, NV50TCL_LOGIC_OP_ENABLE, 1);
        so_data  (so, 0);
    } else {
        so_method(so, tesla, NV50TCL_LOGIC_OP_ENABLE, 2);
        so_data  (so, 1);
        so_data  (so, nvgl_logicop_func(cso->logicop_func));
    }

    so_method(so, tesla, NV50TCL_COLOR_MASK(0), 8);
    if (cso->independent_blend_enable)
        for (i = 0; i < 8; ++i)
            so_data(so, nv50_colormask(cso->rt[i].colormask));
    else {
        uint32_t cmask = nv50_colormask(cso->rt[0].colormask);
        for (i = 0; i < 8; i++)
            so_data(so, cmask);
    }

    bso->pipe = *cso;
    so_ref(so, &bso->so);
    so_ref(NULL, &so);
    return (void *)bso;
}
示例#8
0
static void *
nv30_blend_state_create(struct pipe_context *pipe,
                        const struct pipe_blend_state *cso)
{
   struct nouveau_object *eng3d = nv30_context(pipe)->screen->eng3d;
   struct nv30_blend_stateobj *so;
   uint32_t blend[2], cmask[2];
   int i;

   so = CALLOC_STRUCT(nv30_blend_stateobj);
   if (!so)
      return NULL;
   so->pipe = *cso;

   if (cso->logicop_enable) {
      SB_MTHD30(so, COLOR_LOGIC_OP_ENABLE, 2);
      SB_DATA  (so, 1);
      SB_DATA  (so, nvgl_logicop_func(cso->logicop_func));
   } else {
      SB_MTHD30(so, COLOR_LOGIC_OP_ENABLE, 1);
      SB_DATA  (so, 0);
   }

   SB_MTHD30(so, DITHER_ENABLE, 1);
   SB_DATA  (so, cso->dither);

   blend[0] = cso->rt[0].blend_enable;
   cmask[0] = !!(cso->rt[0].colormask & PIPE_MASK_A) << 24 |
              !!(cso->rt[0].colormask & PIPE_MASK_R) << 16 |
              !!(cso->rt[0].colormask & PIPE_MASK_G) <<  8 |
              !!(cso->rt[0].colormask & PIPE_MASK_B);
   if (cso->independent_blend_enable) {
      blend[1] = 0;
      cmask[1] = 0;
      for (i = 1; i < 4; i++) {
         blend[1] |= cso->rt[i].blend_enable << i;
         cmask[1] |= !!(cso->rt[i].colormask & PIPE_MASK_A) << (0 + (i * 4)) |
                     !!(cso->rt[i].colormask & PIPE_MASK_R) << (1 + (i * 4)) |
                     !!(cso->rt[i].colormask & PIPE_MASK_G) << (2 + (i * 4)) |
                     !!(cso->rt[i].colormask & PIPE_MASK_B) << (3 + (i * 4));
      }
   } else {
      blend[1]  = 0x0000000e *   (blend[0] & 0x00000001);
      cmask[1]  = 0x00001110 * !!(cmask[0] & 0x01000000);
      cmask[1] |= 0x00002220 * !!(cmask[0] & 0x00010000);
      cmask[1] |= 0x00004440 * !!(cmask[0] & 0x00000100);
      cmask[1] |= 0x00008880 * !!(cmask[0] & 0x00000001);
   }

   if (eng3d->oclass >= NV40_3D_CLASS) {
      SB_MTHD40(so, MRT_BLEND_ENABLE, 2);
      SB_DATA  (so, blend[1]);
      SB_DATA  (so, cmask[1]);
   }

   if (blend[0] || blend[1]) {
      SB_MTHD30(so, BLEND_FUNC_ENABLE, 3);
      SB_DATA  (so, blend[0]);
      SB_DATA  (so, (nvgl_blend_func(cso->rt[0].alpha_src_factor) << 16) |
                     nvgl_blend_func(cso->rt[0].rgb_src_factor));
      SB_DATA  (so, (nvgl_blend_func(cso->rt[0].alpha_dst_factor) << 16) |
                     nvgl_blend_func(cso->rt[0].rgb_dst_factor));
      if (eng3d->oclass < NV40_3D_CLASS) {
         SB_MTHD30(so, BLEND_EQUATION, 1);
         SB_DATA  (so, nvgl_blend_eqn(cso->rt[0].rgb_func));
      } else {
         SB_MTHD40(so, BLEND_EQUATION, 1);
         SB_DATA  (so, (nvgl_blend_eqn(cso->rt[0].alpha_func) << 16) |
                        nvgl_blend_eqn(cso->rt[0].rgb_func));
      }
   } else {
      SB_MTHD30(so, BLEND_FUNC_ENABLE, 1);
      SB_DATA  (so, blend[0]);
   }

   SB_MTHD30(so, COLOR_MASK, 1);
   SB_DATA  (so, cmask[0]);
   return so;
}
示例#9
0
文件: nvc0_state.c 项目: nikai3d/mesa
static void *
nvc0_blend_state_create(struct pipe_context *pipe,
                        const struct pipe_blend_state *cso)
{
    struct nvc0_blend_stateobj *so = CALLOC_STRUCT(nvc0_blend_stateobj);
    int i;
    uint32_t ms;

    so->pipe = *cso;

    SB_IMMED_3D(so, BLEND_INDEPENDENT, cso->independent_blend_enable);

    if (!cso->logicop_enable)
       SB_IMMED_3D(so, LOGIC_OP_ENABLE, 0);

    if (cso->logicop_enable) {
       SB_BEGIN_3D(so, LOGIC_OP_ENABLE, 2);
       SB_DATA    (so, 1);
       SB_DATA    (so, nvgl_logicop_func(cso->logicop_func));

       SB_IMMED_3D(so, BLEND_ENABLES, 0);
    } else
    if (!cso->independent_blend_enable) {
        SB_IMMED_3D(so, BLEND_ENABLES, cso->rt[0].blend_enable ? 0xff : 0);

        if (cso->rt[0].blend_enable) {
            SB_BEGIN_3D(so, BLEND_EQUATION_RGB, 5);
            SB_DATA    (so, nvgl_blend_eqn(cso->rt[0].rgb_func));
            SB_DATA    (so, nvc0_blend_fac(cso->rt[0].rgb_src_factor));
            SB_DATA    (so, nvc0_blend_fac(cso->rt[0].rgb_dst_factor));
            SB_DATA    (so, nvgl_blend_eqn(cso->rt[0].alpha_func));
            SB_DATA    (so, nvc0_blend_fac(cso->rt[0].alpha_src_factor));
            SB_BEGIN_3D(so, BLEND_FUNC_DST_ALPHA, 1);
            SB_DATA    (so, nvc0_blend_fac(cso->rt[0].alpha_dst_factor));
        }

        SB_IMMED_3D(so, COLOR_MASK_COMMON, 1);
        SB_BEGIN_3D(so, COLOR_MASK(0), 1);
        SB_DATA    (so, nvc0_colormask(cso->rt[0].colormask));
    } else {
        uint8_t en = 0;

        for (i = 0; i < 8; ++i) {
            if (!cso->rt[i].blend_enable)
                continue;
            en |= 1 << i;

            SB_BEGIN_3D(so, IBLEND_EQUATION_RGB(i), 6);
            SB_DATA    (so, nvgl_blend_eqn(cso->rt[i].rgb_func));
            SB_DATA    (so, nvc0_blend_fac(cso->rt[i].rgb_src_factor));
            SB_DATA    (so, nvc0_blend_fac(cso->rt[i].rgb_dst_factor));
            SB_DATA    (so, nvgl_blend_eqn(cso->rt[i].alpha_func));
            SB_DATA    (so, nvc0_blend_fac(cso->rt[i].alpha_src_factor));
            SB_DATA    (so, nvc0_blend_fac(cso->rt[i].alpha_dst_factor));
        }
        SB_IMMED_3D(so, BLEND_ENABLES, en);

        SB_IMMED_3D(so, COLOR_MASK_COMMON, 0);
        SB_BEGIN_3D(so, COLOR_MASK(0), 8);
        for (i = 0; i < 8; ++i)
            SB_DATA(so, nvc0_colormask(cso->rt[i].colormask));
    }

    ms = 0;
    if (cso->alpha_to_coverage)
       ms |= NVC0_3D_MULTISAMPLE_CTRL_ALPHA_TO_COVERAGE;
    if (cso->alpha_to_one)
       ms |= NVC0_3D_MULTISAMPLE_CTRL_ALPHA_TO_ONE;

    SB_BEGIN_3D(so, MULTISAMPLE_CTRL, 1);
    SB_DATA    (so, ms);

    assert(so->size <= (sizeof(so->state) / sizeof(so->state[0])));
    return so;
}