xref: /aosp_15_r20/external/mesa3d/docs/codingstyle.rst (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1Coding Style
2============
3
4Mesa is over 20 years old and the coding style has evolved over time.
5Some old parts use a style that's a bit out of date. Different sections
6of mesa can use different coding style as set in the local EditorConfig
7(.editorconfig) and/or Emacs (.dir-locals.el) file. Alternatively the
8following is applicable. If the guidelines below don't cover something,
9try following the format of existing, neighboring code.
10
11``clang-format``
12----------------
13
14A growing number of drivers and components are adopting ``clang-format``
15to standardize the formatting and make it easy for everyone to apply it.
16
17You can re-format the code for the components that have opted-in to the
18formatting enforcement (listed in ``.clang-format-include``) by simply
19running ``ninja -C build/ clang-format``.
20
21Since mass-reformatting commits can be an annoying extra jump to go
22through when looking at ``git blame``, you can configure it to ignore
23them by running::
24
25  git config blame.ignoreRevsFile .git-blame-ignore-revs
26
27Most code editors also support automatically formatting code as you
28write it; check your editor or its plug-ins to see how to enable this.
29
30Vim
31***
32
33Add this to your ``.vimrc`` to automatically format any C & C++ file
34(that has a .clang-format config) when you save it:
35
36.. code:: vim
37
38   augroup ClangFormatOnSave
39     au!
40
41     function! ClangFormatOnSave()
42       " Only format files that have a .clang-format in a parent folder
43       if !empty(findfile('.clang-format', '.;'))
44         let l:formatdiff = 1 " Only format lines that have changed
45         py3f /usr/share/clang/clang-format.py
46       endif
47     endfunction
48
49     autocmd BufWritePre *.h,*.c,*.cc,*.cpp call ClangFormatOnSave()
50   augroup END
51
52If ``/usr/share/clang/clang-format.py`` doesn't exist, try
53``/usr/share/clang/clang-format-$CLANG_VERSION/clang-format.py``
54(replacing ``$CLANG_VERSION`` with your clang version). If your distro
55has put the file somewhere else, look through the files in the package
56providing ``clang-format``.
57
58Emacs
59*****
60
61Add this to your ``.emacs`` to automatically format any C & C++ file
62(that has a .clang-format config) when you save it:
63
64.. code:: emacs
65
66   (load "/usr/share/clang/clang-format.el")
67
68   (defun clang-format-save-hook-for-this-buffer ()
69     "Create a buffer local save hook."
70     (add-hook 'before-save-hook
71               (lambda ()
72                 (when (locate-dominating-file "." ".clang-format")
73                   (clang-format-buffer))
74                 ;; Continue to save.
75                 nil)
76               nil
77               ;; Buffer local hook.
78               t))
79
80   ;; Run this for each mode you want to use the hook.
81   (add-hook 'c-mode-hook (lambda () (clang-format-save-hook-for-this-buffer)))
82   (add-hook 'c++-mode-hook (lambda () (clang-format-save-hook-for-this-buffer)))
83
84If ``/usr/share/clang/clang-format.el`` doesn't exist, look through the
85files in the package providing ``clang-format`` in your distro. If you
86can't find anything (e.g. on Debian/Ubuntu), refer to `this StackOverflow
87answer <https://stackoverflow.com/questions/59690583/how-do-you-use-clang-format-on-emacs-ubuntu/59850773#59850773>`__
88to install clang-format through Emacs instead.
89
90git ``pre-commit`` hook
91***********************
92
93If your editor doesn't support this, or if you don't want to enable it, you
94can always just run ``ninja clang-format`` to format everything, or add
95a ``pre-commit`` hook that runs this automatically whenever you ``git
96commit`` by adding the following in your ``.git/hooks/pre-commit``:
97
98.. code:: sh
99
100   shopt -s globstar
101   git clang-format $upstream -- $(grep -E '^[^#]' .clang-format-include)
102   # replace $upstream with the name of the remote tracking upstream mesa
103   # if you don't know, it's probably `origin`
104
105
106Basic formatting guidelines
107---------------------------
108
109-  3-space indentation, no tabs.
110-  Limit lines to 78 or fewer characters. The idea is to prevent line
111   wrapping in 80-column editors and terminals. There are exceptions,
112   such as if you're defining a large, static table of information.
113-  Opening braces go on the same line as the if/for/while statement. For
114   example:
115
116   .. code-block:: c
117
118      if (condition) {
119         foo;
120      } else {
121         bar;
122      }
123
124-  Put a space before/after operators. For example, ``a = b + c;`` and
125   not ``a=b+c;``
126-  This GNU indent command generally does the right thing for
127   formatting:
128
129   .. code-block:: sh
130
131      indent -br -i3 -npcs --no-tabs infile.c -o outfile.c
132
133-  Use comments wherever you think it would be helpful for other
134   developers. Several specific cases and style examples follow. Note
135   that we roughly follow `Doxygen <https://www.doxygen.nl>`__
136   conventions.
137
138   Single-line comments:
139
140   .. code-block:: c
141
142      /* null-out pointer to prevent dangling reference below */
143      bufferObj = NULL;
144
145   Or,
146
147   .. code-block:: c
148
149      bufferObj = NULL;  /* prevent dangling reference below */
150
151   Multi-line comment:
152
153   .. code-block:: c
154
155      /* If this is a new buffer object id, or one which was generated but
156       * never used before, allocate a buffer object now.
157       */
158
159   We try to quote the OpenGL specification where prudent:
160
161   .. code-block:: c
162
163      /* Page 38 of the PDF of the OpenGL ES 3.0 spec says:
164       *
165       *     "An INVALID_OPERATION error is generated for any of the following
166       *     conditions:
167       *
168       *     * <length> is zero."
169       *
170       * Additionally, page 94 of the PDF of the OpenGL 4.5 core spec
171       * (30.10.2014) also says this, so it's no longer allowed for desktop GL,
172       * either.
173       */
174
175   Function comment example:
176
177   .. code-block:: c
178
179      /**
180       * Create and initialize a new buffer object.  Called via the
181       * ctx->Driver.CreateObject() driver callback function.
182       * \param  name  integer name of the object
183       * \param  type  one of GL_FOO, GL_BAR, etc.
184       * \return  pointer to new object or NULL if error
185       */
186      struct gl_object *
187      _mesa_create_object(GLuint name, GLenum type)
188      {
189         /* function body */
190      }
191
192-  Put the function return type and qualifiers on one line and the
193   function name and parameters on the next, as seen above. This makes
194   it easy to use ``grep ^function_name dir/*`` to find function
195   definitions. Also, the opening brace goes on the next line by itself
196   (see above.)
197-  Function names follow various conventions depending on the type of
198   function:
199
200   +---------------------+------------------------------------------+
201   | Convention          | Explanation                              |
202   +=====================+==========================================+
203   | ``glFooBar()``      | a public GL entry point (in              |
204   |                     | :file:`glapi_dispatch.c`)                |
205   +---------------------+------------------------------------------+
206   | ``_mesa_FooBar()``  | the internal immediate mode function     |
207   +---------------------+------------------------------------------+
208   | ``save_FooBar()``   | retained mode (display list) function in |
209   |                     | :file:`dlist.c`                          |
210   +---------------------+------------------------------------------+
211   | ``foo_bar()``       | a static (private) function              |
212   +---------------------+------------------------------------------+
213   | ``_mesa_foo_bar()`` | an internal non-static Mesa function     |
214   +---------------------+------------------------------------------+
215
216-  Constants, macros and enum names are ``ALL_UPPERCASE``, with \_
217   between words.
218-  Mesa usually uses camel case for local variables (Ex:
219   ``localVarname``) while Gallium typically uses underscores (Ex:
220   ``local_var_name``).
221-  Global variables are almost never used because Mesa should be
222   thread-safe.
223-  Booleans. Places that are not directly visible to the GL API should
224   prefer the use of ``bool``, ``true``, and ``false`` over
225   ``GLboolean``, ``GL_TRUE``, and ``GL_FALSE``. In C code, this may
226   mean that ``#include <stdbool.h>`` needs to be added. The
227   ``try_emit_*`` method ``src/mesa/state_tracker/st_glsl_to_tgsi.cpp``
228   can serve as an example.
229