text:
require 'rack/mount'
require 'rack/auth/basic'
require 'rack/auth/digest/md5'
require 'logger'

module Grape
  # The API class is the primary entry point for
  # creating Grape APIs. Users should subclass this
  # class in order to build an API.
  class API
    class << self
      attr_reader :route_set
      attr_reader :versions
      attr_reader :routes

      def logger(logger = nil)
        if logger
          @logger = logger
        else
          @logger ||= Logger.new($STDOUT)
        end
      end

      def reset!
        @settings = [{}]
        @route_set = Rack::Mount::RouteSet.new
        @prototype = nil
      end

      def call(env)
        logger.info "#{env['REQUEST_METHOD']} #{env['PATH_INFO']}"
        route_set.freeze.call(env)
      end

      # Settings are a stack, so when we
      # want to access them they are merged
      # in the order pushed.
      def settings
        @settings.inject({}){|f,h| f.merge!(h); f}
      end

      def settings_stack
        @settings
      end

      # Set a configuration value for this
      # namespace.
      #
      # @param key [Symbol] The key of the configuration variable.
      # @param value [Object] The value to which to set the configuration variable.
      def set(key, value)
        @settings.last[key.to_sym] = value
      end

      # Add to a configuration value for this
      # namespace.
      #
      # @param key [Symbol] The key of the configuration variable.
      # @param value [Object] The value to which to set the configuration variable.
      def add(key, value)
        current = @settings.last[key.to_sym]
        if current.is_a?(Array)
          current.concat(value)
        elsif current.is_a?(Hash)
          current.merge!(value)
        else
          @settings.last[key.to_sym] = value
        end
      end

      # Define a root URL prefix for your entire
      # API.
      def prefix(prefix = nil)
        prefix ? set(:root_prefix, prefix) : settings[:root_prefix]
      end

      # Specify an API version.
      #
      # @example API with legacy support.
      #   class MyAPI < Grape::API
      #     version 'v2'
      #
      #     get '/main' do
      #       {:some => 'data'}
      #     end
      #
      #     version 'v1' do
      #       get '/main' do
      #         {:legacy => 'data'}
      #       end
      #     end
      #   end
      #
      def version(*new_versions, &block)
        if new_versions.any?
          @versions = versions | new_versions
          nest(block) { set(:version, new_versions) }
        else
          settings[:version]
        end
      end

      # Specify the default format for the API's
      # serializers. Currently only `:json` is
      # supported.
      def default_format(new_format = nil)
        new_format ? set(:default_format, new_format.to_sym) : settings[:default_format]
      end

      # Specify the format for error messages.
      # May be `:json` or `:txt` (default).
      def error_format(new_format = nil)
        new_format ? set(:error_format, new_format.to_sym) : settings[:error_format]
      end

      # Specify the default status code for errors.
      def default_error_status(new_status = nil)
        new_status ? set(:default_error_status, new_status) : settings[:default_error_status]
      end

      # Allows you to rescue certain exceptions that occur to return
      # a grape error rather than raising all the way to the
      # server level.
      #
      # @example Rescue from custom exceptions
      #     class ExampleAPI < Grape::API
      #       class CustomError < StandardError; end
      #
      #       rescue_from CustomError
      #     end
      #
      # @overload rescue_from(*exception_classes, options = {})
      #   @param [Array] exception_classes A list of classes that you want to rescue, or
      #     the symbol :all to rescue from all exceptions.
      #   @param [Block] block Execution block to handle the given exception.
      #   @param [Hash] options Options for the rescue usage.
      #   @option options [Boolean] :backtrace Include a backtrace in the rescue response.
      def rescue_from(*args, &block)
        if block_given?
          args.each do |arg|
            add(:rescue_handlers, { arg => block })
          end
        end
        add(:rescue_options, args.pop) if args.last.is_a?(Hash)
        set(:rescue_all, true) and return if args.include?(:all)
        add(:rescued_errors, args)
      end

      # Add helper methods that will be accessible from any
      # endpoint within this namespace (and child namespaces).
      #
      # @example Define some helpers.
      #     class ExampleAPI < Grape::API
      #       helpers do
      #         def current_user
      #           User.find_by_id(params[:token])
      #         end
      #       end
      #     end
      def helpers(&block)
        if block_given?
          m = settings_stack.last[:helpers] || Module.new
          m.class_eval &block
          set(:helpers, m)
        else
          m = Module.new
          settings_stack.each do |s|
            m.send :include, s[:helpers] if s[:helpers]
          end
          m
        end
      end

      # Add an authentication type to the API. Currently
      # only `:http_basic`, `:http_digest` and `:oauth2` are supported.
      def auth(type = nil, options = {}, &block)
        if type
          set(:auth, {:type => type.to_sym, :proc => block}.merge(options))
        else
          settings[:auth]
        end
      end

      # Add HTTP Basic authorization to the API.
      #
      # @param [Hash] options A hash of options.
      # @option options [String] :realm "API Authorization" The HTTP Basic realm.
      def http_basic(options = {}, &block)
        options[:realm] ||= "API Authorization"
        auth :http_basic, options, &block
      end

      def http_digest(options = {}, &block)
        options[:realm] ||= "API Authorization"
        options[:opaque] ||= "secret"
        auth :http_digest, options, &block
      end

      # Defines a route that will be recognized
      # by the Grape API.
      #
      # @param methods [HTTP Verb] One or more HTTP verbs that are accepted by this route. Set to `:any` if you want any verb to be accepted.
      # @param paths [String] One or more strings representing the URL segment(s) for this route.
      #
      # @example Defining a basic route.
      #   class MyAPI < Grape::API
      #     route(:any, '/hello') do
      #       {:hello => 'world'}
      #     end
      #   end
      def route(methods, paths = ['/'], route_options = {}, &block)
        methods = Array(methods)

        paths = ['/'] if ! paths || paths == []
        paths = Array(paths)

        endpoint = build_endpoint(&block)

        endpoint_options = {}
        endpoint_options[:version] = /#{version.join('|')}/ if version

        route_options ||= {}

        methods.each do |method|
          paths.each do |path|

            compiled_path = compile_path(path)
            path = Rack::Mount::Strexp.compile(compiled_path, endpoint_options, %w( / . ? ), true)
            regex = Rack::Mount::RegexpWithNamedGroups.new(path)
            path_params = regex.named_captures.map { |nc| nc[0] } - [ 'version', 'format' ]
            path_params |= (route_options[:params] || [])
            request_method = (method.to_s.upcase unless method == :any)

            routes << Route.new(route_options.merge({
              :prefix => prefix,
              :version => version ? version.join('|') : nil,
              :namespace => namespace,
              :method => request_method,
              :path => compiled_path,
              :params => path_params}))

            route_set.add_route(endpoint,
              :path_info => path,
              :request_method => request_method
            )
          end
        end
      end

      def before(&block)
        settings_stack.last[:befores] ||= []
        settings_stack.last[:befores] << block
      end

      def after(&block)
        settings_stack.last[:afters] ||= []
        settings_stack.last[:afters] << block
      end

      def get(paths = ['/'], options = {}, &block); route('GET', paths, options, &block) end
      def post(paths = ['/'], options = {}, &block); route('POST', paths, options, &block) end
      def put(paths = ['/'], options = {}, &block); route('PUT', paths, options, &block) end
      def head(paths = ['/'], options = {}, &block); route('HEAD', paths, options, &block) end
      def delete(paths = ['/'], options = {}, &block); route('DELETE', paths, options, &block) end

      def namespace(space = nil, &block)
        if space || block_given?
          nest(block) do
            set(:namespace, space.to_s) if space
          end
        else
          Rack::Mount::Utils.normalize_path(settings_stack.map{|s| s[:namespace]}.join('/'))
        end
      end

      alias_method :group, :namespace
      alias_method :resource, :namespace
      alias_method :resources, :namespace
      alias_method :segment, :namespace

      # Create a scope without affecting the URL.
      #
      # @param name [Symbol] Purely placebo, just allows to to name the scope to make the code more readable.
      def scope(name = nil, &block)
        nest(block)
      end

      # Apply a custom middleware to the API. Applies
      # to the current namespace and any children, but
      # not parents.
      #
      # @param middleware_class [Class] The class of the middleware you'd like to inject.
      def use(middleware_class, *args)
        settings_stack.last[:middleware] ||= []
        settings_stack.last[:middleware] << [middleware_class, *args]
      end

      # Retrieve an array of the middleware classes
      # and arguments that are currently applied to the
      # application.
      def middleware
        settings_stack.inject([]){|a,s| a += s[:middleware] if s[:middleware]; a}
      end

      # An array of API routes.
      def routes
        @routes ||= []
      end

      def versions
        @versions ||= []
      end

      protected

      # Execute first the provided block, then each of the
      # block passed in. Allows for simple 'before' setups
      # of settings stack pushes.
      def nest(*blocks, &block)
        blocks.reject!{|b| b.nil?}
        if blocks.any?
          settings_stack << {}
          instance_eval &block if block_given?
          blocks.each{|b| instance_eval &b}
          settings_stack.pop
        else
          instance_eval &block
        end
      end

      def aggregate_setting(key)
        settings_stack.inject([]) do |befores, settings|
          befores += (settings[key] || [])
        end
      end

      def build_endpoint(&block)
        b = Rack::Builder.new
        b.use Grape::Middleware::Error,
          :default_status => settings[:default_error_status] || 403,
          :rescue_all => settings[:rescue_all],
          :rescued_errors => settings[:rescued_errors],
          :format => settings[:error_format] || :txt,
          :rescue_options => settings[:rescue_options],
          :rescue_handlers => settings[:rescue_handlers] || {}
        b.use Rack::Auth::Basic, settings[:auth][:realm], &settings[:auth][:proc] if settings[:auth] && settings[:auth][:type] == :http_basic
        b.use Rack::Auth::Digest::MD5, settings[:auth][:realm], settings[:auth][:opaque], &settings[:auth][:proc] if settings[:auth] && settings[:auth][:type] == :http_digest
        b.use Grape::Middleware::Prefixer, :prefix => prefix if prefix
        b.use Grape::Middleware::Versioner, :versions => (version if version.is_a?(Array)) if version
        b.use Grape::Middleware::Formatter, :default_format => default_format || :json
        middleware.each{|m| b.use *m }

        befores = aggregate_setting(:befores)
        afters =  aggregate_setting(:afters)

        endpoint = Grape::Endpoint.generate({:befores => befores, :afters => afters}, &block)
        endpoint.send :include, helpers
        b.run endpoint

        b.to_app
      end

      def inherited(subclass)
        subclass.reset!
      end

      def route_set
        @route_set ||= Rack::Mount::RouteSet.new
      end

      def compile_path(path)
        parts = []
        parts << prefix if prefix
        parts << ':version' if version
        parts << namespace.to_s if namespace
        parts << path.to_s if path && '/' != path
        parts.last << '(.:format)'
        Rack::Mount::Utils.normalize_path(parts.join('/'))
      end
    end

    reset!
  end
end


text:
package virtuozo.interfaces;

import virtuozo.infra.Elements;

public final class Text extends Component<Text> implements HasText<Text>, HasHtml<Text>{

  public static Text create(){
    return new Text();
  }

  private Text() {
    super(Elements.span());
    this.hide();
  }

  @Override
  public String html() {
    return this.element().getInnerHTML();
  }

  @Override
  public Text html(String html) {
    this.element().setInnerHTML(html);
    return this.show();
  }

  @Override
  public String text() {
    return this.element().getInnerText();
  }

  public Text text(String text) {
    this.element().setInnerText(text);
    return this.show();
  }
}

redpajama_set_name: RedPajamaGithub


text:
#include "sysdeps.h"
#include <xf86drm.h>
#include "va_drm_utils.h"
#include "va_drmcommon.h"

struct driver_name_map {
    const char *key;
    int         key_len;
    const char *name;
};

static const struct driver_name_map g_driver_name_map[] = {
    { "i915",       4, "i965"   }, // Intel OTC GenX driver
    { "pvrsrvkm",   8, "pvr"    }, // Intel UMG PVR driver
    { "emgd",       4, "emgd"   }, // Intel ECG PVR driver
    { NULL, }
};

/* Returns the VA driver name for the active display */
VAStatus
VA_DRM_GetDriverName(VADriverContextP ctx, char **driver_name_ptr)
{
    struct drm_state * const drm_state = ctx->drm_state;
    drmVersionPtr drm_version;
    char *driver_name = NULL;
    const struct driver_name_map *m;

    *driver_name_ptr = NULL;

    if (!drm_state || drm_state->fd < 0)
        return VA_STATUS_ERROR_INVALID_DISPLAY;

    drm_version = drmGetVersion(drm_state->fd);
    if (!drm_version)
        return VA_STATUS_ERROR_UNKNOWN;

    for (m = g_driver_name_map; m->key != NULL; m++) {
        if (drm_version->name_len >= m->key_len &&
            strncmp(drm_version->name, m->key, m->key_len) == 0)
            break;
    }
    drmFreeVersion(drm_version);

    if (!m->name)
        return VA_STATUS_ERROR_UNKNOWN;

    driver_name = strdup(m->name);
    if (!driver_name)
        return VA_STATUS_ERROR_ALLOCATION_FAILED;

    *driver_name_ptr = driver_name;
    return VA_STATUS_SUCCESS;
}


text:
Cooperation IO
--------------

Do you want to challenge your colleagues/friends thought a list a games requiring cooperation and deep search.

##Install
Install node.js: http://nodejs.org/

Then ```npm install```

##Games
The possible games are:
- click game: global click button
- question game factory: To create your own question game. Pass the question and the expected answer, it returns the question-game
- mole game: can everyone click on all the pictures at the same time?
- keyboard game: can everyone press one keyboard button at the same time?

Once you built and made all your games, list them in game.js in the "games" list.

Run ```node main.js``` and visit http://localhost:3000


text:
package com.github.thbrown.softballsim.data.gson;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import com.github.thbrown.softballsim.util.Logger;
import com.github.thbrown.softballsim.util.StringUtils;

public class DataPlayer {
  private String id;
  private String name;
  private String gender;

  public String getId() {
    return id;
  }

  public String getName() {
    return name;
  }

  public String getGender() {
    return gender;
  }

  private transient Set<DataTeam> teams = new HashSet<>();
  private transient Set<DataGame> games = new HashSet<>();
  private transient Set<DataPlateAppearance> plateAppearances = new HashSet<>();

  public void addTeam(DataTeam team) {
    teams.add(team);
  }

  public void addGame(DataGame game) {
    games.add(game);
  }

  public void addPlateAppearences(DataPlateAppearance plateAppearance) {
    plateAppearances.add(plateAppearance);
  }

  public Set<DataTeam> getTeams() {
    return teams;
  }

  public Set<DataGame> getGames() {
    return games;
  }

  public Set<DataPlateAppearance> getPlateAppearances() {
    return plateAppearances;
  }

