]> icculus.org git repositories - taylor/freespace2.git/blob - src/graphics/grgl2.cpp
rendering functions mostly done; more complete shader setup
[taylor/freespace2.git] / src / graphics / grgl2.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on
6  * the source.
7  */
8
9 #include "SDL_opengles2.h"
10
11 #include "gropengl.h"
12 #include "gropenglinternal.h"
13 #include "grgl2.h"
14 #include "2d.h"
15 #include "mouse.h"
16 #include "pstypes.h"
17 #include "cfile.h"
18 #include "bmpman.h"
19 #include "grinternal.h"
20 #include "osapi.h"
21 #include "osregistry.h"
22
23
24 int GL_two_inited = 0;
25
26 bool Use_mipmaps = false;
27
28
29 static gr_alpha_blend GL_current_alpha_blend = (gr_alpha_blend) -1;
30 static gr_zbuffer_type GL_current_zbuffer_type = (gr_zbuffer_type) -1;
31
32 void opengl2_set_state(gr_texture_source ts, gr_alpha_blend ab, gr_zbuffer_type zt)
33 {
34         opengl2_set_texture_state(ts);
35
36         if (ab != GL_current_alpha_blend) {
37                 switch (ab) {
38                         case ALPHA_BLEND_NONE:                  // 1*SrcPixel + 0*DestPixel
39                                 glBlendFunc(GL_ONE, GL_ZERO);
40                                 break;
41                         case ALPHA_BLEND_ADDITIVE:              // 1*SrcPixel + 1*DestPixel
42                                 glBlendFunc(GL_ONE, GL_ONE);
43                                 break;
44                         case ALPHA_BLEND_ALPHA_ADDITIVE:        // Alpha*SrcPixel + 1*DestPixel
45                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
46                                 break;
47                         case ALPHA_BLEND_ALPHA_BLEND_ALPHA:     // Alpha*SrcPixel + (1-Alpha)*DestPixel
48                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
49                                 break;
50                         case ALPHA_BLEND_ALPHA_BLEND_SRC_COLOR: // Alpha*SrcPixel + (1-SrcPixel)*DestPixel
51                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_COLOR);
52                                 break;
53                         default:
54                                 break;
55                 }
56
57                 GL_current_alpha_blend = ab;
58         }
59
60         if (zt != GL_current_zbuffer_type) {
61                 switch (zt) {
62                         case ZBUFFER_TYPE_NONE:
63                                 glDepthFunc(GL_ALWAYS);
64                                 glDepthMask(GL_FALSE);
65                                 break;
66                         case ZBUFFER_TYPE_READ:
67                                 glDepthFunc(GL_LESS);
68                                 glDepthMask(GL_FALSE);
69                                 break;
70                         case ZBUFFER_TYPE_WRITE:
71                                 glDepthFunc(GL_ALWAYS);
72                                 glDepthMask(GL_TRUE);
73                                 break;
74                         case ZBUFFER_TYPE_FULL:
75                                 glDepthFunc(GL_LESS);
76                                 glDepthMask(GL_TRUE);
77                                 break;
78                         default:
79                                 break;
80                 }
81
82                 GL_current_zbuffer_type = zt;
83         }
84 }
85
86 void opengl2_cleanup()
87 {
88         if ( !GL_two_inited ) {
89                 return;
90         }
91
92         opengl2_tcache_cleanup();
93         opengl2_shader_cleanup();
94
95         GL_two_inited = 0;
96 }
97
98 static void opengl2_init_func_pointers()
99 {
100         gr_screen.gf_flip = gr_opengl2_flip;
101         gr_screen.gf_set_clip = gr_opengl2_set_clip;
102         gr_screen.gf_reset_clip = gr_opengl_reset_clip;
103
104         gr_screen.gf_clear = gr_opengl_clear;
105
106         gr_screen.gf_aabitmap = gr_opengl2_aabitmap;
107         gr_screen.gf_aabitmap_ex = gr_opengl2_aabitmap_ex;
108
109         gr_screen.gf_rect = gr_opengl2_rect;
110         gr_screen.gf_shade = gr_opengl2_shade;
111         gr_screen.gf_string = gr_opengl2_string;
112         gr_screen.gf_circle = gr_opengl2_circle;
113
114         gr_screen.gf_line = gr_opengl2_line;
115         gr_screen.gf_aaline = gr_opengl2_aaline;
116         gr_screen.gf_pixel = gr_opengl2_pixel;
117         gr_screen.gf_scaler = gr_opengl2_scaler;
118         gr_screen.gf_tmapper = gr_opengl2_tmapper;
119
120         gr_screen.gf_gradient = gr_opengl2_gradient;
121
122         gr_screen.gf_print_screen = gr_opengl_print_screen;
123
124         gr_screen.gf_fade_in = gr_opengl2_fade_in;
125         gr_screen.gf_fade_out = gr_opengl2_fade_out;
126         gr_screen.gf_flash = gr_opengl2_flash;
127
128         gr_screen.gf_zbuffer_clear = gr_opengl2_zbuffer_clear;
129
130         gr_screen.gf_save_screen = gr_opengl2_save_screen;
131         gr_screen.gf_restore_screen = gr_opengl2_restore_screen;
132         gr_screen.gf_free_screen = gr_opengl2_free_screen;
133
134         gr_screen.gf_dump_frame_start = gr_opengl2_dump_frame_start;
135         gr_screen.gf_dump_frame_stop = gr_opengl2_dump_frame_stop;
136         gr_screen.gf_dump_frame = gr_opengl2_dump_frame;
137
138         gr_screen.gf_set_gamma = gr_opengl2_set_gamma;
139
140         gr_screen.gf_lock = gr_opengl_lock;
141         gr_screen.gf_unlock = gr_opengl_unlock;
142
143         gr_screen.gf_fog_set = gr_opengl2_fog_set;
144
145         gr_screen.gf_get_region = gr_opengl2_get_region;
146
147         gr_screen.gf_set_cull = gr_opengl_set_cull;
148
149         gr_screen.gf_cross_fade = gr_opengl2_cross_fade;
150
151         gr_screen.gf_preload_init = gr_opengl2_preload_init;
152         gr_screen.gf_preload = gr_opengl2_preload;
153
154         gr_screen.gf_zbias = gr_opengl_zbias;
155
156         gr_screen.gf_force_windowed = gr_opengl_force_windowed;
157         gr_screen.gf_force_fullscreen = gr_opengl_force_fullscreen;
158         gr_screen.gf_toggle_fullscreen = gr_opengl_toggle_fullscreen;
159
160         gr_screen.gf_set_viewport = gr_opengl2_set_viewport;
161
162         gr_screen.gf_activate = gr_opengl_activate;
163
164         gr_screen.gf_release_texture = gr_opengl2_release_texture;
165 }
166
167 int opengl2_init()
168 {
169         if (GL_two_inited) {
170                 return 1;
171         }
172
173         SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
174         SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
175         SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
176
177         GL_context = SDL_GL_CreateContext(GL_window);
178
179         if ( !GL_context ) {
180                 return 0;
181         }
182
183         mprintf(("  Vendor   : %s\n", glGetString(GL_VENDOR)));
184         mprintf(("  Renderer : %s\n", glGetString(GL_RENDERER)));
185         mprintf(("  Version  : %s\n", glGetString(GL_VERSION)));
186
187         // set up generic variables
188         opengl_set_variables();
189
190         opengl2_init_func_pointers();
191         opengl2_tcache_init();
192         opengl2_shader_init();
193
194         // initial viewport setup
195         gr_opengl2_set_viewport(gr_screen.max_w, gr_screen.max_h);
196
197         glEnable(GL_DITHER);
198         glEnable(GL_DEPTH_TEST);
199         glEnable(GL_BLEND);
200
201         glDepthRangef(0.0f, 1.0f);
202
203         glPixelStorei(GL_PACK_ALIGNMENT, 1);
204         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
205
206         if ( SDL_GL_ExtensionSupported("GL_OES_texture_npot") ) {
207                 Use_mipmaps     = true;
208         }
209
210         mprintf(("  Mipmaps  : %s\n", Use_mipmaps ? "Enabled" : "Disabled"));
211
212         glFlush();
213
214         gr_opengl_clear();
215         gr_opengl_set_cull(1);
216
217         GL_two_inited = 1;
218
219         return 1;
220 }
221
222 void gr_opengl2_flip()
223 {
224         if ( !GL_two_inited ) {
225                 return;
226         }
227
228         gr_opengl_reset_clip();
229
230         mouse_eval_deltas();
231
232         if ( mouse_is_visible() ) {
233                 int mx, my;
234
235                 mouse_get_pos(&mx, &my);
236
237                 if (Gr_cursor == -1) {
238 #ifndef NDEBUG
239                         gr_set_color(255, 255, 255);
240                         gr_opengl2_line(mx, my, mx+7, my+7);
241                         gr_opengl2_line(mx, my, mx+5, my);
242                         gr_opengl2_line(mx, my, mx, my+5);
243 #endif
244                 } else {
245                         gr_set_bitmap(Gr_cursor);
246                         gr_bitmap(mx, my);
247                 }
248         }
249
250 #ifndef NDEBUG
251         GLenum error = GL_NO_ERROR;
252
253         do {
254                 error = glGetError();
255
256                 if (error != GL_NO_ERROR) {
257                         nprintf(("Warning", "!!DEBUG!! OpenGL Error: %d\n", error));
258                 }
259         } while (error != GL_NO_ERROR);
260 #endif
261
262         SDL_GL_SwapWindow(GL_window);
263
264         opengl2_tcache_frame();
265 }
266
267 void gr_opengl2_set_clip(int x, int y, int w, int h)
268 {
269         // check for sanity of parameters
270         CAP(x, 0, gr_screen.max_w - 1);
271         CAP(y, 0, gr_screen.max_h - 1);
272         CAP(w, 0, gr_screen.max_w - x);
273         CAP(h, 0, gr_screen.max_h - y);
274
275         gr_screen.offset_x = x;
276         gr_screen.offset_y = y;
277         gr_screen.clip_left = 0;
278         gr_screen.clip_right = w-1;
279         gr_screen.clip_top = 0;
280         gr_screen.clip_bottom = h-1;
281         gr_screen.clip_width = w;
282         gr_screen.clip_height = h;
283
284         glEnable(GL_SCISSOR_TEST);
285         glScissor(x, GL_viewport_h-y-h, w, h);
286 }
287
288 void gr_opengl2_fog_set(int fog_mode, int r, int g, int b, float fog_near, float fog_far)
289 {
290         gr_screen.current_fog_mode = fog_mode;
291
292         if (fog_mode == GR_FOGMODE_NONE) {
293                 return;
294         }
295
296         gr_screen.fog_near = fog_near;
297         gr_screen.fog_far = fog_far;
298
299         gr_init_color(&gr_screen.current_fog_color, r, g, b);
300 }
301
302 void gr_opengl2_zbuffer_clear(int mode)
303 {
304         if (mode) {
305                 Gr_zbuffering = 1;
306                 Gr_zbuffering_mode = GR_ZBUFF_FULL;
307                 Gr_global_zbuffering = 1;
308
309                 opengl2_set_state(TEXTURE_SOURCE_NONE, ALPHA_BLEND_NONE, ZBUFFER_TYPE_FULL);
310                 glClear(GL_DEPTH_BUFFER_BIT);
311         } else {
312                 Gr_zbuffering = 0;
313                 Gr_zbuffering_mode = GR_ZBUFF_NONE;
314                 Gr_global_zbuffering = 0;
315         }
316 }
317
318 void gr_opengl2_fade_in(int instantaneous)
319 {
320
321 }
322
323 void gr_opengl2_fade_out(int instantaneous)
324 {
325
326 }
327
328 void gr_opengl2_get_region(int front, int w, int h, ubyte *data)
329 {
330         opengl2_set_state(TEXTURE_SOURCE_NO_FILTERING, ALPHA_BLEND_NONE, ZBUFFER_TYPE_NONE);
331
332         int x = GL_viewport_x;
333         int y = (GL_viewport_y+GL_viewport_h)-h-1;
334
335         GLenum pxtype = GL_UNSIGNED_SHORT_5_5_5_1;
336
337         if (gr_screen.bytes_per_pixel == 4) {
338                 pxtype = GL_UNSIGNED_BYTE;
339         }
340
341         glReadPixels(x, y, w, h, GL_RGBA, pxtype, data);
342 }
343
344 int gr_opengl2_save_screen()
345 {
346         return -1;
347 }
348
349 void gr_opengl2_restore_screen(int)
350 {
351
352 }
353
354 void gr_opengl2_free_screen(int)
355 {
356
357 }
358
359 void gr_opengl2_dump_frame_start(int first_frame, int frames_between_dumps)
360 {
361
362 }
363
364 void gr_opengl2_dump_frame_stop()
365 {
366
367 }
368
369 void gr_opengl2_dump_frame()
370 {
371
372 }
373
374 void gr_opengl2_set_viewport(int width, int height)
375 {
376         int w, h, x, y;
377
378         float ratio = gr_screen.max_w / i2fl(gr_screen.max_h);
379
380         w = width;
381         h = fl2i((width / ratio) + 0.5f);
382
383         if (h > height) {
384                 h = height;
385                 w = fl2i((height * ratio) + 0.5f);
386         }
387
388         x = (width - w) / 2;
389         y = (height - h) / 2;
390
391         GL_viewport_x = x;
392         GL_viewport_y = y;
393         GL_viewport_w = w;
394         GL_viewport_h = h;
395         GL_viewport_scale_w = w / i2fl(gr_screen.max_w);
396         GL_viewport_scale_h = h / i2fl(gr_screen.max_h);
397
398         glViewport(GL_viewport_x, GL_viewport_y, GL_viewport_w, GL_viewport_h);
399
400         // clear screen once to fix issues with edges on non-4:3
401         gr_opengl_clear();
402 }