summaryrefslogtreecommitdiff
path: root/src/gl/buffer.cc
diff options
context:
space:
mode:
authorGravatar Benjamin Barenblat <bbarenblat@gmail.com>2022-01-17 23:12:32 -0500
committerGravatar Benjamin Barenblat <bbarenblat@gmail.com>2022-01-30 15:55:27 -0500
commitd0e18bdb7924c71cdca8dd983711171d87ef28be (patch)
tree6be11aae0b7c8874e6507b75b4ef26d1353952c7 /src/gl/buffer.cc
glplanet, an OpenGL-based planetary rendererHEADmain
glplanet draws Earth like it currently appears from space, putting nighttime areas in shadow and daytime areas in light. It’s modeled after Xplanet (http://xplanet.sourceforge.net/), but whereas Xplanet is entirely a CPU-resident program, glplanet draws using OpenGL. It’s thus much less resource-intensive, particularly when using high-resolution textures.
Diffstat (limited to 'src/gl/buffer.cc')
-rw-r--r--src/gl/buffer.cc105
1 files changed, 105 insertions, 0 deletions
diff --git a/src/gl/buffer.cc b/src/gl/buffer.cc
new file mode 100644
index 0000000..a56e36a
--- /dev/null
+++ b/src/gl/buffer.cc
@@ -0,0 +1,105 @@
+// Copyright 2021 Benjamin Barenblat
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+#include "src/gl/buffer.h"
+
+#include <stdint.h>
+
+#include <stdexcept>
+
+#include "src/gl/error.h"
+#include "src/util.h"
+#include "third_party/abseil/absl/strings/substitute.h"
+#include "third_party/glew/include/GL/glew.h"
+
+namespace gl {
+
+namespace {
+
+constexpr uint16_t Pack(Buffer::AccessFrequency frequency,
+ Buffer::AccessNature nature) noexcept {
+ static_assert(sizeof(Buffer::AccessFrequency) == 1);
+ static_assert(sizeof(Buffer::AccessNature) == 1);
+ return FromEnum(frequency) << 8 | FromEnum(nature);
+}
+
+GLenum CombineFrequencyAndNature(Buffer::AccessFrequency frequency,
+ Buffer::AccessNature nature) {
+ using F = ::gl::Buffer::AccessFrequency;
+ using N = ::gl::Buffer::AccessNature;
+ switch (Pack(frequency, nature)) {
+ case Pack(F::kStream, N::kDraw):
+ return GL_STREAM_DRAW;
+ case Pack(F::kStream, N::kRead):
+ return GL_STREAM_READ;
+ case Pack(F::kStream, N::kCopy):
+ return GL_STREAM_COPY;
+
+ case Pack(F::kStatic, N::kDraw):
+ return GL_STATIC_DRAW;
+ case Pack(F::kStatic, N::kRead):
+ return GL_STATIC_READ;
+ case Pack(F::kStatic, N::kCopy):
+ return GL_STATIC_COPY;
+
+ case Pack(F::kDynamic, N::kDraw):
+ return GL_DYNAMIC_DRAW;
+ case Pack(F::kDynamic, N::kRead):
+ return GL_DYNAMIC_READ;
+ case Pack(F::kDynamic, N::kCopy):
+ return GL_DYNAMIC_COPY;
+
+ default:
+ throw std::invalid_argument(absl::Substitute(
+ "GL: invalid access frequency and/or nature ($0, $1)",
+ FromEnum(frequency), FromEnum(nature)));
+ }
+}
+
+} // namespace
+
+Buffer::Buffer(const Buffer& other)
+ : size_bytes_(other.size_bytes_),
+ frequency_(other.frequency_),
+ nature_(other.nature_) {
+ gl_internal::CheckThreadSafety();
+
+ glCreateBuffers(1, &buffer_);
+ gl_internal::UnnecessaryErrorCheck();
+
+ glNamedBufferData(buffer_, size_bytes_, /*data=*/nullptr,
+ CombineFrequencyAndNature(frequency_, nature_));
+ // An error check is necessary here to detect allocation failure, but it can
+ // be folded into a future error check.
+ gl_internal::UnnecessaryErrorCheck();
+
+ glCopyNamedBufferSubData(other.buffer_, buffer_, /*readOffset=*/0,
+ /*writeOffset=*/0, other.size_bytes_);
+ // This error check is necessary because other might be mapped.
+ gl_internal::ErrorCheck();
+
+ fprintf(stderr, "BUFFER COPY\n");
+}
+
+void Buffer::SetData(const void* data, int size_bytes,
+ AccessFrequency frequency, AccessNature nature) {
+ gl_internal::CheckThreadSafety();
+ glNamedBufferData(buffer_, size_bytes, data,
+ CombineFrequencyAndNature(frequency, nature));
+ // This error check is necessary to detect allocation failure.
+ gl_internal::ErrorCheck();
+ size_bytes_ = size_bytes;
+}
+
+} // namespace gl