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. 110