Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/freedreno/a6xx/fd6_blend.c
4574 views
1
/*
2
* Copyright (C) 2016 Rob Clark <[email protected]>
3
* Copyright © 2018 Google, Inc.
4
*
5
* Permission is hereby granted, free of charge, to any person obtaining a
6
* copy of this software and associated documentation files (the "Software"),
7
* to deal in the Software without restriction, including without limitation
8
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
9
* and/or sell copies of the Software, and to permit persons to whom the
10
* Software is furnished to do so, subject to the following conditions:
11
*
12
* The above copyright notice and this permission notice (including the next
13
* paragraph) shall be included in all copies or substantial portions of the
14
* Software.
15
*
16
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
* SOFTWARE.
23
*
24
* Authors:
25
* Rob Clark <[email protected]>
26
*/
27
28
#include "pipe/p_state.h"
29
#include "util/u_blend.h"
30
#include "util/u_dual_blend.h"
31
#include "util/u_memory.h"
32
#include "util/u_string.h"
33
34
#include "fd6_blend.h"
35
#include "fd6_context.h"
36
#include "fd6_format.h"
37
#include "fd6_pack.h"
38
39
// XXX move somewhere common.. same across a3xx/a4xx/a5xx..
40
static enum a3xx_rb_blend_opcode
41
blend_func(unsigned func)
42
{
43
switch (func) {
44
case PIPE_BLEND_ADD:
45
return BLEND_DST_PLUS_SRC;
46
case PIPE_BLEND_MIN:
47
return BLEND_MIN_DST_SRC;
48
case PIPE_BLEND_MAX:
49
return BLEND_MAX_DST_SRC;
50
case PIPE_BLEND_SUBTRACT:
51
return BLEND_SRC_MINUS_DST;
52
case PIPE_BLEND_REVERSE_SUBTRACT:
53
return BLEND_DST_MINUS_SRC;
54
default:
55
DBG("invalid blend func: %x", func);
56
return 0;
57
}
58
}
59
60
struct fd6_blend_variant *
61
__fd6_setup_blend_variant(struct fd6_blend_stateobj *blend,
62
unsigned sample_mask)
63
{
64
const struct pipe_blend_state *cso = &blend->base;
65
struct fd6_blend_variant *so;
66
enum a3xx_rop_code rop = ROP_COPY;
67
bool reads_dest = false;
68
unsigned mrt_blend = 0;
69
70
if (cso->logicop_enable) {
71
rop = cso->logicop_func; /* maps 1:1 */
72
reads_dest = util_logicop_reads_dest(cso->logicop_func);
73
}
74
75
so = rzalloc_size(blend, sizeof(*so));
76
if (!so)
77
return NULL;
78
79
struct fd_ringbuffer *ring = fd_ringbuffer_new_object(
80
blend->ctx->pipe, ((A6XX_MAX_RENDER_TARGETS * 4) + 6) * 4);
81
so->stateobj = ring;
82
83
for (unsigned i = 0; i <= cso->max_rt; i++) {
84
const struct pipe_rt_blend_state *rt;
85
86
if (cso->independent_blend_enable)
87
rt = &cso->rt[i];
88
else
89
rt = &cso->rt[0];
90
91
OUT_REG(ring,
92
A6XX_RB_MRT_BLEND_CONTROL(
93
i, .rgb_src_factor = fd_blend_factor(rt->rgb_src_factor),
94
.rgb_blend_opcode = blend_func(rt->rgb_func),
95
.rgb_dest_factor = fd_blend_factor(rt->rgb_dst_factor),
96
.alpha_src_factor = fd_blend_factor(rt->alpha_src_factor),
97
.alpha_blend_opcode = blend_func(rt->alpha_func),
98
.alpha_dest_factor = fd_blend_factor(rt->alpha_dst_factor), ));
99
100
OUT_REG(ring, A6XX_RB_MRT_CONTROL(i, .rop_code = rop,
101
.rop_enable = cso->logicop_enable,
102
.component_enable = rt->colormask,
103
.blend = rt->blend_enable,
104
.blend2 = rt->blend_enable, ));
105
106
if (rt->blend_enable) {
107
mrt_blend |= (1 << i);
108
}
109
110
if (reads_dest) {
111
mrt_blend |= (1 << i);
112
}
113
}
114
115
OUT_REG(
116
ring,
117
A6XX_RB_DITHER_CNTL(
118
.dither_mode_mrt0 = cso->dither ? DITHER_ALWAYS : DITHER_DISABLE,
119
.dither_mode_mrt1 = cso->dither ? DITHER_ALWAYS : DITHER_DISABLE,
120
.dither_mode_mrt2 = cso->dither ? DITHER_ALWAYS : DITHER_DISABLE,
121
.dither_mode_mrt3 = cso->dither ? DITHER_ALWAYS : DITHER_DISABLE,
122
.dither_mode_mrt4 = cso->dither ? DITHER_ALWAYS : DITHER_DISABLE,
123
.dither_mode_mrt5 = cso->dither ? DITHER_ALWAYS : DITHER_DISABLE,
124
.dither_mode_mrt6 = cso->dither ? DITHER_ALWAYS : DITHER_DISABLE,
125
.dither_mode_mrt7 =
126
cso->dither ? DITHER_ALWAYS : DITHER_DISABLE, ));
127
128
OUT_REG(ring, A6XX_SP_BLEND_CNTL(.enable_blend = mrt_blend,
129
.unk8 = true,
130
.alpha_to_coverage = cso->alpha_to_coverage,
131
.dual_color_in_enable =
132
blend->use_dual_src_blend, ));
133
134
OUT_REG(ring,
135
A6XX_RB_BLEND_CNTL(.enable_blend = mrt_blend,
136
.alpha_to_coverage = cso->alpha_to_coverage,
137
.alpha_to_one = cso->alpha_to_one,
138
.independent_blend = cso->independent_blend_enable,
139
.sample_mask = sample_mask,
140
.dual_color_in_enable = blend->use_dual_src_blend, ));
141
142
so->sample_mask = sample_mask;
143
144
util_dynarray_append(&blend->variants, struct fd6_blend_variant *, so);
145
146
return so;
147
}
148
149
void *
150
fd6_blend_state_create(struct pipe_context *pctx,
151
const struct pipe_blend_state *cso)
152
{
153
struct fd6_blend_stateobj *so;
154
155
so = rzalloc_size(NULL, sizeof(*so));
156
if (!so)
157
return NULL;
158
159
so->base = *cso;
160
so->ctx = fd_context(pctx);
161
162
if (cso->logicop_enable) {
163
so->reads_dest |= util_logicop_reads_dest(cso->logicop_func);
164
}
165
166
so->use_dual_src_blend =
167
cso->rt[0].blend_enable && util_blend_state_is_dual(cso, 0);
168
169
unsigned nr = cso->independent_blend_enable ? cso->max_rt : 0;
170
for (unsigned i = 0; i <= nr; i++) {
171
const struct pipe_rt_blend_state *rt = &cso->rt[i];
172
173
so->reads_dest |= rt->blend_enable;
174
175
/* From the PoV of LRZ, having masked color channels is
176
* the same as having blend enabled, in that the draw will
177
* care about the fragments from an earlier draw.
178
*
179
* NOTE we actually don't care about masked color channels
180
* that don't actually exist in the render target, but we
181
* don't know the render target format here to determine
182
* that. It is probably not worth worrying about, but if
183
* we find a game/benchmark that goes out of it's way to
184
* mask off non-existent channels, we should fixup the
185
* pipe_blend_state to give us more info.
186
*/
187
if (rt->blend_enable || (rt->colormask != 0xf)) {
188
so->reads_dest = true;
189
}
190
}
191
192
util_dynarray_init(&so->variants, so);
193
194
return so;
195
}
196
197
void
198
fd6_blend_state_delete(struct pipe_context *pctx, void *hwcso)
199
{
200
struct fd6_blend_stateobj *so = hwcso;
201
202
util_dynarray_foreach (&so->variants, struct fd6_blend_variant *, vp) {
203
struct fd6_blend_variant *v = *vp;
204
fd_ringbuffer_del(v->stateobj);
205
}
206
207
ralloc_free(so);
208
}
209
210