LCOV - code coverage report
Current view: top level - dom/canvas - WebGLContextBuffers.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 233 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 18 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; 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/. */
       5             : 
       6             : #include "WebGLContext.h"
       7             : 
       8             : #include "GLContext.h"
       9             : #include "WebGLBuffer.h"
      10             : #include "WebGLTransformFeedback.h"
      11             : #include "WebGLVertexArray.h"
      12             : 
      13             : namespace mozilla {
      14             : 
      15             : WebGLRefPtr<WebGLBuffer>*
      16           0 : WebGLContext::ValidateBufferSlot(const char* funcName, GLenum target)
      17             : {
      18           0 :     WebGLRefPtr<WebGLBuffer>* slot = nullptr;
      19             : 
      20           0 :     switch (target) {
      21             :     case LOCAL_GL_ARRAY_BUFFER:
      22           0 :         slot = &mBoundArrayBuffer;
      23           0 :         break;
      24             : 
      25             :     case LOCAL_GL_ELEMENT_ARRAY_BUFFER:
      26           0 :         slot = &(mBoundVertexArray->mElementArrayBuffer);
      27           0 :         break;
      28             :     }
      29             : 
      30           0 :     if (IsWebGL2()) {
      31           0 :         switch (target) {
      32             :         case LOCAL_GL_COPY_READ_BUFFER:
      33           0 :             slot = &mBoundCopyReadBuffer;
      34           0 :             break;
      35             : 
      36             :         case LOCAL_GL_COPY_WRITE_BUFFER:
      37           0 :             slot = &mBoundCopyWriteBuffer;
      38           0 :             break;
      39             : 
      40             :         case LOCAL_GL_PIXEL_PACK_BUFFER:
      41           0 :             slot = &mBoundPixelPackBuffer;
      42           0 :             break;
      43             : 
      44             :         case LOCAL_GL_PIXEL_UNPACK_BUFFER:
      45           0 :             slot = &mBoundPixelUnpackBuffer;
      46           0 :             break;
      47             : 
      48             :         case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER:
      49           0 :             slot = &(mBoundTransformFeedback->mGenericBufferBinding);
      50           0 :             break;
      51             : 
      52             :         case LOCAL_GL_UNIFORM_BUFFER:
      53           0 :             slot = &mBoundUniformBuffer;
      54           0 :             break;
      55             :         }
      56             :     }
      57             : 
      58           0 :     if (!slot) {
      59           0 :         ErrorInvalidEnum("%s: Bad `target`: 0x%04x", funcName, target);
      60           0 :         return nullptr;
      61             :     }
      62             : 
      63           0 :     return slot;
      64             : }
      65             : 
      66             : WebGLBuffer*
      67           0 : WebGLContext::ValidateBufferSelection(const char* funcName, GLenum target)
      68             : {
      69           0 :     const auto& slot = ValidateBufferSlot(funcName, target);
      70           0 :     if (!slot)
      71           0 :         return nullptr;
      72           0 :     const auto& buffer = *slot;
      73             : 
      74           0 :     if (!buffer) {
      75           0 :         ErrorInvalidOperation("%s: Buffer for `target` is null.", funcName);
      76           0 :         return nullptr;
      77             :     }
      78             : 
      79           0 :     if (target == LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER) {
      80           0 :         if (mBoundTransformFeedback->IsActiveAndNotPaused()) {
      81             :             ErrorInvalidOperation("%s: Cannot select TRANSFORM_FEEDBACK_BUFFER when"
      82             :                                   " transform feedback is active and unpaused.",
      83           0 :                                   funcName);
      84           0 :             return nullptr;
      85             :         }
      86           0 :         if (buffer->IsBoundForNonTF()) {
      87             :             ErrorInvalidOperation("%s: Specified WebGLBuffer is currently bound for"
      88             :                                   " non-transform-feedback.",
      89           0 :                                   funcName);
      90           0 :             return nullptr;
      91             :         }
      92             :     } else {
      93           0 :         if (buffer->IsBoundForTF()) {
      94             :             ErrorInvalidOperation("%s: Specified WebGLBuffer is currently bound for"
      95             :                                   " transform feedback.",
      96           0 :                                   funcName);
      97           0 :             return nullptr;
      98             :         }
      99             :     }
     100             : 
     101           0 :     return buffer.get();
     102             : }
     103             : 
     104             : IndexedBufferBinding*
     105           0 : WebGLContext::ValidateIndexedBufferSlot(const char* funcName, GLenum target, GLuint index)
     106             : {
     107             :     decltype(mIndexedUniformBufferBindings)* bindings;
     108             :     const char* maxIndexEnum;
     109           0 :     switch (target) {
     110             :     case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER:
     111           0 :         bindings = &(mBoundTransformFeedback->mIndexedBindings);
     112           0 :         maxIndexEnum = "MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS";
     113           0 :         break;
     114             : 
     115             :     case LOCAL_GL_UNIFORM_BUFFER:
     116           0 :         bindings = &mIndexedUniformBufferBindings;
     117           0 :         maxIndexEnum = "MAX_UNIFORM_BUFFER_BINDINGS";
     118           0 :         break;
     119             : 
     120             :     default:
     121           0 :         ErrorInvalidEnum("%s: Bad `target`: 0x%04x", funcName, target);
     122           0 :         return nullptr;
     123             :     }
     124             : 
     125           0 :     if (index >= bindings->size()) {
     126           0 :         ErrorInvalidValue("%s: `index` >= %s.", funcName, maxIndexEnum);
     127           0 :         return nullptr;
     128             :     }
     129             : 
     130           0 :     return &(*bindings)[index];
     131             : }
     132             : 
     133             : ////////////////////////////////////////
     134             : 
     135             : void
     136           0 : WebGLContext::BindBuffer(GLenum target, WebGLBuffer* buffer)
     137             : {
     138           0 :     const char funcName[] = "bindBuffer";
     139           0 :     if (IsContextLost())
     140           0 :         return;
     141             : 
     142           0 :     if (buffer && !ValidateObject(funcName, *buffer))
     143           0 :         return;
     144             : 
     145           0 :     const auto& slot = ValidateBufferSlot(funcName, target);
     146           0 :     if (!slot)
     147           0 :         return;
     148             : 
     149           0 :     if (buffer && !buffer->ValidateCanBindToTarget(funcName, target))
     150           0 :         return;
     151             : 
     152           0 :     gl->MakeCurrent();
     153           0 :     gl->fBindBuffer(target, buffer ? buffer->mGLName : 0);
     154             : 
     155           0 :     WebGLBuffer::SetSlot(target, buffer, slot);
     156           0 :     if (buffer) {
     157           0 :         buffer->SetContentAfterBind(target);
     158             :     }
     159             : 
     160           0 :     switch (target) {
     161             :     case LOCAL_GL_PIXEL_PACK_BUFFER:
     162             :     case LOCAL_GL_PIXEL_UNPACK_BUFFER:
     163           0 :         gl->fBindBuffer(target, 0);
     164           0 :         break;
     165             :     }
     166             : }
     167             : 
     168             : ////////////////////////////////////////
     169             : 
     170             : bool
     171           0 : WebGLContext::ValidateIndexedBufferBinding(const char* funcName, GLenum target,
     172             :                                            GLuint index,
     173             :                                            WebGLRefPtr<WebGLBuffer>** const out_genericBinding,
     174             :                                            IndexedBufferBinding** const out_indexedBinding)
     175             : {
     176           0 :     *out_genericBinding = ValidateBufferSlot(funcName, target);
     177           0 :     if (!*out_genericBinding)
     178           0 :         return false;
     179             : 
     180           0 :     *out_indexedBinding = ValidateIndexedBufferSlot(funcName, target, index);
     181           0 :     if (!*out_indexedBinding)
     182           0 :         return false;
     183             : 
     184           0 :     if (target == LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER &&
     185           0 :         mBoundTransformFeedback->mIsActive)
     186             :     {
     187             :         ErrorInvalidOperation("%s: Cannot update indexed buffer bindings on active"
     188             :                               " transform feedback objects.",
     189           0 :                               funcName);
     190           0 :         return false;
     191             :     }
     192             : 
     193           0 :     return true;
     194             : }
     195             : 
     196             : void
     197           0 : WebGLContext::BindBufferBase(GLenum target, GLuint index, WebGLBuffer* buffer)
     198             : {
     199           0 :     const char funcName[] = "bindBufferBase";
     200           0 :     if (IsContextLost())
     201           0 :         return;
     202             : 
     203           0 :     if (buffer && !ValidateObject(funcName, *buffer))
     204           0 :         return;
     205             : 
     206             :     WebGLRefPtr<WebGLBuffer>* genericBinding;
     207             :     IndexedBufferBinding* indexedBinding;
     208           0 :     if (!ValidateIndexedBufferBinding(funcName, target, index, &genericBinding,
     209             :                                       &indexedBinding))
     210             :     {
     211           0 :         return;
     212             :     }
     213             : 
     214           0 :     if (buffer && !buffer->ValidateCanBindToTarget(funcName, target))
     215           0 :         return;
     216             : 
     217             :     ////
     218             : 
     219           0 :     gl->MakeCurrent();
     220           0 :     gl->fBindBufferBase(target, index, buffer ? buffer->mGLName : 0);
     221             : 
     222             :     ////
     223             : 
     224           0 :     WebGLBuffer::SetSlot(target, buffer, genericBinding);
     225           0 :     WebGLBuffer::SetSlot(target, buffer, &indexedBinding->mBufferBinding);
     226           0 :     indexedBinding->mRangeStart = 0;
     227           0 :     indexedBinding->mRangeSize = 0;
     228             : 
     229           0 :     if (buffer) {
     230           0 :         buffer->SetContentAfterBind(target);
     231             :     }
     232             : }
     233             : 
     234             : void
     235           0 : WebGLContext::BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buffer,
     236             :                               WebGLintptr offset, WebGLsizeiptr size)
     237             : {
     238           0 :     const char funcName[] = "bindBufferRange";
     239           0 :     if (IsContextLost())
     240           0 :         return;
     241             : 
     242           0 :     if (buffer && !ValidateObject(funcName, *buffer))
     243           0 :         return;
     244             : 
     245           0 :     if (!ValidateNonNegative(funcName, "offset", offset) ||
     246           0 :         !ValidateNonNegative(funcName, "size", size))
     247             :     {
     248           0 :         return;
     249             :     }
     250             : 
     251             :     WebGLRefPtr<WebGLBuffer>* genericBinding;
     252             :     IndexedBufferBinding* indexedBinding;
     253           0 :     if (!ValidateIndexedBufferBinding(funcName, target, index, &genericBinding,
     254             :                                       &indexedBinding))
     255             :     {
     256           0 :         return;
     257             :     }
     258             : 
     259           0 :     if (buffer && !buffer->ValidateCanBindToTarget(funcName, target))
     260           0 :         return;
     261             : 
     262           0 :     if (buffer && !size) {
     263           0 :         ErrorInvalidValue("%s: size must be non-zero for non-null buffer.", funcName);
     264           0 :         return;
     265             :     }
     266             : 
     267             :     ////
     268             : 
     269           0 :     gl->MakeCurrent();
     270             : 
     271           0 :     switch (target) {
     272             :     case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER:
     273           0 :         if (offset % 4 != 0 || size % 4 != 0) {
     274             :             ErrorInvalidValue("%s: For %s, `offset` and `size` must be multiples of 4.",
     275           0 :                               funcName, "TRANSFORM_FEEDBACK_BUFFER");
     276           0 :             return;
     277             :         }
     278           0 :         break;
     279             : 
     280             :     case LOCAL_GL_UNIFORM_BUFFER:
     281             :         {
     282           0 :             GLuint offsetAlignment = 0;
     283           0 :             gl->GetUIntegerv(LOCAL_GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &offsetAlignment);
     284           0 :             if (offset % offsetAlignment != 0) {
     285             :                 ErrorInvalidValue("%s: For %s, `offset` must be a multiple of %s.",
     286             :                                   funcName, "UNIFORM_BUFFER",
     287           0 :                                   "UNIFORM_BUFFER_OFFSET_ALIGNMENT");
     288           0 :                 return;
     289             :             }
     290             :         }
     291           0 :         break;
     292             :     }
     293             : 
     294             :     ////
     295             : 
     296             : #ifdef XP_MACOSX
     297             :     if (buffer && buffer->Content() == WebGLBuffer::Kind::Undefined &&
     298             :         gl->WorkAroundDriverBugs())
     299             :     {
     300             :         // BindBufferRange will fail if the buffer's contents is undefined.
     301             :         // Bind so driver initializes the buffer.
     302             :         gl->fBindBuffer(target, buffer->mGLName);
     303             :     }
     304             : #endif
     305             : 
     306           0 :     gl->fBindBufferRange(target, index, buffer ? buffer->mGLName : 0, offset, size);
     307             : 
     308             :     ////
     309             : 
     310           0 :     WebGLBuffer::SetSlot(target, buffer, genericBinding);
     311           0 :     WebGLBuffer::SetSlot(target, buffer, &indexedBinding->mBufferBinding);
     312           0 :     indexedBinding->mRangeStart = offset;
     313           0 :     indexedBinding->mRangeSize = size;
     314             : 
     315           0 :     if (buffer) {
     316           0 :         buffer->SetContentAfterBind(target);
     317             :     }
     318             : }
     319             : 
     320             : ////////////////////////////////////////
     321             : 
     322             : void
     323           0 : WebGLContext::BufferDataImpl(GLenum target, size_t dataLen, const uint8_t* data,
     324             :                              GLenum usage)
     325             : {
     326           0 :     const char funcName[] = "bufferData";
     327             : 
     328           0 :     const auto& buffer = ValidateBufferSelection(funcName, target);
     329           0 :     if (!buffer)
     330           0 :         return;
     331             : 
     332           0 :     buffer->BufferData(target, dataLen, data, usage);
     333             : }
     334             : 
     335             : ////
     336             : 
     337             : void
     338           0 : WebGLContext::BufferData(GLenum target, WebGLsizeiptr size, GLenum usage)
     339             : {
     340           0 :     const char funcName[] = "bufferData";
     341           0 :     if (IsContextLost())
     342           0 :         return;
     343             : 
     344           0 :     if (!ValidateNonNegative(funcName, "size", size))
     345           0 :         return;
     346             : 
     347             :     ////
     348             : 
     349           0 :     const UniqueBuffer zeroBuffer(calloc(size, 1));
     350           0 :     if (!zeroBuffer)
     351           0 :         return ErrorOutOfMemory("%s: Failed to allocate zeros.", funcName);
     352             : 
     353           0 :     BufferDataImpl(target, size_t(size), (const uint8_t*)zeroBuffer.get(), usage);
     354             : }
     355             : 
     356             : void
     357           0 : WebGLContext::BufferData(GLenum target, const dom::Nullable<dom::ArrayBuffer>& maybeSrc,
     358             :                          GLenum usage)
     359             : {
     360           0 :     if (IsContextLost())
     361           0 :         return;
     362             : 
     363           0 :     if (!ValidateNonNull("bufferData", maybeSrc))
     364           0 :         return;
     365           0 :     const auto& src = maybeSrc.Value();
     366             : 
     367           0 :     src.ComputeLengthAndData();
     368           0 :     BufferDataImpl(target, src.LengthAllowShared(), src.DataAllowShared(), usage);
     369             : }
     370             : 
     371             : void
     372           0 : WebGLContext::BufferData(GLenum target, const dom::ArrayBufferView& src, GLenum usage,
     373             :                          GLuint srcElemOffset, GLuint srcElemCountOverride)
     374             : {
     375           0 :     const char funcName[] = "bufferData";
     376           0 :     if (IsContextLost())
     377           0 :         return;
     378             : 
     379             :     uint8_t* bytes;
     380             :     size_t byteLen;
     381           0 :     if (!ValidateArrayBufferView(funcName, src, srcElemOffset, srcElemCountOverride,
     382             :                                  &bytes, &byteLen))
     383             :     {
     384           0 :         return;
     385             :     }
     386             : 
     387           0 :     BufferDataImpl(target, byteLen, bytes, usage);
     388             : }
     389             : 
     390             : ////////////////////////////////////////
     391             : 
     392             : void
     393           0 : WebGLContext::BufferSubDataImpl(GLenum target, WebGLsizeiptr dstByteOffset,
     394             :                                 size_t dataLen, const uint8_t* data)
     395             : {
     396           0 :     const char funcName[] = "bufferSubData";
     397             : 
     398           0 :     if (!ValidateNonNegative(funcName, "byteOffset", dstByteOffset))
     399           0 :         return;
     400             : 
     401           0 :     const auto& buffer = ValidateBufferSelection(funcName, target);
     402           0 :     if (!buffer)
     403           0 :         return;
     404             : 
     405           0 :     buffer->BufferSubData(target, size_t(dstByteOffset), dataLen, data);
     406             : }
     407             : 
     408             : ////
     409             : 
     410             : void
     411           0 : WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr dstByteOffset,
     412             :                             const dom::ArrayBuffer& src)
     413             : {
     414           0 :     if (IsContextLost())
     415           0 :         return;
     416             : 
     417           0 :     src.ComputeLengthAndData();
     418           0 :     BufferSubDataImpl(target, dstByteOffset, src.LengthAllowShared(),
     419           0 :                       src.DataAllowShared());
     420             : }
     421             : 
     422             : void
     423           0 : WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr dstByteOffset,
     424             :                             const dom::ArrayBufferView& src, GLuint srcElemOffset,
     425             :                             GLuint srcElemCountOverride)
     426             : {
     427           0 :     const char funcName[] = "bufferSubData";
     428           0 :     if (IsContextLost())
     429           0 :         return;
     430             : 
     431             :     uint8_t* bytes;
     432             :     size_t byteLen;
     433           0 :     if (!ValidateArrayBufferView(funcName, src, srcElemOffset, srcElemCountOverride,
     434             :                                  &bytes, &byteLen))
     435             :     {
     436           0 :         return;
     437             :     }
     438             : 
     439           0 :     BufferSubDataImpl(target, dstByteOffset, byteLen, bytes);
     440             : }
     441             : 
     442             : ////////////////////////////////////////
     443             : 
     444             : already_AddRefed<WebGLBuffer>
     445           0 : WebGLContext::CreateBuffer()
     446             : {
     447           0 :     if (IsContextLost())
     448           0 :         return nullptr;
     449             : 
     450           0 :     GLuint buf = 0;
     451           0 :     MakeContextCurrent();
     452           0 :     gl->fGenBuffers(1, &buf);
     453             : 
     454           0 :     RefPtr<WebGLBuffer> globj = new WebGLBuffer(this, buf);
     455           0 :     return globj.forget();
     456             : }
     457             : 
     458             : void
     459           0 : WebGLContext::DeleteBuffer(WebGLBuffer* buffer)
     460             : {
     461           0 :     if (!ValidateDeleteObject("deleteBuffer", buffer))
     462           0 :         return;
     463             : 
     464             :     ////
     465             : 
     466           0 :     const auto fnClearIfBuffer = [&](GLenum target, WebGLRefPtr<WebGLBuffer>& bindPoint) {
     467           0 :         if (bindPoint == buffer) {
     468           0 :             WebGLBuffer::SetSlot(target, nullptr, &bindPoint);
     469             :         }
     470           0 :     };
     471             : 
     472           0 :     fnClearIfBuffer(0, mBoundArrayBuffer);
     473           0 :     fnClearIfBuffer(0, mBoundVertexArray->mElementArrayBuffer);
     474             : 
     475           0 :     for (auto& cur : mBoundVertexArray->mAttribs) {
     476           0 :         fnClearIfBuffer(0, cur.mBuf);
     477             :     }
     478             : 
     479             :     // WebGL binding points
     480           0 :     if (IsWebGL2()) {
     481           0 :         fnClearIfBuffer(0, mBoundCopyReadBuffer);
     482           0 :         fnClearIfBuffer(0, mBoundCopyWriteBuffer);
     483           0 :         fnClearIfBuffer(0, mBoundPixelPackBuffer);
     484           0 :         fnClearIfBuffer(0, mBoundPixelUnpackBuffer);
     485           0 :         fnClearIfBuffer(0, mBoundUniformBuffer);
     486           0 :         fnClearIfBuffer(LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER,
     487           0 :                         mBoundTransformFeedback->mGenericBufferBinding);
     488             : 
     489           0 :         if (!mBoundTransformFeedback->mIsActive) {
     490           0 :             for (auto& binding : mBoundTransformFeedback->mIndexedBindings) {
     491           0 :                 fnClearIfBuffer(LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER,
     492           0 :                                 binding.mBufferBinding);
     493             :             }
     494             :         }
     495             : 
     496           0 :         for (auto& binding : mIndexedUniformBufferBindings) {
     497           0 :             fnClearIfBuffer(0, binding.mBufferBinding);
     498             :         }
     499             :     }
     500             : 
     501             :     ////
     502             : 
     503           0 :     buffer->RequestDelete();
     504             : }
     505             : 
     506             : bool
     507           0 : WebGLContext::IsBuffer(WebGLBuffer* buffer)
     508             : {
     509           0 :     if (!ValidateIsObject("isBuffer", buffer))
     510           0 :         return false;
     511             : 
     512           0 :     MakeContextCurrent();
     513           0 :     return gl->fIsBuffer(buffer->mGLName);
     514             : }
     515             : 
     516             : } // namespace mozilla

Generated by: LCOV version 1.13