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
Handle()50 ShareableSurface::Handle::Handle()
51 : m_port(MACH_PORT_NULL)
52 {
53 }
54
~Handle()55 ShareableSurface::Handle::~Handle()
56 {
57 if (m_port != MACH_PORT_NULL)
58 mach_port_deallocate(mach_task_self(), m_port);
59 }
60
encode(CoreIPC::ArgumentEncoder * encoder) const61 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
decode(CoreIPC::ArgumentDecoder * decoder,Handle & handle)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
createIOSurface(const IntSize & size)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
create(CGLContextObj cglContextObj,const IntSize & size)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
create(CGLContextObj cglContextObj,const Handle & handle)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
ShareableSurface(CGLContextObj cglContextObj,const IntSize & size,IOSurfaceRef ioSurface)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
~ShareableSurface()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
createHandle(Handle & handle)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
attach()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
detach()189 void ShareableSurface::detach()
190 {
191 DECLARE_GL_CONTEXT_VARIABLE(m_cglContextObj);
192
193 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
194 }
195
textureID()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