etnaviv: add helper to work out RS alignment
[mesa.git] / src / gallium / drivers / etnaviv / etnaviv_translate.h
1 /*
2 * Copyright (c) 2012-2013 Etnaviv Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sub license,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the
12 * next paragraph) shall be included in all copies or substantial portions
13 * of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23 /* inlined translation functions between gallium and vivante */
24 #ifndef H_TRANSLATE
25 #define H_TRANSLATE
26
27 #include "pipe/p_defines.h"
28 #include "pipe/p_format.h"
29 #include "pipe/p_state.h"
30
31 #include "etnaviv_debug.h"
32 #include "etnaviv_format.h"
33 #include "etnaviv_tiling.h"
34 #include "etnaviv_util.h"
35 #include "hw/cmdstream.xml.h"
36 #include "hw/state.xml.h"
37 #include "hw/state_3d.xml.h"
38
39 #include "util/u_format.h"
40 #include "util/u_math.h"
41
42 #include <stdio.h>
43
44 /* Returned when there is no match of pipe value to etna value */
45 #define ETNA_NO_MATCH (~0)
46
47 static inline uint32_t
48 translate_cull_face(unsigned cull_face, unsigned front_ccw)
49 {
50 switch (cull_face) {
51 case PIPE_FACE_NONE:
52 return VIVS_PA_CONFIG_CULL_FACE_MODE_OFF;
53 case PIPE_FACE_BACK:
54 return front_ccw ? VIVS_PA_CONFIG_CULL_FACE_MODE_CW
55 : VIVS_PA_CONFIG_CULL_FACE_MODE_CCW;
56 case PIPE_FACE_FRONT:
57 return front_ccw ? VIVS_PA_CONFIG_CULL_FACE_MODE_CCW
58 : VIVS_PA_CONFIG_CULL_FACE_MODE_CW;
59 default:
60 DBG("Unhandled cull face mode %i", cull_face);
61 return ETNA_NO_MATCH;
62 }
63 }
64
65 static inline uint32_t
66 translate_polygon_mode(unsigned polygon_mode)
67 {
68 switch (polygon_mode) {
69 case PIPE_POLYGON_MODE_FILL:
70 return VIVS_PA_CONFIG_FILL_MODE_SOLID;
71 case PIPE_POLYGON_MODE_LINE:
72 return VIVS_PA_CONFIG_FILL_MODE_WIREFRAME;
73 case PIPE_POLYGON_MODE_POINT:
74 return VIVS_PA_CONFIG_FILL_MODE_POINT;
75 default:
76 DBG("Unhandled polygon mode %i", polygon_mode);
77 return ETNA_NO_MATCH;
78 }
79 }
80
81 static inline uint32_t
82 translate_stencil_mode(bool enable_0, bool enable_1)
83 {
84 if (enable_0) {
85 return enable_1 ? VIVS_PE_STENCIL_CONFIG_MODE_TWO_SIDED
86 : VIVS_PE_STENCIL_CONFIG_MODE_ONE_SIDED;
87 } else {
88 return VIVS_PE_STENCIL_CONFIG_MODE_DISABLED;
89 }
90 }
91
92 static inline uint32_t
93 translate_stencil_op(unsigned stencil_op)
94 {
95 switch (stencil_op) {
96 case PIPE_STENCIL_OP_KEEP:
97 return STENCIL_OP_KEEP;
98 case PIPE_STENCIL_OP_ZERO:
99 return STENCIL_OP_ZERO;
100 case PIPE_STENCIL_OP_REPLACE:
101 return STENCIL_OP_REPLACE;
102 case PIPE_STENCIL_OP_INCR:
103 return STENCIL_OP_INCR;
104 case PIPE_STENCIL_OP_DECR:
105 return STENCIL_OP_DECR;
106 case PIPE_STENCIL_OP_INCR_WRAP:
107 return STENCIL_OP_INCR_WRAP;
108 case PIPE_STENCIL_OP_DECR_WRAP:
109 return STENCIL_OP_DECR_WRAP;
110 case PIPE_STENCIL_OP_INVERT:
111 return STENCIL_OP_INVERT;
112 default:
113 DBG("Unhandled stencil op: %i", stencil_op);
114 return ETNA_NO_MATCH;
115 }
116 }
117
118 static inline uint32_t
119 translate_blend(unsigned blend)
120 {
121 switch (blend) {
122 case PIPE_BLEND_ADD:
123 return BLEND_EQ_ADD;
124 case PIPE_BLEND_SUBTRACT:
125 return BLEND_EQ_SUBTRACT;
126 case PIPE_BLEND_REVERSE_SUBTRACT:
127 return BLEND_EQ_REVERSE_SUBTRACT;
128 case PIPE_BLEND_MIN:
129 return BLEND_EQ_MIN;
130 case PIPE_BLEND_MAX:
131 return BLEND_EQ_MAX;
132 default:
133 DBG("Unhandled blend: %i", blend);
134 return ETNA_NO_MATCH;
135 }
136 }
137
138 static inline uint32_t
139 translate_blend_factor(unsigned blend_factor)
140 {
141 switch (blend_factor) {
142 case PIPE_BLENDFACTOR_ONE:
143 return BLEND_FUNC_ONE;
144 case PIPE_BLENDFACTOR_SRC_COLOR:
145 return BLEND_FUNC_SRC_COLOR;
146 case PIPE_BLENDFACTOR_SRC_ALPHA:
147 return BLEND_FUNC_SRC_ALPHA;
148 case PIPE_BLENDFACTOR_DST_ALPHA:
149 return BLEND_FUNC_DST_ALPHA;
150 case PIPE_BLENDFACTOR_DST_COLOR:
151 return BLEND_FUNC_DST_COLOR;
152 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
153 return BLEND_FUNC_SRC_ALPHA_SATURATE;
154 case PIPE_BLENDFACTOR_CONST_COLOR:
155 return BLEND_FUNC_CONSTANT_COLOR;
156 case PIPE_BLENDFACTOR_CONST_ALPHA:
157 return BLEND_FUNC_CONSTANT_ALPHA;
158 case PIPE_BLENDFACTOR_ZERO:
159 return BLEND_FUNC_ZERO;
160 case PIPE_BLENDFACTOR_INV_SRC_COLOR:
161 return BLEND_FUNC_ONE_MINUS_SRC_COLOR;
162 case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
163 return BLEND_FUNC_ONE_MINUS_SRC_ALPHA;
164 case PIPE_BLENDFACTOR_INV_DST_ALPHA:
165 return BLEND_FUNC_ONE_MINUS_DST_ALPHA;
166 case PIPE_BLENDFACTOR_INV_DST_COLOR:
167 return BLEND_FUNC_ONE_MINUS_DST_COLOR;
168 case PIPE_BLENDFACTOR_INV_CONST_COLOR:
169 return BLEND_FUNC_ONE_MINUS_CONSTANT_COLOR;
170 case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
171 return BLEND_FUNC_ONE_MINUS_CONSTANT_ALPHA;
172 case PIPE_BLENDFACTOR_SRC1_COLOR:
173 case PIPE_BLENDFACTOR_SRC1_ALPHA:
174 case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
175 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
176 default:
177 DBG("Unhandled blend factor: %i", blend_factor);
178 return ETNA_NO_MATCH;
179 }
180 }
181
182 static inline uint32_t
183 translate_texture_wrapmode(unsigned wrap)
184 {
185 switch (wrap) {
186 case PIPE_TEX_WRAP_REPEAT:
187 return TEXTURE_WRAPMODE_REPEAT;
188 case PIPE_TEX_WRAP_CLAMP:
189 return TEXTURE_WRAPMODE_CLAMP_TO_EDGE;
190 case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
191 return TEXTURE_WRAPMODE_CLAMP_TO_EDGE;
192 case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
193 return TEXTURE_WRAPMODE_CLAMP_TO_EDGE; /* XXX */
194 case PIPE_TEX_WRAP_MIRROR_REPEAT:
195 return TEXTURE_WRAPMODE_MIRRORED_REPEAT;
196 case PIPE_TEX_WRAP_MIRROR_CLAMP:
197 return TEXTURE_WRAPMODE_MIRRORED_REPEAT; /* XXX */
198 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
199 return TEXTURE_WRAPMODE_MIRRORED_REPEAT; /* XXX */
200 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
201 return TEXTURE_WRAPMODE_MIRRORED_REPEAT; /* XXX */
202 default:
203 DBG("Unhandled texture wrapmode: %i", wrap);
204 return ETNA_NO_MATCH;
205 }
206 }
207
208 static inline uint32_t
209 translate_texture_mipfilter(unsigned filter)
210 {
211 switch (filter) {
212 case PIPE_TEX_MIPFILTER_NEAREST:
213 return TEXTURE_FILTER_NEAREST;
214 case PIPE_TEX_MIPFILTER_LINEAR:
215 return TEXTURE_FILTER_LINEAR;
216 case PIPE_TEX_MIPFILTER_NONE:
217 return TEXTURE_FILTER_NONE;
218 default:
219 DBG("Unhandled texture mipfilter: %i", filter);
220 return ETNA_NO_MATCH;
221 }
222 }
223
224 static inline uint32_t
225 translate_texture_filter(unsigned filter)
226 {
227 switch (filter) {
228 case PIPE_TEX_FILTER_NEAREST:
229 return TEXTURE_FILTER_NEAREST;
230 case PIPE_TEX_FILTER_LINEAR:
231 return TEXTURE_FILTER_LINEAR;
232 /* What about anisotropic? */
233 default:
234 DBG("Unhandled texture filter: %i", filter);
235 return ETNA_NO_MATCH;
236 }
237 }
238
239 /* return a RS "compatible" format for use when copying */
240 static inline enum pipe_format
241 etna_compatible_rs_format(enum pipe_format fmt)
242 {
243 /* YUYV and UYVY are blocksize 4, but 2 bytes per pixel */
244 if (fmt == PIPE_FORMAT_YUYV || fmt == PIPE_FORMAT_UYVY)
245 return PIPE_FORMAT_B4G4R4A4_UNORM;
246
247 switch (util_format_get_blocksize(fmt)) {
248 case 2:
249 return PIPE_FORMAT_B4G4R4A4_UNORM;
250 case 4:
251 return PIPE_FORMAT_B8G8R8A8_UNORM;
252 default:
253 return fmt;
254 }
255 }
256
257 static inline int
258 translate_rb_src_dst_swap(enum pipe_format src, enum pipe_format dst)
259 {
260 return translate_rs_format_rb_swap(src) ^ translate_rs_format_rb_swap(dst);
261 }
262
263 static inline uint32_t
264 translate_depth_format(enum pipe_format fmt)
265 {
266 /* Note: Pipe format convention is LSB to MSB, VIVS is MSB to LSB */
267 switch (fmt) {
268 case PIPE_FORMAT_Z16_UNORM:
269 return VIVS_PE_DEPTH_CONFIG_DEPTH_FORMAT_D16;
270 case PIPE_FORMAT_X8Z24_UNORM:
271 return VIVS_PE_DEPTH_CONFIG_DEPTH_FORMAT_D24S8;
272 case PIPE_FORMAT_S8_UINT_Z24_UNORM:
273 return VIVS_PE_DEPTH_CONFIG_DEPTH_FORMAT_D24S8;
274 default:
275 return ETNA_NO_MATCH;
276 }
277 }
278
279 /* render target format for MSAA */
280 static inline uint32_t
281 translate_msaa_format(enum pipe_format fmt)
282 {
283 /* Note: Pipe format convention is LSB to MSB, VIVS is MSB to LSB */
284 switch (fmt) {
285 case PIPE_FORMAT_B4G4R4X4_UNORM:
286 return VIVS_TS_MEM_CONFIG_MSAA_FORMAT_A4R4G4B4;
287 case PIPE_FORMAT_B4G4R4A4_UNORM:
288 return VIVS_TS_MEM_CONFIG_MSAA_FORMAT_A4R4G4B4;
289 case PIPE_FORMAT_B5G5R5X1_UNORM:
290 return VIVS_TS_MEM_CONFIG_MSAA_FORMAT_A1R5G5B5;
291 case PIPE_FORMAT_B5G5R5A1_UNORM:
292 return VIVS_TS_MEM_CONFIG_MSAA_FORMAT_A1R5G5B5;
293 case PIPE_FORMAT_B5G6R5_UNORM:
294 return VIVS_TS_MEM_CONFIG_MSAA_FORMAT_R5G6B5;
295 case PIPE_FORMAT_B8G8R8X8_UNORM:
296 return VIVS_TS_MEM_CONFIG_MSAA_FORMAT_X8R8G8B8;
297 case PIPE_FORMAT_B8G8R8A8_UNORM:
298 return VIVS_TS_MEM_CONFIG_MSAA_FORMAT_A8R8G8B8;
299 /* MSAA with YUYV not supported */
300 default:
301 return ETNA_NO_MATCH;
302 }
303 }
304
305 /* Return normalization flag for vertex element format */
306 static inline uint32_t
307 translate_vertex_format_normalize(enum pipe_format fmt)
308 {
309 const struct util_format_description *desc = util_format_description(fmt);
310 if (!desc)
311 return VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_OFF;
312
313 /* assumes that normalization of channel 0 holds for all channels;
314 * this holds for all vertex formats that we support */
315 return desc->channel[0].normalized
316 ? VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_ON
317 : VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_OFF;
318 }
319
320 static inline uint32_t
321 translate_index_size(unsigned index_size)
322 {
323 switch (index_size) {
324 case 1:
325 return VIVS_FE_INDEX_STREAM_CONTROL_TYPE_UNSIGNED_CHAR;
326 case 2:
327 return VIVS_FE_INDEX_STREAM_CONTROL_TYPE_UNSIGNED_SHORT;
328 case 4:
329 return VIVS_FE_INDEX_STREAM_CONTROL_TYPE_UNSIGNED_INT;
330 default:
331 DBG("Unhandled index size %i", index_size);
332 return ETNA_NO_MATCH;
333 }
334 }
335
336 static inline uint32_t
337 translate_draw_mode(unsigned mode)
338 {
339 switch (mode) {
340 case PIPE_PRIM_POINTS:
341 return PRIMITIVE_TYPE_POINTS;
342 case PIPE_PRIM_LINES:
343 return PRIMITIVE_TYPE_LINES;
344 case PIPE_PRIM_LINE_LOOP:
345 return PRIMITIVE_TYPE_LINE_LOOP;
346 case PIPE_PRIM_LINE_STRIP:
347 return PRIMITIVE_TYPE_LINE_STRIP;
348 case PIPE_PRIM_TRIANGLES:
349 return PRIMITIVE_TYPE_TRIANGLES;
350 case PIPE_PRIM_TRIANGLE_STRIP:
351 return PRIMITIVE_TYPE_TRIANGLE_STRIP;
352 case PIPE_PRIM_TRIANGLE_FAN:
353 return PRIMITIVE_TYPE_TRIANGLE_FAN;
354 case PIPE_PRIM_QUADS:
355 return PRIMITIVE_TYPE_QUADS;
356 default:
357 DBG("Unhandled draw mode primitive %i", mode);
358 return ETNA_NO_MATCH;
359 }
360 }
361
362 /* Get size multiple for size of texture/rendertarget with a certain layout
363 * This is affected by many different parameters:
364 * - A horizontal multiple of 16 is used when possible as resolve can be used
365 * at the cost of only a little bit extra memory usage.
366 * - If the surface is to be used with the resolve engine, set rs_align true.
367 * If set, a horizontal multiple of 16 will be used for tiled and linear,
368 * otherwise one of 16. However, such a surface will be incompatible
369 * with the samplers if the GPU does hot support the HALIGN feature.
370 * - If the surface is supertiled, horizontal and vertical multiple is always 64
371 * - If the surface is multi tiled or supertiled, make sure that the vertical size
372 * is a multiple of the number of pixel pipes as well.
373 * */
374 static inline void
375 etna_layout_multiple(unsigned layout, unsigned pixel_pipes, bool rs_align,
376 unsigned *paddingX, unsigned *paddingY, unsigned *halign)
377 {
378 switch (layout) {
379 case ETNA_LAYOUT_LINEAR:
380 *paddingX = rs_align ? 16 : 4;
381 *paddingY = 1;
382 *halign = rs_align ? TEXTURE_HALIGN_SIXTEEN : TEXTURE_HALIGN_FOUR;
383 break;
384 case ETNA_LAYOUT_TILED:
385 *paddingX = rs_align ? 16 : 4;
386 *paddingY = 4;
387 *halign = rs_align ? TEXTURE_HALIGN_SIXTEEN : TEXTURE_HALIGN_FOUR;
388 break;
389 case ETNA_LAYOUT_SUPER_TILED:
390 *paddingX = 64;
391 *paddingY = 64;
392 *halign = TEXTURE_HALIGN_SUPER_TILED;
393 break;
394 case ETNA_LAYOUT_MULTI_TILED:
395 *paddingX = 16;
396 *paddingY = 4 * pixel_pipes;
397 *halign = TEXTURE_HALIGN_SPLIT_TILED;
398 break;
399 case ETNA_LAYOUT_MULTI_SUPERTILED:
400 *paddingX = 64;
401 *paddingY = 64 * pixel_pipes;
402 *halign = TEXTURE_HALIGN_SPLIT_SUPER_TILED;
403 break;
404 default:
405 DBG("Unhandled layout %i", layout);
406 }
407 }
408
409 static inline void etna_adjust_rs_align(unsigned num_pixelpipes,
410 unsigned *paddingX, unsigned *paddingY)
411 {
412 unsigned alignX = ETNA_RS_WIDTH_MASK + 1;
413 unsigned alignY = (ETNA_RS_HEIGHT_MASK + 1) * num_pixelpipes;
414
415 if (paddingX)
416 *paddingX = align(*paddingX, alignX);
417 if (paddingY)
418 *paddingY = align(*paddingY, alignY);
419 }
420
421 static inline uint32_t
422 translate_clear_depth_stencil(enum pipe_format format, float depth,
423 unsigned stencil)
424 {
425 uint32_t clear_value = 0;
426
427 // XXX util_pack_color
428 switch (format) {
429 case PIPE_FORMAT_Z16_UNORM:
430 clear_value = etna_cfloat_to_uintN(depth, 16);
431 clear_value |= clear_value << 16;
432 break;
433 case PIPE_FORMAT_X8Z24_UNORM:
434 case PIPE_FORMAT_S8_UINT_Z24_UNORM:
435 clear_value = (etna_cfloat_to_uintN(depth, 24) << 8) | (stencil & 0xFF);
436 break;
437 default:
438 DBG("Unhandled pipe format for depth stencil clear: %i", format);
439 }
440 return clear_value;
441 }
442
443 /* Convert MSAA number of samples to x and y scaling factor and
444 * VIVS_GL_MULTI_SAMPLE_CONFIG value.
445 * Return true if supported and false otherwise. */
446 static inline bool
447 translate_samples_to_xyscale(int num_samples, int *xscale_out, int *yscale_out,
448 uint32_t *config_out)
449 {
450 int xscale, yscale;
451 uint32_t config;
452
453 switch (num_samples) {
454 case 0:
455 case 1:
456 xscale = 1;
457 yscale = 1;
458 config = VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_NONE;
459 break;
460 case 2:
461 xscale = 2;
462 yscale = 1;
463 config = VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_2X;
464 break;
465 case 4:
466 xscale = 2;
467 yscale = 2;
468 config = VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_4X;
469 break;
470 default:
471 return false;
472 }
473
474 if (xscale_out)
475 *xscale_out = xscale;
476 if (yscale_out)
477 *yscale_out = yscale;
478 if (config_out)
479 *config_out = config;
480
481 return true;
482 }
483
484 #endif