  // Caching variables for calculated fields - using composite data types here to allow null to
  // represent an un-initialized cache
  private transient Integer directOutCount;
  private transient Integer singleCount;
  private transient Integer doubleCount;
  private transient Integer tripleCount;
  private transient Integer homerunCount;
  private transient Integer walkCount;
  private transient Integer sacCount;
  private transient Integer atBatCount;
  private transient Integer errorCount;
  private transient Integer strikeoutCount;
  private transient Integer fcCount;
  private transient Integer outCount;
  private transient Integer hitCount;
  private transient Integer totalBases;
  private transient Double battingAverage;
  private transient Double sluggingPercentage;

  public int getOutCount() {
    calculateIfNull(outCount);
    return outCount;
  }

  public int getSingleCount() {
    calculateIfNull(singleCount);
    return singleCount;
  }

  public int getDoubleCount() {
    calculateIfNull(doubleCount);
    return doubleCount;
  }

  public int getTripleCount() {
    calculateIfNull(tripleCount);
    return tripleCount;
  }

  public int getHomerunCount() {
    calculateIfNull(homerunCount);
    return homerunCount;
  }

  public int getWalkCount() {
    calculateIfNull(walkCount);
    return walkCount;
  }

  public int getPlateAppearanceCount() {
    return plateAppearances.size();
  }

  public double getBattingAverage() {
    calculateIfNull(battingAverage);
    return battingAverage;
  }

  public double getSluggingPercentage() {
    calculateIfNull(sluggingPercentage);
    return sluggingPercentage;
  }

  public int getSacCount() {
    calculateIfNull(sacCount);
    return sacCount;
  }

  public int getStrikeoutCount() {
    calculateIfNull(strikeoutCount);
    return strikeoutCount;
  }

  public int getReachedOnErrorCount() {
    calculateIfNull(errorCount);
    return this.errorCount;
  }

  private void calculateIfNull(Object input) {
    if (input == null) {
      calculatePlayerStats();
    }
  }

  private int zeroIfNull(Integer object) {
    return Optional.ofNullable(object).orElse(0);
  }

  private void calculatePlayerStats() {
    // Build a map with the counts for each
    Map<String, Integer> results = new HashMap<>();
    for (DataPlateAppearance pa : this.plateAppearances) {
      Integer result = results.get(pa.getResult());
      if (result == null) {
        results.put(pa.getResult(), 1);
      } else {
        results.put(pa.getResult(), result + 1);
      }
    }

    Logger.log(results);

    // Remember these results so we don't have to calculate them again
    this.directOutCount =
        zeroIfNull(results.get("Out")) + zeroIfNull(results.get("DP")) + zeroIfNull(results.get("TP"));
    this.errorCount = zeroIfNull(results.get("E"));
    this.fcCount = zeroIfNull(results.get("FC"));

    // "êž°" and "\u2588" are both different encodings for the backward K unicode character
    this.strikeoutCount =
        zeroIfNull(results.get("K")) + zeroIfNull(results.get("Ʞ")) + zeroIfNull(results.get("\uA7B0"));
    this.sacCount = zeroIfNull(results.get("SAC"));
    this.walkCount = zeroIfNull(results.get("BB"));
    this.singleCount = zeroIfNull(results.get("1B"));
    this.doubleCount = zeroIfNull(results.get("2B"));
    this.tripleCount = zeroIfNull(results.get("3B"));
    this.homerunCount = zeroIfNull(results.get("HRi")) + zeroIfNull(results.get("HRo"));
    this.outCount = this.directOutCount + this.fcCount + this.strikeoutCount + this.errorCount; // Omits SAC/BB
    this.hitCount = this.singleCount + this.doubleCount + this.tripleCount + this.homerunCount;
    this.atBatCount = this.hitCount + this.outCount;
    this.totalBases = this.singleCount + this.doubleCount * 2 + this.tripleCount * 3 + this.homerunCount * 4;

    if (this.atBatCount == 0) {
      this.battingAverage = 0d;
      this.sluggingPercentage = 0d;
    } else {
      this.battingAverage = ((double) this.hitCount / (double) this.atBatCount);
      this.sluggingPercentage = ((double) (this.totalBases) / (double) this.atBatCount);
    }
  }

  private static final int NAME_PADDING = 24;

  public static String getListHeader() {
    return StringUtils.padRight("Name", NAME_PADDING) + " " + StringUtils.padRight("Id", 14) + " "
        + StringUtils.padRight("avg", 5) + " " + StringUtils.padRight("slg", 5);
  }

  @Override
  public String toString() {
    calculatePlayerStats();
    // Test
    return StringUtils.padRight(this.name, NAME_PADDING) + " " + this.id + " "
        + StringUtils.formatDecimal(this.getBattingAverage(), 3) + " "
        + StringUtils.formatDecimal(this.getSluggingPercentage(), 3);
    // + this.hitCount + " "
    // + this.atBatCount + " "
    // + this.getOutCount() + " "
    // + this.directOutCount + " "
    // + this.fcCount + " "
    // + this.strikeoutCount + " "
    // + this.errorCount + " "
    // + this.hitCount + " "
    // + this.singleCount + " "
    // + this.doubleCount + " "
    // + this.tripleCount + " "
    // + this.homerunCount + " ";

  }

}


text:
require "bundler/setup"
require "lit_doc"

RSpec.configure do |config|
  # Enable flags like --only-failures and --next-failure
  config.example_status_persistence_file_path = ".rspec_status"

  config.expect_with :rspec do |c|
    c.syntax = :expect
  end
end


text:
#pragma once
#include <aws/sagemaker/SageMaker_EXPORTS.h>
#include <aws/core/utils/memory/stl/AWSVector.h>
#include <aws/core/utils/memory/stl/AWSString.h>
#include <aws/sagemaker/model/ModelSummary.h>
#include <utility>

namespace Aws
{
template<typename RESULT_TYPE>
class AmazonWebServiceResult;

namespace Utils
{
namespace Json
{
  class JsonValue;
} // namespace Json
} // namespace Utils
namespace SageMaker
{
namespace Model
{
  class AWS_SAGEMAKER_API ListModelsResult
  {
  public:
    ListModelsResult();
    ListModelsResult(const Aws::AmazonWebServiceResult<Aws::Utils::Json::JsonValue>& result);
    ListModelsResult& operator=(const Aws::AmazonWebServiceResult<Aws::Utils::Json::JsonValue>& result);

    /**
     *
An array of ModelSummary objects, each of which lists a
     * model.

     */
    inline const Aws::Vector<ModelSummary>& GetModels() const{ return m_models; }

    /**
     *
An array of ModelSummary objects, each of which lists a
     * model.

     */
    inline void SetModels(const Aws::Vector<ModelSummary>& value) { m_models = value; }

    /**
     *
An array of ModelSummary objects, each of which lists a
     * model.

     */
    inline void SetModels(Aws::Vector<ModelSummary>&& value) { m_models = std::move(value); }

    /**
     *
An array of ModelSummary objects, each of which lists a
     * model.

     */
    inline ListModelsResult& WithModels(const Aws::Vector<ModelSummary>& value) { SetModels(value); return *this;}

    /**
     *
An array of ModelSummary objects, each of which lists a
     * model.

     */
    inline ListModelsResult& WithModels(Aws::Vector<ModelSummary>&& value) { SetModels(std::move(value)); return *this;}

    /**
     *
An array of ModelSummary objects, each of which lists a
     * model.

     */
    inline ListModelsResult& AddModels(const ModelSummary& value) { m_models.push_back(value); return *this; }

    /**
     *
An array of ModelSummary objects, each of which lists a
     * model.

     */
    inline ListModelsResult& AddModels(ModelSummary&& value) { m_models.push_back(std::move(value)); return *this; }

    /**
     *
 If the response is truncated, SageMaker returns this token. To retrieve the
     * next set of models, use it in the subsequent request.

     */
    inline const Aws::String& GetNextToken() const{ return m_nextToken; }

    /**
     *
 If the response is truncated, SageMaker returns this token. To retrieve the
     * next set of models, use it in the subsequent request.

     */
    inline void SetNextToken(const Aws::String& value) { m_nextToken = value; }

    /**
     *
 If the response is truncated, SageMaker returns this token. To retrieve the
     * next set of models, use it in the subsequent request.

     */
    inline void SetNextToken(Aws::String&& value) { m_nextToken = std::move(value); }

    /**
     *
 If the response is truncated, SageMaker returns this token. To retrieve the
     * next set of models, use it in the subsequent request.

     */
    inline void SetNextToken(const char* value) { m_nextToken.assign(value); }

    /**
     *
 If the response is truncated, SageMaker returns this token. To retrieve the
     * next set of models, use it in the subsequent request.

     */
    inline ListModelsResult& WithNextToken(const Aws::String& value) { SetNextToken(value); return *this;}

    /**
     *
 If the response is truncated, SageMaker returns this token. To retrieve the
     * next set of models, use it in the subsequent request.

     */
    inline ListModelsResult& WithNextToken(Aws::String&& value) { SetNextToken(std::move(value)); return *this;}

    /**
     *
 If the response is truncated, SageMaker returns this token. To retrieve the
     * next set of models, use it in the subsequent request.

     */
    inline ListModelsResult& WithNextToken(const char* value) { SetNextToken(value); return *this;}

  private:

    Aws::Vector<ModelSummary> m_models;

    Aws::String m_nextToken;
  };

} // namespace Model
} // namespace SageMaker
} // namespace Aws


text:
import _ from 'lodash'
import * as actionTypes from './hex-view-action-types'

_.each(actionTypes, type => {
  module.exports[_.camelCase(type.split('/')[1])] = payload => {
    return (dispatch) => {
      dispatch({ type, payload })
    }
  }
})


text:
#include "gl_renderstate.h"
#include "gl_driver.h"

void PixelUnpackState::Fetch(const GLHookSet *funcs, bool compressed)
{
  funcs->glGetIntegerv(eGL_UNPACK_SWAP_BYTES, &swapBytes);
  funcs->glGetIntegerv(eGL_UNPACK_ROW_LENGTH, &rowlength);
  funcs->glGetIntegerv(eGL_UNPACK_IMAGE_HEIGHT, &imageheight);
  funcs->glGetIntegerv(eGL_UNPACK_SKIP_PIXELS, &skipPixels);
  funcs->glGetIntegerv(eGL_UNPACK_SKIP_ROWS, &skipRows);
  funcs->glGetIntegerv(eGL_UNPACK_SKIP_IMAGES, &skipImages);
  funcs->glGetIntegerv(eGL_UNPACK_ALIGNMENT, &alignment);

  if(compressed)
  {
    funcs->glGetIntegerv(eGL_UNPACK_COMPRESSED_BLOCK_WIDTH, &compressedBlockWidth);
    funcs->glGetIntegerv(eGL_UNPACK_COMPRESSED_BLOCK_HEIGHT, &compressedBlockHeight);
    funcs->glGetIntegerv(eGL_UNPACK_COMPRESSED_BLOCK_DEPTH, &compressedBlockDepth);
    funcs->glGetIntegerv(eGL_UNPACK_COMPRESSED_BLOCK_SIZE, &compressedBlockSize);
  }
}

void PixelUnpackState::Apply(const GLHookSet *funcs, bool compressed)
{
  funcs->glPixelStorei(eGL_UNPACK_SWAP_BYTES, swapBytes);
  funcs->glPixelStorei(eGL_UNPACK_ROW_LENGTH, rowlength);
  funcs->glPixelStorei(eGL_UNPACK_IMAGE_HEIGHT, imageheight);
  funcs->glPixelStorei(eGL_UNPACK_SKIP_PIXELS, skipPixels);
  funcs->glPixelStorei(eGL_UNPACK_SKIP_ROWS, skipRows);
  funcs->glPixelStorei(eGL_UNPACK_SKIP_IMAGES, skipImages);
  funcs->glPixelStorei(eGL_UNPACK_ALIGNMENT, alignment);

  if(compressed)
  {
    funcs->glPixelStorei(eGL_UNPACK_COMPRESSED_BLOCK_WIDTH, compressedBlockWidth);
    funcs->glPixelStorei(eGL_UNPACK_COMPRESSED_BLOCK_HEIGHT, compressedBlockHeight);
    funcs->glPixelStorei(eGL_UNPACK_COMPRESSED_BLOCK_DEPTH, compressedBlockDepth);
    funcs->glPixelStorei(eGL_UNPACK_COMPRESSED_BLOCK_SIZE, compressedBlockSize);
  }
}

bool PixelUnpackState::FastPath(GLsizei width, GLsizei height, GLsizei depth, GLenum dataformat,
                                GLenum basetype)
{
  if(swapBytes)
    return false;

  if(skipPixels)
    return false;

  if(height > 0 && skipRows)
    return false;

  if(depth > 0 && skipImages)
    return false;

  if(width > 0 && rowlength > 0 && width < rowlength)
    return false;

  if(height > 0 && imageheight > 0 && height < imageheight)
    return false;

  if(alignment > (int32_t)GetByteSize(1, 1, 1, dataformat, basetype))
    return false;

  return true;
}

bool PixelUnpackState::FastPathCompressed(GLsizei width, GLsizei height, GLsizei depth)
{
  // compressedBlockSize and compressedBlockWidth must be set for any of the unpack params to be
  // used
  // if they are 0, all of the unpack params are ignored, so we go through the fast path (no
  // unpacking)
  if(compressedBlockSize == 0 || compressedBlockWidth == 0)
    return true;

  if(skipPixels)
    return false;

  if(width > 0 && rowlength > 0 && width < rowlength)
    return false;

  // the below two unpack params require compressedBlockHeight to be set so if we haven't "failed"
  // to
  // hit the fast path, none of the other params make a difference as they're ignored and we go
  // through
  // the fast path (no unpacking)
  if(compressedBlockHeight == 0)
    return true;

  if(height > 0 && skipRows)
    return false;

  if(height > 0 && imageheight > 0 && height < imageheight)
    return false;

  // the final unpack param requires compressedBlockDepth to be set, as above if it's 0 then we can
  // just go straight through the fast path (no unpacking)
  if(compressedBlockDepth == 0)
    return true;

  if(depth > 0 && skipImages)
    return false;

  return true;
}

