1/*
2 * Copyright (C) 2009 Apple Inc. All rights reserved.
3 * Copyright (C) 2011 Igalia S.L.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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 COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "config.h"
28#include "GraphicsContext3D.h"
29
30#if ENABLE(WEBGL)
31
32#include "Extensions3DOpenGL.h"
33#include "GraphicsContext3DInternal.h"
34#include "OpenGLShims.h"
35#include "ShaderLang.h"
36#include <wtf/NotFound.h>
37
38namespace WebCore {
39
40PassRefPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attributes attributes, HostWindow* hostWindow, GraphicsContext3D::RenderStyle renderStyle)
41{
42    // This implementation doesn't currently support rendering directly to the HostWindow.
43    if (renderStyle == RenderDirectlyToHostWindow)
44        return 0;
45
46    GraphicsContext3DInternal* internal = GraphicsContext3DInternal::create();
47    if (!internal)
48        return 0;
49
50    RefPtr<GraphicsContext3D> context = adoptRef(new GraphicsContext3D(attributes, hostWindow, false));
51    context->m_internal.set(internal);
52    return context.release();
53}
54
55GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attributes, HostWindow*, bool)
56    : m_currentWidth(0)
57    , m_currentHeight(0)
58    , m_attrs(attributes)
59    , m_texture(0)
60    , m_fbo(0)
61    , m_depthStencilBuffer(0)
62    , m_boundFBO(0)
63    , m_multisampleFBO(0)
64    , m_multisampleDepthStencilBuffer(0)
65    , m_multisampleColorBuffer(0)
66{
67    GraphicsContext3DInternal::addActiveGraphicsContext(this);
68
69    validateAttributes();
70
71    // Create a texture to render into.
72    ::glGenTextures(1, &m_texture);
73    ::glBindTexture(GL_TEXTURE_2D, m_texture);
74    ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
75    ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
76    ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
77    ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
78    ::glBindTexture(GL_TEXTURE_2D, 0);
79
80    // Create an FBO.
81    ::glGenFramebuffersEXT(1, &m_fbo);
82    ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
83
84    m_boundFBO = m_fbo;
85    if (!m_attrs.antialias && (m_attrs.stencil || m_attrs.depth))
86        ::glGenRenderbuffersEXT(1, &m_depthStencilBuffer);
87
88    // Create a multisample FBO.
89    if (m_attrs.antialias) {
90        ::glGenFramebuffersEXT(1, &m_multisampleFBO);
91        ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO);
92        m_boundFBO = m_multisampleFBO;
93        ::glGenRenderbuffersEXT(1, &m_multisampleColorBuffer);
94        if (m_attrs.stencil || m_attrs.depth)
95            ::glGenRenderbuffersEXT(1, &m_multisampleDepthStencilBuffer);
96    }
97
98    // ANGLE initialization.
99    ShBuiltInResources ANGLEResources;
100    ShInitBuiltInResources(&ANGLEResources);
101
102    getIntegerv(GraphicsContext3D::MAX_VERTEX_ATTRIBS, &ANGLEResources.MaxVertexAttribs);
103    getIntegerv(GraphicsContext3D::MAX_VERTEX_UNIFORM_VECTORS, &ANGLEResources.MaxVertexUniformVectors);
104    getIntegerv(GraphicsContext3D::MAX_VARYING_VECTORS, &ANGLEResources.MaxVaryingVectors);
105    getIntegerv(GraphicsContext3D::MAX_VERTEX_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxVertexTextureImageUnits);
106    getIntegerv(GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxCombinedTextureImageUnits);
107    getIntegerv(GraphicsContext3D::MAX_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxTextureImageUnits);
108    getIntegerv(GraphicsContext3D::MAX_FRAGMENT_UNIFORM_VECTORS, &ANGLEResources.MaxFragmentUniformVectors);
109
110    // Always set to 1 for OpenGL ES.
111    ANGLEResources.MaxDrawBuffers = 1;
112    m_compiler.setResources(ANGLEResources);
113
114    ::glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
115    ::glEnable(GL_POINT_SPRITE);
116    ::glClearColor(0, 0, 0, 0);
117}
118
119GraphicsContext3D::~GraphicsContext3D()
120{
121    GraphicsContext3DInternal::removeActiveGraphicsContext(this);
122    if (!m_internal->m_context)
123        return;
124
125    makeContextCurrent();
126    ::glDeleteTextures(1, &m_texture);
127    if (m_attrs.antialias) {
128        ::glDeleteRenderbuffersEXT(1, &m_multisampleColorBuffer);
129        if (m_attrs.stencil || m_attrs.depth)
130            ::glDeleteRenderbuffersEXT(1, &m_multisampleDepthStencilBuffer);
131        ::glDeleteFramebuffersEXT(1, &m_multisampleFBO);
132    } else {
133        if (m_attrs.stencil || m_attrs.depth)
134            ::glDeleteRenderbuffersEXT(1, &m_depthStencilBuffer);
135    }
136    ::glDeleteFramebuffersEXT(1, &m_fbo);
137}
138
139void GraphicsContext3D::makeContextCurrent()
140{
141    if (!m_internal)
142        return;
143    m_internal->makeContextCurrent();
144}
145
146PlatformGraphicsContext3D GraphicsContext3D::platformGraphicsContext3D()
147{
148    return m_internal->m_context;
149}
150
151bool GraphicsContext3D::isGLES2Compliant() const
152{
153    return false;
154}
155
156}
157
158#endif // ENABLE(WEBGL)
159