<commit_before>// Copyright 2014 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "precompiled.h"  // NOLINT

#include "fplbase/internal/type_conversions_gl.h"
#include "fplbase/preprocessor.h"
#include "fplbase/render_target.h"
#include "fplbase/render_utils.h"
#include "fplbase/renderer.h"
#include "fplbase/texture.h"
#include "fplbase/utilities.h"
#include "mesh_impl_gl.h"

using mathfu::mat4;
using mathfu::vec2;
using mathfu::vec2i;
using mathfu::vec3;
using mathfu::vec4;

namespace fplbase {

// Local helper functions to help rendering.
namespace {

void DrawElement(int32_t count, int32_t instances, uint32_t index_type,
                 GLenum gl_primitive, bool support_instancing) {
  static const void *kNullIndices = nullptr;

  if (instances == 1) {
    GL_CALL(glDrawElements(gl_primitive, count, index_type, kNullIndices));
  } else {
    assert(support_instancing);
    GL_CALL(glDrawElementsInstanced(gl_primitive, count, index_type,
                                    kNullIndices, instances));
  }
}

void BindAttributes(BufferHandle vao, BufferHandle vbo,
                    const Attribute *attributes, size_t vertex_size) {
  if (ValidBufferHandle(vao)) {
    GL_CALL(glBindVertexArray(GlBufferHandle(vao)));
  } else {
    SetAttributes(GlBufferHandle(vbo), attributes,
                  static_cast<int>(vertex_size), nullptr);
  }
}

void UnbindAttributes(BufferHandle vao, const Attribute *attributes) {
  if (ValidBufferHandle(vao)) {
    GL_CALL(glBindVertexArray(0));  // TODO(wvo): could probably omit this?
  } else {
    UnSetAttributes(attributes);
  }
}

}  // namespace

TextureHandle InvalidTextureHandle() { return TextureHandleFromGl(0); }
TextureTarget InvalidTextureTarget() { return TextureTargetFromGl(0); }
ShaderHandle InvalidShaderHandle() { return ShaderHandleFromGl(0); }
UniformHandle InvalidUniformHandle() { return UniformHandleFromGl(-1); }
BufferHandle InvalidBufferHandle() { return BufferHandleFromGl(0); }
DeviceMemoryHandle InvalidDeviceMemoryHandle() { return DeviceMemoryHandle(); }

bool ValidTextureHandle(TextureHandle handle) {
  return GlTextureHandle(handle) != 0;
}
bool ValidTextureTarget(TextureTarget target) {
  return GlTextureTarget(target) != 0;
}
bool ValidShaderHandle(ShaderHandle handle) {
  return GlShaderHandle(handle) != 0;
}
bool ValidUniformHandle(UniformHandle handle) {
  return GlUniformHandle(handle) >= 0;
}
bool ValidBufferHandle(BufferHandle handle) {
  return GlBufferHandle(handle) != 0;
}
bool ValidDeviceMemoryHandle(DeviceMemoryHandle /*handle*/) { return false; }

RendererBaseImpl *RendererBase::CreateRendererBaseImpl() { return nullptr; }
void RendererBase::DestroyRendererBaseImpl(RendererBaseImpl *impl) {
  (void)impl;
}

RendererImpl *Renderer::CreateRendererImpl() { return nullptr; }
void Renderer::DestroyRendererImpl(RendererImpl *impl) { (void)impl; }

void RendererBase::AdvanceFrame(bool minimized, double time) {
  time_ = time;

  environment_.AdvanceFrame(minimized);
}

bool RendererBase::InitializeRenderingState() {
  auto exts = reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS));

  auto HasGLExt = [&exts](const char *ext) -> bool {
    // TODO(b/28761934): Consider supporting GL3.0 version.
    if (exts == nullptr) {
      return false;
    }
    auto pos = strstr(exts, ext);
    return pos && pos[strlen(ext)] <= ' ';  // Make sure it matched all.
  };

  // Check for multiview extension support.
  if (HasGLExt("GL_OVR_multiview") || HasGLExt("GL_OVR_multiview2")) {
    supports_multiview_ = true;
  }

  // Check for ASTC: Available in devices supporting AEP.
  if (!HasGLExt("GL_KHR_texture_compression_astc_ldr")) {
    supports_texture_format_ &= ~(1 << kFormatASTC);
  }
#ifdef __ANDROID__
  // Check for Non Power of 2 (NPOT) extension.
  if (HasGLExt("GL_ARB_texture_non_power_of_two") ||
      HasGLExt("GL_OES_texture_npot")) {
    supports_texture_npot_ = true;
  }
#else
  // All desktop platforms support NPOT.
  // iOS ES 2 is supposed to only have limited support, but in practice always
  // supports it.
  supports_texture_npot_ = true;
#endif

  supports_instancing_ = environment_.feature_level() >= kFeatureLevel30;

