content/canvas/src/WebGLFramebuffer.cpp

Thu, 15 Jan 2015 21:03:48 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 21:03:48 +0100
branch
TOR_BUG_9701
changeset 11
deefc01c0e14
permissions
-rw-r--r--

Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)

michael@0 1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "WebGLContext.h"
michael@0 7 #include "WebGLFramebuffer.h"
michael@0 8 #include "WebGLExtensions.h"
michael@0 9 #include "WebGLRenderbuffer.h"
michael@0 10 #include "WebGLTexture.h"
michael@0 11 #include "mozilla/dom/WebGLRenderingContextBinding.h"
michael@0 12 #include "WebGLTexture.h"
michael@0 13 #include "WebGLRenderbuffer.h"
michael@0 14 #include "GLContext.h"
michael@0 15 #include "WebGLContextUtils.h"
michael@0 16
michael@0 17 using namespace mozilla;
michael@0 18 using namespace mozilla::gl;
michael@0 19
michael@0 20 JSObject*
michael@0 21 WebGLFramebuffer::WrapObject(JSContext* cx)
michael@0 22 {
michael@0 23 return dom::WebGLFramebufferBinding::Wrap(cx, this);
michael@0 24 }
michael@0 25
michael@0 26 WebGLFramebuffer::WebGLFramebuffer(WebGLContext* context)
michael@0 27 : WebGLContextBoundObject(context)
michael@0 28 , mStatus(0)
michael@0 29 , mHasEverBeenBound(false)
michael@0 30 , mDepthAttachment(LOCAL_GL_DEPTH_ATTACHMENT)
michael@0 31 , mStencilAttachment(LOCAL_GL_STENCIL_ATTACHMENT)
michael@0 32 , mDepthStencilAttachment(LOCAL_GL_DEPTH_STENCIL_ATTACHMENT)
michael@0 33 {
michael@0 34 SetIsDOMBinding();
michael@0 35 mContext->MakeContextCurrent();
michael@0 36 mContext->gl->fGenFramebuffers(1, &mGLName);
michael@0 37 mContext->mFramebuffers.insertBack(this);
michael@0 38
michael@0 39 mColorAttachments.SetLength(1);
michael@0 40 mColorAttachments[0].mAttachmentPoint = LOCAL_GL_COLOR_ATTACHMENT0;
michael@0 41 }
michael@0 42
michael@0 43 bool
michael@0 44 WebGLFramebuffer::Attachment::IsDeleteRequested() const
michael@0 45 {
michael@0 46 return Texture() ? Texture()->IsDeleteRequested()
michael@0 47 : Renderbuffer() ? Renderbuffer()->IsDeleteRequested()
michael@0 48 : false;
michael@0 49 }
michael@0 50
michael@0 51 bool
michael@0 52 WebGLFramebuffer::Attachment::HasAlpha() const
michael@0 53 {
michael@0 54 MOZ_ASSERT(HasImage());
michael@0 55
michael@0 56 GLenum format = 0;
michael@0 57 if (Texture() && Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel))
michael@0 58 format = Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel).WebGLFormat();
michael@0 59 else if (Renderbuffer())
michael@0 60 format = Renderbuffer()->InternalFormat();
michael@0 61 return FormatHasAlpha(format);
michael@0 62 }
michael@0 63
michael@0 64 bool
michael@0 65 WebGLFramebuffer::Attachment::IsReadableFloat() const
michael@0 66 {
michael@0 67 if (Texture() && Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel)) {
michael@0 68 GLenum type = Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel).WebGLType();
michael@0 69 switch (type) {
michael@0 70 case LOCAL_GL_FLOAT:
michael@0 71 case LOCAL_GL_HALF_FLOAT_OES:
michael@0 72 return true;
michael@0 73 }
michael@0 74 return false;
michael@0 75 }
michael@0 76
michael@0 77 if (Renderbuffer()) {
michael@0 78 GLenum format = Renderbuffer()->InternalFormat();
michael@0 79 switch (format) {
michael@0 80 case LOCAL_GL_RGB16F:
michael@0 81 case LOCAL_GL_RGBA16F:
michael@0 82 case LOCAL_GL_RGB32F:
michael@0 83 case LOCAL_GL_RGBA32F:
michael@0 84 return true;
michael@0 85 }
michael@0 86 return false;
michael@0 87 }
michael@0 88
michael@0 89 MOZ_ASSERT(false, "Should not get here.");
michael@0 90 return false;
michael@0 91 }
michael@0 92
michael@0 93 void
michael@0 94 WebGLFramebuffer::Attachment::SetTexImage(WebGLTexture* tex, GLenum target, GLint level)
michael@0 95 {
michael@0 96 mTexturePtr = tex;
michael@0 97 mRenderbufferPtr = nullptr;
michael@0 98 mTexImageTarget = target;
michael@0 99 mTexImageLevel = level;
michael@0 100
michael@0 101 mNeedsFinalize = true;
michael@0 102 }
michael@0 103
michael@0 104 void
michael@0 105 WebGLFramebuffer::Attachment::SetRenderbuffer(WebGLRenderbuffer* rb)
michael@0 106 {
michael@0 107 mTexturePtr = nullptr;
michael@0 108 mRenderbufferPtr = rb;
michael@0 109
michael@0 110 mNeedsFinalize = true;
michael@0 111 }
michael@0 112
michael@0 113 bool
michael@0 114 WebGLFramebuffer::Attachment::HasUninitializedImageData() const
michael@0 115 {
michael@0 116 if (!HasImage())
michael@0 117 return false;
michael@0 118
michael@0 119 if (Renderbuffer()) {
michael@0 120 return Renderbuffer()->HasUninitializedImageData();
michael@0 121 }
michael@0 122
michael@0 123 if (Texture()) {
michael@0 124 MOZ_ASSERT(Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel));
michael@0 125 return Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel).HasUninitializedImageData();
michael@0 126 }
michael@0 127
michael@0 128 MOZ_ASSERT(false, "Should not get here.");
michael@0 129 return false;
michael@0 130 }
michael@0 131
michael@0 132 void
michael@0 133 WebGLFramebuffer::Attachment::SetImageDataStatus(WebGLImageDataStatus newStatus)
michael@0 134 {
michael@0 135 if (!HasImage())
michael@0 136 return;
michael@0 137
michael@0 138 if (Renderbuffer()) {
michael@0 139 Renderbuffer()->SetImageDataStatus(newStatus);
michael@0 140 return;
michael@0 141 }
michael@0 142
michael@0 143 if (Texture()) {
michael@0 144 Texture()->SetImageDataStatus(mTexImageTarget, mTexImageLevel, newStatus);
michael@0 145 return;
michael@0 146 }
michael@0 147
michael@0 148 MOZ_ASSERT(false, "Should not get here.");
michael@0 149 }
michael@0 150
michael@0 151 bool
michael@0 152 WebGLFramebuffer::Attachment::HasImage() const
michael@0 153 {
michael@0 154 if (Texture() && Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel))
michael@0 155 return true;
michael@0 156
michael@0 157 if (Renderbuffer())
michael@0 158 return true;
michael@0 159
michael@0 160 return false;
michael@0 161 }
michael@0 162
michael@0 163 const WebGLRectangleObject&
michael@0 164 WebGLFramebuffer::Attachment::RectangleObject() const
michael@0 165 {
michael@0 166 MOZ_ASSERT(HasImage(), "Make sure it has an image before requesting the rectangle.");
michael@0 167
michael@0 168 if (Texture()) {
michael@0 169 MOZ_ASSERT(Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel));
michael@0 170 return Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel);
michael@0 171 }
michael@0 172
michael@0 173 if (Renderbuffer()) {
michael@0 174 return *Renderbuffer();
michael@0 175 }
michael@0 176
michael@0 177 MOZ_CRASH("Should not get here.");
michael@0 178 }
michael@0 179
michael@0 180 /* The following IsValidFBOTextureXXX functions check the internal
michael@0 181 format that is used by GL or GL ES texture formats. This
michael@0 182 corresponds to the state that is stored in
michael@0 183 WebGLTexture::ImageInfo::InternalFormat()*/
michael@0 184 static inline bool
michael@0 185 IsValidFBOTextureColorFormat(GLenum internalFormat)
michael@0 186 {
michael@0 187 /* These formats are internal formats for each texture -- the actual
michael@0 188 * low level format, which we might have to do conversions for when
michael@0 189 * running against desktop GL (e.g. GL_RGBA + GL_FLOAT -> GL_RGBA32F).
michael@0 190 *
michael@0 191 * This function just handles all of them whether desktop GL or ES.
michael@0 192 */
michael@0 193
michael@0 194 return (
michael@0 195 /* linear 8-bit formats */
michael@0 196 internalFormat == LOCAL_GL_ALPHA ||
michael@0 197 internalFormat == LOCAL_GL_LUMINANCE ||
michael@0 198 internalFormat == LOCAL_GL_LUMINANCE_ALPHA ||
michael@0 199 internalFormat == LOCAL_GL_RGB ||
michael@0 200 internalFormat == LOCAL_GL_RGBA ||
michael@0 201 /* sRGB 8-bit formats */
michael@0 202 internalFormat == LOCAL_GL_SRGB_EXT ||
michael@0 203 internalFormat == LOCAL_GL_SRGB_ALPHA_EXT ||
michael@0 204 /* linear float32 formats */
michael@0 205 internalFormat == LOCAL_GL_ALPHA32F_ARB ||
michael@0 206 internalFormat == LOCAL_GL_LUMINANCE32F_ARB ||
michael@0 207 internalFormat == LOCAL_GL_LUMINANCE_ALPHA32F_ARB ||
michael@0 208 internalFormat == LOCAL_GL_RGB32F_ARB ||
michael@0 209 internalFormat == LOCAL_GL_RGBA32F_ARB ||
michael@0 210 /* texture_half_float formats */
michael@0 211 internalFormat == LOCAL_GL_ALPHA16F_ARB ||
michael@0 212 internalFormat == LOCAL_GL_LUMINANCE16F_ARB ||
michael@0 213 internalFormat == LOCAL_GL_LUMINANCE_ALPHA16F_ARB ||
michael@0 214 internalFormat == LOCAL_GL_RGB16F_ARB ||
michael@0 215 internalFormat == LOCAL_GL_RGBA16F_ARB
michael@0 216 );
michael@0 217 }
michael@0 218
michael@0 219 static inline bool
michael@0 220 IsValidFBOTextureDepthFormat(GLenum internalFormat)
michael@0 221 {
michael@0 222 return (
michael@0 223 internalFormat == LOCAL_GL_DEPTH_COMPONENT ||
michael@0 224 internalFormat == LOCAL_GL_DEPTH_COMPONENT16 ||
michael@0 225 internalFormat == LOCAL_GL_DEPTH_COMPONENT32);
michael@0 226 }
michael@0 227
michael@0 228 static inline bool
michael@0 229 IsValidFBOTextureDepthStencilFormat(GLenum internalFormat)
michael@0 230 {
michael@0 231 return (
michael@0 232 internalFormat == LOCAL_GL_DEPTH_STENCIL ||
michael@0 233 internalFormat == LOCAL_GL_DEPTH24_STENCIL8);
michael@0 234 }
michael@0 235
michael@0 236 /* The following IsValidFBORenderbufferXXX functions check the internal
michael@0 237 format that is stored by WebGLRenderbuffer::InternalFormat(). Valid
michael@0 238 values can be found in WebGLContext::RenderbufferStorage. */
michael@0 239 static inline bool
michael@0 240 IsValidFBORenderbufferColorFormat(GLenum internalFormat)
michael@0 241 {
michael@0 242 return (
michael@0 243 internalFormat == LOCAL_GL_RGB565 ||
michael@0 244 internalFormat == LOCAL_GL_RGB5_A1 ||
michael@0 245 internalFormat == LOCAL_GL_RGBA4 ||
michael@0 246 internalFormat == LOCAL_GL_SRGB8_ALPHA8_EXT);
michael@0 247 }
michael@0 248
michael@0 249 static inline bool
michael@0 250 IsValidFBORenderbufferDepthFormat(GLenum internalFormat)
michael@0 251 {
michael@0 252 return internalFormat == LOCAL_GL_DEPTH_COMPONENT16;
michael@0 253 }
michael@0 254
michael@0 255 static inline bool
michael@0 256 IsValidFBORenderbufferDepthStencilFormat(GLenum internalFormat)
michael@0 257 {
michael@0 258 return internalFormat == LOCAL_GL_DEPTH_STENCIL;
michael@0 259 }
michael@0 260
michael@0 261 static inline bool
michael@0 262 IsValidFBORenderbufferStencilFormat(GLenum internalFormat)
michael@0 263 {
michael@0 264 return internalFormat == LOCAL_GL_STENCIL_INDEX8;
michael@0 265 }
michael@0 266
michael@0 267 bool
michael@0 268 WebGLFramebuffer::Attachment::IsComplete() const
michael@0 269 {
michael@0 270 if (!HasImage())
michael@0 271 return false;
michael@0 272
michael@0 273 const WebGLRectangleObject& rect = RectangleObject();
michael@0 274
michael@0 275 if (!rect.Width() ||
michael@0 276 !rect.Height())
michael@0 277 {
michael@0 278 return false;
michael@0 279 }
michael@0 280
michael@0 281 if (Texture()) {
michael@0 282 MOZ_ASSERT(Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel));
michael@0 283 const WebGLTexture::ImageInfo& imageInfo =
michael@0 284 Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel);
michael@0 285 GLenum webGLFormat = imageInfo.WebGLFormat();
michael@0 286
michael@0 287 if (mAttachmentPoint == LOCAL_GL_DEPTH_ATTACHMENT)
michael@0 288 return IsValidFBOTextureDepthFormat(webGLFormat);
michael@0 289
michael@0 290 if (mAttachmentPoint == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT)
michael@0 291 return IsValidFBOTextureDepthStencilFormat(webGLFormat);
michael@0 292
michael@0 293 if (mAttachmentPoint >= LOCAL_GL_COLOR_ATTACHMENT0 &&
michael@0 294 mAttachmentPoint < GLenum(LOCAL_GL_COLOR_ATTACHMENT0 +
michael@0 295 WebGLContext::sMaxColorAttachments))
michael@0 296 {
michael@0 297 return IsValidFBOTextureColorFormat(webGLFormat);
michael@0 298 }
michael@0 299 MOZ_ASSERT(false, "Invalid WebGL attachment point?");
michael@0 300 return false;
michael@0 301 }
michael@0 302
michael@0 303 if (Renderbuffer()) {
michael@0 304 GLenum internalFormat = Renderbuffer()->InternalFormat();
michael@0 305
michael@0 306 if (mAttachmentPoint == LOCAL_GL_DEPTH_ATTACHMENT)
michael@0 307 return IsValidFBORenderbufferDepthFormat(internalFormat);
michael@0 308
michael@0 309 if (mAttachmentPoint == LOCAL_GL_STENCIL_ATTACHMENT)
michael@0 310 return IsValidFBORenderbufferStencilFormat(internalFormat);
michael@0 311
michael@0 312 if (mAttachmentPoint == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT)
michael@0 313 return IsValidFBORenderbufferDepthStencilFormat(internalFormat);
michael@0 314
michael@0 315 if (mAttachmentPoint >= LOCAL_GL_COLOR_ATTACHMENT0 &&
michael@0 316 mAttachmentPoint < GLenum(LOCAL_GL_COLOR_ATTACHMENT0 +
michael@0 317 WebGLContext::sMaxColorAttachments))
michael@0 318 {
michael@0 319 return IsValidFBORenderbufferColorFormat(internalFormat);
michael@0 320 }
michael@0 321 MOZ_ASSERT(false, "Invalid WebGL attachment point?");
michael@0 322 return false;
michael@0 323 }
michael@0 324
michael@0 325 MOZ_ASSERT(false, "Should not get here.");
michael@0 326 return false;
michael@0 327 }
michael@0 328
michael@0 329 void
michael@0 330 WebGLFramebuffer::Attachment::FinalizeAttachment(GLContext* gl, GLenum attachmentLoc) const
michael@0 331 {
michael@0 332 if (!mNeedsFinalize)
michael@0 333 return;
michael@0 334
michael@0 335 mNeedsFinalize = false;
michael@0 336
michael@0 337 if (!HasImage()) {
michael@0 338 if (attachmentLoc == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
michael@0 339 gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT,
michael@0 340 LOCAL_GL_RENDERBUFFER, 0);
michael@0 341 gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT,
michael@0 342 LOCAL_GL_RENDERBUFFER, 0);
michael@0 343 } else {
michael@0 344 gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, attachmentLoc,
michael@0 345 LOCAL_GL_RENDERBUFFER, 0);
michael@0 346 }
michael@0 347
michael@0 348 return;
michael@0 349 }
michael@0 350 MOZ_ASSERT(HasImage());
michael@0 351
michael@0 352 if (Texture()) {
michael@0 353 MOZ_ASSERT(gl == Texture()->Context()->gl);
michael@0 354
michael@0 355 if (attachmentLoc == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
michael@0 356 gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT,
michael@0 357 TexImageTarget(), Texture()->GLName(), TexImageLevel());
michael@0 358 gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT,
michael@0 359 TexImageTarget(), Texture()->GLName(), TexImageLevel());
michael@0 360 } else {
michael@0 361 gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, attachmentLoc,
michael@0 362 TexImageTarget(), Texture()->GLName(), TexImageLevel());
michael@0 363 }
michael@0 364 return;
michael@0 365 }
michael@0 366
michael@0 367 if (Renderbuffer()) {
michael@0 368 Renderbuffer()->FramebufferRenderbuffer(attachmentLoc);
michael@0 369 return;
michael@0 370 }
michael@0 371
michael@0 372 MOZ_ASSERT(false, "Should not get here.");
michael@0 373 }
michael@0 374
michael@0 375 void
michael@0 376 WebGLFramebuffer::Delete()
michael@0 377 {
michael@0 378 DetachAllAttachments();
michael@0 379 mColorAttachments.Clear();
michael@0 380 mDepthAttachment.Reset();
michael@0 381 mStencilAttachment.Reset();
michael@0 382 mDepthStencilAttachment.Reset();
michael@0 383
michael@0 384 mContext->MakeContextCurrent();
michael@0 385 mContext->gl->fDeleteFramebuffers(1, &mGLName);
michael@0 386 LinkedListElement<WebGLFramebuffer>::removeFrom(mContext->mFramebuffers);
michael@0 387 }
michael@0 388
michael@0 389 void
michael@0 390 WebGLFramebuffer::DetachAttachment(WebGLFramebuffer::Attachment& attachment)
michael@0 391 {
michael@0 392 if (attachment.Texture())
michael@0 393 attachment.Texture()->DetachFrom(this, attachment.mAttachmentPoint);
michael@0 394
michael@0 395 if (attachment.Renderbuffer())
michael@0 396 attachment.Renderbuffer()->DetachFrom(this, attachment.mAttachmentPoint);
michael@0 397 }
michael@0 398
michael@0 399 void
michael@0 400 WebGLFramebuffer::DetachAllAttachments()
michael@0 401 {
michael@0 402 size_t count = mColorAttachments.Length();
michael@0 403 for (size_t i = 0; i < count; i++) {
michael@0 404 DetachAttachment(mColorAttachments[i]);
michael@0 405 }
michael@0 406
michael@0 407 DetachAttachment(mDepthAttachment);
michael@0 408 DetachAttachment(mStencilAttachment);
michael@0 409 DetachAttachment(mDepthStencilAttachment);
michael@0 410 }
michael@0 411
michael@0 412 void
michael@0 413 WebGLFramebuffer::FramebufferRenderbuffer(GLenum target,
michael@0 414 GLenum attachment,
michael@0 415 GLenum rbtarget,
michael@0 416 WebGLRenderbuffer* wrb)
michael@0 417 {
michael@0 418 MOZ_ASSERT(mContext->mBoundFramebuffer == this);
michael@0 419
michael@0 420 if (!mContext->ValidateObjectAllowNull("framebufferRenderbuffer: renderbuffer", wrb))
michael@0 421 return;
michael@0 422
michael@0 423 if (target != LOCAL_GL_FRAMEBUFFER)
michael@0 424 return mContext->ErrorInvalidEnumInfo("framebufferRenderbuffer: target", target);
michael@0 425
michael@0 426 if (rbtarget != LOCAL_GL_RENDERBUFFER)
michael@0 427 return mContext->ErrorInvalidEnumInfo("framebufferRenderbuffer: renderbuffer target:", rbtarget);
michael@0 428
michael@0 429 /* Get the requested attachment. If result is NULL, attachment is
michael@0 430 * invalid and an error is generated.
michael@0 431 *
michael@0 432 * Don't use GetAttachment(...) here because it opt builds it
michael@0 433 * returns mColorAttachment[0] for invalid attachment, which we
michael@0 434 * really don't want to mess with.
michael@0 435 */
michael@0 436 Attachment* a = GetAttachmentOrNull(attachment);
michael@0 437 if (!a)
michael@0 438 return; // Error generated internally to GetAttachmentOrNull.
michael@0 439
michael@0 440 /* Invalidate cached framebuffer status and inform texture of it's
michael@0 441 * new attachment
michael@0 442 */
michael@0 443 mStatus = 0;
michael@0 444 // Detach current
michael@0 445 if (a->Texture())
michael@0 446 a->Texture()->DetachFrom(this, attachment);
michael@0 447 else if (a->Renderbuffer())
michael@0 448 a->Renderbuffer()->DetachFrom(this, attachment);
michael@0 449
michael@0 450 // Attach new
michael@0 451 if (wrb)
michael@0 452 wrb->AttachTo(this, attachment);
michael@0 453
michael@0 454 a->SetRenderbuffer(wrb);
michael@0 455 }
michael@0 456
michael@0 457 void
michael@0 458 WebGLFramebuffer::FramebufferTexture2D(GLenum target,
michael@0 459 GLenum attachment,
michael@0 460 GLenum textarget,
michael@0 461 WebGLTexture* wtex,
michael@0 462 GLint level)
michael@0 463 {
michael@0 464 MOZ_ASSERT(mContext->mBoundFramebuffer == this);
michael@0 465
michael@0 466 if (!mContext->ValidateObjectAllowNull("framebufferTexture2D: texture", wtex))
michael@0 467 return;
michael@0 468
michael@0 469 if (target != LOCAL_GL_FRAMEBUFFER)
michael@0 470 return mContext->ErrorInvalidEnumInfo("framebufferTexture2D: target", target);
michael@0 471
michael@0 472 if (textarget != LOCAL_GL_TEXTURE_2D &&
michael@0 473 (textarget < LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
michael@0 474 textarget > LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))
michael@0 475 {
michael@0 476 return mContext->ErrorInvalidEnumInfo("framebufferTexture2D: invalid texture target", textarget);
michael@0 477 }
michael@0 478
michael@0 479 if (wtex) {
michael@0 480 bool isTexture2D = wtex->Target() == LOCAL_GL_TEXTURE_2D;
michael@0 481 bool isTexTarget2D = textarget == LOCAL_GL_TEXTURE_2D;
michael@0 482 if (isTexture2D != isTexTarget2D) {
michael@0 483 return mContext->ErrorInvalidOperation("framebufferTexture2D: mismatched texture and texture target");
michael@0 484 }
michael@0 485 }
michael@0 486
michael@0 487 if (level != 0)
michael@0 488 return mContext->ErrorInvalidValue("framebufferTexture2D: level must be 0");
michael@0 489
michael@0 490 /* Get the requested attachment. If result is NULL, attachment is
michael@0 491 * invalid and an error is generated.
michael@0 492 *
michael@0 493 * Don't use GetAttachment(...) here because it opt builds it
michael@0 494 * returns mColorAttachment[0] for invalid attachment, which we
michael@0 495 * really don't want to mess with.
michael@0 496 */
michael@0 497 Attachment* a = GetAttachmentOrNull(attachment);
michael@0 498 if (!a)
michael@0 499 return; // Error generated internally to GetAttachmentOrNull.
michael@0 500
michael@0 501 /* Invalidate cached framebuffer status and inform texture of it's
michael@0 502 * new attachment
michael@0 503 */
michael@0 504 mStatus = 0;
michael@0 505 // Detach current
michael@0 506 if (a->Texture())
michael@0 507 a->Texture()->DetachFrom(this, attachment);
michael@0 508 else if (a->Renderbuffer())
michael@0 509 a->Renderbuffer()->DetachFrom(this, attachment);
michael@0 510
michael@0 511 // Attach new
michael@0 512 if (wtex)
michael@0 513 wtex->AttachTo(this, attachment);
michael@0 514
michael@0 515 a->SetTexImage(wtex, textarget, level);
michael@0 516 }
michael@0 517
michael@0 518 WebGLFramebuffer::Attachment*
michael@0 519 WebGLFramebuffer::GetAttachmentOrNull(GLenum attachment)
michael@0 520 {
michael@0 521 if (attachment == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT)
michael@0 522 return &mDepthStencilAttachment;
michael@0 523
michael@0 524 if (attachment == LOCAL_GL_DEPTH_ATTACHMENT)
michael@0 525 return &mDepthAttachment;
michael@0 526
michael@0 527 if (attachment == LOCAL_GL_STENCIL_ATTACHMENT)
michael@0 528 return &mStencilAttachment;
michael@0 529
michael@0 530 if (!CheckColorAttachmentNumber(attachment, "getAttachmentOrNull"))
michael@0 531 return nullptr;
michael@0 532
michael@0 533 size_t colorAttachmentId = attachment - LOCAL_GL_COLOR_ATTACHMENT0;
michael@0 534 EnsureColorAttachments(colorAttachmentId);
michael@0 535
michael@0 536 return &mColorAttachments[colorAttachmentId];
michael@0 537 }
michael@0 538
michael@0 539 const WebGLFramebuffer::Attachment&
michael@0 540 WebGLFramebuffer::GetAttachment(GLenum attachment) const
michael@0 541 {
michael@0 542 if (attachment == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT)
michael@0 543 return mDepthStencilAttachment;
michael@0 544 if (attachment == LOCAL_GL_DEPTH_ATTACHMENT)
michael@0 545 return mDepthAttachment;
michael@0 546 if (attachment == LOCAL_GL_STENCIL_ATTACHMENT)
michael@0 547 return mStencilAttachment;
michael@0 548
michael@0 549 if (!CheckColorAttachmentNumber(attachment, "getAttachment")) {
michael@0 550 MOZ_ASSERT(false);
michael@0 551 return mColorAttachments[0];
michael@0 552 }
michael@0 553
michael@0 554 size_t colorAttachmentId = attachment - LOCAL_GL_COLOR_ATTACHMENT0;
michael@0 555 if (colorAttachmentId >= mColorAttachments.Length()) {
michael@0 556 MOZ_ASSERT(false);
michael@0 557 return mColorAttachments[0];
michael@0 558 }
michael@0 559
michael@0 560 return mColorAttachments[colorAttachmentId];
michael@0 561 }
michael@0 562
michael@0 563 void
michael@0 564 WebGLFramebuffer::DetachTexture(const WebGLTexture* tex)
michael@0 565 {
michael@0 566 size_t count = mColorAttachments.Length();
michael@0 567 for (size_t i = 0; i < count; i++) {
michael@0 568 if (mColorAttachments[i].Texture() == tex) {
michael@0 569 FramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0+i, LOCAL_GL_TEXTURE_2D, nullptr, 0);
michael@0 570 // a texture might be attached more that once while editing the framebuffer
michael@0 571 }
michael@0 572 }
michael@0 573
michael@0 574 if (mDepthAttachment.Texture() == tex)
michael@0 575 FramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT, LOCAL_GL_TEXTURE_2D, nullptr, 0);
michael@0 576 if (mStencilAttachment.Texture() == tex)
michael@0 577 FramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT, LOCAL_GL_TEXTURE_2D, nullptr, 0);
michael@0 578 if (mDepthStencilAttachment.Texture() == tex)
michael@0 579 FramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_STENCIL_ATTACHMENT, LOCAL_GL_TEXTURE_2D, nullptr, 0);
michael@0 580 }
michael@0 581
michael@0 582 void
michael@0 583 WebGLFramebuffer::DetachRenderbuffer(const WebGLRenderbuffer* rb)
michael@0 584 {
michael@0 585 size_t count = mColorAttachments.Length();
michael@0 586 for (size_t i = 0; i < count; i++) {
michael@0 587 if (mColorAttachments[i].Renderbuffer() == rb) {
michael@0 588 FramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0+i, LOCAL_GL_RENDERBUFFER, nullptr);
michael@0 589 // a renderbuffer might be attached more that once while editing the framebuffer
michael@0 590 }
michael@0 591 }
michael@0 592
michael@0 593 if (mDepthAttachment.Renderbuffer() == rb)
michael@0 594 FramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT, LOCAL_GL_RENDERBUFFER, nullptr);
michael@0 595 if (mStencilAttachment.Renderbuffer() == rb)
michael@0 596 FramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT, LOCAL_GL_RENDERBUFFER, nullptr);
michael@0 597 if (mDepthStencilAttachment.Renderbuffer() == rb)
michael@0 598 FramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_STENCIL_ATTACHMENT, LOCAL_GL_RENDERBUFFER, nullptr);
michael@0 599 }
michael@0 600
michael@0 601 bool
michael@0 602 WebGLFramebuffer::HasDefinedAttachments() const
michael@0 603 {
michael@0 604 bool hasAttachments = false;
michael@0 605
michael@0 606 size_t count = mColorAttachments.Length();
michael@0 607 for (size_t i = 0; i < count; i++) {
michael@0 608 hasAttachments |= mColorAttachments[i].IsDefined();
michael@0 609 }
michael@0 610
michael@0 611 hasAttachments |= mDepthAttachment.IsDefined();
michael@0 612 hasAttachments |= mStencilAttachment.IsDefined();
michael@0 613 hasAttachments |= mDepthStencilAttachment.IsDefined();
michael@0 614
michael@0 615 return hasAttachments;
michael@0 616 }
michael@0 617
michael@0 618
michael@0 619 static bool
michael@0 620 IsIncomplete(const WebGLFramebuffer::Attachment& cur)
michael@0 621 {
michael@0 622 return cur.IsDefined() && !cur.IsComplete();
michael@0 623 }
michael@0 624
michael@0 625 bool
michael@0 626 WebGLFramebuffer::HasIncompleteAttachments() const
michael@0 627 {
michael@0 628 bool hasIncomplete = false;
michael@0 629
michael@0 630 size_t count = mColorAttachments.Length();
michael@0 631 for (size_t i = 0; i < count; i++) {
michael@0 632 hasIncomplete |= IsIncomplete(mColorAttachments[i]);
michael@0 633 }
michael@0 634
michael@0 635 hasIncomplete |= IsIncomplete(mDepthAttachment);
michael@0 636 hasIncomplete |= IsIncomplete(mStencilAttachment);
michael@0 637 hasIncomplete |= IsIncomplete(mDepthStencilAttachment);
michael@0 638
michael@0 639 return hasIncomplete;
michael@0 640 }
michael@0 641
michael@0 642
michael@0 643 const WebGLRectangleObject&
michael@0 644 WebGLFramebuffer::GetAnyRectObject() const
michael@0 645 {
michael@0 646 MOZ_ASSERT(HasDefinedAttachments());
michael@0 647
michael@0 648 size_t count = mColorAttachments.Length();
michael@0 649 for (size_t i = 0; i < count; i++) {
michael@0 650 if (mColorAttachments[i].HasImage())
michael@0 651 return mColorAttachments[i].RectangleObject();
michael@0 652 }
michael@0 653
michael@0 654 if (mDepthAttachment.HasImage())
michael@0 655 return mDepthAttachment.RectangleObject();
michael@0 656
michael@0 657 if (mStencilAttachment.HasImage())
michael@0 658 return mStencilAttachment.RectangleObject();
michael@0 659
michael@0 660 if (mDepthStencilAttachment.HasImage())
michael@0 661 return mDepthStencilAttachment.RectangleObject();
michael@0 662
michael@0 663 MOZ_CRASH("Should not get here.");
michael@0 664 }
michael@0 665
michael@0 666
michael@0 667 static bool
michael@0 668 RectsMatch(const WebGLFramebuffer::Attachment& attachment,
michael@0 669 const WebGLRectangleObject& rect)
michael@0 670 {
michael@0 671 return attachment.RectangleObject().HasSameDimensionsAs(rect);
michael@0 672 }
michael@0 673
michael@0 674 bool
michael@0 675 WebGLFramebuffer::AllImageRectsMatch() const
michael@0 676 {
michael@0 677 MOZ_ASSERT(HasDefinedAttachments());
michael@0 678 MOZ_ASSERT(!HasIncompleteAttachments());
michael@0 679
michael@0 680 const WebGLRectangleObject& rect = GetAnyRectObject();
michael@0 681
michael@0 682 // Alright, we have *a* rect, let's check all the others.
michael@0 683 bool imageRectsMatch = true;
michael@0 684
michael@0 685 size_t count = mColorAttachments.Length();
michael@0 686 for (size_t i = 0; i < count; i++) {
michael@0 687 if (mColorAttachments[i].HasImage())
michael@0 688 imageRectsMatch &= RectsMatch(mColorAttachments[i], rect);
michael@0 689 }
michael@0 690
michael@0 691 if (mDepthAttachment.HasImage())
michael@0 692 imageRectsMatch &= RectsMatch(mDepthAttachment, rect);
michael@0 693
michael@0 694 if (mStencilAttachment.HasImage())
michael@0 695 imageRectsMatch &= RectsMatch(mStencilAttachment, rect);
michael@0 696
michael@0 697 if (mDepthStencilAttachment.HasImage())
michael@0 698 imageRectsMatch &= RectsMatch(mDepthStencilAttachment, rect);
michael@0 699
michael@0 700 return imageRectsMatch;
michael@0 701 }
michael@0 702
michael@0 703
michael@0 704 const WebGLRectangleObject&
michael@0 705 WebGLFramebuffer::RectangleObject() const
michael@0 706 {
michael@0 707 // If we're using this as the RectObj of an FB, we need to be sure the FB
michael@0 708 // has a consistent rect.
michael@0 709 MOZ_ASSERT(AllImageRectsMatch(), "Did you mean `GetAnyRectObject`?");
michael@0 710 return GetAnyRectObject();
michael@0 711 }
michael@0 712
michael@0 713 GLenum
michael@0 714 WebGLFramebuffer::PrecheckFramebufferStatus() const
michael@0 715 {
michael@0 716 MOZ_ASSERT(mContext->mBoundFramebuffer == this);
michael@0 717
michael@0 718 if (!HasDefinedAttachments())
michael@0 719 return LOCAL_GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; // No attachments
michael@0 720
michael@0 721 if (HasIncompleteAttachments())
michael@0 722 return LOCAL_GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
michael@0 723
michael@0 724 if (!AllImageRectsMatch())
michael@0 725 return LOCAL_GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; // Inconsistent sizes
michael@0 726
michael@0 727 if (HasDepthStencilConflict())
michael@0 728 return LOCAL_GL_FRAMEBUFFER_UNSUPPORTED;
michael@0 729
michael@0 730 return LOCAL_GL_FRAMEBUFFER_COMPLETE;
michael@0 731 }
michael@0 732
michael@0 733 GLenum
michael@0 734 WebGLFramebuffer::CheckFramebufferStatus() const
michael@0 735 {
michael@0 736 if (mStatus != 0)
michael@0 737 return mStatus;
michael@0 738
michael@0 739 mStatus = PrecheckFramebufferStatus();
michael@0 740 if (mStatus != LOCAL_GL_FRAMEBUFFER_COMPLETE)
michael@0 741 return mStatus;
michael@0 742
michael@0 743 // Looks good on our end. Let's ask the driver.
michael@0 744 mContext->MakeContextCurrent();
michael@0 745
michael@0 746 // Ok, attach our chosen flavor of {DEPTH, STENCIL, DEPTH_STENCIL}.
michael@0 747 FinalizeAttachments();
michael@0 748
michael@0 749 mStatus = mContext->gl->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
michael@0 750 return mStatus;
michael@0 751 }
michael@0 752
michael@0 753 bool
michael@0 754 WebGLFramebuffer::HasCompletePlanes(GLbitfield mask)
michael@0 755 {
michael@0 756 if (CheckFramebufferStatus() != LOCAL_GL_FRAMEBUFFER_COMPLETE)
michael@0 757 return false;
michael@0 758
michael@0 759 MOZ_ASSERT(mContext->mBoundFramebuffer == this);
michael@0 760 bool hasPlanes = true;
michael@0 761 if (mask & LOCAL_GL_COLOR_BUFFER_BIT) {
michael@0 762 hasPlanes &= ColorAttachmentCount() &&
michael@0 763 ColorAttachment(0).IsDefined();
michael@0 764 }
michael@0 765
michael@0 766 if (mask & LOCAL_GL_DEPTH_BUFFER_BIT) {
michael@0 767 hasPlanes &= DepthAttachment().IsDefined() ||
michael@0 768 DepthStencilAttachment().IsDefined();
michael@0 769 }
michael@0 770
michael@0 771 if (mask & LOCAL_GL_STENCIL_BUFFER_BIT) {
michael@0 772 hasPlanes &= StencilAttachment().IsDefined() ||
michael@0 773 DepthStencilAttachment().IsDefined();
michael@0 774 }
michael@0 775
michael@0 776 return hasPlanes;
michael@0 777 }
michael@0 778
michael@0 779 bool
michael@0 780 WebGLFramebuffer::CheckAndInitializeAttachments()
michael@0 781 {
michael@0 782 MOZ_ASSERT(mContext->mBoundFramebuffer == this);
michael@0 783
michael@0 784 if (CheckFramebufferStatus() != LOCAL_GL_FRAMEBUFFER_COMPLETE)
michael@0 785 return false;
michael@0 786
michael@0 787 // Cool! We've checked out ok. Just need to initialize.
michael@0 788 size_t colorAttachmentCount = mColorAttachments.Length();
michael@0 789
michael@0 790 // Check if we need to initialize anything
michael@0 791 {
michael@0 792 bool hasUninitializedAttachments = false;
michael@0 793
michael@0 794 for (size_t i = 0; i < colorAttachmentCount; i++) {
michael@0 795 if (mColorAttachments[i].HasImage())
michael@0 796 hasUninitializedAttachments |= mColorAttachments[i].HasUninitializedImageData();
michael@0 797 }
michael@0 798
michael@0 799 if (mDepthAttachment.HasImage())
michael@0 800 hasUninitializedAttachments |= mDepthAttachment.HasUninitializedImageData();
michael@0 801 if (mStencilAttachment.HasImage())
michael@0 802 hasUninitializedAttachments |= mStencilAttachment.HasUninitializedImageData();
michael@0 803 if (mDepthStencilAttachment.HasImage())
michael@0 804 hasUninitializedAttachments |= mDepthStencilAttachment.HasUninitializedImageData();
michael@0 805
michael@0 806 if (!hasUninitializedAttachments)
michael@0 807 return true;
michael@0 808 }
michael@0 809
michael@0 810 // Get buffer-bit-mask and color-attachment-mask-list
michael@0 811 uint32_t mask = 0;
michael@0 812 bool colorAttachmentsMask[WebGLContext::sMaxColorAttachments] = { false };
michael@0 813 MOZ_ASSERT(colorAttachmentCount <= WebGLContext::sMaxColorAttachments);
michael@0 814
michael@0 815 for (size_t i = 0; i < colorAttachmentCount; i++) {
michael@0 816 if (mColorAttachments[i].HasUninitializedImageData()) {
michael@0 817 colorAttachmentsMask[i] = true;
michael@0 818 mask |= LOCAL_GL_COLOR_BUFFER_BIT;
michael@0 819 }
michael@0 820 }
michael@0 821
michael@0 822 if (mDepthAttachment.HasUninitializedImageData() ||
michael@0 823 mDepthStencilAttachment.HasUninitializedImageData())
michael@0 824 {
michael@0 825 mask |= LOCAL_GL_DEPTH_BUFFER_BIT;
michael@0 826 }
michael@0 827
michael@0 828 if (mStencilAttachment.HasUninitializedImageData() ||
michael@0 829 mDepthStencilAttachment.HasUninitializedImageData())
michael@0 830 {
michael@0 831 mask |= LOCAL_GL_STENCIL_BUFFER_BIT;
michael@0 832 }
michael@0 833
michael@0 834 // Clear!
michael@0 835 mContext->ForceClearFramebufferWithDefaultValues(mask, colorAttachmentsMask);
michael@0 836
michael@0 837 // Mark all the uninitialized images as initialized.
michael@0 838 for (size_t i = 0; i < colorAttachmentCount; i++) {
michael@0 839 if (mColorAttachments[i].HasUninitializedImageData())
michael@0 840 mColorAttachments[i].SetImageDataStatus(WebGLImageDataStatus::InitializedImageData);
michael@0 841 }
michael@0 842
michael@0 843 if (mDepthAttachment.HasUninitializedImageData())
michael@0 844 mDepthAttachment.SetImageDataStatus(WebGLImageDataStatus::InitializedImageData);
michael@0 845 if (mStencilAttachment.HasUninitializedImageData())
michael@0 846 mStencilAttachment.SetImageDataStatus(WebGLImageDataStatus::InitializedImageData);
michael@0 847 if (mDepthStencilAttachment.HasUninitializedImageData())
michael@0 848 mDepthStencilAttachment.SetImageDataStatus(WebGLImageDataStatus::InitializedImageData);
michael@0 849
michael@0 850 return true;
michael@0 851 }
michael@0 852
michael@0 853 bool WebGLFramebuffer::CheckColorAttachmentNumber(GLenum attachment, const char* functionName) const
michael@0 854 {
michael@0 855 const char* const errorFormating = "%s: attachment: invalid enum value 0x%x";
michael@0 856
michael@0 857 if (mContext->IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers)) {
michael@0 858 if (attachment < LOCAL_GL_COLOR_ATTACHMENT0 ||
michael@0 859 attachment >= GLenum(LOCAL_GL_COLOR_ATTACHMENT0 + mContext->mGLMaxColorAttachments))
michael@0 860 {
michael@0 861 mContext->ErrorInvalidEnum(errorFormating, functionName, attachment);
michael@0 862 return false;
michael@0 863 }
michael@0 864 } else if (attachment != LOCAL_GL_COLOR_ATTACHMENT0) {
michael@0 865 if (attachment > LOCAL_GL_COLOR_ATTACHMENT0 &&
michael@0 866 attachment <= LOCAL_GL_COLOR_ATTACHMENT15)
michael@0 867 {
michael@0 868 mContext->ErrorInvalidEnum("%s: attachment: invalid enum value 0x%x. "
michael@0 869 "Try the WEBGL_draw_buffers extension if supported.", functionName, attachment);
michael@0 870 return false;
michael@0 871 } else {
michael@0 872 mContext->ErrorInvalidEnum(errorFormating, functionName, attachment);
michael@0 873 return false;
michael@0 874 }
michael@0 875 }
michael@0 876
michael@0 877 return true;
michael@0 878 }
michael@0 879
michael@0 880 void WebGLFramebuffer::EnsureColorAttachments(size_t colorAttachmentId)
michael@0 881 {
michael@0 882 MOZ_ASSERT(colorAttachmentId < WebGLContext::sMaxColorAttachments);
michael@0 883
michael@0 884 size_t currentAttachmentCount = mColorAttachments.Length();
michael@0 885 if (colorAttachmentId < currentAttachmentCount)
michael@0 886 return;
michael@0 887
michael@0 888 mColorAttachments.SetLength(colorAttachmentId + 1);
michael@0 889
michael@0 890 for (size_t i = colorAttachmentId; i >= currentAttachmentCount; i--) {
michael@0 891 mColorAttachments[i].mAttachmentPoint = LOCAL_GL_COLOR_ATTACHMENT0 + i;
michael@0 892 }
michael@0 893 }
michael@0 894
michael@0 895 void
michael@0 896 WebGLFramebuffer::NotifyAttachableChanged() const
michael@0 897 {
michael@0 898 // Attachment has changed, so invalidate cached status
michael@0 899 mStatus = 0;
michael@0 900 }
michael@0 901
michael@0 902 static void
michael@0 903 FinalizeDrawAndReadBuffers(GLContext* aGL, bool aColorBufferDefined)
michael@0 904 {
michael@0 905 MOZ_ASSERT(aGL, "Expected a valid GLContext ptr.");
michael@0 906 // GLES don't support DrawBuffer()/ReadBuffer.
michael@0 907 // According to http://www.opengl.org/wiki/Framebuffer_Object
michael@0 908 //
michael@0 909 // Each draw buffers must either specify color attachment points that have images
michael@0 910 // attached or must be GL_NONE​. (GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER​ when false).
michael@0 911 //
michael@0 912 // If the read buffer is set, then it must specify an attachment point that has an
michael@0 913 // image attached. (GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER​ when false).
michael@0 914 //
michael@0 915 // Note that this test is not performed if OpenGL 4.2 or ARB_ES2_compatibility is
michael@0 916 // available.
michael@0 917 if (aGL->IsGLES() ||
michael@0 918 aGL->IsSupported(GLFeature::ES2_compatibility) ||
michael@0 919 aGL->IsAtLeast(ContextProfile::OpenGL, 420))
michael@0 920 {
michael@0 921 return;
michael@0 922 }
michael@0 923
michael@0 924 // TODO(djg): Assert that fDrawBuffer/fReadBuffer is not NULL.
michael@0 925 GLenum colorBufferSource = aColorBufferDefined ? LOCAL_GL_COLOR_ATTACHMENT0 : LOCAL_GL_NONE;
michael@0 926 aGL->fDrawBuffer(colorBufferSource);
michael@0 927 aGL->fReadBuffer(colorBufferSource);
michael@0 928 }
michael@0 929
michael@0 930 void
michael@0 931 WebGLFramebuffer::FinalizeAttachments() const
michael@0 932 {
michael@0 933 GLContext* gl = mContext->gl;
michael@0 934
michael@0 935 size_t count = ColorAttachmentCount();
michael@0 936 for (size_t i = 0; i < count; i++) {
michael@0 937 ColorAttachment(i).FinalizeAttachment(gl, LOCAL_GL_COLOR_ATTACHMENT0 + i);
michael@0 938 }
michael@0 939
michael@0 940 DepthAttachment().FinalizeAttachment(gl, LOCAL_GL_DEPTH_ATTACHMENT);
michael@0 941 StencilAttachment().FinalizeAttachment(gl, LOCAL_GL_STENCIL_ATTACHMENT);
michael@0 942 DepthStencilAttachment().FinalizeAttachment(gl, LOCAL_GL_DEPTH_STENCIL_ATTACHMENT);
michael@0 943
michael@0 944 FinalizeDrawAndReadBuffers(gl, ColorAttachment(0).IsDefined());
michael@0 945 }
michael@0 946
michael@0 947 inline void
michael@0 948 ImplCycleCollectionUnlink(mozilla::WebGLFramebuffer::Attachment& aField)
michael@0 949 {
michael@0 950 aField.mTexturePtr = nullptr;
michael@0 951 aField.mRenderbufferPtr = nullptr;
michael@0 952 }
michael@0 953
michael@0 954 inline void
michael@0 955 ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
michael@0 956 mozilla::WebGLFramebuffer::Attachment& aField,
michael@0 957 const char* aName,
michael@0 958 uint32_t aFlags = 0)
michael@0 959 {
michael@0 960 CycleCollectionNoteChild(aCallback, aField.mTexturePtr.get(),
michael@0 961 aName, aFlags);
michael@0 962
michael@0 963 CycleCollectionNoteChild(aCallback, aField.mRenderbufferPtr.get(),
michael@0 964 aName, aFlags);
michael@0 965 }
michael@0 966
michael@0 967 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_4(WebGLFramebuffer,
michael@0 968 mColorAttachments,
michael@0 969 mDepthAttachment,
michael@0 970 mStencilAttachment,
michael@0 971 mDepthStencilAttachment)
michael@0 972
michael@0 973 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLFramebuffer, AddRef)
michael@0 974 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLFramebuffer, Release)

mercurial