deepstone

annotate src/mglrast.c @ 28:11d14f688485

added clipping
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 22 Sep 2013 06:38:08 +0300
parents 5ff8ce78059a
children 17a5107b6fa4
rev   line source
nuclear@0 1 #include <stdio.h>
nuclear@0 2 #include <stdlib.h>
nuclear@0 3 #include <string.h>
nuclear@9 4 #include <limits.h>
nuclear@0 5 #include <assert.h>
nuclear@0 6 #include "mingl.h"
nuclear@0 7 #include "mglimpl.h"
nuclear@0 8
nuclear@0 9
nuclear@25 10 #ifdef RAST_FLOAT
nuclear@25 11 typedef struct vertex VERTEX;
nuclear@25 12 #else
nuclear@25 13 typedef struct fixed_vertex VERTEX;
nuclear@25 14 #endif
nuclear@25 15
nuclear@25 16 static VERTEX *vleft, *vright;
nuclear@0 17 static struct framebuffer *fb;
nuclear@0 18 static struct state *st;
nuclear@0 19
nuclear@0 20
nuclear@0 21 #define SCAN_EDGE scan_edge_flat
nuclear@0 22 #define SCAN_LINE scan_line_flat
nuclear@0 23 #undef INTERP_DEPTH
nuclear@0 24 #undef INTERP_ENERGY
nuclear@3 25 #undef INTERP_TEX
nuclear@0 26 #include "scantmpl.h"
nuclear@0 27 #undef SCAN_EDGE
nuclear@0 28 #undef SCAN_LINE
nuclear@0 29
nuclear@0 30 #define SCAN_EDGE scan_edge_z
nuclear@0 31 #define SCAN_LINE scan_line_z
nuclear@0 32 #define INTERP_DEPTH
nuclear@0 33 #undef INTERP_ENERGY
nuclear@3 34 #undef INTERP_TEX
nuclear@0 35 #include "scantmpl.h"
nuclear@0 36 #undef SCAN_EDGE
nuclear@0 37 #undef SCAN_LINE
nuclear@0 38
nuclear@0 39 #define SCAN_EDGE scan_edge_e
nuclear@0 40 #define SCAN_LINE scan_line_e
nuclear@0 41 #undef INTERP_DEPTH
nuclear@0 42 #define INTERP_ENERGY
nuclear@3 43 #undef INTERP_TEX
nuclear@0 44 #include "scantmpl.h"
nuclear@0 45 #undef SCAN_EDGE
nuclear@0 46 #undef SCAN_LINE
nuclear@0 47
nuclear@0 48 #define SCAN_EDGE scan_edge_ze
nuclear@0 49 #define SCAN_LINE scan_line_ze
nuclear@0 50 #define INTERP_DEPTH
nuclear@0 51 #define INTERP_ENERGY
nuclear@3 52 #undef INTERP_TEX
nuclear@0 53 #include "scantmpl.h"
nuclear@0 54 #undef SCAN_EDGE
nuclear@0 55 #undef SCAN_LINE
nuclear@0 56
nuclear@3 57 #define SCAN_EDGE scan_edge_t
nuclear@3 58 #define SCAN_LINE scan_line_t
nuclear@3 59 #undef INTERP_DEPTH
nuclear@3 60 #undef INTERP_ENERGY
nuclear@3 61 #define INTERP_TEX
nuclear@3 62 #include "scantmpl.h"
nuclear@3 63 #undef SCAN_EDGE
nuclear@3 64 #undef SCAN_LINE
nuclear@3 65
nuclear@3 66 #define SCAN_EDGE scan_edge_zt
nuclear@3 67 #define SCAN_LINE scan_line_zt
nuclear@3 68 #define INTERP_DEPTH
nuclear@3 69 #undef INTERP_ENERGY
nuclear@3 70 #define INTERP_TEX
nuclear@3 71 #include "scantmpl.h"
nuclear@3 72 #undef SCAN_EDGE
nuclear@3 73 #undef SCAN_LINE
nuclear@3 74
nuclear@3 75 #define SCAN_EDGE scan_edge_et
nuclear@3 76 #define SCAN_LINE scan_line_et
nuclear@3 77 #undef INTERP_DEPTH
nuclear@3 78 #define INTERP_ENERGY
nuclear@3 79 #define INTERP_TEX
nuclear@3 80 #include "scantmpl.h"
nuclear@3 81 #undef SCAN_EDGE
nuclear@3 82 #undef SCAN_LINE
nuclear@3 83
nuclear@3 84 #define SCAN_EDGE scan_edge_zet
nuclear@3 85 #define SCAN_LINE scan_line_zet
nuclear@3 86 #define INTERP_DEPTH
nuclear@3 87 #define INTERP_ENERGY
nuclear@3 88 #define INTERP_TEX
nuclear@3 89 #include "scantmpl.h"
nuclear@3 90 #undef SCAN_EDGE
nuclear@3 91 #undef SCAN_LINE
nuclear@3 92
nuclear@3 93
nuclear@25 94 static void (*scan_edge)(VERTEX*, VERTEX*);
nuclear@0 95 static void (*scan_line)(int, unsigned char*);
nuclear@0 96
nuclear@25 97
nuclear@0 98 int mgl_rast_init(struct state *state, struct framebuffer *fbuf)
nuclear@0 99 {
nuclear@0 100 fb = fbuf;
nuclear@0 101 st = state;
nuclear@0 102
nuclear@0 103 if(!(vleft = malloc(fb->height * sizeof *vleft))) {
nuclear@0 104 return -1;
nuclear@0 105 }
nuclear@0 106 if(!(vright = malloc(fb->height * sizeof *vright))) {
nuclear@0 107 free(vleft);
nuclear@0 108 return -1;
nuclear@0 109 }
nuclear@0 110
nuclear@0 111 scan_edge = scan_edge_flat;
nuclear@0 112 scan_line = scan_line_flat;
nuclear@0 113
nuclear@0 114 return 0;
nuclear@0 115 }
nuclear@0 116
nuclear@0 117 void mgl_rast_cleanup(void)
nuclear@0 118 {
nuclear@0 119 free(vleft);
nuclear@0 120 free(vright);
nuclear@0 121 }
nuclear@0 122
nuclear@0 123 void mgl_rast_prepare(void)
nuclear@0 124 {
nuclear@25 125 static void (*sedge[])(VERTEX*, VERTEX*) = {
nuclear@3 126 /* tez */
nuclear@3 127 scan_edge_flat, /* 000 */
nuclear@3 128 scan_edge_z, /* 001 */
nuclear@3 129 scan_edge_e, /* 010 */
nuclear@3 130 scan_edge_ze, /* 011 */
nuclear@3 131 scan_edge_t, /* 100 */
nuclear@3 132 scan_edge_zt, /* 101 */
nuclear@3 133 scan_edge_et, /* 110 */
nuclear@3 134 scan_edge_zet /* 111 */
nuclear@0 135 };
nuclear@0 136 static void (*sline[])(int, unsigned char*) = {
nuclear@3 137 /* tez */
nuclear@3 138 scan_line_flat, /* 000 */
nuclear@3 139 scan_line_z, /* 001 */
nuclear@3 140 scan_line_e, /* 010 */
nuclear@3 141 scan_line_ze, /* 011 */
nuclear@3 142 scan_line_t, /* 100 */
nuclear@3 143 scan_line_zt, /* 101 */
nuclear@3 144 scan_line_et, /* 110 */
nuclear@3 145 scan_line_zet /* 111 */
nuclear@0 146 };
nuclear@0 147 int bits = 0;
nuclear@0 148
nuclear@28 149 if(IS_ENABLED(st->flags, MGL_TEXTURE_2D) && st->tex.pixels) {
nuclear@3 150 bits |= 4;
nuclear@3 151 }
nuclear@28 152 if(IS_ENABLED(st->flags, MGL_SMOOTH)) {
nuclear@0 153 bits |= 2;
nuclear@0 154 }
nuclear@28 155 if(IS_ENABLED(st->flags, MGL_DEPTH_TEST) && fb->zbuf) {
nuclear@0 156 bits |= 1;
nuclear@0 157 }
nuclear@0 158
nuclear@0 159 scan_edge = sedge[bits];
nuclear@0 160 scan_line = sline[bits];
nuclear@0 161 }
nuclear@0 162
nuclear@0 163 void mgl_draw_point(struct vertex *v)
nuclear@0 164 {
nuclear@0 165 int x = (int)ROUND(v->pos.x);
nuclear@0 166 int y = (int)ROUND(v->pos.y);
nuclear@0 167
nuclear@0 168 if(x >= 0 && x < fb->width && y >= 0 && y < fb->height) {
nuclear@0 169 int cidx = v->cidx + v->energy * st->col_range;
nuclear@0 170 fb->pixels[y * fb->width + x] = cidx;
nuclear@0 171 }
nuclear@0 172 }
nuclear@0 173
nuclear@0 174 void mgl_draw_line(struct vertex *v0, struct vertex *v1)
nuclear@0 175 {
nuclear@0 176 /* TODO */
nuclear@0 177 fprintf(stderr, "draw_line unimplemented\n");
nuclear@0 178 abort();
nuclear@0 179 }
nuclear@0 180
nuclear@0 181 void mgl_draw_poly(struct vertex *v, int numv)
nuclear@0 182 {
nuclear@25 183 #ifdef RAST_FLOAT
nuclear@0 184 int ybeg, yend, i;
nuclear@0 185 unsigned char *sline;
nuclear@0 186
nuclear@0 187 ybeg = fb->height;
nuclear@0 188 yend = 0;
nuclear@0 189
nuclear@0 190 for(i=0; i<numv; i++) {
nuclear@0 191 struct vertex *v0 = v + i;
nuclear@0 192 struct vertex *v1 = v + (i + 1) % numv;
nuclear@0 193 int y = (int)ROUND(v0->pos.y);
nuclear@0 194
nuclear@0 195 scan_edge(v0, v1);
nuclear@0 196
nuclear@0 197 if(y > yend) yend = y;
nuclear@0 198 if(y < ybeg) ybeg = y;
nuclear@0 199 }
nuclear@0 200
nuclear@0 201 if(ybeg < 0) ybeg = 0;
nuclear@0 202 if(yend >= fb->height) yend = fb->height - 1;
nuclear@0 203
nuclear@0 204 sline = fb->pixels + ybeg * fb->width;
nuclear@0 205 for(i=ybeg; i<yend; i++) {
nuclear@0 206 scan_line(i, sline);
nuclear@0 207 sline += fb->width;
nuclear@0 208 }
nuclear@25 209 #else
nuclear@25 210 int ybeg, yend, i;
nuclear@25 211 unsigned char *sline;
nuclear@25 212
nuclear@25 213 ybeg = fb->height;
nuclear@25 214 yend = 0;
nuclear@25 215
nuclear@25 216 for(i=0; i<numv; i++) {
nuclear@25 217 int y;
nuclear@25 218 struct vertex *v0 = v + i;
nuclear@25 219 struct vertex *v1 = v + (i + 1) % numv;
nuclear@25 220 struct fixed_vertex vx0, vx1;
nuclear@25 221
nuclear@25 222 vertex_to_fixedvertex(*v0, vx0);
nuclear@25 223 vertex_to_fixedvertex(*v1, vx1);
nuclear@25 224
nuclear@25 225 y = fixed_round(vx0.pos.y);
nuclear@25 226
nuclear@25 227 scan_edge(&vx0, &vx1);
nuclear@25 228
nuclear@25 229 if(y > yend) yend = y;
nuclear@25 230 if(y < ybeg) ybeg = y;
nuclear@25 231 }
nuclear@25 232
nuclear@25 233 if(ybeg < 0) ybeg = 0;
nuclear@25 234 if(yend >= fb->height) yend = fb->height - 1;
nuclear@25 235
nuclear@25 236 sline = fb->pixels + ybeg * fb->width;
nuclear@25 237 for(i=ybeg; i<yend; i++) {
nuclear@25 238 scan_line(i, sline);
nuclear@25 239 sline += fb->width;
nuclear@25 240 }
nuclear@25 241 #endif
nuclear@0 242 }