| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2009 Apple Inc. All rights reserved. | 2 * Copyright (C) 2009 Apple Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 namespace blink { | 30 namespace blink { |
| 31 | 31 |
| 32 WebGLTexture* WebGLTexture::create(WebGLRenderingContextBase* ctx) | 32 WebGLTexture* WebGLTexture::create(WebGLRenderingContextBase* ctx) |
| 33 { | 33 { |
| 34 return new WebGLTexture(ctx); | 34 return new WebGLTexture(ctx); |
| 35 } | 35 } |
| 36 | 36 |
| 37 WebGLTexture::WebGLTexture(WebGLRenderingContextBase* ctx) | 37 WebGLTexture::WebGLTexture(WebGLRenderingContextBase* ctx) |
| 38 : WebGLSharedPlatform3DObject(ctx) | 38 : WebGLSharedPlatform3DObject(ctx) |
| 39 , m_target(0) | 39 , m_target(0) |
| 40 , m_isNPOT(false) | |
| 41 , m_isCubeComplete(false) | |
| 42 , m_isComplete(false) | |
| 43 , m_isFloatType(false) | |
| 44 , m_isHalfFloatType(false) | |
| 45 , m_isWebGL2OrHigher(ctx->isWebGL2OrHigher()) | 40 , m_isWebGL2OrHigher(ctx->isWebGL2OrHigher()) |
| 46 , m_immutable(false) | |
| 47 , m_baseLevel(0) | 41 , m_baseLevel(0) |
| 48 , m_maxLevel(1000) | 42 , m_maxLevel(1000) |
| 49 { | 43 { |
| 50 setObject(ctx->webContext()->createTexture()); | 44 setObject(ctx->webContext()->createTexture()); |
| 51 } | 45 } |
| 52 | 46 |
| 53 WebGLTexture::~WebGLTexture() | 47 WebGLTexture::~WebGLTexture() |
| 54 { | 48 { |
| 55 // See the comment in WebGLObject::detachAndDeleteObject(). | 49 // See the comment in WebGLObject::detachAndDeleteObject(). |
| 56 detachAndDeleteObject(); | 50 detachAndDeleteObject(); |
| 57 } | 51 } |
| 58 | 52 |
| 59 void WebGLTexture::setTarget(GLenum target, GLint maxLevel) | 53 void WebGLTexture::setTarget(GLenum target, GLint maxLevel) |
| 60 { | 54 { |
| 61 if (!object()) | 55 if (!object()) |
| 62 return; | 56 return; |
| 63 // Target is finalized the first time bindTexture() is called. | 57 // Target is finalized the first time bindTexture() is called. |
| 64 if (m_target) | 58 if (m_target) |
| 65 return; | 59 return; |
| 66 switch (target) { | 60 m_target = target; |
| 67 case GL_TEXTURE_2D: | |
| 68 case GL_TEXTURE_2D_ARRAY: | |
| 69 case GL_TEXTURE_3D: | |
| 70 m_target = target; | |
| 71 m_info.resize(1); | |
| 72 m_info[0].resize(maxLevel); | |
| 73 break; | |
| 74 case GL_TEXTURE_CUBE_MAP: | |
| 75 m_target = target; | |
| 76 m_info.resize(6); | |
| 77 for (int ii = 0; ii < 6; ++ii) | |
| 78 m_info[ii].resize(maxLevel); | |
| 79 break; | |
| 80 } | |
| 81 } | 61 } |
| 82 | 62 |
| 83 void WebGLTexture::setParameteri(GLenum pname, GLint param) | 63 void WebGLTexture::setParameteri(GLenum pname, GLint param) |
| 84 { | 64 { |
| 85 if (!object() || !m_target) | 65 if (!object() || !m_target) |
| 86 return; | 66 return; |
| 87 switch (pname) { | 67 switch (pname) { |
| 88 case GL_TEXTURE_MIN_FILTER: | 68 case GL_TEXTURE_MIN_FILTER: |
| 89 switch (param) { | 69 switch (param) { |
| 90 case GL_NEAREST: | 70 case GL_NEAREST: |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 136 if (m_isWebGL2OrHigher && param >= 0) | 116 if (m_isWebGL2OrHigher && param >= 0) |
| 137 m_baseLevel = param; | 117 m_baseLevel = param; |
| 138 break; | 118 break; |
| 139 case GL_TEXTURE_MAX_LEVEL: | 119 case GL_TEXTURE_MAX_LEVEL: |
| 140 if (m_isWebGL2OrHigher && param >= 0) | 120 if (m_isWebGL2OrHigher && param >= 0) |
| 141 m_maxLevel = param; | 121 m_maxLevel = param; |
| 142 break; | 122 break; |
| 143 default: | 123 default: |
| 144 return; | 124 return; |
| 145 } | 125 } |
| 146 update(); | |
| 147 } | 126 } |
| 148 | 127 |
| 149 void WebGLTexture::setParameterf(GLenum pname, GLfloat param) | 128 void WebGLTexture::setParameterf(GLenum pname, GLfloat param) |
| 150 { | 129 { |
| 151 if (!object() || !m_target) | 130 if (!object() || !m_target) |
| 152 return; | 131 return; |
| 153 GLint iparam = static_cast<GLint>(param); | 132 GLint iparam = static_cast<GLint>(param); |
| 154 setParameteri(pname, iparam); | 133 setParameteri(pname, iparam); |
| 155 } | 134 } |
| 156 | 135 |
| 157 void WebGLTexture::setLevelInfo(GLenum target, GLint level, GLenum internalForma
t, GLsizei width, GLsizei height, GLsizei depth, GLenum type) | |
| 158 { | |
| 159 ASSERT(!m_immutable); | |
| 160 | |
| 161 if (!object() || !m_target) | |
| 162 return; | |
| 163 // We assume level, internalFormat, width, height, depth, and type have all
been | |
| 164 // validated already. | |
| 165 int index = mapTargetToIndex(target); | |
| 166 if (index < 0) | |
| 167 return; | |
| 168 m_info[index][level].setInfo(internalFormat, width, height, depth, type); | |
| 169 update(); | |
| 170 } | |
| 171 | |
| 172 void WebGLTexture::setTexStorageInfo(GLenum target, GLint levels, GLenum interna
lFormat, GLsizei width, GLsizei height, GLsizei depth) | |
| 173 { | |
| 174 ASSERT(!m_immutable); | |
| 175 | |
| 176 // We assume level, internalFormat, width, height, and depth have all been | |
| 177 // validated already. | |
| 178 if (!object() || !m_target || target != m_target) | |
| 179 return; | |
| 180 | |
| 181 GLenum type = getValidTypeForInternalFormat(internalFormat); | |
| 182 if (type == GL_NONE) | |
| 183 return; | |
| 184 | |
| 185 for (size_t ii = 0; ii < m_info.size(); ++ii) { | |
| 186 GLsizei levelWidth = width; | |
| 187 GLsizei levelHeight = height; | |
| 188 GLsizei levelDepth = depth; | |
| 189 for (GLint level = 0; level < levels; ++level) { | |
| 190 LevelInfo& info = m_info[ii][level]; | |
| 191 info.setInfo(internalFormat, levelWidth, levelHeight, levelDepth, ty
pe); | |
| 192 levelWidth = std::max(1, levelWidth >> 1); | |
| 193 levelHeight = std::max(1, levelHeight >> 1); | |
| 194 levelDepth = m_target == GL_TEXTURE_2D_ARRAY ? levelDepth : std::max
(1, levelDepth >> 1); | |
| 195 } | |
| 196 } | |
| 197 update(); | |
| 198 | |
| 199 m_immutable = true; | |
| 200 } | |
| 201 | |
| 202 void WebGLTexture::generateMipmapLevelInfo() | |
| 203 { | |
| 204 if (!object() || !m_target) | |
| 205 return; | |
| 206 if (!canGenerateMipmaps()) | |
| 207 return; | |
| 208 if (!m_isComplete) { | |
| 209 for (size_t ii = 0; ii < m_info.size(); ++ii) { | |
| 210 const LevelInfo& info0 = m_info[ii][m_baseLevel]; | |
| 211 GLsizei width = info0.width; | |
| 212 GLsizei height = info0.height; | |
| 213 GLsizei depth = info0.depth; | |
| 214 GLint levelCount = computeLevelCount(width, height, (m_target == GL_
TEXTURE_2D_ARRAY ? 0 : depth)); | |
| 215 size_t maxLevel = 0; | |
| 216 if (m_baseLevel + levelCount > 0) | |
| 217 maxLevel = m_baseLevel + levelCount - 1; | |
| 218 maxLevel = m_isWebGL2OrHigher ? std::min(m_maxLevel, maxLevel) : max
Level; | |
| 219 ASSERT(maxLevel < m_info[ii].size()); | |
| 220 for (size_t level = m_baseLevel + 1; level <= maxLevel; ++level) { | |
| 221 width = std::max(1, width >> 1); | |
| 222 height = std::max(1, height >> 1); | |
| 223 depth = m_target == GL_TEXTURE_2D_ARRAY ? depth : std::max(1, de
pth >> 1); | |
| 224 LevelInfo& info = m_info[ii][level]; | |
| 225 info.setInfo(info0.internalFormat, width, height, depth, info0.t
ype); | |
| 226 } | |
| 227 } | |
| 228 m_isComplete = true; | |
| 229 } | |
| 230 } | |
| 231 | |
| 232 GLenum WebGLTexture::getInternalFormat(GLenum target, GLint level) const | |
| 233 { | |
| 234 const LevelInfo* info = getLevelInfo(target, level); | |
| 235 if (!info) | |
| 236 return 0; | |
| 237 return info->internalFormat; | |
| 238 } | |
| 239 | |
| 240 GLenum WebGLTexture::getType(GLenum target, GLint level) const | |
| 241 { | |
| 242 const LevelInfo* info = getLevelInfo(target, level); | |
| 243 if (!info) | |
| 244 return 0; | |
| 245 return info->type; | |
| 246 } | |
| 247 | |
| 248 GLsizei WebGLTexture::getWidth(GLenum target, GLint level) const | |
| 249 { | |
| 250 const LevelInfo* info = getLevelInfo(target, level); | |
| 251 if (!info) | |
| 252 return 0; | |
| 253 return info->width; | |
| 254 } | |
| 255 | |
| 256 GLsizei WebGLTexture::getHeight(GLenum target, GLint level) const | |
| 257 { | |
| 258 const LevelInfo* info = getLevelInfo(target, level); | |
| 259 if (!info) | |
| 260 return 0; | |
| 261 return info->height; | |
| 262 } | |
| 263 | |
| 264 GLsizei WebGLTexture::getDepth(GLenum target, GLint level) const | |
| 265 { | |
| 266 const LevelInfo* info = getLevelInfo(target, level); | |
| 267 if (!info) | |
| 268 return 0; | |
| 269 return info->depth; | |
| 270 } | |
| 271 | |
| 272 bool WebGLTexture::isValid(GLenum target, GLint level) const | |
| 273 { | |
| 274 const LevelInfo* info = getLevelInfo(target, level); | |
| 275 if (!info) | |
| 276 return 0; | |
| 277 return info->valid; | |
| 278 } | |
| 279 | |
| 280 bool WebGLTexture::isNPOT(GLsizei width, GLsizei height) | 136 bool WebGLTexture::isNPOT(GLsizei width, GLsizei height) |
| 281 { | 137 { |
| 282 ASSERT(width >= 0 && height >= 0); | 138 ASSERT(width >= 0 && height >= 0); |
| 283 if (!width || !height) | 139 if (!width || !height) |
| 284 return false; | 140 return false; |
| 285 if ((width & (width - 1)) || (height & (height - 1))) | 141 if ((width & (width - 1)) || (height & (height - 1))) |
| 286 return true; | 142 return true; |
| 287 return false; | 143 return false; |
| 288 } | 144 } |
| 289 | 145 |
| 290 bool WebGLTexture::isNPOT() const | |
| 291 { | |
| 292 if (!object()) | |
| 293 return false; | |
| 294 return m_isNPOT; | |
| 295 } | |
| 296 | |
| 297 void WebGLTexture::deleteObjectImpl(WebGraphicsContext3D* context3d) | 146 void WebGLTexture::deleteObjectImpl(WebGraphicsContext3D* context3d) |
| 298 { | 147 { |
| 299 context3d->deleteTexture(m_object); | 148 context3d->deleteTexture(m_object); |
| 300 m_object = 0; | 149 m_object = 0; |
| 301 } | 150 } |
| 302 | 151 |
| 303 int WebGLTexture::mapTargetToIndex(GLenum target) const | 152 int WebGLTexture::mapTargetToIndex(GLenum target) const |
| 304 { | 153 { |
| 305 if (m_target == GL_TEXTURE_2D) { | 154 if (m_target == GL_TEXTURE_2D) { |
| 306 if (target == GL_TEXTURE_2D) | 155 if (target == GL_TEXTURE_2D) |
| (...skipping 16 matching lines...) Expand all Loading... |
| 323 } else if (m_target == GL_TEXTURE_3D) { | 172 } else if (m_target == GL_TEXTURE_3D) { |
| 324 if (target == GL_TEXTURE_3D) | 173 if (target == GL_TEXTURE_3D) |
| 325 return 0; | 174 return 0; |
| 326 } else if (m_target == GL_TEXTURE_2D_ARRAY) { | 175 } else if (m_target == GL_TEXTURE_2D_ARRAY) { |
| 327 if (target == GL_TEXTURE_2D_ARRAY) | 176 if (target == GL_TEXTURE_2D_ARRAY) |
| 328 return 0; | 177 return 0; |
| 329 } | 178 } |
| 330 return -1; | 179 return -1; |
| 331 } | 180 } |
| 332 | 181 |
| 333 bool WebGLTexture::canGenerateMipmaps() | |
| 334 { | |
| 335 if (!m_isWebGL2OrHigher && isNPOT()) | |
| 336 return false; | |
| 337 | |
| 338 if (m_baseLevel >= m_info[0].size()) | |
| 339 return false; | |
| 340 | |
| 341 if (m_info.size() > 1 && !m_isCubeComplete) | |
| 342 return false; | |
| 343 | |
| 344 return true; | |
| 345 } | |
| 346 | |
| 347 GLint WebGLTexture::computeLevelCount(GLsizei width, GLsizei height, GLsizei dep
th) | 182 GLint WebGLTexture::computeLevelCount(GLsizei width, GLsizei height, GLsizei dep
th) |
| 348 { | 183 { |
| 349 // return 1 + log2Floor(std::max(width, height)); | 184 // return 1 + log2Floor(std::max(width, height)); |
| 350 GLsizei n = std::max(std::max(width, height), depth); | 185 GLsizei n = std::max(std::max(width, height), depth); |
| 351 if (n <= 0) | 186 if (n <= 0) |
| 352 return 0; | 187 return 0; |
| 353 GLint log = 0; | 188 GLint log = 0; |
| 354 GLsizei value = n; | 189 GLsizei value = n; |
| 355 for (int ii = 4; ii >= 0; --ii) { | 190 for (int ii = 4; ii >= 0; --ii) { |
| 356 int shift = (1 << ii); | 191 int shift = (1 << ii); |
| 357 GLsizei x = (value >> shift); | 192 GLsizei x = (value >> shift); |
| 358 if (x) { | 193 if (x) { |
| 359 value = x; | 194 value = x; |
| 360 log += shift; | 195 log += shift; |
| 361 } | 196 } |
| 362 } | 197 } |
| 363 ASSERT(value == 1); | 198 ASSERT(value == 1); |
| 364 return log + 1; | 199 return log + 1; |
| 365 } | 200 } |
| 366 | 201 |
| 367 void WebGLTexture::update() | |
| 368 { | |
| 369 m_isNPOT = false; | |
| 370 for (size_t ii = 0; ii < m_info.size(); ++ii) { | |
| 371 if (isNPOT(m_info[ii][0].width, m_info[ii][0].height)) { | |
| 372 m_isNPOT = true; | |
| 373 break; | |
| 374 } | |
| 375 } | |
| 376 m_isComplete = true; | |
| 377 m_isCubeComplete = true; | |
| 378 | |
| 379 if (m_baseLevel > m_maxLevel || m_baseLevel >= m_info[0].size()) { | |
| 380 m_isComplete = false; | |
| 381 } | |
| 382 else { | |
| 383 const LevelInfo& base = m_info[0][m_baseLevel]; | |
| 384 size_t levelCount = computeLevelCount(base.width, base.height, (m_target
== GL_TEXTURE_2D_ARRAY ? 0 : base.depth)); | |
| 385 size_t maxLevel = 0; | |
| 386 if (m_baseLevel + levelCount > 0) | |
| 387 maxLevel = m_baseLevel + levelCount - 1; | |
| 388 maxLevel = m_isWebGL2OrHigher ? std::min(m_maxLevel, maxLevel) : maxLeve
l; | |
| 389 for (size_t ii = 0; ii < m_info.size(); ++ii) { | |
| 390 const LevelInfo& info0 = m_info[ii][m_baseLevel]; | |
| 391 if (!info0.valid | |
| 392 || info0.width != base.width || info0.height != base.height || i
nfo0.depth != base.depth | |
| 393 || info0.internalFormat != base.internalFormat || info0.type !=
base.type | |
| 394 || (m_info.size() > 1 && info0.width != info0.height)) { | |
| 395 if (m_info.size() > 1) | |
| 396 m_isCubeComplete = false; | |
| 397 m_isComplete = false; | |
| 398 break; | |
| 399 } | |
| 400 | |
| 401 if (!m_isComplete) | |
| 402 continue; | |
| 403 GLsizei width = info0.width; | |
| 404 GLsizei height = info0.height; | |
| 405 GLsizei depth = info0.depth; | |
| 406 ASSERT(maxLevel < m_info[ii].size()); | |
| 407 for (size_t level = m_baseLevel + 1; level <= maxLevel; ++level) { | |
| 408 width = std::max(1, width >> 1); | |
| 409 height = std::max(1, height >> 1); | |
| 410 depth = m_target == GL_TEXTURE_2D_ARRAY ? depth : std::max(1, de
pth >> 1); | |
| 411 const LevelInfo& info = m_info[ii][level]; | |
| 412 if (!info.valid | |
| 413 || info.width != width || info.height != height || info.dept
h != depth | |
| 414 || info.internalFormat != info0.internalFormat || info.type
!= info0.type) { | |
| 415 m_isComplete = false; | |
| 416 break; | |
| 417 } | |
| 418 | |
| 419 } | |
| 420 } | |
| 421 } | |
| 422 m_isFloatType = m_info[0][0].type == GL_FLOAT; | |
| 423 m_isHalfFloatType = m_info[0][0].type == GL_HALF_FLOAT_OES; | |
| 424 } | |
| 425 | |
| 426 const WebGLTexture::LevelInfo* WebGLTexture::getLevelInfo(GLenum target, GLint l
evel) const | |
| 427 { | |
| 428 if (!object() || !m_target) | |
| 429 return nullptr; | |
| 430 int targetIndex = mapTargetToIndex(target); | |
| 431 if (targetIndex < 0 || targetIndex >= static_cast<int>(m_info.size())) | |
| 432 return nullptr; | |
| 433 if (level < 0 || level >= static_cast<GLint>(m_info[targetIndex].size())) | |
| 434 return nullptr; | |
| 435 return &(m_info[targetIndex][level]); | |
| 436 } | |
| 437 | |
| 438 // TODO(bajones): Logic surrounding relationship of internalFormat, format, and
type needs to be revisisted for WebGL 2.0 | 202 // TODO(bajones): Logic surrounding relationship of internalFormat, format, and
type needs to be revisisted for WebGL 2.0 |
| 439 GLenum WebGLTexture::getValidTypeForInternalFormat(GLenum internalFormat) | 203 GLenum WebGLTexture::getValidTypeForInternalFormat(GLenum internalFormat) |
| 440 { | 204 { |
| 441 switch (internalFormat) { | 205 switch (internalFormat) { |
| 442 case GL_R8: | 206 case GL_R8: |
| 443 return GL_UNSIGNED_BYTE; | 207 return GL_UNSIGNED_BYTE; |
| 444 case GL_R8_SNORM: | 208 case GL_R8_SNORM: |
| 445 return GL_BYTE; | 209 return GL_BYTE; |
| 446 case GL_R16F: | 210 case GL_R16F: |
| 447 return GL_HALF_FLOAT; | 211 return GL_HALF_FLOAT; |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 560 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: | 324 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: |
| 561 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: | 325 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: |
| 562 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: | 326 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: |
| 563 return GL_UNSIGNED_BYTE; | 327 return GL_UNSIGNED_BYTE; |
| 564 default: | 328 default: |
| 565 return GL_NONE; | 329 return GL_NONE; |
| 566 } | 330 } |
| 567 } | 331 } |
| 568 | 332 |
| 569 } // namespace blink | 333 } // namespace blink |
| OLD | NEW |