• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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