1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
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 #ifndef WEBGL_VERTEX_ARRAY_H_
7 #define WEBGL_VERTEX_ARRAY_H_
8 
9 #include <array>
10 #include <bitset>
11 #include <vector>
12 
13 #include "mozilla/IntegerRange.h"
14 
15 #include "CacheInvalidator.h"
16 #include "WebGLObjectModel.h"
17 #include "WebGLStrongTypes.h"
18 
19 namespace mozilla {
20 
21 class WebGLBuffer;
22 class WebGLVertexArrayFake;
23 
24 namespace webgl {
25 struct LinkedProgramInfo;
26 
27 struct VertAttribLayoutData final {
28   // Keep this packed tightly!
29   uint32_t divisor = 0;
30   bool isArray = false;
31   uint8_t byteSize = 0;
32   uint8_t byteStride = 0;  // at-most 255
33   webgl::AttribBaseType baseType = webgl::AttribBaseType::Float;
34   uint64_t byteOffset = 0;
35 };
36 
37 struct VertAttribBindingData final {
38   VertAttribLayoutData layout;
39   RefPtr<WebGLBuffer> buffer;
40 };
41 
42 }  // namespace webgl
43 
44 void DoVertexAttribPointer(gl::GLContext&, uint32_t index,
45                            const webgl::VertAttribPointerDesc&);
46 
47 class WebGLVertexArray : public WebGLContextBoundObject {
48   friend class ScopedDrawHelper;
49   friend class WebGLContext;
50   friend class WebGLVertexArrayFake;
51   friend class WebGL2Context;
52   friend struct webgl::LinkedProgramInfo;
53 
54   static constexpr size_t kMaxAttribs = 32;  // gpuinfo.org says so
55 
56   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(WebGLVertexArray, override)
57 
58   RefPtr<WebGLBuffer> mElementArrayBuffer;
59 
60   std::bitset<kMaxAttribs> mAttribIsArray;
61   std::array<webgl::VertAttribBindingData, kMaxAttribs> mBindings;  // Hot data.
62   std::array<webgl::VertAttribPointerDesc, kMaxAttribs>
63       mDescs;  // cold data, parallel to mBindings.
64 
65   std::bitset<kMaxAttribs> mAttribIsArrayWithNullBuffer;
66   bool mHasBeenBound = false;
67 
68  public:
69   static WebGLVertexArray* Create(WebGLContext* webgl);
70 
71  protected:
72   explicit WebGLVertexArray(WebGLContext* webgl);
73   ~WebGLVertexArray();
74 
75  public:
76   virtual void BindVertexArray() = 0;
77 
SetAttribIsArray(const uint32_t index,const bool val)78   void SetAttribIsArray(const uint32_t index, const bool val) {
79     auto& binding = mBindings[index];
80     binding.layout.isArray = val;
81     mAttribIsArrayWithNullBuffer[index] =
82         binding.layout.isArray && !binding.buffer;
83   }
84 
AttribDivisor(const uint32_t index,const uint32_t val)85   void AttribDivisor(const uint32_t index, const uint32_t val) {
86     auto& binding = mBindings[index];
87     binding.layout.divisor = val;
88   }
89 
AttribPointer(const uint32_t index,WebGLBuffer * const buffer,const webgl::VertAttribPointerDesc & desc,const webgl::VertAttribPointerCalculated & calc)90   void AttribPointer(const uint32_t index, WebGLBuffer* const buffer,
91                      const webgl::VertAttribPointerDesc& desc,
92                      const webgl::VertAttribPointerCalculated& calc) {
93     mDescs[index] = desc;
94 
95     auto& binding = mBindings[index];
96     binding.buffer = buffer;
97     binding.layout.byteSize = calc.byteSize;
98     binding.layout.byteStride = calc.byteStride;
99     binding.layout.baseType = calc.baseType;
100     binding.layout.byteOffset = desc.byteOffset;
101 
102     mAttribIsArrayWithNullBuffer[index] =
103         binding.layout.isArray && !binding.buffer;
104   }
105 
AttribBinding(const uint32_t index)106   const auto& AttribBinding(const uint32_t index) const {
107     return mBindings[index];
108   }
AttribDesc(const uint32_t index)109   const auto& AttribDesc(const uint32_t index) const { return mDescs[index]; }
110 
GetAttribIsArrayWithNullBuffer()111   Maybe<uint32_t> GetAttribIsArrayWithNullBuffer() const {
112     const auto& bitset = mAttribIsArrayWithNullBuffer;
113     if (MOZ_LIKELY(bitset.none())) return {};
114     for (const auto i : IntegerRange(bitset.size())) {
115       if (bitset[i]) return Some(i);
116     }
117     MOZ_CRASH();
118   }
119 
120   Maybe<double> GetVertexAttrib(uint32_t index, GLenum pname) const;
121 };
122 
123 }  // namespace mozilla
124 
125 #endif  // WEBGL_VERTEX_ARRAY_H_
126