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 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
196 WebGLFramebuffer* WebGLFramebuffer::create(WebGLRenderingContextBase* ctx) | 196 WebGLFramebuffer* WebGLFramebuffer::create(WebGLRenderingContextBase* ctx) |
197 { | 197 { |
198 return new WebGLFramebuffer(ctx); | 198 return new WebGLFramebuffer(ctx); |
199 } | 199 } |
200 | 200 |
201 WebGLFramebuffer::WebGLFramebuffer(WebGLRenderingContextBase* ctx) | 201 WebGLFramebuffer::WebGLFramebuffer(WebGLRenderingContextBase* ctx) |
202 : WebGLContextObject(ctx) | 202 : WebGLContextObject(ctx) |
203 , m_object(0) | 203 , m_object(0) |
204 , m_destructionInProgress(false) | 204 , m_destructionInProgress(false) |
205 , m_hasEverBeenBound(false) | 205 , m_hasEverBeenBound(false) |
206 , m_webGL1DepthStencilConsistent(true) | |
206 , m_readBuffer(GL_COLOR_ATTACHMENT0) | 207 , m_readBuffer(GL_COLOR_ATTACHMENT0) |
207 { | 208 { |
208 ctx->contextGL()->GenFramebuffers(1, &m_object); | 209 ctx->contextGL()->GenFramebuffers(1, &m_object); |
209 } | 210 } |
210 | 211 |
211 WebGLFramebuffer::~WebGLFramebuffer() | 212 WebGLFramebuffer::~WebGLFramebuffer() |
212 { | 213 { |
213 // Attachments in |m_attachments| will be deleted from other | 214 // Attachments in |m_attachments| will be deleted from other |
214 // places, and we must not touch that map in deleteObjectImpl once | 215 // places, and we must not touch that map in deleteObjectImpl once |
215 // the destructor has been entered. | 216 // the destructor has been entered. |
216 m_destructionInProgress = true; | 217 m_destructionInProgress = true; |
217 | 218 |
218 // See the comment in WebGLObject::detachAndDeleteObject(). | 219 // See the comment in WebGLObject::detachAndDeleteObject(). |
219 detachAndDeleteObject(); | 220 detachAndDeleteObject(); |
220 } | 221 } |
221 | 222 |
222 void WebGLFramebuffer::setAttachmentForBoundFramebuffer(GLenum target, GLenum at tachment, GLenum texTarget, WebGLTexture* texture, GLint level, GLint layer) | 223 void WebGLFramebuffer::setAttachmentForBoundFramebuffer(GLenum target, GLenum at tachment, GLenum texTarget, WebGLTexture* texture, GLint level, GLint layer) |
223 { | 224 { |
224 ASSERT(isBound(target)); | 225 DCHECK(m_object); |
225 removeAttachmentFromBoundFramebuffer(target, attachment); | 226 DCHECK(isBound(target)); |
226 if (!m_object) | 227 if (context()->isWebGL2OrHigher()) { |
227 return; | 228 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) { |
228 if (texture && texture->object()) { | 229 setAttachmentInternal(target, GL_DEPTH_ATTACHMENT, texTarget, textur e, level, layer); |
229 m_attachments.add(attachment, WebGLTextureAttachment::create(texture, te xTarget, level, layer)); | 230 setAttachmentInternal(target, GL_STENCIL_ATTACHMENT, texTarget, text ure, level, layer); |
230 drawBuffersIfNecessary(false); | 231 } else { |
231 texture->onAttached(); | 232 setAttachmentInternal(target, attachment, texTarget, texture, level, layer); |
233 } | |
234 GLuint textureId = objectOrZero(texture); | |
235 // texTarget can be 0 if detaching using framebufferTextureLayer. | |
236 DCHECK(texTarget || !textureId); | |
237 switch (texTarget) { | |
238 case 0: | |
239 case GL_TEXTURE_3D: | |
240 case GL_TEXTURE_2D_ARRAY: | |
241 context()->contextGL()->FramebufferTextureLayer(target, attachment, textureId, level, layer); | |
242 break; | |
243 default: | |
244 DCHECK_EQ(layer, 0); | |
245 context()->contextGL()->FramebufferTexture2D(target, attachment, tex Target, textureId, level); | |
246 break; | |
247 } | |
248 } else { | |
249 DCHECK_EQ(layer, 0); | |
250 setAttachmentInternal(target, attachment, texTarget, texture, level, lay er); | |
251 switch (attachment) { | |
252 case GL_DEPTH_ATTACHMENT: | |
253 case GL_STENCIL_ATTACHMENT: | |
254 case GL_DEPTH_STENCIL_ATTACHMENT: | |
255 commitWebGL1DepthStencilIfConsistent(target); | |
256 break; | |
257 default: | |
258 context()->contextGL()->FramebufferTexture2D(target, attachment, tex Target, objectOrZero(texture), level); | |
259 break; | |
260 } | |
232 } | 261 } |
233 } | 262 } |
234 | 263 |
235 void WebGLFramebuffer::setAttachmentForBoundFramebuffer(GLenum target, GLenum at tachment, WebGLRenderbuffer* renderbuffer) | 264 void WebGLFramebuffer::setAttachmentForBoundFramebuffer(GLenum target, GLenum at tachment, WebGLRenderbuffer* renderbuffer) |
236 { | 265 { |
237 ASSERT(isBound(target)); | 266 DCHECK(m_object); |
238 removeAttachmentFromBoundFramebuffer(target, attachment); | 267 DCHECK(isBound(target)); |
239 if (!m_object) | 268 if (context()->isWebGL2OrHigher()) { |
240 return; | 269 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) { |
241 if (renderbuffer && renderbuffer->object()) { | 270 setAttachmentInternal(target, GL_DEPTH_ATTACHMENT, renderbuffer); |
242 m_attachments.add(attachment, WebGLRenderbufferAttachment::create(render buffer)); | 271 setAttachmentInternal(target, GL_STENCIL_ATTACHMENT, renderbuffer); |
243 drawBuffersIfNecessary(false); | 272 } else { |
244 renderbuffer->onAttached(); | 273 setAttachmentInternal(target, attachment, renderbuffer); |
274 } | |
275 context()->contextGL()->FramebufferRenderbuffer(target, attachment, GL_R ENDERBUFFER, objectOrZero(renderbuffer)); | |
276 } else { | |
277 setAttachmentInternal(target, attachment, renderbuffer); | |
278 switch (attachment) { | |
279 case GL_DEPTH_ATTACHMENT: | |
280 case GL_STENCIL_ATTACHMENT: | |
281 case GL_DEPTH_STENCIL_ATTACHMENT: | |
282 commitWebGL1DepthStencilIfConsistent(target); | |
283 break; | |
284 default: | |
285 context()->contextGL()->FramebufferRenderbuffer(target, attachment, GL_RENDERBUFFER, objectOrZero(renderbuffer)); | |
286 break; | |
287 } | |
245 } | 288 } |
246 } | 289 } |
247 | 290 |
248 void WebGLFramebuffer::attach(GLenum target, GLenum attachment, GLenum attachmen tPoint) | |
249 { | |
250 ASSERT(isBound(target)); | |
251 WebGLAttachment* attachmentObject = getAttachment(attachment); | |
252 if (attachmentObject) | |
253 attachmentObject->attach(context()->contextGL(), target, attachmentPoint ); | |
254 } | |
255 | |
256 WebGLSharedObject* WebGLFramebuffer::getAttachmentObject(GLenum attachment) cons t | 291 WebGLSharedObject* WebGLFramebuffer::getAttachmentObject(GLenum attachment) cons t |
257 { | 292 { |
258 if (!m_object) | 293 if (!m_object) |
259 return nullptr; | 294 return nullptr; |
260 WebGLAttachment* attachmentObject = getAttachment(attachment); | 295 WebGLAttachment* attachmentObject = getAttachment(attachment); |
261 return attachmentObject ? attachmentObject->object() : nullptr; | 296 return attachmentObject ? attachmentObject->object() : nullptr; |
262 } | 297 } |
263 | 298 |
264 WebGLFramebuffer::WebGLAttachment* WebGLFramebuffer::getAttachment(GLenum attach ment) const | 299 WebGLFramebuffer::WebGLAttachment* WebGLFramebuffer::getAttachment(GLenum attach ment) const |
265 { | 300 { |
266 const AttachmentMap::const_iterator it = m_attachments.find(attachment); | 301 const AttachmentMap::const_iterator it = m_attachments.find(attachment); |
267 return (it != m_attachments.end()) ? it->value.get() : 0; | 302 return (it != m_attachments.end()) ? it->value.get() : 0; |
268 } | 303 } |
269 | 304 |
270 void WebGLFramebuffer::removeAttachmentFromBoundFramebuffer(GLenum target, GLenu m attachment) | |
271 { | |
272 ASSERT(isBound(target)); | |
273 if (!m_object) | |
274 return; | |
275 | |
276 WebGLAttachment* attachmentObject = getAttachment(attachment); | |
277 if (attachmentObject) { | |
278 attachmentObject->onDetached(context()->contextGL()); | |
279 m_attachments.remove(attachment); | |
280 drawBuffersIfNecessary(false); | |
281 switch (attachment) { | |
282 case GL_DEPTH_STENCIL_ATTACHMENT: | |
283 attach(target, GL_DEPTH_ATTACHMENT, GL_DEPTH_ATTACHMENT); | |
284 attach(target, GL_STENCIL_ATTACHMENT, GL_STENCIL_ATTACHMENT); | |
285 break; | |
286 case GL_DEPTH_ATTACHMENT: | |
287 case GL_STENCIL_ATTACHMENT: | |
288 attach(target, GL_DEPTH_STENCIL_ATTACHMENT, GL_DEPTH_STENCIL_ATTACHM ENT); | |
289 break; | |
290 } | |
291 } | |
292 } | |
293 | |
294 void WebGLFramebuffer::removeAttachmentFromBoundFramebuffer(GLenum target, WebGL SharedObject* attachment) | 305 void WebGLFramebuffer::removeAttachmentFromBoundFramebuffer(GLenum target, WebGL SharedObject* attachment) |
295 { | 306 { |
296 ASSERT(isBound(target)); | 307 ASSERT(isBound(target)); |
297 if (!m_object) | 308 if (!m_object) |
298 return; | 309 return; |
299 if (!attachment) | 310 if (!attachment) |
300 return; | 311 return; |
301 | 312 |
302 bool checkMore = true; | 313 bool checkMore = true; |
314 bool isWebGL1 = !context()->isWebGL2OrHigher(); | |
315 bool checkWebGL1DepthStencil = false; | |
303 while (checkMore) { | 316 while (checkMore) { |
304 checkMore = false; | 317 checkMore = false; |
305 for (const auto& it : m_attachments) { | 318 for (const auto& it : m_attachments) { |
306 WebGLAttachment* attachmentObject = it.value.get(); | 319 WebGLAttachment* attachmentObject = it.value.get(); |
307 if (attachmentObject->isSharedObject(attachment)) { | 320 if (attachmentObject->isSharedObject(attachment)) { |
308 GLenum attachmentType = it.key; | 321 GLenum attachmentType = it.key; |
309 attachmentObject->unattach(context()->contextGL(), target, attac hmentType); | 322 switch (attachmentType) { |
310 removeAttachmentFromBoundFramebuffer(target, attachmentType); | 323 case GL_DEPTH_ATTACHMENT: |
324 case GL_STENCIL_ATTACHMENT: | |
325 case GL_DEPTH_STENCIL_ATTACHMENT: | |
326 if (isWebGL1) { | |
327 checkWebGL1DepthStencil = true; | |
328 } else { | |
329 attachmentObject->unattach(context()->contextGL(), targe t, attachmentType); | |
330 } | |
331 break; | |
332 default: | |
333 attachmentObject->unattach(context()->contextGL(), target, a ttachmentType); | |
334 break; | |
335 } | |
336 removeAttachmentInternal(target, attachmentType); | |
311 checkMore = true; | 337 checkMore = true; |
312 break; | 338 break; |
313 } | 339 } |
314 } | 340 } |
315 } | 341 } |
342 if (checkWebGL1DepthStencil) | |
343 commitWebGL1DepthStencilIfConsistent(target); | |
316 } | 344 } |
317 | 345 |
318 GLenum WebGLFramebuffer::checkDepthStencilStatus(const char** reason) const | 346 GLenum WebGLFramebuffer::checkDepthStencilStatus(const char** reason) const |
319 { | 347 { |
320 if (context()->isWebGL2OrHigher()) | 348 if (context()->isWebGL2OrHigher() || m_webGL1DepthStencilConsistent) |
321 return GL_FRAMEBUFFER_COMPLETE; | 349 return GL_FRAMEBUFFER_COMPLETE; |
322 WebGLAttachment* depthAttachment = nullptr; | 350 *reason = "conflicting DEPTH/STENCIL/DEPTH_STENCIL attachments"; |
323 WebGLAttachment* stencilAttachment = nullptr; | 351 return GL_FRAMEBUFFER_UNSUPPORTED; |
324 WebGLAttachment* depthStencilAttachment = nullptr; | |
325 for (const auto& it : m_attachments) { | |
326 WebGLAttachment* attachment = it.value.get(); | |
327 ASSERT(attachment); | |
328 switch (it.key) { | |
329 case GL_DEPTH_ATTACHMENT: | |
330 depthAttachment = attachment; | |
331 break; | |
332 case GL_STENCIL_ATTACHMENT: | |
333 stencilAttachment = attachment; | |
334 break; | |
335 case GL_DEPTH_STENCIL_ATTACHMENT: | |
336 depthStencilAttachment = attachment; | |
337 break; | |
338 default: | |
339 break; | |
340 } | |
341 } | |
342 if ((depthStencilAttachment && (depthAttachment || stencilAttachment)) | |
343 || (depthAttachment && stencilAttachment)) { | |
344 *reason = "conflicting DEPTH/STENCIL/DEPTH_STENCIL attachments"; | |
345 return GL_FRAMEBUFFER_UNSUPPORTED; | |
346 } | |
347 return GL_FRAMEBUFFER_COMPLETE; | |
348 } | 352 } |
349 | 353 |
350 bool WebGLFramebuffer::hasStencilBuffer() const | 354 bool WebGLFramebuffer::hasStencilBuffer() const |
351 { | 355 { |
352 WebGLAttachment* attachment = getAttachment(GL_STENCIL_ATTACHMENT); | 356 WebGLAttachment* attachment = getAttachment(GL_STENCIL_ATTACHMENT); |
353 if (!attachment) | 357 if (!attachment) |
354 attachment = getAttachment(GL_DEPTH_STENCIL_ATTACHMENT); | 358 attachment = getAttachment(GL_DEPTH_STENCIL_ATTACHMENT); |
355 return attachment && attachment->valid(); | 359 return attachment && attachment->valid(); |
356 } | 360 } |
357 | 361 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
404 } | 408 } |
405 } | 409 } |
406 } | 410 } |
407 if (reset) { | 411 if (reset) { |
408 context()->contextGL()->DrawBuffersEXT( | 412 context()->contextGL()->DrawBuffersEXT( |
409 m_filteredDrawBuffers.size(), m_filteredDrawBuffers.data()); | 413 m_filteredDrawBuffers.size(), m_filteredDrawBuffers.data()); |
410 } | 414 } |
411 } | 415 } |
412 } | 416 } |
413 | 417 |
418 void WebGLFramebuffer::setAttachmentInternal(GLenum target, GLenum attachment, G Lenum texTarget, WebGLTexture* texture, GLint level, GLint layer) | |
419 { | |
420 DCHECK(isBound(target)); | |
421 DCHECK(m_object); | |
422 removeAttachmentInternal(target, attachment); | |
423 if (texture && texture->object()) { | |
424 m_attachments.add(attachment, WebGLTextureAttachment::create(texture, te xTarget, level, layer)); | |
425 drawBuffersIfNecessary(false); | |
426 texture->onAttached(); | |
427 } | |
428 } | |
429 | |
430 void WebGLFramebuffer::setAttachmentInternal(GLenum target, GLenum attachment, W ebGLRenderbuffer* renderbuffer) | |
431 { | |
432 DCHECK(isBound(target)); | |
433 DCHECK(m_object); | |
434 removeAttachmentInternal(target, attachment); | |
435 if (renderbuffer && renderbuffer->object()) { | |
436 m_attachments.add(attachment, WebGLRenderbufferAttachment::create(render buffer)); | |
437 drawBuffersIfNecessary(false); | |
438 renderbuffer->onAttached(); | |
439 } | |
440 } | |
441 | |
442 void WebGLFramebuffer::removeAttachmentInternal(GLenum target, GLenum attachment ) | |
443 { | |
444 DCHECK(isBound(target)); | |
445 DCHECK(m_object); | |
446 | |
447 WebGLAttachment* attachmentObject = getAttachment(attachment); | |
448 if (attachmentObject) { | |
449 attachmentObject->onDetached(context()->contextGL()); | |
450 m_attachments.remove(attachment); | |
451 drawBuffersIfNecessary(false); | |
452 } | |
453 } | |
454 | |
455 void WebGLFramebuffer::commitWebGL1DepthStencilIfConsistent(GLenum target) | |
456 { | |
457 DCHECK(!context()->isWebGL2OrHigher()); | |
458 WebGLAttachment* depthAttachment = nullptr; | |
459 WebGLAttachment* stencilAttachment = nullptr; | |
460 WebGLAttachment* depthStencilAttachment = nullptr; | |
461 int count = 0; | |
462 for (const auto& it : m_attachments) { | |
463 WebGLAttachment* attachment = it.value.get(); | |
464 DCHECK(attachment); | |
465 switch (it.key) { | |
466 case GL_DEPTH_ATTACHMENT: | |
467 depthAttachment = attachment; | |
468 ++count; | |
469 break; | |
470 case GL_STENCIL_ATTACHMENT: | |
471 stencilAttachment = attachment; | |
472 ++count; | |
473 break; | |
474 case GL_DEPTH_STENCIL_ATTACHMENT: | |
475 depthStencilAttachment = attachment; | |
476 ++count; | |
477 break; | |
478 default: | |
479 break; | |
480 } | |
481 } | |
482 | |
483 m_webGL1DepthStencilConsistent = count <= 1; | |
484 if (!m_webGL1DepthStencilConsistent) | |
485 return; | |
Ken Russell (switch to Gerrit)
2016/09/29 03:07:43
Can this lazy flushing of the framebuffer's attach
| |
486 | |
487 gpu::gles2::GLES2Interface* gl = context()->contextGL(); | |
488 if (depthAttachment) { | |
489 depthAttachment->attach(gl, target, GL_DEPTH_ATTACHMENT); | |
490 gl->FramebufferRenderbuffer(target, GL_STENCIL_ATTACHMENT, GL_RENDERBUFF ER, 0); | |
491 } else if (stencilAttachment) { | |
492 gl->FramebufferRenderbuffer(target, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER , 0); | |
493 stencilAttachment->attach(gl, target, GL_STENCIL_ATTACHMENT); | |
494 } else if (depthStencilAttachment) { | |
495 depthStencilAttachment->attach(gl, target, GL_DEPTH_STENCIL_ATTACHMENT); | |
496 } else { | |
497 gl->FramebufferRenderbuffer(target, GL_DEPTH_STENCIL_ATTACHMENT, GL_REND ERBUFFER, 0); | |
498 } | |
499 } | |
500 | |
414 GLenum WebGLFramebuffer::getDrawBuffer(GLenum drawBuffer) | 501 GLenum WebGLFramebuffer::getDrawBuffer(GLenum drawBuffer) |
415 { | 502 { |
416 int index = static_cast<int>(drawBuffer - GL_DRAW_BUFFER0_EXT); | 503 int index = static_cast<int>(drawBuffer - GL_DRAW_BUFFER0_EXT); |
417 ASSERT(index >= 0); | 504 ASSERT(index >= 0); |
418 if (index < static_cast<int>(m_drawBuffers.size())) | 505 if (index < static_cast<int>(m_drawBuffers.size())) |
419 return m_drawBuffers[index]; | 506 return m_drawBuffers[index]; |
420 if (drawBuffer == GL_DRAW_BUFFER0_EXT) | 507 if (drawBuffer == GL_DRAW_BUFFER0_EXT) |
421 return GL_COLOR_ATTACHMENT0; | 508 return GL_COLOR_ATTACHMENT0; |
422 return GL_NONE; | 509 return GL_NONE; |
423 } | 510 } |
424 | 511 |
425 void WebGLFramebuffer::visitChildDOMWrappers(v8::Isolate* isolate, const v8::Per sistent<v8::Object>& wrapper) | 512 void WebGLFramebuffer::visitChildDOMWrappers(v8::Isolate* isolate, const v8::Per sistent<v8::Object>& wrapper) |
426 { | 513 { |
427 for (const auto& attachment : m_attachments) { | 514 for (const auto& attachment : m_attachments) { |
428 DOMWrapperWorld::setWrapperReferencesInAllWorlds(wrapper, attachment.val ue->object(), isolate); | 515 DOMWrapperWorld::setWrapperReferencesInAllWorlds(wrapper, attachment.val ue->object(), isolate); |
429 } | 516 } |
430 } | 517 } |
431 | 518 |
432 DEFINE_TRACE(WebGLFramebuffer) | 519 DEFINE_TRACE(WebGLFramebuffer) |
433 { | 520 { |
434 visitor->trace(m_attachments); | 521 visitor->trace(m_attachments); |
435 WebGLContextObject::trace(visitor); | 522 WebGLContextObject::trace(visitor); |
436 } | 523 } |
437 | 524 |
438 } // namespace blink | 525 } // namespace blink |
OLD | NEW |