]> gitweb.factorcode.org Git - factor.git/blob - extra/gpu/framebuffers/framebuffers.factor
Factor source files should not be executable
[factor.git] / extra / gpu / framebuffers / framebuffers.factor
1 ! (c)2009 Joe Groff bsd license
2 USING: accessors alien.c-types arrays byte-arrays combinators
3 destructors gpu gpu.buffers gpu.private gpu.textures
4 gpu.textures.private images kernel locals math math.rectangles opengl
5 opengl.framebuffers opengl.gl opengl.textures sequences
6 specialized-arrays ui.gadgets.worlds variants ;
7 SPECIALIZED-ARRAY: int
8 SPECIALIZED-ARRAY: uint
9 IN: gpu.framebuffers
10
11 SINGLETON: system-framebuffer
12
13 TUPLE: renderbuffer < gpu-object
14     { component-order component-order initial: RGBA }
15     { component-type component-type initial: ubyte-components }
16     { samples integer initial: 0 } ;
17
18 <PRIVATE
19
20 : get-framebuffer-int ( enum -- value )
21     GL_RENDERBUFFER swap 0 <int> [ glGetRenderbufferParameteriv ] keep *int ;
22
23 PRIVATE>
24
25 :: allocate-renderbuffer ( renderbuffer dim -- )
26     GL_RENDERBUFFER renderbuffer handle>> glBindRenderbuffer
27     GL_RENDERBUFFER
28     renderbuffer samples>> dup zero?
29     [ drop renderbuffer texture-gl-internal-format dim first2 glRenderbufferStorage ]
30     [ renderbuffer texture-gl-internal-format dim first2 glRenderbufferStorageMultisample ]
31     if ;
32
33 :: renderbuffer-dim ( renderbuffer -- dim )
34     GL_RENDERBUFFER renderbuffer handle>> glBindRenderbuffer
35     GL_RENDERBUFFER_WIDTH get-framebuffer-int
36     GL_RENDERBUFFER_HEIGHT get-framebuffer-int 2array ;
37
38 : <renderbuffer> ( component-order component-type samples dim -- renderbuffer )
39     [ [ gen-renderbuffer ] 3dip renderbuffer boa dup ] dip
40     [ allocate-renderbuffer ] [ drop ] if*
41     window-resource ;
42
43 M: renderbuffer dispose
44     [ [ delete-renderbuffer ] when* f ] change-handle drop ;
45
46 TUPLE: texture-1d-attachment
47     { texture texture-1d-data-target read-only initial: T{ texture-1d } }
48     { level integer read-only } ;
49
50 C: <texture-1d-attachment> texture-1d-attachment
51
52 TUPLE: texture-2d-attachment
53     { texture texture-2d-data-target read-only initial: T{ texture-2d } }
54     { level integer read-only } ;
55
56 C: <texture-2d-attachment> texture-2d-attachment
57
58 TUPLE: texture-3d-attachment
59     { texture texture-3d read-only initial: T{ texture-3d } }
60     { z-offset integer read-only }
61     { level integer read-only } ;
62
63 C: <texture-3d-attachment> texture-3d-attachment
64
65 TUPLE: texture-layer-attachment
66     { texture texture-3d-data-target read-only initial: T{ texture-3d } }
67     { layer integer read-only }
68     { level integer read-only } ;
69
70 C: <texture-layer-attachment> texture-layer-attachment
71
72 UNION: texture-attachment
73     texture-1d-attachment texture-2d-attachment texture-3d-attachment texture-layer-attachment ;
74
75 M: texture-attachment dispose texture>> dispose ;
76
77 UNION: framebuffer-attachment renderbuffer texture-attachment ;
78 UNION: ?framebuffer-attachment framebuffer-attachment POSTPONE: f ;
79
80 GENERIC: attachment-object ( attachment -- object )
81 M: renderbuffer attachment-object ;
82 M: texture-attachment attachment-object texture>> texture-object ;
83
84 TUPLE: framebuffer < gpu-object
85     { color-attachments array read-only }
86     { depth-attachment ?framebuffer-attachment read-only initial: f }
87     { stencil-attachment ?framebuffer-attachment read-only initial: f } ;
88
89 UNION: any-framebuffer system-framebuffer framebuffer ;
90
91 VARIANT: framebuffer-attachment-side
92     left-side right-side ;
93
94 VARIANT: framebuffer-attachment-face
95     back-face front-face ;
96
97 UNION: ?framebuffer-attachment-side framebuffer-attachment-side POSTPONE: f ;
98 UNION: ?framebuffer-attachment-face framebuffer-attachment-face POSTPONE: f ;
99
100 VARIANT: color-attachment-ref
101     default-attachment
102     system-attachment: {
103         { side ?framebuffer-attachment-side initial: f }
104         { face ?framebuffer-attachment-face initial: back-face }
105     }
106     color-attachment: { { index integer } } ;
107
108 VARIANT: non-color-attachment-ref
109     depth-attachment
110     stencil-attachment ;
111
112 UNION: attachment-ref
113     color-attachment-ref
114     non-color-attachment-ref
115     POSTPONE: f ;
116
117 TUPLE: framebuffer-rect
118     { framebuffer any-framebuffer read-only initial: system-framebuffer }
119     { attachment color-attachment-ref read-only initial: default-attachment }
120     { rect rect read-only } ;
121
122 C: <framebuffer-rect> framebuffer-rect
123
124 : framebuffer-attachment-at ( framebuffer attachment-ref -- attachment )
125     {
126         { default-attachment [ color-attachments>> first ] }
127         { color-attachment [ swap color-attachments>> nth ] }
128         { depth-attachment [ depth-attachment>> ] }
129         { stencil-attachment [ stencil-attachment>> ] }
130     } match ;
131
132 <PRIVATE
133
134 GENERIC: framebuffer-handle ( framebuffer -- handle )
135
136 M: system-framebuffer framebuffer-handle drop 0 ;
137 M: framebuffer framebuffer-handle handle>> ;
138
139 GENERIC# allocate-framebuffer-attachment 1 ( framebuffer-attachment dim -- )
140
141 M: texture-attachment allocate-framebuffer-attachment
142     [ [ texture>> ] [ level>> ] bi ] dip f allocate-texture ;
143 M: renderbuffer allocate-framebuffer-attachment
144     allocate-renderbuffer ;
145
146 GENERIC: framebuffer-attachment-dim ( framebuffer-attachment -- dim )
147
148 M: texture-attachment framebuffer-attachment-dim
149     [ texture>> ] [ level>> ] bi texture-dim
150     dup number? [ 1 2array ] [ 2 head ] if ;
151
152 M: renderbuffer framebuffer-attachment-dim
153     renderbuffer-dim ;
154
155 : each-attachment ( framebuffer quot: ( attachment -- ) -- )
156     [ [ color-attachments>> ] dip each ]
157     [ swap depth-attachment>>   [ swap call ] [ drop ] if* ]
158     [ swap stencil-attachment>> [ swap call ] [ drop ] if* ] 2tri ; inline
159
160 :: each-attachment-target ( framebuffer quot: ( attachment-target attachment -- ) -- )
161     framebuffer color-attachments>>
162     [| attachment n | n GL_COLOR_ATTACHMENT0 + attachment quot call ] each-index
163     framebuffer depth-attachment>>
164     [| attachment | GL_DEPTH_ATTACHMENT attachment quot call ] when*
165     framebuffer stencil-attachment>>
166     [| attachment | GL_STENCIL_ATTACHMENT attachment quot call ] when* ; inline
167
168 GENERIC: bind-framebuffer-attachment ( attachment-target attachment -- )
169
170 M:: renderbuffer bind-framebuffer-attachment ( attachment-target renderbuffer -- )
171     GL_DRAW_FRAMEBUFFER attachment-target
172     GL_RENDERBUFFER renderbuffer handle>>
173     glFramebufferRenderbuffer ;
174
175 M:: texture-1d-attachment bind-framebuffer-attachment ( attachment-target texture-attachment -- )
176     GL_DRAW_FRAMEBUFFER attachment-target
177     texture-attachment [ texture>> [ texture-data-gl-target ] [ texture-object handle>> ] bi ] [ level>> ] bi
178     glFramebufferTexture1D ;
179
180 M:: texture-2d-attachment bind-framebuffer-attachment ( attachment-target texture-attachment -- )
181     GL_DRAW_FRAMEBUFFER attachment-target
182     texture-attachment [ texture>> [ texture-data-gl-target ] [ texture-object handle>> ] bi ] [ level>> ] bi
183     glFramebufferTexture2D ;
184
185 M:: texture-3d-attachment bind-framebuffer-attachment ( attachment-target texture-attachment -- )
186     GL_DRAW_FRAMEBUFFER attachment-target
187     texture-attachment
188     [ texture>> [ texture-data-gl-target ] [ texture-object handle>> ] bi ]
189     [ level>> ] [ z-offset>> ] tri
190     glFramebufferTexture3D ;
191
192 M:: texture-layer-attachment bind-framebuffer-attachment ( attachment-target texture-attachment -- )
193     GL_DRAW_FRAMEBUFFER attachment-target
194     texture-attachment
195     [ texture>> texture-object handle>> ]
196     [ level>> ] [ layer>> ] tri
197     glFramebufferTextureLayer ;
198
199 GENERIC: (default-gl-attachment) ( framebuffer -- gl-attachment )
200 GENERIC: (default-attachment-type) ( framebuffer -- type )
201 GENERIC: (default-attachment-image-type) ( framebuffer -- order type )
202
203 M: system-framebuffer (default-gl-attachment)
204     drop GL_BACK ;
205 M: framebuffer (default-gl-attachment)
206     drop GL_COLOR_ATTACHMENT0 ;
207
208 SYMBOLS: float-type int-type uint-type ;
209
210 : (color-attachment-type) ( framebuffer index -- type )
211     swap color-attachments>> nth attachment-object component-type>> {
212         { [ dup signed-unnormalized-integer-components?   ] [ drop int-type  ] }
213         { [ dup unsigned-unnormalized-integer-components? ] [ drop uint-type ] }
214         [ drop float-type ]
215     } cond ;
216
217 M: system-framebuffer (default-attachment-type)
218     drop float-type ;
219 M: framebuffer (default-attachment-type)
220     0 (color-attachment-type) ;
221
222 M: system-framebuffer (default-attachment-image-type) ( framebuffer -- order type )
223     drop RGBA ubyte-components ;
224 M: framebuffer (default-attachment-image-type) ( framebuffer -- order type )
225     color-attachments>> first attachment-object
226     [ component-order>> ] [ component-type>> ] bi ;
227
228 : gl-system-attachment ( side face -- attachment )
229     2array {
230         { { f          f          } [ GL_FRONT_AND_BACK ] }
231         { { f          front-face } [ GL_FRONT          ] }
232         { { f          back-face  } [ GL_BACK           ] }
233         { { left-side  f          } [ GL_LEFT           ] }
234         { { left-side  front-face } [ GL_FRONT_LEFT     ] }
235         { { left-side  back-face  } [ GL_BACK_LEFT      ] }
236         { { right-side f          } [ GL_RIGHT          ] }
237         { { right-side front-face } [ GL_FRONT_RIGHT    ] }
238         { { right-side back-face  } [ GL_BACK_RIGHT     ] }
239     } case ;
240
241 : gl-attachment ( framebuffer attachment-ref -- gl-attachment )
242     [ {
243         { depth-attachment [ GL_DEPTH_ATTACHMENT ] }
244         { stencil-attachment [ GL_STENCIL_ATTACHMENT ] }
245         { color-attachment [ GL_COLOR_ATTACHMENT0 + ] }
246         { system-attachment [ gl-system-attachment ] }
247         { default-attachment [ dup (default-gl-attachment) ] }
248     } match ] [ GL_NONE ] if* nip ;
249
250 : color-attachment-image-type ( framebuffer attachment-ref -- order type )
251     {
252         { color-attachment [
253             swap color-attachments>> nth
254             attachment-object [ component-order>> ] [ component-type>> ] bi
255         ] }
256         { system-attachment [ 3drop RGBA ubyte-components ] }
257         { default-attachment [ (default-attachment-image-type) ] }
258     } match ;
259
260 : framebuffer-rect-image-type ( framebuffer-rect -- order type )
261     [ framebuffer>> ] [ attachment>> ] bi color-attachment-image-type ;
262
263 HOOK: (clear-integer-color-attachment) gpu-api ( type value -- )
264
265 M: opengl-2 (clear-integer-color-attachment)
266     4 0 pad-tail first4
267     swap {
268         { int-type [ glClearColorIiEXT ] }
269         { uint-type [ glClearColorIuiEXT ] }
270     } case GL_COLOR_BUFFER_BIT glClear ;
271
272 M: opengl-3 (clear-integer-color-attachment)
273     [ GL_COLOR 0 ] dip 4 0 pad-tail
274     swap {
275         { int-type  [ >int-array  glClearBufferiv  ] }
276         { uint-type [ >uint-array glClearBufferuiv ] }
277     } case ;
278
279 :: (clear-color-attachment) ( type attachment value -- )
280     attachment glDrawBuffer
281     type float-type =
282     [ value 4 value last pad-tail first4 glClearColor GL_COLOR_BUFFER_BIT glClear ]
283     [ type value (clear-integer-color-attachment) ] if ;
284
285 : framebuffer-rect-size ( framebuffer-rect -- size )
286     [ rect>> dim>> product ]
287     [ framebuffer-rect-image-type (bytes-per-pixel) ] bi * ;
288
289 PRIVATE>
290
291 : <full-framebuffer-rect> ( framebuffer attachment -- framebuffer-rect )
292     2dup framebuffer-attachment-at
293     { 0 0 } swap framebuffer-attachment-dim <rect>
294     <framebuffer-rect> ;
295
296 : resize-framebuffer ( framebuffer dim -- )
297     [ allocate-framebuffer-attachment ] curry each-attachment ;
298
299 :: attach-framebuffer-attachments ( framebuffer -- )
300     GL_DRAW_FRAMEBUFFER framebuffer handle>> glBindFramebuffer
301     framebuffer [ bind-framebuffer-attachment ] each-attachment-target ;
302
303 M: framebuffer dispose
304     [ [ delete-framebuffer ] when* f ] change-handle drop ;
305
306 : dispose-framebuffer-attachments ( framebuffer -- )
307     [ [ dispose ] when* ] each-attachment ;
308
309 : <framebuffer> ( color-attachments depth-attachment stencil-attachment dim -- framebuffer )
310     [ [ 0 ] 3dip framebuffer boa dup ] dip
311     [ resize-framebuffer ] [ drop ] if*
312     gen-framebuffer >>handle
313     dup attach-framebuffer-attachments
314     window-resource ;
315
316 :: clear-framebuffer-attachment ( framebuffer attachment-ref value -- )
317     GL_DRAW_FRAMEBUFFER framebuffer framebuffer-handle glBindFramebuffer
318     attachment-ref {
319         { system-attachment [| side face |
320             float-type
321             side face gl-system-attachment
322             value (clear-color-attachment)
323         ] }
324         { color-attachment [| i |
325             framebuffer i (color-attachment-type)
326             GL_COLOR_ATTACHMENT0 i +
327             value (clear-color-attachment)
328         ] }
329         { default-attachment [
330             framebuffer [ (default-attachment-type) ] [ (default-gl-attachment) ] bi
331             value (clear-color-attachment)
332         ] }
333         { depth-attachment   [ value glClearDepth GL_DEPTH_BUFFER_BIT glClear ] }
334         { stencil-attachment [ value glClearStencil GL_STENCIL_BUFFER_BIT glClear ] }
335     } match ;
336
337 : clear-framebuffer ( framebuffer alist -- )
338     [ first2 clear-framebuffer-attachment ] with each ;
339
340 :: read-framebuffer-to ( framebuffer-rect gpu-data-ptr -- )
341     GL_READ_FRAMEBUFFER framebuffer-rect framebuffer>> framebuffer-handle glBindFramebuffer
342     framebuffer-rect [ framebuffer>> ] [ attachment>> ] bi gl-attachment glReadBuffer
343     framebuffer-rect rect>> [ loc>> first2 ] [ dim>> first2 ] bi 
344     framebuffer-rect framebuffer-rect-image-type image-data-format
345     gpu-data-ptr pixel-pack-buffer [ glReadPixels ] with-gpu-data-ptr ;
346     
347 : read-framebuffer ( framebuffer-rect -- byte-array )
348     dup framebuffer-rect-size <byte-array> [ read-framebuffer-to ] keep ;
349
350 : read-framebuffer-image ( framebuffer-rect -- image )
351     [ <image> ] dip {
352         [ rect>> dim>> >>dim ]
353         [
354             framebuffer-rect-image-type
355             [ >>component-order ] [ >>component-type ] bi*
356         ]
357         [ read-framebuffer >>bitmap ] 
358     } cleave ;
359
360 :: copy-framebuffer ( to-fb-rect from-fb-rect depth? stencil? filter -- )
361     GL_DRAW_FRAMEBUFFER to-fb-rect framebuffer>> framebuffer-handle glBindFramebuffer
362     to-fb-rect [ framebuffer>> ] [ attachment>> ] bi gl-attachment glDrawBuffer
363     GL_READ_FRAMEBUFFER from-fb-rect framebuffer>> framebuffer-handle glBindFramebuffer
364     from-fb-rect [ framebuffer>> ] [ attachment>> ] bi gl-attachment glReadBuffer
365     to-fb-rect attachment>> [ GL_COLOR_BUFFER_BIT ] [ 0 ] if
366     depth?   [ GL_DEPTH_BUFFER_BIT   ] [ 0 ] if bitor
367     stencil? [ GL_STENCIL_BUFFER_BIT ] [ 0 ] if bitor :> mask
368     
369     from-fb-rect rect>> rect-extent [ first2 ] bi@
370     to-fb-rect   rect>> rect-extent [ first2 ] bi@
371     mask filter gl-mag-filter glBlitFramebuffer ;
372