byte *PixelUnpackState::Unpack(byte *pixels, GLsizei width, GLsizei height, GLsizei depth,
                               GLenum dataformat, GLenum basetype)
{
  size_t pixelSize = GetByteSize(1, 1, 1, dataformat, basetype);

  size_t srcrowstride = pixelSize * RDCMAX(RDCMAX(width, 1), rowlength);
  size_t srcimgstride = srcrowstride * RDCMAX(RDCMAX(height, 1), imageheight);

  size_t destrowstride = pixelSize * width;
  size_t destimgstride = destrowstride * height;

  size_t elemSize = 1;
  switch(basetype)
  {
    case eGL_UNSIGNED_BYTE:
    case eGL_BYTE: elemSize = 1; break;
    case eGL_UNSIGNED_SHORT:
    case eGL_SHORT:
    case eGL_HALF_FLOAT: elemSize = 2; break;
    case eGL_UNSIGNED_INT:
    case eGL_INT:
    case eGL_FLOAT: elemSize = 4; break;
    case eGL_DOUBLE: elemSize = 8; break;
    default: break;
  }

  size_t allocsize = width * RDCMAX(1, height) * RDCMAX(1, depth) * pixelSize;
  byte *ret = new byte[allocsize];

  byte *source = pixels;

  if(skipPixels > 0)
    source += skipPixels * pixelSize;
  if(skipRows > 0 && height > 0)
    source += skipRows * srcrowstride;
  if(skipImages > 0 && depth > 0)
    source += skipImages * srcimgstride;

  size_t align = 1;
  // "If the number of bits per element is not 1, 2, 4, or 8 times the number of
  // bits in a GL ubyte, then k = nl for all values of a"
  // ie. alignment is only used for pixel formats of those pixel sizes.
  if(pixelSize == 1 || pixelSize == 2 || pixelSize == 4 || pixelSize == 8)
    align = RDCMAX(align, (size_t)alignment);

  byte *dest = ret;

  for(GLsizei img = 0; img < RDCMAX(1, depth); img++)
  {
    byte *rowsource = source;
    byte *rowdest = dest;

    for(GLsizei row = 0; row < RDCMAX(1, height); row++)
    {
      memcpy(rowdest, rowsource, destrowstride);

      if(swapBytes && elemSize > 1)
      {
        for(size_t el = 0; el < pixelSize * width; el += elemSize)
        {
          byte *element = rowdest + el;

          if(elemSize == 2)
          {
            std::swap(element[0], element[1]);
          }
          else if(elemSize == 4)
          {
            std::swap(element[0], element[3]);
            std::swap(element[1], element[2]);
          }
          else if(elemSize == 8)
          {
            std::swap(element[0], element[7]);
            std::swap(element[1], element[6]);
            std::swap(element[2], element[5]);
            std::swap(element[3], element[4]);
          }
        }
      }

      rowdest += destrowstride;
      rowsource += srcrowstride;
      rowsource = (byte *)AlignUp((size_t)rowsource, align);
    }

    dest += destimgstride;
    source += srcimgstride;
    source = (byte *)AlignUp((size_t)source, align);
  }

  return ret;
}

byte *PixelUnpackState::UnpackCompressed(byte *pixels, GLsizei width, GLsizei height, GLsizei depth,
                                         GLsizei &imageSize)
{
  int blockWidth = RDCMAX(compressedBlockWidth, 1);
  int blockHeight = RDCMAX(compressedBlockHeight, 1);
  int blockDepth = RDCMAX(compressedBlockDepth, 1);
  int blockSize = RDCMAX(compressedBlockSize, 1);

  RDCASSERT(compressedBlockWidth != 0);
  RDCASSERT(compressedBlockSize != 0);

  size_t blocksX = width ? (width + blockWidth - 1) / blockWidth : 0;
  size_t blocksY = height ? (height + blockHeight - 1) / blockHeight : 0;
  size_t blocksZ = depth ? (depth + blockDepth - 1) / blockDepth : 0;

  if(height != 0)
    RDCASSERT(compressedBlockHeight != 0);

  if(depth != 0)
    RDCASSERT(compressedBlockDepth != 0);

  blocksX = RDCMAX((size_t)1, blocksX);
  blocksY = RDCMAX((size_t)1, blocksY);
  blocksZ = RDCMAX((size_t)1, blocksZ);

  size_t srcrowstride = blockSize * RDCMAX(RDCMAX(width, blockWidth), rowlength) / blockWidth;
  size_t srcimgstride = srcrowstride * RDCMAX(RDCMAX(height, blockHeight), imageheight) / blockHeight;

  size_t destrowstride = blockSize * RDCMAX(width, blockWidth) / blockWidth;
  size_t destimgstride = destrowstride * RDCMAX(height, blockHeight) / blockHeight;

  size_t allocsize = blocksX * blocksY * blocksZ * blockSize;
  byte *ret = new byte[allocsize];

  imageSize = (GLsizei)allocsize;

  byte *source = pixels;

  if(skipPixels > 0)
    source += (skipPixels / blockWidth) * blockSize;
  if(skipRows > 0 && height > 0)
    source += (skipRows / compressedBlockHeight) * srcrowstride;
  if(skipImages > 0 && depth > 0)
    source += skipImages * srcimgstride;

  byte *dest = ret;

  for(GLsizei img = 0; img < RDCMAX(1, depth); img++)
  {
    byte *rowsource = source;
    byte *rowdest = dest;

    for(size_t row = 0; row < blocksY; row++)
    {
      memcpy(rowdest, rowsource, destrowstride);

      rowsource += srcrowstride;
      rowdest += destrowstride;
    }

    source += srcimgstride;
    dest += destimgstride;
  }

  return ret;
}

GLRenderState::GLRenderState(const GLHookSet *funcs, Serialiser *ser, LogState state)
    : m_Real(funcs), m_pSerialiser(ser), m_State(state)
{
  Clear();
}

GLRenderState::~GLRenderState()
{
}

void GLRenderState::MarkReferenced(WrappedOpenGL *gl, bool initial) const
{
  GLResourceManager *manager = gl->GetResourceManager();

  void *ctx = gl->GetCtx();

  for(GLuint i = 0; i < (GLuint)ARRAY_COUNT(Tex2D); i++)
  {
    manager->MarkResourceFrameReferenced(TextureRes(ctx, Tex1D[i]),
                                         initial ? eFrameRef_Unknown : eFrameRef_Read);
    manager->MarkResourceFrameReferenced(TextureRes(ctx, Tex2D[i]),
                                         initial ? eFrameRef_Unknown : eFrameRef_Read);
    manager->MarkResourceFrameReferenced(TextureRes(ctx, Tex3D[i]),
                                         initial ? eFrameRef_Unknown : eFrameRef_Read);
    manager->MarkResourceFrameReferenced(TextureRes(ctx, Tex1DArray[i]),
                                         initial ? eFrameRef_Unknown : eFrameRef_Read);
    manager->MarkResourceFrameReferenced(TextureRes(ctx, Tex2DArray[i]),
                                         initial ? eFrameRef_Unknown : eFrameRef_Read);
    manager->MarkResourceFrameReferenced(TextureRes(ctx, TexCubeArray[i]),
                                         initial ? eFrameRef_Unknown : eFrameRef_Read);
    manager->MarkResourceFrameReferenced(TextureRes(ctx, TexRect[i]),
                                         initial ? eFrameRef_Unknown : eFrameRef_Read);
    manager->MarkResourceFrameReferenced(TextureRes(ctx, TexBuffer[i]),
                                         initial ? eFrameRef_Unknown : eFrameRef_Read);
    manager->MarkResourceFrameReferenced(TextureRes(ctx, TexCube[i]),
                                         initial ? eFrameRef_Unknown : eFrameRef_Read);
    manager->MarkResourceFrameReferenced(TextureRes(ctx, Tex2DMS[i]),
                                         initial ? eFrameRef_Unknown : eFrameRef_Read);
    manager->MarkResourceFrameReferenced(TextureRes(ctx, Tex2DMSArray[i]),
                                         initial ? eFrameRef_Unknown : eFrameRef_Read);
    manager->MarkResourceFrameReferenced(SamplerRes(ctx, Samplers[i]),
                                         initial ? eFrameRef_Unknown : eFrameRef_Read);
  }

  for(GLuint i = 0; i < (GLuint)ARRAY_COUNT(Images); i++)
  {
    manager->MarkResourceFrameReferenced(TextureRes(ctx, Images[i].name),
                                         initial ? eFrameRef_Unknown : eFrameRef_ReadBeforeWrite);
    gl->AddMissingTrack(manager->GetID(TextureRes(ctx, Images[i].name)));
  }

  manager->MarkVAOReferenced(VertexArrayRes(ctx, VAO), initial ? eFrameRef_Unknown : eFrameRef_Read,
                             true);

  manager->MarkResourceFrameReferenced(FeedbackRes(ctx, FeedbackObj),
                                       initial ? eFrameRef_Unknown : eFrameRef_Read);

  manager->MarkResourceFrameReferenced(ProgramRes(ctx, Program),
                                       initial ? eFrameRef_Unknown : eFrameRef_Read);
  manager->MarkResourceFrameReferenced(ProgramPipeRes(ctx, Pipeline),
                                       initial ? eFrameRef_Unknown : eFrameRef_Read);

  // the pipeline correctly has program parents, but we must also mark the programs as frame
  // referenced so that their
  // initial contents will be serialised.
  GLResourceRecord *record = manager->GetResourceRecord(ProgramPipeRes(ctx, Pipeline));
  if(record)
    record->MarkParentsReferenced(manager, initial ? eFrameRef_Unknown : eFrameRef_Read);

  for(size_t i = 0; i < ARRAY_COUNT(BufferBindings); i++)
    manager->MarkResourceFrameReferenced(BufferRes(ctx, BufferBindings[i]),
                                         initial ? eFrameRef_Unknown : eFrameRef_Read);

  for(size_t i = 0; i < ARRAY_COUNT(AtomicCounter); i++)
    manager->MarkResourceFrameReferenced(BufferRes(ctx, AtomicCounter[i].name),
                                         initial ? eFrameRef_Unknown : eFrameRef_ReadBeforeWrite);

  for(size_t i = 0; i < ARRAY_COUNT(ShaderStorage); i++)
    manager->MarkResourceFrameReferenced(BufferRes(ctx, ShaderStorage[i].name),
                                         initial ? eFrameRef_Unknown : eFrameRef_ReadBeforeWrite);

  for(size_t i = 0; i < ARRAY_COUNT(TransformFeedback); i++)
    manager->MarkResourceFrameReferenced(BufferRes(ctx, TransformFeedback[i].name),
                                         initial ? eFrameRef_Unknown : eFrameRef_ReadBeforeWrite);

  for(size_t i = 0; i < ARRAY_COUNT(UniformBinding); i++)
    manager->MarkResourceFrameReferenced(BufferRes(ctx, UniformBinding[i].name),
                                         initial ? eFrameRef_Unknown : eFrameRef_Read);

  manager->MarkFBOReferenced(FramebufferRes(ctx, DrawFBO),
                             initial ? eFrameRef_Unknown : eFrameRef_ReadBeforeWrite);

  // if same FBO is bound to both targets, treat it as draw only
  if(ReadFBO != DrawFBO)
    manager->MarkFBOReferenced(FramebufferRes(ctx, ReadFBO),
                               initial ? eFrameRef_Unknown : eFrameRef_Read);
}

void GLRenderState::MarkDirty(WrappedOpenGL *gl)
{
  GLResourceManager *manager = gl->GetResourceManager();

  void *ctx = gl->GetCtx();

  GLint maxCount = 0;
  GLuint name = 0;

  if(HasExt[ARB_transform_feedback2])
  {
    m_Real->glGetIntegerv(eGL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &maxCount);

    for(GLint i = 0; i < maxCount; i++)
    {
      name = 0;
      m_Real->glGetIntegeri_v(eGL_TRANSFORM_FEEDBACK_BUFFER_BINDING, i, (GLint *)&name);

      if(name)
        manager->MarkDirtyResource(BufferRes(ctx, name));
    }
  }

  if(HasExt[ARB_shader_image_load_store])
  {
    m_Real->glGetIntegerv(eGL_MAX_IMAGE_UNITS, &maxCount);

    for(GLint i = 0; i < maxCount; i++)
    {
      name = 0;
      m_Real->glGetIntegeri_v(eGL_IMAGE_BINDING_NAME, i, (GLint *)&name);

      if(name)
        manager->MarkDirtyResource(TextureRes(ctx, name));
    }
  }

  if(HasExt[ARB_shader_atomic_counters])
  {
    m_Real->glGetIntegerv(eGL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &maxCount);

    for(GLint i = 0; i < maxCount; i++)
    {
      name = 0;
      m_Real->glGetIntegeri_v(eGL_ATOMIC_COUNTER_BUFFER_BINDING, i, (GLint *)&name);

      if(name)
        manager->MarkDirtyResource(BufferRes(ctx, name));
    }
  }

  if(HasExt[ARB_shader_storage_buffer_object])
  {
    m_Real->glGetIntegerv(eGL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &maxCount);

    for(GLint i = 0; i < maxCount; i++)
    {
      name = 0;
      m_Real->glGetIntegeri_v(eGL_SHADER_STORAGE_BUFFER_BINDING, i, (GLint *)&name);

      if(name)
        manager->MarkDirtyResource(BufferRes(ctx, name));
    }
  }

  m_Real->glGetIntegerv(eGL_MAX_COLOR_ATTACHMENTS, &maxCount);

  m_Real->glGetIntegerv(eGL_DRAW_FRAMEBUFFER_BINDING, (GLint *)&name);

  if(name)
  {
    GLenum type = eGL_TEXTURE;
    for(GLint i = 0; i < maxCount; i++)
    {
      m_Real->glGetFramebufferAttachmentParameteriv(
          eGL_DRAW_FRAMEBUFFER, GLenum(eGL_COLOR_ATTACHMENT0 + i),
          eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, (GLint *)&name);
      m_Real->glGetFramebufferAttachmentParameteriv(
          eGL_DRAW_FRAMEBUFFER, GLenum(eGL_COLOR_ATTACHMENT0 + i),
          eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, (GLint *)&type);

      if(name)
      {
        if(type == eGL_RENDERBUFFER)
          manager->MarkDirtyResource(RenderbufferRes(ctx, name));
        else
          manager->MarkDirtyResource(TextureRes(ctx, name));
      }
    }

    m_Real->glGetFramebufferAttachmentParameteriv(eGL_DRAW_FRAMEBUFFER, eGL_DEPTH_ATTACHMENT,
                                                  eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
                                                  (GLint *)&name);
    m_Real->glGetFramebufferAttachmentParameteriv(eGL_DRAW_FRAMEBUFFER, eGL_DEPTH_ATTACHMENT,
                                                  eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
                                                  (GLint *)&type);

    if(name)
    {
      if(type == eGL_RENDERBUFFER)
        manager->MarkDirtyResource(RenderbufferRes(ctx, name));
      else
        manager->MarkDirtyResource(TextureRes(ctx, name));
    }

    m_Real->glGetFramebufferAttachmentParameteriv(eGL_DRAW_FRAMEBUFFER, eGL_STENCIL_ATTACHMENT,
                                                  eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
                                                  (GLint *)&name);
    m_Real->glGetFramebufferAttachmentParameteriv(eGL_DRAW_FRAMEBUFFER, eGL_STENCIL_ATTACHMENT,
                                                  eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
                                                  (GLint *)&type);

    if(name)
    {
      if(type == eGL_RENDERBUFFER)
        manager->MarkDirtyResource(RenderbufferRes(ctx, name));
      else
        manager->MarkDirtyResource(TextureRes(ctx, name));
    }
  }
}

