1""" 2SampleCIView - simple OpenGL based CoreImage view 3""" 4 5from Cocoa import * 6from Quartz import * 7import CGL 8 9from OpenGL.GL import * 10 11# XXX: this may or may not be a bug in the OpenGL bindings 12from OpenGL.GL.APPLE.transform_hint import * 13 14import objc 15 16# The default pixel format 17_pf = None 18 19class SampleCIView (NSOpenGLView): 20 _context = objc.ivar() 21 _image = objc.ivar() 22 _lastBounds = objc.ivar(type=NSRect.__typestr__) 23 24 @classmethod 25 def defaultPixelFormat(self): 26 global _pf 27 28 if _pf is None: 29 # Making sure the context's pixel format doesn't have a recovery 30 # renderer is important - otherwise CoreImage may not be able to 31 # create deeper context's that share textures with this one. 32 33 attr = ( NSOpenGLPFAAccelerated, 34 NSOpenGLPFANoRecovery, NSOpenGLPFAColorSize, 32 ) 35 _pf = NSOpenGLPixelFormat.alloc().initWithAttributes_(attr) 36 37 return _pf 38 39 def image(self): 40 return self._image 41 42 def setImage_dirtyRect_(self, image, r): 43 if self._image is not image: 44 self._image = image 45 46 if CGRectIsInfinite(r): 47 self.setNeedsDisplay_(True) 48 else: 49 self.setNeedsDisplayInRect_(r) 50 51 def setImage_(self, image): 52 self.setImage_dirtyRect_(image, CGRectInfinite) 53 54 def prepareOpenGL(self): 55 parm = 1 56 57 # Enable beam-synced updates. 58 59 self.openGLContext().setValues_forParameter_( 60 (parm,), NSOpenGLCPSwapInterval) 61 62 # Make sure that everything we don't need is disabled. Some of these 63 # are enabled by default and can slow down rendering. 64 65 glDisable(GL_ALPHA_TEST) 66 glDisable(GL_DEPTH_TEST) 67 glDisable(GL_SCISSOR_TEST) 68 glDisable(GL_BLEND) 69 glDisable(GL_DITHER) 70 glDisable(GL_CULL_FACE) 71 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE) 72 glDepthMask(GL_FALSE) 73 glStencilMask(0) 74 glClearColor(0.0, 0.0, 0.0, 0.0) 75 glHint (GL_TRANSFORM_HINT_APPLE, GL_FASTEST) 76 77 def viewBoundsDidChange_(self, bounds): 78 # For subclasses. 79 pass 80 81 def updateMatrices(self): 82 r = self.bounds() 83 84 if r != self._lastBounds: 85 self.openGLContext().update() 86 87 # Install an orthographic projection matrix (no perspective) 88 # with the origin in the bottom left and one unit equal to one 89 # device pixel. 90 91 glViewport(0, 0, r.size.width, r.size.height) 92 93 glMatrixMode(GL_PROJECTION) 94 glLoadIdentity() 95 glOrtho(0, r.size.width, 0, r.size.height, -1, 1) 96 97 glMatrixMode(GL_MODELVIEW) 98 glLoadIdentity() 99 100 self._lastBounds = r 101 102 self.viewBoundsDidChange_(r) 103 104 def drawRect_(self, r): 105 self.openGLContext().makeCurrentContext() 106 107 # Allocate a CoreImage rendering context using the view's OpenGL 108 # context as its destination if none already exists. 109 110 if self._context is None: 111 pf = self.pixelFormat() 112 if pf is None: 113 pf = type(self).defaultPixelFormat() 114 115 self._context=CIContext.contextWithCGLContext_pixelFormat_options_( 116 CGL.CGLGetCurrentContext(), pf.CGLPixelFormatObj(), None) 117 118 ir = CGRectIntegral(r) 119 120 if NSGraphicsContext.currentContextDrawingToScreen(): 121 self.updateMatrices() 122 123 # Clear the specified subrect of the OpenGL surface then 124 # render the image into the view. Use the GL scissor test to 125 # clip to * the subrect. Ask CoreImage to generate an extra 126 # pixel in case * it has to interpolate (allow for hardware 127 # inaccuracies) 128 129 rr = CGRectIntersection (CGRectInset(ir, -1.0, -1.0), 130 self._lastBounds) 131 132 glScissor(ir.origin.x, ir.origin.y, ir.size.width, ir.size.height) 133 glEnable(GL_SCISSOR_TEST) 134 135 glClear(GL_COLOR_BUFFER_BIT) 136 137 if self.respondsToSelector_('drawRect:inCIContext:'): 138 self.drawRect_inCIContext_(rr, self._context) 139 140 elif self._image is not None: 141 self._context.drawImage_atPoint_fromRect_( 142 self._image, rr.origin, rr) 143 144 glDisable(GL_SCISSOR_TEST) 145 146 # Flush the OpenGL command stream. If the view is double 147 # buffered this should be replaced by [[self openGLContext] 148 # flushBuffer]. 149 150 glFlush () 151 152 else: 153 # Printing the view contents. Render using CG, not OpenGL. 154 155 if self.respondsToSelector_('drawRect:inCIContext:'): 156 self.drawRect_inCIContext_(ir, self._context) 157 158 elif self._image is not None: 159 cgImage = self._context.createCGImage_fromRect_( 160 self._image, ir) 161 162 if cgImage is not None: 163 CGContextDrawImage( 164 NSGraphicsContext.currentContext().graphicsPort(), 165 ir, cgImage) 166