| OLD | NEW |
| (Empty) |
| 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 "sky/engine/config.h" | |
| 27 | |
| 28 #include "sky/engine/core/html/canvas/WebGLFramebuffer.h" | |
| 29 | |
| 30 #include "sky/engine/core/html/canvas/WebGLRenderingContextBase.h" | |
| 31 #include "sky/engine/platform/NotImplemented.h" | |
| 32 #include "sky/engine/wtf/Vector.h" | |
| 33 | |
| 34 namespace blink { | |
| 35 | |
| 36 namespace { | |
| 37 | |
| 38 Platform3DObject objectOrZero(WebGLObject* object) | |
| 39 { | |
| 40 return object ? object->object() : 0; | |
| 41 } | |
| 42 | |
| 43 class WebGLRenderbufferAttachment final : public WebGLFramebuffer::WebGLAtta
chment { | |
| 44 public: | |
| 45 static PassRefPtr<WebGLFramebuffer::WebGLAttachment> create(WebGLRenderb
uffer*); | |
| 46 | |
| 47 private: | |
| 48 explicit WebGLRenderbufferAttachment(WebGLRenderbuffer*); | |
| 49 WebGLRenderbufferAttachment() { } | |
| 50 | |
| 51 virtual GLsizei width() const override; | |
| 52 virtual GLsizei height() const override; | |
| 53 virtual GLenum format() const override; | |
| 54 virtual GLenum type() const override; | |
| 55 virtual WebGLSharedObject* object() const override; | |
| 56 virtual bool isSharedObject(WebGLSharedObject*) const override; | |
| 57 virtual bool valid() const override; | |
| 58 virtual void onDetached(blink::WebGraphicsContext3D*) override; | |
| 59 virtual void attach(blink::WebGraphicsContext3D*, GLenum attachment) ove
rride; | |
| 60 virtual void unattach(blink::WebGraphicsContext3D*, GLenum attachment) o
verride; | |
| 61 | |
| 62 RefPtr<WebGLRenderbuffer> m_renderbuffer; | |
| 63 }; | |
| 64 | |
| 65 PassRefPtr<WebGLFramebuffer::WebGLAttachment> WebGLRenderbufferAttachment::c
reate(WebGLRenderbuffer* renderbuffer) | |
| 66 { | |
| 67 return adoptRef(new WebGLRenderbufferAttachment(renderbuffer)); | |
| 68 } | |
| 69 | |
| 70 WebGLRenderbufferAttachment::WebGLRenderbufferAttachment(WebGLRenderbuffer*
renderbuffer) | |
| 71 : m_renderbuffer(renderbuffer) | |
| 72 { | |
| 73 } | |
| 74 | |
| 75 GLsizei WebGLRenderbufferAttachment::width() const | |
| 76 { | |
| 77 return m_renderbuffer->width(); | |
| 78 } | |
| 79 | |
| 80 GLsizei WebGLRenderbufferAttachment::height() const | |
| 81 { | |
| 82 return m_renderbuffer->height(); | |
| 83 } | |
| 84 | |
| 85 GLenum WebGLRenderbufferAttachment::format() const | |
| 86 { | |
| 87 GLenum format = m_renderbuffer->internalFormat(); | |
| 88 if (format == GL_DEPTH_STENCIL_OES | |
| 89 && m_renderbuffer->emulatedStencilBuffer() | |
| 90 && m_renderbuffer->emulatedStencilBuffer()->internalFormat() != GL_S
TENCIL_INDEX8) { | |
| 91 return 0; | |
| 92 } | |
| 93 return format; | |
| 94 } | |
| 95 | |
| 96 WebGLSharedObject* WebGLRenderbufferAttachment::object() const | |
| 97 { | |
| 98 return m_renderbuffer->object() ? m_renderbuffer.get() : 0; | |
| 99 } | |
| 100 | |
| 101 bool WebGLRenderbufferAttachment::isSharedObject(WebGLSharedObject* object)
const | |
| 102 { | |
| 103 return object == m_renderbuffer; | |
| 104 } | |
| 105 | |
| 106 bool WebGLRenderbufferAttachment::valid() const | |
| 107 { | |
| 108 return m_renderbuffer->object(); | |
| 109 } | |
| 110 | |
| 111 void WebGLRenderbufferAttachment::onDetached(blink::WebGraphicsContext3D* co
ntext) | |
| 112 { | |
| 113 m_renderbuffer->onDetached(context); | |
| 114 } | |
| 115 | |
| 116 void WebGLRenderbufferAttachment::attach(blink::WebGraphicsContext3D* contex
t, GLenum attachment) | |
| 117 { | |
| 118 Platform3DObject object = objectOrZero(m_renderbuffer.get()); | |
| 119 if (attachment == GC3D_DEPTH_STENCIL_ATTACHMENT_WEBGL && m_renderbuffer-
>emulatedStencilBuffer()) { | |
| 120 context->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT
, GL_RENDERBUFFER, object); | |
| 121 context->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHME
NT, GL_RENDERBUFFER, objectOrZero(m_renderbuffer->emulatedStencilBuffer())); | |
| 122 } else { | |
| 123 context->framebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_REND
ERBUFFER, object); | |
| 124 } | |
| 125 } | |
| 126 | |
| 127 void WebGLRenderbufferAttachment::unattach(blink::WebGraphicsContext3D* cont
ext, GLenum attachment) | |
| 128 { | |
| 129 if (attachment == GC3D_DEPTH_STENCIL_ATTACHMENT_WEBGL) { | |
| 130 context->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT
, GL_RENDERBUFFER, 0); | |
| 131 context->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHME
NT, GL_RENDERBUFFER, 0); | |
| 132 } else { | |
| 133 context->framebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_REND
ERBUFFER, 0); | |
| 134 } | |
| 135 } | |
| 136 | |
| 137 GLenum WebGLRenderbufferAttachment::type() const | |
| 138 { | |
| 139 notImplemented(); | |
| 140 return 0; | |
| 141 } | |
| 142 | |
| 143 class WebGLTextureAttachment final : public WebGLFramebuffer::WebGLAttachmen
t { | |
| 144 public: | |
| 145 static PassRefPtr<WebGLFramebuffer::WebGLAttachment> create(WebGLTexture
*, GLenum target, GLint level); | |
| 146 | |
| 147 private: | |
| 148 WebGLTextureAttachment(WebGLTexture*, GLenum target, GLint level); | |
| 149 WebGLTextureAttachment() { } | |
| 150 | |
| 151 virtual GLsizei width() const override; | |
| 152 virtual GLsizei height() const override; | |
| 153 virtual GLenum format() const override; | |
| 154 virtual GLenum type() const override; | |
| 155 virtual WebGLSharedObject* object() const override; | |
| 156 virtual bool isSharedObject(WebGLSharedObject*) const override; | |
| 157 virtual bool valid() const override; | |
| 158 virtual void onDetached(blink::WebGraphicsContext3D*) override; | |
| 159 virtual void attach(blink::WebGraphicsContext3D*, GLenum attachment) ove
rride; | |
| 160 virtual void unattach(blink::WebGraphicsContext3D*, GLenum attachment) o
verride; | |
| 161 | |
| 162 RefPtr<WebGLTexture> m_texture; | |
| 163 GLenum m_target; | |
| 164 GLint m_level; | |
| 165 }; | |
| 166 | |
| 167 PassRefPtr<WebGLFramebuffer::WebGLAttachment> WebGLTextureAttachment::create
(WebGLTexture* texture, GLenum target, GLint level) | |
| 168 { | |
| 169 return adoptRef(new WebGLTextureAttachment(texture, target, level)); | |
| 170 } | |
| 171 | |
| 172 WebGLTextureAttachment::WebGLTextureAttachment(WebGLTexture* texture, GLenum
target, GLint level) | |
| 173 : m_texture(texture) | |
| 174 , m_target(target) | |
| 175 , m_level(level) | |
| 176 { | |
| 177 } | |
| 178 | |
| 179 GLsizei WebGLTextureAttachment::width() const | |
| 180 { | |
| 181 return m_texture->getWidth(m_target, m_level); | |
| 182 } | |
| 183 | |
| 184 GLsizei WebGLTextureAttachment::height() const | |
| 185 { | |
| 186 return m_texture->getHeight(m_target, m_level); | |
| 187 } | |
| 188 | |
| 189 GLenum WebGLTextureAttachment::format() const | |
| 190 { | |
| 191 return m_texture->getInternalFormat(m_target, m_level); | |
| 192 } | |
| 193 | |
| 194 WebGLSharedObject* WebGLTextureAttachment::object() const | |
| 195 { | |
| 196 return m_texture->object() ? m_texture.get() : 0; | |
| 197 } | |
| 198 | |
| 199 bool WebGLTextureAttachment::isSharedObject(WebGLSharedObject* object) const | |
| 200 { | |
| 201 return object == m_texture; | |
| 202 } | |
| 203 | |
| 204 bool WebGLTextureAttachment::valid() const | |
| 205 { | |
| 206 return m_texture->object(); | |
| 207 } | |
| 208 | |
| 209 void WebGLTextureAttachment::onDetached(blink::WebGraphicsContext3D* context
) | |
| 210 { | |
| 211 m_texture->onDetached(context); | |
| 212 } | |
| 213 | |
| 214 void WebGLTextureAttachment::attach(blink::WebGraphicsContext3D* context, GL
enum attachment) | |
| 215 { | |
| 216 Platform3DObject object = objectOrZero(m_texture.get()); | |
| 217 context->framebufferTexture2D(GL_FRAMEBUFFER, attachment, m_target, obje
ct, m_level); | |
| 218 } | |
| 219 | |
| 220 void WebGLTextureAttachment::unattach(blink::WebGraphicsContext3D* context,
GLenum attachment) | |
| 221 { | |
| 222 if (attachment == GC3D_DEPTH_STENCIL_ATTACHMENT_WEBGL) { | |
| 223 context->framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m
_target, 0, m_level); | |
| 224 context->framebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
m_target, 0, m_level); | |
| 225 } else { | |
| 226 context->framebufferTexture2D(GL_FRAMEBUFFER, attachment, m_target,
0, m_level); | |
| 227 } | |
| 228 } | |
| 229 | |
| 230 GLenum WebGLTextureAttachment::type() const | |
| 231 { | |
| 232 return m_texture->getType(m_target, m_level); | |
| 233 } | |
| 234 | |
| 235 bool isColorRenderable(GLenum internalformat) | |
| 236 { | |
| 237 switch (internalformat) { | |
| 238 case GL_RGBA4: | |
| 239 case GL_RGB5_A1: | |
| 240 case GL_RGB565: | |
| 241 return true; | |
| 242 default: | |
| 243 return false; | |
| 244 } | |
| 245 } | |
| 246 | |
| 247 } // anonymous namespace | |
| 248 | |
| 249 WebGLFramebuffer::WebGLAttachment::WebGLAttachment() | |
| 250 { | |
| 251 } | |
| 252 | |
| 253 WebGLFramebuffer::WebGLAttachment::~WebGLAttachment() | |
| 254 { | |
| 255 } | |
| 256 | |
| 257 PassRefPtr<WebGLFramebuffer> WebGLFramebuffer::create(WebGLRenderingContextBase*
ctx) | |
| 258 { | |
| 259 return adoptRef(new WebGLFramebuffer(ctx)); | |
| 260 } | |
| 261 | |
| 262 WebGLFramebuffer::WebGLFramebuffer(WebGLRenderingContextBase* ctx) | |
| 263 : WebGLContextObject(ctx) | |
| 264 , m_hasEverBeenBound(false) | |
| 265 { | |
| 266 setObject(ctx->webContext()->createFramebuffer()); | |
| 267 } | |
| 268 | |
| 269 WebGLFramebuffer::~WebGLFramebuffer() | |
| 270 { | |
| 271 // Delete the platform framebuffer resource. Explicit detachment | |
| 272 // is for the benefit of Oilpan, where the framebuffer object | |
| 273 // isn't detached when it and the WebGLRenderingContextBase object | |
| 274 // it is registered with are both finalized. Without Oilpan, the | |
| 275 // object will have been detached. | |
| 276 // | |
| 277 // To keep the code regular, the trivial detach()ment is always | |
| 278 // performed. | |
| 279 detachAndDeleteObject(); | |
| 280 } | |
| 281 | |
| 282 void WebGLFramebuffer::setAttachmentForBoundFramebuffer(GLenum attachment, GLenu
m texTarget, WebGLTexture* texture, GLint level) | |
| 283 { | |
| 284 ASSERT(isBound()); | |
| 285 removeAttachmentFromBoundFramebuffer(attachment); | |
| 286 if (!object()) | |
| 287 return; | |
| 288 if (texture && texture->object()) { | |
| 289 m_attachments.add(attachment, WebGLTextureAttachment::create(texture, te
xTarget, level)); | |
| 290 drawBuffersIfNecessary(false); | |
| 291 texture->onAttached(); | |
| 292 } | |
| 293 } | |
| 294 | |
| 295 void WebGLFramebuffer::setAttachmentForBoundFramebuffer(GLenum attachment, WebGL
Renderbuffer* renderbuffer) | |
| 296 { | |
| 297 ASSERT(isBound()); | |
| 298 removeAttachmentFromBoundFramebuffer(attachment); | |
| 299 if (!object()) | |
| 300 return; | |
| 301 if (renderbuffer && renderbuffer->object()) { | |
| 302 m_attachments.add(attachment, WebGLRenderbufferAttachment::create(render
buffer)); | |
| 303 drawBuffersIfNecessary(false); | |
| 304 renderbuffer->onAttached(); | |
| 305 } | |
| 306 } | |
| 307 | |
| 308 void WebGLFramebuffer::attach(GLenum attachment, GLenum attachmentPoint) | |
| 309 { | |
| 310 ASSERT(isBound()); | |
| 311 WebGLAttachment* attachmentObject = getAttachment(attachment); | |
| 312 if (attachmentObject) | |
| 313 attachmentObject->attach(context()->webContext(), attachmentPoint); | |
| 314 } | |
| 315 | |
| 316 WebGLSharedObject* WebGLFramebuffer::getAttachmentObject(GLenum attachment) cons
t | |
| 317 { | |
| 318 if (!object()) | |
| 319 return 0; | |
| 320 WebGLAttachment* attachmentObject = getAttachment(attachment); | |
| 321 return attachmentObject ? attachmentObject->object() : 0; | |
| 322 } | |
| 323 | |
| 324 bool WebGLFramebuffer::isAttachmentComplete(WebGLAttachment* attachedObject, GLe
num attachment, const char** reason) const | |
| 325 { | |
| 326 ASSERT(attachedObject && attachedObject->valid()); | |
| 327 ASSERT(reason); | |
| 328 | |
| 329 GLenum internalformat = attachedObject->format(); | |
| 330 WebGLSharedObject* object = attachedObject->object(); | |
| 331 ASSERT(object && (object->isTexture() || object->isRenderbuffer())); | |
| 332 | |
| 333 if (attachment == GL_DEPTH_ATTACHMENT) { | |
| 334 if (object->isRenderbuffer()) { | |
| 335 if (internalformat != GL_DEPTH_COMPONENT16) { | |
| 336 *reason = "the internalformat of the attached renderbuffer is no
t DEPTH_COMPONENT16"; | |
| 337 return false; | |
| 338 } | |
| 339 } else if (object->isTexture()) { | |
| 340 GLenum type = attachedObject->type(); | |
| 341 if (!(context()->extensionEnabled(WebGLDepthTextureName) && internal
format == GL_DEPTH_COMPONENT | |
| 342 && (type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT))) { | |
| 343 *reason = "the attached texture is not a depth texture"; | |
| 344 return false; | |
| 345 } | |
| 346 } | |
| 347 } else if (attachment == GL_STENCIL_ATTACHMENT) { | |
| 348 // Depend on the underlying GL drivers to check stencil textures | |
| 349 // and check renderbuffer type here only. | |
| 350 if (object->isRenderbuffer()) { | |
| 351 if (internalformat != GL_STENCIL_INDEX8) { | |
| 352 *reason = "the internalformat of the attached renderbuffer is no
t STENCIL_INDEX8"; | |
| 353 return false; | |
| 354 } | |
| 355 } | |
| 356 } else if (attachment == GC3D_DEPTH_STENCIL_ATTACHMENT_WEBGL) { | |
| 357 if (object->isRenderbuffer()) { | |
| 358 if (internalformat != GL_DEPTH_STENCIL_OES) { | |
| 359 *reason = "the internalformat of the attached renderbuffer is no
t DEPTH_STENCIL"; | |
| 360 return false; | |
| 361 } | |
| 362 } else if (object->isTexture()) { | |
| 363 GLenum type = attachedObject->type(); | |
| 364 if (!(context()->extensionEnabled(WebGLDepthTextureName) && internal
format == GL_DEPTH_STENCIL_OES | |
| 365 && type == GL_UNSIGNED_INT_24_8_OES)) { | |
| 366 *reason = "the attached texture is not a DEPTH_STENCIL texture"; | |
| 367 return false; | |
| 368 } | |
| 369 } | |
| 370 } else if (attachment == GL_COLOR_ATTACHMENT0 | |
| 371 || (context()->extensionEnabled(WebGLDrawBuffersName) && attachment > GL
_COLOR_ATTACHMENT0 | |
| 372 && attachment < static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + context()
->maxColorAttachments()))) { | |
| 373 if (object->isRenderbuffer()) { | |
| 374 if (!isColorRenderable(internalformat)) { | |
| 375 *reason = "the internalformat of the attached renderbuffer is no
t color-renderable"; | |
| 376 return false; | |
| 377 } | |
| 378 } else if (object->isTexture()) { | |
| 379 GLenum type = attachedObject->type(); | |
| 380 if (internalformat != GL_RGBA && internalformat != GL_RGB) { | |
| 381 *reason = "the internalformat of the attached texture is not col
or-renderable"; | |
| 382 return false; | |
| 383 } | |
| 384 // TODO: WEBGL_color_buffer_float and EXT_color_buffer_half_float ex
tensions have not been implemented in | |
| 385 // WebGL yet. It would be better to depend on the underlying GL driv
ers to check on rendering to floating point textures | |
| 386 // and add the check back to WebGL when above two extensions are imp
lemented. | |
| 387 // Assume UNSIGNED_BYTE is renderable here without the need to expli
citly check if GL_OES_rgb8_rgba8 extension is supported. | |
| 388 if (type != GL_UNSIGNED_BYTE | |
| 389 && type != GL_UNSIGNED_SHORT_5_6_5 | |
| 390 && type != GL_UNSIGNED_SHORT_4_4_4_4 | |
| 391 && type != GL_UNSIGNED_SHORT_5_5_5_1 | |
| 392 && !(type == GL_FLOAT && context()->extensionEnabled(OESTextureF
loatName)) | |
| 393 && !(type == GL_HALF_FLOAT_OES && context()->extensionEnabled(OE
STextureHalfFloatName))) { | |
| 394 *reason = "unsupported type: The attached texture is not support
ed to be rendered to"; | |
| 395 return false; | |
| 396 } | |
| 397 } | |
| 398 } else { | |
| 399 *reason = "unknown framebuffer attachment point"; | |
| 400 return false; | |
| 401 } | |
| 402 | |
| 403 if (!attachedObject->width() || !attachedObject->height()) { | |
| 404 *reason = "attachment has a 0 dimension"; | |
| 405 return false; | |
| 406 } | |
| 407 return true; | |
| 408 } | |
| 409 | |
| 410 WebGLFramebuffer::WebGLAttachment* WebGLFramebuffer::getAttachment(GLenum attach
ment) const | |
| 411 { | |
| 412 const AttachmentMap::const_iterator it = m_attachments.find(attachment); | |
| 413 return (it != m_attachments.end()) ? it->value.get() : 0; | |
| 414 } | |
| 415 | |
| 416 void WebGLFramebuffer::removeAttachmentFromBoundFramebuffer(GLenum attachment) | |
| 417 { | |
| 418 ASSERT(isBound()); | |
| 419 if (!object()) | |
| 420 return; | |
| 421 | |
| 422 WebGLAttachment* attachmentObject = getAttachment(attachment); | |
| 423 if (attachmentObject) { | |
| 424 attachmentObject->onDetached(context()->webContext()); | |
| 425 m_attachments.remove(attachment); | |
| 426 drawBuffersIfNecessary(false); | |
| 427 switch (attachment) { | |
| 428 case GC3D_DEPTH_STENCIL_ATTACHMENT_WEBGL: | |
| 429 attach(GL_DEPTH_ATTACHMENT, GL_DEPTH_ATTACHMENT); | |
| 430 attach(GL_STENCIL_ATTACHMENT, GL_STENCIL_ATTACHMENT); | |
| 431 break; | |
| 432 case GL_DEPTH_ATTACHMENT: | |
| 433 attach(GC3D_DEPTH_STENCIL_ATTACHMENT_WEBGL, GL_DEPTH_ATTACHMENT); | |
| 434 break; | |
| 435 case GL_STENCIL_ATTACHMENT: | |
| 436 attach(GC3D_DEPTH_STENCIL_ATTACHMENT_WEBGL, GL_STENCIL_ATTACHMENT); | |
| 437 break; | |
| 438 } | |
| 439 } | |
| 440 } | |
| 441 | |
| 442 void WebGLFramebuffer::removeAttachmentFromBoundFramebuffer(WebGLSharedObject* a
ttachment) | |
| 443 { | |
| 444 ASSERT(isBound()); | |
| 445 if (!object()) | |
| 446 return; | |
| 447 if (!attachment) | |
| 448 return; | |
| 449 | |
| 450 bool checkMore = true; | |
| 451 while (checkMore) { | |
| 452 checkMore = false; | |
| 453 for (AttachmentMap::iterator it = m_attachments.begin(); it != m_attachm
ents.end(); ++it) { | |
| 454 WebGLAttachment* attachmentObject = it->value.get(); | |
| 455 if (attachmentObject->isSharedObject(attachment)) { | |
| 456 GLenum attachmentType = it->key; | |
| 457 attachmentObject->unattach(context()->webContext(), attachmentTy
pe); | |
| 458 removeAttachmentFromBoundFramebuffer(attachmentType); | |
| 459 checkMore = true; | |
| 460 break; | |
| 461 } | |
| 462 } | |
| 463 } | |
| 464 } | |
| 465 | |
| 466 GLenum WebGLFramebuffer::colorBufferFormat() const | |
| 467 { | |
| 468 if (!object()) | |
| 469 return 0; | |
| 470 WebGLAttachment* attachment = getAttachment(GL_COLOR_ATTACHMENT0); | |
| 471 if (!attachment) | |
| 472 return 0; | |
| 473 return attachment->format(); | |
| 474 } | |
| 475 | |
| 476 GLenum WebGLFramebuffer::checkStatus(const char** reason) const | |
| 477 { | |
| 478 unsigned count = 0; | |
| 479 GLsizei width = 0, height = 0; | |
| 480 bool haveDepth = false; | |
| 481 bool haveStencil = false; | |
| 482 bool haveDepthStencil = false; | |
| 483 for (AttachmentMap::const_iterator it = m_attachments.begin(); it != m_attac
hments.end(); ++it) { | |
| 484 WebGLAttachment* attachment = it->value.get(); | |
| 485 if (!isAttachmentComplete(attachment, it->key, reason)) | |
| 486 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; | |
| 487 if (!attachment->valid()) { | |
| 488 *reason = "attachment is not valid"; | |
| 489 return GL_FRAMEBUFFER_UNSUPPORTED; | |
| 490 } | |
| 491 if (!attachment->format()) { | |
| 492 *reason = "attachment is an unsupported format"; | |
| 493 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; | |
| 494 } | |
| 495 switch (it->key) { | |
| 496 case GL_DEPTH_ATTACHMENT: | |
| 497 haveDepth = true; | |
| 498 break; | |
| 499 case GL_STENCIL_ATTACHMENT: | |
| 500 haveStencil = true; | |
| 501 break; | |
| 502 case GC3D_DEPTH_STENCIL_ATTACHMENT_WEBGL: | |
| 503 haveDepthStencil = true; | |
| 504 break; | |
| 505 } | |
| 506 if (!count) { | |
| 507 width = attachment->width(); | |
| 508 height = attachment->height(); | |
| 509 } else { | |
| 510 if (width != attachment->width() || height != attachment->height())
{ | |
| 511 *reason = "attachments do not have the same dimensions"; | |
| 512 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; | |
| 513 } | |
| 514 } | |
| 515 ++count; | |
| 516 } | |
| 517 if (!count) { | |
| 518 *reason = "no attachments"; | |
| 519 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; | |
| 520 } | |
| 521 if (!width || !height) { | |
| 522 *reason = "framebuffer has a 0 dimension"; | |
| 523 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; | |
| 524 } | |
| 525 // WebGL specific: no conflicting DEPTH/STENCIL/DEPTH_STENCIL attachments. | |
| 526 if ((haveDepthStencil && (haveDepth || haveStencil)) || (haveDepth && haveSt
encil)) { | |
| 527 *reason = "conflicting DEPTH/STENCIL/DEPTH_STENCIL attachments"; | |
| 528 return GL_FRAMEBUFFER_UNSUPPORTED; | |
| 529 } | |
| 530 return GL_FRAMEBUFFER_COMPLETE; | |
| 531 } | |
| 532 | |
| 533 bool WebGLFramebuffer::onAccess(blink::WebGraphicsContext3D* context3d, const ch
ar** reason) | |
| 534 { | |
| 535 if (checkStatus(reason) != GL_FRAMEBUFFER_COMPLETE) | |
| 536 return false; | |
| 537 return true; | |
| 538 } | |
| 539 | |
| 540 bool WebGLFramebuffer::hasStencilBuffer() const | |
| 541 { | |
| 542 WebGLAttachment* attachment = getAttachment(GL_STENCIL_ATTACHMENT); | |
| 543 if (!attachment) | |
| 544 attachment = getAttachment(GC3D_DEPTH_STENCIL_ATTACHMENT_WEBGL); | |
| 545 return attachment && attachment->valid(); | |
| 546 } | |
| 547 | |
| 548 void WebGLFramebuffer::deleteObjectImpl(blink::WebGraphicsContext3D* context3d,
Platform3DObject object) | |
| 549 { | |
| 550 #if !ENABLE(OILPAN) | |
| 551 // With Oilpan, both the AttachmentMap and its WebGLAttachment objects are | |
| 552 // GCed objects and cannot be accessed, as they may have been finalized | |
| 553 // already during the same GC sweep. | |
| 554 // | |
| 555 // The WebGLAttachment-derived classes instead handle detachment | |
| 556 // on their own when finalizing, so the explicit notification is | |
| 557 // not needed. | |
| 558 for (AttachmentMap::iterator it = m_attachments.begin(); it != m_attachments
.end(); ++it) | |
| 559 it->value->onDetached(context3d); | |
| 560 #endif | |
| 561 | |
| 562 context3d->deleteFramebuffer(object); | |
| 563 } | |
| 564 | |
| 565 bool WebGLFramebuffer::isBound() const | |
| 566 { | |
| 567 return (context()->m_framebufferBinding.get() == this); | |
| 568 } | |
| 569 | |
| 570 void WebGLFramebuffer::drawBuffers(const Vector<GLenum>& bufs) | |
| 571 { | |
| 572 m_drawBuffers = bufs; | |
| 573 m_filteredDrawBuffers.resize(m_drawBuffers.size()); | |
| 574 for (size_t i = 0; i < m_filteredDrawBuffers.size(); ++i) | |
| 575 m_filteredDrawBuffers[i] = GL_NONE; | |
| 576 drawBuffersIfNecessary(true); | |
| 577 } | |
| 578 | |
| 579 void WebGLFramebuffer::drawBuffersIfNecessary(bool force) | |
| 580 { | |
| 581 if (!context()->extensionEnabled(WebGLDrawBuffersName)) | |
| 582 return; | |
| 583 bool reset = force; | |
| 584 // This filtering works around graphics driver bugs on Mac OS X. | |
| 585 for (size_t i = 0; i < m_drawBuffers.size(); ++i) { | |
| 586 if (m_drawBuffers[i] != GL_NONE && getAttachment(m_drawBuffers[i])) { | |
| 587 if (m_filteredDrawBuffers[i] != m_drawBuffers[i]) { | |
| 588 m_filteredDrawBuffers[i] = m_drawBuffers[i]; | |
| 589 reset = true; | |
| 590 } | |
| 591 } else { | |
| 592 if (m_filteredDrawBuffers[i] != GL_NONE) { | |
| 593 m_filteredDrawBuffers[i] = GL_NONE; | |
| 594 reset = true; | |
| 595 } | |
| 596 } | |
| 597 } | |
| 598 if (reset) { | |
| 599 context()->webContext()->drawBuffersEXT( | |
| 600 m_filteredDrawBuffers.size(), m_filteredDrawBuffers.data()); | |
| 601 } | |
| 602 } | |
| 603 | |
| 604 GLenum WebGLFramebuffer::getDrawBuffer(GLenum drawBuffer) | |
| 605 { | |
| 606 int index = static_cast<int>(drawBuffer - GL_DRAW_BUFFER0_EXT); | |
| 607 ASSERT(index >= 0); | |
| 608 if (index < static_cast<int>(m_drawBuffers.size())) | |
| 609 return m_drawBuffers[index]; | |
| 610 if (drawBuffer == GL_DRAW_BUFFER0_EXT) | |
| 611 return GL_COLOR_ATTACHMENT0; | |
| 612 return GL_NONE; | |
| 613 } | |
| 614 | |
| 615 } | |
| OLD | NEW |