void GLRenderState::FetchState(void *ctx, WrappedOpenGL *gl)
{
  GLint boolread = 0;

  if(ctx == NULL)
  {
    ContextPresent = false;
    return;
  }

  {
    GLenum pnames[] = {
        eGL_CLIP_DISTANCE0,
        eGL_CLIP_DISTANCE1,
        eGL_CLIP_DISTANCE2,
        eGL_CLIP_DISTANCE3,
        eGL_CLIP_DISTANCE4,
        eGL_CLIP_DISTANCE5,
        eGL_CLIP_DISTANCE6,
        eGL_CLIP_DISTANCE7,
        eGL_COLOR_LOGIC_OP,
        eGL_CULL_FACE,
        eGL_DEPTH_CLAMP,
        eGL_DEPTH_TEST,
        eGL_DEPTH_BOUNDS_TEST_EXT,
        eGL_DITHER,
        eGL_FRAMEBUFFER_SRGB,
        eGL_LINE_SMOOTH,
        eGL_MULTISAMPLE,
        eGL_POLYGON_SMOOTH,
        eGL_POLYGON_OFFSET_FILL,
        eGL_POLYGON_OFFSET_LINE,
        eGL_POLYGON_OFFSET_POINT,
        eGL_PROGRAM_POINT_SIZE,
        eGL_PRIMITIVE_RESTART,
        eGL_PRIMITIVE_RESTART_FIXED_INDEX,
        eGL_SAMPLE_ALPHA_TO_COVERAGE,
        eGL_SAMPLE_ALPHA_TO_ONE,
        eGL_SAMPLE_COVERAGE,
        eGL_SAMPLE_MASK,
        eGL_SAMPLE_SHADING,
        eGL_RASTER_MULTISAMPLE_EXT,
        eGL_STENCIL_TEST,
        eGL_TEXTURE_CUBE_MAP_SEAMLESS,
        eGL_BLEND_ADVANCED_COHERENT_KHR,
        eGL_RASTERIZER_DISCARD,
    };

    RDCCOMPILE_ASSERT(ARRAY_COUNT(pnames) == eEnabled_Count, "Wrong number of pnames");

    for(GLuint i = 0; i < eEnabled_Count; i++)
    {
      if(pnames[i] == eGL_BLEND_ADVANCED_COHERENT_KHR && !HasExt[KHR_blend_equation_advanced_coherent])
      {
        Enabled[i] = true;
        continue;
      }

      if(pnames[i] == eGL_RASTER_MULTISAMPLE_EXT && !HasExt[EXT_raster_multisample])
      {
        Enabled[i] = false;
        continue;
      }

      if(pnames[i] == eGL_DEPTH_BOUNDS_TEST_EXT && !HasExt[EXT_depth_bounds_test])
      {
        Enabled[i] = false;
        continue;
      }

      if(pnames[i] == eGL_SAMPLE_SHADING && !HasExt[ARB_sample_shading])
      {
        Enabled[i] = false;
        continue;
      }

      if(pnames[i] == eGL_PRIMITIVE_RESTART_FIXED_INDEX && !HasExt[ARB_ES3_compatibility])
      {
        Enabled[i] = false;
        continue;
      }

      Enabled[i] = (m_Real->glIsEnabled(pnames[i]) == GL_TRUE);
    }
  }

  m_Real->glGetIntegerv(eGL_ACTIVE_TEXTURE, (GLint *)&ActiveTexture);

  GLuint maxTextures = 0;
  m_Real->glGetIntegerv(eGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, (GLint *)&maxTextures);

  RDCCOMPILE_ASSERT(
      sizeof(Tex1D) == sizeof(Tex2D) && sizeof(Tex2D) == sizeof(Tex3D) &&
          sizeof(Tex3D) == sizeof(Tex1DArray) && sizeof(Tex1DArray) == sizeof(Tex2DArray) &&
          sizeof(Tex2DArray) == sizeof(TexCubeArray) && sizeof(TexCubeArray) == sizeof(TexRect) &&
          sizeof(TexRect) == sizeof(TexBuffer) && sizeof(TexBuffer) == sizeof(TexCube) &&
          sizeof(TexCube) == sizeof(Tex2DMS) && sizeof(Tex2DMS) == sizeof(Tex2DMSArray) &&
          sizeof(Tex2DMSArray) == sizeof(Samplers),
      "All texture arrays should be identically sized");

  for(GLuint i = 0; i < RDCMIN(maxTextures, (GLuint)ARRAY_COUNT(Tex2D)); i++)
  {
    m_Real->glActiveTexture(GLenum(eGL_TEXTURE0 + i));
    m_Real->glGetIntegerv(eGL_TEXTURE_BINDING_1D, (GLint *)&Tex1D[i]);
    m_Real->glGetIntegerv(eGL_TEXTURE_BINDING_2D, (GLint *)&Tex2D[i]);
    m_Real->glGetIntegerv(eGL_TEXTURE_BINDING_3D, (GLint *)&Tex3D[i]);
    m_Real->glGetIntegerv(eGL_TEXTURE_BINDING_1D_ARRAY, (GLint *)&Tex1DArray[i]);
    m_Real->glGetIntegerv(eGL_TEXTURE_BINDING_2D_ARRAY, (GLint *)&Tex2DArray[i]);
    m_Real->glGetIntegerv(eGL_TEXTURE_BINDING_CUBE_MAP, (GLint *)&TexCube[i]);
    m_Real->glGetIntegerv(eGL_TEXTURE_BINDING_RECTANGLE, (GLint *)&TexRect[i]);
    m_Real->glGetIntegerv(eGL_TEXTURE_BINDING_BUFFER, (GLint *)&TexBuffer[i]);
    m_Real->glGetIntegerv(eGL_TEXTURE_BINDING_2D_MULTISAMPLE, (GLint *)&Tex2DMS[i]);
    m_Real->glGetIntegerv(eGL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY, (GLint *)&Tex2DMSArray[i]);

    if(HasExt[ARB_texture_cube_map_array])
      m_Real->glGetIntegerv(eGL_TEXTURE_BINDING_CUBE_MAP_ARRAY, (GLint *)&TexCubeArray[i]);
    else
      TexCubeArray[i] = 0;

    if(HasExt[ARB_sampler_objects])
      m_Real->glGetIntegerv(eGL_SAMPLER_BINDING, (GLint *)&Samplers[i]);
    else
      Samplers[i] = 0;
  }

  if(HasExt[ARB_shader_image_load_store])
  {
    GLuint maxImages = 0;
    m_Real->glGetIntegerv(eGL_MAX_IMAGE_UNITS, (GLint *)&maxImages);

    for(GLuint i = 0; i < RDCMIN(maxImages, (GLuint)ARRAY_COUNT(Images)); i++)
    {
      GLboolean layered = GL_FALSE;

      m_Real->glGetIntegeri_v(eGL_IMAGE_BINDING_NAME, i, (GLint *)&Images[i].name);
      m_Real->glGetIntegeri_v(eGL_IMAGE_BINDING_LEVEL, i, (GLint *)&Images[i].level);
      m_Real->glGetIntegeri_v(eGL_IMAGE_BINDING_ACCESS, i, (GLint *)&Images[i].access);
      m_Real->glGetIntegeri_v(eGL_IMAGE_BINDING_FORMAT, i, (GLint *)&Images[i].format);
      m_Real->glGetBooleani_v(eGL_IMAGE_BINDING_LAYERED, i, &layered);
      Images[i].layered = (layered == GL_TRUE);
      if(layered)
        m_Real->glGetIntegeri_v(eGL_IMAGE_BINDING_LAYER, i, (GLint *)&Images[i].layer);
    }
  }

  m_Real->glActiveTexture(ActiveTexture);

  m_Real->glGetIntegerv(eGL_VERTEX_ARRAY_BINDING, (GLint *)&VAO);

  if(HasExt[ARB_transform_feedback2])
    m_Real->glGetIntegerv(eGL_TRANSFORM_FEEDBACK_BINDING, (GLint *)&FeedbackObj);

  // the spec says that you can only query for the format that was previously set, or you get
  // undefined results. Ie. if someone set ints, this might return anything. However there's also
  // no way to query for the type so we just have to hope for the best and hope most people are
  // sane and don't use these except for a default "all 0s" attrib.

  GLuint maxNumAttribs = 0;
  m_Real->glGetIntegerv(eGL_MAX_VERTEX_ATTRIBS, (GLint *)&maxNumAttribs);
  for(GLuint i = 0; i < RDCMIN(maxNumAttribs, (GLuint)ARRAY_COUNT(GenericVertexAttribs)); i++)
    m_Real->glGetVertexAttribfv(i, eGL_CURRENT_VERTEX_ATTRIB, &GenericVertexAttribs[i].x);

  m_Real->glGetFloatv(eGL_POINT_FADE_THRESHOLD_SIZE, &PointFadeThresholdSize);
  m_Real->glGetIntegerv(eGL_POINT_SPRITE_COORD_ORIGIN, (GLint *)&PointSpriteOrigin);
  m_Real->glGetFloatv(eGL_LINE_WIDTH, &LineWidth);
  m_Real->glGetFloatv(eGL_POINT_SIZE, &PointSize);

  m_Real->glGetIntegerv(eGL_PRIMITIVE_RESTART_INDEX, (GLint *)&PrimitiveRestartIndex);
  if(HasExt[ARB_clip_control])
  {
    m_Real->glGetIntegerv(eGL_CLIP_ORIGIN, (GLint *)&ClipOrigin);
    m_Real->glGetIntegerv(eGL_CLIP_DEPTH_MODE, (GLint *)&ClipDepth);
  }
  else
  {
    ClipOrigin = eGL_LOWER_LEFT;
    ClipDepth = eGL_NEGATIVE_ONE_TO_ONE;
  }
  m_Real->glGetIntegerv(eGL_PROVOKING_VERTEX, (GLint *)&ProvokingVertex);

  m_Real->glGetIntegerv(eGL_CURRENT_PROGRAM, (GLint *)&Program);

  if(HasExt[ARB_separate_shader_objects])
    m_Real->glGetIntegerv(eGL_PROGRAM_PIPELINE_BINDING, (GLint *)&Pipeline);
  else
    Pipeline = 0;

  const GLenum shs[] = {
      eGL_VERTEX_SHADER,   eGL_TESS_CONTROL_SHADER, eGL_TESS_EVALUATION_SHADER,
      eGL_GEOMETRY_SHADER, eGL_FRAGMENT_SHADER,     eGL_COMPUTE_SHADER,
  };

  if(HasExt[ARB_shader_subroutine])
  {
    RDCCOMPILE_ASSERT(ARRAY_COUNT(shs) == ARRAY_COUNT(Subroutines),
                      "Subroutine array not the right size");

    for(size_t s = 0; s < ARRAY_COUNT(shs); s++)
    {
      if(shs[s] == eGL_COMPUTE_SHADER && !HasExt[ARB_compute_shader])
        continue;

      if((shs[s] == eGL_TESS_CONTROL_SHADER || shs[s] == eGL_TESS_EVALUATION_SHADER) &&
         !HasExt[ARB_tessellation_shader])
        continue;

      GLuint prog = Program;
      if(prog == 0 && Pipeline != 0)
      {
        // can't query for GL_COMPUTE_SHADER on some AMD cards
        if(shs[s] != eGL_COMPUTE_SHADER || !VendorCheck[VendorCheck_AMD_pipeline_compute_query])
          m_Real->glGetProgramPipelineiv(Pipeline, shs[s], (GLint *)&prog);
      }

      if(prog == 0)
        continue;

      m_Real->glGetProgramStageiv(prog, shs[s], eGL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS,
                                  &Subroutines[s].numSubroutines);

      for(GLint i = 0; i < Subroutines[s].numSubroutines; i++)
        m_Real->glGetUniformSubroutineuiv(shs[s], i, &Subroutines[s].Values[0]);
    }
  }
  else
  {
    RDCEraseEl(Subroutines);
  }

  m_Real->glGetIntegerv(eGL_ARRAY_BUFFER_BINDING, (GLint *)&BufferBindings[eBufIdx_Array]);
  m_Real->glGetIntegerv(eGL_COPY_READ_BUFFER_BINDING, (GLint *)&BufferBindings[eBufIdx_Copy_Read]);
  m_Real->glGetIntegerv(eGL_COPY_WRITE_BUFFER_BINDING, (GLint *)&BufferBindings[eBufIdx_Copy_Write]);
  m_Real->glGetIntegerv(eGL_PIXEL_PACK_BUFFER_BINDING, (GLint *)&BufferBindings[eBufIdx_Pixel_Pack]);
  m_Real->glGetIntegerv(eGL_PIXEL_UNPACK_BUFFER_BINDING,
                        (GLint *)&BufferBindings[eBufIdx_Pixel_Unpack]);
  m_Real->glGetIntegerv(eGL_TEXTURE_BUFFER_BINDING, (GLint *)&BufferBindings[eBufIdx_Texture]);

  if(HasExt[ARB_draw_indirect])
    m_Real->glGetIntegerv(eGL_DRAW_INDIRECT_BUFFER_BINDING,
                          (GLint *)&BufferBindings[eBufIdx_Draw_Indirect]);
  if(HasExt[ARB_compute_shader])
    m_Real->glGetIntegerv(eGL_DISPATCH_INDIRECT_BUFFER_BINDING,
                          (GLint *)&BufferBindings[eBufIdx_Dispatch_Indirect]);
  if(HasExt[ARB_query_buffer_object])
    m_Real->glGetIntegerv(eGL_QUERY_BUFFER_BINDING, (GLint *)&BufferBindings[eBufIdx_Query]);
  if(HasExt[ARB_indirect_parameters])
    m_Real->glGetIntegerv(eGL_PARAMETER_BUFFER_BINDING_ARB,
                          (GLint *)&BufferBindings[eBufIdx_Parameter]);

  struct
  {
    IdxRangeBuffer *bufs;
    int count;
    GLenum binding;
    GLenum start;
    GLenum size;
    GLenum maxcount;
  } idxBufs[] = {
      {
          AtomicCounter, ARRAY_COUNT(AtomicCounter), eGL_ATOMIC_COUNTER_BUFFER_BINDING,
          eGL_ATOMIC_COUNTER_BUFFER_START, eGL_ATOMIC_COUNTER_BUFFER_SIZE,
          eGL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS,
      },
      {
          ShaderStorage, ARRAY_COUNT(ShaderStorage), eGL_SHADER_STORAGE_BUFFER_BINDING,
          eGL_SHADER_STORAGE_BUFFER_START, eGL_SHADER_STORAGE_BUFFER_SIZE,
          eGL_MAX_SHADER_STORAGE_BUFFER_BINDINGS,
      },
      {
          TransformFeedback, ARRAY_COUNT(TransformFeedback), eGL_TRANSFORM_FEEDBACK_BUFFER_BINDING,
          eGL_TRANSFORM_FEEDBACK_BUFFER_START, eGL_TRANSFORM_FEEDBACK_BUFFER_SIZE,
          eGL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
      },
      {
          UniformBinding, ARRAY_COUNT(UniformBinding), eGL_UNIFORM_BUFFER_BINDING,
          eGL_UNIFORM_BUFFER_START, eGL_UNIFORM_BUFFER_SIZE, eGL_MAX_UNIFORM_BUFFER_BINDINGS,
      },
  };

  for(GLuint b = 0; b < (GLuint)ARRAY_COUNT(idxBufs); b++)
  {
    if(idxBufs[b].binding == eGL_ATOMIC_COUNTER_BUFFER_BINDING && !HasExt[ARB_shader_atomic_counters])
      continue;

    if(idxBufs[b].binding == eGL_SHADER_STORAGE_BUFFER_BINDING &&
       !HasExt[ARB_shader_storage_buffer_object])
      continue;

    if(idxBufs[b].binding == eGL_TRANSFORM_FEEDBACK_BUFFER_BINDING && !HasExt[ARB_transform_feedback2])
      continue;

    GLint maxCount = 0;
    m_Real->glGetIntegerv(idxBufs[b].maxcount, &maxCount);
    for(int i = 0; i < idxBufs[b].count && i < maxCount; i++)
    {
      m_Real->glGetIntegeri_v(idxBufs[b].binding, i, (GLint *)&idxBufs[b].bufs[i].name);
      m_Real->glGetInteger64i_v(idxBufs[b].start, i, (GLint64 *)&idxBufs[b].bufs[i].start);
      m_Real->glGetInteger64i_v(idxBufs[b].size, i, (GLint64 *)&idxBufs[b].bufs[i].size);
    }
  }

  GLuint maxDraws = 0;
  m_Real->glGetIntegerv(eGL_MAX_DRAW_BUFFERS, (GLint *)&maxDraws);

  if(HasExt[ARB_draw_buffers_blend])
  {
    for(GLuint i = 0; i < RDCMIN(maxDraws, (GLuint)ARRAY_COUNT(Blends)); i++)
    {
      m_Real->glGetIntegeri_v(eGL_BLEND_EQUATION_RGB, i, (GLint *)&Blends[i].EquationRGB);
      m_Real->glGetIntegeri_v(eGL_BLEND_EQUATION_ALPHA, i, (GLint *)&Blends[i].EquationAlpha);

      m_Real->glGetIntegeri_v(eGL_BLEND_SRC_RGB, i, (GLint *)&Blends[i].SourceRGB);
      m_Real->glGetIntegeri_v(eGL_BLEND_SRC_ALPHA, i, (GLint *)&Blends[i].SourceAlpha);

      m_Real->glGetIntegeri_v(eGL_BLEND_DST_RGB, i, (GLint *)&Blends[i].DestinationRGB);
      m_Real->glGetIntegeri_v(eGL_BLEND_DST_ALPHA, i, (GLint *)&Blends[i].DestinationAlpha);

      Blends[i].Enabled = (m_Real->glIsEnabledi(eGL_BLEND, i) == GL_TRUE);
    }
  }
  else
  {
    // if we don't have separate blending, then replicate across all from 0

    m_Real->glGetIntegerv(eGL_BLEND_EQUATION_RGB, (GLint *)&Blends[0].EquationRGB);
    m_Real->glGetIntegerv(eGL_BLEND_EQUATION_ALPHA, (GLint *)&Blends[0].EquationAlpha);

    m_Real->glGetIntegerv(eGL_BLEND_SRC_RGB, (GLint *)&Blends[0].SourceRGB);
    m_Real->glGetIntegerv(eGL_BLEND_SRC_ALPHA, (GLint *)&Blends[0].SourceAlpha);

    m_Real->glGetIntegerv(eGL_BLEND_DST_RGB, (GLint *)&Blends[0].DestinationRGB);
    m_Real->glGetIntegerv(eGL_BLEND_DST_ALPHA, (GLint *)&Blends[0].DestinationAlpha);

    Blends[0].Enabled = (m_Real->glIsEnabled(eGL_BLEND) == GL_TRUE);

    for(GLuint i = 1; i < (GLuint)ARRAY_COUNT(Blends); i++)
      memcpy(&Blends[i], &Blends[0], sizeof(Blends[i]));
  }

  m_Real->glGetFloatv(eGL_BLEND_COLOR, &BlendColor[0]);

  if(HasExt[ARB_viewport_array])
  {
    GLuint maxViews = 0;
    m_Real->glGetIntegerv(eGL_MAX_VIEWPORTS, (GLint *)&maxViews);

    for(GLuint i = 0; i < RDCMIN(maxViews, (GLuint)ARRAY_COUNT(Viewports)); i++)
      m_Real->glGetFloati_v(eGL_VIEWPORT, i, &Viewports[i].x);

    for(GLuint i = 0; i < RDCMIN(maxViews, (GLuint)ARRAY_COUNT(Scissors)); i++)
    {
      m_Real->glGetIntegeri_v(eGL_SCISSOR_BOX, i, &Scissors[i].x);
      Scissors[i].enabled = (m_Real->glIsEnabledi(eGL_SCISSOR_TEST, i) == GL_TRUE);
    }

    for(GLuint i = 0; i < RDCMIN(maxViews, (GLuint)ARRAY_COUNT(DepthRanges)); i++)
      m_Real->glGetDoublei_v(eGL_DEPTH_RANGE, i, &DepthRanges[i].nearZ);
  }
  else
  {
    // if we don't have separate viewport/etc, then replicate across all from 0
    // note that the same extension introduced indexed viewports, scissors and
    // depth ranges. Convenient!

    m_Real->glGetFloatv(eGL_VIEWPORT, &Viewports[0].x);
    m_Real->glGetIntegerv(eGL_SCISSOR_BOX, &Scissors[0].x);
    Scissors[0].enabled = (m_Real->glIsEnabled(eGL_SCISSOR_TEST) == GL_TRUE);
    m_Real->glGetDoublev(eGL_DEPTH_RANGE, &DepthRanges[0].nearZ);

    for(GLuint i = 1; i < (GLuint)ARRAY_COUNT(Viewports); i++)
      memcpy(&Viewports[i], &Viewports[0], sizeof(Viewports[i]));

    for(GLuint i = 1; i < (GLuint)ARRAY_COUNT(Scissors); i++)
      memcpy(&Scissors[i], &Scissors[0], sizeof(Scissors[i]));

    for(GLuint i = 1; i < (GLuint)ARRAY_COUNT(DepthRanges); i++)
      memcpy(&DepthRanges[i], &DepthRanges[0], sizeof(DepthRanges[i]));
  }

  m_Real->glGetIntegerv(eGL_DRAW_FRAMEBUFFER_BINDING, (GLint *)&DrawFBO);
  m_Real->glGetIntegerv(eGL_READ_FRAMEBUFFER_BINDING, (GLint *)&ReadFBO);

  m_Real->glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, 0);
  m_Real->glBindFramebuffer(eGL_READ_FRAMEBUFFER, 0);

  for(GLuint i = 0; i < RDCMIN(maxDraws, (GLuint)ARRAY_COUNT(DrawBuffers)); i++)
    m_Real->glGetIntegerv(GLenum(eGL_DRAW_BUFFER0 + i), (GLint *)&DrawBuffers[i]);

  m_Real->glGetIntegerv(eGL_READ_BUFFER, (GLint *)&ReadBuffer);

  m_Real->glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, DrawFBO);
  m_Real->glBindFramebuffer(eGL_READ_FRAMEBUFFER, ReadFBO);

  m_Real->glGetIntegerv(eGL_FRAGMENT_SHADER_DERIVATIVE_HINT, (GLint *)&Hints.Derivatives);
  m_Real->glGetIntegerv(eGL_LINE_SMOOTH_HINT, (GLint *)&Hints.LineSmooth);
  m_Real->glGetIntegerv(eGL_POLYGON_SMOOTH_HINT, (GLint *)&Hints.PolySmooth);
  m_Real->glGetIntegerv(eGL_TEXTURE_COMPRESSION_HINT, (GLint *)&Hints.TexCompression);

  m_Real->glGetBooleanv(eGL_DEPTH_WRITEMASK, &DepthWriteMask);
  m_Real->glGetFloatv(eGL_DEPTH_CLEAR_VALUE, &DepthClearValue);
  m_Real->glGetIntegerv(eGL_DEPTH_FUNC, (GLint *)&DepthFunc);

  if(HasExt[EXT_depth_bounds_test])
  {
    m_Real->glGetDoublev(eGL_DEPTH_BOUNDS_TEST_EXT, &DepthBounds.nearZ);
  }
  else
  {
    DepthBounds.nearZ = 0.0f;
    DepthBounds.farZ = 1.0f;
  }

  {
    m_Real->glGetIntegerv(eGL_STENCIL_FUNC, (GLint *)&StencilFront.func);
    m_Real->glGetIntegerv(eGL_STENCIL_BACK_FUNC, (GLint *)&StencilBack.func);

    m_Real->glGetIntegerv(eGL_STENCIL_REF, (GLint *)&StencilFront.ref);
    m_Real->glGetIntegerv(eGL_STENCIL_BACK_REF, (GLint *)&StencilBack.ref);

    GLint maskval;
    m_Real->glGetIntegerv(eGL_STENCIL_VALUE_MASK, &maskval);
    StencilFront.valuemask = uint8_t(maskval & 0xff);
    m_Real->glGetIntegerv(eGL_STENCIL_BACK_VALUE_MASK, &maskval);
    StencilBack.valuemask = uint8_t(maskval & 0xff);

    m_Real->glGetIntegerv(eGL_STENCIL_WRITEMASK, &maskval);
    StencilFront.writemask = uint8_t(maskval & 0xff);
    m_Real->glGetIntegerv(eGL_STENCIL_BACK_WRITEMASK, &maskval);
    StencilBack.writemask = uint8_t(maskval & 0xff);

    m_Real->glGetIntegerv(eGL_STENCIL_FAIL, (GLint *)&StencilFront.stencilFail);
    m_Real->glGetIntegerv(eGL_STENCIL_BACK_FAIL, (GLint *)&StencilBack.stencilFail);

    m_Real->glGetIntegerv(eGL_STENCIL_PASS_DEPTH_FAIL, (GLint *)&StencilFront.depthFail);
    m_Real->glGetIntegerv(eGL_STENCIL_BACK_PASS_DEPTH_FAIL, (GLint *)&StencilBack.depthFail);

    m_Real->glGetIntegerv(eGL_STENCIL_PASS_DEPTH_PASS, (GLint *)&StencilFront.pass);
    m_Real->glGetIntegerv(eGL_STENCIL_BACK_PASS_DEPTH_PASS, (GLint *)&StencilBack.pass);
  }

  m_Real->glGetIntegerv(eGL_STENCIL_CLEAR_VALUE, (GLint *)&StencilClearValue);

  for(GLuint i = 0; i < RDCMIN(maxDraws, (GLuint)ARRAY_COUNT(ColorMasks)); i++)
    m_Real->glGetBooleanv(eGL_COLOR_WRITEMASK, &ColorMasks[i].red);

  m_Real->glGetIntegeri_v(eGL_SAMPLE_MASK_VALUE, 0, (GLint *)&SampleMask[0]);
  m_Real->glGetIntegerv(eGL_SAMPLE_COVERAGE_VALUE, (GLint *)&SampleCoverage);
  m_Real->glGetIntegerv(eGL_SAMPLE_COVERAGE_INVERT, (GLint *)&boolread);
  SampleCoverageInvert = (boolread != 0);

  if(HasExt[ARB_sample_shading])
    m_Real->glGetFloatv(eGL_MIN_SAMPLE_SHADING_VALUE, &MinSampleShading);
  else
    MinSampleShading = 0;

  if(HasExt[EXT_raster_multisample])
    m_Real->glGetIntegerv(eGL_RASTER_SAMPLES_EXT, (GLint *)&RasterSamples);
  else
    RasterSamples = 0;

  if(HasExt[EXT_raster_multisample])
    m_Real->glGetIntegerv(eGL_RASTER_FIXED_SAMPLE_LOCATIONS_EXT, (GLint *)&RasterFixed);
  else
    RasterFixed = false;

  m_Real->glGetIntegerv(eGL_LOGIC_OP_MODE, (GLint *)&LogicOp);

  m_Real->glGetFloatv(eGL_COLOR_CLEAR_VALUE, &ColorClearValue.red);

  if(HasExt[ARB_tessellation_shader])
  {
    m_Real->glGetIntegerv(eGL_PATCH_VERTICES, &PatchParams.numVerts);
    m_Real->glGetFloatv(eGL_PATCH_DEFAULT_INNER_LEVEL, &PatchParams.defaultInnerLevel[0]);
    m_Real->glGetFloatv(eGL_PATCH_DEFAULT_OUTER_LEVEL, &PatchParams.defaultOuterLevel[0]);
  }
  else
  {
    PatchParams.numVerts = 3;
    PatchParams.defaultInnerLevel[0] = PatchParams.defaultInnerLevel[1] = 1.0f;
    PatchParams.defaultOuterLevel[0] = PatchParams.defaultOuterLevel[1] =
        PatchParams.defaultOuterLevel[2] = PatchParams.defaultOuterLevel[3] = 1.0f;
  }

  if(!VendorCheck[VendorCheck_AMD_polygon_mode_query])
  {
    // This was listed in docs as enumeration[2] even though polygon mode can't be set independently
    // for front
    // and back faces for a while, so pass large enough array to be sure.
    // AMD driver claims this doesn't exist anymore in core, so don't return any value, set to
    // default GL_FILL to be safe
    GLenum dummy[2] = {eGL_FILL, eGL_FILL};
    m_Real->glGetIntegerv(eGL_POLYGON_MODE, (GLint *)&dummy);
    PolygonMode = dummy[0];
  }
  else
  {
    PolygonMode = eGL_FILL;
  }

  m_Real->glGetFloatv(eGL_POLYGON_OFFSET_FACTOR, &PolygonOffset[0]);
  m_Real->glGetFloatv(eGL_POLYGON_OFFSET_UNITS, &PolygonOffset[1]);
  if(HasExt[EXT_polygon_offset_clamp])
    m_Real->glGetFloatv(eGL_POLYGON_OFFSET_CLAMP_EXT, &PolygonOffset[2]);
  else
    PolygonOffset[2] = 0.0f;

  m_Real->glGetIntegerv(eGL_FRONT_FACE, (GLint *)&FrontFace);
  m_Real->glGetIntegerv(eGL_CULL_FACE_MODE, (GLint *)&CullFace);

  Unpack.Fetch(m_Real, true);

  ClearGLErrors(*m_Real);
}

