root/trunk/dglut/ext.d

Revision 172, 5.6 kB (checked in by FeepingCreature, 1 year ago)
  • Went back to the simple blob
Line 
1 module dglut.ext;
2 import dglut.opengl;
3 import std.string: toString, toStringz, split;
4 public import dglut.set;
5
6 template glStringFunction(string name, StringName glname) {
7   mixin("string "~name~"() { string res; glChecked(res=toString(glGetString(glname))); return res; }");
8 }
9 mixin MultiMixin!(glStringFunction, 2, "Vendor", GL_VENDOR, "Renderer", GL_RENDERER, "Version", GL_VERSION);
10 Set!(string) Extensions() {
11   string ext;
12   glChecked(ext=toString(glGetString(GL_EXTENSIONS)));
13   Set!(string) res;
14   foreach (e; ext.split(" ")) if (!e.length) continue; else res.set(e);
15   return res;
16 }
17
18 version(Win32) { }
19 else {
20   extern(C) void *glXGetProcAddressARB(char *procName);
21 }
22
23 import std.traits: ReturnType, ParameterTypeTuple;
24 template SysFunc(C) { extern(System) alias ReturnType!(C) function(ParameterTypeTuple!(C)) SysFunc; }
25
26 struct ExtFunc(C, string name) {
27   static {
28     SysFunc!(C) load() {
29       static if (is(typeof(&glXGetProcAddressARB))) {
30         return cast(SysFunc!(C)) glXGetProcAddressARB(toStringz("gl"~name));
31       } else static assert(false, "Platform not supported (yet)");
32     }
33     SysFunc!(C) fn;
34     ReturnType!(C) opCall(ParameterTypeTuple!(C) params) {
35       if (!fn) fn=cast(typeof(fn)) load();
36       if (!fn) throw new Exception("Extension function \""~name~"\" not found in lookup table!");
37       return fn(params);
38     }
39   }
40 }
41
42 const GLenum GL_FRAMEBUFFER_EXT=0x8D40, GL_RENDERBUFFER_EXT=0x8D41;
43 const GLenum GL_FRAMEBUFFER_BINDING_EXT=0x8CA6, GL_RENDERBUFFER_BINDING_EXT=0x8CA7,
44   GL_MAX_COLOR_ATTACHMENTS_EXT=0x8CDF, GL_MAX_RENDERBUFFER_SIZE_EXT=0x84E8;
45 typedef GLenum Attachment;
46 mixin ConstEnum!(Attachment, "+1",
47   0x8CE0, Expand!("GL_COLOR_ATTACHMENT{0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15}_EXT"),
48   0x8D00, "GL_DEPTH_ATTACHMENT_EXT", 0x8D20, "GL_STENCIL_ATTACHMENT_EXT"
49 );
50
51
52 class glExtension(string name) {
53   static { bool checked, _supported; }
54   this() {
55     if (!checked) {
56       _supported=name in Extensions;
57       checked=true;
58     }
59     if (!_supported) throw new Exception("Cannot create "~(cast(Object) this).toString~": "~name~" not supported!");
60   }
61   static bool supported() { if (!checked) { checked=true; _supported=name in Extensions; } return _supported; }
62 }
63
64 mixin ConstEnum!(GLenum, "+1", 0x8CD5, Prepend!("GL_FRAMEBUFFER_", Append!("_EXT",
65     "COMPLETE", Expand!("INCOMPLETE_{ATTACHMENT|MISSING_ATTACHMENT}"),
66     0x8CD9, Expand!("INCOMPLETE_{DIMENSIONS|FORMATS|DRAW_BUFFER_EXT|READ_BUFFER_EXT}"), "UNSUPPORTED"
67   ))
68 );
69
70 const GLenum GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT=0x8CD0,
71   GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT=0x8CD1;
72
73 class FrameBuffer : glExtension!("GL_EXT_framebuffer_object") {
74   void checkState() {
75     auto old=bound(); scope(exit) bind(old); bind;
76     alias ExtFunc!(void function(GLenum, GLenum, GLenum, int *), "GetFramebufferAttachmentParameterivEXT") getpar;
77     foreach (where, obj; attachedObjects) {
78       int res, res2;
79       getpar(GL_FRAMEBUFFER_EXT, where, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT, &res);
80       getpar(GL_FRAMEBUFFER_EXT, where, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT, &res2);
81       if (!res || !res2) throw new Exception("Weird .. no draw buffer attached?");
82     }
83    
84     auto res=ExtFunc!(GLenum function(GLenum target), "CheckFramebufferStatusEXT")(GL_FRAMEBUFFER_EXT);
85     if (res==GL_FRAMEBUFFER_COMPLETE_EXT) return;
86     string[GLenum] decode=[0x8CD6: "Incomplete (attachment)"[], 0x8CD7: "Incomplete (missing attachment)",
87       0x8CD9: "Incomplete (dimensions)", 0x8CDA: "Incomplete (formats)",
88       0x8CDB: "Incomplete (draw buffer)", 0x8CDC: "Incomplete (read buffer)",
89       0x8CDD: "Unsupported"];
90     if (!(res in decode)) throw new Exception("Unknown framebuffer error!");
91     throw new Exception("Framebuffer error: "~decode[res]);
92   }
93   uint fb;
94   this() { ExtFunc!(void function(int, uint *), "GenFramebuffersEXT")(1, &fb); }
95   void free() {
96     ExtFunc!(void function(int, uint *), "DeleteFramebuffersEXT")(1, &fb);
97     fb=0;
98   }
99   ~this() { free; }
100  
101   static void bind(uint whar) { ExtFunc!(void function(GLenum, uint), "BindFramebufferEXT")(GL_FRAMEBUFFER_EXT, whar); }
102   static uint bound() { uint res; glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, cast(int*)&res); return res; }
103   bool isBound() { return bound==fb; }
104   void bind() { bind(fb); }
105   void Using(void delegate()[] dgs...) {
106     glPushAttrib(GL_VIEWPORT_BIT); scope(exit) glPopAttrib;
107     glViewport(0, 0, width, height);
108     auto old=bound(); scope(exit) bind(old); bind;
109     checkState;
110     foreach (dg; dgs) dg();
111   }
112   void With(void delegate()[] dgs...) {
113     auto old=bound(); scope(exit) bind(old); bind;
114     foreach (dg; dgs) dg();
115   }
116  
117   Texture[Attachment] attachedObjects; // for the sake of the GC
118   int width, height;
119  
120   alias ExtFunc!(void function(GLenum, Attachment, GLenum, uint), "FramebufferRenderbufferEXT") FramebufferRenderbuffer;
121   alias ExtFunc!(void function(GLenum target, Attachment, GLenum target, uint texture, int level), "FramebufferTexture2DEXT")
122     glfbtex2d;
123   void attach(Attachment where, PixelFormat component, Texture tex, int level=0) {
124     auto old=bound(); scope(exit) bind(old); bind;
125     if (width || height) {
126       if (width!=tex.width || height!=tex.height)
127         throw new Exception("All textures attached to a frame buffer must be the same size!");
128     } else { width=tex.width; height=tex.height; }
129     glChecked("FrameBufBindTexture", {
130       auto prev=tex.bound; scope(exit) tex.bind(prev);
131       tex.bind;
132       glChecked("FrameBufAttachTexture", glfbtex2d(GL_FRAMEBUFFER_EXT, where, GL_TEXTURE_2D, tex.me, level));
133     });
134   }
135   void detach(Attachment where, int level=0) {
136     glfbtex2d(GL_FRAMEBUFFER_EXT, where, GL_TEXTURE_2D, 0, level);
137     width=0; height=0;
138   }
139 }
Note: See TracBrowser for help on using the browser.