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 ;
8 SPECIALIZED-ARRAY: uint
11 SINGLETON: system-framebuffer
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 } ;
20 : get-framebuffer-int ( enum -- value )
21 GL_RENDERBUFFER swap 0 <int> [ glGetRenderbufferParameteriv ] keep *int ;
25 :: allocate-renderbuffer ( renderbuffer dim -- )
26 GL_RENDERBUFFER renderbuffer handle>> glBindRenderbuffer
28 renderbuffer samples>> dup zero?
29 [ drop renderbuffer texture-gl-internal-format dim first2 glRenderbufferStorage ]
30 [ renderbuffer texture-gl-internal-format dim first2 glRenderbufferStorageMultisample ]
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 ;
38 : <renderbuffer> ( component-order component-type samples dim -- renderbuffer )
39 [ [ gen-renderbuffer ] 3dip renderbuffer boa dup ] dip
40 [ allocate-renderbuffer ] [ drop ] if*
43 M: renderbuffer dispose
44 [ [ delete-renderbuffer ] when* f ] change-handle drop ;
46 TUPLE: texture-1d-attachment
47 { texture texture-1d-data-target read-only initial: T{ texture-1d } }
48 { level integer read-only } ;
50 C: <texture-1d-attachment> texture-1d-attachment
52 TUPLE: texture-2d-attachment
53 { texture texture-2d-data-target read-only initial: T{ texture-2d } }
54 { level integer read-only } ;
56 C: <texture-2d-attachment> texture-2d-attachment
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 } ;
63 C: <texture-3d-attachment> texture-3d-attachment
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 } ;
70 C: <texture-layer-attachment> texture-layer-attachment
72 UNION: texture-attachment
73 texture-1d-attachment texture-2d-attachment texture-3d-attachment texture-layer-attachment ;
75 M: texture-attachment dispose texture>> dispose ;
77 UNION: framebuffer-attachment renderbuffer texture-attachment ;
78 UNION: ?framebuffer-attachment framebuffer-attachment POSTPONE: f ;
80 GENERIC: attachment-object ( attachment -- object )
81 M: renderbuffer attachment-object ;
82 M: texture-attachment attachment-object texture>> texture-object ;
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 } ;
89 UNION: any-framebuffer system-framebuffer framebuffer ;
91 VARIANT: framebuffer-attachment-side
92 left-side right-side ;
94 VARIANT: framebuffer-attachment-face
95 back-face front-face ;
97 UNION: ?framebuffer-attachment-side framebuffer-attachment-side POSTPONE: f ;
98 UNION: ?framebuffer-attachment-face framebuffer-attachment-face POSTPONE: f ;
100 VARIANT: color-attachment-ref
103 { side ?framebuffer-attachment-side initial: f }
104 { face ?framebuffer-attachment-face initial: back-face }
106 color-attachment: { { index integer } } ;
108 VARIANT: non-color-attachment-ref
112 UNION: attachment-ref
114 non-color-attachment-ref
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 } ;
122 C: <framebuffer-rect> framebuffer-rect
124 : framebuffer-attachment-at ( framebuffer attachment-ref -- attachment )
126 { default-attachment [ color-attachments>> first ] }
127 { color-attachment [ swap color-attachments>> nth ] }
128 { depth-attachment [ depth-attachment>> ] }
129 { stencil-attachment [ stencil-attachment>> ] }
134 GENERIC: framebuffer-handle ( framebuffer -- handle )
136 M: system-framebuffer framebuffer-handle drop 0 ;
137 M: framebuffer framebuffer-handle handle>> ;
139 GENERIC# allocate-framebuffer-attachment 1 ( framebuffer-attachment dim -- )
141 M: texture-attachment allocate-framebuffer-attachment
142 [ [ texture>> ] [ level>> ] bi ] dip f allocate-texture ;
143 M: renderbuffer allocate-framebuffer-attachment
144 allocate-renderbuffer ;
146 GENERIC: framebuffer-attachment-dim ( framebuffer-attachment -- dim )
148 M: texture-attachment framebuffer-attachment-dim
149 [ texture>> ] [ level>> ] bi texture-dim
150 dup number? [ 1 2array ] [ 2 head ] if ;
152 M: renderbuffer framebuffer-attachment-dim
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
160 : each-attachment-target ( framebuffer quot: ( attachment-target attachment -- ) -- )
161 [ [ color-attachments>> ] dip [ GL_COLOR_ATTACHMENT0 + swap ] prepose each-index ]
162 [ swap depth-attachment>> [ GL_DEPTH_ATTACHMENT spin call ] [ drop ] if* ]
163 [ swap stencil-attachment>> [ GL_STENCIL_ATTACHMENT spin call ] [ drop ] if* ] 2tri ; inline
165 GENERIC: bind-framebuffer-attachment ( attachment-target attachment -- )
167 M:: renderbuffer bind-framebuffer-attachment ( attachment-target renderbuffer -- )
168 GL_DRAW_FRAMEBUFFER attachment-target
169 GL_RENDERBUFFER renderbuffer handle>>
170 glFramebufferRenderbuffer ;
172 M:: texture-1d-attachment bind-framebuffer-attachment ( attachment-target texture-attachment -- )
173 GL_DRAW_FRAMEBUFFER attachment-target
174 texture-attachment [ texture>> [ texture-data-gl-target ] [ texture-object handle>> ] bi ] [ level>> ] bi
175 glFramebufferTexture1D ;
177 M:: texture-2d-attachment bind-framebuffer-attachment ( attachment-target texture-attachment -- )
178 GL_DRAW_FRAMEBUFFER attachment-target
179 texture-attachment [ texture>> [ texture-data-gl-target ] [ texture-object handle>> ] bi ] [ level>> ] bi
180 glFramebufferTexture2D ;
182 M:: texture-3d-attachment bind-framebuffer-attachment ( attachment-target texture-attachment -- )
183 GL_DRAW_FRAMEBUFFER attachment-target
185 [ texture>> [ texture-data-gl-target ] [ texture-object handle>> ] bi ]
186 [ level>> ] [ z-offset>> ] tri
187 glFramebufferTexture3D ;
189 M:: texture-layer-attachment bind-framebuffer-attachment ( attachment-target texture-attachment -- )
190 GL_DRAW_FRAMEBUFFER attachment-target
192 [ texture>> texture-object handle>> ]
193 [ level>> ] [ layer>> ] tri
194 glFramebufferTextureLayer ;
196 GENERIC: (default-gl-attachment) ( framebuffer -- gl-attachment )
197 GENERIC: (default-attachment-type) ( framebuffer -- type )
198 GENERIC: (default-attachment-image-type) ( framebuffer -- order type )
200 M: system-framebuffer (default-gl-attachment)
202 M: framebuffer (default-gl-attachment)
203 drop GL_COLOR_ATTACHMENT0 ;
205 SYMBOLS: float-type int-type uint-type ;
207 : (color-attachment-type) ( framebuffer index -- type )
208 swap color-attachments>> nth attachment-object component-type>> {
209 { [ dup signed-unnormalized-integer-components? ] [ drop int-type ] }
210 { [ dup unsigned-unnormalized-integer-components? ] [ drop uint-type ] }
214 M: system-framebuffer (default-attachment-type)
216 M: framebuffer (default-attachment-type)
217 0 (color-attachment-type) ;
219 M: system-framebuffer (default-attachment-image-type) ( framebuffer -- order type )
220 drop RGBA ubyte-components ;
221 M: framebuffer (default-attachment-image-type) ( framebuffer -- order type )
222 color-attachments>> first attachment-object
223 [ component-order>> ] [ component-type>> ] bi ;
225 : gl-system-attachment ( side face -- attachment )
227 { { f f } [ GL_FRONT_AND_BACK ] }
228 { { f front-face } [ GL_FRONT ] }
229 { { f back-face } [ GL_BACK ] }
230 { { left-side f } [ GL_LEFT ] }
231 { { left-side front-face } [ GL_FRONT_LEFT ] }
232 { { left-side back-face } [ GL_BACK_LEFT ] }
233 { { right-side f } [ GL_RIGHT ] }
234 { { right-side front-face } [ GL_FRONT_RIGHT ] }
235 { { right-side back-face } [ GL_BACK_RIGHT ] }
238 : gl-attachment ( framebuffer attachment-ref -- gl-attachment )
240 { depth-attachment [ GL_DEPTH_ATTACHMENT ] }
241 { stencil-attachment [ GL_STENCIL_ATTACHMENT ] }
242 { color-attachment [ GL_COLOR_ATTACHMENT0 + ] }
243 { system-attachment [ gl-system-attachment ] }
244 { default-attachment [ dup (default-gl-attachment) ] }
245 } match ] [ GL_NONE ] if* nip ;
247 : color-attachment-image-type ( framebuffer attachment-ref -- order type )
250 swap color-attachments>> nth
251 attachment-object [ component-order>> ] [ component-type>> ] bi
253 { system-attachment [ 3drop RGBA ubyte-components ] }
254 { default-attachment [ (default-attachment-image-type) ] }
257 : framebuffer-rect-image-type ( framebuffer-rect -- order type )
258 [ framebuffer>> ] [ attachment>> ] bi color-attachment-image-type ;
260 HOOK: (clear-integer-color-attachment) gpu-api ( type value -- )
262 M: opengl-2 (clear-integer-color-attachment)
265 { int-type [ glClearColorIiEXT ] }
266 { uint-type [ glClearColorIuiEXT ] }
267 } case GL_COLOR_BUFFER_BIT glClear ;
269 M: opengl-3 (clear-integer-color-attachment)
270 [ GL_COLOR 0 ] dip 4 0 pad-tail
272 { int-type [ >int-array glClearBufferiv ] }
273 { uint-type [ >uint-array glClearBufferuiv ] }
276 :: (clear-color-attachment) ( type attachment value -- )
277 attachment glDrawBuffer
279 [ value 4 value last pad-tail first4 glClearColor GL_COLOR_BUFFER_BIT glClear ]
280 [ type value (clear-integer-color-attachment) ] if ;
282 : framebuffer-rect-size ( framebuffer-rect -- size )
283 [ rect>> dim>> product ]
284 [ framebuffer-rect-image-type (bytes-per-pixel) ] bi * ;
288 : <full-framebuffer-rect> ( framebuffer attachment -- framebuffer-rect )
289 2dup framebuffer-attachment-at
290 { 0 0 } swap framebuffer-attachment-dim <rect>
293 : resize-framebuffer ( framebuffer dim -- )
294 [ allocate-framebuffer-attachment ] curry each-attachment ;
296 :: attach-framebuffer-attachments ( framebuffer -- )
297 GL_DRAW_FRAMEBUFFER framebuffer handle>> glBindFramebuffer
298 framebuffer [ bind-framebuffer-attachment ] each-attachment-target ;
300 M: framebuffer dispose
301 [ [ delete-framebuffer ] when* f ] change-handle drop ;
303 : dispose-framebuffer-attachments ( framebuffer -- )
304 [ [ dispose ] when* ] each-attachment ;
306 : <framebuffer> ( color-attachments depth-attachment stencil-attachment dim -- framebuffer )
307 [ [ 0 ] 3dip framebuffer boa dup ] dip
308 [ resize-framebuffer ] [ drop ] if*
309 gen-framebuffer >>handle
310 dup attach-framebuffer-attachments
313 :: clear-framebuffer-attachment ( framebuffer attachment-ref value -- )
314 GL_DRAW_FRAMEBUFFER framebuffer framebuffer-handle glBindFramebuffer
316 { system-attachment [| side face |
318 side face gl-system-attachment
319 value (clear-color-attachment)
321 { color-attachment [| i |
322 framebuffer i (color-attachment-type)
323 GL_COLOR_ATTACHMENT0 i +
324 value (clear-color-attachment)
326 { default-attachment [
327 framebuffer [ (default-attachment-type) ] [ (default-gl-attachment) ] bi
328 value (clear-color-attachment)
330 { depth-attachment [ value glClearDepth GL_DEPTH_BUFFER_BIT glClear ] }
331 { stencil-attachment [ value glClearStencil GL_STENCIL_BUFFER_BIT glClear ] }
334 : clear-framebuffer ( framebuffer alist -- )
335 [ first2 clear-framebuffer-attachment ] with each ;
337 :: read-framebuffer-to ( framebuffer-rect gpu-data-ptr -- )
338 GL_READ_FRAMEBUFFER framebuffer-rect framebuffer>> framebuffer-handle glBindFramebuffer
339 framebuffer-rect [ framebuffer>> ] [ attachment>> ] bi gl-attachment glReadBuffer
340 framebuffer-rect rect>> [ loc>> first2 ] [ dim>> first2 ] bi
341 framebuffer-rect framebuffer-rect-image-type image-data-format
342 gpu-data-ptr pixel-pack-buffer [ glReadPixels ] with-gpu-data-ptr ;
344 : read-framebuffer ( framebuffer-rect -- byte-array )
345 dup framebuffer-rect-size <byte-array> [ read-framebuffer-to ] keep ;
347 : read-framebuffer-image ( framebuffer-rect -- image )
349 [ rect>> dim>> >>dim ]
351 framebuffer-rect-image-type
352 [ >>component-order ] [ >>component-type ] bi*
354 [ read-framebuffer >>bitmap ]
357 :: copy-framebuffer ( to-fb-rect from-fb-rect depth? stencil? filter -- )
358 GL_DRAW_FRAMEBUFFER to-fb-rect framebuffer>> framebuffer-handle glBindFramebuffer
359 to-fb-rect [ framebuffer>> ] [ attachment>> ] bi gl-attachment glDrawBuffer
360 GL_READ_FRAMEBUFFER from-fb-rect framebuffer>> framebuffer-handle glBindFramebuffer
361 from-fb-rect [ framebuffer>> ] [ attachment>> ] bi gl-attachment glReadBuffer
362 to-fb-rect attachment>> [ GL_COLOR_BUFFER_BIT ] [ 0 ] if
363 depth? [ GL_DEPTH_BUFFER_BIT ] [ 0 ] if bitor
364 stencil? [ GL_STENCIL_BUFFER_BIT ] [ 0 ] if bitor :> mask
366 from-fb-rect rect>> rect-extent [ first2 ] bi@
367 to-fb-rect rect>> rect-extent [ first2 ] bi@
368 mask filter gl-mag-filter glBlitFramebuffer ;