void GLRenderState::ApplyState(void *ctx, WrappedOpenGL *gl)
{
  if(!ContextPresent || ctx == NULL)
    return;

  {
    GLenum pnames[] = {
        eGL_CLIP_DISTANCE0,
        eGL_CLIP_DISTANCE1,
        eGL_CLIP_DISTANCE2,
        eGL_CLIP_DISTANCE3,
        eGL_CLIP_DISTANCE4,
        eGL_CLIP_DISTANCE5,
        eGL_CLIP_DISTANCE6,
        eGL_CLIP_DISTANCE7,
        eGL_COLOR_LOGIC_OP,
        eGL_CULL_FACE,
        eGL_DEPTH_CLAMP,
        eGL_DEPTH_TEST,
        eGL_DEPTH_BOUNDS_TEST_EXT,
        eGL_DITHER,
        eGL_FRAMEBUFFER_SRGB,
        eGL_LINE_SMOOTH,
        eGL_MULTISAMPLE,
        eGL_POLYGON_SMOOTH,
        eGL_POLYGON_OFFSET_FILL,
        eGL_POLYGON_OFFSET_LINE,
        eGL_POLYGON_OFFSET_POINT,
        eGL_PROGRAM_POINT_SIZE,
        eGL_PRIMITIVE_RESTART,
        eGL_PRIMITIVE_RESTART_FIXED_INDEX,
        eGL_SAMPLE_ALPHA_TO_COVERAGE,
        eGL_SAMPLE_ALPHA_TO_ONE,
        eGL_SAMPLE_COVERAGE,
        eGL_SAMPLE_MASK,
        eGL_SAMPLE_SHADING,
        eGL_RASTER_MULTISAMPLE_EXT,
        eGL_STENCIL_TEST,
        eGL_TEXTURE_CUBE_MAP_SEAMLESS,
        eGL_BLEND_ADVANCED_COHERENT_KHR,
        eGL_RASTERIZER_DISCARD,
    };

    RDCCOMPILE_ASSERT(ARRAY_COUNT(pnames) == eEnabled_Count, "Wrong number of pnames");

    for(GLuint i = 0; i < eEnabled_Count; i++)
    {
      if(pnames[i] == eGL_BLEND_ADVANCED_COHERENT_KHR && !HasExt[KHR_blend_equation_advanced_coherent])
        continue;

      if(pnames[i] == eGL_RASTER_MULTISAMPLE_EXT && !HasExt[EXT_raster_multisample])
        continue;

      if(pnames[i] == eGL_DEPTH_BOUNDS_TEST_EXT && !HasExt[EXT_depth_bounds_test])
        continue;

      if(pnames[i] == eGL_SAMPLE_SHADING && !HasExt[ARB_sample_shading])
        continue;

      if(pnames[i] == eGL_PRIMITIVE_RESTART_FIXED_INDEX && !HasExt[ARB_ES3_compatibility])
        continue;

      if(Enabled[i])
        m_Real->glEnable(pnames[i]);
      else
        m_Real->glDisable(pnames[i]);
    }
  }

  GLuint maxTextures = 0;
  m_Real->glGetIntegerv(eGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, (GLint *)&maxTextures);

  for(GLuint i = 0; i < RDCMIN(maxTextures, (GLuint)ARRAY_COUNT(Tex2D)); i++)
  {
    m_Real->glActiveTexture(GLenum(eGL_TEXTURE0 + i));
    m_Real->glBindTexture(eGL_TEXTURE_1D, Tex1D[i]);
    m_Real->glBindTexture(eGL_TEXTURE_2D, Tex2D[i]);
    m_Real->glBindTexture(eGL_TEXTURE_3D, Tex3D[i]);
    m_Real->glBindTexture(eGL_TEXTURE_1D_ARRAY, Tex1DArray[i]);
    m_Real->glBindTexture(eGL_TEXTURE_2D_ARRAY, Tex2DArray[i]);
    m_Real->glBindTexture(eGL_TEXTURE_RECTANGLE, TexRect[i]);
    m_Real->glBindTexture(eGL_TEXTURE_BUFFER, TexBuffer[i]);
    m_Real->glBindTexture(eGL_TEXTURE_CUBE_MAP, TexCube[i]);
    m_Real->glBindTexture(eGL_TEXTURE_2D_MULTISAMPLE, Tex2DMS[i]);
    m_Real->glBindTexture(eGL_TEXTURE_2D_MULTISAMPLE_ARRAY, Tex2DMSArray[i]);

    if(HasExt[ARB_sampler_objects])
      m_Real->glBindSampler(i, Samplers[i]);

    if(HasExt[ARB_texture_cube_map_array])
      m_Real->glBindTexture(eGL_TEXTURE_CUBE_MAP_ARRAY, TexCubeArray[i]);
  }

  if(HasExt[ARB_shader_image_load_store])
  {
    GLuint maxImages = 0;
    m_Real->glGetIntegerv(eGL_MAX_IMAGE_UNITS, (GLint *)&maxImages);

    for(GLuint i = 0; i < RDCMIN(maxImages, (GLuint)ARRAY_COUNT(Images)); i++)
    {
      // use sanitised parameters when no image is bound
      if(Images[i].name == 0)
        m_Real->glBindImageTexture(i, 0, 0, GL_FALSE, 0, eGL_READ_ONLY, eGL_R8);
      else
        m_Real->glBindImageTexture(i, Images[i].name, (GLint)Images[i].level, Images[i].layered,
                                   (GLint)Images[i].layer, Images[i].access, Images[i].format);
    }
  }

  m_Real->glActiveTexture(ActiveTexture);

  m_Real->glBindVertexArray(VAO);
  if(HasExt[ARB_transform_feedback2])
    m_Real->glBindTransformFeedback(eGL_TRANSFORM_FEEDBACK, FeedbackObj);

  // See FetchState(). The spec says that you have to SET the right format for the shader too,
  // but we couldn't query for the format so we can't set it here.
  GLuint maxNumAttribs = 0;
  m_Real->glGetIntegerv(eGL_MAX_VERTEX_ATTRIBS, (GLint *)&maxNumAttribs);
  for(GLuint i = 0; i < RDCMIN(maxNumAttribs, (GLuint)ARRAY_COUNT(GenericVertexAttribs)); i++)
    m_Real->glVertexAttrib4fv(i, &GenericVertexAttribs[i].x);

  m_Real->glPointParameterf(eGL_POINT_FADE_THRESHOLD_SIZE, PointFadeThresholdSize);
  m_Real->glPointParameteri(eGL_POINT_SPRITE_COORD_ORIGIN, (GLint)PointSpriteOrigin);
  m_Real->glLineWidth(LineWidth);
  m_Real->glPointSize(PointSize);

  m_Real->glPrimitiveRestartIndex(PrimitiveRestartIndex);
  if(m_Real->glClipControl && HasExt[ARB_clip_control])
    m_Real->glClipControl(ClipOrigin, ClipDepth);
  m_Real->glProvokingVertex(ProvokingVertex);

  m_Real->glUseProgram(Program);
  if(HasExt[ARB_separate_shader_objects])
    m_Real->glBindProgramPipeline(Pipeline);

  GLenum shs[] = {eGL_VERTEX_SHADER,   eGL_TESS_CONTROL_SHADER, eGL_TESS_EVALUATION_SHADER,
                  eGL_GEOMETRY_SHADER, eGL_FRAGMENT_SHADER,     eGL_COMPUTE_SHADER};

  RDCCOMPILE_ASSERT(ARRAY_COUNT(shs) == ARRAY_COUNT(Subroutines),
                    "Subroutine array not the right size");
  for(size_t s = 0; s < ARRAY_COUNT(shs); s++)
  {
    if(shs[s] == eGL_COMPUTE_SHADER && !HasExt[ARB_compute_shader])
      continue;

    if((shs[s] == eGL_TESS_CONTROL_SHADER || shs[s] == eGL_TESS_EVALUATION_SHADER) &&
       !HasExt[ARB_tessellation_shader])
      continue;

    if(Subroutines[s].numSubroutines > 0)
      m_Real->glUniformSubroutinesuiv(shs[s], Subroutines[s].numSubroutines, Subroutines[s].Values);
  }

  m_Real->glBindBuffer(eGL_ARRAY_BUFFER, BufferBindings[eBufIdx_Array]);
  m_Real->glBindBuffer(eGL_COPY_READ_BUFFER, BufferBindings[eBufIdx_Copy_Read]);
  m_Real->glBindBuffer(eGL_COPY_WRITE_BUFFER, BufferBindings[eBufIdx_Copy_Write]);
  m_Real->glBindBuffer(eGL_PIXEL_PACK_BUFFER, BufferBindings[eBufIdx_Pixel_Pack]);
  m_Real->glBindBuffer(eGL_PIXEL_UNPACK_BUFFER, BufferBindings[eBufIdx_Pixel_Unpack]);
  m_Real->glBindBuffer(eGL_TEXTURE_BUFFER, BufferBindings[eBufIdx_Texture]);
  if(HasExt[ARB_draw_indirect])
    m_Real->glBindBuffer(eGL_DRAW_INDIRECT_BUFFER, BufferBindings[eBufIdx_Draw_Indirect]);
  if(HasExt[ARB_compute_shader])
    m_Real->glBindBuffer(eGL_DISPATCH_INDIRECT_BUFFER, BufferBindings[eBufIdx_Dispatch_Indirect]);
  if(HasExt[ARB_query_buffer_object])
    m_Real->glBindBuffer(eGL_QUERY_BUFFER, BufferBindings[eBufIdx_Query]);
  if(HasExt[ARB_indirect_parameters])
    m_Real->glBindBuffer(eGL_PARAMETER_BUFFER_ARB, BufferBindings[eBufIdx_Parameter]);

  struct
  {
    IdxRangeBuffer *bufs;
    int count;
    GLenum binding;
    GLenum maxcount;
  } idxBufs[] = {
      {
          AtomicCounter, ARRAY_COUNT(AtomicCounter), eGL_ATOMIC_COUNTER_BUFFER,
          eGL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS,
      },
      {
          ShaderStorage, ARRAY_COUNT(ShaderStorage), eGL_SHADER_STORAGE_BUFFER,
          eGL_MAX_SHADER_STORAGE_BUFFER_BINDINGS,
      },
      {
          TransformFeedback, ARRAY_COUNT(TransformFeedback), eGL_TRANSFORM_FEEDBACK_BUFFER,
          eGL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
      },
      {
          UniformBinding, ARRAY_COUNT(UniformBinding), eGL_UNIFORM_BUFFER,
          eGL_MAX_UNIFORM_BUFFER_BINDINGS,
      },
  };

  for(size_t b = 0; b < ARRAY_COUNT(idxBufs); b++)
  {
    // only restore buffer bindings here if we were using the default transform feedback object
    if(idxBufs[b].binding == eGL_TRANSFORM_FEEDBACK_BUFFER && FeedbackObj)
      continue;

    if(idxBufs[b].binding == eGL_ATOMIC_COUNTER_BUFFER && !HasExt[ARB_shader_atomic_counters])
      continue;

    if(idxBufs[b].binding == eGL_SHADER_STORAGE_BUFFER && !HasExt[ARB_shader_storage_buffer_object])
      continue;

    if(idxBufs[b].binding == eGL_TRANSFORM_FEEDBACK_BUFFER && !HasExt[ARB_transform_feedback2])
      continue;

    GLint maxCount = 0;
    m_Real->glGetIntegerv(idxBufs[b].maxcount, &maxCount);
    for(int i = 0; i < idxBufs[b].count && i < maxCount; i++)
    {
      if(idxBufs[b].bufs[i].name == 0 ||
         (idxBufs[b].bufs[i].start == 0 && idxBufs[b].bufs[i].size == 0))
        m_Real->glBindBufferBase(idxBufs[b].binding, i, idxBufs[b].bufs[i].name);
      else
        m_Real->glBindBufferRange(idxBufs[b].binding, i, idxBufs[b].bufs[i].name,
                                  (GLintptr)idxBufs[b].bufs[i].start,
                                  (GLsizeiptr)idxBufs[b].bufs[i].size);
    }
  }

  GLuint maxDraws = 0;
  m_Real->glGetIntegerv(eGL_MAX_DRAW_BUFFERS, (GLint *)&maxDraws);

  if(HasExt[ARB_draw_buffers_blend])
  {
    for(GLuint i = 0; i < RDCMIN(maxDraws, (GLuint)ARRAY_COUNT(Blends)); i++)
    {
      m_Real->glBlendFuncSeparatei(i, Blends[i].SourceRGB, Blends[i].DestinationRGB,
                                   Blends[i].SourceAlpha, Blends[i].DestinationAlpha);
      m_Real->glBlendEquationSeparatei(i, Blends[i].EquationRGB, Blends[i].EquationAlpha);

      if(Blends[i].Enabled)
        m_Real->glEnablei(eGL_BLEND, i);
      else
        m_Real->glDisablei(eGL_BLEND, i);
    }
  }

  m_Real->glBlendColor(BlendColor[0], BlendColor[1], BlendColor[2], BlendColor[3]);

  if(HasExt[ARB_viewport_array])
  {
    GLuint maxViews = 0;
    m_Real->glGetIntegerv(eGL_MAX_VIEWPORTS, (GLint *)&maxViews);

    m_Real->glViewportArrayv(0, RDCMIN(maxViews, (GLuint)ARRAY_COUNT(Viewports)), &Viewports[0].x);

    for(GLuint s = 0; s < RDCMIN(maxViews, (GLuint)ARRAY_COUNT(Scissors)); ++s)
    {
      m_Real->glScissorIndexedv(s, &Scissors[s].x);

      if(Scissors[s].enabled)
        m_Real->glEnablei(eGL_SCISSOR_TEST, s);
      else
        m_Real->glDisablei(eGL_SCISSOR_TEST, s);
    }

    for(GLuint i = 0; i < RDCMIN(maxViews, (GLuint)ARRAY_COUNT(DepthRanges)); i++)
    {
      double v[2] = {DepthRanges[i].nearZ, DepthRanges[i].farZ};
      m_Real->glDepthRangeArrayv(i, 1, v);
    }
  }
  else
  {
    m_Real->glViewport((GLint)Viewports[0].x, (GLint)Viewports[0].y, (GLsizei)Viewports[0].width,
                       (GLsizei)Viewports[0].height);

    m_Real->glScissor(Scissors[0].x, Scissors[0].y, Scissors[0].width, Scissors[0].height);

    if(Scissors[0].enabled)
      m_Real->glEnable(eGL_SCISSOR_TEST);
    else
      m_Real->glDisable(eGL_SCISSOR_TEST);

    m_Real->glDepthRange(DepthRanges[0].nearZ, DepthRanges[0].farZ);
  }

  GLenum DBs[8] = {eGL_NONE};
  uint32_t numDBs = 0;
  for(GLuint i = 0; i < RDCMIN(maxDraws, (GLuint)ARRAY_COUNT(DrawBuffers)); i++)
  {
    if(DrawBuffers[i] != eGL_NONE)
    {
      numDBs++;
      DBs[i] = DrawBuffers[i];

      if(m_State < WRITING)
      {
        // since we are faking the default framebuffer with our own
        // to see the results, replace back/front/left/right with color attachment 0
        if(DBs[i] == eGL_BACK_LEFT || DBs[i] == eGL_BACK_RIGHT || DBs[i] == eGL_FRONT_LEFT ||
           DBs[i] == eGL_FRONT_RIGHT)
          DBs[i] = eGL_COLOR_ATTACHMENT0;

        // These aren't valid for glDrawBuffers but can be returned when we call glGet,
        // assume they mean left implicitly
        if(DBs[i] == eGL_BACK || DBs[i] == eGL_FRONT)
          DBs[i] = eGL_COLOR_ATTACHMENT0;
      }
    }
    else
    {
      break;
    }
  }

  // this will always return true during capture, but on replay we only do
  // this work if we're on the replay context
  if(gl->GetReplay()->IsReplayContext(ctx))
  {
    // apply drawbuffers/readbuffer to default framebuffer
    m_Real->glBindFramebuffer(eGL_READ_FRAMEBUFFER, gl->GetFakeBBFBO());
    m_Real->glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, gl->GetFakeBBFBO());
    m_Real->glDrawBuffers(numDBs, DBs);

    // see above for reasoning for this
    m_Real->glReadBuffer(eGL_COLOR_ATTACHMENT0);

    m_Real->glBindFramebuffer(eGL_READ_FRAMEBUFFER, ReadFBO);
    m_Real->glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, DrawFBO);
  }

  m_Real->glHint(eGL_FRAGMENT_SHADER_DERIVATIVE_HINT, Hints.Derivatives);
  m_Real->glHint(eGL_LINE_SMOOTH_HINT, Hints.LineSmooth);
  m_Real->glHint(eGL_POLYGON_SMOOTH_HINT, Hints.PolySmooth);
  m_Real->glHint(eGL_TEXTURE_COMPRESSION_HINT, Hints.TexCompression);

  m_Real->glDepthMask(DepthWriteMask);
  m_Real->glClearDepth(DepthClearValue);
  m_Real->glDepthFunc(DepthFunc);

  if(HasExt[EXT_depth_bounds_test] && m_Real->glDepthBoundsEXT)
    m_Real->glDepthBoundsEXT(DepthBounds.nearZ, DepthBounds.farZ);

  {
    m_Real->glStencilFuncSeparate(eGL_FRONT, StencilFront.func, StencilFront.ref,
                                  StencilFront.valuemask);
    m_Real->glStencilFuncSeparate(eGL_BACK, StencilBack.func, StencilBack.ref, StencilBack.valuemask);

    m_Real->glStencilMaskSeparate(eGL_FRONT, StencilFront.writemask);
    m_Real->glStencilMaskSeparate(eGL_BACK, StencilBack.writemask);

    m_Real->glStencilOpSeparate(eGL_FRONT, StencilFront.stencilFail, StencilFront.depthFail,
                                StencilFront.pass);
    m_Real->glStencilOpSeparate(eGL_BACK, StencilBack.stencilFail, StencilBack.depthFail,
                                StencilBack.pass);
  }

  m_Real->glClearStencil((GLint)StencilClearValue);

  for(GLuint i = 0; i < RDCMIN(maxDraws, (GLuint)ARRAY_COUNT(ColorMasks)); i++)
    m_Real->glColorMaski(i, ColorMasks[i].red, ColorMasks[i].green, ColorMasks[i].blue,
                         ColorMasks[i].alpha);

  m_Real->glSampleMaski(0, (GLbitfield)SampleMask[0]);
  m_Real->glSampleCoverage(SampleCoverage, SampleCoverageInvert ? GL_TRUE : GL_FALSE);
  if(HasExt[ARB_sample_shading])
    m_Real->glMinSampleShading(MinSampleShading);

  if(HasExt[EXT_raster_multisample] && m_Real->glRasterSamplesEXT)
    m_Real->glRasterSamplesEXT(RasterSamples, RasterFixed);

  m_Real->glLogicOp(LogicOp);

  m_Real->glClearColor(ColorClearValue.red, ColorClearValue.green, ColorClearValue.blue,
                       ColorClearValue.alpha);

  if(HasExt[ARB_tessellation_shader])
  {
    m_Real->glPatchParameteri(eGL_PATCH_VERTICES, PatchParams.numVerts);
    m_Real->glPatchParameterfv(eGL_PATCH_DEFAULT_INNER_LEVEL, PatchParams.defaultInnerLevel);
    m_Real->glPatchParameterfv(eGL_PATCH_DEFAULT_OUTER_LEVEL, PatchParams.defaultOuterLevel);
  }

  m_Real->glPolygonMode(eGL_FRONT_AND_BACK, PolygonMode);
  if(HasExt[EXT_polygon_offset_clamp] && m_Real->glPolygonOffsetClampEXT)
    m_Real->glPolygonOffsetClampEXT(PolygonOffset[0], PolygonOffset[1], PolygonOffset[2]);
  else
    m_Real->glPolygonOffset(PolygonOffset[0], PolygonOffset[1]);

  m_Real->glFrontFace(FrontFace);
  m_Real->glCullFace(CullFace);

  Unpack.Apply(m_Real, true);

  ClearGLErrors(*m_Real);
}