// Check for ETC2:
#ifdef FPLBASE_GLES
  if (environment_.feature_level() < kFeatureLevel30) {
#else
  if (!HasGLExt("GL_ARB_ES3_compatibility")) {
#endif
    supports_texture_format_ &= ~((1 << kFormatPKM) | (1 << kFormatKTX));
  }

#ifndef FPLBASE_GLES
  if (!HasGLExt("GL_ARB_vertex_buffer_object") ||
      !HasGLExt("GL_ARB_multitexture") || !HasGLExt("GL_ARB_vertex_program") ||
      !HasGLExt("GL_ARB_fragment_program")) {
    last_error_ = "missing GL extensions";
    return false;
  }
#endif

  GL_CALL(glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS,
                        &max_vertex_uniform_components_));
#if defined(GL_MAX_VERTEX_UNIFORM_VECTORS)
  if (max_vertex_uniform_components_ == 0) {
    // If missing the number of uniform components, use the number of vectors.
    GL_CALL(glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS,
                          &max_vertex_uniform_components_));
    max_vertex_uniform_components_ *= 4;
  }
#endif  // defined(GL_MAX_VERTEX_UNIFORM_VECTORS)

  return true;
}

void Renderer::ClearFrameBuffer(const vec4 &color) {
  GL_CALL(glClearColor(color.x, color.y, color.z, color.w));
  GL_CALL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
}

void Renderer::ClearDepthBuffer() { GL_CALL(glClear(GL_DEPTH_BUFFER_BIT)); }

