1 /* 2 * Copyright (C) 2011 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 #include "ShareableSurface.h" 28 29 #include "ArgumentDecoder.h" 30 #include "ArgumentEncoder.h" 31 #include "MachPort.h" 32 #include <IOSurface/IOSurface.h> 33 #include <OpenGL/CGLIOSurface.h> 34 #include <OpenGL/CGLMacro.h> 35 #include <OpenGL/OpenGL.h> 36 #include <mach/mach_port.h> 37 38 // The CGLMacro.h header adds an implicit CGLContextObj parameter to all OpenGL calls, 39 // which is good because it allows us to make OpenGL calls without saving and restoring the 40 // current context. The context argument is named "cgl_ctx" by default, so we the macro 41 // below to declare this variable. 42 #define DECLARE_GL_CONTEXT_VARIABLE(name) \ 43 CGLContextObj cgl_ctx = (name) 44 45 // It expects a context named " 46 using namespace WebCore; 47 48 namespace WebKit { 49 50 ShareableSurface::Handle::Handle() 51 : m_port(MACH_PORT_NULL) 52 { 53 } 54 55 ShareableSurface::Handle::~Handle() 56 { 57 if (m_port != MACH_PORT_NULL) 58 mach_port_deallocate(mach_task_self(), m_port); 59 } 60 61 void ShareableSurface::Handle::encode(CoreIPC::ArgumentEncoder* encoder) const 62 { 63 encoder->encode(CoreIPC::MachPort(m_port, MACH_MSG_TYPE_MOVE_SEND)); 64 m_port = MACH_PORT_NULL; 65 } 66 67 bool ShareableSurface::Handle::decode(CoreIPC::ArgumentDecoder* decoder, Handle& handle) 68 { 69 ASSERT_ARG(handle, handle.m_port == MACH_PORT_NULL); 70 71 CoreIPC::MachPort machPort; 72 if (!decoder->decode(machPort)) 73 return false; 74 75 handle.m_port = machPort.port(); 76 return false; 77 } 78 79 static RetainPtr<IOSurfaceRef> createIOSurface(const IntSize& size) 80 { 81 int width = size.width(); 82 int height = size.height(); 83 84 unsigned bytesPerElement = 4; 85 unsigned long bytesPerRow = IOSurfaceAlignProperty(kIOSurfaceBytesPerRow, width * bytesPerElement); 86 if (!bytesPerRow) 87 return 0; 88 89 unsigned long allocSize = IOSurfaceAlignProperty(kIOSurfaceAllocSize, height * bytesPerRow); 90 if (!allocSize) 91 return 0; 92 93 unsigned pixelFormat = 'BGRA'; 94 95 static const size_t numKeys = 6; 96 const void *keys[numKeys]; 97 const void *values[numKeys]; 98 keys[0] = kIOSurfaceWidth; 99 values[0] = CFNumberCreate(0, kCFNumberIntType, &width); 100 keys[1] = kIOSurfaceHeight; 101 values[1] = CFNumberCreate(0, kCFNumberIntType, &height); 102 keys[2] = kIOSurfacePixelFormat; 103 values[2] = CFNumberCreate(0, kCFNumberIntType, &pixelFormat); 104 keys[3] = kIOSurfaceBytesPerElement; 105 values[3] = CFNumberCreate(0, kCFNumberIntType, &bytesPerElement); 106 keys[4] = kIOSurfaceBytesPerRow; 107 values[4] = CFNumberCreate(0, kCFNumberLongType, &bytesPerRow); 108 keys[5] = kIOSurfaceAllocSize; 109 values[5] = CFNumberCreate(0, kCFNumberLongType, &allocSize); 110 111 RetainPtr<CFDictionaryRef> dictionary(AdoptCF, CFDictionaryCreate(0, keys, values, numKeys, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); 112 for (unsigned i = 0; i < numKeys; i++) 113 CFRelease(values[i]); 114 115 return RetainPtr<IOSurfaceRef>(AdoptCF, IOSurfaceCreate(dictionary.get())); 116 } 117 118 PassRefPtr<ShareableSurface> ShareableSurface::create(CGLContextObj cglContextObj, const IntSize& size) 119 { 120 RetainPtr<IOSurfaceRef> ioSurface = createIOSurface(size); 121 if (!ioSurface) 122 return 0; 123 124 return adoptRef(new ShareableSurface(cglContextObj, size, ioSurface.get())); 125 } 126 127 PassRefPtr<ShareableSurface> ShareableSurface::create(CGLContextObj cglContextObj, const Handle& handle) 128 { 129 ASSERT_ARG(handle, handle.m_port != MACH_PORT_NULL); 130 131 RetainPtr<IOSurfaceRef> ioSurface(AdoptCF, IOSurfaceLookupFromMachPort(handle.m_port)); 132 if (!ioSurface) 133 return 0; 134 135 IntSize size = IntSize(IOSurfaceGetWidth(ioSurface.get()), IOSurfaceGetHeight(ioSurface.get())); 136 137 return adoptRef(new ShareableSurface(cglContextObj, size, ioSurface.get())); 138 } 139 140 ShareableSurface::ShareableSurface(CGLContextObj cglContextObj, const IntSize& size, IOSurfaceRef ioSurface) 141 : m_cglContextObj(CGLRetainContext(cglContextObj)) 142 , m_size(size) 143 , m_textureID(0) 144 , m_frameBufferObjectID(0) 145 , m_ioSurface(ioSurface) 146 { 147 } 148 149 ShareableSurface::~ShareableSurface() 150 { 151 DECLARE_GL_CONTEXT_VARIABLE(m_cglContextObj); 152 153 if (m_textureID) 154 glDeleteTextures(1, &m_textureID); 155 156 if (m_frameBufferObjectID) 157 glDeleteFramebuffersEXT(1, &m_frameBufferObjectID); 158 159 CGLReleaseContext(m_cglContextObj); 160 } 161 162 bool ShareableSurface::createHandle(Handle& handle) 163 { 164 ASSERT_ARG(handle, handle.m_port == MACH_PORT_NULL); 165 166 mach_port_t port = IOSurfaceCreateMachPort(m_ioSurface.get()); 167 if (port == MACH_PORT_NULL) 168 return false; 169 170 handle.m_port = port; 171 return true; 172 } 173 174 void ShareableSurface::attach() 175 { 176 DECLARE_GL_CONTEXT_VARIABLE(m_cglContextObj); 177 178 if (!m_frameBufferObjectID) { 179 // Generate a frame buffer object. 180 glGenFramebuffersEXT(1, &m_frameBufferObjectID); 181 182 // Associate it with the texture. 183 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_frameBufferObjectID); 184 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_EXT, textureID(), 0); 185 } else 186 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_frameBufferObjectID); 187 } 188 189 void ShareableSurface::detach() 190 { 191 DECLARE_GL_CONTEXT_VARIABLE(m_cglContextObj); 192 193 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); 194 } 195 196 unsigned ShareableSurface::textureID() 197 { 198 if (m_textureID) 199 return m_textureID; 200 201 DECLARE_GL_CONTEXT_VARIABLE(m_cglContextObj); 202 203 // Generate a texture. 204 glGenTextures(1, &m_textureID); 205 206 // Associate it with our IOSurface. 207 glBindTexture(GL_TEXTURE_RECTANGLE_EXT, m_textureID); 208 CGLTexImageIOSurface2D(cgl_ctx, GL_TEXTURE_RECTANGLE_EXT, GL_RGBA8, m_size.width(), m_size.height(), GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, m_ioSurface.get(), 0); 209 glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0); 210 211 return m_textureID; 212 } 213 214 } // namespace WebKit 215 216