void GLRenderState::Clear()
{
  ContextPresent = true;

  RDCEraseEl(Enabled);

  RDCEraseEl(Tex1D);
  RDCEraseEl(Tex2D);
  RDCEraseEl(Tex3D);
  RDCEraseEl(Tex1DArray);
  RDCEraseEl(Tex2DArray);
  RDCEraseEl(TexCubeArray);
  RDCEraseEl(TexRect);
  RDCEraseEl(TexBuffer);
  RDCEraseEl(TexCube);
  RDCEraseEl(Tex2DMS);
  RDCEraseEl(Tex2DMSArray);
  RDCEraseEl(Samplers);
  RDCEraseEl(ActiveTexture);

  RDCEraseEl(Images);
  for(GLuint i = 0; i < (GLuint)ARRAY_COUNT(Images); i++)
  {
    Images[i].access = eGL_READ_ONLY;
    Images[i].format = eGL_R8;
  }

  RDCEraseEl(Program);
  RDCEraseEl(Pipeline);

  RDCEraseEl(Subroutines);

  RDCEraseEl(VAO);
  RDCEraseEl(FeedbackObj);

  RDCEraseEl(GenericVertexAttribs);

  RDCEraseEl(PointFadeThresholdSize);
  RDCEraseEl(PointSpriteOrigin);
  RDCEraseEl(LineWidth);
  RDCEraseEl(PointSize);

  RDCEraseEl(PrimitiveRestartIndex);
  RDCEraseEl(ClipOrigin);
  RDCEraseEl(ClipDepth);
  RDCEraseEl(ProvokingVertex);

  RDCEraseEl(BufferBindings);
  RDCEraseEl(AtomicCounter);
  RDCEraseEl(ShaderStorage);
  RDCEraseEl(TransformFeedback);
  RDCEraseEl(UniformBinding);
  RDCEraseEl(Blends);
  RDCEraseEl(BlendColor);
  RDCEraseEl(Viewports);
  RDCEraseEl(Scissors);

  RDCEraseEl(DrawFBO);
  RDCEraseEl(ReadFBO);
  RDCEraseEl(DrawBuffers);
  RDCEraseEl(ReadBuffer);

  RDCEraseEl(PatchParams);
  RDCEraseEl(PolygonMode);
  RDCEraseEl(PolygonOffset);

  RDCEraseEl(DepthWriteMask);
  RDCEraseEl(DepthClearValue);
  RDCEraseEl(DepthRanges);
  RDCEraseEl(DepthBounds);
  RDCEraseEl(DepthFunc);
  RDCEraseEl(StencilFront);
  RDCEraseEl(StencilBack);
  RDCEraseEl(StencilClearValue);
  RDCEraseEl(ColorMasks);
  RDCEraseEl(SampleMask);
  RDCEraseEl(RasterSamples);
  RDCEraseEl(RasterFixed);
  RDCEraseEl(SampleCoverage);
  RDCEraseEl(SampleCoverageInvert);
  RDCEraseEl(MinSampleShading);
  RDCEraseEl(LogicOp);
  RDCEraseEl(ColorClearValue);

  RDCEraseEl(Hints);
  RDCEraseEl(FrontFace);
  RDCEraseEl(CullFace);

  RDCEraseEl(Unpack);
}

