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

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

Issue 2389363002: Move special DEPTH_STENCIL attachment logic from command buffers to WebGL1 (Closed)
Patch Set: 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 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 201
202 WebGLFramebuffer* WebGLFramebuffer::create(WebGLRenderingContextBase* ctx) { 202 WebGLFramebuffer* WebGLFramebuffer::create(WebGLRenderingContextBase* ctx) {
203 return new WebGLFramebuffer(ctx); 203 return new WebGLFramebuffer(ctx);
204 } 204 }
205 205
206 WebGLFramebuffer::WebGLFramebuffer(WebGLRenderingContextBase* ctx) 206 WebGLFramebuffer::WebGLFramebuffer(WebGLRenderingContextBase* ctx)
207 : WebGLContextObject(ctx), 207 : WebGLContextObject(ctx),
208 m_object(0), 208 m_object(0),
209 m_destructionInProgress(false), 209 m_destructionInProgress(false),
210 m_hasEverBeenBound(false), 210 m_hasEverBeenBound(false),
211 m_webGL1DepthStencilConsistent(true),
211 m_readBuffer(GL_COLOR_ATTACHMENT0) { 212 m_readBuffer(GL_COLOR_ATTACHMENT0) {
212 ctx->contextGL()->GenFramebuffers(1, &m_object); 213 ctx->contextGL()->GenFramebuffers(1, &m_object);
213 } 214 }
214 215
215 WebGLFramebuffer::~WebGLFramebuffer() { 216 WebGLFramebuffer::~WebGLFramebuffer() {
216 // Attachments in |m_attachments| will be deleted from other 217 // Attachments in |m_attachments| will be deleted from other
217 // places, and we must not touch that map in deleteObjectImpl once 218 // places, and we must not touch that map in deleteObjectImpl once
218 // the destructor has been entered. 219 // the destructor has been entered.
219 m_destructionInProgress = true; 220 m_destructionInProgress = true;
220 221
221 // See the comment in WebGLObject::detachAndDeleteObject(). 222 // See the comment in WebGLObject::detachAndDeleteObject().
222 detachAndDeleteObject(); 223 detachAndDeleteObject();
223 } 224 }
224 225
225 void WebGLFramebuffer::setAttachmentForBoundFramebuffer(GLenum target, 226 void WebGLFramebuffer::setAttachmentForBoundFramebuffer(GLenum target,
226 GLenum attachment, 227 GLenum attachment,
227 GLenum texTarget, 228 GLenum texTarget,
228 WebGLTexture* texture, 229 WebGLTexture* texture,
229 GLint level, 230 GLint level,
230 GLint layer) { 231 GLint layer) {
231 ASSERT(isBound(target)); 232 DCHECK(m_object);
232 removeAttachmentFromBoundFramebuffer(target, attachment); 233 DCHECK(isBound(target));
233 if (!m_object) 234 if (context()->isWebGL2OrHigher()) {
234 return; 235 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
235 if (texture && texture->object()) { 236 setAttachmentInternal(target, GL_DEPTH_ATTACHMENT, texTarget, texture,
236 m_attachments.add(attachment, WebGLTextureAttachment::create( 237 level, layer);
237 texture, texTarget, level, layer)); 238 setAttachmentInternal(target, GL_STENCIL_ATTACHMENT, texTarget, texture,
238 drawBuffersIfNecessary(false); 239 level, layer);
239 texture->onAttached(); 240 } else {
241 setAttachmentInternal(target, attachment, texTarget, texture, level,
242 layer);
243 }
244 GLuint textureId = objectOrZero(texture);
245 // texTarget can be 0 if detaching using framebufferTextureLayer.
246 DCHECK(texTarget || !textureId);
247 switch (texTarget) {
248 case 0:
249 case GL_TEXTURE_3D:
250 case GL_TEXTURE_2D_ARRAY:
251 context()->contextGL()->FramebufferTextureLayer(
252 target, attachment, textureId, level, layer);
253 break;
254 default:
255 DCHECK_EQ(layer, 0);
256 context()->contextGL()->FramebufferTexture2D(
257 target, attachment, texTarget, textureId, level);
258 break;
259 }
260 } else {
261 DCHECK_EQ(layer, 0);
262 setAttachmentInternal(target, attachment, texTarget, texture, level, layer);
263 switch (attachment) {
264 case GL_DEPTH_ATTACHMENT:
265 case GL_STENCIL_ATTACHMENT:
266 case GL_DEPTH_STENCIL_ATTACHMENT:
267 commitWebGL1DepthStencilIfConsistent(target);
268 break;
269 default:
270 context()->contextGL()->FramebufferTexture2D(
271 target, attachment, texTarget, objectOrZero(texture), level);
272 break;
273 }
240 } 274 }
241 } 275 }
242 276
243 void WebGLFramebuffer::setAttachmentForBoundFramebuffer( 277 void WebGLFramebuffer::setAttachmentForBoundFramebuffer(
244 GLenum target, 278 GLenum target,
245 GLenum attachment, 279 GLenum attachment,
246 WebGLRenderbuffer* renderbuffer) { 280 WebGLRenderbuffer* renderbuffer) {
247 ASSERT(isBound(target)); 281 DCHECK(m_object);
248 removeAttachmentFromBoundFramebuffer(target, attachment); 282 DCHECK(isBound(target));
249 if (!m_object) 283 if (context()->isWebGL2OrHigher()) {
250 return; 284 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
251 if (renderbuffer && renderbuffer->object()) { 285 setAttachmentInternal(target, GL_DEPTH_ATTACHMENT, renderbuffer);
252 m_attachments.add(attachment, 286 setAttachmentInternal(target, GL_STENCIL_ATTACHMENT, renderbuffer);
253 WebGLRenderbufferAttachment::create(renderbuffer)); 287 } else {
254 drawBuffersIfNecessary(false); 288 setAttachmentInternal(target, attachment, renderbuffer);
255 renderbuffer->onAttached(); 289 }
290 context()->contextGL()->FramebufferRenderbuffer(
291 target, attachment, GL_RENDERBUFFER, objectOrZero(renderbuffer));
292 } else {
293 setAttachmentInternal(target, attachment, renderbuffer);
294 switch (attachment) {
295 case GL_DEPTH_ATTACHMENT:
296 case GL_STENCIL_ATTACHMENT:
297 case GL_DEPTH_STENCIL_ATTACHMENT:
298 commitWebGL1DepthStencilIfConsistent(target);
299 break;
300 default:
301 context()->contextGL()->FramebufferRenderbuffer(
302 target, attachment, GL_RENDERBUFFER, objectOrZero(renderbuffer));
303 break;
304 }
256 } 305 }
257 } 306 }
258 307
259 void WebGLFramebuffer::attach(GLenum target,
260 GLenum attachment,
261 GLenum attachmentPoint) {
262 ASSERT(isBound(target));
263 WebGLAttachment* attachmentObject = getAttachment(attachment);
264 if (attachmentObject)
265 attachmentObject->attach(context()->contextGL(), target, attachmentPoint);
266 }
267
268 WebGLSharedObject* WebGLFramebuffer::getAttachmentObject( 308 WebGLSharedObject* WebGLFramebuffer::getAttachmentObject(
269 GLenum attachment) const { 309 GLenum attachment) const {
270 if (!m_object) 310 if (!m_object)
271 return nullptr; 311 return nullptr;
272 WebGLAttachment* attachmentObject = getAttachment(attachment); 312 WebGLAttachment* attachmentObject = getAttachment(attachment);
273 return attachmentObject ? attachmentObject->object() : nullptr; 313 return attachmentObject ? attachmentObject->object() : nullptr;
274 } 314 }
275 315
276 WebGLFramebuffer::WebGLAttachment* WebGLFramebuffer::getAttachment( 316 WebGLFramebuffer::WebGLAttachment* WebGLFramebuffer::getAttachment(
277 GLenum attachment) const { 317 GLenum attachment) const {
278 const AttachmentMap::const_iterator it = m_attachments.find(attachment); 318 const AttachmentMap::const_iterator it = m_attachments.find(attachment);
279 return (it != m_attachments.end()) ? it->value.get() : 0; 319 return (it != m_attachments.end()) ? it->value.get() : 0;
280 } 320 }
281 321
282 void WebGLFramebuffer::removeAttachmentFromBoundFramebuffer(GLenum target,
283 GLenum attachment) {
284 ASSERT(isBound(target));
285 if (!m_object)
286 return;
287
288 WebGLAttachment* attachmentObject = getAttachment(attachment);
289 if (attachmentObject) {
290 attachmentObject->onDetached(context()->contextGL());
291 m_attachments.remove(attachment);
292 drawBuffersIfNecessary(false);
293 switch (attachment) {
294 case GL_DEPTH_STENCIL_ATTACHMENT:
295 attach(target, GL_DEPTH_ATTACHMENT, GL_DEPTH_ATTACHMENT);
296 attach(target, GL_STENCIL_ATTACHMENT, GL_STENCIL_ATTACHMENT);
297 break;
298 case GL_DEPTH_ATTACHMENT:
299 case GL_STENCIL_ATTACHMENT:
300 attach(target, GL_DEPTH_STENCIL_ATTACHMENT,
301 GL_DEPTH_STENCIL_ATTACHMENT);
302 break;
303 }
304 }
305 }
306
307 void WebGLFramebuffer::removeAttachmentFromBoundFramebuffer( 322 void WebGLFramebuffer::removeAttachmentFromBoundFramebuffer(
308 GLenum target, 323 GLenum target,
309 WebGLSharedObject* attachment) { 324 WebGLSharedObject* attachment) {
310 ASSERT(isBound(target)); 325 ASSERT(isBound(target));
311 if (!m_object) 326 if (!m_object)
312 return; 327 return;
313 if (!attachment) 328 if (!attachment)
314 return; 329 return;
315 330
316 bool checkMore = true; 331 bool checkMore = true;
332 bool isWebGL1 = !context()->isWebGL2OrHigher();
333 bool checkWebGL1DepthStencil = false;
317 while (checkMore) { 334 while (checkMore) {
318 checkMore = false; 335 checkMore = false;
319 for (const auto& it : m_attachments) { 336 for (const auto& it : m_attachments) {
320 WebGLAttachment* attachmentObject = it.value.get(); 337 WebGLAttachment* attachmentObject = it.value.get();
321 if (attachmentObject->isSharedObject(attachment)) { 338 if (attachmentObject->isSharedObject(attachment)) {
322 GLenum attachmentType = it.key; 339 GLenum attachmentType = it.key;
323 attachmentObject->unattach(context()->contextGL(), target, 340 switch (attachmentType) {
324 attachmentType); 341 case GL_DEPTH_ATTACHMENT:
325 removeAttachmentFromBoundFramebuffer(target, attachmentType); 342 case GL_STENCIL_ATTACHMENT:
343 case GL_DEPTH_STENCIL_ATTACHMENT:
344 if (isWebGL1) {
345 checkWebGL1DepthStencil = true;
346 } else {
347 attachmentObject->unattach(context()->contextGL(), target,
348 attachmentType);
349 }
350 break;
351 default:
352 attachmentObject->unattach(context()->contextGL(), target,
353 attachmentType);
354 break;
355 }
356 removeAttachmentInternal(target, attachmentType);
326 checkMore = true; 357 checkMore = true;
327 break; 358 break;
328 } 359 }
329 } 360 }
330 } 361 }
362 if (checkWebGL1DepthStencil)
363 commitWebGL1DepthStencilIfConsistent(target);
331 } 364 }
332 365
333 GLenum WebGLFramebuffer::checkDepthStencilStatus(const char** reason) const { 366 GLenum WebGLFramebuffer::checkDepthStencilStatus(const char** reason) const {
334 if (context()->isWebGL2OrHigher()) 367 if (context()->isWebGL2OrHigher() || m_webGL1DepthStencilConsistent)
335 return GL_FRAMEBUFFER_COMPLETE; 368 return GL_FRAMEBUFFER_COMPLETE;
336 WebGLAttachment* depthAttachment = nullptr; 369 *reason = "conflicting DEPTH/STENCIL/DEPTH_STENCIL attachments";
337 WebGLAttachment* stencilAttachment = nullptr; 370 return GL_FRAMEBUFFER_UNSUPPORTED;
338 WebGLAttachment* depthStencilAttachment = nullptr;
339 for (const auto& it : m_attachments) {
340 WebGLAttachment* attachment = it.value.get();
341 ASSERT(attachment);
342 switch (it.key) {
343 case GL_DEPTH_ATTACHMENT:
344 depthAttachment = attachment;
345 break;
346 case GL_STENCIL_ATTACHMENT:
347 stencilAttachment = attachment;
348 break;
349 case GL_DEPTH_STENCIL_ATTACHMENT:
350 depthStencilAttachment = attachment;
351 break;
352 default:
353 break;
354 }
355 }
356 if ((depthStencilAttachment && (depthAttachment || stencilAttachment)) ||
357 (depthAttachment && stencilAttachment)) {
358 *reason = "conflicting DEPTH/STENCIL/DEPTH_STENCIL attachments";
359 return GL_FRAMEBUFFER_UNSUPPORTED;
360 }
361 return GL_FRAMEBUFFER_COMPLETE;
362 } 371 }
363 372
364 bool WebGLFramebuffer::hasStencilBuffer() const { 373 bool WebGLFramebuffer::hasStencilBuffer() const {
365 WebGLAttachment* attachment = getAttachment(GL_STENCIL_ATTACHMENT); 374 WebGLAttachment* attachment = getAttachment(GL_STENCIL_ATTACHMENT);
366 if (!attachment) 375 if (!attachment)
367 attachment = getAttachment(GL_DEPTH_STENCIL_ATTACHMENT); 376 attachment = getAttachment(GL_DEPTH_STENCIL_ATTACHMENT);
368 return attachment && attachment->valid(); 377 return attachment && attachment->valid();
369 } 378 }
370 379
371 void WebGLFramebuffer::deleteObjectImpl(gpu::gles2::GLES2Interface* gl) { 380 void WebGLFramebuffer::deleteObjectImpl(gpu::gles2::GLES2Interface* gl) {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
413 } 422 }
414 } 423 }
415 } 424 }
416 if (reset) { 425 if (reset) {
417 context()->contextGL()->DrawBuffersEXT(m_filteredDrawBuffers.size(), 426 context()->contextGL()->DrawBuffersEXT(m_filteredDrawBuffers.size(),
418 m_filteredDrawBuffers.data()); 427 m_filteredDrawBuffers.data());
419 } 428 }
420 } 429 }
421 } 430 }
422 431
432 void WebGLFramebuffer::setAttachmentInternal(GLenum target,
433 GLenum attachment,
434 GLenum texTarget,
435 WebGLTexture* texture,
436 GLint level,
437 GLint layer) {
438 DCHECK(isBound(target));
439 DCHECK(m_object);
440 removeAttachmentInternal(target, attachment);
441 if (texture && texture->object()) {
442 m_attachments.add(attachment, WebGLTextureAttachment::create(
443 texture, texTarget, level, layer));
444 drawBuffersIfNecessary(false);
445 texture->onAttached();
446 }
447 }
448
449 void WebGLFramebuffer::setAttachmentInternal(GLenum target,
450 GLenum attachment,
451 WebGLRenderbuffer* renderbuffer) {
452 DCHECK(isBound(target));
453 DCHECK(m_object);
454 removeAttachmentInternal(target, attachment);
455 if (renderbuffer && renderbuffer->object()) {
456 m_attachments.add(attachment,
457 WebGLRenderbufferAttachment::create(renderbuffer));
458 drawBuffersIfNecessary(false);
459 renderbuffer->onAttached();
460 }
461 }
462
463 void WebGLFramebuffer::removeAttachmentInternal(GLenum target,
464 GLenum attachment) {
465 DCHECK(isBound(target));
466 DCHECK(m_object);
467
468 WebGLAttachment* attachmentObject = getAttachment(attachment);
469 if (attachmentObject) {
470 attachmentObject->onDetached(context()->contextGL());
471 m_attachments.remove(attachment);
472 drawBuffersIfNecessary(false);
473 }
474 }
475
476 void WebGLFramebuffer::commitWebGL1DepthStencilIfConsistent(GLenum target) {
477 DCHECK(!context()->isWebGL2OrHigher());
478 WebGLAttachment* depthAttachment = nullptr;
479 WebGLAttachment* stencilAttachment = nullptr;
480 WebGLAttachment* depthStencilAttachment = nullptr;
481 int count = 0;
482 for (const auto& it : m_attachments) {
483 WebGLAttachment* attachment = it.value.get();
484 DCHECK(attachment);
485 switch (it.key) {
486 case GL_DEPTH_ATTACHMENT:
487 depthAttachment = attachment;
488 ++count;
489 break;
490 case GL_STENCIL_ATTACHMENT:
491 stencilAttachment = attachment;
492 ++count;
493 break;
494 case GL_DEPTH_STENCIL_ATTACHMENT:
495 depthStencilAttachment = attachment;
496 ++count;
497 break;
498 default:
499 break;
500 }
501 }
502
503 m_webGL1DepthStencilConsistent = count <= 1;
504 if (!m_webGL1DepthStencilConsistent)
505 return;
506
507 gpu::gles2::GLES2Interface* gl = context()->contextGL();
508 if (depthAttachment) {
509 depthAttachment->attach(gl, target, GL_DEPTH_ATTACHMENT);
510 gl->FramebufferRenderbuffer(target, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
511 0);
512 } else if (stencilAttachment) {
513 gl->FramebufferRenderbuffer(target, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
514 0);
515 stencilAttachment->attach(gl, target, GL_STENCIL_ATTACHMENT);
516 } else if (depthStencilAttachment) {
517 depthStencilAttachment->attach(gl, target, GL_DEPTH_STENCIL_ATTACHMENT);
518 } else {
519 gl->FramebufferRenderbuffer(target, GL_DEPTH_STENCIL_ATTACHMENT,
520 GL_RENDERBUFFER, 0);
521 }
522 }
523
423 GLenum WebGLFramebuffer::getDrawBuffer(GLenum drawBuffer) { 524 GLenum WebGLFramebuffer::getDrawBuffer(GLenum drawBuffer) {
424 int index = static_cast<int>(drawBuffer - GL_DRAW_BUFFER0_EXT); 525 int index = static_cast<int>(drawBuffer - GL_DRAW_BUFFER0_EXT);
425 ASSERT(index >= 0); 526 ASSERT(index >= 0);
426 if (index < static_cast<int>(m_drawBuffers.size())) 527 if (index < static_cast<int>(m_drawBuffers.size()))
427 return m_drawBuffers[index]; 528 return m_drawBuffers[index];
428 if (drawBuffer == GL_DRAW_BUFFER0_EXT) 529 if (drawBuffer == GL_DRAW_BUFFER0_EXT)
429 return GL_COLOR_ATTACHMENT0; 530 return GL_COLOR_ATTACHMENT0;
430 return GL_NONE; 531 return GL_NONE;
431 } 532 }
432 533
433 void WebGLFramebuffer::visitChildDOMWrappers( 534 void WebGLFramebuffer::visitChildDOMWrappers(
434 v8::Isolate* isolate, 535 v8::Isolate* isolate,
435 const v8::Persistent<v8::Object>& wrapper) { 536 const v8::Persistent<v8::Object>& wrapper) {
436 for (const auto& attachment : m_attachments) { 537 for (const auto& attachment : m_attachments) {
437 DOMWrapperWorld::setWrapperReferencesInAllWorlds( 538 DOMWrapperWorld::setWrapperReferencesInAllWorlds(
438 wrapper, attachment.value->object(), isolate); 539 wrapper, attachment.value->object(), isolate);
439 } 540 }
440 } 541 }
441 542
442 DEFINE_TRACE(WebGLFramebuffer) { 543 DEFINE_TRACE(WebGLFramebuffer) {
443 visitor->trace(m_attachments); 544 visitor->trace(m_attachments);
444 WebGLContextObject::trace(visitor); 545 WebGLContextObject::trace(visitor);
445 } 546 }
446 547
447 } // namespace blink 548 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698