1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158

gpu / command_buffer / service / transform_feedback_manager.h [blame]

// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef GPU_COMMAND_BUFFER_SERVICE_TRANSFORM_FEEDBACK_MANAGER_H_
#define GPU_COMMAND_BUFFER_SERVICE_TRANSFORM_FEEDBACK_MANAGER_H_

#include <unordered_map>
#include <vector>

#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "gpu/command_buffer/service/gl_utils.h"
#include "gpu/command_buffer/service/indexed_buffer_binding_host.h"
#include "gpu/gpu_gles2_export.h"

namespace gpu {
namespace gles2 {

class Buffer;
class TransformFeedbackManager;

// Info about TransformFeedbacks currently in the system.
class GPU_GLES2_EXPORT TransformFeedback : public IndexedBufferBindingHost {
 public:
  TransformFeedback(TransformFeedbackManager* manager,
                    GLuint client_id,
                    GLuint service_id);

  // All the following functions do state update and call the underlying GL
  // function.  All validations have been done already and the GL function is
  // guaranteed to succeed.
  void DoBindTransformFeedback(GLenum target,
                               TransformFeedback* last_bound_transform_feedback,
                               Buffer* bound_transform_feedback_buffer);
  void DoBeginTransformFeedback(GLenum primitive_mode);
  void DoEndTransformFeedback();
  void DoPauseTransformFeedback();
  void DoResumeTransformFeedback();

  GLuint client_id() const {
    return client_id_;
  }

  GLuint service_id() const {
    return service_id_;
  }

  bool has_been_bound() const {
    return has_been_bound_;
  }

  bool active() const {
    return active_;
  }

  bool paused() const {
    return paused_;
  }

  GLenum primitive_mode() const {
    return primitive_mode_;
  }

  // Calculates the number of vertices that this draw call will write to the
  // transform feedback buffer, plus the number of vertices that were previously
  // written since the last call to BeginTransformFeedback (because vertices are
  // written starting just after the last vertex written by the previous draw),
  // plus |pending_vertices_drawn|. The pending vertices are used to iteratively
  // validate and accumulate the number of vertices drawn for multiple draws.
  // This is used to calculate whether there is enough space in the transform
  // feedback buffers. Returns false on integer overflow.
  bool GetVerticesNeededForDraw(GLenum mode,
                                GLsizei count,
                                GLsizei primcount,
                                GLsizei pending_vertices_drawn,
                                GLsizei* vertices_out) const;
  // This must be called every time a transform feedback draw happens to keep
  // track of how many vertices have been written to the transform feedback
  // buffers.
  void OnVerticesDrawn(GLsizei vertices_drawn);

 private:
  ~TransformFeedback() override;

  // The manager that owns this Buffer.
  raw_ptr<TransformFeedbackManager> manager_;

  GLuint client_id_;
  GLuint service_id_;

  bool has_been_bound_;

  bool active_;
  bool paused_;

  GLenum primitive_mode_;
  GLsizei vertices_drawn_;
};

// This class keeps tracks of the transform feedbacks and their states.
class GPU_GLES2_EXPORT TransformFeedbackManager {
 public:
  // In theory |needs_emulation| needs to be true on Desktop GL 4.1 or lower.
  // However, we set it to true everywhere, not to trust drivers to handle
  // out-of-bounds buffer accesses.
  TransformFeedbackManager(GLuint max_transform_feedback_separate_attribs,
                           bool needs_emulation);

  TransformFeedbackManager(const TransformFeedbackManager&) = delete;
  TransformFeedbackManager& operator=(const TransformFeedbackManager&) = delete;

  ~TransformFeedbackManager();

  void MarkContextLost() {
    lost_context_ = true;
  }

  // Must call before destruction.
  void Destroy();

  // Creates a TransformFeedback from the given client/service IDs and
  // insert it into the list.
  TransformFeedback* CreateTransformFeedback(
      GLuint client_id, GLuint service_id);

  TransformFeedback* GetTransformFeedback(GLuint client_id);

  // Removes a TransformFeedback info for the given client ID.
  void RemoveTransformFeedback(GLuint client_id);

  GLuint max_transform_feedback_separate_attribs() const {
    return max_transform_feedback_separate_attribs_;
  }

  bool needs_emulation() const {
    return needs_emulation_;
  }

  bool lost_context() const {
    return lost_context_;
  }

 private:
  // Info for each transform feedback in the system.
  std::unordered_map<GLuint, scoped_refptr<TransformFeedback>>
      transform_feedbacks_;

  GLuint max_transform_feedback_separate_attribs_;

  bool needs_emulation_;
  bool lost_context_;
};

}  // namespace gles2
}  // namespace gpu

#endif  // GPU_COMMAND_BUFFER_SERVICE_TRANSFORM_FEEDBACK_MANAGER_H_