void GLRenderState::Serialise(LogState state, void *ctx, WrappedOpenGL *gl)
{
  GLResourceManager *rm = gl->GetResourceManager();

  m_pSerialiser->Serialise("Context Present", ContextPresent);

  if(!ContextPresent)
    return;

  m_pSerialiser->SerialisePODArray<eEnabled_Count>("GL_ENABLED", Enabled);

  ResourceId ids[128];

  GLuint *texArrays[] = {
      Tex1D,   Tex2D,     Tex3D,   Tex1DArray, Tex2DArray,   TexCubeArray,
      TexRect, TexBuffer, TexCube, Tex2DMS,    Tex2DMSArray,
  };

  const char *names[] = {
      "GL_TEXTURE_BINDING_1D",
      "GL_TEXTURE_BINDING_2D",
      "GL_TEXTURE_BINDING_3D",
      "GL_TEXTURE_BINDING_1D_ARRAY",
      "GL_TEXTURE_BINDING_2D_ARRAY",
      "GL_TEXTURE_BINDING_CUBE_MAP_ARRAY",
      "GL_TEXTURE_BINDING_RECTANGLE",
      "GL_TEXTURE_BINDING_BUFFER",
      "GL_TEXTURE_BINDING_CUBE_MAP",
      "GL_TEXTURE_BINDING_2D_MULTISAMPLE",
      "GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY",
  };

  for(size_t t = 0; t < ARRAY_COUNT(texArrays); t++)
  {
    RDCEraseEl(ids);
    if(state >= WRITING)
      for(size_t i = 0; i < ARRAY_COUNT(Tex2D); i++)
        if(texArrays[t][i])
          ids[i] = rm->GetID(TextureRes(ctx, texArrays[t][i]));

    m_pSerialiser->SerialisePODArray<ARRAY_COUNT(Tex2D)>(names[t], ids);

    if(state < WRITING)
      for(size_t i = 0; i < ARRAY_COUNT(Tex2D); i++)
        if(ids[i] != ResourceId())
          texArrays[t][i] = rm->GetLiveResource(ids[i]).name;
  }

  for(size_t i = 0; i < ARRAY_COUNT(Samplers); i++)
  {
    ResourceId ID = ResourceId();
    if(state >= WRITING)
      ID = rm->GetID(SamplerRes(ctx, Samplers[i]));
    m_pSerialiser->Serialise("GL_SAMPLER_BINDING", ID);
    if(state < WRITING && ID != ResourceId())
      Samplers[i] = rm->GetLiveResource(ID).name;
  }

  for(size_t i = 0; i < ARRAY_COUNT(Images); i++)
  {
    ResourceId ID = ResourceId();
    if(state >= WRITING)
      ID = rm->GetID(TextureRes(ctx, Images[i].name));
    m_pSerialiser->Serialise("GL_IMAGE_BINDING_NAME", ID);
    m_pSerialiser->Serialise("GL_IMAGE_BINDING_LEVEL", Images[i].level);
    m_pSerialiser->Serialise("GL_IMAGE_BINDING_LAYERED", Images[i].layered);
    m_pSerialiser->Serialise("GL_IMAGE_BINDING_LAYER", Images[i].layer);
    m_pSerialiser->Serialise("GL_IMAGE_BINDING_ACCESS", Images[i].access);
    m_pSerialiser->Serialise("GL_IMAGE_BINDING_FORMAT", Images[i].format);
    if(state < WRITING && ID != ResourceId())
      Images[i].name = rm->GetLiveResource(ID).name;
  }

  m_pSerialiser->Serialise("GL_ACTIVE_TEXTURE", ActiveTexture);

  {
    ResourceId ID = ResourceId();
    if(state >= WRITING)
      ID = rm->GetID(VertexArrayRes(ctx, VAO));
    m_pSerialiser->Serialise("GL_VERTEX_ARRAY_BINDING", ID);
    if(state < WRITING && ID != ResourceId())
      VAO = rm->GetLiveResource(ID).name;

    if(VAO == 0)
      VAO = gl->GetFakeVAO();
  }

  {
    ResourceId ID = ResourceId();
    if(state >= WRITING)
      ID = rm->GetID(FeedbackRes(ctx, FeedbackObj));
    m_pSerialiser->Serialise("GL_TRANSFORM_FEEDBACK_BINDING", ID);
    if(state < WRITING && ID != ResourceId())
      FeedbackObj = rm->GetLiveResource(ID).name;
  }

  for(size_t i = 0; i < ARRAY_COUNT(GenericVertexAttribs); i++)
  {
    m_pSerialiser->SerialisePODArray<4>("GL_CURRENT_VERTEX_ATTRIB", &GenericVertexAttribs[i].x);
  }

  m_pSerialiser->Serialise("GL_POINT_FADE_THRESHOLD_SIZE", PointFadeThresholdSize);
  m_pSerialiser->Serialise("GL_POINT_SPRITE_COORD_ORIGIN", PointSpriteOrigin);
  m_pSerialiser->Serialise("GL_LINE_WIDTH", LineWidth);
  m_pSerialiser->Serialise("GL_POINT_SIZE", PointSize);

  m_pSerialiser->Serialise("GL_PRIMITIVE_RESTART_INDEX", PrimitiveRestartIndex);
  m_pSerialiser->Serialise("GL_CLIP_ORIGIN", ClipOrigin);
  m_pSerialiser->Serialise("GL_CLIP_DEPTH_MODE", ClipDepth);
  m_pSerialiser->Serialise("GL_PROVOKING_VERTEX", ProvokingVertex);

  for(size_t i = 0; i < ARRAY_COUNT(BufferBindings); i++)
  {
    ResourceId ID = ResourceId();
    if(state >= WRITING)
      ID = rm->GetID(BufferRes(ctx, BufferBindings[i]));
    m_pSerialiser->Serialise("GL_BUFFER_BINDING", ID);
    if(state < WRITING && ID != ResourceId())
      BufferBindings[i] = rm->GetLiveResource(ID).name;
  }

  {
    ResourceId ID = ResourceId();
    if(state >= WRITING)
      ID = rm->GetID(ProgramRes(ctx, Program));
    m_pSerialiser->Serialise("GL_CURRENT_PROGRAM", ID);
    if(state < WRITING && ID != ResourceId())
      Program = rm->GetLiveResource(ID).name;
  }
  {
    ResourceId ID = ResourceId();
    if(state >= WRITING)
      ID = rm->GetID(ProgramPipeRes(ctx, Pipeline));
    m_pSerialiser->Serialise("GL_PROGRAM_PIPELINE_BINDING", ID);
    if(state < WRITING && ID != ResourceId())
      Pipeline = rm->GetLiveResource(ID).name;
  }

  for(size_t s = 0; s < ARRAY_COUNT(Subroutines); s++)
  {
    m_pSerialiser->Serialise("GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS", Subroutines[s].numSubroutines);
    m_pSerialiser->SerialisePODArray<128>("GL_SUBROUTINE_UNIFORMS", Subroutines[s].Values);
  }

  {
    ResourceId ID = ResourceId();
    if(state >= WRITING)
      ID = rm->GetID(FramebufferRes(ctx, DrawFBO));
    m_pSerialiser->Serialise("GL_DRAW_FRAMEBUFFER_BINDING", ID);
    if(state < WRITING && ID != ResourceId())
      DrawFBO = rm->GetLiveResource(ID).name;

    if(DrawFBO == 0)
      DrawFBO = gl->GetFakeBBFBO();
  }
  {
    ResourceId ID = ResourceId();
    if(state >= WRITING)
      ID = rm->GetID(FramebufferRes(ctx, ReadFBO));
    m_pSerialiser->Serialise("GL_READ_FRAMEBUFFER_BINDING", ID);
    if(state < WRITING && ID != ResourceId())
      ReadFBO = rm->GetLiveResource(ID).name;

    if(ReadFBO == 0)
      ReadFBO = gl->GetFakeBBFBO();
  }

  struct
  {
    IdxRangeBuffer *bufs;
    int count;
  } idxBufs[] = {
      {
          AtomicCounter, ARRAY_COUNT(AtomicCounter),
      },
      {
          ShaderStorage, ARRAY_COUNT(ShaderStorage),
      },
      {
          TransformFeedback, ARRAY_COUNT(TransformFeedback),
      },
      {
          UniformBinding, ARRAY_COUNT(UniformBinding),
      },
  };

  for(size_t b = 0; b < ARRAY_COUNT(idxBufs); b++)
  {
    for(int i = 0; i < idxBufs[b].count; i++)
    {
      ResourceId ID = ResourceId();
      if(state >= WRITING)
        ID = rm->GetID(BufferRes(ctx, idxBufs[b].bufs[i].name));
      m_pSerialiser->Serialise("BUFFER_BINDING", ID);
      if(state < WRITING && ID != ResourceId())
        idxBufs[b].bufs[i].name = rm->GetLiveResource(ID).name;

      m_pSerialiser->Serialise("BUFFER_START", idxBufs[b].bufs[i].start);
      m_pSerialiser->Serialise("BUFFER_SIZE", idxBufs[b].bufs[i].size);
    }
  }

  for(size_t i = 0; i < ARRAY_COUNT(Blends); i++)
  {
    m_pSerialiser->Serialise("GL_BLEND_EQUATION_RGB", Blends[i].EquationRGB);
    m_pSerialiser->Serialise("GL_BLEND_EQUATION_ALPHA", Blends[i].EquationAlpha);

    m_pSerialiser->Serialise("GL_BLEND_SRC_RGB", Blends[i].SourceRGB);
    m_pSerialiser->Serialise("GL_BLEND_SRC_ALPHA", Blends[i].SourceAlpha);

    m_pSerialiser->Serialise("GL_BLEND_DST_RGB", Blends[i].DestinationRGB);
    m_pSerialiser->Serialise("GL_BLEND_DST_ALPHA", Blends[i].DestinationAlpha);

    m_pSerialiser->Serialise("GL_BLEND", Blends[i].Enabled);
  }

  m_pSerialiser->SerialisePODArray<4>("GL_BLEND_COLOR", BlendColor);

  for(size_t i = 0; i < ARRAY_COUNT(Viewports); i++)
  {
    m_pSerialiser->Serialise("GL_VIEWPORT.x", Viewports[i].x);
    m_pSerialiser->Serialise("GL_VIEWPORT.y", Viewports[i].y);
    m_pSerialiser->Serialise("GL_VIEWPORT.w", Viewports[i].width);
    m_pSerialiser->Serialise("GL_VIEWPORT.h", Viewports[i].height);
  }

  for(size_t i = 0; i < ARRAY_COUNT(Scissors); i++)
  {
    m_pSerialiser->Serialise("GL_SCISSOR.x", Scissors[i].x);
    m_pSerialiser->Serialise("GL_SCISSOR.y", Scissors[i].y);
    m_pSerialiser->Serialise("GL_SCISSOR.w", Scissors[i].width);
    m_pSerialiser->Serialise("GL_SCISSOR.h", Scissors[i].height);
    m_pSerialiser->Serialise("GL_SCISSOR.enabled", Scissors[i].enabled);
  }

  m_pSerialiser->SerialisePODArray<8>("GL_DRAW_BUFFERS", DrawBuffers);
  m_pSerialiser->Serialise("GL_READ_BUFFER", ReadBuffer);

  m_pSerialiser->Serialise("GL_FRAGMENT_SHADER_DERIVATIVE_HINT", Hints.Derivatives);
  m_pSerialiser->Serialise("GL_LINE_SMOOTH_HINT", Hints.LineSmooth);
  m_pSerialiser->Serialise("GL_POLYGON_SMOOTH_HINT", Hints.PolySmooth);
  m_pSerialiser->Serialise("GL_TEXTURE_COMPRESSION_HINT", Hints.TexCompression);

  m_pSerialiser->Serialise("GL_DEPTH_WRITEMASK", DepthWriteMask);
  m_pSerialiser->Serialise("GL_DEPTH_CLEAR_VALUE", DepthClearValue);
  m_pSerialiser->Serialise("GL_DEPTH_FUNC", DepthFunc);

  for(size_t i = 0; i < ARRAY_COUNT(DepthRanges); i++)
  {
    m_pSerialiser->Serialise("GL_DEPTH_RANGE.near", DepthRanges[i].nearZ);
    m_pSerialiser->Serialise("GL_DEPTH_RANGE.far", DepthRanges[i].farZ);
  }

  {
    m_pSerialiser->Serialise("GL_DEPTH_BOUNDS_EXT.near", DepthBounds.nearZ);
    m_pSerialiser->Serialise("GL_DEPTH_BOUNDS_EXT.far", DepthBounds.farZ);
  }

  {
    m_pSerialiser->Serialise("GL_STENCIL_FUNC", StencilFront.func);
    m_pSerialiser->Serialise("GL_STENCIL_BACK_FUNC", StencilBack.func);

    m_pSerialiser->Serialise("GL_STENCIL_REF", StencilFront.ref);
    m_pSerialiser->Serialise("GL_STENCIL_BACK_REF", StencilBack.ref);

    m_pSerialiser->Serialise("GL_STENCIL_VALUE_MASK", StencilFront.valuemask);
    m_pSerialiser->Serialise("GL_STENCIL_BACK_VALUE_MASK", StencilBack.valuemask);

    m_pSerialiser->Serialise("GL_STENCIL_WRITEMASK", StencilFront.writemask);
    m_pSerialiser->Serialise("GL_STENCIL_BACK_WRITEMASK", StencilBack.writemask);

    m_pSerialiser->Serialise("GL_STENCIL_FAIL", StencilFront.stencilFail);
    m_pSerialiser->Serialise("GL_STENCIL_BACK_FAIL", StencilBack.stencilFail);

    m_pSerialiser->Serialise("GL_STENCIL_PASS_DEPTH_FAIL", StencilFront.depthFail);
    m_pSerialiser->Serialise("GL_STENCIL_BACK_PASS_DEPTH_FAIL", StencilBack.depthFail);

    m_pSerialiser->Serialise("GL_STENCIL_PASS_DEPTH_PASS", StencilFront.pass);
    m_pSerialiser->Serialise("GL_STENCIL_BACK_PASS_DEPTH_PASS", StencilBack.pass);
  }

  m_pSerialiser->Serialise("GL_STENCIL_CLEAR_VALUE", StencilClearValue);

  for(size_t i = 0; i < ARRAY_COUNT(ColorMasks); i++)
    m_pSerialiser->SerialisePODArray<4>("GL_COLOR_WRITEMASK", &ColorMasks[i].red);

  m_pSerialiser->SerialisePODArray<2>("GL_SAMPLE_MASK_VALUE", &SampleMask[0]);
  m_pSerialiser->Serialise("GL_SAMPLE_COVERAGE_VALUE", SampleCoverage);
  m_pSerialiser->Serialise("GL_SAMPLE_COVERAGE_INVERT", SampleCoverageInvert);
  m_pSerialiser->Serialise("GL_MIN_SAMPLE_SHADING", MinSampleShading);

  m_pSerialiser->Serialise("GL_RASTER_SAMPLES_EXT", RasterSamples);
  m_pSerialiser->Serialise("GL_RASTER_FIXED_SAMPLE_LOCATIONS_EXT", RasterFixed);

  m_pSerialiser->Serialise("GL_LOGIC_OP_MODE", LogicOp);

  m_pSerialiser->SerialisePODArray<4>("GL_COLOR_CLEAR_VALUE", &ColorClearValue.red);

  {
    m_pSerialiser->Serialise("GL_PATCH_VERTICES", PatchParams.numVerts);
    m_pSerialiser->SerialisePODArray<2>("GL_PATCH_DEFAULT_INNER_LEVEL",
                                        &PatchParams.defaultInnerLevel[0]);
    m_pSerialiser->SerialisePODArray<4>("GL_PATCH_DEFAULT_OUTER_LEVEL",
                                        &PatchParams.defaultOuterLevel[0]);
  }

  m_pSerialiser->Serialise("GL_POLYGON_MODE", PolygonMode);
  m_pSerialiser->Serialise("GL_POLYGON_OFFSET_FACTOR", PolygonOffset[0]);
  m_pSerialiser->Serialise("GL_POLYGON_OFFSET_UNITS", PolygonOffset[1]);
  m_pSerialiser->Serialise("GL_POLYGON_OFFSET_CLAMP_EXT", PolygonOffset[2]);

  m_pSerialiser->Serialise("GL_FRONT_FACE", FrontFace);
  m_pSerialiser->Serialise("GL_CULL_FACE_MODE", CullFace);

  m_pSerialiser->Serialise("GL_UNPACK_SWAP_BYTES", Unpack.swapBytes);
  m_pSerialiser->Serialise("GL_UNPACK_ROW_LENGTH", Unpack.rowlength);
  m_pSerialiser->Serialise("GL_UNPACK_IMAGE_HEIGHT", Unpack.imageheight);
  m_pSerialiser->Serialise("GL_UNPACK_SKIP_PIXELS", Unpack.skipPixels);
  m_pSerialiser->Serialise("GL_UNPACK_SKIP_ROWS", Unpack.skipRows);
  m_pSerialiser->Serialise("GL_UNPACK_SKIP_IMAGES", Unpack.skipImages);
  m_pSerialiser->Serialise("GL_UNPACK_ALIGNMENT", Unpack.alignment);
  m_pSerialiser->Serialise("GL_UNPACK_COMPRESSED_BLOCK_WIDTH", Unpack.compressedBlockWidth);
  m_pSerialiser->Serialise("GL_UNPACK_COMPRESSED_BLOCK_HEIGHT", Unpack.compressedBlockHeight);
  m_pSerialiser->Serialise("GL_UNPACK_COMPRESSED_BLOCK_DEPTH", Unpack.compressedBlockDepth);
  m_pSerialiser->Serialise("GL_UNPACK_COMPRESSED_BLOCK_SIZE", Unpack.compressedBlockSize);
}


