1848b8605Smrg CROSS-PLATFORM PORTABILITY GUIDELINES FOR GALLIUM3D 2848b8605Smrg 3848b8605Smrg 4848b8605Smrg= General Considerations = 5848b8605Smrg 6848b8605SmrgThe state tracker and winsys driver support a rather limited number of 7848b8605Smrgplatforms. However, the pipe drivers are meant to run in a wide number of 8848b8605Smrgplatforms. Hence the pipe drivers, the auxiliary modules, and all public 9848b8605Smrgheaders in general, should strictly follow these guidelines to ensure 10848b8605Smrg 11848b8605Smrg 12848b8605Smrg= Compiler Support = 13848b8605Smrg 14848b8605Smrg* Include the p_compiler.h. 15848b8605Smrg 16848b8605Smrg* Cast explicitly when converting to integer types of smaller sizes. 17848b8605Smrg 18848b8605Smrg* Cast explicitly when converting between float, double and integral types. 19848b8605Smrg 20848b8605Smrg* Don't use named struct initializers. 21848b8605Smrg 22848b8605Smrg* Don't use variable number of macro arguments. Use static inline functions 23848b8605Smrginstead. 24848b8605Smrg 25848b8605Smrg* Don't use C99 features. 26848b8605Smrg 27848b8605Smrg= Standard Library = 28848b8605Smrg 29848b8605Smrg* Avoid including standard library headers. Most standard library functions are 30848b8605Smrgnot available in Windows Kernel Mode. Use the appropriate p_*.h include. 31848b8605Smrg 32848b8605Smrg== Memory Allocation == 33848b8605Smrg 34848b8605Smrg* Use MALLOC, CALLOC, FREE instead of the malloc, calloc, free functions. 35848b8605Smrg 36848b8605Smrg* Use align_pointer() function defined in u_memory.h for aligning pointers 37848b8605Smrg in a portable way. 38848b8605Smrg 39848b8605Smrg== Debugging == 40848b8605Smrg 41848b8605Smrg* Use the functions/macros in p_debug.h. 42848b8605Smrg 43848b8605Smrg* Don't include assert.h, call abort, printf, etc. 44848b8605Smrg 45848b8605Smrg 46848b8605Smrg= Code Style = 47848b8605Smrg 48848b8605Smrg== Inherantice in C == 49848b8605Smrg 50848b8605SmrgThe main thing we do is mimic inheritance by structure containment. 51848b8605Smrg 52848b8605SmrgHere's a silly made-up example: 53848b8605Smrg 54848b8605Smrg/* base class */ 55848b8605Smrgstruct buffer 56848b8605Smrg{ 57848b8605Smrg int size; 58848b8605Smrg void (*validate)(struct buffer *buf); 59848b8605Smrg}; 60848b8605Smrg 61848b8605Smrg/* sub-class of bufffer */ 62848b8605Smrgstruct texture_buffer 63848b8605Smrg{ 64848b8605Smrg struct buffer base; /* the base class, MUST COME FIRST! */ 65848b8605Smrg int format; 66848b8605Smrg int width, height; 67848b8605Smrg}; 68848b8605Smrg 69848b8605Smrg 70848b8605SmrgThen, we'll typically have cast-wrapper functions to convert base-class 71848b8605Smrgpointers to sub-class pointers where needed: 72848b8605Smrg 73848b8605Smrgstatic inline struct vertex_buffer *vertex_buffer(struct buffer *buf) 74848b8605Smrg{ 75848b8605Smrg return (struct vertex_buffer *) buf; 76848b8605Smrg} 77848b8605Smrg 78848b8605Smrg 79848b8605SmrgTo create/init a sub-classed object: 80848b8605Smrg 81848b8605Smrgstruct buffer *create_texture_buffer(int w, int h, int format) 82848b8605Smrg{ 83848b8605Smrg struct texture_buffer *t = malloc(sizeof(*t)); 84848b8605Smrg t->format = format; 85848b8605Smrg t->width = w; 86848b8605Smrg t->height = h; 87848b8605Smrg t->base.size = w * h; 88848b8605Smrg t->base.validate = tex_validate; 89848b8605Smrg return &t->base; 90848b8605Smrg} 91848b8605Smrg 92848b8605SmrgExample sub-class method: 93848b8605Smrg 94848b8605Smrgvoid tex_validate(struct buffer *buf) 95848b8605Smrg{ 96848b8605Smrg struct texture_buffer *tb = texture_buffer(buf); 97848b8605Smrg assert(tb->format); 98848b8605Smrg assert(tb->width); 99848b8605Smrg assert(tb->height); 100848b8605Smrg} 101848b8605Smrg 102848b8605Smrg 103848b8605SmrgNote that we typically do not use typedefs to make "class names"; we use 104848b8605Smrg'struct whatever' everywhere. 105848b8605Smrg 106848b8605SmrgGallium's pipe_context and the subclassed psb_context, etc are prime examples 107848b8605Smrgof this. There's also many examples in Mesa and the Mesa state tracker. 108