1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437
|
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/351564777): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif
// This file contains the ContextState class.
#ifndef GPU_COMMAND_BUFFER_SERVICE_CONTEXT_STATE_H_
#define GPU_COMMAND_BUFFER_SERVICE_CONTEXT_STATE_H_
#include <array>
#include <memory>
#include <vector>
#include "base/check_op.h"
#include "base/memory/raw_ptr.h"
#include "base/notreached.h"
#include "gpu/command_buffer/service/gl_utils.h"
#include "gpu/command_buffer/service/sampler_manager.h"
#include "gpu/command_buffer/service/shader_manager.h"
#include "gpu/command_buffer/service/texture_manager.h"
#include "gpu/command_buffer/service/vertex_array_manager.h"
#include "gpu/command_buffer/service/vertex_attrib_manager.h"
#include "gpu/gpu_gles2_export.h"
namespace gpu {
namespace gles2 {
class Buffer;
class FeatureInfo;
class IndexedBufferBindingHost;
class Program;
class Renderbuffer;
class TransformFeedback;
// State associated with each texture unit.
struct GPU_GLES2_EXPORT TextureUnit {
TextureUnit();
TextureUnit(const TextureUnit& other);
~TextureUnit();
// The last target that was bound to this texture unit.
GLenum bind_target;
// texture currently bound to this unit's GL_TEXTURE_2D with glBindTexture
scoped_refptr<TextureRef> bound_texture_2d;
// texture currently bound to this unit's GL_TEXTURE_CUBE_MAP with
// glBindTexture
scoped_refptr<TextureRef> bound_texture_cube_map;
// texture currently bound to this unit's GL_TEXTURE_EXTERNAL_OES with
// glBindTexture
scoped_refptr<TextureRef> bound_texture_external_oes;
// texture currently bound to this unit's GL_TEXTURE_RECTANGLE_ANGLE with
// glBindTexture
scoped_refptr<TextureRef> bound_texture_rectangle_arb;
// texture currently bound to this unit's GL_TEXTURE_3D with glBindTexture
scoped_refptr<TextureRef> bound_texture_3d;
// texture currently bound to this unit's GL_TEXTURE_2D_ARRAY with
// glBindTexture
scoped_refptr<TextureRef> bound_texture_2d_array;
bool AnyTargetBound() const {
return bound_texture_2d || bound_texture_cube_map ||
bound_texture_external_oes || bound_texture_rectangle_arb ||
bound_texture_3d || bound_texture_2d_array;
}
TextureRef* GetInfoForSamplerType(GLenum type) {
switch (type) {
case GL_SAMPLER_2D:
case GL_SAMPLER_2D_SHADOW:
case GL_INT_SAMPLER_2D:
case GL_UNSIGNED_INT_SAMPLER_2D:
return bound_texture_2d.get();
case GL_SAMPLER_CUBE:
case GL_SAMPLER_CUBE_SHADOW:
case GL_INT_SAMPLER_CUBE:
case GL_UNSIGNED_INT_SAMPLER_CUBE:
return bound_texture_cube_map.get();
case GL_SAMPLER_EXTERNAL_OES:
return bound_texture_external_oes.get();
case GL_SAMPLER_2D_RECT_ANGLE:
return bound_texture_rectangle_arb.get();
case GL_SAMPLER_3D:
case GL_INT_SAMPLER_3D:
case GL_UNSIGNED_INT_SAMPLER_3D:
return bound_texture_3d.get();
case GL_SAMPLER_2D_ARRAY:
case GL_SAMPLER_2D_ARRAY_SHADOW:
case GL_INT_SAMPLER_2D_ARRAY:
case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
return bound_texture_2d_array.get();
default:
NOTREACHED();
}
}
TextureRef* GetInfoForTarget(GLenum target) {
switch (target) {
case GL_TEXTURE_2D:
return bound_texture_2d.get();
case GL_TEXTURE_CUBE_MAP:
return bound_texture_cube_map.get();
case GL_TEXTURE_EXTERNAL_OES:
return bound_texture_external_oes.get();
case GL_TEXTURE_RECTANGLE_ANGLE:
return bound_texture_rectangle_arb.get();
case GL_TEXTURE_3D:
return bound_texture_3d.get();
case GL_TEXTURE_2D_ARRAY:
return bound_texture_2d_array.get();
default:
NOTREACHED();
}
}
void SetInfoForTarget(GLenum target, TextureRef* texture_ref) {
switch (target) {
case GL_TEXTURE_2D:
bound_texture_2d = texture_ref;
break;
case GL_TEXTURE_CUBE_MAP:
bound_texture_cube_map = texture_ref;
break;
case GL_TEXTURE_EXTERNAL_OES:
bound_texture_external_oes = texture_ref;
break;
case GL_TEXTURE_RECTANGLE_ANGLE:
bound_texture_rectangle_arb = texture_ref;
break;
case GL_TEXTURE_3D:
bound_texture_3d = texture_ref;
break;
case GL_TEXTURE_2D_ARRAY:
bound_texture_2d_array = texture_ref;
break;
default:
NOTREACHED();
}
}
};
class GPU_GLES2_EXPORT Vec4 {
public:
Vec4() {
v_[0].float_value = 0.0f;
v_[1].float_value = 0.0f;
v_[2].float_value = 0.0f;
v_[3].float_value = 1.0f;
type_ = SHADER_VARIABLE_FLOAT;
}
template <typename T>
void GetValues(T* values) const;
template <typename T>
void SetValues(const T* values);
ShaderVariableBaseType type() const { return type_; }
bool Equal(const Vec4& other) const;
private:
union ValueUnion {
GLfloat float_value;
GLint int_value;
GLuint uint_value;
};
std::array<ValueUnion, 4> v_;
ShaderVariableBaseType type_;
};
template <>
GPU_GLES2_EXPORT void Vec4::GetValues<GLfloat>(GLfloat* values) const;
template <>
GPU_GLES2_EXPORT void Vec4::GetValues<GLint>(GLint* values) const;
template <>
GPU_GLES2_EXPORT void Vec4::GetValues<GLuint>(GLuint* values) const;
template <>
GPU_GLES2_EXPORT void Vec4::SetValues<GLfloat>(const GLfloat* values);
template <>
GPU_GLES2_EXPORT void Vec4::SetValues<GLint>(const GLint* values);
template <>
GPU_GLES2_EXPORT void Vec4::SetValues<GLuint>(const GLuint* values);
struct GPU_GLES2_EXPORT ContextState {
enum Dimension { k2D, k3D };
ContextState(FeatureInfo* feature_info,
bool track_texture_and_sampler_units = true);
~ContextState();
void set_api(gl::GLApi* api) { api_ = api; }
gl::GLApi* api() const { return api_; }
void Initialize();
void MarkContextLost() { context_lost_ = true; }
void SetLineWidthBounds(GLfloat min, GLfloat max);
void SetIgnoreCachedStateForTest(bool ignore) {
ignore_cached_state = ignore;
}
void RestoreState(const ContextState* prev_state);
void InitCapabilities(const ContextState* prev_state) const;
void InitState(const ContextState* prev_state) const;
void RestoreActiveTexture() const;
void RestoreAllTextureUnitAndSamplerBindings(
const ContextState* prev_state) const;
void RestoreActiveTextureUnitBinding(unsigned int target) const;
void RestoreVertexAttribValues() const;
void RestoreVertexAttribArrays(
const scoped_refptr<VertexAttribManager> attrib_manager) const;
void RestoreVertexAttribs(const ContextState* prev_state) const;
void RestoreBufferBindings() const;
void RestoreGlobalState(const ContextState* prev_state) const;
void RestoreProgramSettings(const ContextState* prev_state,
bool restore_transform_feedback_bindings) const;
void RestoreRenderbufferBindings();
void RestoreIndexedUniformBufferBindings(const ContextState* prev_state);
void RestoreTextureUnitBindings(GLuint unit,
const ContextState* prev_state) const;
void RestoreSamplerBinding(GLuint unit, const ContextState* prev_state) const;
void PushTextureUnpackState() const;
void RestoreUnpackState() const;
void DoLineWidth(GLfloat width) const;
// Helper for getting cached state.
bool GetStateAsGLint(GLenum pname, GLint* params, GLsizei* num_written) const;
bool GetStateAsGLfloat(GLenum pname,
GLfloat* params,
GLsizei* num_written) const;
bool GetEnabled(GLenum cap) const;
inline void SetDeviceColorMask(GLboolean red,
GLboolean green,
GLboolean blue,
GLboolean alpha) {
if (cached_color_mask_red == red && cached_color_mask_green == green &&
cached_color_mask_blue == blue && cached_color_mask_alpha == alpha &&
!ignore_cached_state)
return;
cached_color_mask_red = red;
cached_color_mask_green = green;
cached_color_mask_blue = blue;
cached_color_mask_alpha = alpha;
api()->glColorMaskFn(red, green, blue, alpha);
}
inline void SetDeviceDepthMask(GLboolean mask) {
if (cached_depth_mask == mask && !ignore_cached_state)
return;
cached_depth_mask = mask;
api()->glDepthMaskFn(mask);
}
inline void SetDeviceStencilMaskSeparate(GLenum op, GLuint mask) {
if (op == GL_FRONT) {
if (cached_stencil_front_writemask == mask && !ignore_cached_state)
return;
cached_stencil_front_writemask = mask;
} else if (op == GL_BACK) {
if (cached_stencil_back_writemask == mask && !ignore_cached_state)
return;
cached_stencil_back_writemask = mask;
} else {
NOTREACHED();
}
api()->glStencilMaskSeparateFn(op, mask);
}
void SetBoundBuffer(GLenum target, Buffer* buffer);
void RemoveBoundBuffer(Buffer* buffer);
void InitGenericAttribs(GLuint max_vertex_attribs) {
attrib_values.resize(max_vertex_attribs);
uint32_t packed_size = max_vertex_attribs / 16;
packed_size += (max_vertex_attribs % 16 == 0) ? 0 : 1;
generic_attrib_base_type_mask_.resize(packed_size);
for (uint32_t i = 0; i < packed_size; ++i) {
// All generic attribs are float type by default.
generic_attrib_base_type_mask_[i] = 0x55555555u * SHADER_VARIABLE_FLOAT;
}
}
void SetGenericVertexAttribBaseType(GLuint index, GLenum base_type) {
DCHECK_LT(index, attrib_values.size());
int shift_bits = (index % 16) * 2;
generic_attrib_base_type_mask_[index / 16] &= ~(0x3 << shift_bits);
generic_attrib_base_type_mask_[index / 16] |= (base_type << shift_bits);
}
const std::vector<uint32_t>& generic_attrib_base_type_mask() const {
return generic_attrib_base_type_mask_;
}
void UnbindTexture(TextureRef* texture);
void UnbindSampler(Sampler* sampler);
PixelStoreParams GetPackParams();
PixelStoreParams GetUnpackParams(Dimension dimension);
// If a buffer object is bound to PIXEL_PACK_BUFFER, set all pack parameters
// user values; otherwise, set them to 0.
void UpdatePackParameters() const;
// If a buffer object is bound to PIXEL_UNPACK_BUFFER, set all unpack
// parameters user values; otherwise, set them to 0.
void UpdateUnpackParameters() const;
void SetMaxWindowRectangles(size_t max);
size_t GetMaxWindowRectangles() const;
void SetWindowRectangles(GLenum mode,
size_t count,
const volatile GLint* box);
template <typename T>
void GetWindowRectangle(GLuint index, T* box) {
for (size_t i = 0; i < 4; ++i) {
box[i] = window_rectangles_[4 * index + i];
}
}
void UpdateWindowRectangles() const;
void UpdateWindowRectanglesForBoundDrawFramebufferClientID(GLuint client_id);
void EnableDisableFramebufferSRGB(bool enable);
#include "gpu/command_buffer/service/context_state_autogen.h"
// if false, we will not track individual texture and sampler units, instead
// we only track if all units are in ground state or not.
const bool track_texture_and_sampler_units;
EnableFlags enable_flags;
// Current active texture by 0 - n index.
// In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
// be 2.
GLuint active_texture_unit = 0u;
// The currently bound array buffer. If this is 0 it is illegal to call
// glVertexAttribPointer.
scoped_refptr<Buffer> bound_array_buffer;
scoped_refptr<Buffer> bound_copy_read_buffer;
scoped_refptr<Buffer> bound_copy_write_buffer;
scoped_refptr<Buffer> bound_pixel_pack_buffer;
scoped_refptr<Buffer> bound_pixel_unpack_buffer;
scoped_refptr<Buffer> bound_transform_feedback_buffer;
scoped_refptr<Buffer> bound_uniform_buffer;
// Which textures are bound to texture units through glActiveTexture.
std::vector<TextureUnit> texture_units;
mutable bool texture_units_in_ground_state = true;
// Which samplers are bound to each texture unit;
std::vector<scoped_refptr<Sampler>> sampler_units;
// We create a transform feedback as the default one per ES3 enabled context
// instead of using GL's default one to make context switching easier.
// For other context, we will never change the default transform feedback's
// states, so we can just use the GL's default one.
scoped_refptr<TransformFeedback> default_transform_feedback;
scoped_refptr<TransformFeedback> bound_transform_feedback;
scoped_refptr<IndexedBufferBindingHost> indexed_uniform_buffer_bindings;
// The values for each attrib.
std::vector<Vec4> attrib_values;
// Class that manages vertex attribs.
scoped_refptr<VertexAttribManager> vertex_attrib_manager;
scoped_refptr<VertexAttribManager> default_vertex_attrib_manager;
// The program in use by glUseProgram
scoped_refptr<Program> current_program;
// The currently bound renderbuffer
scoped_refptr<Renderbuffer> bound_renderbuffer;
bool bound_renderbuffer_valid = false;
bool pack_reverse_row_order = false;
bool ignore_cached_state = false;
mutable bool fbo_binding_for_scissor_workaround_dirty = false;
mutable bool stencil_state_changed_since_validation = true;
GLuint current_draw_framebuffer_client_id = 0;
private:
void EnableDisable(GLenum pname, bool enable) const;
void InitStateManual(const ContextState* prev_state) const;
// EnableDisableFramebufferSRGB is called at very high frequency. Cache the
// true value of FRAMEBUFFER_SRGB, if we know it, to elide some of these
// calls.
bool framebuffer_srgb_valid_ = false;
bool framebuffer_srgb_ = false;
// Generic vertex attrib base types: FLOAT, INT, or UINT.
// Each base type is encoded into 2 bits, the lowest 2 bits for location 0,
// the highest 2 bits for location (max_vertex_attribs - 1).
std::vector<uint32_t> generic_attrib_base_type_mask_;
GLfloat line_width_min_ = 0.0f;
GLfloat line_width_max_ = 1.0f;
// Stores the list of N window rectangles as N*4 GLints, like
// vector<[x,y,w,h]>. Always has space for MAX_WINDOW_RECTANGLES rectangles.
std::vector<GLint> window_rectangles_;
raw_ptr<gl::GLApi, DanglingUntriaged> api_ = nullptr;
raw_ptr<FeatureInfo, DanglingUntriaged> feature_info_;
bool context_lost_ = false;
};
} // namespace gles2
} // namespace gpu
#endif // GPU_COMMAND_BUFFER_SERVICE_CONTEXT_STATE_H_
|