1/*
2 * Copyright (C) 2009 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 COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF 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 "WebGLProgram.h"
31
32#include "WebGLRenderingContext.h"
33
34namespace WebCore {
35
36PassRefPtr<WebGLProgram> WebGLProgram::create(WebGLRenderingContext* ctx)
37{
38    return adoptRef(new WebGLProgram(ctx));
39}
40
41WebGLProgram::WebGLProgram(WebGLRenderingContext* ctx)
42    : WebGLObject(ctx)
43    , m_linkStatus(false)
44    , m_linkCount(0)
45{
46    setObject(context()->graphicsContext3D()->createProgram());
47}
48
49void WebGLProgram::deleteObjectImpl(Platform3DObject obj)
50{
51    context()->graphicsContext3D()->deleteProgram(obj);
52    if (m_vertexShader) {
53        m_vertexShader->onDetached();
54        m_vertexShader = 0;
55    }
56    if (m_fragmentShader) {
57        m_fragmentShader->onDetached();
58        m_fragmentShader = 0;
59    }
60}
61
62bool WebGLProgram::cacheActiveAttribLocations()
63{
64    m_activeAttribLocations.clear();
65    if (!object())
66        return false;
67    GraphicsContext3D* context3d = context()->graphicsContext3D();
68
69    // Assume link status has already been cached.
70    if (!m_linkStatus)
71        return false;
72
73    GC3Dint numAttribs = 0;
74    context3d->getProgramiv(object(), GraphicsContext3D::ACTIVE_ATTRIBUTES, &numAttribs);
75    m_activeAttribLocations.resize(static_cast<size_t>(numAttribs));
76    for (int i = 0; i < numAttribs; ++i) {
77        ActiveInfo info;
78        context3d->getActiveAttrib(object(), i, info);
79        m_activeAttribLocations[i] = context3d->getAttribLocation(object(), info.name.charactersWithNullTermination());
80    }
81
82    return true;
83}
84
85unsigned WebGLProgram::numActiveAttribLocations() const
86{
87    return m_activeAttribLocations.size();
88}
89
90GC3Dint WebGLProgram::getActiveAttribLocation(GC3Duint index) const
91{
92    if (index >= numActiveAttribLocations())
93        return -1;
94    return m_activeAttribLocations[index];
95}
96
97bool WebGLProgram::isUsingVertexAttrib0() const
98{
99    for (unsigned ii = 0; ii < numActiveAttribLocations(); ++ii) {
100        if (!getActiveAttribLocation(ii))
101            return true;
102    }
103    return false;
104}
105
106WebGLShader* WebGLProgram::getAttachedShader(GC3Denum type)
107{
108    switch (type) {
109    case GraphicsContext3D::VERTEX_SHADER:
110        return m_vertexShader.get();
111    case GraphicsContext3D::FRAGMENT_SHADER:
112        return m_fragmentShader.get();
113    default:
114        return 0;
115    }
116}
117
118bool WebGLProgram::attachShader(WebGLShader* shader)
119{
120    if (!shader || !shader->object())
121        return false;
122    switch (shader->getType()) {
123    case GraphicsContext3D::VERTEX_SHADER:
124        if (m_vertexShader)
125            return false;
126        m_vertexShader = shader;
127        return true;
128    case GraphicsContext3D::FRAGMENT_SHADER:
129        if (m_fragmentShader)
130            return false;
131        m_fragmentShader = shader;
132        return true;
133    default:
134        return false;
135    }
136}
137
138bool WebGLProgram::detachShader(WebGLShader* shader)
139{
140    if (!shader || !shader->object())
141        return false;
142    switch (shader->getType()) {
143    case GraphicsContext3D::VERTEX_SHADER:
144        if (m_vertexShader != shader)
145            return false;
146        m_vertexShader = 0;
147        return true;
148    case GraphicsContext3D::FRAGMENT_SHADER:
149        if (m_fragmentShader != shader)
150            return false;
151        m_fragmentShader = 0;
152        return true;
153    default:
154        return false;
155    }
156}
157
158}
159
160#endif // ENABLE(WEBGL)
161