1use std::cell::Cell;
9
10mod asi;
11
12use std::mem;
13use Matrix;
14use Rotation;
15
16use WindowConnection;
17
18pub use self::base::Shape;
19pub use self::base::Gradient;
20pub use self::base::Model;
21pub use self::base::TexCoords;
22pub use self::base::Texture;
23
24use self::asi::{
25 OpenGL, OpenGLBuilder, VertexData, Program, Buffer, UniformData,
26 Feature, Topology,
27};
28use super::base;
29use super::base::*;
30
31const SHADER_SOLID_FRAG: &'static [u8] = include_bytes!("shaders/solid-frag.glsl");
32const SHADER_SOLID_VERT: &'static [u8] = include_bytes!("shaders/solid-vert.glsl");
33const SHADER_GRADIENT_FRAG: &'static [u8] = include_bytes!("shaders/gradient-frag.glsl");
34const SHADER_GRADIENT_VERT: &'static [u8] = include_bytes!("shaders/gradient-vert.glsl");
35const SHADER_TEX_FRAG: &'static [u8] = include_bytes!("shaders/texture-frag.glsl");
36const SHADER_TEX_VERT: &'static [u8] = include_bytes!("shaders/texture-vert.glsl");
37const SHADER_FADED_VERT: &'static [u8] = include_bytes!("shaders/faded-vert.glsl");
38const SHADER_TINTED_FRAG: &'static [u8] = include_bytes!("shaders/tinted-frag.glsl");
39const SHADER_COMPLEX_VERT: &'static [u8] = include_bytes!("shaders/complex-vert.glsl");
40const SHADER_COMPLEX_FRAG: &'static [u8] = include_bytes!("shaders/complex-frag.glsl");
41
42const STYLE_GRADIENT: usize = 0;
43const STYLE_TEXTURE: usize = 1;
44const STYLE_FADED: usize = 2;
45const STYLE_TINTED: usize = 3;
46const STYLE_SOLID: usize = 4;
47const STYLE_COMPLEX: usize = 5;
48
49struct Style {
50 shader: Program,
51 matrix_uniform: UniformData,
52 has_camera: UniformData,
53 camera_uniform: UniformData,
54 has_fog: UniformData,
55 fog: UniformData,
56 range: UniformData,
57 alpha: UniformData,
58 color: UniformData,
59 position: VertexData,
60 texpos: VertexData,
61 acolor: VertexData,
62}
63
64impl Style {
65 fn new(context: &OpenGL, vert: &[u8], frag: &[u8]) -> Style {
67 let shader = Program::new(context, vert, frag);
68 let matrix_uniform = shader.uniform(b"models_tfm\0");
69 let has_camera = shader.uniform(b"has_camera\0");
70 let camera_uniform = shader.uniform(b"matrix\0");
71 let has_fog = shader.uniform(b"has_fog\0");
72 let fog = shader.uniform(b"fog\0");
73 let range = shader.uniform(b"range\0");
74 let alpha = shader.uniform(b"alpha\0");
75 let color = shader.uniform(b"color\0");
76 let position = shader.vertex_data(b"position\0");
77 let texpos = shader.vertex_data(b"texpos\0");
78 let acolor = shader.vertex_data(b"acolor\0");
79
80 Style {
81 shader, matrix_uniform, has_camera, camera_uniform, fog,
82 range, position, texpos, alpha, has_fog, color, acolor,
83 }
84 }
85}
86
87struct ShapeData {
88 style: usize,
89 buffers: [Option<Buffer>; 2],
90 has_fog: bool,
91 alpha: Option<f32>,
92 color: Option<[f32; 4]>,
93 transform: Matrix, texture: Option<asi::Texture>,
95 vertex_buffer: Buffer,
96 fans: Vec<(u32, u32)>,
97}
98
99impl base::Point for ShapeData {
100 fn point(&self) -> Vector {
101 self.transform * (vector!(0f32, 0f32, 0f32), 1f32)
103 }
104}
105
106struct ModelData {
107 vertex_buffer: Buffer,
108 vertex_count: u32,
110 fans: Vec<(u32, u32)>,
111}
112
113struct TexcoordsData {
114 vertex_buffer: Buffer,
115 vertex_count: u32,
116}
117
118struct GradientData {
119 vertex_buffer: Buffer,
120 vertex_count: u32,
121}
122
123struct TextureData {
124 t: asi::Texture,
125}
126
127pub struct Display {
129 window: ::Window,
130 context: OpenGL,
131 color: (f32, f32, f32),
132 opaque_ind: Vec<u32>,
133 alpha_ind: Vec<u32>,
134 opaque_vec: Cell<Vec<ShapeData>>,
135 alpha_vec: Cell<Vec<ShapeData>>,
136 gui_vec: Cell<Vec<ShapeData>>,
137 models: Vec<ModelData>,
138 texcoords: Vec<TexcoordsData>,
139 gradients: Vec<GradientData>,
140 textures: Vec<TextureData>,
141 styles: [Style; 6],
142 xyz: Vector,
143 rotate_xyz: Vector,
144 ar: f32,
145 projection: Matrix,
146}
147
148pub fn new() -> Result<Box<Display>, &'static str> {
149 if let Some(tuple) = OpenGLBuilder::new() {
150 let (builder, v) = tuple;
151 let window = ::Window::new(Some(v));
152
153 let context = builder.to_opengl(match window.get_connection() {
154 WindowConnection::Xcb(_, window) => {
157 unsafe {mem::transmute(window as usize)}
158 },
159 WindowConnection::Windows(_, window) => {
160 window
161 }
162 WindowConnection::Wayland => return Err(
163 "OpenGL support on Wayland is WIP"),
164 WindowConnection::DirectFB => return Err(
165 "OpenGL support on DirectFB is WIP"),
166 WindowConnection::Android => return Err(
167 "OpenGL support on Android is WIP"),
168 WindowConnection::IOS => return Err(
169 "OpenGL support on iOS is WIP"),
170 WindowConnection::AldaronsOS => return Err(
171 "AldaronsOS doesn't support OpenGL"),
172 WindowConnection::Arduino => return Err(
173 "Arduino doesn't support OpenGL"),
174 WindowConnection::Switch => return Err(
175 "Nintendo Switch doesn't support OpenGL"),
176 WindowConnection::Web => return Err(
177 "WebGL support is WIP"),
178 WindowConnection::NoOS => return Err(
179 "NoOS doesn't support OpenGL"),
180 });
181
182 context.disable(Feature::Dither);
184 context.enable(Feature::CullFace);
185 context.enable(Feature::Blend);
186 context.blend();
187
188 let style_solid = Style::new(&context,
190 SHADER_SOLID_VERT, SHADER_SOLID_FRAG);
191 let style_gradient = Style::new(&context,
192 SHADER_GRADIENT_VERT, SHADER_GRADIENT_FRAG);
193 let style_texture = Style::new(&context,
194 SHADER_TEX_VERT, SHADER_TEX_FRAG);
195 let style_faded = Style::new(&context,
196 SHADER_FADED_VERT, SHADER_TEX_FRAG);
197 let style_tinted = Style::new(&context,
198 SHADER_TEX_VERT, SHADER_TINTED_FRAG);
199 let style_complex = Style::new(&context,
200 SHADER_COMPLEX_VERT, SHADER_COMPLEX_FRAG);
201
202 let wh = window.wh();
203 let ar = wh.0 as f32 / wh.1 as f32;
204
205 let projection = base::projection(ar, 0.5 * PI);
206
207 context.viewport(wh.0, wh.1);
209
210 let mut display = self::Display {
211 window,
212 context,
213 color: (0.0, 0.0, 0.0),
214 alpha_ind: vec![],
215 opaque_ind: vec![],
216 alpha_vec: Cell::new(vec![]),
217 opaque_vec: Cell::new(vec![]),
218 gui_vec: Cell::new(vec![]),
219 models: vec![],
220 texcoords: vec![],
221 gradients: vec![],
222 textures: vec![],
223 styles: [
224 style_gradient,
225 style_texture,
226 style_faded,
227 style_tinted,
228 style_solid,
229 style_complex,
230 ],
231 xyz: vector!(0.0, 0.0, 0.0),
232 rotate_xyz: vector!(0.0, 0.0, 0.0),
233 ar,
234 projection,
235 };
236
237 use self::base::Display;
238
239 Ok(Box::new(display))
240 } else {
241 Err("Couldn't find OpenGL!")
242 }
243}
244
245fn as_mut(slf: &Cell<Vec<ShapeData>>) -> &mut Vec<ShapeData> {
246 unsafe {
247 ::std::mem::transmute(slf.as_ptr())
248 }
249}
250
251impl base::Display for Display {
252 fn color(&mut self, color: (u8, u8, u8)) {
253 self.color = (color.0 as f32 / 255.0,
254 color.1 as f32 / 255.0, color.2 as f32 / 255.0);
255 self.context.color(self.color.0, self.color.1, self.color.2);
256 }
257
258 fn input(&mut self) -> Option<base::Event> {
259 self.window.update()
260 }
261
262 fn update(&mut self) -> f32 {
263 for i in (&self.styles).iter() {
265 i.has_camera.set_int1(1);
266 }
267
268 self.context.enable(Feature::DepthTest);
270
271 base::zsort(&mut self.opaque_ind, self.opaque_vec.get_mut(),
273 true, self.xyz);
274 for shape in as_mut(&self.opaque_vec).iter() {
275 draw_shape(&self.styles[shape.style], shape);
276 }
277
278 base::zsort(&mut self.alpha_ind, &self.alpha_vec.get_mut(),
280 false, self.xyz);
281 for shape in as_mut(&self.alpha_vec).iter() {
282 draw_shape(&self.styles[shape.style], shape);
283 }
284
285 self.context.disable(Feature::DepthTest);
287
288 for shape in as_mut(&self.gui_vec).iter() {
290 draw_shape(&self.styles[shape.style], shape);
291 }
292
293 self.context.update()
294 }
295
296 fn model(&mut self, vertices: &[f32], fans: Vec<(u32, u32)>) -> Model {
297 let index = self.models.len();
299
300 let buffer = Buffer::new(&self.context);
301
302 let vertex_buffer = buffer;
303 vertex_buffer.set(vertices);
304
305
306 self.models.push(ModelData {
307 vertex_buffer, vertex_count: vertices.len() as u32 / 4,
308 fans
309 });
310
311 Model(index)
312 }
313
314 fn texture(&mut self, wh: (u16,u16), graphic: &VFrame) -> Texture {
315 let (w, h) = wh;
316 let pixels = graphic.0.as_slice();
317
318 let t = self.context.texture();
319
320 t.set(w, h, pixels);
321
322 let a = self.textures.len();
323
324 self.textures.push(TextureData { t });
325
326 Texture(a, w, h)
327 }
328
329 fn gradient(&mut self, colors: &[f32]) -> Gradient {
330 let vertex_buffer = Buffer::new(&self.context);
333 vertex_buffer.set(colors);
334
335 let a = self.gradients.len();
336
337 self.gradients.push(GradientData {
338 vertex_buffer,
339 vertex_count: colors.len() as u32 / 4,
340 });
341
342 Gradient(a)
343 }
344
345 fn texcoords(&mut self, texcoords: &[(f32, f32)]) -> TexCoords {
346 let vertex_buffer = Buffer::new(&self.context);
349 let mut buffer = vec![];
350 for i in texcoords {
351 buffer.push(i.0);
352 buffer.push(i.1);
353 buffer.push(1.0);
354 buffer.push(1.0);
355 }
356 vertex_buffer.set(buffer.as_slice());
357
358 let a = self.texcoords.len();
359
360 self.texcoords.push(TexcoordsData {
361 vertex_buffer,
362 vertex_count: texcoords.len() as u32,
363 });
364
365 TexCoords(a)
366 }
367
368 fn set_texture(&mut self, texture: &mut Texture, wh: (u16,u16),
369 graphic: &VFrame)
370 {
371 self.textures[texture.0].t.set(wh.0, wh.1,
372 graphic.0.as_slice());
373 }
374
375 #[inline(always)]
376 fn shape_solid(&mut self, model: &Model, transform: Matrix,
377 color: [f32; 4], blending: bool, fog: bool, camera: bool)
378 -> Shape
379 {
380 let shape = ShapeData {
381 style: STYLE_SOLID,
382 buffers: [None, None],
383 has_fog: fog,
384 alpha: None,
385 color: Some(color),
386 texture: None,
387 vertex_buffer: self.models[model.0].vertex_buffer.clone(),
388 transform, fans: self.models[model.0].fans.clone(),
390 };
391
392 base::new_shape(if blending {
393 let alpha_vec = self.alpha_vec.get_mut();
394 let index = alpha_vec.len() as u32;
395 alpha_vec.push(shape);
396 self.alpha_ind.push(index);
397 base::ShapeHandle::Alpha(index)
398 } else {
399 let opaque_vec = self.opaque_vec.get_mut();
400 let index = opaque_vec.len() as u32;
401 opaque_vec.push(shape);
402 self.opaque_ind.push(index);
403 base::ShapeHandle::Opaque(index)
404 })
405 }
406
407 #[inline(always)]
408 fn shape_gradient(&mut self, model: &Model, transform: Matrix,
409 colors: Gradient, blending: bool, fog: bool, camera: bool)
410 -> Shape
411 {
412 if self.models[model.0].vertex_count
414 != self.gradients[colors.0].vertex_count
415 {
416 panic!("TexCoord length doesn't match gradient length");
417 }
418
419 let shape = ShapeData {
420 style: STYLE_GRADIENT,
421 buffers: [
422 Some(self.gradients[colors.0].vertex_buffer.clone()),
423 None
424 ],
425 has_fog: fog,
426 alpha: None,
427 color: None,
428 texture: None,
429 vertex_buffer: self.models[model.0].vertex_buffer.clone(),
430 transform, fans: self.models[model.0].fans.clone(),
432 };
433
434 base::new_shape(if blending {
435 let alpha_vec = self.alpha_vec.get_mut();
436 let index = alpha_vec.len() as u32;
437 alpha_vec.push(shape);
438 self.alpha_ind.push(index);
439 base::ShapeHandle::Alpha(index)
440 } else {
441 let opaque_vec = self.opaque_vec.get_mut();
442 let index = opaque_vec.len() as u32;
443 opaque_vec.push(shape);
444 self.opaque_ind.push(index);
445 base::ShapeHandle::Opaque(index)
446 })
447 }
448
449 #[inline(always)]
450 fn shape_texture(&mut self, model: &Model, transform: Matrix,
451 texture: &Texture, tc: TexCoords, blending: bool, fog: bool,
452 camera: bool) -> Shape
453 {
454 if self.models[model.0].vertex_count
456 != self.texcoords[tc.0].vertex_count
457 {
458 panic!("TexCoord length doesn't match vertex length");
459 }
460
461 let shape = ShapeData {
462 style: STYLE_TEXTURE,
463 buffers: [
464 Some(self.texcoords[tc.0].vertex_buffer.clone()),
465 None
466 ],
467 has_fog: fog,
468 alpha: None,
469 color: None,
470 texture: Some(self.textures[texture.0].t.clone()),
471 vertex_buffer: self.models[model.0].vertex_buffer.clone(),
472 transform, fans: self.models[model.0].fans.clone(),
474 };
475
476 base::new_shape(if blending {
477 let alpha_vec = self.alpha_vec.get_mut();
478 let index = alpha_vec.len() as u32;
479 alpha_vec.push(shape);
480 self.alpha_ind.push(index);
481 base::ShapeHandle::Alpha(index)
482 } else {
483 let opaque_vec = self.opaque_vec.get_mut();
484 let index = opaque_vec.len() as u32;
485 opaque_vec.push(shape);
486 self.opaque_ind.push(index);
487 base::ShapeHandle::Opaque(index)
488 })
489 }
490
491 #[inline(always)]
492 fn shape_faded(&mut self, model: &Model, transform: Matrix,
493 texture: &Texture, tc: TexCoords, alpha: f32, fog: bool,
494 camera: bool) -> Shape
495 {
496 if self.models[model.0].vertex_count
498 != self.texcoords[tc.0].vertex_count
499 {
500 panic!("TexCoord length doesn't match vertex length");
501 }
502
503 let shape = ShapeData {
504 style: STYLE_FADED,
505 buffers: [
506 Some(self.texcoords[tc.0].vertex_buffer.clone()),
507 None
508 ],
509 has_fog: fog,
510 alpha: Some(alpha),
511 color: None,
512 texture: Some(self.textures[texture.0].t.clone()),
513 vertex_buffer: self.models[model.0].vertex_buffer.clone(),
514 transform, fans: self.models[model.0].fans.clone(),
516 };
517
518 base::new_shape({
519 let alpha_vec = self.alpha_vec.get_mut();
520 let index = alpha_vec.len() as u32;
521 alpha_vec.push(shape);
522 self.alpha_ind.push(index);
523 base::ShapeHandle::Alpha(index)
524 })
525 }
526
527 #[inline(always)]
528 fn shape_tinted(&mut self, model: &Model, transform: Matrix,
529 texture: &Texture, tc: TexCoords, tint: [f32; 4], blending: bool,
530 fog: bool, camera: bool) -> Shape
531 {
532 if self.models[model.0].vertex_count
534 != self.texcoords[tc.0].vertex_count
535 {
536 panic!("TexCoord length doesn't match vertex length");
537 }
538
539 let shape = ShapeData {
540 style: STYLE_TINTED,
541 buffers: [
542 Some(self.texcoords[tc.0].vertex_buffer.clone()),
543 None,
544 ],
545 has_fog: fog,
546 alpha: None,
547 color: Some(tint),
548 texture: Some(self.textures[texture.0].t.clone()),
549 vertex_buffer: self.models[model.0].vertex_buffer.clone(),
550 transform, fans: self.models[model.0].fans.clone(),
552 };
553
554 base::new_shape(if blending {
555 let alpha_vec = self.alpha_vec.get_mut();
556 let index = alpha_vec.len() as u32;
557 alpha_vec.push(shape);
558 self.alpha_ind.push(index);
559 base::ShapeHandle::Alpha(index)
560 } else {
561 let opaque_vec = self.opaque_vec.get_mut();
562 let index = opaque_vec.len() as u32;
563 opaque_vec.push(shape);
564 self.opaque_ind.push(index);
565 base::ShapeHandle::Opaque(index)
566 })
567 }
568
569 #[inline(always)]
570 fn shape_complex(&mut self, model: &Model, transform: Matrix,
571 texture: &Texture, tc: TexCoords, tints: Gradient,
572 blending: bool, fog: bool, camera: bool) -> Shape
573 {
574 if self.models[model.0].vertex_count
576 != self.texcoords[tc.0].vertex_count
577 {
578 panic!("TexCoord length doesn't match vertex length");
579 }
580
581 if self.models[model.0].vertex_count
583 != self.gradients[tints.0].vertex_count
584 {
585 panic!("TexCoord length doesn't match gradient length");
586 }
587
588 let shape = ShapeData {
589 style: STYLE_COMPLEX,
590 buffers: [
591 Some(self.texcoords[tc.0].vertex_buffer.clone()),
592 Some(self.gradients[tints.0].vertex_buffer.clone()),
593 ],
594 has_fog: fog,
595 alpha: None,
596 color: None,
597 texture: Some(self.textures[texture.0].t.clone()),
598 vertex_buffer: self.models[model.0].vertex_buffer.clone(),
599 transform, fans: self.models[model.0].fans.clone(),
601 };
602
603 base::new_shape(if blending {
604 let alpha_vec = self.alpha_vec.get_mut();
605 let index = alpha_vec.len() as u32;
606 alpha_vec.push(shape);
607 self.alpha_ind.push(index);
608 base::ShapeHandle::Alpha(index)
609 } else {
610 let opaque_vec = self.opaque_vec.get_mut();
611 let index = opaque_vec.len() as u32;
612 opaque_vec.push(shape);
613 self.opaque_ind.push(index);
614 base::ShapeHandle::Opaque(index)
615 })
616 }
617
618 #[inline(always)]
619 fn drop_shape(&mut self, shape: &Shape) {
620 match get_shape(&shape) {
621 ShapeHandle::Opaque(x) => {
622 let index = self.opaque_ind.iter()
623 .position(|y| *y == x).unwrap();
624 self.opaque_ind.remove(index);
625 }
626 ShapeHandle::Alpha(x) => {
627 let index = self.alpha_ind.iter()
628 .position(|y| *y == x).unwrap();
629 self.alpha_ind.remove(index);
630 }
631 }
632 }
633
634 fn transform(&self, shape: &Shape, transform: Matrix) {
635 match base::get_shape(shape) {
637 ShapeHandle::Opaque(x) => {
638 let x = x as usize; as_mut(&self.opaque_vec)[x].transform = transform;
640 }
641 ShapeHandle::Alpha(x) => {
642 let x = x as usize; as_mut(&self.alpha_vec)[x].transform = transform;
644 }
645 }
646 }
647
648 fn resize(&mut self, wh: (u16, u16)) -> () {
649 let xyz = self.xyz;
650 let rotate_xyz = self.rotate_xyz;
651
652 self.ar = wh.0 as f32 / wh.1 as f32;
653 self.context.viewport(wh.0, wh.1);
654
655 self.projection = super::base::projection(self.ar, 0.5 * PI);
656 }
657
658 fn wh(&self) -> (u16, u16) {
659 self.window.wh()
660 }
661
662 fn draw(&self, _writer: &Fn(u16, u16) -> [u8; 4]) {
663 }
665}
666
667fn draw_shape(style: &Style, shape: &ShapeData) {
668 style.matrix_uniform.set_mat4(shape.transform.into());
669
670 if !style.texpos.is_none() {
671 style.texpos.set(shape.buffers[0].as_ref().unwrap());
673 shape.texture.as_ref().unwrap().bind();
675 }
676
677 if !style.acolor.is_none() {
678 style.acolor.set(shape.buffers[0].as_ref().unwrap());
681 }
682
683 if !style.alpha.is_none() {
684 style.alpha.set_vec1(shape.alpha.unwrap());
685 }
686
687 if !style.color.is_none() {
688 style.color.set_vec4(&shape.color.unwrap());
689 }
690
691 if shape.has_fog {
692 style.has_fog.set_int1(1);
693 } else {
694 style.has_fog.set_int1(0);
695 }
696
697 style.position.set(&shape.vertex_buffer);
699 for i in shape.fans.iter() {
700 style.shader.draw_arrays(Topology::TriangleFan, i.0..i.1);
701 }
702}