text:
ReportDownloadFormatは、定義されたダウンロードレポートのファイル形式を表します。

#### Service

+ [ReportDefinitionService](../../services/ReportDefinitionService.md)

#### Namespace

[ReportDefinitionService#Namespace](../../services/ReportDefinitionService.md#namespace)

| Enumeration  |       Type       |          Description          |
| ------------ | ---------------- | ----------------------------- |
| CSV | xsd:string | カンマ区分されたフォーマットです。 |
| XML | xsd:string | XMLフォーマットです。 |

この 作品 は クリエイティブ・コモンズ 表示 - 改変禁止 2.1 日本 ライセンスの下に提供されています。


text:
package example.com.coolweather.gson;

import com.google.gson.annotations.SerializedName;

import java.util.List;

/**
 * Created by Adminstrator on 2017/5/6.
 */

public class Weather {
    public String status;
    public AQI aqi;
    public Basic basic;
    public Now now;
    public Suggestion suggestion;
    @SerializedName("daily_forecast")
    public List<Forecast> forecasts;
}


text:
#region SearchAThing.Core, Copyright(C) 2015-2016 Lorenzo Delana, License under MIT

#endregion

using SearchAThing.Core;
using System;
using System.Collections;
using System.Collections.Generic;

namespace SearchAThing
{

    namespace Core
    {

        public class CircularEnumerator<D> : IEnumerator<D>
        {

            IEnumerator<D> enumerator;

            public CircularEnumerator(IEnumerable<D> en)
            {
                enumerator = en.GetEnumerator();
            }

            public D Current
            {
                get
                {
                    return enumerator.Current;
                }
            }

            object IEnumerator.Current
            {
                get
                {
                    return enumerator.Current;
                }
            }

            public void Dispose()
            {
                enumerator.Dispose();
            }

            public bool MoveNext()
            {
                if (!enumerator.MoveNext())
                {
                    enumerator.Reset();
                    return enumerator.MoveNext();
                }
                return true;
            }

            public void Reset()
            {
                enumerator.Reset();
            }
        }

        public class CircularEnumerable<D> : IEnumerable<D>
        {
            IEnumerable<D> enumerable;

            public CircularEnumerable(IEnumerable<D> _enumerable)
            {
                enumerable = _enumerable;
            }

            public IEnumerator<D> GetEnumerator()
            {
                return new CircularEnumerator<D>(enumerable);
            }

            IEnumerator IEnumerable.GetEnumerator()
            {
                return new CircularEnumerator<D>(enumerable);
            }
        }

    }

    public static partial class Extensions
    {

        public static IEnumerable<D> AsCircularEnumerable<D>(this IEnumerable<D> enumerable)
        {
            return new CircularEnumerable<D>(enumerable);
        }

        public static IEnumerator<D> AsCircularEnumerator<D>(this IEnumerable<D> enumerable)
        {
            return enumerable.AsCircularEnumerable().GetEnumerator();
        }

    }

}


text:
package com.geekcattle.service.console;

import com.geekcattle.mapper.console.RoleMapper;
import com.geekcattle.model.console.Role;
import com.geekcattle.util.CamelCaseUtil;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.util.List;
import java.util.Set;

/**
 * @author geekcattle
 */
@Service
public class RoleService {

    @Autowired
    private RoleMapper roleMapper;

    public List<Role> getPageList(Role role) {
        PageHelper.offsetPage(role.getOffset(), role.getLimit());
        PageHelper.orderBy(CamelCaseUtil.toUnderlineName(role.getSort())+" "+role.getOrder());
        return roleMapper.selectAll();
    }

    public List<Role> getFromAll(){
        Example example = new Example(Role.class);
        example.createCriteria()
                .andCondition("enable = ", 1);
        return roleMapper.selectByExample(example);
    }

    public Integer getCount(Example example){
        return roleMapper.selectCountByExample(example);
    }

    public Role getById(String id) {
        return roleMapper.selectByPrimaryKey(id);
    }

    public List<Role> getById(Role roles) {
        return roleMapper.select( roles);
    }

    public void deleteById(String id) {
        roleMapper.deleteByPrimaryKey(id);
    }

    public void save(Role role) {
        roleMapper.updateByPrimaryKey(role);
    }

    public void insert(Role role){
        roleMapper.insert(role);
    }

    public Set<String> findRoleByUserId(String userId) {
        return roleMapper.findRoleByUserId(userId);
    }

    public List<Role> selectRoleListByAdminId(String id){
        return roleMapper.selectRoleListByAdminId(id);
    }

}