Remove remaining PLATFORM(CHROMIUM)-guarded code in WebCore
[WebKit-https.git] / Source / WebCore / html / canvas / EXTDrawBuffers.cpp
1 /*
2  * Copyright (C) 2013 Google 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  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27
28 #if ENABLE(WEBGL)
29
30 #include "EXTDrawBuffers.h"
31
32 #include "Extensions3D.h"
33
34 namespace WebCore {
35
36 EXTDrawBuffers::EXTDrawBuffers(WebGLRenderingContext* context)
37     : WebGLExtension(context)
38 {
39 }
40
41 EXTDrawBuffers::~EXTDrawBuffers()
42 {
43 }
44
45 WebGLExtension::ExtensionName EXTDrawBuffers::getName() const
46 {
47     return WebGLExtension::EXTDrawBuffersName;
48 }
49
50 PassOwnPtr<EXTDrawBuffers> EXTDrawBuffers::create(WebGLRenderingContext* context)
51 {
52     return adoptPtr(new EXTDrawBuffers(context));
53 }
54
55 // static
56 bool EXTDrawBuffers::supported(WebGLRenderingContext* context)
57 {
58 #if OS(DARWIN)
59     // https://bugs.webkit.org/show_bug.cgi?id=112486
60     return false;
61 #endif
62     Extensions3D* extensions = context->graphicsContext3D()->getExtensions();
63     return (extensions->supports("GL_EXT_draw_buffers")
64         && satisfiesWebGLRequirements(context));
65 }
66
67 void EXTDrawBuffers::drawBuffersEXT(const Vector<GC3Denum>& buffers)
68 {
69     if (m_context->isContextLost())
70         return;
71     GC3Dsizei n = buffers.size();
72     const GC3Denum* bufs = buffers.data();
73     if (!m_context->m_framebufferBinding) {
74         if (n != 1) {
75             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "drawBuffersEXT", "more than one buffer");
76             return;
77         }
78         if (bufs[0] != GraphicsContext3D::BACK && bufs[0] != GraphicsContext3D::NONE) {
79             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "drawBuffersEXT", "BACK or NONE");
80             return;
81         }
82         // Because the backbuffer is simulated on all current WebKit ports, we need to change BACK to COLOR_ATTACHMENT0.
83         GC3Denum value = (bufs[0] == GraphicsContext3D::BACK) ? GraphicsContext3D::COLOR_ATTACHMENT0 : GraphicsContext3D::NONE;
84         m_context->graphicsContext3D()->getExtensions()->drawBuffersEXT(1, &value);
85         m_context->setBackDrawBuffer(bufs[0]);
86     } else {
87         if (n > m_context->getMaxDrawBuffers()) {
88             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "drawBuffersEXT", "more than max draw buffers");
89             return;
90         }
91         for (GC3Dsizei i = 0; i < n; ++i) {
92             if (bufs[i] != GraphicsContext3D::NONE && bufs[i] != static_cast<GC3Denum>(Extensions3D::COLOR_ATTACHMENT0_EXT + i)) {
93                 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "drawBuffersEXT", "COLOR_ATTACHMENTi_EXT or NONE");
94                 return;
95             }
96         }
97         m_context->m_framebufferBinding->drawBuffers(buffers);
98     }
99 }
100
101 // static
102 bool EXTDrawBuffers::satisfiesWebGLRequirements(WebGLRenderingContext* webglContext)
103 {
104     GraphicsContext3D* context = webglContext->graphicsContext3D();
105
106     // This is called after we make sure GL_EXT_draw_buffers is supported.
107     GC3Dint maxDrawBuffers = 0;
108     GC3Dint maxColorAttachments = 0;
109     context->getIntegerv(Extensions3D::MAX_DRAW_BUFFERS_EXT, &maxDrawBuffers);
110     context->getIntegerv(Extensions3D::MAX_COLOR_ATTACHMENTS_EXT, &maxColorAttachments);
111     if (maxDrawBuffers < 4 || maxColorAttachments < 4)
112         return false;
113
114     Platform3DObject fbo = context->createFramebuffer();
115     context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, fbo);
116
117     const unsigned char buffer[4] = { 0, 0, 0, 0 }; // textures are required to be initialized for other ports.
118     bool supportsDepth = (context->getExtensions()->supports("GL_CHROMIUM_depth_texture")
119         || context->getExtensions()->supports("GL_OES_depth_texture")
120         || context->getExtensions()->supports("GL_ARB_depth_texture"));
121     bool supportsDepthStencil = (context->getExtensions()->supports("GL_EXT_packed_depth_stencil")
122         || context->getExtensions()->supports("GL_OES_packed_depth_stencil"));
123     Platform3DObject depthStencil = 0;
124     if (supportsDepthStencil) {
125         depthStencil = context->createTexture();
126         context->bindTexture(GraphicsContext3D::TEXTURE_2D, depthStencil);
127         context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::DEPTH_STENCIL, 1, 1, 0, GraphicsContext3D::DEPTH_STENCIL, GraphicsContext3D::UNSIGNED_INT_24_8, buffer);
128     }
129     Platform3DObject depth = 0;
130     if (supportsDepth) {
131         depth = context->createTexture();
132         context->bindTexture(GraphicsContext3D::TEXTURE_2D, depth);
133         context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::DEPTH_COMPONENT, 1, 1, 0, GraphicsContext3D::DEPTH_COMPONENT, GraphicsContext3D::UNSIGNED_INT, buffer);
134     }
135
136     Vector<Platform3DObject> colors;
137     bool ok = true;
138     GC3Dint maxAllowedBuffers = std::min(maxDrawBuffers, maxColorAttachments);
139     for (GC3Dint i = 0; i < maxAllowedBuffers; ++i) {
140         Platform3DObject color = context->createTexture();
141         colors.append(color);
142         context->bindTexture(GraphicsContext3D::TEXTURE_2D, color);
143         context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, 1, 1, 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, buffer);
144         context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0 + i, GraphicsContext3D::TEXTURE_2D, color, 0);
145         if (context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
146             ok = false;
147             break;
148         }
149         if (supportsDepth) {
150             context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::TEXTURE_2D, depth, 0);
151             if (context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
152                 ok = false;
153                 break;
154             }
155             context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::TEXTURE_2D, 0, 0);
156         }
157         if (supportsDepthStencil) {
158             context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::TEXTURE_2D, depthStencil, 0);
159             context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::TEXTURE_2D, depthStencil, 0);
160             if (context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
161                 ok = false;
162                 break;
163             }
164             context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::TEXTURE_2D, 0, 0);
165             context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::TEXTURE_2D, 0, 0);
166         }
167     }
168
169     webglContext->restoreCurrentFramebuffer();
170     context->deleteFramebuffer(fbo);
171     webglContext->restoreCurrentTexture2D();
172     if (supportsDepth)
173         context->deleteTexture(depth);
174     if (supportsDepthStencil)
175         context->deleteTexture(depthStencil);
176     for (size_t i = 0; i < colors.size(); ++i)
177         context->deleteTexture(colors[i]);
178     return ok;
179 }
180
181 } // namespace WebCore
182
183 #endif // ENABLE(WEBGL)