Welcome to mirror list, hosted at ThFree Co, Russian Federation.

draw_state.h « intern « draw « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: bf1e63e0852f0771b3fbc58d376e5d740426bc42 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/* SPDX-License-Identifier: GPL-2.0-or-later
 * Copyright 2022 Blender Foundation. */

#pragma once

#ifdef __cplusplus
extern "C" {
#endif

/** \file
 * \ingroup draw
 *
 * Internal Pipeline State tracking. It is higher level than GPU state as everything fits a single
 * enum.
 */

/**
 * DRWState is a bit-mask that stores the current render state and the desired render state. Based
 * on the differences the minimum state changes can be invoked to setup the desired render state.
 *
 * The Write Stencil, Stencil test, Depth test and Blend state options are mutual exclusive
 * therefore they aren't ordered as a bit mask.
 */
typedef enum {
  /** To be used for compute passes. */
  DRW_STATE_NO_DRAW = 0,
  /** Write mask */
  DRW_STATE_WRITE_DEPTH = (1 << 0),
  DRW_STATE_WRITE_COLOR = (1 << 1),
  /* Write Stencil. These options are mutual exclusive and packed into 2 bits */
  DRW_STATE_WRITE_STENCIL = (1 << 2),
  DRW_STATE_WRITE_STENCIL_SHADOW_PASS = (2 << 2),
  DRW_STATE_WRITE_STENCIL_SHADOW_FAIL = (3 << 2),
  /** Depth test. These options are mutual exclusive and packed into 3 bits */
  DRW_STATE_DEPTH_ALWAYS = (1 << 4),
  DRW_STATE_DEPTH_LESS = (2 << 4),
  DRW_STATE_DEPTH_LESS_EQUAL = (3 << 4),
  DRW_STATE_DEPTH_EQUAL = (4 << 4),
  DRW_STATE_DEPTH_GREATER = (5 << 4),
  DRW_STATE_DEPTH_GREATER_EQUAL = (6 << 4),
  /** Culling test */
  DRW_STATE_CULL_BACK = (1 << 7),
  DRW_STATE_CULL_FRONT = (1 << 8),
  /** Stencil test. These options are mutually exclusive and packed into 2 bits. */
  DRW_STATE_STENCIL_ALWAYS = (1 << 9),
  DRW_STATE_STENCIL_EQUAL = (2 << 9),
  DRW_STATE_STENCIL_NEQUAL = (3 << 9),

  /** Blend state. These options are mutual exclusive and packed into 4 bits */
  DRW_STATE_BLEND_ADD = (1 << 11),
  /** Same as additive but let alpha accumulate without pre-multiply. */
  DRW_STATE_BLEND_ADD_FULL = (2 << 11),
  /** Standard alpha blending. */
  DRW_STATE_BLEND_ALPHA = (3 << 11),
  /** Use that if color is already pre-multiply by alpha. */
  DRW_STATE_BLEND_ALPHA_PREMUL = (4 << 11),
  DRW_STATE_BLEND_BACKGROUND = (5 << 11),
  DRW_STATE_BLEND_OIT = (6 << 11),
  DRW_STATE_BLEND_MUL = (7 << 11),
  DRW_STATE_BLEND_SUB = (8 << 11),
  /** Use dual source blending. WARNING: Only one color buffer allowed. */
  DRW_STATE_BLEND_CUSTOM = (9 << 11),
  DRW_STATE_LOGIC_INVERT = (10 << 11),
  DRW_STATE_BLEND_ALPHA_UNDER_PREMUL = (11 << 11),

  DRW_STATE_IN_FRONT_SELECT = (1 << 27),
  DRW_STATE_SHADOW_OFFSET = (1 << 28),
  DRW_STATE_CLIP_PLANES = (1 << 29),
  DRW_STATE_FIRST_VERTEX_CONVENTION = (1 << 30),
  /** DO NOT USE. Assumed always enabled. Only used internally. */
  DRW_STATE_PROGRAM_POINT_SIZE = (1u << 31),
} DRWState;

ENUM_OPERATORS(DRWState, DRW_STATE_PROGRAM_POINT_SIZE);

#define DRW_STATE_DEFAULT \
  (DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL)
#define DRW_STATE_BLEND_ENABLED \
  (DRW_STATE_BLEND_ADD | DRW_STATE_BLEND_ADD_FULL | DRW_STATE_BLEND_ALPHA | \
   DRW_STATE_BLEND_ALPHA_PREMUL | DRW_STATE_BLEND_BACKGROUND | DRW_STATE_BLEND_OIT | \
   DRW_STATE_BLEND_MUL | DRW_STATE_BLEND_SUB | DRW_STATE_BLEND_CUSTOM | DRW_STATE_LOGIC_INVERT)
#define DRW_STATE_RASTERIZER_ENABLED \
  (DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_STENCIL | \
   DRW_STATE_WRITE_STENCIL_SHADOW_PASS | DRW_STATE_WRITE_STENCIL_SHADOW_FAIL)
#define DRW_STATE_DEPTH_TEST_ENABLED \
  (DRW_STATE_DEPTH_ALWAYS | DRW_STATE_DEPTH_LESS | DRW_STATE_DEPTH_LESS_EQUAL | \
   DRW_STATE_DEPTH_EQUAL | DRW_STATE_DEPTH_GREATER | DRW_STATE_DEPTH_GREATER_EQUAL)
#define DRW_STATE_STENCIL_TEST_ENABLED \
  (DRW_STATE_STENCIL_ALWAYS | DRW_STATE_STENCIL_EQUAL | DRW_STATE_STENCIL_NEQUAL)
#define DRW_STATE_WRITE_STENCIL_ENABLED \
  (DRW_STATE_WRITE_STENCIL | DRW_STATE_WRITE_STENCIL_SHADOW_PASS | \
   DRW_STATE_WRITE_STENCIL_SHADOW_FAIL)

#ifdef __cplusplus
}
#endif

