a3ec81acf559b08638541d8d7ae4b7d6645496b4
[WebKit-https.git] / Source / WebCore / platform / graphics / opengl / GraphicsContext3DOpenGLES.cpp
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  * Copyright (C) 2011 Google Inc. All rights reserved.
4  * Copyright (C) 2012 ChangSeok Oh <shivamidow@gmail.com>
5  * Copyright (C) 2012 Research In Motion Limited. All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
27  */
28
29 #include "config.h"
30
31 #if USE(3D_GRAPHICS)
32
33 #include "GraphicsContext3D.h"
34
35 #include "Extensions3DOpenGLES.h"
36 #include "IntRect.h"
37 #include "IntSize.h"
38 #include "NotImplemented.h"
39
40 namespace WebCore {
41
42 void GraphicsContext3D::releaseShaderCompiler()
43 {
44     makeContextCurrent();
45     ::glReleaseShaderCompiler();
46 }
47
48 void GraphicsContext3D::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, void* data)
49 {
50     makeContextCurrent();
51     // FIXME: remove the two glFlush calls when the driver bug is fixed, i.e.,
52     // all previous rendering calls should be done before reading pixels.
53     ::glFlush();
54     if (m_attrs.antialias && m_state.boundFBO == m_multisampleFBO) {
55          resolveMultisamplingIfNecessary(IntRect(x, y, width, height));
56         ::glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
57         ::glFlush();
58     }
59
60     ::glReadPixels(x, y, width, height, format, type, data);
61
62     if (m_attrs.antialias && m_state.boundFBO == m_multisampleFBO)
63         ::glBindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO);
64 }
65
66 void GraphicsContext3D::readPixelsAndConvertToBGRAIfNecessary(int x, int y, int width, int height, unsigned char* pixels)
67 {
68     ::glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
69     int totalBytes = width * height * 4;
70     if (isGLES2Compliant()) {
71         for (int i = 0; i < totalBytes; i += 4)
72             std::swap(pixels[i], pixels[i + 2]); // Convert to BGRA.
73     }
74 }
75
76 bool GraphicsContext3D::reshapeFBOs(const IntSize& size)
77 {
78     const int width = size.width();
79     const int height = size.height();
80     GLuint colorFormat = 0, pixelDataType = 0;
81     if (m_attrs.alpha) {
82         m_internalColorFormat = GL_RGBA;
83         colorFormat = GL_RGBA;
84         pixelDataType = GL_UNSIGNED_BYTE;
85     } else {
86         m_internalColorFormat = GL_RGB;
87         colorFormat = GL_RGB;
88         pixelDataType = GL_UNSIGNED_SHORT_5_6_5;
89     }
90
91     // We don't allow the logic where stencil is required and depth is not.
92     // See GraphicsContext3D::validateAttributes.
93     bool supportPackedDepthStencilBuffer = (m_attrs.stencil || m_attrs.depth) && getExtensions()->supports("GL_OES_packed_depth_stencil");
94
95     // Resize regular FBO.
96     bool mustRestoreFBO = false;
97     if (m_state.boundFBO != m_fbo) {
98         mustRestoreFBO = true;
99         ::glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
100     }
101
102     ASSERT(m_texture);
103     ::glBindTexture(GL_TEXTURE_2D, m_texture);
104     ::glTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, width, height, 0, colorFormat, pixelDataType, 0);
105     ::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0);
106
107     if (m_compositorTexture) {
108         ::glBindTexture(GL_TEXTURE_2D, m_compositorTexture);
109         ::glTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, width, height, 0, colorFormat, GL_UNSIGNED_BYTE, 0);
110         ::glBindTexture(GL_TEXTURE_2D, 0);
111     }
112
113     // We don't support antialiasing yet. See GraphicsContext3D::validateAttributes.
114     ASSERT(!m_attrs.antialias);
115
116     if (m_attrs.stencil || m_attrs.depth) {
117         // Use a 24 bit depth buffer where we know we have it.
118         if (supportPackedDepthStencilBuffer) {
119             ::glBindRenderbuffer(GL_RENDERBUFFER, m_depthStencilBuffer);
120             ::glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, width, height);
121             if (m_attrs.stencil)
122                 ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer);
123             if (m_attrs.depth)
124                 ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer);
125             ::glBindRenderbuffer(GL_RENDERBUFFER, 0);
126         } else {
127             if (m_attrs.stencil) {
128                 ::glBindRenderbuffer(GL_RENDERBUFFER, m_stencilBuffer);
129                 ::glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, width, height);
130                 ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_stencilBuffer);
131             }
132             if (m_attrs.depth) {
133                 ::glBindRenderbuffer(GL_RENDERBUFFER, m_depthBuffer);
134                 ::glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
135                 ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthBuffer);
136             }
137             ::glBindRenderbuffer(GL_RENDERBUFFER, 0);
138         }
139     }
140     if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
141         // FIXME: cleanup
142         notImplemented();
143     }
144
145     return mustRestoreFBO;
146 }
147
148 void GraphicsContext3D::resolveMultisamplingIfNecessary(const IntRect& rect)
149 {
150     // FIXME: We don't support antialiasing yet.
151     notImplemented();
152 }
153
154 void GraphicsContext3D::renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height)
155 {
156     makeContextCurrent();
157     ::glRenderbufferStorage(target, internalformat, width, height);
158 }
159
160 void GraphicsContext3D::getIntegerv(GC3Denum pname, GC3Dint* value)
161 {
162     makeContextCurrent();
163     ::glGetIntegerv(pname, value);
164 }
165
166 void GraphicsContext3D::getShaderPrecisionFormat(GC3Denum shaderType, GC3Denum precisionType, GC3Dint* range, GC3Dint* precision)
167 {
168     ASSERT(range);
169     ASSERT(precision);
170
171     makeContextCurrent();
172     ::glGetShaderPrecisionFormat(shaderType, precisionType, range, precision);
173 }
174
175 bool GraphicsContext3D::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels)
176 {
177     if (width && height && !pixels) {
178         synthesizeGLError(INVALID_VALUE);
179         return false;
180     }
181
182     texImage2DDirect(target, level, internalformat, width, height, border, format, type, pixels);
183     return true;
184 }
185
186 void GraphicsContext3D::validateAttributes()
187 {
188     validateDepthStencil("GL_OES_packed_depth_stencil");
189
190     if (m_attrs.antialias) {
191         Extensions3D* extensions = getExtensions();
192         if (!extensions->supports("GL_IMG_multisampled_render_to_texture"))
193             m_attrs.antialias = false;
194     }
195 }
196
197 void GraphicsContext3D::depthRange(GC3Dclampf zNear, GC3Dclampf zFar)
198 {
199     makeContextCurrent();
200     ::glDepthRangef(zNear, zFar);
201 }
202
203 void GraphicsContext3D::clearDepth(GC3Dclampf depth)
204 {
205     makeContextCurrent();
206     ::glClearDepthf(depth);
207 }
208
209
210 Extensions3D* GraphicsContext3D::getExtensions()
211 {
212     if (!m_extensions)
213         m_extensions = adoptPtr(new Extensions3DOpenGLES(this));
214     return m_extensions.get();
215 }
216
217 }
218
219 #endif // USE(3D_GRAPHICS)