PageRenderTime 45ms CodeModel.GetById 5ms app.highlight 35ms RepoModel.GetById 1ms app.codeStats 0ms

/extra/gpu/framebuffers/framebuffers.factor

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