1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
use super::{
Texture,
TextureFilter,
};
use std::{
marker::PhantomData,
mem::MaybeUninit,
};
use gl::{
// constants
READ_FRAMEBUFFER,
DRAW_FRAMEBUFFER,
FRAMEBUFFER,
COLOR_ATTACHMENT0,
DEPTH_ATTACHMENT,
STENCIL_ATTACHMENT,
// functions
GenFramebuffers,
BindFramebuffer,
FramebufferTexture2D,
BlitFramebuffer,
DeleteFramebuffers,
};
#[repr(u32)]
#[derive(Clone,Copy,Debug)]
pub enum FrameBufferTarget{
Read=READ_FRAMEBUFFER,
Draw=DRAW_FRAMEBUFFER,
FrameBuffer=FRAMEBUFFER,
}
#[repr(u32)]
#[derive(Clone,Copy,Debug)]
pub enum FrameBufferAttachment{
ColourAttachment0=COLOR_ATTACHMENT0,
DepthAttachment=DEPTH_ATTACHMENT,
StencilAttachment=STENCIL_ATTACHMENT,
}
/// Since OpenGL 3.0.
pub struct FrameBuffer<'a>{
id:u32,
texture:&'a Texture,
}
impl<'a> FrameBuffer<'a>{
pub unsafe fn new_2d(target:FrameBufferTarget,attachement:FrameBufferAttachment,texture:&'a Texture,texture_target:u32)->FrameBuffer<'a>{
let mut id:u32=MaybeUninit::uninit().assume_init();
GenFramebuffers(1,&mut id as *mut u32);
BindFramebuffer(target as u32,id);
texture.bind(texture_target);
FramebufferTexture2D(target as u32,attachement as u32,texture_target,texture.id(),0);
BindFramebuffer(target as u32,0);
Self{
id,
texture,
}
}
#[inline(always)]
pub fn id(&self)->u32{
self.id
}
pub fn texture(&self)->&Texture{
self.texture
}
}
impl<'a> FrameBuffer<'a>{
pub unsafe fn bind(&'a self,target:FrameBufferTarget)->BoundFrameBuffer<'a>{
BindFramebuffer(target as u32,self.id);
BoundFrameBuffer{
target:target as u32,
marker:PhantomData,
}
}
pub unsafe fn unbind(&self,target:FrameBufferTarget){
BindFramebuffer(target as u32,0);
}
// pub unsafe fn write(&self,target:u32,offset:usize,items:&[I]){
// BindFramebuffer(target,self.id);
// let data_ref=(items as *const [I]) as *const core::ffi::c_void;
// BufferSubData(target,(offset*size_of::<I>()),(items.len()*size_of::<I>()),data_ref)
// }
// /// Offset in bytes.
// pub unsafe fn write_value(&self,target:u32,offset:usize,value:&I){
// BindFramebuffer(target,self.id);
// let data_ref=(value as *const I) as *const core::ffi::c_void;
// BufferSubData(target,offset,size_of::<I>(),data_ref)
// }
/// Offset in bytes.
pub unsafe fn write_frame_buffer(&self,[x1,y1,x2,y2]:[i32;4],frame_buffer:&FrameBuffer,[src_x1,src_y1,src_x2,src_y2]:[i32;4],mask:u32,filter:TextureFilter){
self.bind(FrameBufferTarget::Draw);
frame_buffer.bind(FrameBufferTarget::Read);
BlitFramebuffer(src_x1,src_y1,src_x2,src_y2,x1,y1,x2,y2,mask,filter as u32);
BindFramebuffer(DRAW_FRAMEBUFFER,0);
BindFramebuffer(READ_FRAMEBUFFER,0);
}
pub unsafe fn write_screen_buffer(&self,[x1,y1,x2,y2]:[i32;4],[src_x1,src_y1,src_x2,src_y2]:[i32;4],mask:u32,filter:TextureFilter){
self.bind(FrameBufferTarget::Draw);
BlitFramebuffer(src_x1,src_y1,src_x2,src_y2,x1,y1,x2,y2,mask,filter as u32);
BindFramebuffer(DRAW_FRAMEBUFFER,0);
}
// pub unsafe fn rewrite(&self,target:u32,items:&[I]){
// BindFramebuffer(target,self.id);
// let data_ref=(items as *const [I]) as *const core::ffi::c_void;
// BufferData(target,(items.len()*size_of::<I>()),data_ref,DYNAMIC_DRAW);
// }
}
impl<'a> Drop for FrameBuffer<'a>{
fn drop(&mut self){
unsafe{
DeleteFramebuffers(1,&self.id as *const u32);
}
}
}
pub struct BoundFrameBuffer<'a>{
target:u32,
marker:PhantomData<&'a FrameBuffer<'a>>,
}
impl<'a> BoundFrameBuffer<'a>{
// pub unsafe fn write(&self,offset:usize,items:&[I]){
// let data_ref=(items as *const [I]) as *const core::ffi::c_void;
// BufferSubData(self.target,(offset*size_of::<I>()),(items.len()*size_of::<I>()),data_ref)
// }
// pub unsafe fn rewrite(&self,items:&[I]){
// let data_ref=(items as *const [I]) as *const core::ffi::c_void;
// BufferData(self.target,(items.len()*size_of::<I>()),data_ref,DYNAMIC_DRAW);
// }
}