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/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(unsigned blend)
118{
119   switch (blend) {
120   case PIPE_BLEND_ADD:
121      return BLEND_EQ_ADD;
122   case PIPE_BLEND_SUBTRACT:
123      return BLEND_EQ_SUBTRACT;
124   case PIPE_BLEND_REVERSE_SUBTRACT:
125      return BLEND_EQ_REVERSE_SUBTRACT;
126   case PIPE_BLEND_MIN:
127      return BLEND_EQ_MIN;
128   case PIPE_BLEND_MAX:
129      return BLEND_EQ_MAX;
130   default:
131      DBG("Unhandled blend: %i", blend);
132      return ETNA_NO_MATCH;
133   }
134}
135
136static inline uint32_t
137translate_blend_factor(unsigned blend_factor)
138{
139   switch (blend_factor) {
140   case PIPE_BLENDFACTOR_ONE:
141      return BLEND_FUNC_ONE;
142   case PIPE_BLENDFACTOR_SRC_COLOR:
143      return BLEND_FUNC_SRC_COLOR;
144   case PIPE_BLENDFACTOR_SRC_ALPHA:
145      return BLEND_FUNC_SRC_ALPHA;
146   case PIPE_BLENDFACTOR_DST_ALPHA:
147      return BLEND_FUNC_DST_ALPHA;
148   case PIPE_BLENDFACTOR_DST_COLOR:
149      return BLEND_FUNC_DST_COLOR;
150   case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
151      return BLEND_FUNC_SRC_ALPHA_SATURATE;
152   case PIPE_BLENDFACTOR_CONST_COLOR:
153      return BLEND_FUNC_CONSTANT_COLOR;
154   case PIPE_BLENDFACTOR_CONST_ALPHA:
155      return BLEND_FUNC_CONSTANT_ALPHA;
156   case PIPE_BLENDFACTOR_ZERO:
157      return BLEND_FUNC_ZERO;
158   case PIPE_BLENDFACTOR_INV_SRC_COLOR:
159      return BLEND_FUNC_ONE_MINUS_SRC_COLOR;
160   case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
161      return BLEND_FUNC_ONE_MINUS_SRC_ALPHA;
162   case PIPE_BLENDFACTOR_INV_DST_ALPHA:
163      return BLEND_FUNC_ONE_MINUS_DST_ALPHA;
164   case PIPE_BLENDFACTOR_INV_DST_COLOR:
165      return BLEND_FUNC_ONE_MINUS_DST_COLOR;
166   case PIPE_BLENDFACTOR_INV_CONST_COLOR:
167      return BLEND_FUNC_ONE_MINUS_CONSTANT_COLOR;
168   case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
169      return BLEND_FUNC_ONE_MINUS_CONSTANT_ALPHA;
170   case PIPE_BLENDFACTOR_SRC1_COLOR:
171   case PIPE_BLENDFACTOR_SRC1_ALPHA:
172   case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
173   case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
174   default:
175      DBG("Unhandled blend factor: %i", blend_factor);
176      return ETNA_NO_MATCH;
177   }
178}
179
180static inline uint32_t
181translate_texture_wrapmode(unsigned wrap)
182{
183   switch (wrap) {
184   case PIPE_TEX_WRAP_REPEAT:
185      return TEXTURE_WRAPMODE_REPEAT;
186   case PIPE_TEX_WRAP_CLAMP:
187      return TEXTURE_WRAPMODE_CLAMP_TO_EDGE;
188   case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
189      return TEXTURE_WRAPMODE_CLAMP_TO_EDGE;
190   case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
191      return TEXTURE_WRAPMODE_CLAMP_TO_EDGE; /* XXX */
192   case PIPE_TEX_WRAP_MIRROR_REPEAT:
193      return TEXTURE_WRAPMODE_MIRRORED_REPEAT;
194   case PIPE_TEX_WRAP_MIRROR_CLAMP:
195      return TEXTURE_WRAPMODE_MIRRORED_REPEAT; /* XXX */
196   case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
197      return TEXTURE_WRAPMODE_MIRRORED_REPEAT; /* XXX */
198   case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
199      return TEXTURE_WRAPMODE_MIRRORED_REPEAT; /* XXX */
200   default:
201      DBG("Unhandled texture wrapmode: %i", wrap);
202      return ETNA_NO_MATCH;
203   }
204}
205
206static inline uint32_t
207translate_texture_mipfilter(unsigned filter)
208{
209   switch (filter) {
210   case PIPE_TEX_MIPFILTER_NEAREST:
211      return TEXTURE_FILTER_NEAREST;
212   case PIPE_TEX_MIPFILTER_LINEAR:
213      return TEXTURE_FILTER_LINEAR;
214   case PIPE_TEX_MIPFILTER_NONE:
215      return TEXTURE_FILTER_NONE;
216   default:
217      DBG("Unhandled texture mipfilter: %i", filter);
218      return ETNA_NO_MATCH;
219   }
220}
221
222static inline uint32_t
223translate_texture_filter(unsigned filter)
224{
225   switch (filter) {
226   case PIPE_TEX_FILTER_NEAREST:
227      return TEXTURE_FILTER_NEAREST;
228   case PIPE_TEX_FILTER_LINEAR:
229      return TEXTURE_FILTER_LINEAR;
230   /* What about anisotropic? */
231   default:
232      DBG("Unhandled texture filter: %i", filter);
233      return ETNA_NO_MATCH;
234   }
235}
236
237/* return a RS "compatible" format for use when copying */
238static inline enum pipe_format
239etna_compatible_rs_format(enum pipe_format fmt)
240{
241   /* YUYV and UYVY are blocksize 4, but 2 bytes per pixel */
242   if (fmt == PIPE_FORMAT_YUYV || fmt == PIPE_FORMAT_UYVY)
243      return PIPE_FORMAT_B4G4R4A4_UNORM;
244
245   switch (util_format_get_blocksize(fmt)) {
246   case 2:
247      return PIPE_FORMAT_B4G4R4A4_UNORM;
248   case 4:
249      return PIPE_FORMAT_B8G8R8A8_UNORM;
250   default:
251      return fmt;
252   }
253}
254
255static inline int
256translate_rb_src_dst_swap(enum pipe_format src, enum pipe_format dst)
257{
258   return translate_rs_format_rb_swap(src) ^ translate_rs_format_rb_swap(dst);
259}
260
261static inline uint32_t
262translate_depth_format(enum pipe_format fmt)
263{
264   /* Note: Pipe format convention is LSB to MSB, VIVS is MSB to LSB */
265   switch (fmt) {
266   case PIPE_FORMAT_Z16_UNORM:
267      return VIVS_PE_DEPTH_CONFIG_DEPTH_FORMAT_D16;
268   case PIPE_FORMAT_X8Z24_UNORM:
269      return VIVS_PE_DEPTH_CONFIG_DEPTH_FORMAT_D24S8;
270   case PIPE_FORMAT_S8_UINT_Z24_UNORM:
271      return VIVS_PE_DEPTH_CONFIG_DEPTH_FORMAT_D24S8;
272   default:
273      return ETNA_NO_MATCH;
274   }
275}
276
277/* render target format for MSAA */
278static inline uint32_t
279translate_msaa_format(enum pipe_format fmt)
280{
281   /* Note: Pipe format convention is LSB to MSB, VIVS is MSB to LSB */
282   switch (fmt) {
283   case PIPE_FORMAT_B4G4R4X4_UNORM:
284      return COLOR_COMPRESSION_FORMAT_A4R4G4B4;
285   case PIPE_FORMAT_B4G4R4A4_UNORM:
286      return COLOR_COMPRESSION_FORMAT_A4R4G4B4;
287   case PIPE_FORMAT_B5G5R5X1_UNORM:
288      return COLOR_COMPRESSION_FORMAT_A1R5G5B5;
289   case PIPE_FORMAT_B5G5R5A1_UNORM:
290      return COLOR_COMPRESSION_FORMAT_A1R5G5B5;
291   case PIPE_FORMAT_B5G6R5_UNORM:
292      return COLOR_COMPRESSION_FORMAT_R5G6B5;
293   case PIPE_FORMAT_B8G8R8X8_UNORM:
294      return COLOR_COMPRESSION_FORMAT_X8R8G8B8;
295   case PIPE_FORMAT_B8G8R8A8_UNORM:
296      return COLOR_COMPRESSION_FORMAT_A8R8G8B8;
297   /* MSAA with YUYV not supported */
298   default:
299      return ETNA_NO_MATCH;
300   }
301}
302
303/* Return normalization flag for vertex element format */
304static inline uint32_t
305translate_vertex_format_normalize(enum pipe_format fmt)
306{
307   const struct util_format_description *desc = util_format_description(fmt);
308   if (!desc)
309      return VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_OFF;
310
311   /* assumes that normalization of channel 0 holds for all channels;
312    * this holds for all vertex formats that we support */
313   return desc->channel[0].normalized
314             ? VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_ON
315             : VIVS_FE_VERTEX_ELEMENT_CONFIG_NORMALIZE_OFF;
316}
317
318static inline uint32_t
319translate_index_size(unsigned index_size)
320{
321   switch (index_size) {
322   case 1:
323      return VIVS_FE_INDEX_STREAM_CONTROL_TYPE_UNSIGNED_CHAR;
324   case 2:
325      return VIVS_FE_INDEX_STREAM_CONTROL_TYPE_UNSIGNED_SHORT;
326   case 4:
327      return VIVS_FE_INDEX_STREAM_CONTROL_TYPE_UNSIGNED_INT;
328   default:
329      DBG("Unhandled index size %i", index_size);
330      return ETNA_NO_MATCH;
331   }
332}
333
334static inline uint32_t
335translate_draw_mode(unsigned mode)
336{
337   switch (mode) {
338   case PIPE_PRIM_POINTS:
339      return PRIMITIVE_TYPE_POINTS;
340   case PIPE_PRIM_LINES:
341      return PRIMITIVE_TYPE_LINES;
342   case PIPE_PRIM_LINE_LOOP:
343      return PRIMITIVE_TYPE_LINE_LOOP;
344   case PIPE_PRIM_LINE_STRIP:
345      return PRIMITIVE_TYPE_LINE_STRIP;
346   case PIPE_PRIM_TRIANGLES:
347      return PRIMITIVE_TYPE_TRIANGLES;
348   case PIPE_PRIM_TRIANGLE_STRIP:
349      return PRIMITIVE_TYPE_TRIANGLE_STRIP;
350   case PIPE_PRIM_TRIANGLE_FAN:
351      return PRIMITIVE_TYPE_TRIANGLE_FAN;
352   case PIPE_PRIM_QUADS:
353      return PRIMITIVE_TYPE_QUADS;
354   default:
355      DBG("Unhandled draw mode primitive %i", mode);
356      return ETNA_NO_MATCH;
357   }
358}
359
360/* Get size multiple for size of texture/rendertarget with a certain layout
361 * This is affected by many different parameters:
362 *   - A horizontal multiple of 16 is used when possible as resolve can be used
363 *       at the cost of only a little bit extra memory usage.
364 *   - If the surface is to be used with the resolve engine, set rs_align true.
365 *       If set, a horizontal multiple of 16 will be used for tiled and linear,
366 *       otherwise one of 16.  However, such a surface will be incompatible
367 *       with the samplers if the GPU does hot support the HALIGN feature.
368 *   - If the surface is supertiled, horizontal and vertical multiple is always 64
369 *   - If the surface is multi tiled or supertiled, make sure that the vertical size
370 *     is a multiple of the number of pixel pipes as well.
371 * */
372static inline void
373etna_layout_multiple(unsigned layout, unsigned pixel_pipes, bool rs_align,
374                     unsigned *paddingX, unsigned *paddingY, unsigned *halign)
375{
376   switch (layout) {
377   case ETNA_LAYOUT_LINEAR:
378      *paddingX = rs_align ? 16 : 4;
379      *paddingY = 1;
380      *halign = rs_align ? TEXTURE_HALIGN_SIXTEEN : TEXTURE_HALIGN_FOUR;
381      break;
382   case ETNA_LAYOUT_TILED:
383      *paddingX = rs_align ? 16 : 4;
384      *paddingY = 4;
385      *halign = rs_align ? TEXTURE_HALIGN_SIXTEEN : TEXTURE_HALIGN_FOUR;
386      break;
387   case ETNA_LAYOUT_SUPER_TILED:
388      *paddingX = 64;
389      *paddingY = 64;
390      *halign = TEXTURE_HALIGN_SUPER_TILED;
391      break;
392   case ETNA_LAYOUT_MULTI_TILED:
393      *paddingX = 16;
394      *paddingY = 4 * pixel_pipes;
395      *halign = TEXTURE_HALIGN_SPLIT_TILED;
396      break;
397   case ETNA_LAYOUT_MULTI_SUPERTILED:
398      *paddingX = 64;
399      *paddingY = 64 * pixel_pipes;
400      *halign = TEXTURE_HALIGN_SPLIT_SUPER_TILED;
401      break;
402   default:
403      DBG("Unhandled layout %i", layout);
404   }
405}
406
407static inline void etna_adjust_rs_align(unsigned num_pixelpipes,
408                                        unsigned *paddingX, unsigned *paddingY)
409{
410   unsigned alignX = ETNA_RS_WIDTH_MASK + 1;
411   unsigned alignY = (ETNA_RS_HEIGHT_MASK + 1) * num_pixelpipes;
412
413   if (paddingX)
414      *paddingX = align(*paddingX, alignX);
415   if (paddingY)
416      *paddingY = align(*paddingY, alignY);
417}
418
419static inline uint32_t
420translate_clear_depth_stencil(enum pipe_format format, float depth,
421                              unsigned stencil)
422{
423   uint32_t clear_value = 0;
424
425   // XXX util_pack_color
426   switch (format) {
427   case PIPE_FORMAT_Z16_UNORM:
428      clear_value = etna_cfloat_to_uintN(depth, 16);
429      clear_value |= clear_value << 16;
430      break;
431   case PIPE_FORMAT_X8Z24_UNORM:
432   case PIPE_FORMAT_S8_UINT_Z24_UNORM:
433      clear_value = (etna_cfloat_to_uintN(depth, 24) << 8) | (stencil & 0xFF);
434      break;
435   default:
436      DBG("Unhandled pipe format for depth stencil clear: %i", format);
437   }
438   return clear_value;
439}
440
441/* Convert MSAA number of samples to x and y scaling factor and
442 * VIVS_GL_MULTI_SAMPLE_CONFIG value.
443 * Return true if supported and false otherwise. */
444static inline bool
445translate_samples_to_xyscale(int num_samples, int *xscale_out, int *yscale_out,
446                             uint32_t *config_out)
447{
448   int xscale, yscale;
449   uint32_t config;
450
451   switch (num_samples) {
452   case 0:
453   case 1:
454      xscale = 1;
455      yscale = 1;
456      config = VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_NONE;
457      break;
458   case 2:
459      xscale = 2;
460      yscale = 1;
461      config = VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_2X;
462      break;
463   case 4:
464      xscale = 2;
465      yscale = 2;
466      config = VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_4X;
467      break;
468   default:
469      return false;
470   }
471
472   if (xscale_out)
473      *xscale_out = xscale;
474   if (yscale_out)
475      *yscale_out = yscale;
476   if (config_out)
477      *config_out = config;
478
479   return true;
480}
481
482#endif
483