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