1#![allow(unused_variables)]
2use std::{
3 rc::Rc,
4 hash::{Hasher, Hash},
5 ffi::c_void,
6 marker::PhantomData,
7 os::raw::c_int,
8};
9use gleam::gl::{self, Gl, GlType, DebugMessage, types::*};
10use crate::{
11 FastHashMap,
12 window::LogicalSize,
13 app_resources::{Epoch, ExternalImageId},
14 callbacks::PipelineId,
15};
16use azul_css::{ColorU, ColorF};
17
18pub type GLuint = u32;
20pub type GLint = i32;
21
22pub(crate) type GlTextureStorage = FastHashMap<Epoch, FastHashMap<ExternalImageId, Texture>>;
25
26static mut ACTIVE_GL_TEXTURES: Option<FastHashMap<PipelineId, GlTextureStorage>> = None;
42
43pub fn insert_into_active_gl_textures(pipeline_id: PipelineId, epoch: Epoch, texture: Texture) -> ExternalImageId {
48
49 let external_image_id = ExternalImageId::new();
50
51 unsafe {
52 if ACTIVE_GL_TEXTURES.is_none() {
53 ACTIVE_GL_TEXTURES = Some(FastHashMap::new());
54 }
55 let active_textures = ACTIVE_GL_TEXTURES.as_mut().unwrap();
56 let active_epochs = active_textures.entry(pipeline_id).or_insert_with(|| FastHashMap::new());
57 let active_textures_for_epoch = active_epochs.entry(epoch).or_insert_with(|| FastHashMap::new());
58 active_textures_for_epoch.insert(external_image_id, texture);
59 }
60
61 external_image_id
62}
63
64pub fn get_opengl_texture(image_key: &ExternalImageId) -> Option<(GLuint, (f32, f32))> {
75 let active_textures = unsafe { ACTIVE_GL_TEXTURES.as_ref()? };
76 active_textures.values()
77 .flat_map(|active_pipeline| active_pipeline.values())
78 .find_map(|active_epoch| active_epoch.get(image_key))
79 .map(|tex| (tex.texture_id, (tex.size.width as f32, tex.size.height as f32)))
80}
81
82pub fn gl_textures_remove_active_pipeline(pipeline_id: &PipelineId) {
83 unsafe {
84 let active_textures = match ACTIVE_GL_TEXTURES.as_mut() {
85 Some(s) => s,
86 None => return,
87 };
88 active_textures.remove(pipeline_id);
89 }
90}
91
92pub fn gl_textures_remove_epochs_from_pipeline(pipeline_id: &PipelineId, epoch: Epoch) {
95 unsafe {
97 let active_textures = match ACTIVE_GL_TEXTURES.as_mut() {
98 Some(s) => s,
99 None => return,
100 };
101 let active_epochs = match active_textures.get_mut(pipeline_id) {
102 Some(s) => s,
103 None => return,
104 };
105 active_epochs.retain(|gl_texture_epoch, _| *gl_texture_epoch > epoch);
106 }
107}
108
109pub fn gl_textures_clear_opengl_cache() {
111 unsafe { ACTIVE_GL_TEXTURES = None; }
112}
113
114
115pub struct VirtualGlDriver {
122 }
126
127impl VirtualGlDriver {
128 pub fn new() -> Self {
129 Self { }
130 }
131}
132
133impl Gl for VirtualGlDriver {
134 fn get_type(&self) -> GlType {
135 unimplemented()
136 }
137
138 fn buffer_data_untyped(&self, target: GLenum, size: GLsizeiptr, data: *const GLvoid, usage: GLenum) {
139 unimplemented()
140 }
141
142 fn buffer_sub_data_untyped(&self, target: GLenum, offset: isize, size: GLsizeiptr, data: *const GLvoid) {
143 unimplemented()
144 }
145
146 fn map_buffer(&self, target: GLenum, access: GLbitfield) -> *mut c_void {
147 unimplemented()
148 }
149
150 fn map_buffer_range(&self, target: GLenum, offset: GLintptr, length: GLsizeiptr, access: GLbitfield) -> *mut c_void {
151 unimplemented()
152 }
153
154 fn unmap_buffer(&self, target: GLenum) -> GLboolean {
155 unimplemented()
156 }
157
158 fn tex_buffer(&self, target: GLenum, internal_format: GLenum, buffer: GLuint) {
159 unimplemented()
160 }
161
162 fn shader_source(&self, shader: GLuint, strings: &[&[u8]]) {
163 unimplemented()
164 }
165
166 fn read_buffer(&self, mode: GLenum) {
167 unimplemented()
168 }
169
170 fn read_pixels_into_buffer(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei, format: GLenum, pixel_type: GLenum, dst_buffer: &mut [u8]) {
171 unimplemented()
172 }
173
174 fn read_pixels(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei, format: GLenum, pixel_type: GLenum) -> Vec<u8> {
175 unimplemented()
176 }
177
178 unsafe fn read_pixels_into_pbo(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei, format: GLenum, pixel_type: GLenum) {
179 unimplemented()
180 }
181
182 fn sample_coverage(&self, value: GLclampf, invert: bool) {
183 unimplemented()
184 }
185
186 fn polygon_offset(&self, factor: GLfloat, units: GLfloat) {
187 unimplemented()
188 }
189
190 fn pixel_store_i(&self, name: GLenum, param: GLint) {
191 unimplemented()
192 }
193
194 fn gen_buffers(&self, n: GLsizei) -> Vec<GLuint> {
195 unimplemented()
196 }
197
198 fn gen_renderbuffers(&self, n: GLsizei) -> Vec<GLuint> {
199 unimplemented()
200 }
201
202 fn gen_framebuffers(&self, n: GLsizei) -> Vec<GLuint> {
203 unimplemented()
204 }
205
206 fn gen_textures(&self, n: GLsizei) -> Vec<GLuint> {
207 unimplemented()
208 }
209
210 fn gen_vertex_arrays(&self, n: GLsizei) -> Vec<GLuint> {
211 unimplemented()
212 }
213
214 fn gen_queries(&self, n: GLsizei) -> Vec<GLuint> {
215 unimplemented()
216 }
217
218 fn begin_query(&self, target: GLenum, id: GLuint) {
219 unimplemented()
220 }
221
222 fn end_query(&self, target: GLenum) {
223 unimplemented()
224 }
225
226 fn query_counter(&self, id: GLuint, target: GLenum) {
227 unimplemented()
228 }
229
230 fn get_query_object_iv(&self, id: GLuint, pname: GLenum) -> i32 {
231 unimplemented()
232 }
233
234 fn get_query_object_uiv(&self, id: GLuint, pname: GLenum) -> u32 {
235 unimplemented()
236 }
237
238 fn get_query_object_i64v(&self, id: GLuint, pname: GLenum) -> i64 {
239 unimplemented()
240 }
241
242 fn get_query_object_ui64v(&self, id: GLuint, pname: GLenum) -> u64 {
243 unimplemented()
244 }
245
246 fn delete_queries(&self, queries: &[GLuint]) {
247 unimplemented()
248 }
249
250 fn delete_vertex_arrays(&self, vertex_arrays: &[GLuint]) {
251 unimplemented()
252 }
253
254 fn delete_buffers(&self, buffers: &[GLuint]) {
255 unimplemented()
256 }
257
258 fn delete_renderbuffers(&self, renderbuffers: &[GLuint]) {
259 unimplemented()
260 }
261
262 fn delete_framebuffers(&self, framebuffers: &[GLuint]) {
263 unimplemented()
264 }
265
266 fn delete_textures(&self, textures: &[GLuint]) {
267 unimplemented()
268 }
269
270 fn framebuffer_renderbuffer(&self, target: GLenum, attachment: GLenum, renderbuffertarget: GLenum, renderbuffer: GLuint) {
271 unimplemented()
272 }
273
274 fn renderbuffer_storage(&self, target: GLenum, internalformat: GLenum, width: GLsizei, height: GLsizei) {
275 unimplemented()
276 }
277
278 fn depth_func(&self, func: GLenum) {
279 unimplemented()
280 }
281
282 fn active_texture(&self, texture: GLenum) {
283 unimplemented()
284 }
285
286 fn attach_shader(&self, program: GLuint, shader: GLuint) {
287 unimplemented()
288 }
289
290 fn bind_attrib_location(&self, program: GLuint, index: GLuint, name: &str) {
291 unimplemented()
292 }
293
294 unsafe fn get_uniform_iv(&self, program: GLuint, location: GLint, result: &mut [GLint]) {
295 unimplemented()
296 }
297
298 unsafe fn get_uniform_fv(&self, program: GLuint, location: GLint, result: &mut [GLfloat]) {
299 unimplemented()
300 }
301
302 fn get_uniform_block_index(&self, program: GLuint, name: &str) -> GLuint {
303 unimplemented()
304 }
305
306 fn get_uniform_indices(&self, program: GLuint, names: &[&str]) -> Vec<GLuint> {
307 unimplemented()
308 }
309
310 fn bind_buffer_base(&self, target: GLenum, index: GLuint, buffer: GLuint) {
311 unimplemented()
312 }
313
314 fn bind_buffer_range(&self, target: GLenum, index: GLuint, buffer: GLuint, offset: GLintptr, size: GLsizeiptr) {
315 unimplemented()
316 }
317
318 fn uniform_block_binding(&self, program: GLuint, uniform_block_index: GLuint, uniform_block_binding: GLuint) {
319 unimplemented()
320 }
321
322 fn bind_buffer(&self, target: GLenum, buffer: GLuint) {
323 unimplemented()
324 }
325
326 fn bind_vertex_array(&self, vao: GLuint) {
327 unimplemented()
328 }
329
330 fn bind_renderbuffer(&self, target: GLenum, renderbuffer: GLuint) {
331 unimplemented()
332 }
333
334 fn bind_framebuffer(&self, target: GLenum, framebuffer: GLuint) {
335 unimplemented()
336 }
337
338 fn bind_texture(&self, target: GLenum, texture: GLuint) {
339 unimplemented()
340 }
341
342 fn draw_buffers(&self, bufs: &[GLenum]) {
343 unimplemented()
344 }
345
346 fn tex_image_2d(&self, target: GLenum, level: GLint, internal_format: GLint, width: GLsizei, height: GLsizei, border: GLint, format: GLenum, ty: GLenum, opt_data: Option<&[u8]>) {
347 unimplemented()
348 }
349
350 fn compressed_tex_image_2d(&self, target: GLenum, level: GLint, internal_format: GLenum, width: GLsizei, height: GLsizei, border: GLint, data: &[u8]) {
351 unimplemented()
352 }
353
354 fn compressed_tex_sub_image_2d(&self, target: GLenum, level: GLint, xoffset: GLint, yoffset: GLint, width: GLsizei, height: GLsizei, format: GLenum, data: &[u8]) {
355 unimplemented()
356 }
357
358 fn tex_image_3d(&self, target: GLenum, level: GLint, internal_format: GLint, width: GLsizei, height: GLsizei, depth: GLsizei, border: GLint, format: GLenum, ty: GLenum, opt_data: Option<&[u8]>) {
359 unimplemented()
360 }
361
362 fn copy_tex_image_2d(&self, target: GLenum, level: GLint, internal_format: GLenum, x: GLint, y: GLint, width: GLsizei, height: GLsizei, border: GLint) {
363 unimplemented()
364 }
365
366 fn copy_tex_sub_image_2d(&self, target: GLenum, level: GLint, xoffset: GLint, yoffset: GLint, x: GLint, y: GLint, width: GLsizei, height: GLsizei) {
367 unimplemented()
368 }
369
370 fn copy_tex_sub_image_3d(&self, target: GLenum, level: GLint, xoffset: GLint, yoffset: GLint, zoffset: GLint, x: GLint, y: GLint, width: GLsizei, height: GLsizei) {
371 unimplemented()
372 }
373
374 fn tex_sub_image_2d(&self, target: GLenum, level: GLint, xoffset: GLint, yoffset: GLint, width: GLsizei, height: GLsizei, format: GLenum, ty: GLenum, data: &[u8]) {
375 unimplemented()
376 }
377
378 fn tex_sub_image_2d_pbo(&self, target: GLenum, level: GLint, xoffset: GLint, yoffset: GLint, width: GLsizei, height: GLsizei, format: GLenum, ty: GLenum, offset: usize) {
379 unimplemented()
380 }
381
382 fn tex_sub_image_3d(&self, target: GLenum, level: GLint, xoffset: GLint, yoffset: GLint, zoffset: GLint, width: GLsizei, height: GLsizei, depth: GLsizei, format: GLenum, ty: GLenum, data: &[u8]) {
383 unimplemented()
384 }
385
386 fn tex_sub_image_3d_pbo(&self, target: GLenum, level: GLint, xoffset: GLint, yoffset: GLint, zoffset: GLint, width: GLsizei, height: GLsizei, depth: GLsizei, format: GLenum, ty: GLenum, offset: usize) {
387 unimplemented()
388 }
389
390 fn tex_storage_2d(&self, target: GLenum, levels: GLint, internal_format: GLenum, width: GLsizei, height: GLsizei) {
391 unimplemented()
392 }
393
394 fn tex_storage_3d(&self, target: GLenum, levels: GLint, internal_format: GLenum, width: GLsizei, height: GLsizei, depth: GLsizei) {
395 unimplemented()
396 }
397
398 fn get_tex_image_into_buffer(&self, target: GLenum, level: GLint, format: GLenum, ty: GLenum, output: &mut [u8]) {
399 unimplemented()
400 }
401
402 unsafe fn copy_image_sub_data(&self, src_name: GLuint, src_target: GLenum, src_level: GLint, src_x: GLint, src_y: GLint, src_z: GLint, dst_name: GLuint, dst_target: GLenum, dst_level: GLint, dst_x: GLint, dst_y: GLint, dst_z: GLint, src_width: GLsizei, src_height: GLsizei, src_depth: GLsizei) {
403 unimplemented()
404 }
405
406 fn invalidate_framebuffer(&self, target: GLenum, attachments: &[GLenum]) {
407 unimplemented()
408 }
409
410 fn invalidate_sub_framebuffer(&self, target: GLenum, attachments: &[GLenum], xoffset: GLint, yoffset: GLint, width: GLsizei, height: GLsizei) {
411 unimplemented()
412 }
413
414 unsafe fn get_integer_v(&self, name: GLenum, result: &mut [GLint]) {
415 unimplemented()
416 }
417
418 unsafe fn get_integer_64v(&self, name: GLenum, result: &mut [GLint64]) {
419 unimplemented()
420 }
421
422 unsafe fn get_integer_iv(&self, name: GLenum, index: GLuint, result: &mut [GLint]) {
423 unimplemented()
424 }
425
426 unsafe fn get_integer_64iv(&self, name: GLenum, index: GLuint, result: &mut [GLint64]) {
427 unimplemented()
428 }
429
430 unsafe fn get_boolean_v(&self, name: GLenum, result: &mut [GLboolean]) {
431 unimplemented()
432 }
433
434 unsafe fn get_float_v(&self, name: GLenum, result: &mut [GLfloat]) {
435 unimplemented()
436 }
437
438 fn get_framebuffer_attachment_parameter_iv(&self, target: GLenum, attachment: GLenum, pname: GLenum) -> GLint {
439 unimplemented()
440 }
441
442 fn get_renderbuffer_parameter_iv(&self, target: GLenum, pname: GLenum) -> GLint {
443 unimplemented()
444 }
445
446 fn get_tex_parameter_iv(&self, target: GLenum, name: GLenum) -> GLint {
447 unimplemented()
448 }
449
450 fn get_tex_parameter_fv(&self, target: GLenum, name: GLenum) -> GLfloat {
451 unimplemented()
452 }
453
454 fn tex_parameter_i(&self, target: GLenum, pname: GLenum, param: GLint) {
455 unimplemented()
456 }
457
458 fn tex_parameter_f(&self, target: GLenum, pname: GLenum, param: GLfloat) {
459 unimplemented()
460 }
461
462 fn framebuffer_texture_2d(&self, target: GLenum, attachment: GLenum, textarget: GLenum, texture: GLuint, level: GLint) {
463 unimplemented()
464 }
465
466 fn framebuffer_texture_layer(&self, target: GLenum, attachment: GLenum, texture: GLuint, level: GLint, layer: GLint) {
467 unimplemented()
468 }
469
470 fn blit_framebuffer(&self, src_x0: GLint, src_y0: GLint, src_x1: GLint, src_y1: GLint, dst_x0: GLint, dst_y0: GLint, dst_x1: GLint, dst_y1: GLint, mask: GLbitfield, filter: GLenum) {
471 unimplemented()
472 }
473
474 fn vertex_attrib_4f(&self, index: GLuint, x: GLfloat, y: GLfloat, z: GLfloat, w: GLfloat) {
475 unimplemented()
476 }
477
478 fn vertex_attrib_pointer_f32(&self, index: GLuint, size: GLint, normalized: bool, stride: GLsizei, offset: GLuint) {
479 unimplemented()
480 }
481
482 fn vertex_attrib_pointer(&self, index: GLuint, size: GLint, type_: GLenum, normalized: bool, stride: GLsizei, offset: GLuint) {
483 unimplemented()
484 }
485
486 fn vertex_attrib_i_pointer(&self, index: GLuint, size: GLint, type_: GLenum, stride: GLsizei, offset: GLuint) {
487 unimplemented()
488 }
489
490 fn vertex_attrib_divisor(&self, index: GLuint, divisor: GLuint) {
491 unimplemented()
492 }
493
494 fn viewport(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei) {
495 unimplemented()
496 }
497
498 fn scissor(&self, x: GLint, y: GLint, width: GLsizei, height: GLsizei) {
499 unimplemented()
500 }
501
502 fn line_width(&self, width: GLfloat) {
503 unimplemented()
504 }
505
506 fn use_program(&self, program: GLuint) {
507 unimplemented()
508 }
509
510 fn validate_program(&self, program: GLuint) {
511 unimplemented()
512 }
513
514 fn draw_arrays(&self, mode: GLenum, first: GLint, count: GLsizei) {
515 unimplemented()
516 }
517
518 fn draw_arrays_instanced(&self, mode: GLenum, first: GLint, count: GLsizei, primcount: GLsizei) {
519 unimplemented()
520 }
521
522 fn draw_elements(&self, mode: GLenum, count: GLsizei, element_type: GLenum, indices_offset: GLuint) {
523 unimplemented()
524 }
525
526 fn draw_elements_instanced(&self, mode: GLenum, count: GLsizei, element_type: GLenum, indices_offset: GLuint, primcount: GLsizei) {
527 unimplemented()
528 }
529
530 fn blend_color(&self, r: f32, g: f32, b: f32, a: f32) {
531 unimplemented()
532 }
533
534 fn blend_func(&self, sfactor: GLenum, dfactor: GLenum) {
535 unimplemented()
536 }
537
538 fn blend_func_separate(&self, src_rgb: GLenum, dest_rgb: GLenum, src_alpha: GLenum, dest_alpha: GLenum) {
539 unimplemented()
540 }
541
542 fn blend_equation(&self, mode: GLenum) {
543 unimplemented()
544 }
545
546 fn blend_equation_separate(&self, mode_rgb: GLenum, mode_alpha: GLenum) {
547 unimplemented()
548 }
549
550 fn color_mask(&self, r: bool, g: bool, b: bool, a: bool) {
551 unimplemented()
552 }
553
554 fn cull_face(&self, mode: GLenum) {
555 unimplemented()
556 }
557
558 fn front_face(&self, mode: GLenum) {
559 unimplemented()
560 }
561
562 fn enable(&self, cap: GLenum) {
563 unimplemented()
564 }
565
566 fn disable(&self, cap: GLenum) {
567 unimplemented()
568 }
569
570 fn hint(&self, param_name: GLenum, param_val: GLenum) {
571 unimplemented()
572 }
573
574 fn is_enabled(&self, cap: GLenum) -> GLboolean {
575 unimplemented()
576 }
577
578 fn is_shader(&self, shader: GLuint) -> GLboolean {
579 unimplemented()
580 }
581
582 fn is_texture(&self, texture: GLenum) -> GLboolean {
583 unimplemented()
584 }
585
586 fn is_framebuffer(&self, framebuffer: GLenum) -> GLboolean {
587 unimplemented()
588 }
589
590 fn is_renderbuffer(&self, renderbuffer: GLenum) -> GLboolean {
591 unimplemented()
592 }
593
594 fn check_frame_buffer_status(&self, target: GLenum) -> GLenum {
595 unimplemented()
596 }
597
598 fn enable_vertex_attrib_array(&self, index: GLuint) {
599 unimplemented()
600 }
601
602 fn disable_vertex_attrib_array(&self, index: GLuint) {
603 unimplemented()
604 }
605
606 fn uniform_1f(&self, location: GLint, v0: GLfloat) {
607 unimplemented()
608 }
609
610 fn uniform_1fv(&self, location: GLint, values: &[f32]) {
611 unimplemented()
612 }
613
614 fn uniform_1i(&self, location: GLint, v0: GLint) {
615 unimplemented()
616 }
617
618 fn uniform_1iv(&self, location: GLint, values: &[i32]) {
619 unimplemented()
620 }
621
622 fn uniform_1ui(&self, location: GLint, v0: GLuint) {
623 unimplemented()
624 }
625
626 fn uniform_2f(&self, location: GLint, v0: GLfloat, v1: GLfloat) {
627 unimplemented()
628 }
629
630 fn uniform_2fv(&self, location: GLint, values: &[f32]) {
631 unimplemented()
632 }
633
634 fn uniform_2i(&self, location: GLint, v0: GLint, v1: GLint) {
635 unimplemented()
636 }
637
638 fn uniform_2iv(&self, location: GLint, values: &[i32]) {
639 unimplemented()
640 }
641
642 fn uniform_2ui(&self, location: GLint, v0: GLuint, v1: GLuint) {
643 unimplemented()
644 }
645
646 fn uniform_3f(&self, location: GLint, v0: GLfloat, v1: GLfloat, v2: GLfloat) {
647 unimplemented()
648 }
649
650 fn uniform_3fv(&self, location: GLint, values: &[f32]) {
651 unimplemented()
652 }
653
654 fn uniform_3i(&self, location: GLint, v0: GLint, v1: GLint, v2: GLint) {
655 unimplemented()
656 }
657
658 fn uniform_3iv(&self, location: GLint, values: &[i32]) {
659 unimplemented()
660 }
661
662 fn uniform_3ui(&self, location: GLint, v0: GLuint, v1: GLuint, v2: GLuint) {
663 unimplemented()
664 }
665
666 fn uniform_4f(&self, location: GLint, x: GLfloat, y: GLfloat, z: GLfloat, w: GLfloat) {
667 unimplemented()
668 }
669
670 fn uniform_4i(&self, location: GLint, x: GLint, y: GLint, z: GLint, w: GLint) {
671 unimplemented()
672 }
673
674 fn uniform_4iv(&self, location: GLint, values: &[i32]) {
675 unimplemented()
676 }
677
678 fn uniform_4ui(&self, location: GLint, x: GLuint, y: GLuint, z: GLuint, w: GLuint) {
679 unimplemented()
680 }
681
682 fn uniform_4fv(&self, location: GLint, values: &[f32]) {
683 unimplemented()
684 }
685
686 fn uniform_matrix_2fv(&self, location: GLint, transpose: bool, value: &[f32]) {
687 unimplemented()
688 }
689
690 fn uniform_matrix_3fv(&self, location: GLint, transpose: bool, value: &[f32]) {
691 unimplemented()
692 }
693
694 fn uniform_matrix_4fv(&self, location: GLint, transpose: bool, value: &[f32]) {
695 unimplemented()
696 }
697
698 fn depth_mask(&self, flag: bool) {
699 unimplemented()
700 }
701
702 fn depth_range(&self, near: f64, far: f64) {
703 unimplemented()
704 }
705
706 fn get_active_attrib(&self, program: GLuint, index: GLuint) -> (i32, u32, String) {
707 unimplemented()
708 }
709
710 fn get_active_uniform(&self, program: GLuint, index: GLuint) -> (i32, u32, String) {
711 unimplemented()
712 }
713
714 fn get_active_uniforms_iv(&self, program: GLuint, indices: Vec<GLuint>, pname: GLenum) -> Vec<GLint> {
715 unimplemented()
716 }
717
718 fn get_active_uniform_block_i(&self, program: GLuint, index: GLuint, pname: GLenum) -> GLint {
719 unimplemented()
720 }
721
722 fn get_active_uniform_block_iv(&self, program: GLuint, index: GLuint, pname: GLenum) -> Vec<GLint> {
723 unimplemented()
724 }
725
726 fn get_active_uniform_block_name(&self, program: GLuint, index: GLuint) -> String {
727 unimplemented()
728 }
729
730 fn get_attrib_location(&self, program: GLuint, name: &str) -> c_int {
731 unimplemented()
732 }
733
734 fn get_frag_data_location(&self, program: GLuint, name: &str) -> c_int {
735 unimplemented()
736 }
737
738 fn get_uniform_location(&self, program: GLuint, name: &str) -> c_int {
739 unimplemented()
740 }
741
742 fn get_program_info_log(&self, program: GLuint) -> String {
743 unimplemented()
744 }
745
746 unsafe fn get_program_iv(&self, program: GLuint, pname: GLenum, result: &mut [GLint]) {
747 unimplemented()
748 }
749
750 fn get_program_binary(&self, program: GLuint) -> (Vec<u8>, GLenum) {
751 unimplemented()
752 }
753
754 fn program_binary(&self, program: GLuint, format: GLenum, binary: &[u8]) {
755 unimplemented()
756 }
757
758 fn program_parameter_i(&self, program: GLuint, pname: GLenum, value: GLint) {
759 unimplemented()
760 }
761
762 unsafe fn get_vertex_attrib_iv(&self, index: GLuint, pname: GLenum, result: &mut [GLint]) {
763 unimplemented()
764 }
765
766 unsafe fn get_vertex_attrib_fv(&self, index: GLuint, pname: GLenum, result: &mut [GLfloat]) {
767 unimplemented()
768 }
769
770 fn get_vertex_attrib_pointer_v(&self, index: GLuint, pname: GLenum) -> GLsizeiptr {
771 unimplemented()
772 }
773
774 fn get_buffer_parameter_iv(&self, target: GLuint, pname: GLenum) -> GLint {
775 unimplemented()
776 }
777
778 fn get_shader_info_log(&self, shader: GLuint) -> String {
779 unimplemented()
780 }
781
782 fn get_string(&self, which: GLenum) -> String {
783 unimplemented()
784 }
785
786 fn get_string_i(&self, which: GLenum, index: GLuint) -> String {
787 unimplemented()
788 }
789
790 unsafe fn get_shader_iv(&self, shader: GLuint, pname: GLenum, result: &mut [GLint]) {
791 unimplemented()
792 }
793
794 fn get_shader_precision_format(&self, shader_type: GLuint, precision_type: GLuint) -> (GLint, GLint, GLint) {
795 unimplemented()
796 }
797
798 fn compile_shader(&self, shader: GLuint) {
799 unimplemented()
800 }
801
802 fn create_program(&self) -> GLuint {
803 unimplemented()
804 }
805
806 fn delete_program(&self, program: GLuint) {
807 unimplemented()
808 }
809
810 fn create_shader(&self, shader_type: GLenum) -> GLuint {
811 unimplemented()
812 }
813
814 fn delete_shader(&self, shader: GLuint) {
815 unimplemented()
816 }
817
818 fn detach_shader(&self, program: GLuint, shader: GLuint) {
819 unimplemented()
820 }
821
822 fn link_program(&self, program: GLuint) {
823 unimplemented()
824 }
825
826 fn clear_color(&self, r: f32, g: f32, b: f32, a: f32) {
827 unimplemented()
828 }
829
830 fn clear(&self, buffer_mask: GLbitfield) {
831 unimplemented()
832 }
833
834 fn clear_depth(&self, depth: f64) {
835 unimplemented()
836 }
837
838 fn clear_stencil(&self, s: GLint) {
839 unimplemented()
840 }
841
842 fn flush(&self) {
843 unimplemented()
844 }
845
846 fn finish(&self) {
847 unimplemented()
848 }
849
850 fn get_error(&self) -> GLenum {
851 unimplemented()
852 }
853
854 fn stencil_mask(&self, mask: GLuint) {
855 unimplemented()
856 }
857
858 fn stencil_mask_separate(&self, face: GLenum, mask: GLuint) {
859 unimplemented()
860 }
861
862 fn stencil_func(&self, func: GLenum, ref_: GLint, mask: GLuint) {
863 unimplemented()
864 }
865
866 fn stencil_func_separate(&self, face: GLenum, func: GLenum, ref_: GLint, mask: GLuint) {
867 unimplemented()
868 }
869
870 fn stencil_op(&self, sfail: GLenum, dpfail: GLenum, dppass: GLenum) {
871 unimplemented()
872 }
873
874 fn stencil_op_separate(&self, face: GLenum, sfail: GLenum, dpfail: GLenum, dppass: GLenum) {
875 unimplemented()
876 }
877
878 fn egl_image_target_texture2d_oes(&self, target: GLenum, image: GLeglImageOES) {
879 unimplemented()
880 }
881
882 fn generate_mipmap(&self, target: GLenum) {
883 unimplemented()
884 }
885
886 fn insert_event_marker_ext(&self, message: &str) {
887 unimplemented()
888 }
889
890 fn push_group_marker_ext(&self, message: &str) {
891 unimplemented()
892 }
893
894 fn pop_group_marker_ext(&self) {
895 unimplemented()
896 }
897
898 fn debug_message_insert_khr(&self, source: GLenum, type_: GLenum, id: GLuint, severity: GLenum, message: &str) {
899 unimplemented()
900 }
901
902 fn push_debug_group_khr(&self, source: GLenum, id: GLuint, message: &str) {
903 unimplemented()
904 }
905
906 fn pop_debug_group_khr(&self) {
907 unimplemented()
908 }
909
910 fn fence_sync(&self, condition: GLenum, flags: GLbitfield) -> GLsync {
911 unimplemented()
912 }
913
914 fn client_wait_sync(&self, sync: GLsync, flags: GLbitfield, timeout: GLuint64) {
915 unimplemented()
916 }
917
918 fn wait_sync(&self, sync: GLsync, flags: GLbitfield, timeout: GLuint64) {
919 unimplemented()
920 }
921
922 fn delete_sync(&self, sync: GLsync) {
923 unimplemented()
924 }
925
926 fn texture_range_apple(&self, target: GLenum, data: &[u8]) {
927 unimplemented()
928 }
929
930 fn gen_fences_apple(&self, n: GLsizei) -> Vec<GLuint> {
931 unimplemented()
932 }
933
934 fn delete_fences_apple(&self, fences: &[GLuint]) {
935 unimplemented()
936 }
937
938 fn set_fence_apple(&self, fence: GLuint) {
939 unimplemented()
940 }
941
942 fn finish_fence_apple(&self, fence: GLuint) {
943 unimplemented()
944 }
945
946 fn test_fence_apple(&self, fence: GLuint) {
947 unimplemented()
948 }
949
950 fn test_object_apple(&self, object: GLenum, name: GLuint) -> GLboolean {
951 unimplemented()
952 }
953
954 fn finish_object_apple(&self, object: GLenum, name: GLuint) {
955 unimplemented()
956 }
957
958 fn get_frag_data_index( &self, program: GLuint, name: &str) -> GLint {
959 unimplemented()
960 }
961
962 fn blend_barrier_khr(&self) {
963 unimplemented()
964 }
965
966 fn bind_frag_data_location_indexed( &self, program: GLuint, color_number: GLuint, index: GLuint, name: &str) {
967 unimplemented()
968 }
969
970 fn get_debug_messages(&self) -> Vec<DebugMessage> {
971 unimplemented()
972 }
973
974 fn provoking_vertex_angle(&self, mode: GLenum) {
975 unimplemented()
976 }
977
978 fn gen_vertex_arrays_apple(&self, n: GLsizei) -> Vec<GLuint> {
981 unimplemented()
982 }
983
984 fn bind_vertex_array_apple(&self, vao: GLuint) {
985 unimplemented()
986 }
987
988 fn delete_vertex_arrays_apple(&self, vertex_arrays: &[GLuint]) {
989 unimplemented()
990 }
991
992 fn copy_texture_chromium(
993 &self,
994 source_id: GLuint,
995 source_level: GLint,
996 dest_target: GLenum,
997 dest_id: GLuint,
998 dest_level: GLint,
999 internal_format: GLint,
1000 dest_type: GLenum,
1001 unpack_flip_y: GLboolean,
1002 unpack_premultiply_alpha: GLboolean,
1003 unpack_unmultiply_alpha: GLboolean
1004 ) {
1005 unimplemented()
1006 }
1007
1008 fn copy_sub_texture_chromium(
1009 &self,
1010 source_id: GLuint,
1011 source_level: GLint,
1012 dest_target: GLenum,
1013 dest_id: GLuint,
1014 dest_level: GLint,
1015 x_offset: GLint,
1016 y_offset: GLint,
1017 x: GLint,
1018 y: GLint,
1019 width: GLsizei,
1020 height: GLsizei,
1021 unpack_flip_y: GLboolean,
1022 unpack_premultiply_alpha: GLboolean,
1023 unpack_unmultiply_alpha: GLboolean
1024 ) {
1025 unimplemented()
1026 }
1027
1028 fn egl_image_target_renderbuffer_storage_oes(&self, target: u32, image: *const c_void) {
1031 unimplemented()
1032 }
1033
1034 fn copy_texture_3d_angle(
1035 &self,
1036 source_id: GLuint,
1037 source_level: GLint,
1038 dest_target: GLenum,
1039 dest_id: GLuint,
1040 dest_level: GLint,
1041 internal_format: GLint,
1042 dest_type: GLenum,
1043 unpack_flip_y: GLboolean,
1044 unpack_premultiply_alpha: GLboolean,
1045 unpack_unmultiply_alpha: GLboolean
1046 ) {
1047 unimplemented()
1048 }
1049
1050 fn copy_sub_texture_3d_angle(
1051 &self,
1052 source_id: GLuint,
1053 source_level: GLint,
1054 dest_target: GLenum,
1055 dest_id: GLuint,
1056 dest_level: GLint,
1057 x_offset: GLint,
1058 y_offset: GLint,
1059 z_offset: GLint,
1060 x: GLint,
1061 y: GLint,
1062 z: GLint,
1063 width: GLsizei,
1064 height: GLsizei,
1065 depth: GLsizei,
1066 unpack_flip_y: GLboolean,
1067 unpack_premultiply_alpha: GLboolean,
1068 unpack_unmultiply_alpha: GLboolean
1069 ) {
1070 unimplemented()
1071 }
1072}
1073
1074fn unimplemented() -> ! {
1075 panic!("You cannot call OpenGL functions on the VirtualGlDriver");
1076}
1077
1078pub struct Texture {
1080 pub texture_id: GLuint,
1082 pub flags: TextureFlags,
1084 pub size: LogicalSize,
1086 pub gl_context: Rc<dyn Gl>,
1088}
1089
1090#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1091pub struct TextureFlags {
1092 pub is_opaque: bool,
1094 pub is_video_texture: bool,
1096}
1097
1098impl ::std::fmt::Display for Texture {
1099 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
1100 write!(f, "Texture {{ id: {}, {}x{} }}", self.texture_id, self.size.width, self.size.height)
1101 }
1102}
1103
1104macro_rules! impl_traits_for_gl_object {
1105 ($struct_name:ident, $gl_id_field:ident) => {
1106
1107 impl ::std::fmt::Debug for $struct_name {
1108 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
1109 write!(f, "{}", self)
1110 }
1111 }
1112
1113 impl Hash for $struct_name {
1114 fn hash<H: Hasher>(&self, state: &mut H) {
1115 self.$gl_id_field.hash(state);
1116 }
1117 }
1118
1119 impl PartialEq for $struct_name {
1120 fn eq(&self, other: &$struct_name) -> bool {
1121 self.$gl_id_field == other.$gl_id_field
1122 }
1123 }
1124
1125 impl Eq for $struct_name { }
1126
1127 impl PartialOrd for $struct_name {
1128 fn partial_cmp(&self, other: &Self) -> Option<::std::cmp::Ordering> {
1129 Some((self.$gl_id_field).cmp(&(other.$gl_id_field)))
1130 }
1131 }
1132
1133 impl Ord for $struct_name {
1134 fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
1135 (self.$gl_id_field).cmp(&(other.$gl_id_field))
1136 }
1137 }
1138 };
1139 ($struct_name:ident<$lt:lifetime>, $gl_id_field:ident) => {
1140 impl<$lt> ::std::fmt::Debug for $struct_name<$lt> {
1141 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
1142 write!(f, "{}", self)
1143 }
1144 }
1145
1146 impl<$lt> Hash for $struct_name<$lt> {
1147 fn hash<H: Hasher>(&self, state: &mut H) {
1148 self.$gl_id_field.hash(state);
1149 }
1150 }
1151
1152 impl<$lt>PartialEq for $struct_name<$lt> {
1153 fn eq(&self, other: &$struct_name) -> bool {
1154 self.$gl_id_field == other.$gl_id_field
1155 }
1156 }
1157
1158 impl<$lt> Eq for $struct_name<$lt> { }
1159
1160 impl<$lt> PartialOrd for $struct_name<$lt> {
1161 fn partial_cmp(&self, other: &Self) -> Option<::std::cmp::Ordering> {
1162 Some((self.$gl_id_field).cmp(&(other.$gl_id_field)))
1163 }
1164 }
1165
1166 impl<$lt> Ord for $struct_name<$lt> {
1167 fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
1168 (self.$gl_id_field).cmp(&(other.$gl_id_field))
1169 }
1170 }
1171 };
1172 ($struct_name:ident<$t:ident: $constraint:ident>, $gl_id_field:ident) => {
1173 impl<$t: $constraint> ::std::fmt::Debug for $struct_name<$t> {
1174 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
1175 write!(f, "{}", self)
1176 }
1177 }
1178
1179 impl<$t: $constraint> Hash for $struct_name<$t> {
1180 fn hash<H: Hasher>(&self, state: &mut H) {
1181 self.$gl_id_field.hash(state);
1182 }
1183 }
1184
1185 impl<$t: $constraint>PartialEq for $struct_name<$t> {
1186 fn eq(&self, other: &$struct_name<$t>) -> bool {
1187 self.$gl_id_field == other.$gl_id_field
1188 }
1189 }
1190
1191 impl<$t: $constraint> Eq for $struct_name<$t> { }
1192
1193 impl<$t: $constraint> PartialOrd for $struct_name<$t> {
1194 fn partial_cmp(&self, other: &Self) -> Option<::std::cmp::Ordering> {
1195 Some((self.$gl_id_field).cmp(&(other.$gl_id_field)))
1196 }
1197 }
1198
1199 impl<$t: $constraint> Ord for $struct_name<$t> {
1200 fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
1201 (self.$gl_id_field).cmp(&(other.$gl_id_field))
1202 }
1203 }
1204 };
1205}
1206
1207impl_traits_for_gl_object!(Texture, texture_id);
1208
1209impl Drop for Texture {
1210 fn drop(&mut self) {
1211 self.gl_context.delete_textures(&[self.texture_id]);
1212 }
1213}
1214
1215#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1217pub struct VertexLayout {
1218 pub fields: Vec<VertexAttribute>,
1219}
1220
1221impl VertexLayout {
1222
1223 pub fn bind(&self, shader: &GlShader) {
1225
1226 const VERTICES_ARE_NORMALIZED: bool = false;
1227
1228 let gl_context = &*shader.gl_context;
1229
1230 let mut offset = 0;
1231
1232 let stride_between_vertices: usize = self.fields.iter().map(VertexAttribute::get_stride).sum();
1233
1234 for vertex_attribute in self.fields.iter() {
1235
1236 let attribute_location = vertex_attribute.layout_location
1237 .map(|ll| ll as i32)
1238 .unwrap_or_else(|| gl_context.get_attrib_location(shader.program_id, &vertex_attribute.name));
1239
1240 gl_context.vertex_attrib_pointer(
1241 attribute_location as u32,
1242 vertex_attribute.item_count as i32,
1243 vertex_attribute.attribute_type.get_gl_id(),
1244 VERTICES_ARE_NORMALIZED,
1245 stride_between_vertices as i32,
1246 offset as u32,
1247 );
1248 gl_context.enable_vertex_attrib_array(attribute_location as u32);
1249 offset += vertex_attribute.get_stride();
1250 }
1251 }
1252
1253 pub fn unbind(&self, shader: &GlShader) {
1255 let gl_context = &*shader.gl_context;
1256 for vertex_attribute in self.fields.iter() {
1257 let attribute_location = vertex_attribute.layout_location
1258 .map(|ll| ll as i32)
1259 .unwrap_or_else(|| gl_context.get_attrib_location(shader.program_id, &vertex_attribute.name));
1260 gl_context.disable_vertex_attrib_array(attribute_location as u32);
1261 }
1262 }
1263}
1264
1265#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1266pub struct VertexAttribute {
1267 pub name: &'static str,
1269 pub layout_location: Option<usize>,
1272 pub attribute_type: VertexAttributeType,
1274 pub item_count: usize,
1276}
1277
1278impl VertexAttribute {
1279 pub fn get_stride(&self) -> usize {
1280 self.attribute_type.get_mem_size() * self.item_count
1281 }
1282}
1283
1284#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1285pub enum VertexAttributeType {
1286 Float,
1288 Double,
1290 UnsignedByte,
1292 UnsignedShort,
1294 UnsignedInt,
1296}
1297
1298impl VertexAttributeType {
1299
1300 pub fn get_gl_id(&self) -> GLuint {
1302 use self::VertexAttributeType::*;
1303 match self {
1304 Float => gl::FLOAT,
1305 Double => gl::DOUBLE,
1306 UnsignedByte => gl::UNSIGNED_BYTE,
1307 UnsignedShort => gl::UNSIGNED_SHORT,
1308 UnsignedInt => gl::UNSIGNED_INT,
1309 }
1310 }
1311
1312 pub fn get_mem_size(&self) -> usize {
1313 use std::mem;
1314 use self::VertexAttributeType::*;
1315 match self {
1316 Float => mem::size_of::<f32>(),
1317 Double => mem::size_of::<f64>(),
1318 UnsignedByte => mem::size_of::<u8>(),
1319 UnsignedShort => mem::size_of::<u16>(),
1320 UnsignedInt => mem::size_of::<u32>(),
1321 }
1322 }
1323}
1324
1325pub trait VertexLayoutDescription {
1326 fn get_description() -> VertexLayout;
1327}
1328
1329pub struct VertexArrayObject {
1330 pub vertex_layout: VertexLayout,
1331 pub vao_id: GLuint,
1332 pub gl_context: Rc<dyn Gl>,
1333}
1334
1335impl Drop for VertexArrayObject {
1336 fn drop(&mut self) {
1337 self.gl_context.delete_vertex_arrays(&[self.vao_id]);
1338 }
1339}
1340
1341pub struct VertexBuffer<T: VertexLayoutDescription> {
1342 pub vertex_buffer_id: GLuint,
1343 pub vertex_buffer_len: usize,
1344 pub gl_context: Rc<dyn Gl>,
1345 pub vao: VertexArrayObject,
1346 pub vertex_buffer_type: PhantomData<T>,
1347
1348 pub index_buffer_id: GLuint,
1350 pub index_buffer_len: usize,
1351 pub index_buffer_format: IndexBufferFormat,
1352}
1353
1354impl<T: VertexLayoutDescription> ::std::fmt::Display for VertexBuffer<T> {
1355 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
1356 write!(f,
1357 "VertexBuffer {{ buffer: {} (length: {}) }})",
1358 self.vertex_buffer_id, self.vertex_buffer_len
1359 )
1360 }
1361}
1362
1363impl_traits_for_gl_object!(VertexBuffer<T: VertexLayoutDescription>, vertex_buffer_id);
1364
1365impl<T: VertexLayoutDescription> Drop for VertexBuffer<T> {
1366 fn drop(&mut self) {
1367 self.gl_context.delete_buffers(&[self.vertex_buffer_id, self.index_buffer_id]);
1368 }
1369}
1370
1371impl<T: VertexLayoutDescription> VertexBuffer<T> {
1372 pub fn new(shader: &GlShader, vertices: &[T], indices: &[u32], index_buffer_format: IndexBufferFormat) -> Self {
1373
1374 use std::mem;
1375
1376 let gl_context = shader.gl_context.clone();
1377
1378 let mut current_vertex_array = [0_i32];
1380 let mut current_vertex_buffer = [0_i32];
1381 let mut current_index_buffer = [0_i32];
1382
1383 unsafe { gl_context.get_integer_v(gl::VERTEX_ARRAY, &mut current_vertex_array) };
1384 unsafe { gl_context.get_integer_v(gl::ARRAY_BUFFER, &mut current_vertex_buffer) };
1385 unsafe { gl_context.get_integer_v(gl::ELEMENT_ARRAY_BUFFER, &mut current_index_buffer) };
1386
1387 let vertex_array_object = gl_context.gen_vertex_arrays(1);
1388 let vertex_array_object = vertex_array_object[0];
1389
1390 let vertex_buffer_id = gl_context.gen_buffers(1);
1391 let vertex_buffer_id = vertex_buffer_id[0];
1392
1393 let index_buffer_id = gl_context.gen_buffers(1);
1394 let index_buffer_id = index_buffer_id[0];
1395
1396 gl_context.bind_vertex_array(vertex_array_object);
1397
1398 gl_context.bind_buffer(gl::ARRAY_BUFFER, vertex_buffer_id);
1400 gl_context.buffer_data_untyped(
1401 gl::ARRAY_BUFFER,
1402 (mem::size_of::<T>() * vertices.len()) as isize,
1403 vertices.as_ptr() as *const c_void,
1404 gl::STATIC_DRAW
1405 );
1406
1407 gl_context.bind_buffer(gl::ELEMENT_ARRAY_BUFFER, index_buffer_id);
1409 gl_context.buffer_data_untyped(
1410 gl::ELEMENT_ARRAY_BUFFER,
1411 (mem::size_of::<u32>() * indices.len()) as isize,
1412 indices.as_ptr() as *const c_void,
1413 gl::STATIC_DRAW
1414 );
1415
1416 let vertex_description = T::get_description();
1417 vertex_description.bind(shader);
1418
1419 gl_context.bind_buffer(gl::ARRAY_BUFFER, current_vertex_buffer[0] as u32);
1421 gl_context.bind_buffer(gl::ELEMENT_ARRAY_BUFFER, current_index_buffer[0] as u32);
1422 gl_context.bind_vertex_array(current_vertex_array[0] as u32);
1423
1424 Self {
1425 vertex_buffer_id,
1426 vertex_buffer_len: vertices.len(),
1427 gl_context: gl_context.clone(),
1428 vao: VertexArrayObject {
1429 vertex_layout: vertex_description,
1430 vao_id: vertex_array_object,
1431 gl_context,
1432 },
1433 vertex_buffer_type: PhantomData,
1434 index_buffer_id,
1435 index_buffer_len: indices.len(),
1436 index_buffer_format,
1437 }
1438 }
1439}
1440
1441#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1442pub enum GlApiVersion {
1443 Gl { major: usize, minor: usize },
1444 GlEs { major: usize, minor: usize },
1445}
1446
1447impl GlApiVersion {
1448 pub fn get(gl_context: &dyn Gl) -> Self {
1450 let mut major = [0];
1451 unsafe { gl_context.get_integer_v(gl::MAJOR_VERSION, &mut major) };
1452 let mut minor = [0];
1453 unsafe { gl_context.get_integer_v(gl::MINOR_VERSION, &mut minor) };
1454
1455 GlApiVersion::Gl { major: major[0] as usize, minor: minor[0] as usize }
1456 }
1457}
1458
1459#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1460pub enum IndexBufferFormat {
1461 Points,
1462 Lines,
1463 LineStrip,
1464 Triangles,
1465 TriangleStrip,
1466 TriangleFan,
1467}
1468
1469impl IndexBufferFormat {
1470 pub fn get_gl_id(&self) -> GLuint {
1472 use self::IndexBufferFormat::*;
1473 match self {
1474 Points => gl::POINTS,
1475 Lines => gl::LINES,
1476 LineStrip => gl::LINE_STRIP,
1477 Triangles => gl::TRIANGLES,
1478 TriangleStrip => gl::TRIANGLE_STRIP,
1479 TriangleFan => gl::TRIANGLE_FAN,
1480 }
1481 }
1482}
1483
1484#[derive(Debug, Clone, PartialEq, PartialOrd)]
1485pub struct Uniform {
1486 pub name: String,
1487 pub uniform_type: UniformType,
1488}
1489
1490impl Uniform {
1491 pub fn new<S: Into<String>>(name: S, uniform_type: UniformType) -> Self {
1492 Self { name: name.into(), uniform_type }
1493 }
1494}
1495
1496#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
1497pub enum UniformType {
1498 Float(f32),
1499 FloatVec2([f32;2]),
1500 FloatVec3([f32;3]),
1501 FloatVec4([f32;4]),
1502 Int(i32),
1503 IntVec2([i32;2]),
1504 IntVec3([i32;3]),
1505 IntVec4([i32;4]),
1506 UnsignedInt(u32),
1507 UnsignedIntVec2([u32;2]),
1508 UnsignedIntVec3([u32;3]),
1509 UnsignedIntVec4([u32;4]),
1510 Matrix2 { transpose: bool, matrix: [f32;2*2] },
1511 Matrix3 { transpose: bool, matrix: [f32;3*3] },
1512 Matrix4 { transpose: bool, matrix: [f32;4*4] },
1513}
1514
1515impl UniformType {
1516 pub fn set(self, gl_context: &dyn Gl, location: GLint) {
1518 use self::UniformType::*;
1519 match self {
1520 Float(r) => gl_context.uniform_1f(location, r),
1521 FloatVec2([r,g]) => gl_context.uniform_2f(location, r, g),
1522 FloatVec3([r,g,b]) => gl_context.uniform_3f(location, r, g, b),
1523 FloatVec4([r,g,b,a]) => gl_context.uniform_4f(location, r, g, b, a),
1524 Int(r) => gl_context.uniform_1i(location, r),
1525 IntVec2([r,g]) => gl_context.uniform_2i(location, r, g),
1526 IntVec3([r,g,b]) => gl_context.uniform_3i(location, r, g, b),
1527 IntVec4([r,g,b,a]) => gl_context.uniform_4i(location, r, g, b, a),
1528 UnsignedInt(r) => gl_context.uniform_1ui(location, r),
1529 UnsignedIntVec2([r,g]) => gl_context.uniform_2ui(location, r, g),
1530 UnsignedIntVec3([r,g,b]) => gl_context.uniform_3ui(location, r, g, b),
1531 UnsignedIntVec4([r,g,b,a]) => gl_context.uniform_4ui(location, r, g, b, a),
1532 Matrix2 { transpose, matrix } => gl_context.uniform_matrix_2fv(location, transpose, &matrix[..]),
1533 Matrix3 { transpose, matrix } => gl_context.uniform_matrix_2fv(location, transpose, &matrix[..]),
1534 Matrix4 { transpose, matrix } => gl_context.uniform_matrix_2fv(location, transpose, &matrix[..]),
1535 }
1536 }
1537}
1538
1539pub struct GlShader {
1540 pub program_id: GLuint,
1541 pub gl_context: Rc<dyn Gl>,
1542}
1543
1544impl ::std::fmt::Display for GlShader {
1545 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
1546 write!(f, "GlShader {{ program_id: {} }}", self.program_id)
1547 }
1548}
1549
1550impl_traits_for_gl_object!(GlShader, program_id);
1551
1552impl Drop for GlShader {
1553 fn drop(&mut self) {
1554 self.gl_context.delete_program(self.program_id);
1555 }
1556}
1557
1558#[derive(Clone)]
1559pub struct VertexShaderCompileError {
1560 pub error_id: i32,
1561 pub info_log: String
1562}
1563
1564impl_traits_for_gl_object!(VertexShaderCompileError, error_id);
1565
1566impl ::std::fmt::Display for VertexShaderCompileError {
1567 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
1568 write!(f, "E{}: {}", self.error_id, self.info_log)
1569 }
1570}
1571
1572#[derive(Clone)]
1573pub struct FragmentShaderCompileError {
1574 pub error_id: i32,
1575 pub info_log: String
1576}
1577
1578impl_traits_for_gl_object!(FragmentShaderCompileError, error_id);
1579
1580impl ::std::fmt::Display for FragmentShaderCompileError {
1581 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
1582 write!(f, "E{}: {}", self.error_id, self.info_log)
1583 }
1584}
1585
1586#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
1587pub enum GlShaderCompileError {
1588 Vertex(VertexShaderCompileError),
1589 Fragment(FragmentShaderCompileError),
1590}
1591
1592impl ::std::fmt::Display for GlShaderCompileError {
1593 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
1594 use self::GlShaderCompileError::*;
1595 match self {
1596 Vertex(vert_err) => write!(f, "Failed to compile vertex shader: {}", vert_err),
1597 Fragment(frag_err) => write!(f, "Failed to compile fragment shader: {}", frag_err),
1598 }
1599 }
1600}
1601
1602impl ::std::fmt::Debug for GlShaderCompileError {
1603 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
1604 write!(f, "{}", self)
1605 }
1606}
1607
1608#[derive(Clone)]
1609pub struct GlShaderLinkError {
1610 pub error_id: i32,
1611 pub info_log: String
1612}
1613
1614impl_traits_for_gl_object!(GlShaderLinkError, error_id);
1615
1616impl ::std::fmt::Display for GlShaderLinkError {
1617 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
1618 write!(f, "E{}: {}", self.error_id, self.info_log)
1619 }
1620}
1621
1622#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
1623pub enum GlShaderCreateError {
1624 Compile(GlShaderCompileError),
1625 Link(GlShaderLinkError),
1626 NoShaderCompiler,
1627}
1628
1629impl ::std::fmt::Display for GlShaderCreateError {
1630 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
1631 use self::GlShaderCreateError::*;
1632 match self {
1633 Compile(compile_err) => write!(f, "Shader compile error: {}", compile_err),
1634 Link(link_err) => write!(f, "Shader linking error: {}", link_err),
1635 NoShaderCompiler => write!(f, "OpenGL implementation doesn't include a shader compiler"),
1636 }
1637 }
1638}
1639
1640impl ::std::fmt::Debug for GlShaderCreateError {
1641 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
1642 write!(f, "{}", self)
1643 }
1644}
1645
1646impl GlShader {
1647
1648 pub fn new(gl_context: Rc<dyn Gl>, vertex_shader: &str, fragment_shader: &str) -> Result<Self, GlShaderCreateError> {
1652
1653 let mut shader_compiler_supported = [gl::FALSE];
1655 unsafe { gl_context.get_boolean_v(gl::SHADER_COMPILER, &mut shader_compiler_supported) };
1656 if shader_compiler_supported[0] == gl::FALSE {
1657 return Err(GlShaderCreateError::NoShaderCompiler);
1659 }
1660
1661 fn str_to_bytes(input: &str) -> Vec<u8> {
1662 let mut v: Vec<u8> = input.into();
1663 v.push(0);
1664 v
1665 }
1666
1667 let vertex_shader_source = str_to_bytes(vertex_shader);
1668 let fragment_shader_source = str_to_bytes(fragment_shader);
1669
1670 let vertex_shader_object = gl_context.create_shader(gl::VERTEX_SHADER);
1673 gl_context.shader_source(vertex_shader_object, &[&vertex_shader_source]);
1674 gl_context.compile_shader(vertex_shader_object);
1675
1676 #[cfg(debug_assertions)] {
1677 if let Some(error_id) = get_gl_shader_error(&*gl_context, vertex_shader_object) {
1678 let info_log = gl_context.get_shader_info_log(vertex_shader_object);
1679 gl_context.delete_shader(vertex_shader_object);
1680 return Err(GlShaderCreateError::Compile(GlShaderCompileError::Vertex(VertexShaderCompileError { error_id, info_log })));
1681 }
1682 }
1683
1684 let fragment_shader_object = gl_context.create_shader(gl::FRAGMENT_SHADER);
1687 gl_context.shader_source(fragment_shader_object, &[&fragment_shader_source]);
1688 gl_context.compile_shader(fragment_shader_object);
1689
1690 #[cfg(debug_assertions)] {
1691 if let Some(error_id) = get_gl_shader_error(&*gl_context, fragment_shader_object) {
1692 let info_log = gl_context.get_shader_info_log(fragment_shader_object);
1693 gl_context.delete_shader(vertex_shader_object);
1694 gl_context.delete_shader(fragment_shader_object);
1695 return Err(GlShaderCreateError::Compile(GlShaderCompileError::Fragment(FragmentShaderCompileError { error_id, info_log })));
1696 }
1697 }
1698
1699 let program_id = gl_context.create_program();
1702 gl_context.attach_shader(program_id, vertex_shader_object);
1703 gl_context.attach_shader(program_id, fragment_shader_object);
1704 gl_context.link_program(program_id);
1705
1706 #[cfg(debug_assertions)] {
1707 if let Some(error_id) = get_gl_program_error(&*gl_context, program_id) {
1708 let info_log = gl_context.get_program_info_log(program_id);
1709 gl_context.delete_shader(vertex_shader_object);
1710 gl_context.delete_shader(fragment_shader_object);
1711 gl_context.delete_program(program_id);
1712 return Err(GlShaderCreateError::Link(GlShaderLinkError { error_id, info_log }));
1713 }
1714 }
1715
1716 gl_context.delete_shader(vertex_shader_object);
1717 gl_context.delete_shader(fragment_shader_object);
1718
1719 Ok(GlShader { program_id, gl_context })
1720 }
1721
1722 pub fn draw<T: VertexLayoutDescription>(
1726 &mut self,
1727 buffers: &[(Rc<VertexBuffer<T>>, Vec<Uniform>)],
1728 clear_color: Option<ColorU>,
1729 texture_size: LogicalSize,
1730 ) -> Texture {
1731
1732 use std::ops::Deref;
1733 use std::collections::HashMap;
1734
1735 const INDEX_TYPE: GLuint = gl::UNSIGNED_INT;
1736
1737 let gl_context = &*self.gl_context;
1738
1739 let mut current_multisample = [0_u8];
1741 let mut current_index_buffer = [0_i32];
1742 let mut current_vertex_buffer = [0_i32];
1743 let mut current_vertex_array_object = [0_i32];
1744 let mut current_program = [0_i32];
1745 let mut current_framebuffers = [0_i32];
1746 let mut current_renderbuffers = [0_i32];
1747 let mut current_texture_2d = [0_i32];
1748
1749 unsafe { gl_context.get_boolean_v(gl::MULTISAMPLE, &mut current_multisample) };
1750 unsafe { gl_context.get_integer_v(gl::ARRAY_BUFFER_BINDING, &mut current_vertex_buffer) };
1751 unsafe { gl_context.get_integer_v(gl::ELEMENT_ARRAY_BUFFER_BINDING, &mut current_index_buffer) };
1752 unsafe { gl_context.get_integer_v(gl::CURRENT_PROGRAM, &mut current_program) };
1753 unsafe { gl_context.get_integer_v(gl::VERTEX_ARRAY_BINDING, &mut current_vertex_array_object) };
1754 unsafe { gl_context.get_integer_v(gl::RENDERBUFFER, &mut current_renderbuffers) };
1755 unsafe { gl_context.get_integer_v(gl::FRAMEBUFFER, &mut current_framebuffers) };
1756 unsafe { gl_context.get_integer_v(gl::TEXTURE_2D, &mut current_texture_2d) };
1757
1758 let textures = gl_context.gen_textures(1);
1761 let texture_id = textures[0];
1762 let framebuffers = gl_context.gen_framebuffers(1);
1763 let framebuffer_id = framebuffers[0];
1764 gl_context.bind_framebuffer(gl::FRAMEBUFFER, framebuffer_id);
1765
1766 let depthbuffers = gl_context.gen_renderbuffers(1);
1767 let depthbuffer_id = depthbuffers[0];
1768
1769 gl_context.bind_texture(gl::TEXTURE_2D, texture_id);
1770 gl_context.tex_image_2d(gl::TEXTURE_2D, 0, gl::RGBA as i32, texture_size.width as i32, texture_size.height as i32, 0, gl::RGBA, gl::UNSIGNED_BYTE, None);
1771 gl_context.tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as i32);
1772 gl_context.tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as i32);
1773 gl_context.tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as i32);
1774 gl_context.tex_parameter_i(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as i32);
1775
1776 gl_context.bind_renderbuffer(gl::RENDERBUFFER, depthbuffer_id);
1777 gl_context.renderbuffer_storage(gl::RENDERBUFFER, gl::DEPTH_COMPONENT, texture_size.width as i32, texture_size.height as i32);
1778 gl_context.framebuffer_renderbuffer(gl::FRAMEBUFFER, gl::DEPTH_ATTACHMENT, gl::RENDERBUFFER, depthbuffer_id);
1779
1780 gl_context.framebuffer_texture_2d(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D, texture_id, 0);
1781 gl_context.draw_buffers(&[gl::COLOR_ATTACHMENT0]);
1782 gl_context.viewport(0, 0, texture_size.width as i32, texture_size.height as i32);
1783
1784 debug_assert!(gl_context.check_frame_buffer_status(gl::FRAMEBUFFER) == gl::FRAMEBUFFER_COMPLETE);
1785
1786 gl_context.use_program(self.program_id);
1787 gl_context.disable(gl::MULTISAMPLE);
1788
1789 let mut uniform_locations: HashMap<String, i32> = HashMap::new();
1791 let mut max_uniform_len = 0;
1792 for (_, uniforms) in buffers {
1793 for uniform in uniforms.iter() {
1794 if !uniform_locations.contains_key(&uniform.name) {
1795 uniform_locations.insert(uniform.name.clone(), gl_context.get_uniform_location(self.program_id, &uniform.name));
1796 }
1797 }
1798 max_uniform_len = max_uniform_len.max(uniforms.len());
1799 }
1800 let mut current_uniforms = vec![None;max_uniform_len];
1801
1802 if let Some(clear_color) = clear_color {
1806 let clear_color: ColorF = clear_color.into();
1807 gl_context.clear_color(clear_color.r, clear_color.g, clear_color.b, clear_color.a);
1808 }
1809
1810 gl_context.clear_depth(0.0);
1811 gl_context.clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);
1812
1813 for (vi, uniforms) in buffers {
1815
1816 let vertex_buffer = vi.deref();
1817
1818 gl_context.bind_vertex_array(vertex_buffer.vao.vao_id);
1819 gl_context.bind_buffer(gl::ELEMENT_ARRAY_BUFFER, vertex_buffer.index_buffer_id);
1821
1822 for (uniform_index, uniform) in uniforms.iter().enumerate() {
1824 if current_uniforms[uniform_index] != Some(uniform.uniform_type) {
1825 let uniform_location = uniform_locations[&uniform.name];
1826 uniform.uniform_type.set(gl_context, uniform_location);
1827 current_uniforms[uniform_index] = Some(uniform.uniform_type);
1828 }
1829 }
1830
1831 gl_context.draw_elements(vertex_buffer.index_buffer_format.get_gl_id(), vertex_buffer.index_buffer_len as i32, INDEX_TYPE, 0);
1832 }
1833
1834 if current_multisample[0] == gl::TRUE { gl_context.enable(gl::MULTISAMPLE); }
1836 gl_context.bind_vertex_array(current_vertex_array_object[0] as u32);
1837 gl_context.bind_framebuffer(gl::FRAMEBUFFER, current_framebuffers[0] as u32);
1838 gl_context.bind_texture(gl::TEXTURE_2D, current_texture_2d[0] as u32);
1839 gl_context.bind_texture(gl::RENDERBUFFER, current_renderbuffers[0] as u32);
1840 gl_context.bind_buffer(gl::ELEMENT_ARRAY_BUFFER, current_index_buffer[0] as u32);
1841 gl_context.bind_buffer(gl::ARRAY_BUFFER, current_vertex_buffer[0] as u32);
1842 gl_context.use_program(current_program[0] as u32);
1843
1844 gl_context.delete_framebuffers(&[framebuffer_id]);
1845 gl_context.delete_renderbuffers(&[depthbuffer_id]);
1846
1847 Texture {
1848 texture_id,
1849 size: texture_size,
1850 flags: TextureFlags {
1851 is_opaque: true,
1852 is_video_texture: false,
1853 },
1854 gl_context: self.gl_context.clone(),
1855 }
1856 }
1857}
1858
1859#[cfg(debug_assertions)]
1860fn get_gl_shader_error(context: &dyn Gl, shader_object: GLuint) -> Option<i32> {
1861 let mut err = [0];
1862 unsafe { context.get_shader_iv(shader_object, gl::COMPILE_STATUS, &mut err) };
1863 let err_code = err[0];
1864 if err_code == gl::TRUE as i32 { None } else { Some(err_code) }
1865}
1866
1867#[cfg(debug_assertions)]
1868fn get_gl_program_error(context: &dyn Gl, shader_object: GLuint) -> Option<i32> {
1869 let mut err = [0];
1870 unsafe { context.get_program_iv(shader_object, gl::LINK_STATUS, &mut err) };
1871 let err_code = err[0];
1872 if err_code == gl::TRUE as i32 { None } else { Some(err_code) }
1873}