]> gitweb.factorcode.org Git - factor.git/blob - extra/gpu/state/state.factor
Update some copyright headers to follow the current convention
[factor.git] / extra / gpu / state / state.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 gpu kernel literals math math.rectangles opengl
5 opengl.gl sequences typed variants specialized-arrays ;
6 QUALIFIED-WITH: alien.c-types c
7 FROM: math => float ;
8 SPECIALIZED-ARRAY: c:int
9 SPECIALIZED-ARRAY: c:float
10 IN: gpu.state
11
12 TUPLE: viewport-state
13     { rect rect read-only } ;
14 C: <viewport-state> viewport-state
15
16 TUPLE: scissor-state
17     { rect maybe{ rect } read-only } ;
18 C: <scissor-state> scissor-state
19
20 TUPLE: multisample-state
21     { multisample? boolean read-only }
22     { sample-alpha-to-coverage? boolean read-only }
23     { sample-alpha-to-one? boolean read-only }
24     { sample-coverage maybe{ float } read-only }
25     { invert-sample-coverage? boolean read-only } ;
26 C: <multisample-state> multisample-state
27
28 VARIANT: comparison
29     cmp-never cmp-always
30     cmp-less cmp-less-equal cmp-equal
31     cmp-greater-equal cmp-greater cmp-not-equal ;
32 VARIANT: stencil-op
33     op-keep op-zero
34     op-replace op-invert
35     op-inc-sat op-dec-sat
36     op-inc-wrap op-dec-wrap ;
37
38 TUPLE: stencil-mode
39     { value integer initial: 0 read-only }
40     { mask integer initial: 0xFFFFFFFF read-only }
41     { comparison comparison initial: cmp-always read-only }
42     { stencil-fail-op stencil-op initial: op-keep read-only }
43     { depth-fail-op stencil-op initial: op-keep read-only }
44     { depth-pass-op stencil-op initial: op-keep read-only } ;
45 C: <stencil-mode> stencil-mode
46
47 TUPLE: stencil-state
48     { front-mode maybe{ stencil-mode } initial: f read-only }
49     { back-mode maybe{ stencil-mode } initial: f read-only } ;
50 C: <stencil-state> stencil-state
51
52 TUPLE: depth-range-state
53     { near float initial: 0.0 read-only }
54     { far  float initial: 1.0 read-only } ;
55 C: <depth-range-state> depth-range-state
56
57 TUPLE: depth-state
58     { comparison maybe{ comparison } initial: f read-only } ;
59 C: <depth-state> depth-state
60
61 VARIANT: blend-equation
62     eq-add eq-subtract eq-reverse-subtract eq-min eq-max ;
63 VARIANT: blend-function
64     func-zero func-one
65     func-source func-one-minus-source
66     func-dest func-one-minus-dest
67     func-constant func-one-minus-constant
68     func-source-alpha func-one-minus-source-alpha
69     func-dest-alpha func-one-minus-dest-alpha
70     func-constant-alpha func-one-minus-constant-alpha ;
71
72 VARIANT: source-only-blend-function
73     func-source-alpha-saturate ;
74
75 UNION: source-blend-function blend-function source-only-blend-function ;
76
77 TUPLE: blend-mode
78     { equation blend-equation initial: eq-add read-only }
79     { source-function source-blend-function initial: func-source-alpha read-only }
80     { dest-function blend-function initial: func-one-minus-source-alpha read-only } ;
81 C: <blend-mode> blend-mode
82
83 TUPLE: blend-state
84     { constant-color sequence initial: f read-only }
85     { rgb-mode maybe{ blend-mode } read-only }
86     { alpha-mode maybe{ blend-mode } read-only } ;
87 C: <blend-state> blend-state
88
89 TUPLE: mask-state
90     { color sequence initial: { t t t t } read-only }
91     { depth boolean initial: t read-only }
92     { stencil-front integer initial: 0xFFFFFFFF read-only }
93     { stencil-back integer initial: 0xFFFFFFFF read-only } ;
94 C: <mask-state> mask-state
95
96 VARIANT: triangle-face
97     face-ccw face-cw ;
98 VARIANT: triangle-cull
99     cull-front cull-back cull-all ;
100 VARIANT: triangle-mode
101     triangle-points triangle-lines triangle-fill ;
102
103 TUPLE: triangle-cull-state
104     { front-face triangle-face initial: face-ccw read-only }
105     { cull maybe{ triangle-cull } initial: f read-only } ;
106 C: <triangle-cull-state> triangle-cull-state
107
108 TUPLE: triangle-state
109     { front-mode triangle-mode initial: triangle-fill read-only }
110     { back-mode triangle-mode initial: triangle-fill read-only }
111     { antialias? boolean initial: f read-only } ;
112 C: <triangle-state> triangle-state
113
114 VARIANT: point-sprite-origin
115     origin-upper-left origin-lower-left ;
116
117 TUPLE: point-state
118     { size maybe{ float } initial: 1.0 read-only }
119     { sprite-origin point-sprite-origin initial: origin-upper-left read-only }
120     { fade-threshold float initial: 1.0 read-only } ;
121 C: <point-state> point-state
122
123 TUPLE: line-state
124     { width float initial: 1.0 read-only }
125     { antialias? boolean initial: f read-only } ;
126 C: <line-state> line-state
127
128 UNION: gpu-state
129     viewport-state
130     triangle-cull-state
131     triangle-state
132     point-state
133     line-state
134     scissor-state
135     multisample-state
136     stencil-state
137     depth-range-state
138     depth-state
139     blend-state
140     mask-state ;
141
142 <PRIVATE
143
144 : gl-triangle-face ( triangle-face -- face )
145     {
146         { face-ccw [ GL_CCW ] }
147         { face-cw  [ GL_CW  ] }
148     } case ;
149
150 : gl-triangle-face> ( triangle-face -- face )
151     {
152         { $ GL_CCW [ face-ccw ] }
153         { $ GL_CW  [ face-cw  ] }
154     } case ;
155
156 : gl-triangle-cull ( triangle-cull -- cull )
157     {
158         { cull-front [ GL_FRONT          ] }
159         { cull-back  [ GL_BACK           ] }
160         { cull-all   [ GL_FRONT_AND_BACK ] }
161     } case ;
162
163 : gl-triangle-cull> ( triangle-cull -- cull )
164     {
165         { $ GL_FRONT          [ cull-front ] }
166         { $ GL_BACK           [ cull-back  ] }
167         { $ GL_FRONT_AND_BACK [ cull-all   ] }
168     } case ;
169
170 : gl-triangle-mode ( triangle-mode -- mode )
171     {
172         { triangle-points [ GL_POINT ] }
173         { triangle-lines  [ GL_LINE  ] }
174         { triangle-fill   [ GL_FILL  ] }
175     } case ;
176
177 : gl-triangle-mode> ( triangle-mode -- mode )
178     {
179         { $ GL_POINT [ triangle-points ] }
180         { $ GL_LINE  [ triangle-lines  ] }
181         { $ GL_FILL  [ triangle-fill   ] }
182     } case ;
183
184 : gl-point-sprite-origin ( point-sprite-origin -- sprite-origin )
185     {
186         { origin-upper-left [ GL_UPPER_LEFT ] }
187         { origin-lower-left [ GL_LOWER_LEFT ] }
188     } case ;
189
190 : gl-point-sprite-origin> ( point-sprite-origin -- sprite-origin )
191     {
192         { $ GL_UPPER_LEFT [ origin-upper-left ] }
193         { $ GL_LOWER_LEFT [ origin-lower-left ] }
194     } case ;
195
196 : gl-comparison ( comparison -- comparison )
197     {
198         { cmp-never         [ GL_NEVER    ] }
199         { cmp-always        [ GL_ALWAYS   ] }
200         { cmp-less          [ GL_LESS     ] }
201         { cmp-less-equal    [ GL_LEQUAL   ] }
202         { cmp-equal         [ GL_EQUAL    ] }
203         { cmp-greater-equal [ GL_GEQUAL   ] }
204         { cmp-greater       [ GL_GREATER  ] }
205         { cmp-not-equal     [ GL_NOTEQUAL ] }
206     } case ;
207
208 : gl-comparison> ( comparison -- comparison )
209     {
210         { $ GL_NEVER    [ cmp-never         ] }
211         { $ GL_ALWAYS   [ cmp-always        ] }
212         { $ GL_LESS     [ cmp-less          ] }
213         { $ GL_LEQUAL   [ cmp-less-equal    ] }
214         { $ GL_EQUAL    [ cmp-equal         ] }
215         { $ GL_GEQUAL   [ cmp-greater-equal ] }
216         { $ GL_GREATER  [ cmp-greater       ] }
217         { $ GL_NOTEQUAL [ cmp-not-equal     ] }
218     } case ;
219
220 : gl-stencil-op ( stencil-op -- op )
221     {
222         { op-keep [ GL_KEEP ] }
223         { op-zero [ GL_ZERO ] }
224         { op-replace [ GL_REPLACE ] }
225         { op-invert [ GL_INVERT ] }
226         { op-inc-sat [ GL_INCR ] }
227         { op-dec-sat [ GL_DECR ] }
228         { op-inc-wrap [ GL_INCR_WRAP ] }
229         { op-dec-wrap [ GL_DECR_WRAP ] }
230     } case ;
231
232 : gl-stencil-op> ( op -- op )
233     {
234         { $ GL_KEEP      [ op-keep     ] }
235         { $ GL_ZERO      [ op-zero     ] }
236         { $ GL_REPLACE   [ op-replace  ] }
237         { $ GL_INVERT    [ op-invert   ] }
238         { $ GL_INCR      [ op-inc-sat  ] }
239         { $ GL_DECR      [ op-dec-sat  ] }
240         { $ GL_INCR_WRAP [ op-inc-wrap ] }
241         { $ GL_DECR_WRAP [ op-dec-wrap ] }
242     } case ;
243
244 : (set-stencil-mode) ( gl-face stencil-mode -- )
245     {
246         [ [ comparison>> gl-comparison ] [ value>> ] [ mask>> ] tri glStencilFuncSeparate ]
247         [
248             [ stencil-fail-op>> ] [ depth-fail-op>> ] [ depth-pass-op>> ] tri
249             [ gl-stencil-op ] tri@ glStencilOpSeparate
250         ]
251     } 2cleave ;
252
253 : gl-blend-equation ( blend-equation -- blend-equation )
254     {
255         { eq-add              [ GL_FUNC_ADD              ] }
256         { eq-subtract         [ GL_FUNC_SUBTRACT         ] }
257         { eq-reverse-subtract [ GL_FUNC_REVERSE_SUBTRACT ] }
258         { eq-min              [ GL_MIN                   ] }
259         { eq-max              [ GL_MAX                   ] }
260     } case ;
261
262 : gl-blend-equation> ( blend-equation -- blend-equation )
263     {
264         { $ GL_FUNC_ADD              [ eq-add              ] }
265         { $ GL_FUNC_SUBTRACT         [ eq-subtract         ] }
266         { $ GL_FUNC_REVERSE_SUBTRACT [ eq-reverse-subtract ] }
267         { $ GL_MIN                   [ eq-min              ] }
268         { $ GL_MAX                   [ eq-max              ] }
269     } case ;
270
271 : gl-blend-function ( blend-function -- blend-function )
272     {
273         { func-zero                     [ GL_ZERO                     ] }
274         { func-one                      [ GL_ONE                      ] }
275         { func-source                   [ GL_SRC_COLOR                ] }
276         { func-one-minus-source         [ GL_ONE_MINUS_SRC_COLOR      ] }
277         { func-dest                     [ GL_DST_COLOR                ] }
278         { func-one-minus-dest           [ GL_ONE_MINUS_DST_COLOR      ] }
279         { func-constant                 [ GL_CONSTANT_COLOR           ] }
280         { func-one-minus-constant       [ GL_ONE_MINUS_CONSTANT_COLOR ] }
281         { func-source-alpha             [ GL_SRC_ALPHA                ] }
282         { func-one-minus-source-alpha   [ GL_ONE_MINUS_SRC_ALPHA      ] }
283         { func-dest-alpha               [ GL_DST_ALPHA                ] }
284         { func-one-minus-dest-alpha     [ GL_ONE_MINUS_DST_ALPHA      ] }
285         { func-constant-alpha           [ GL_CONSTANT_ALPHA           ] }
286         { func-one-minus-constant-alpha [ GL_ONE_MINUS_CONSTANT_ALPHA ] }
287         { func-source-alpha-saturate    [ GL_SRC_ALPHA_SATURATE       ] }
288     } case ;
289
290 : gl-blend-function> ( blend-function -- blend-function )
291     {
292         { $ GL_ZERO                     [ func-zero                     ] }
293         { $ GL_ONE                      [ func-one                      ] }
294         { $ GL_SRC_COLOR                [ func-source                   ] }
295         { $ GL_ONE_MINUS_SRC_COLOR      [ func-one-minus-source         ] }
296         { $ GL_DST_COLOR                [ func-dest                     ] }
297         { $ GL_ONE_MINUS_DST_COLOR      [ func-one-minus-dest           ] }
298         { $ GL_CONSTANT_COLOR           [ func-constant                 ] }
299         { $ GL_ONE_MINUS_CONSTANT_COLOR [ func-one-minus-constant       ] }
300         { $ GL_SRC_ALPHA                [ func-source-alpha             ] }
301         { $ GL_ONE_MINUS_SRC_ALPHA      [ func-one-minus-source-alpha   ] }
302         { $ GL_DST_ALPHA                [ func-dest-alpha               ] }
303         { $ GL_ONE_MINUS_DST_ALPHA      [ func-one-minus-dest-alpha     ] }
304         { $ GL_CONSTANT_ALPHA           [ func-constant-alpha           ] }
305         { $ GL_ONE_MINUS_CONSTANT_ALPHA [ func-one-minus-constant-alpha ] }
306         { $ GL_SRC_ALPHA_SATURATE       [ func-source-alpha-saturate    ] }
307     } case ;
308
309 PRIVATE>
310
311 GENERIC: set-gpu-state* ( state -- )
312
313 M: viewport-state set-gpu-state*
314     rect>> [ loc>> ] [ dim>> ] bi gl-viewport ;
315
316 M: triangle-cull-state set-gpu-state*
317     {
318         [ front-face>> gl-triangle-face glFrontFace ]
319         [ GL_CULL_FACE swap cull>> [ gl-triangle-cull glCullFace glEnable ] [ glDisable ] if* ]
320     } cleave ;
321
322 M: triangle-state set-gpu-state*
323     {
324         [ GL_FRONT swap front-mode>> gl-triangle-mode glPolygonMode ]
325         [ GL_BACK swap back-mode>> gl-triangle-mode glPolygonMode ]
326         [ GL_POLYGON_SMOOTH swap antialias?>> [ glEnable ] [ glDisable ] if ]
327     } cleave ;
328
329 M: point-state set-gpu-state*
330     {
331         [ GL_VERTEX_PROGRAM_POINT_SIZE swap size>> [ glPointSize glDisable ] [ glEnable ] if* ]
332         [ GL_POINT_SPRITE_COORD_ORIGIN swap sprite-origin>> gl-point-sprite-origin glPointParameteri ]
333         [ GL_POINT_FADE_THRESHOLD_SIZE swap fade-threshold>> glPointParameterf ]
334     } cleave ;
335
336 M: line-state set-gpu-state*
337     {
338         [ width>> glLineWidth ]
339         [ GL_LINE_SMOOTH swap antialias?>> [ glEnable ] [ glDisable ] if ]
340     } cleave ;
341
342 M: scissor-state set-gpu-state*
343     GL_SCISSOR_TEST swap rect>>
344     [ [ loc>> first2 ] [ dim>> first2 ] bi glViewport glEnable ]
345     [ glDisable ] if* ;
346
347 M: multisample-state set-gpu-state*
348     dup multisample?>> [
349         GL_MULTISAMPLE glEnable
350         {
351             [ GL_SAMPLE_ALPHA_TO_COVERAGE swap sample-alpha-to-coverage?>>
352                 [ glEnable ] [ glDisable ] if
353             ]
354             [ GL_SAMPLE_ALPHA_TO_ONE swap sample-alpha-to-one?>>
355                 [ glEnable ] [ glDisable ] if
356             ]
357             [ GL_SAMPLE_COVERAGE swap [ invert-sample-coverage?>> >c-bool ] [ sample-coverage>> ] bi
358                 [ swap glSampleCoverage glEnable ] [ drop glDisable ] if*
359             ]
360         } cleave
361     ] [ drop GL_MULTISAMPLE glDisable ] if ;
362
363 M: stencil-state set-gpu-state*
364     [ ] [ front-mode>> ] [ back-mode>> ] tri or
365     [
366         GL_STENCIL_TEST glEnable
367         [ front-mode>> GL_FRONT swap (set-stencil-mode) ]
368         [ back-mode>> GL_BACK swap (set-stencil-mode) ] bi
369     ] [ drop GL_STENCIL_TEST glDisable ] if ;
370
371 M: depth-range-state set-gpu-state*
372     [ near>> ] [ far>> ] bi glDepthRange ;
373
374 M: depth-state set-gpu-state*
375     GL_DEPTH_TEST swap comparison>> [ gl-comparison glDepthFunc glEnable ] [ glDisable ] if* ;
376
377 M: blend-state set-gpu-state*
378     [ ] [ rgb-mode>> ] [ alpha-mode>> ] tri or
379     [
380         GL_BLEND glEnable
381         [ constant-color>> [ first4 glBlendColor ] when* ]
382         [
383             [ rgb-mode>> ] [ alpha-mode>> ] bi {
384                 [ [ equation>> gl-blend-equation ] bi@ glBlendEquationSeparate ]
385                 [
386                     [
387                         [ source-function>> gl-blend-function ]
388                         [ dest-function>> gl-blend-function ] bi
389                     ] bi@ glBlendFuncSeparate
390                 ]
391             } 2cleave
392         ] bi
393     ] [ drop GL_BLEND glDisable ] if ;
394
395 M: mask-state set-gpu-state*
396     {
397         [ color>> [ >c-bool ] map first4 glColorMask ]
398         [ depth>> >c-bool glDepthMask ]
399         [ GL_FRONT swap stencil-front>> glStencilMaskSeparate ]
400         [ GL_BACK  swap stencil-back>> glStencilMaskSeparate ]
401     } cleave ;
402
403 : set-gpu-state ( states -- )
404     dup sequence?
405     [ [ set-gpu-state* ] each ]
406     [ set-gpu-state* ] if ; inline
407
408 : get-gl-bool ( enum -- value )
409     0 c:uchar <ref> [ glGetBooleanv ] keep c:uchar deref c-bool> ;
410 : get-gl-int ( enum -- value )
411     0 c:int <ref> [ glGetIntegerv ] keep c:int deref ;
412 : get-gl-float ( enum -- value )
413     0 c:float <ref> [ glGetFloatv ] keep c:float deref ;
414
415 : get-gl-bools ( enum count -- value )
416     <byte-array> [ glGetBooleanv ] keep [ c-bool> ] { } map-as ;
417 : get-gl-ints ( enum count -- value )
418     c:int <c-array> [ glGetIntegerv ] keep ;
419 : get-gl-floats ( enum count -- value )
420     c:float <c-array> [ glGetFloatv ] keep ;
421
422 : get-gl-rect ( enum -- value )
423     4 get-gl-ints first4 [ 2array ] 2bi@ <rect> ;
424
425 : gl-enabled? ( enum -- ? )
426     glIsEnabled c-bool> ;
427
428 TYPED: get-viewport-state ( -- viewport-state: viewport-state )
429     GL_VIEWPORT get-gl-rect <viewport-state> ;
430
431 TYPED: get-scissor-state ( -- scissor-state: scissor-state )
432     GL_SCISSOR_TEST get-gl-bool
433     [ GL_SCISSOR_BOX get-gl-rect ] [ f ] if
434     <scissor-state> ;
435
436 TYPED: get-multisample-state ( -- multisample-state: multisample-state )
437     GL_MULTISAMPLE gl-enabled?
438     GL_SAMPLE_ALPHA_TO_COVERAGE gl-enabled?
439     GL_SAMPLE_ALPHA_TO_ONE gl-enabled?
440     GL_SAMPLE_COVERAGE gl-enabled? [
441         GL_SAMPLE_COVERAGE_VALUE get-gl-float
442         GL_SAMPLE_COVERAGE_INVERT get-gl-bool
443     ] [ f f ] if
444     <multisample-state> ;
445
446 TYPED: get-stencil-state ( -- stencil-state: stencil-state )
447     GL_STENCIL_TEST gl-enabled? [
448         GL_STENCIL_REF get-gl-int
449         GL_STENCIL_VALUE_MASK get-gl-int
450         GL_STENCIL_FUNC get-gl-int gl-comparison>
451         GL_STENCIL_FAIL get-gl-int gl-stencil-op>
452         GL_STENCIL_PASS_DEPTH_FAIL get-gl-int gl-stencil-op>
453         GL_STENCIL_PASS_DEPTH_PASS get-gl-int gl-stencil-op>
454         <stencil-mode>
455
456         GL_STENCIL_BACK_REF get-gl-int
457         GL_STENCIL_BACK_VALUE_MASK get-gl-int
458         GL_STENCIL_BACK_FUNC get-gl-int gl-comparison>
459         GL_STENCIL_BACK_FAIL get-gl-int gl-stencil-op>
460         GL_STENCIL_BACK_PASS_DEPTH_FAIL get-gl-int gl-stencil-op>
461         GL_STENCIL_BACK_PASS_DEPTH_PASS get-gl-int gl-stencil-op>
462         <stencil-mode>
463     ] [ f f ] if
464     <stencil-state> ;
465
466 TYPED: get-depth-range-state ( -- depth-range-state: depth-range-state )
467     GL_DEPTH_RANGE 2 get-gl-floats first2 <depth-range-state> ;
468
469 TYPED: get-depth-state ( -- depth-state: depth-state )
470     GL_DEPTH_TEST gl-enabled?
471     [ GL_DEPTH_FUNC get-gl-int gl-comparison> ] [ f ] if
472     <depth-state> ;
473
474 TYPED: get-blend-state ( -- blend-state: blend-state )
475     GL_BLEND gl-enabled? [
476         GL_BLEND_COLOR 4 get-gl-floats
477
478         GL_BLEND_EQUATION_RGB get-gl-int gl-blend-equation>
479         GL_BLEND_SRC_RGB get-gl-int gl-blend-function>
480         GL_BLEND_DST_RGB get-gl-int gl-blend-function>
481         <blend-mode>
482
483         GL_BLEND_EQUATION_ALPHA get-gl-int gl-blend-equation>
484         GL_BLEND_SRC_ALPHA get-gl-int gl-blend-function>
485         GL_BLEND_DST_ALPHA get-gl-int gl-blend-function>
486         <blend-mode>
487     ] [ f f f ] if
488     <blend-state> ;
489
490 TYPED: get-mask-state ( -- mask-state: mask-state )
491     GL_COLOR_WRITEMASK 4 get-gl-bools
492     GL_DEPTH_WRITEMASK get-gl-bool
493     GL_STENCIL_WRITEMASK get-gl-int
494     GL_STENCIL_BACK_WRITEMASK get-gl-int
495     <mask-state> ;
496
497 TYPED: get-triangle-cull-state ( -- triangle-cull-state: triangle-cull-state )
498     GL_FRONT_FACE get-gl-int gl-triangle-face>
499     GL_CULL_FACE gl-enabled?
500     [ GL_CULL_FACE_MODE get-gl-int gl-triangle-cull> ]
501     [ f ] if
502     <triangle-cull-state> ;
503
504 TYPED: get-triangle-state ( -- triangle-state: triangle-state )
505     GL_POLYGON_MODE 2 get-gl-ints
506     first2 [ gl-triangle-mode> ] bi@
507     GL_POLYGON_SMOOTH gl-enabled?
508     <triangle-state> ;
509
510 TYPED: get-point-state ( -- point-state: point-state )
511     GL_VERTEX_PROGRAM_POINT_SIZE gl-enabled?
512     [ f ] [ GL_POINT_SIZE get-gl-float ] if
513     GL_POINT_SPRITE_COORD_ORIGIN get-gl-int gl-point-sprite-origin>
514     GL_POINT_FADE_THRESHOLD_SIZE get-gl-float
515     <point-state> ;
516
517 TYPED: get-line-state ( -- line-state: line-state )
518     GL_LINE_WIDTH get-gl-float
519     GL_LINE_SMOOTH gl-enabled?
520     <line-state> ;