Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(27)

Side by Side Diff: third_party/WebKit/Source/modules/webgl/WebGLFramebuffer.cpp

Issue 2372953002: Move special DEPTH_STENCIL attachment logic from command buffers to WebGL1 (Closed)
Patch Set: add more tests Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698