2 * Copyright (C) 2009 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
28 #include "core/html/canvas/WebGLTexture.h"
30 #include "core/html/canvas/WebGLRenderingContextBase.h"
34 PassRefPtrWillBeRawPtr<WebGLTexture> WebGLTexture::create(WebGLRenderingContextBase* ctx)
36 return adoptRefWillBeNoop(new WebGLTexture(ctx));
39 WebGLTexture::WebGLTexture(WebGLRenderingContextBase* ctx)
40 : WebGLSharedObject(ctx)
42 , m_minFilter(GL_NEAREST_MIPMAP_LINEAR)
43 , m_magFilter(GL_LINEAR)
47 , m_isCubeComplete(false)
49 , m_needToUseBlackTexture(false)
50 , m_isFloatType(false)
51 , m_isHalfFloatType(false)
53 ScriptWrappable::init(this);
54 setObject(ctx->webContext()->createTexture());
57 WebGLTexture::~WebGLTexture()
59 // Always perform detach here to ensure that platform object
60 // deletion happens with Oilpan enabled. It keeps the code regular
61 // to do it with or without Oilpan enabled.
63 // See comment in WebGLBuffer's destructor for additional
64 // information on why this is done for WebGLSharedObject-derived
66 detachAndDeleteObject();
69 void WebGLTexture::setTarget(GLenum target, GLint maxLevel)
73 // Target is finalized the first time bindTexture() is called.
80 m_info[0].resize(maxLevel);
82 case GL_TEXTURE_CUBE_MAP:
85 for (int ii = 0; ii < 6; ++ii)
86 m_info[ii].resize(maxLevel);
91 void WebGLTexture::setParameteri(GLenum pname, GLint param)
93 if (!object() || !m_target)
96 case GL_TEXTURE_MIN_FILTER:
100 case GL_NEAREST_MIPMAP_NEAREST:
101 case GL_LINEAR_MIPMAP_NEAREST:
102 case GL_NEAREST_MIPMAP_LINEAR:
103 case GL_LINEAR_MIPMAP_LINEAR:
108 case GL_TEXTURE_MAG_FILTER:
116 case GL_TEXTURE_WRAP_S:
118 case GL_CLAMP_TO_EDGE:
119 case GL_MIRRORED_REPEAT:
125 case GL_TEXTURE_WRAP_T:
127 case GL_CLAMP_TO_EDGE:
128 case GL_MIRRORED_REPEAT:
140 void WebGLTexture::setParameterf(GLenum pname, GLfloat param)
142 if (!object() || !m_target)
144 GLint iparam = static_cast<GLint>(param);
145 setParameteri(pname, iparam);
148 void WebGLTexture::setLevelInfo(GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum type)
150 if (!object() || !m_target)
152 // We assume level, internalFormat, width, height, and type have all been
153 // validated already.
154 int index = mapTargetToIndex(target);
157 m_info[index][level].setInfo(internalFormat, width, height, type);
161 void WebGLTexture::generateMipmapLevelInfo()
163 if (!object() || !m_target)
165 if (!canGenerateMipmaps())
168 for (size_t ii = 0; ii < m_info.size(); ++ii) {
169 const LevelInfo& info0 = m_info[ii][0];
170 GLsizei width = info0.width;
171 GLsizei height = info0.height;
172 GLint levelCount = computeLevelCount(width, height);
173 for (GLint level = 1; level < levelCount; ++level) {
174 width = std::max(1, width >> 1);
175 height = std::max(1, height >> 1);
176 LevelInfo& info = m_info[ii][level];
177 info.setInfo(info0.internalFormat, width, height, info0.type);
182 m_needToUseBlackTexture = false;
185 GLenum WebGLTexture::getInternalFormat(GLenum target, GLint level) const
187 const LevelInfo* info = getLevelInfo(target, level);
190 return info->internalFormat;
193 GLenum WebGLTexture::getType(GLenum target, GLint level) const
195 const LevelInfo* info = getLevelInfo(target, level);
201 GLsizei WebGLTexture::getWidth(GLenum target, GLint level) const
203 const LevelInfo* info = getLevelInfo(target, level);
209 GLsizei WebGLTexture::getHeight(GLenum target, GLint level) const
211 const LevelInfo* info = getLevelInfo(target, level);
217 bool WebGLTexture::isValid(GLenum target, GLint level) const
219 const LevelInfo* info = getLevelInfo(target, level);
225 bool WebGLTexture::isNPOT(GLsizei width, GLsizei height)
227 ASSERT(width >= 0 && height >= 0);
228 if (!width || !height)
230 if ((width & (width - 1)) || (height & (height - 1)))
235 bool WebGLTexture::isNPOT() const
242 bool WebGLTexture::needToUseBlackTexture(TextureExtensionFlag flag) const
246 if (m_needToUseBlackTexture)
248 if ((m_isFloatType && !(flag & TextureFloatLinearExtensionEnabled)) || (m_isHalfFloatType && !(flag && TextureHalfFloatLinearExtensionEnabled))) {
249 if (m_magFilter != GL_NEAREST || (m_minFilter != GL_NEAREST && m_minFilter != GL_NEAREST_MIPMAP_NEAREST))
255 void WebGLTexture::deleteObjectImpl(blink::WebGraphicsContext3D* context3d, Platform3DObject object)
257 context3d->deleteTexture(object);
260 int WebGLTexture::mapTargetToIndex(GLenum target) const
262 if (m_target == GL_TEXTURE_2D) {
263 if (target == GL_TEXTURE_2D)
265 } else if (m_target == GL_TEXTURE_CUBE_MAP) {
267 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
269 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
271 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
273 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
275 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
277 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
284 bool WebGLTexture::canGenerateMipmaps()
288 const LevelInfo& first = m_info[0][0];
289 for (size_t ii = 0; ii < m_info.size(); ++ii) {
290 const LevelInfo& info = m_info[ii][0];
292 || info.width != first.width || info.height != first.height
293 || info.internalFormat != first.internalFormat || info.type != first.type
294 || (m_info.size() > 1 && !m_isCubeComplete))
300 GLint WebGLTexture::computeLevelCount(GLsizei width, GLsizei height)
302 // return 1 + log2Floor(std::max(width, height));
303 GLsizei n = std::max(width, height);
308 for (int ii = 4; ii >= 0; --ii) {
309 int shift = (1 << ii);
310 GLsizei x = (value >> shift);
320 void WebGLTexture::update()
323 for (size_t ii = 0; ii < m_info.size(); ++ii) {
324 if (isNPOT(m_info[ii][0].width, m_info[ii][0].height)) {
330 m_isCubeComplete = true;
331 const LevelInfo& first = m_info[0][0];
332 GLint levelCount = computeLevelCount(first.width, first.height);
334 m_isComplete = false;
336 for (size_t ii = 0; ii < m_info.size() && m_isComplete; ++ii) {
337 const LevelInfo& info0 = m_info[ii][0];
339 || info0.width != first.width || info0.height != first.height
340 || info0.internalFormat != first.internalFormat || info0.type != first.type
341 || (m_info.size() > 1 && info0.width != info0.height)) {
342 if (m_info.size() > 1)
343 m_isCubeComplete = false;
344 m_isComplete = false;
347 GLsizei width = info0.width;
348 GLsizei height = info0.height;
349 for (GLint level = 1; level < levelCount; ++level) {
350 width = std::max(1, width >> 1);
351 height = std::max(1, height >> 1);
352 const LevelInfo& info = m_info[ii][level];
354 || info.width != width || info.height != height
355 || info.internalFormat != info0.internalFormat || info.type != info0.type) {
356 m_isComplete = false;
363 m_isFloatType = m_info[0][0].type == GL_FLOAT;
364 m_isHalfFloatType = m_info[0][0].type == GL_HALF_FLOAT_OES;
366 m_needToUseBlackTexture = false;
368 if (m_isNPOT && ((m_minFilter != GL_NEAREST && m_minFilter != GL_LINEAR)
369 || m_wrapS != GL_CLAMP_TO_EDGE || m_wrapT != GL_CLAMP_TO_EDGE))
370 m_needToUseBlackTexture = true;
371 // If it is a Cube texture, check Cube Completeness first
372 if (m_info.size() > 1 && !m_isCubeComplete)
373 m_needToUseBlackTexture = true;
375 if (!m_isComplete && m_minFilter != GL_NEAREST && m_minFilter != GL_LINEAR)
376 m_needToUseBlackTexture = true;
379 const WebGLTexture::LevelInfo* WebGLTexture::getLevelInfo(GLenum target, GLint level) const
381 if (!object() || !m_target)
383 int targetIndex = mapTargetToIndex(target);
384 if (targetIndex < 0 || targetIndex >= static_cast<int>(m_info.size()))
386 if (level < 0 || level >= static_cast<GLint>(m_info[targetIndex].size()))
388 return &(m_info[targetIndex][level]);