1 /* ResidualVM - A 3D game interpreter
2 *
3 * ResidualVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the AUTHORS
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 /*
24 * This file is based on, or a modified version of code from TinyGL (C) 1997-1998 Fabrice Bellard,
25 * which is licensed under the zlib-license (see LICENSE).
26 * It also has modifications by the ResidualVM-team, which are covered under the GPLv2 (or later).
27 */
28
29 #define FORBIDDEN_SYMBOL_EXCEPTION_FILE
30 #define FORBIDDEN_SYMBOL_EXCEPTION_fprintf
31 #define FORBIDDEN_SYMBOL_EXCEPTION_fputc
32 #define FORBIDDEN_SYMBOL_EXCEPTION_stderr
33
34 #include "graphics/tinygl/zgl.h"
35
36 namespace TinyGL {
37
38 static const char *op_table_str[] = {
39 #define ADD_OP(a, b, c) "gl" #a " " #c,
40
41 #include "graphics/tinygl/opinfo.h"
42 };
43
44 static void (*op_table_func[])(GLContext *, GLParam *) = {
45 #define ADD_OP(a, b, c) glop ## a ,
46
47 #include "graphics/tinygl/opinfo.h"
48 };
49
50 static int op_table_size[] = {
51 #define ADD_OP(a, b, c) b + 1 ,
52
53 #include "graphics/tinygl/opinfo.h"
54 };
55
gl_get_context()56 GLContext *gl_get_context() {
57 return gl_ctx;
58 }
59
find_list(GLContext * c,unsigned int list)60 static GLList *find_list(GLContext *c, unsigned int list) {
61 return c->shared_state.lists[list];
62 }
63
delete_list(GLContext * c,int list)64 static void delete_list(GLContext *c, int list) {
65 GLParamBuffer *pb, *pb1;
66 GLList *l;
67
68 l = find_list(c, list);
69 assert(l);
70
71 // free param buffer
72 pb = l->first_op_buffer;
73 while (pb) {
74 pb1 = pb->next;
75 gl_free(pb);
76 pb = pb1;
77 }
78
79 gl_free(l);
80 c->shared_state.lists[list] = NULL;
81 }
82
alloc_list(GLContext * c,int list)83 static GLList *alloc_list(GLContext *c, int list) {
84 GLList *l;
85 GLParamBuffer *ob;
86
87 l = (GLList *)gl_zalloc(sizeof(GLList));
88 ob = (GLParamBuffer *)gl_zalloc(sizeof(GLParamBuffer));
89
90 ob->next = NULL;
91 l->first_op_buffer = ob;
92
93 ob->ops[0].op = OP_EndList;
94
95 c->shared_state.lists[list] = l;
96 return l;
97 }
98
gl_print_op(FILE * f,GLParam * p)99 void gl_print_op(FILE *f, GLParam *p) {
100 int op;
101 const char *s;
102
103 op = p[0].op;
104 p++;
105 s = op_table_str[op];
106 while (*s != 0) {
107 if (*s == '%') {
108 s++;
109 switch (*s++) {
110 case 'f':
111 fprintf(f, "%g", p[0].f);
112 break;
113 default:
114 fprintf(f, "%d", p[0].i);
115 break;
116 }
117 p++;
118 } else {
119 fputc(*s, f);
120 s++;
121 }
122 }
123 fprintf(f, "\n");
124 }
125
126
gl_compile_op(GLContext * c,GLParam * p)127 void gl_compile_op(GLContext *c, GLParam *p) {
128 int op, op_size;
129 GLParamBuffer *ob, *ob1;
130 int index;
131
132 op = p[0].op;
133 op_size = op_table_size[op];
134 index = c->current_op_buffer_index;
135 ob = c->current_op_buffer;
136
137 // we should be able to add a NextBuffer opcode
138 if ((index + op_size) > (OP_BUFFER_MAX_SIZE - 2)) {
139
140 ob1 = (GLParamBuffer *)gl_zalloc(sizeof(GLParamBuffer));
141 ob1->next = NULL;
142
143 ob->next = ob1;
144 ob->ops[index].op = OP_NextBuffer;
145 ob->ops[index + 1].p = (void *)ob1;
146
147 c->current_op_buffer = ob1;
148 ob = ob1;
149 index = 0;
150 }
151
152 for (int i = 0; i < op_size; i++) {
153 ob->ops[index] = p[i];
154 index++;
155 }
156 c->current_op_buffer_index = index;
157 }
158
gl_add_op(GLParam * p)159 void gl_add_op(GLParam *p) {
160 GLContext *c = gl_get_context();
161 int op;
162
163 op = p[0].op;
164 if (c->exec_flag) {
165 op_table_func[op](c, p);
166 }
167 if (c->compile_flag) {
168 gl_compile_op(c, p);
169 }
170 if (c->print_flag) {
171 gl_print_op(stderr, p);
172 }
173 }
174
175 // this opcode is never called directly
glopEndList(GLContext *,GLParam *)176 void glopEndList(GLContext *, GLParam *) {
177 assert(0);
178 }
179
180 // this opcode is never called directly
glopNextBuffer(GLContext *,GLParam *)181 void glopNextBuffer(GLContext *, GLParam *) {
182 assert(0);
183 }
184
glopCallList(GLContext * c,GLParam * p)185 void glopCallList(GLContext *c, GLParam *p) {
186 GLList *l;
187 int list, op;
188
189 list = p[1].ui;
190 l = find_list(c, list);
191 if (!l)
192 error("list %d not defined", list);
193 p = l->first_op_buffer->ops;
194
195 while (1) {
196 op = p[0].op;
197 if (op == OP_EndList)
198 break;
199 if (op == OP_NextBuffer) {
200 p = (GLParam *)p[1].p;
201 } else {
202 op_table_func[op](c, p);
203 p += op_table_size[op];
204 }
205 }
206 }
207
glNewList(unsigned int list,int mode)208 void glNewList(unsigned int list, int mode) {
209 GLList *l;
210 GLContext *c = gl_get_context();
211
212 assert(mode == TGL_COMPILE || mode == TGL_COMPILE_AND_EXECUTE);
213 assert(c->compile_flag == 0);
214
215 l = find_list(c, list);
216 if (l)
217 delete_list(c, list);
218 l = alloc_list(c, list);
219
220 c->current_op_buffer = l->first_op_buffer;
221 c->current_op_buffer_index = 0;
222
223 c->compile_flag = 1;
224 c->exec_flag = (mode == TGL_COMPILE_AND_EXECUTE);
225 }
226
glEndList()227 void glEndList() {
228 GLContext *c = gl_get_context();
229 GLParam p[1];
230
231 assert(c->compile_flag == 1);
232
233 // end of list
234 p[0].op = OP_EndList;
235 gl_compile_op(c, p);
236
237 c->compile_flag = 0;
238 c->exec_flag = 1;
239 }
240
glIsList(unsigned int list)241 int glIsList(unsigned int list) {
242 GLContext *c = gl_get_context();
243 GLList *l = find_list(c, list);
244
245 return (l != NULL);
246 }
247
glGenLists(int range)248 unsigned int glGenLists(int range) {
249 GLContext *c = gl_get_context();
250 int count, list;
251 GLList **lists;
252
253 lists = c->shared_state.lists;
254 count = 0;
255 for (int i = 0; i < MAX_DISPLAY_LISTS; i++) {
256 if (!lists[i]) {
257 count++;
258 if (count == range) {
259 list = i - range + 1;
260 for (int j = 0; j < range; j++) {
261 alloc_list(c, list + j);
262 }
263 return list;
264 }
265 } else {
266 count = 0;
267 }
268 }
269 return 0;
270 }
271
272 } // end of namespace TinyGL
273