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 35 PassRefPtr<WebGLBuffer> WebGLBuffer::create(WebGLRenderingContext* ctx) 36 { 37 return adoptRef(new WebGLBuffer(ctx)); 38 } 39 40 PassRefPtr<WebGLBuffer> WebGLBuffer::create(WebGLRenderingContext* ctx, Platform3DObject obj) 41 { 42 return adoptRef(new WebGLBuffer(ctx, obj)); 43 } 44 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 55 WebGLBuffer::WebGLBuffer(WebGLRenderingContext* ctx, Platform3DObject obj) 56 : CanvasObject(ctx) 57 , m_nextAvailableCacheEntry(0) 58 { 59 setObject(obj, false); 60 clearCachedMaxIndices(); 61 } 62 63 void WebGLBuffer::_deleteObject(Platform3DObject object) 64 { 65 context()->graphicsContext3D()->deleteBuffer(object); 66 } 67 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 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 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 132 unsigned WebGLBuffer::byteLength(unsigned long target) const 133 { 134 return (target == GraphicsContext3D::ARRAY_BUFFER) ? m_arrayBufferByteLength : m_elementArrayBufferByteLength; 135 } 136 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 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 159 void WebGLBuffer::clearCachedMaxIndices() 160 { 161 memset(m_maxIndexCache, 0, sizeof(m_maxIndexCache)); 162 } 163 164 } 165 166 #endif // ENABLE(3D_CANVAS) 167