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_util.h"
34#include "hw/cmdstream.xml.h"
35#include "hw/common_3d.xml.h"
36#include "hw/state.xml.h"
37#include "hw/state_3d.xml.h"
38
39#include "util/format/u_format.h"
40#include "util/u_math.h"
41
42/* Returned when there is no match of pipe value to etna value */
43#define ETNA_NO_MATCH (~0)
44
45static inline uint32_t
46translate_cull_face(unsigned cull_face, unsigned front_ccw)
47{
48   switch (cull_face) {
49   case PIPE_FACE_NONE:
50      return VIVS_PA_CONFIG_CULL_FACE_MODE_OFF;
51   case PIPE_FACE_BACK:
52      return front_ccw ? VIVS_PA_CONFIG_CULL_FACE_MODE_CW
53                       : VIVS_PA_CONFIG_CULL_FACE_MODE_CCW;
54   case PIPE_FACE_FRONT:
55      return front_ccw ? VIVS_PA_CONFIG_CULL_FACE_MODE_CCW
56                       : VIVS_PA_CONFIG_CULL_FACE_MODE_CW;
57   default:
58      DBG("Unhandled cull face mode %i", cull_face);
59      return ETNA_NO_MATCH;
60   }
61}
62
63static inline uint32_t
64translate_polygon_mode(unsigned polygon_mode)
65{
66   switch (polygon_mode) {
67   case PIPE_POLYGON_MODE_FILL:
68      return VIVS_PA_CONFIG_FILL_MODE_SOLID;
69   case PIPE_POLYGON_MODE_LINE:
70      return VIVS_PA_CONFIG_FILL_MODE_WIREFRAME;
71   case PIPE_POLYGON_MODE_POINT:
72      return VIVS_PA_CONFIG_FILL_MODE_POINT;
73   default:
74      DBG("Unhandled polygon mode %i", polygon_mode);
75      return ETNA_NO_MATCH;
76   }
77}
78
79static inline uint32_t
80translate_stencil_mode(bool enable_0, bool enable_1)
81{
82   if (enable_0) {
83      return enable_1 ? VIVS_PE_STENCIL_CONFIG_MODE_TWO_SIDED
84                      : VIVS_PE_STENCIL_CONFIG_MODE_ONE_SIDED;
85   } else {
86      return VIVS_PE_STENCIL_CONFIG_MODE_DISABLED;
87   }
88}
89
90static inline uint32_t
91translate_stencil_op(unsigned stencil_op)
92{
93   switch (stencil_op) {
94   case PIPE_STENCIL_OP_KEEP:
95      return STENCIL_OP_KEEP;
96   case PIPE_STENCIL_OP_ZERO:
97      return STENCIL_OP_ZERO;
98   case PIPE_STENCIL_OP_REPLACE:
99      return STENCIL_OP_REPLACE;
100   case PIPE_STENCIL_OP_INCR:
101      return STENCIL_OP_INCR;
102   case PIPE_STENCIL_OP_DECR:
103      return STENCIL_OP_DECR;
104   case PIPE_STENCIL_OP_INCR_WRAP:
105      return STENCIL_OP_INCR_WRAP;
106   case PIPE_STENCIL_OP_DECR_WRAP:
107      return STENCIL_OP_DECR_WRAP;
108   case PIPE_STENCIL_OP_INVERT:
109      return STENCIL_OP_INVERT;
110   default:
111      DBG("Unhandled stencil op: %i", stencil_op);
112      return ETNA_NO_MATCH;
113   }
114}
115
116static inline uint32_t
117translate_blend_factor(unsigned blend_factor)
118{
119   switch (blend_factor) {
120   case PIPE_BLENDFACTOR_ONE:
121      return BLEND_FUNC_ONE;
122   case PIPE_BLENDFACTOR_SRC_COLOR:
123      return BLEND_FUNC_SRC_COLOR;
124   case PIPE_BLENDFACTOR_SRC_ALPHA:
125      return BLEND_FUNC_SRC_ALPHA;
126   case PIPE_BLENDFACTOR_DST_ALPHA:
127      return BLEND_FUNC_DST_ALPHA;
128   case PIPE_BLENDFACTOR_DST_COLOR:
129      return BLEND_FUNC_DST_COLOR;
130   case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
131      return BLEND_FUNC_SRC_ALPHA_SATURATE;
132   case PIPE_BLENDFACTOR_CONST_COLOR:
133      return BLEND_FUNC_CONSTANT_COLOR;
134   case PIPE_BLENDFACTOR_CONST_ALPHA:
135      return BLEND_FUNC_CONSTANT_ALPHA;
136   case PIPE_BLENDFACTOR_ZERO:
137      return BLEND_FUNC_ZERO;
138   case PIPE_BLENDFACTOR_INV_SRC_COLOR:
139      return BLEND_FUNC_ONE_MINUS_SRC_COLOR;
140   case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
141      return BLEND_FUNC_ONE_MINUS_SRC_ALPHA;
142   case PIPE_BLENDFACTOR_INV_DST_ALPHA:
143      return BLEND_FUNC_ONE_MINUS_DST_ALPHA;
144   case PIPE_BLENDFACTOR_INV_DST_COLOR:
145      return BLEND_FUNC_ONE_MINUS_DST_COLOR;
146   case PIPE_BLENDFACTOR_INV_CONST_COLOR:
147      return BLEND_FUNC_ONE_MINUS_CONSTANT_COLOR;
148   case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
149      return BLEND_FUNC_ONE_MINUS_CONSTANT_ALPHA;
150   case PIPE_BLENDFACTOR_SRC1_COLOR:
151   case PIPE_BLENDFACTOR_SRC1_ALPHA:
152   case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
153   case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
154   default:
155      DBG("Unhandled blend factor: %i", blend_factor);
156      return ETNA_NO_MATCH;
157   }
158}
159
160static inline uint32_t
161translate_texture_wrapmode(unsigned wrap)
162{
163   switch (wrap) {
164   case PIPE_TEX_WRAP_REPEAT:
165      return TEXTURE_WRAPMODE_REPEAT;
166   case PIPE_TEX_WRAP_CLAMP:
167      return TEXTURE_WRAPMODE_CLAMP_TO_EDGE;
168   case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
169      return TEXTURE_WRAPMODE_CLAMP_TO_EDGE;
170   case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
171      return TEXTURE_WRAPMODE_CLAMP_TO_EDGE; /* XXX */
172   case PIPE_TEX_WRAP_MIRROR_REPEAT:
173      return TEXTURE_WRAPMODE_MIRRORED_REPEAT;
174   case PIPE_TEX_WRAP_MIRROR_CLAMP:
175      return TEXTURE_WRAPMODE_MIRRORED_REPEAT; /* XXX */
176   case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
177      return TEXTURE_WRAPMODE_MIRRORED_REPEAT; /* XXX */
178   case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
179      return TEXTURE_WRAPMODE_MIRRORED_REPEAT; /* XXX */
180   default:
181      DBG("Unhandled texture wrapmode: %i", wrap);
182      return ETNA_NO_MATCH;
183   }
184}
185
186static inline uint32_t
187translate_texture_mipfilter(unsigned filter)
188{
189   switch (filter) {
190   case PIPE_TEX_MIPFILTER_NEAREST:
191      return TEXTURE_FILTER_NEAREST;
192   case PIPE_TEX_MIPFILTER_LINEAR:
193      return TEXTURE_FILTER_LINEAR;
194   case PIPE_TEX_MIPFILTER_NONE:
195      return TEXTURE_FILTER_NONE;
196   default:
197      DBG("Unhandled texture mipfilter: %i", filter);
198      return ETNA_NO_MATCH;
199   }
200}
201
202static inline uint32_t
203translate_texture_filter(unsigned filter)
204{
205   switch (filter) {
206   case PIPE_TEX_FILTER_NEAREST:
207      return TEXTURE_FILTER_NEAREST;
208   case PIPE_TEX_FILTER_LINEAR:
209      return TEXTURE_FILTER_LINEAR;
210   default:
211      DBG("Unhandled texture filter: %i", filter);
212      return ETNA_NO_MATCH;
213   }
214}
215
216static inline int
217translate_rb_src_dst_swap(enum pipe_format src, enum pipe_format dst)
218{
219   return translate_pe_format_rb_swap(src) ^ translate_pe_format_rb_swap(dst);
220}
221
222static inline uint32_t
223translate_depth_format(enum pipe_format fmt)
224{
225   /* Note: Pipe format convention is LSB to MSB, VIVS is MSB to LSB */
226   switch (fmt) {
227   case PIPE_FORMAT_Z16_UNORM:
228      return VIVS_PE_DEPTH_CONFIG_DEPTH_FORMAT_D16;
229   case PIPE_FORMAT_X8Z24_UNORM:
230      return VIVS_PE_DEPTH_CONFIG_DEPTH_FORMAT_D24S8;
231   case PIPE_FORMAT_S8_UINT_Z24_UNORM:
232      return VIVS_PE_DEPTH_CONFIG_DEPTH_FORMAT_D24S8;
233   default:
234      return ETNA_NO_MATCH;
235   }
236}
237
238/* render target format for MSAA */
239static inline uint32_t
240translate_ts_format(enum pipe_format fmt)
241{
242   /* Note: Pipe format convention is LSB to MSB, VIVS is MSB to LSB */
243   switch (fmt) {
244   case PIPE_FORMAT_B4G4R4X4_UNORM:
245   case PIPE_FORMAT_B4G4R4A4_UNORM:
246      return COMPRESSION_FORMAT_A4R4G4B4;
247   case PIPE_FORMAT_B5G5R5X1_UNORM:
248      return COMPRESSION_FORMAT_A1R5G5B5;
249   case PIPE_FORMAT_B5G5R5A1_UNORM:
250      return COMPRESSION_FORMAT_A1R5G5B5;
251   case PIPE_FORMAT_B5G6R5_UNORM:
252      return COMPRESSION_FORMAT_R5G6B5;
253   case PIPE_FORMAT_B8G8R8X8_UNORM:
254   case PIPE_FORMAT_B8G8R8X8_SRGB:
255   case PIPE_FORMAT_R8G8B8X8_UNORM:
256      return COMPRESSION_FORMAT_X8R8G8B8;
257   case PIPE_FORMAT_B8G8R8A8_UNORM:
258   case PIPE_FORMAT_B8G8R8A8_SRGB:
259   case PIPE_FORMAT_R8G8B8A8_UNORM:
260      return COMPRESSION_FORMAT_A8R8G8B8;
261   case PIPE_FORMAT_S8_UINT_Z24_UNORM:
262      return COMPRESSION_FORMAT_D24S8;
263   case PIPE_FORMAT_X8Z24_UNORM:
264      return COMPRESSION_FORMAT_D24X8;
265   case PIPE_FORMAT_Z16_UNORM:
266      return COMPRESSION_FORMAT_D16;
267   /* MSAA with YUYV not supported */
268   default:
269      return ETNA_NO_MATCH;
270   }
271}
272
273/* Return normalization flag for vertex element format */
274static inline uint32_t
275translate_vertex_format_normalize(enum pipe_format fmt)
276{
277   const struct util_format_description *desc = util_format_description(fmt);
278   if (!desc)
279      return VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_OFF;
280
281   /* assumes that normalization of channel 0 holds for all channels;
282    * this holds for all vertex formats that we support */
283   return desc->channel[0].normalized
284             ? VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_SIGN_EXTEND
285             : VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_OFF;
286}
287
288static inline uint32_t
289translate_output_mode(enum pipe_format fmt, bool halti5)
290{
291   const unsigned bits =
292      util_format_get_component_bits(fmt, UTIL_FORMAT_COLORSPACE_RGB, 0);
293
294   if (bits == 32)
295      return COLOR_OUTPUT_MODE_UIF32;
296
297   if (!util_format_is_pure_integer(fmt))
298      return COLOR_OUTPUT_MODE_NORMAL;
299
300   /* generic integer output mode pre-halti5 (?) */
301   if (bits == 10 || !halti5)
302      return COLOR_OUTPUT_MODE_A2B10G10R10UI;
303
304   if (util_format_is_pure_sint(fmt))
305      return bits == 8 ? COLOR_OUTPUT_MODE_I8 : COLOR_OUTPUT_MODE_I16;
306
307   return bits == 8 ? COLOR_OUTPUT_MODE_U8 : COLOR_OUTPUT_MODE_U16;
308}
309
310static inline uint32_t
311translate_index_size(unsigned index_size)
312{
313   switch (index_size) {
314   case 1:
315      return VIVS_FE_INDEX_STREAM_CONTROL_TYPE_UNSIGNED_CHAR;
316   case 2:
317      return VIVS_FE_INDEX_STREAM_CONTROL_TYPE_UNSIGNED_SHORT;
318   case 4:
319      return VIVS_FE_INDEX_STREAM_CONTROL_TYPE_UNSIGNED_INT;
320   default:
321      DBG("Unhandled index size %i", index_size);
322      return ETNA_NO_MATCH;
323   }
324}
325
326static inline uint32_t
327translate_draw_mode(unsigned mode)
328{
329   switch (mode) {
330   case PIPE_PRIM_POINTS:
331      return PRIMITIVE_TYPE_POINTS;
332   case PIPE_PRIM_LINES:
333      return PRIMITIVE_TYPE_LINES;
334   case PIPE_PRIM_LINE_LOOP:
335      return PRIMITIVE_TYPE_LINE_LOOP;
336   case PIPE_PRIM_LINE_STRIP:
337      return PRIMITIVE_TYPE_LINE_STRIP;
338   case PIPE_PRIM_TRIANGLES:
339      return PRIMITIVE_TYPE_TRIANGLES;
340   case PIPE_PRIM_TRIANGLE_STRIP:
341      return PRIMITIVE_TYPE_TRIANGLE_STRIP;
342   case PIPE_PRIM_TRIANGLE_FAN:
343      return PRIMITIVE_TYPE_TRIANGLE_FAN;
344   case PIPE_PRIM_QUADS:
345      return PRIMITIVE_TYPE_QUADS;
346   default:
347      DBG("Unhandled draw mode primitive %i", mode);
348      return ETNA_NO_MATCH;
349   }
350}
351
352/* Get size multiple for size of texture/rendertarget with a certain layout
353 * This is affected by many different parameters:
354 *   - A horizontal multiple of 16 is used when possible as resolve can be used
355 *       at the cost of only a little bit extra memory usage.
356 *   - If the surface is to be used with the resolve engine, set rs_align true.
357 *       If set, a horizontal multiple of 16 will be used for tiled and linear,
358 *       otherwise one of 16.  However, such a surface will be incompatible
359 *       with the samplers if the GPU does hot support the HALIGN feature.
360 *   - If the surface is supertiled, horizontal and vertical multiple is always 64
361 *   - If the surface is multi tiled or supertiled, make sure that the vertical size
362 *     is a multiple of the number of pixel pipes as well.
363 * */
364static inline void
365etna_layout_multiple(unsigned layout, unsigned pixel_pipes, bool rs_align,
366                     unsigned *paddingX, unsigned *paddingY, unsigned *halign)
367{
368   switch (layout) {
369   case ETNA_LAYOUT_LINEAR:
370      *paddingX = rs_align ? 16 : 4;
371      *paddingY = 1;
372      *halign = rs_align ? TEXTURE_HALIGN_SIXTEEN : TEXTURE_HALIGN_FOUR;
373      break;
374   case ETNA_LAYOUT_TILED:
375      *paddingX = rs_align ? 16 : 4;
376      *paddingY = 4;
377      *halign = rs_align ? TEXTURE_HALIGN_SIXTEEN : TEXTURE_HALIGN_FOUR;
378      break;
379   case ETNA_LAYOUT_SUPER_TILED:
380      *paddingX = 64;
381      *paddingY = 64;
382      *halign = TEXTURE_HALIGN_SUPER_TILED;
383      break;
384   case ETNA_LAYOUT_MULTI_TILED:
385      *paddingX = 16;
386      *paddingY = 4 * pixel_pipes;
387      *halign = TEXTURE_HALIGN_SPLIT_TILED;
388      break;
389   case ETNA_LAYOUT_MULTI_SUPERTILED:
390      *paddingX = 64;
391      *paddingY = 64 * pixel_pipes;
392      *halign = TEXTURE_HALIGN_SPLIT_SUPER_TILED;
393      break;
394   default:
395      DBG("Unhandled layout %i", layout);
396   }
397}
398
399static inline uint32_t
400translate_clear_depth_stencil(enum pipe_format format, float depth,
401                              unsigned stencil)
402{
403   uint32_t clear_value = 0;
404
405   // XXX util_pack_color
406   switch (format) {
407   case PIPE_FORMAT_Z16_UNORM:
408      clear_value = etna_cfloat_to_uintN(depth, 16);
409      clear_value |= clear_value << 16;
410      break;
411   case PIPE_FORMAT_X8Z24_UNORM:
412   case PIPE_FORMAT_S8_UINT_Z24_UNORM:
413      clear_value = (etna_cfloat_to_uintN(depth, 24) << 8) | (stencil & 0xFF);
414      break;
415   default:
416      DBG("Unhandled pipe format for depth stencil clear: %i", format);
417   }
418   return clear_value;
419}
420
421/* Convert MSAA number of samples to x and y scaling factor.
422 * Return true if supported and false otherwise. */
423static inline bool
424translate_samples_to_xyscale(int num_samples, int *xscale_out, int *yscale_out)
425{
426   int xscale, yscale;
427
428   switch (num_samples) {
429   case 0:
430   case 1:
431      xscale = 1;
432      yscale = 1;
433      break;
434   case 2:
435      xscale = 2;
436      yscale = 1;
437      break;
438   case 4:
439      xscale = 2;
440      yscale = 2;
441      break;
442   default:
443      return false;
444   }
445
446   if (xscale_out)
447      *xscale_out = xscale;
448   if (yscale_out)
449      *yscale_out = yscale;
450
451   return true;
452}
453
454static inline uint32_t
455translate_texture_target(unsigned target)
456{
457   switch (target) {
458   case PIPE_TEXTURE_1D:
459      return TEXTURE_TYPE_1D;
460   case PIPE_TEXTURE_2D:
461   case PIPE_TEXTURE_RECT:
462   case PIPE_TEXTURE_1D_ARRAY:
463      return TEXTURE_TYPE_2D;
464   case PIPE_TEXTURE_CUBE:
465      return TEXTURE_TYPE_CUBE_MAP;
466   case PIPE_TEXTURE_3D:
467   case PIPE_TEXTURE_2D_ARRAY:
468      return TEXTURE_TYPE_3D;
469   default:
470      DBG("Unhandled texture target: %i", target);
471      return ETNA_NO_MATCH;
472   }
473}
474
475static inline uint32_t
476translate_texture_compare(enum pipe_compare_func compare_func)
477{
478   switch (compare_func) {
479   case PIPE_FUNC_NEVER:
480      return TEXTURE_COMPARE_FUNC_NEVER;
481   case PIPE_FUNC_LESS:
482      return TEXTURE_COMPARE_FUNC_LESS;
483   case PIPE_FUNC_EQUAL:
484      return TEXTURE_COMPARE_FUNC_EQUAL;
485   case PIPE_FUNC_LEQUAL:
486      return TEXTURE_COMPARE_FUNC_LEQUAL;
487   case PIPE_FUNC_GREATER:
488      return TEXTURE_COMPARE_FUNC_GREATER;
489   case PIPE_FUNC_NOTEQUAL:
490      return TEXTURE_COMPARE_FUNC_NOTEQUAL;
491   case PIPE_FUNC_GEQUAL:
492      return TEXTURE_COMPARE_FUNC_GEQUAL;
493   case PIPE_FUNC_ALWAYS:
494      return TEXTURE_COMPARE_FUNC_ALWAYS;
495   default:
496      unreachable("Invalid compare func");
497   }
498}
499
500#endif
501