ShaderHandle RendererBase::CompileShader(bool is_vertex_shader,
                                         ShaderHandle program,
                                         const char *csource) {
  assert(max_vertex_uniform_components_);

  const std::string max_components =
      "MAX_VERTEX_UNIFORM_COMPONENTS " +
      flatbuffers::NumToString(max_vertex_uniform_components_);
  const char *defines[] = {max_components.c_str(), nullptr};

  const char *source = csource;
  if (!is_vertex_shader && override_pixel_shader_.length())
    source = override_pixel_shader_.c_str();
  std::string platform_source;
  PlatformSanitizeShaderSource(source, defines, &platform_source);
  const char *platform_source_ptr = platform_source.c_str();

  const GLenum stage = is_vertex_shader ? GL_VERTEX_SHADER : GL_FRAGMENT_SHADER;<commit_msg>Fixed an assert that would sometimes fire due to a GL_INVALID_ENUM if trying to glGet(GL_MAX_VERTEX_UNIFORM_COMPONENTS) on an ES 2.0 context.<commit_after>// Copyright 2014 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "precompiled.h"  // NOLINT

#include "fplbase/internal/type_conversions_gl.h"
#include "fplbase/preprocessor.h"
#include "fplbase/render_target.h"
#include "fplbase/render_utils.h"
#include "fplbase/renderer.h"
#include "fplbase/texture.h"
#include "fplbase/utilities.h"
#include "mesh_impl_gl.h"

using mathfu::mat4;
using mathfu::vec2;
using mathfu::vec2i;
using mathfu::vec3;
using mathfu::vec4;

namespace fplbase {

// Local helper functions to help rendering.
namespace {

void DrawElement(int32_t count, int32_t instances, uint32_t index_type,
                 GLenum gl_primitive, bool support_instancing) {
  static const void *kNullIndices = nullptr;

  if (instances == 1) {
    GL_CALL(glDrawElements(gl_primitive, count, index_type, kNullIndices));
  } else {
    assert(support_instancing);
    GL_CALL(glDrawElementsInstanced(gl_primitive, count, index_type,
                                    kNullIndices, instances));
  }
}

void BindAttributes(BufferHandle vao, BufferHandle vbo,
                    const Attribute *attributes, size_t vertex_size) {
  if (ValidBufferHandle(vao)) {
    GL_CALL(glBindVertexArray(GlBufferHandle(vao)));
  } else {
    SetAttributes(GlBufferHandle(vbo), attributes,
                  static_cast<int>(vertex_size), nullptr);
  }
}

void UnbindAttributes(BufferHandle vao, const Attribute *attributes) {
  if (ValidBufferHandle(vao)) {
    GL_CALL(glBindVertexArray(0));  // TODO(wvo): could probably omit this?
  } else {
    UnSetAttributes(attributes);
  }
}

}  // namespace

TextureHandle InvalidTextureHandle() { return TextureHandleFromGl(0); }
TextureTarget InvalidTextureTarget() { return TextureTargetFromGl(0); }
ShaderHandle InvalidShaderHandle() { return ShaderHandleFromGl(0); }
UniformHandle InvalidUniformHandle() { return UniformHandleFromGl(-1); }
BufferHandle InvalidBufferHandle() { return BufferHandleFromGl(0); }
DeviceMemoryHandle InvalidDeviceMemoryHandle() { return DeviceMemoryHandle(); }

bool ValidTextureHandle(TextureHandle handle) {
  return GlTextureHandle(handle) != 0;
}
bool ValidTextureTarget(TextureTarget target) {
  return GlTextureTarget(target) != 0;
}
bool ValidShaderHandle(ShaderHandle handle) {
  return GlShaderHandle(handle) != 0;
}
bool ValidUniformHandle(UniformHandle handle) {
  return GlUniformHandle(handle) >= 0;
}
bool ValidBufferHandle(BufferHandle handle) {
  return GlBufferHandle(handle) != 0;
}
bool ValidDeviceMemoryHandle(DeviceMemoryHandle /*handle*/) { return false; }

RendererBaseImpl *RendererBase::CreateRendererBaseImpl() { return nullptr; }
void RendererBase::DestroyRendererBaseImpl(RendererBaseImpl *impl) {
  (void)impl;
}

RendererImpl *Renderer::CreateRendererImpl() { return nullptr; }
void Renderer::DestroyRendererImpl(RendererImpl *impl) { (void)impl; }

void RendererBase::AdvanceFrame(bool minimized, double time) {
  time_ = time;

  environment_.AdvanceFrame(minimized);
}

bool RendererBase::InitializeRenderingState() {
  auto exts = reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS));

  auto HasGLExt = [&exts](const char *ext) -> bool {
    // TODO(b/28761934): Consider supporting GL3.0 version.
    if (exts == nullptr) {
      return false;
    }
    auto pos = strstr(exts, ext);
    return pos && pos[strlen(ext)] <= ' ';  // Make sure it matched all.
  };

  // Check for multiview extension support.
  if (HasGLExt("GL_OVR_multiview") || HasGLExt("GL_OVR_multiview2")) {
    supports_multiview_ = true;
  }

  // Check for ASTC: Available in devices supporting AEP.
  if (!HasGLExt("GL_KHR_texture_compression_astc_ldr")) {
    supports_texture_format_ &= ~(1 << kFormatASTC);
  }
#ifdef __ANDROID__
  // Check for Non Power of 2 (NPOT) extension.
  if (HasGLExt("GL_ARB_texture_non_power_of_two") ||
      HasGLExt("GL_OES_texture_npot")) {
    supports_texture_npot_ = true;
  }
#else
  // All desktop platforms support NPOT.
  // iOS ES 2 is supposed to only have limited support, but in practice always
  // supports it.
  supports_texture_npot_ = true;
#endif

  supports_instancing_ = environment_.feature_level() >= kFeatureLevel30;

// Check for ETC2:
#ifdef FPLBASE_GLES
  if (environment_.feature_level() < kFeatureLevel30) {
#else
  if (!HasGLExt("GL_ARB_ES3_compatibility")) {
#endif
    supports_texture_format_ &= ~((1 << kFormatPKM) | (1 << kFormatKTX));
  }

#ifndef FPLBASE_GLES
  if (!HasGLExt("GL_ARB_vertex_buffer_object") ||
      !HasGLExt("GL_ARB_multitexture") || !HasGLExt("GL_ARB_vertex_program") ||
      !HasGLExt("GL_ARB_fragment_program")) {
    last_error_ = "missing GL extensions";
    return false;
  }
#endif

  // We are using GL_MAX_VERTEX_UNIFORM_VECTORS here because it is always
  // available while GL_MAX_VERTEX_UNIFORM_COMPONENTS is not (i.e. GL ES 2.0).
  GL_CALL(glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS,
                        &max_vertex_uniform_components_));
  max_vertex_uniform_components_ *= 4;

  return true;
}

void Renderer::ClearFrameBuffer(const vec4 &color) {
  GL_CALL(glClearColor(color.x, color.y, color.z, color.w));
  GL_CALL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
}

void Renderer::ClearDepthBuffer() { GL_CALL(glClear(GL_DEPTH_BUFFER_BIT)); }

ShaderHandle RendererBase::CompileShader(bool is_vertex_shader,
                                         ShaderHandle program,
                                         const char *csource) {
  assert(max_vertex_uniform_components_);

  const std::string max_components =
      "MAX_VERTEX_UNIFORM_COMPONENTS " +
      flatbuffers::NumToString(max_vertex_uniform_components_);
  const char *defines[] = {max_components.c_str(), nullptr};

  const char *source = csource;
  if (!is_vertex_shader && override_pixel_shader_.length())
    source = override_pixel_shader_.c_str();
  std::string platform_source;
  PlatformSanitizeShaderSource(source, defines, &platform_source);
  const char *platform_source_ptr = platform_source.c_str();

  const GLenum stage = is_vertex_shader ? GL_VERTEX_SHADER : GL_FRAGMENT_SHADER;
{'fraction_non_alphanumeric': 0.10635795663359059, 'fraction_numerical': 0.008452774715178243, 'mean_word_length': 4.477455716586151, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3582359', 'n_tokens_mistral': 4347, 'n_tokens_neox': 4271, 'n_words': 989}