Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4358 | Serge | 1 | CROSS-PLATFORM PORTABILITY GUIDELINES FOR GALLIUM3D |
2 | |||
3 | |||
4 | = General Considerations = |
||
5 | |||
6 | The state tracker and winsys driver support a rather limited number of |
||
7 | platforms. However, the pipe drivers are meant to run in a wide number of |
||
8 | platforms. Hence the pipe drivers, the auxiliary modules, and all public |
||
9 | headers in general, should strictly follow these guidelines to ensure |
||
10 | |||
11 | |||
12 | = Compiler Support = |
||
13 | |||
14 | * Include the p_compiler.h. |
||
15 | |||
16 | * Don't use the 'inline' keyword, use the INLINE macro in p_compiler.h instead. |
||
17 | |||
18 | * Cast explicitly when converting to integer types of smaller sizes. |
||
19 | |||
20 | * Cast explicitly when converting between float, double and integral types. |
||
21 | |||
22 | * Don't use named struct initializers. |
||
23 | |||
24 | * Don't use variable number of macro arguments. Use static inline functions |
||
25 | instead. |
||
26 | |||
27 | * Don't use C99 features. |
||
28 | |||
29 | = Standard Library = |
||
30 | |||
31 | * Avoid including standard library headers. Most standard library functions are |
||
32 | not available in Windows Kernel Mode. Use the appropriate p_*.h include. |
||
33 | |||
34 | == Memory Allocation == |
||
35 | |||
36 | * Use MALLOC, CALLOC, FREE instead of the malloc, calloc, free functions. |
||
37 | |||
38 | * Use align_pointer() function defined in u_memory.h for aligning pointers |
||
39 | in a portable way. |
||
40 | |||
41 | == Debugging == |
||
42 | |||
43 | * Use the functions/macros in p_debug.h. |
||
44 | |||
45 | * Don't include assert.h, call abort, printf, etc. |
||
46 | |||
47 | |||
48 | = Code Style = |
||
49 | |||
50 | == Inherantice in C == |
||
51 | |||
52 | The main thing we do is mimic inheritance by structure containment. |
||
53 | |||
54 | Here's a silly made-up example: |
||
55 | |||
56 | /* base class */ |
||
57 | struct buffer |
||
58 | { |
||
59 | int size; |
||
60 | void (*validate)(struct buffer *buf); |
||
61 | }; |
||
62 | |||
63 | /* sub-class of bufffer */ |
||
64 | struct texture_buffer |
||
65 | { |
||
66 | struct buffer base; /* the base class, MUST COME FIRST! */ |
||
67 | int format; |
||
68 | int width, height; |
||
69 | }; |
||
70 | |||
71 | |||
72 | Then, we'll typically have cast-wrapper functions to convert base-class |
||
73 | pointers to sub-class pointers where needed: |
||
74 | |||
75 | static inline struct vertex_buffer *vertex_buffer(struct buffer *buf) |
||
76 | { |
||
77 | return (struct vertex_buffer *) buf; |
||
78 | } |
||
79 | |||
80 | |||
81 | To create/init a sub-classed object: |
||
82 | |||
83 | struct buffer *create_texture_buffer(int w, int h, int format) |
||
84 | { |
||
85 | struct texture_buffer *t = malloc(sizeof(*t)); |
||
86 | t->format = format; |
||
87 | t->width = w; |
||
88 | t->height = h; |
||
89 | t->base.size = w * h; |
||
90 | t->base.validate = tex_validate; |
||
91 | return &t->base; |
||
92 | } |
||
93 | |||
94 | Example sub-class method: |
||
95 | |||
96 | void tex_validate(struct buffer *buf) |
||
97 | { |
||
98 | struct texture_buffer *tb = texture_buffer(buf); |
||
99 | assert(tb->format); |
||
100 | assert(tb->width); |
||
101 | assert(tb->height); |
||
102 | } |
||
103 | |||
104 | |||
105 | Note that we typically do not use typedefs to make "class names"; we use |
||
106 | 'struct whatever' everywhere. |
||
107 | |||
108 | Gallium's pipe_context and the subclassed psb_context, etc are prime examples |
||
109 | of this. There's also many examples in Mesa and the Mesa state tracker. |