content/canvas/src/WebGLRenderbuffer.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "WebGLContext.h"
     7 #include "WebGLRenderbuffer.h"
     8 #include "WebGLTexture.h"
     9 #include "mozilla/dom/WebGLRenderingContextBinding.h"
    10 #include "GLContext.h"
    11 #include "ScopedGLHelpers.h"
    13 using namespace mozilla;
    14 using namespace mozilla::gl;
    16 static GLenum
    17 DepthStencilDepthFormat(GLContext* gl) {
    18     // We might not be able to get 24-bit, so let's pretend!
    19     if (gl->IsGLES() && !gl->IsExtensionSupported(gl::GLContext::OES_depth24))
    20         return LOCAL_GL_DEPTH_COMPONENT16;
    22     return LOCAL_GL_DEPTH_COMPONENT24;
    23 }
    25 static bool
    26 SupportsDepthStencil(GLContext* gl) {
    27     return gl->IsExtensionSupported(GLContext::EXT_packed_depth_stencil) ||
    28            gl->IsExtensionSupported(GLContext::OES_packed_depth_stencil);
    29 }
    31 static bool
    32 NeedsDepthStencilEmu(GLContext* gl, GLenum internalFormat) {
    33     MOZ_ASSERT(internalFormat != LOCAL_GL_DEPTH_STENCIL);
    34     if (internalFormat != LOCAL_GL_DEPTH24_STENCIL8)
    35         return false;
    37     return !SupportsDepthStencil(gl);
    38 }
    40 JSObject*
    41 WebGLRenderbuffer::WrapObject(JSContext *cx) {
    42     return dom::WebGLRenderbufferBinding::Wrap(cx, this);
    43 }
    45 WebGLRenderbuffer::WebGLRenderbuffer(WebGLContext *context)
    46     : WebGLContextBoundObject(context)
    47     , mPrimaryRB(0)
    48     , mSecondaryRB(0)
    49     , mInternalFormat(0)
    50     , mInternalFormatForGL(0)
    51     , mHasEverBeenBound(false)
    52     , mImageDataStatus(WebGLImageDataStatus::NoImageData)
    53 {
    54     SetIsDOMBinding();
    55     mContext->MakeContextCurrent();
    57     mContext->gl->fGenRenderbuffers(1, &mPrimaryRB);
    58     if (!SupportsDepthStencil(mContext->gl))
    59         mContext->gl->fGenRenderbuffers(1, &mSecondaryRB);
    61     mContext->mRenderbuffers.insertBack(this);
    62 }
    64 void
    65 WebGLRenderbuffer::Delete() {
    66     mContext->MakeContextCurrent();
    68     mContext->gl->fDeleteRenderbuffers(1, &mPrimaryRB);
    69     if (mSecondaryRB)
    70         mContext->gl->fDeleteRenderbuffers(1, &mSecondaryRB);
    72     LinkedListElement<WebGLRenderbuffer>::removeFrom(mContext->mRenderbuffers);
    73 }
    75 int64_t
    76 WebGLRenderbuffer::MemoryUsage() const {
    77     int64_t pixels = int64_t(Width()) * int64_t(Height());
    79     GLenum primaryFormat = InternalFormatForGL();
    80     // If there is no defined format, we're not taking up any memory
    81     if (!primaryFormat) {
    82         return 0;
    83     }
    85     int64_t secondarySize = 0;
    86     if (mSecondaryRB) {
    87         if (NeedsDepthStencilEmu(mContext->gl, primaryFormat)) {
    88             primaryFormat = DepthStencilDepthFormat(mContext->gl);
    89             secondarySize = 1*pixels; // STENCIL_INDEX8
    90         } else {
    91             secondarySize = 1*1*2; // 1x1xRGBA4
    92         }
    93     }
    95     int64_t primarySize = 0;
    96     switch (primaryFormat) {
    97         case LOCAL_GL_STENCIL_INDEX8:
    98             primarySize = 1*pixels;
    99             break;
   100         case LOCAL_GL_RGBA4:
   101         case LOCAL_GL_RGB5_A1:
   102         case LOCAL_GL_RGB565:
   103         case LOCAL_GL_DEPTH_COMPONENT16:
   104             primarySize = 2*pixels;
   105             break;
   106         case LOCAL_GL_RGB8:
   107         case LOCAL_GL_DEPTH_COMPONENT24:
   108             primarySize = 3*pixels;
   109             break;
   110         case LOCAL_GL_RGBA8:
   111         case LOCAL_GL_SRGB8_ALPHA8_EXT:
   112         case LOCAL_GL_DEPTH24_STENCIL8:
   113         case LOCAL_GL_DEPTH_COMPONENT32:
   114             primarySize = 4*pixels;
   115             break;
   116         case LOCAL_GL_RGB16F:
   117             primarySize = 2*3*pixels;
   118             break;
   119         case LOCAL_GL_RGBA16F:
   120             primarySize = 2*4*pixels;
   121             break;
   122         case LOCAL_GL_RGB32F:
   123             primarySize = 4*3*pixels;
   124             break;
   125         case LOCAL_GL_RGBA32F:
   126             primarySize = 4*4*pixels;
   127             break;
   128         default:
   129             MOZ_ASSERT(false, "Unknown `primaryFormat`.");
   130             break;
   131     }
   133     return primarySize + secondarySize;
   134 }
   136 void
   137 WebGLRenderbuffer::BindRenderbuffer() const {
   138     /* Do this explicitly here, since the meaning changes for depth-stencil emu.
   139      * Under normal circumstances, there's only one RB: `mPrimaryRB`.
   140      * `mSecondaryRB` is used when we have to pretend that the renderbuffer is
   141      * DEPTH_STENCIL, when it's actually one DEPTH buffer `mPrimaryRB` and one
   142      * STENCIL buffer `mSecondaryRB`.
   143      *
   144      * In the DEPTH_STENCIL emulation case, we're actually juggling two RBs, but
   145      * we can only bind one of them at a time. We choose to unconditionally bind
   146      * the depth RB. When we need to ask about the stencil buffer (say, how many
   147      * stencil bits we have), we temporarily bind the stencil RB, so that it
   148      * looks like we're just asking the question of a combined DEPTH_STENCIL
   149      * buffer.
   150      */
   151     mContext->gl->fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, mPrimaryRB);
   152 }
   154 void
   155 WebGLRenderbuffer::RenderbufferStorage(GLenum internalFormat, GLsizei width, GLsizei height) const {
   156     GLContext* gl = mContext->gl;
   158     GLenum primaryFormat = internalFormat;
   159     GLenum secondaryFormat = 0;
   161     if (NeedsDepthStencilEmu(mContext->gl, primaryFormat)) {
   162         primaryFormat = DepthStencilDepthFormat(gl);
   163         secondaryFormat = LOCAL_GL_STENCIL_INDEX8;
   164     }
   166     gl->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, primaryFormat, width, height);
   168     if (!mSecondaryRB) {
   169         MOZ_ASSERT(!secondaryFormat);
   170         return;
   171     }
   172     // We can't leave the secondary RB unspecified either, since we should
   173     // handle the case where we attach a non-depth-stencil RB to a
   174     // depth-stencil attachment point, or attach this depth-stencil RB to a
   175     // non-depth-stencil attachment point.
   176     ScopedBindRenderbuffer autoRB(gl, mSecondaryRB);
   177     if (secondaryFormat) {
   178         gl->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, secondaryFormat, width, height);
   179     } else {
   180         gl->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, LOCAL_GL_RGBA4, 1, 1);
   181     }
   182 }
   184 void
   185 WebGLRenderbuffer::FramebufferRenderbuffer(GLenum attachment) const {
   186     GLContext* gl = mContext->gl;
   187     if (attachment != LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
   188         gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, attachment, LOCAL_GL_RENDERBUFFER, mPrimaryRB);
   189         return;
   190     }
   192     GLuint stencilRB = mPrimaryRB;
   193     if (NeedsDepthStencilEmu(mContext->gl, InternalFormatForGL())) {
   194         printf_stderr("DEV-ONLY: Using secondary buffer to emulate DepthStencil.\n");
   195         MOZ_ASSERT(mSecondaryRB);
   196         stencilRB = mSecondaryRB;
   197     }
   198     gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT,   LOCAL_GL_RENDERBUFFER, mPrimaryRB);
   199     gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT, LOCAL_GL_RENDERBUFFER, stencilRB);
   200 }
   202 GLint
   203 WebGLRenderbuffer::GetRenderbufferParameter(GLenum target, GLenum pname) const {
   204     GLContext* gl = mContext->gl;
   206     switch (pname) {
   207         case LOCAL_GL_RENDERBUFFER_STENCIL_SIZE: {
   208             if (NeedsDepthStencilEmu(mContext->gl, InternalFormatForGL())) {
   209                 if (gl->WorkAroundDriverBugs() &&
   210                     gl->Renderer() == GLRenderer::Tegra)
   211                 {
   212                     return 8;
   213                 }
   215                 ScopedBindRenderbuffer autoRB(gl, mSecondaryRB);
   217                 GLint i = 0;
   218                 gl->fGetRenderbufferParameteriv(target, pname, &i);
   219                 return i;
   220             }
   221             // Fall through otherwise.
   222         }
   223         case LOCAL_GL_RENDERBUFFER_WIDTH:
   224         case LOCAL_GL_RENDERBUFFER_HEIGHT:
   225         case LOCAL_GL_RENDERBUFFER_RED_SIZE:
   226         case LOCAL_GL_RENDERBUFFER_GREEN_SIZE:
   227         case LOCAL_GL_RENDERBUFFER_BLUE_SIZE:
   228         case LOCAL_GL_RENDERBUFFER_ALPHA_SIZE:
   229         case LOCAL_GL_RENDERBUFFER_DEPTH_SIZE: {
   230             GLint i = 0;
   231             gl->fGetRenderbufferParameteriv(target, pname, &i);
   232             return i;
   233         }
   234     }
   236     MOZ_ASSERT(false, "This function should only be called with valid `pname`.");
   237     return 0;
   238 }
   241 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLRenderbuffer)
   243 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLRenderbuffer, AddRef)
   244 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLRenderbuffer, Release)

mercurial