#ifdef __cplusplus

namespace blender::draw {

/* -------------------------------------------------------------------- */
/** \name DRWState to GPU state conversion
 * \{ */

static inline eGPUWriteMask to_write_mask(DRWState state)
{
  eGPUWriteMask write_mask = GPU_WRITE_NONE;
  if (state & DRW_STATE_WRITE_DEPTH) {
    write_mask |= GPU_WRITE_DEPTH;
  }
  if (state & DRW_STATE_WRITE_COLOR) {
    write_mask |= GPU_WRITE_COLOR;
  }
  if (state & DRW_STATE_WRITE_STENCIL_ENABLED) {
    write_mask |= GPU_WRITE_STENCIL;
  }
  return write_mask;
}

static inline eGPUFaceCullTest to_face_cull_test(DRWState state)
{
  switch (state & (DRW_STATE_CULL_BACK | DRW_STATE_CULL_FRONT)) {
    case DRW_STATE_CULL_BACK:
      return GPU_CULL_BACK;
    case DRW_STATE_CULL_FRONT:
      return GPU_CULL_FRONT;
    default:
      return GPU_CULL_NONE;
  }
}

static inline eGPUDepthTest to_depth_test(DRWState state)
{
  switch (state & DRW_STATE_DEPTH_TEST_ENABLED) {
    case DRW_STATE_DEPTH_LESS:
      return GPU_DEPTH_LESS;
    case DRW_STATE_DEPTH_LESS_EQUAL:
      return GPU_DEPTH_LESS_EQUAL;
    case DRW_STATE_DEPTH_EQUAL:
      return GPU_DEPTH_EQUAL;
    case DRW_STATE_DEPTH_GREATER:
      return GPU_DEPTH_GREATER;
    case DRW_STATE_DEPTH_GREATER_EQUAL:
      return GPU_DEPTH_GREATER_EQUAL;
    case DRW_STATE_DEPTH_ALWAYS:
      return GPU_DEPTH_ALWAYS;
    default:
      return GPU_DEPTH_NONE;
  }
}

static inline eGPUStencilOp to_stencil_op(DRWState state)
{
  switch (state & DRW_STATE_WRITE_STENCIL_ENABLED) {
    case DRW_STATE_WRITE_STENCIL:
      return GPU_STENCIL_OP_REPLACE;
    case DRW_STATE_WRITE_STENCIL_SHADOW_PASS:
      return GPU_STENCIL_OP_COUNT_DEPTH_PASS;
    case DRW_STATE_WRITE_STENCIL_SHADOW_FAIL:
      return GPU_STENCIL_OP_COUNT_DEPTH_FAIL;
    default:
      return GPU_STENCIL_OP_NONE;
  }
}

static inline eGPUStencilTest to_stencil_test(DRWState state)
{
  switch (state & DRW_STATE_STENCIL_TEST_ENABLED) {
    case DRW_STATE_STENCIL_ALWAYS:
      return GPU_STENCIL_ALWAYS;
    case DRW_STATE_STENCIL_EQUAL:
      return GPU_STENCIL_EQUAL;
    case DRW_STATE_STENCIL_NEQUAL:
      return GPU_STENCIL_NEQUAL;
    default:
      return GPU_STENCIL_NONE;
  }
}

static inline eGPUBlend to_blend(DRWState state)
{
  switch (state & DRW_STATE_BLEND_ENABLED) {
    case DRW_STATE_BLEND_ADD:
      return GPU_BLEND_ADDITIVE;
    case DRW_STATE_BLEND_ADD_FULL:
      return GPU_BLEND_ADDITIVE_PREMULT;
    case DRW_STATE_BLEND_ALPHA:
      return GPU_BLEND_ALPHA;
    case DRW_STATE_BLEND_ALPHA_PREMUL:
      return GPU_BLEND_ALPHA_PREMULT;
    case DRW_STATE_BLEND_BACKGROUND:
      return GPU_BLEND_BACKGROUND;
    case DRW_STATE_BLEND_OIT:
      return GPU_BLEND_OIT;
    case DRW_STATE_BLEND_MUL:
      return GPU_BLEND_MULTIPLY;
    case DRW_STATE_BLEND_SUB:
      return GPU_BLEND_SUBTRACT;
    case DRW_STATE_BLEND_CUSTOM:
      return GPU_BLEND_CUSTOM;
    case DRW_STATE_LOGIC_INVERT:
      return GPU_BLEND_INVERT;
    case DRW_STATE_BLEND_ALPHA_UNDER_PREMUL:
      return GPU_BLEND_ALPHA_UNDER_PREMUL;
    default:
      return GPU_BLEND_NONE;
  }
}

static inline eGPUProvokingVertex to_provoking_vertex(DRWState state)
{
  switch (state & DRW_STATE_FIRST_VERTEX_CONVENTION) {
    case DRW_STATE_FIRST_VERTEX_CONVENTION:
      return GPU_VERTEX_FIRST;
    default:
      return GPU_VERTEX_LAST;
  }
}

/** \} */

};  // namespace blender::draw

#endif