• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(3D_CANVAS)
29 
30 #include "WebGLBuffer.h"
31 #include "WebGLRenderingContext.h"
32 
33 namespace WebCore {
34 
create(WebGLRenderingContext * ctx)35 PassRefPtr<WebGLBuffer> WebGLBuffer::create(WebGLRenderingContext* ctx)
36 {
37     return adoptRef(new WebGLBuffer(ctx));
38 }
39 
create(WebGLRenderingContext * ctx,Platform3DObject obj)40 PassRefPtr<WebGLBuffer> WebGLBuffer::create(WebGLRenderingContext* ctx, Platform3DObject obj)
41 {
42     return adoptRef(new WebGLBuffer(ctx, obj));
43 }
44 
WebGLBuffer(WebGLRenderingContext * ctx)45 WebGLBuffer::WebGLBuffer(WebGLRenderingContext* ctx)
46     : CanvasObject(ctx)
47     , m_elementArrayBufferByteLength(0)
48     , m_arrayBufferByteLength(0)
49     , m_nextAvailableCacheEntry(0)
50 {
51     setObject(context()->graphicsContext3D()->createBuffer());
52     clearCachedMaxIndices();
53 }
54 
WebGLBuffer(WebGLRenderingContext * ctx,Platform3DObject obj)55 WebGLBuffer::WebGLBuffer(WebGLRenderingContext* ctx, Platform3DObject obj)
56     : CanvasObject(ctx)
57     , m_nextAvailableCacheEntry(0)
58 {
59     setObject(obj, false);
60     clearCachedMaxIndices();
61 }
62 
_deleteObject(Platform3DObject object)63 void WebGLBuffer::_deleteObject(Platform3DObject object)
64 {
65     context()->graphicsContext3D()->deleteBuffer(object);
66 }
67 
associateBufferData(unsigned long target,int size)68 bool WebGLBuffer::associateBufferData(unsigned long target, int size)
69 {
70     if (target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER) {
71         m_elementArrayBufferByteLength = size;
72         return true;
73     }
74 
75     if (target == GraphicsContext3D::ARRAY_BUFFER) {
76         m_arrayBufferByteLength = size;
77         return true;
78     }
79 
80     return false;
81 }
82 
associateBufferData(unsigned long target,WebGLArray * array)83 bool WebGLBuffer::associateBufferData(unsigned long target, WebGLArray* array)
84 {
85     if (!array)
86         return false;
87 
88     if (target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER) {
89         clearCachedMaxIndices();
90         m_elementArrayBufferByteLength = array->byteLength();
91         // We must always clone the incoming data because client-side
92         // modifications without calling bufferData or bufferSubData
93         // must never be able to change the validation results.
94         m_elementArrayBuffer = WebGLArrayBuffer::create(array->buffer().get());
95         return true;
96     }
97 
98     if (target == GraphicsContext3D::ARRAY_BUFFER) {
99         m_arrayBufferByteLength = array->byteLength();
100         return true;
101     }
102 
103     return false;
104 }
105 
associateBufferSubData(unsigned long target,long offset,WebGLArray * array)106 bool WebGLBuffer::associateBufferSubData(unsigned long target, long offset, WebGLArray* array)
107 {
108     if (!array)
109         return false;
110 
111     if (target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER) {
112         clearCachedMaxIndices();
113 
114         // We need to protect against integer overflow with these tests
115         if (offset < 0)
116             return false;
117 
118         unsigned long uoffset = static_cast<unsigned long>(offset);
119         if (uoffset > m_elementArrayBufferByteLength || array->byteLength() > m_elementArrayBufferByteLength - uoffset)
120             return false;
121 
122         memcpy(static_cast<unsigned char*>(m_elementArrayBuffer->data()) + offset, array->baseAddress(), array->byteLength());
123         return true;
124     }
125 
126     if (target == GraphicsContext3D::ARRAY_BUFFER)
127         return array->byteLength() + offset <= m_arrayBufferByteLength;
128 
129     return false;
130 }
131 
byteLength(unsigned long target) const132 unsigned WebGLBuffer::byteLength(unsigned long target) const
133 {
134     return (target == GraphicsContext3D::ARRAY_BUFFER) ? m_arrayBufferByteLength : m_elementArrayBufferByteLength;
135 }
136 
getCachedMaxIndex(unsigned long type)137 long WebGLBuffer::getCachedMaxIndex(unsigned long type)
138 {
139     size_t numEntries = sizeof(m_maxIndexCache) / sizeof(MaxIndexCacheEntry);
140     for (size_t i = 0; i < numEntries; i++)
141         if (m_maxIndexCache[i].type == type)
142             return m_maxIndexCache[i].maxIndex;
143     return -1;
144 }
145 
setCachedMaxIndex(unsigned long type,long value)146 void WebGLBuffer::setCachedMaxIndex(unsigned long type, long value)
147 {
148     int numEntries = sizeof(m_maxIndexCache) / sizeof(MaxIndexCacheEntry);
149     for (int i = 0; i < numEntries; i++)
150         if (m_maxIndexCache[i].type == type) {
151             m_maxIndexCache[i].maxIndex = value;
152             return;
153         }
154     m_maxIndexCache[m_nextAvailableCacheEntry].type = type;
155     m_maxIndexCache[m_nextAvailableCacheEntry].maxIndex = value;
156     m_nextAvailableCacheEntry = (m_nextAvailableCacheEntry + 1) % numEntries;
157 }
158 
clearCachedMaxIndices()159 void WebGLBuffer::clearCachedMaxIndices()
160 {
161     memset(m_maxIndexCache, 0, sizeof(m_maxIndexCache));
162 }
163 
164 }
165 
166 #endif // ENABLE(3D_CANVAS)
167