xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/freedreno/a4xx/fd4_blend.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2014 Rob Clark <[email protected]>
3  * SPDX-License-Identifier: MIT
4  *
5  * Authors:
6  *    Rob Clark <[email protected]>
7  */
8 
9 #include "pipe/p_state.h"
10 #include "util/u_blend.h"
11 #include "util/u_memory.h"
12 #include "util/u_string.h"
13 
14 #include "fd4_blend.h"
15 #include "fd4_context.h"
16 #include "fd4_format.h"
17 
18 static enum a3xx_rb_blend_opcode
blend_func(unsigned func)19 blend_func(unsigned func)
20 {
21    switch (func) {
22    case PIPE_BLEND_ADD:
23       return BLEND_DST_PLUS_SRC;
24    case PIPE_BLEND_MIN:
25       return BLEND_MIN_DST_SRC;
26    case PIPE_BLEND_MAX:
27       return BLEND_MAX_DST_SRC;
28    case PIPE_BLEND_SUBTRACT:
29       return BLEND_SRC_MINUS_DST;
30    case PIPE_BLEND_REVERSE_SUBTRACT:
31       return BLEND_DST_MINUS_SRC;
32    default:
33       DBG("invalid blend func: %x", func);
34       return 0;
35    }
36 }
37 
38 void *
fd4_blend_state_create(struct pipe_context * pctx,const struct pipe_blend_state * cso)39 fd4_blend_state_create(struct pipe_context *pctx,
40                        const struct pipe_blend_state *cso)
41 {
42    struct fd4_blend_stateobj *so;
43    enum a3xx_rop_code rop = ROP_COPY;
44    bool reads_dest = false;
45    unsigned i, mrt_blend = 0;
46 
47    if (cso->logicop_enable) {
48       rop = cso->logicop_func; /* maps 1:1 */
49       reads_dest = util_logicop_reads_dest(cso->logicop_func);
50    }
51 
52    so = CALLOC_STRUCT(fd4_blend_stateobj);
53    if (!so)
54       return NULL;
55 
56    so->base = *cso;
57 
58    for (i = 0; i < ARRAY_SIZE(so->rb_mrt); i++) {
59       const struct pipe_rt_blend_state *rt;
60 
61       if (cso->independent_blend_enable)
62          rt = &cso->rt[i];
63       else
64          rt = &cso->rt[0];
65 
66       so->rb_mrt[i].blend_control =
67          A4XX_RB_MRT_BLEND_CONTROL_RGB_SRC_FACTOR(
68             fd_blend_factor(rt->rgb_src_factor)) |
69          A4XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE(blend_func(rt->rgb_func)) |
70          A4XX_RB_MRT_BLEND_CONTROL_RGB_DEST_FACTOR(
71             fd_blend_factor(rt->rgb_dst_factor)) |
72          A4XX_RB_MRT_BLEND_CONTROL_ALPHA_SRC_FACTOR(
73             fd_blend_factor(rt->alpha_src_factor)) |
74          A4XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE(
75             blend_func(rt->alpha_func)) |
76          A4XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR(
77             fd_blend_factor(rt->alpha_dst_factor));
78 
79       so->rb_mrt[i].control =
80          A4XX_RB_MRT_CONTROL_ROP_CODE(rop) |
81          COND(cso->logicop_enable, A4XX_RB_MRT_CONTROL_ROP_ENABLE) |
82          A4XX_RB_MRT_CONTROL_COMPONENT_ENABLE(rt->colormask);
83 
84       if (rt->blend_enable) {
85          so->rb_mrt[i].control |= A4XX_RB_MRT_CONTROL_READ_DEST_ENABLE |
86                                   A4XX_RB_MRT_CONTROL_BLEND |
87                                   A4XX_RB_MRT_CONTROL_BLEND2;
88          mrt_blend |= (1 << i);
89       }
90 
91       if (reads_dest) {
92          so->rb_mrt[i].control |= A4XX_RB_MRT_CONTROL_READ_DEST_ENABLE;
93          mrt_blend |= (1 << i);
94       }
95 
96       if (cso->dither)
97          so->rb_mrt[i].buf_info |=
98             A4XX_RB_MRT_BUF_INFO_DITHER_MODE(DITHER_ALWAYS);
99    }
100 
101    so->rb_fs_output =
102       A4XX_RB_FS_OUTPUT_ENABLE_BLEND(mrt_blend) |
103       COND(cso->independent_blend_enable, A4XX_RB_FS_OUTPUT_INDEPENDENT_BLEND);
104 
105    return so;
106 }
107