diff --git a/pyopencl/_cffi.py b/pyopencl/_cffi.py
index f21334a7f29d10af6e1b29311bf79a989e5bbb52..06c2e9121d8d2abb75c5cb4b108605d78af0d199 100644
--- a/pyopencl/_cffi.py
+++ b/pyopencl/_cffi.py
@@ -8,8 +8,11 @@ _ffi = FFI()
 _cl_header = """
 
 /* gl.h */
+typedef unsigned int	GLenum;
+typedef int		GLint;		/* 4-byte signed */
 typedef unsigned int	GLuint;		/* 4-byte unsigned */
 
+
 /* cl.h */
 /* scalar types */
 typedef int8_t		cl_char;
diff --git a/pyopencl/cffi_cl.py b/pyopencl/cffi_cl.py
index 7fdf69f8259a627d417a00d8443b198217cfc595..7c7b63bdbf3f11b2f2b6773da9d5e24103f95289 100644
--- a/pyopencl/cffi_cl.py
+++ b/pyopencl/cffi_cl.py
@@ -433,15 +433,15 @@ def enqueue_nd_range_kernel(queue, kernel, global_work_size, local_work_size, gl
     ))
     return _create_instance(Event, ptr_event[0])
 
-def _c_wait_for(wait_for=None):
-    if wait_for is None:
+def _c_obj_list(objs=None):
+    if objs is None:
         return _ffi.NULL, 0
-    return _ffi.new('void *[]', [ev.ptr for ev in wait_for]), len(wait_for)
+    return _ffi.new('void *[]', [ev.ptr for ev in objs]), len(objs)
 
 def _enqueue_read_buffer(queue, mem, buf, device_offset=0, wait_for=None, is_blocking=True):
     c_buf, size = Buffer._c_buffer_from_obj(buf)
     ptr_event = _ffi.new('void **')
-    c_wait_for, num_wait_for = _c_wait_for(wait_for=wait_for)
+    c_wait_for, num_wait_for = _c_obj_list(wait_for)
     _handle_error(_lib._enqueue_read_buffer(
         ptr_event,
         queue.ptr,
@@ -456,7 +456,7 @@ def _enqueue_read_buffer(queue, mem, buf, device_offset=0, wait_for=None, is_blo
 
 def _enqueue_copy_buffer(queue, src, dst, byte_count=-1, src_offset=0, dst_offset=0, wait_for=None):
     ptr_event = _ffi.new('void **')
-    c_wait_for, num_wait_for = _c_wait_for(wait_for=wait_for)
+    c_wait_for, num_wait_for = _c_obj_list(wait_for)
     _handle_error(_lib._enqueue_copy_buffer(
         ptr_event,
         queue.ptr,
@@ -472,7 +472,7 @@ def _enqueue_copy_buffer(queue, src, dst, byte_count=-1, src_offset=0, dst_offse
 def _enqueue_write_buffer(queue, mem, hostbuf, device_offset=0, wait_for=None, is_blocking=True):
     c_buf, size = Buffer._c_buffer_from_obj(hostbuf)
     ptr_event = _ffi.new('void **')
-    c_wait_for, num_wait_for = _c_wait_for(wait_for=wait_for)
+    c_wait_for, num_wait_for = _c_obj_list(wait_for)
     _handle_error(_lib._enqueue_write_buffer(
         ptr_event,
         queue.ptr,
@@ -491,7 +491,8 @@ def _create_instance(cls, ptr):
     ins.ptr = ptr
     return ins
 
-# gl interop
+# {{{ gl interop
+
 def have_gl():
     return bool(_lib.have_gl())
 
@@ -499,6 +500,55 @@ class GLBuffer(MemoryObject):
     _id = 'gl_buffer'
     
     def __init__(self, context, flags, bufobj):
-        ptr_buffer = _ffi.new('void **')
-        _handle_error(_lib._create_gl_buffer(ptr_buffer, context.ptr, flags, bufobj))
-        self.ptr = ptr_buffer[0]
+        ptr = _ffi.new('void **')
+        _handle_error(_lib._create_from_gl_buffer(ptr, context.ptr, flags, bufobj))
+        self.ptr = ptr[0]
+
+class GLRenderBuffer(MemoryObject):
+    _id = 'gl_renderbuffer'
+    
+    def __init__(self, context, flags, bufobj):
+        ptr = _ffi.new('void **')
+        _handle_error(_lib._create_from_gl_renderbuffer(ptr, context.ptr, flags, bufobj))
+        self.ptr = ptr[0]
+
+        
+def _create_gl_enqueue(what):
+    def enqueue_gl_objects(queue, mem_objects, wait_for=None):
+        ptr_event = _ffi.new('void **')
+        c_wait_for, num_wait_for = _c_obj_list(wait_for)
+        c_mem_objects, num_mem_objects = _c_obj_list(mem_objects)
+        _handle_error(what(
+            ptr_event,
+            queue.ptr,
+            c_mem_objects,
+            num_mem_objects,
+            c_wait_for,
+            num_wait_for
+            ))
+        return _create_instance(Event, ptr_event[0])
+    return enqueue_gl_objects
+
+enqueue_acquire_gl_objects = _create_gl_enqueue(_lib._enqueue_acquire_gl_objects)
+enqueue_release_gl_objects = _create_gl_enqueue(_lib._enqueue_release_gl_objects)
+
+class Image(MemoryObject):
+    _id = 'image'
+
+    def __init__(self, context, flags, format, *args):
+        if len(args) == 2:
+            # > (1,2)
+            desc, hostbuf = args
+        elif len(args) == 3:
+            # <= (1,1)
+            shape, pitches, hostbuf = args
+        else:
+            assert False
+
+# class GLTexture(MemoryObject):
+#     _id = 'gl_texture'
+    
+#     def __init__(self, context, flags, texture_target, miplevel, texture, dims):
+#         ptr = _ffi.new('void **')
+#         _handle_error(_lib._create_from_gl_texture(ptr, context.ptr, flags, texture_target, miplevel, texture, dims))
+#         self.ptr = ptr[0]
diff --git a/src/c_wrapper/wrap_cl.cpp b/src/c_wrapper/wrap_cl.cpp
index b374da33c8dded92f2ebf593fb89f4732472749b..a42497365adfefbbf804c68e9daad895881d7293 100644
--- a/src/c_wrapper/wrap_cl.cpp
+++ b/src/c_wrapper/wrap_cl.cpp
@@ -192,16 +192,19 @@
     info.value = (void*)ar;						\
     return info;							\
   }
-
+ 
 // {{{ event helpers --------------------------------------------------------------
-#define PYOPENCL_PARSE_WAIT_FOR						\
-  std::vector<cl_event> event_wait_list(num_wait_for);			\
-  {									\
-    for(unsigned i = 0; i < num_wait_for; ++i) {			\
-      event_wait_list[i] = static_cast<pyopencl::event*>(wait_for[i])->data(); \
-    }									\
+#define PYOPENCL_PARSE_OBJECT_LIST(CLS, TYPE, OUT, NAME, NUM)	\
+  std::vector<TYPE> OUT((NUM));					\
+  {								\
+    for(unsigned i = 0; i < (NUM); ++i) {			\
+      OUT[i] = static_cast<pyopencl::CLS*>(NAME[i])->data();	\
+    }								\
   }
 
+
+#define PYOPENCL_PARSE_WAIT_FOR	PYOPENCL_PARSE_OBJECT_LIST(event, cl_event, event_wait_list, wait_for, num_wait_for)
+
 #define PYOPENCL_WAITLIST_ARGS						\
   num_wait_for, event_wait_list.empty( ) ? NULL : &event_wait_list.front()
 
@@ -298,6 +301,7 @@ run_python_gc();				\
   case ::CLASS_PROGRAM: OPERATION(PROGRAM, program); break;		\
   case ::CLASS_EVENT: OPERATION(EVENT, event); break;			\
   case ::CLASS_GL_BUFFER: OPERATION(GL_BUFFER, gl_buffer); break;			\
+  case ::CLASS_GL_RENDERBUFFER: OPERATION(GL_RENDERBUFFER, gl_renderbuffer); break;	\
   default: throw pyopencl::error("unknown class", CL_INVALID_VALUE);	\
   }
 
@@ -310,6 +314,7 @@ run_python_gc();				\
 #define PYOPENCL_CL_PROGRAM cl_program
 #define PYOPENCL_CL_EVENT cl_event
 #define PYOPENCL_CL_GL_BUFFER cl_mem
+#define PYOPENCL_CL_GL_RENDERBUFFER cl_mem
 
 template<class T>
 std::string tostring(const T& v) {
@@ -1920,8 +1925,7 @@ namespace pyopencl
 			       (ctx.data(), flags, renderbuffer, &status_code));
 
   inline
-  gl_texture *create_from_gl_texture(
-				     context &ctx, cl_mem_flags flags,
+  gl_texture *create_from_gl_texture(context &ctx, cl_mem_flags flags,
 				     GLenum texture_target, GLint miplevel,
 				     GLuint texture, unsigned dims)
   {
@@ -1946,34 +1950,31 @@ namespace pyopencl
   //   PYOPENCL_CALL_GUARDED(clGetGLObjectInfo, (mem.data(), &otype, &gl_name));
   //   return py::make_tuple(otype, gl_name);
   // }
-  /*
-#define WRAP_GL_ENQUEUE(what, What) \
-  inline \
-  event *enqueue_##what##_gl_objects( \
-      command_queue &cq, \
-      py::object py_mem_objects, \
-      py::object py_wait_for) \
-  { \
-    PYOPENCL_PARSE_WAIT_FOR; \
-    \
-    std::vector<cl_mem> mem_objects; \
-    PYTHON_FOREACH(mo, py_mem_objects) \
-      mem_objects.push_back(py::extract<memory_object_holder &>(mo)().data()); \
-    \
-    cl_event evt; \
-    PYOPENCL_CALL_GUARDED(clEnqueue##What##GLObjects, ( \
-          cq.data(), \
-          mem_objects.size(), mem_objects.empty( ) ? NULL : &mem_objects.front(), \
-          PYOPENCL_WAITLIST_ARGS, &evt \
-          )); \
-    \
-    PYOPENCL_RETURN_NEW_EVENT(evt); \
+  
+#define WRAP_GL_ENQUEUE(what, What)					\
+  inline								\
+  event *enqueue_##what##_gl_objects(command_queue &cq,			\
+				     void **ptr_mem_objects,		\
+				     uint32_t num_mem_objects,		\
+				     void **wait_for,			\
+				     uint32_t num_wait_for)		\
+  {									\
+    PYOPENCL_PARSE_WAIT_FOR;						\
+    PYOPENCL_PARSE_OBJECT_LIST(memory_object_holder, cl_mem, mem_objects, ptr_mem_objects, num_mem_objects); \
+    cl_event evt;							\
+    PYOPENCL_CALL_GUARDED(clEnqueue##What##GLObjects, (			\
+						       cq.data(),	\
+						       mem_objects.size(), mem_objects.empty( ) ? NULL : &mem_objects.front(), \
+						       PYOPENCL_WAITLIST_ARGS, &evt \
+									)); \
+									\
+    PYOPENCL_RETURN_NEW_EVENT(evt);					\
   }
 
   WRAP_GL_ENQUEUE(acquire, Acquire);
   WRAP_GL_ENQUEUE(release, Release);
 #endif
-  */
+  
 
 
 
@@ -2062,7 +2063,7 @@ namespace pyopencl
   //     }
   //   }
 
-#endif
+  // #endif
 
   // }}}
 
@@ -3071,10 +3072,35 @@ int have_gl() {
 #endif
 }
 
-error *_create_gl_buffer(void **ptr_buffer, void *ptr_context, cl_mem_flags flags, GLuint bufobj) {
+error *_create_from_gl_buffer(void **ptr, void *ptr_context, cl_mem_flags flags, GLuint bufobj) {
   pyopencl::context *ctx = static_cast<pyopencl::context*>(ptr_context);
-  C_HANDLE_ERROR(*ptr_buffer = create_from_gl_buffer(*ctx, flags, bufobj););
-  return 0;  
+  C_HANDLE_ERROR(*ptr = create_from_gl_buffer(*ctx, flags, bufobj););
+  return 0;
+}
+
+error *_create_from_gl_renderbuffer(void **ptr, void *ptr_context, cl_mem_flags flags, GLuint bufobj) {
+  pyopencl::context *ctx = static_cast<pyopencl::context*>(ptr_context);
+  C_HANDLE_ERROR(*ptr = create_from_gl_renderbuffer(*ctx, flags, bufobj););
+  return 0;
+}
+
+::error *_enqueue_acquire_gl_objects(void **ptr_event, void *ptr_command_queue, void **ptr_mem_objects, uint32_t num_mem_objects, void **wait_for, uint32_t num_wait_for) {
+  C_HANDLE_ERROR(
+		 *ptr_event = enqueue_acquire_gl_objects(*static_cast<pyopencl::command_queue*>(ptr_command_queue),
+							 ptr_mem_objects, num_mem_objects,
+							 wait_for, num_wait_for);
+		 );
+  return 0;
+}
+
+::error *_enqueue_release_gl_objects(void **ptr_event, void *ptr_command_queue, void **ptr_mem_objects, uint32_t num_mem_objects, void **wait_for, uint32_t num_wait_for) {
+  C_HANDLE_ERROR(
+		 *ptr_event = enqueue_release_gl_objects(*static_cast<pyopencl::command_queue*>(ptr_command_queue),
+							 ptr_mem_objects, num_mem_objects,
+							 wait_for, num_wait_for);
+		 );
+  return 0;
 }
 
+
 // }}}
diff --git a/src/c_wrapper/wrap_cl_core.h b/src/c_wrapper/wrap_cl_core.h
index 8b24fed0a175577daf346f67043f133a60b67e35..af3f35a11fb8e9709571a5b6ca666e1b785aa97e 100644
--- a/src/c_wrapper/wrap_cl_core.h
+++ b/src/c_wrapper/wrap_cl_core.h
@@ -17,7 +17,8 @@ typedef enum {
   CLASS_PROGRAM,
   CLASS_EVENT,
   CLASS_COMMAND_QUEUE,
-  CLASS_GL_BUFFER
+  CLASS_GL_BUFFER,
+  CLASS_GL_RENDERBUFFER
 } class_t;
 
 
@@ -67,4 +68,7 @@ unsigned bitlog2(unsigned long v);
 /* gl interop */
 
 int have_gl();
-error *_create_gl_buffer(void **ptr_buffer, void *ptr_context, cl_mem_flags flags, GLuint bufobj);
+error *_create_from_gl_buffer(void **ptr, void *ptr_context, cl_mem_flags flags, GLuint bufobj);
+error *_create_from_gl_renderbuffer(void **ptr, void *ptr_context, cl_mem_flags flags, GLuint bufobj);
+error *_enqueue_acquire_gl_objects(void **ptr_event, void *ptr_command_queue, void **ptr_mem_objects, uint32_t num_mem_objects, void **wait_for, uint32_t num_wait_for);
+error *_enqueue_release_gl_objects(void **ptr_event, void *ptr_command_queue, void **ptr_mem_objects, uint32_t num_mem_objects, void **wait_for, uint32_t num_wait_for);