1 /* -*- Mode: C++; tab-width: 20; 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 #include "WebGL2Context.h"
7 
8 #include "mozilla/StaticPrefs_webgl.h"
9 #include "GLContext.h"
10 #include "mozilla/dom/WebGL2RenderingContextBinding.h"
11 #include "mozilla/ArrayUtils.h"
12 #include "mozilla/Telemetry.h"
13 #include "nsPrintfCString.h"
14 #include "WebGLBuffer.h"
15 #include "WebGLFormats.h"
16 #include "WebGLTransformFeedback.h"
17 
18 namespace mozilla {
19 
CreateFormatUsage(gl::GLContext * gl) const20 UniquePtr<webgl::FormatUsageAuthority> WebGL2Context::CreateFormatUsage(
21     gl::GLContext* gl) const {
22   return webgl::FormatUsageAuthority::CreateForWebGL2(gl);
23 }
24 
25 ////////////////////////////////////////////////////////////////////////////////
26 // WebGL 2 initialisation
27 
28 static const gl::GLFeature kRequiredFeatures[] = {
29     gl::GLFeature::blend_minmax,
30     gl::GLFeature::clear_buffers,
31     gl::GLFeature::copy_buffer,
32     gl::GLFeature::depth_texture,
33     gl::GLFeature::draw_instanced,
34     gl::GLFeature::element_index_uint,
35     gl::GLFeature::frag_color_float,
36     gl::GLFeature::frag_depth,
37     gl::GLFeature::framebuffer_object,
38     gl::GLFeature::get_integer_indexed,
39     gl::GLFeature::get_integer64_indexed,
40     gl::GLFeature::gpu_shader4,
41     gl::GLFeature::instanced_arrays,
42     gl::GLFeature::instanced_non_arrays,
43     gl::GLFeature::map_buffer_range,  // Used by GetBufferSubData.
44     gl::GLFeature::occlusion_query2,
45     gl::GLFeature::packed_depth_stencil,
46     gl::GLFeature::query_objects,
47     gl::GLFeature::sRGB,
48     gl::GLFeature::sampler_objects,
49     gl::GLFeature::standard_derivatives,
50     gl::GLFeature::texture_3D,
51     gl::GLFeature::texture_3D_compressed,
52     gl::GLFeature::texture_3D_copy,
53     gl::GLFeature::texture_float,
54     gl::GLFeature::texture_half_float,
55     gl::GLFeature::texture_half_float_linear,
56     gl::GLFeature::texture_non_power_of_two,
57     gl::GLFeature::texture_storage,
58     gl::GLFeature::transform_feedback2,
59     gl::GLFeature::uniform_buffer_object,
60     gl::GLFeature::uniform_matrix_nonsquare,
61     gl::GLFeature::vertex_array_object};
62 
InitWebGL2(FailureReason * const out_failReason)63 bool WebGLContext::InitWebGL2(FailureReason* const out_failReason) {
64   MOZ_ASSERT(IsWebGL2(), "WebGLContext is not a WebGL 2 context!");
65 
66   std::vector<gl::GLFeature> missingList;
67 
68   const auto fnGatherMissing = [&](gl::GLFeature cur) {
69     if (!gl->IsSupported(cur)) {
70       missingList.push_back(cur);
71     }
72   };
73 
74   const auto fnGatherMissing2 = [&](gl::GLFeature main, gl::GLFeature alt) {
75     if (!gl->IsSupported(main) && !gl->IsSupported(alt)) {
76       missingList.push_back(main);
77     }
78   };
79 
80   ////
81 
82   for (const auto& cur : kRequiredFeatures) {
83     fnGatherMissing(cur);
84   }
85 
86   // On desktop, we fake occlusion_query_boolean with occlusion_query if
87   // necessary. (See WebGL2ContextQueries.cpp)
88   fnGatherMissing2(gl::GLFeature::occlusion_query_boolean,
89                    gl::GLFeature::occlusion_query);
90 
91 #ifdef XP_MACOSX
92   // On OSX, GL core profile is used. This requires texture swizzle
93   // support to emulate legacy texture formats: ALPHA, LUMINANCE,
94   // and LUMINANCE_ALPHA.
95   fnGatherMissing(gl::GLFeature::texture_swizzle);
96 #endif
97 
98   fnGatherMissing2(gl::GLFeature::prim_restart_fixed,
99                    gl::GLFeature::prim_restart);
100 
101   ////
102 
103   if (!missingList.empty()) {
104     nsAutoCString exts;
105     for (auto itr = missingList.begin(); itr != missingList.end(); ++itr) {
106       exts.AppendLiteral("\n  ");
107       exts.Append(gl::GLContext::GetFeatureName(*itr));
108     }
109 
110     const nsPrintfCString reason(
111         "WebGL 2 requires support for the following"
112         " features: %s",
113         exts.BeginReading());
114     *out_failReason = FailureReason("FEATURE_FAILURE_WEBGL2_OCCL", reason);
115     return false;
116   }
117 
118   mGLMinProgramTexelOffset =
119       gl->GetIntAs<uint32_t>(LOCAL_GL_MIN_PROGRAM_TEXEL_OFFSET);
120   mGLMaxProgramTexelOffset =
121       gl->GetIntAs<uint32_t>(LOCAL_GL_MAX_PROGRAM_TEXEL_OFFSET);
122 
123   mIndexedUniformBufferBindings.resize(mLimits->maxUniformBufferBindings);
124 
125   mDefaultTransformFeedback = new WebGLTransformFeedback(this, 0);
126   mBoundTransformFeedback = mDefaultTransformFeedback;
127 
128   gl->fGenTransformFeedbacks(1, &mEmptyTFO);
129 
130   ////
131 
132   if (!gl->IsGLES()) {
133     // Desktop OpenGL requires the following to be enabled in order to
134     // support sRGB operations on framebuffers.
135     gl->fEnable(LOCAL_GL_FRAMEBUFFER_SRGB_EXT);
136   }
137 
138   if (gl->IsSupported(gl::GLFeature::prim_restart_fixed)) {
139     gl->fEnable(LOCAL_GL_PRIMITIVE_RESTART_FIXED_INDEX);
140   } else {
141     MOZ_ASSERT(gl->IsSupported(gl::GLFeature::prim_restart));
142   }
143 
144   //////
145 
146   return true;
147 }
148 
149 // -
150 
151 /*virtual*/
IsTexParamValid(GLenum pname) const152 bool WebGL2Context::IsTexParamValid(GLenum pname) const {
153   switch (pname) {
154     case LOCAL_GL_TEXTURE_BASE_LEVEL:
155     case LOCAL_GL_TEXTURE_COMPARE_FUNC:
156     case LOCAL_GL_TEXTURE_COMPARE_MODE:
157     case LOCAL_GL_TEXTURE_IMMUTABLE_FORMAT:
158     case LOCAL_GL_TEXTURE_IMMUTABLE_LEVELS:
159     case LOCAL_GL_TEXTURE_MAX_LEVEL:
160     case LOCAL_GL_TEXTURE_WRAP_R:
161     case LOCAL_GL_TEXTURE_MAX_LOD:
162     case LOCAL_GL_TEXTURE_MIN_LOD:
163       return true;
164 
165     default:
166       return WebGLContext::IsTexParamValid(pname);
167   }
168 }
169 
170 }  // namespace mozilla
171