Krita Source Code Documentation
Loading...
Searching...
No Matches
KisOpenGLBufferCircularStorage.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2021 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
8
9#include <QtMath>
10
11#include "kis_assert.h"
12#include "kis_opengl.h"
13
15 if (bufferStorage) {
16 m_buffer = bufferStorage->getNextBuffer();
17 m_buffer->bind();
18 m_buffer->write(0, *dataPtr, dataSize);
19 *dataPtr = nullptr;
20 }
21
22}
23
25 if (m_buffer) {
26 m_buffer->release();
27
29 KisOpenGL::glInvalidateBufferData(m_buffer->bufferId());
30 }
31 }
32}
33
35{
36 std::vector<QOpenGLBuffer> buffers;
37 decltype(buffers)::size_type nextBuffer = 0;
38 int bufferSize = 0;
39 QOpenGLBuffer::Type type = QOpenGLBuffer::QOpenGLBuffer::VertexBuffer;
40};
41
42
47
49 : m_d(new Private)
50{
51 m_d->type = type;
52}
53
55
56void KisOpenGLBufferCircularStorage::allocate(int numBuffers, int bufferSize)
57{
58 reset();
59 KIS_ASSERT(numBuffers > 0);
61 addBuffersImpl(static_cast<size_t>(numBuffers), bufferSize);
62}
63
65{
67
68 QOpenGLBuffer *buffer = &m_d->buffers[m_d->nextBuffer];
69 m_d->nextBuffer = (m_d->nextBuffer + 1) % m_d->buffers.size();
70 return buffer;
71}
72
74{
75 return !m_d->buffers.empty();
76}
77
79{
80 return static_cast<int>(m_d->buffers.size());
81}
82
84{
85 m_d->buffers.clear();
86 m_d->nextBuffer = 0;
87 m_d->bufferSize = 0;
88}
89
91{
92 const size_t numBuffers = nextPowerOfTwo(m_d->buffers.size());
93
94 KIS_SAFE_ASSERT_RECOVER_RETURN(!m_d->buffers.empty());
95
96 auto begin = m_d->buffers.begin();
97 auto middle = [&]() {
98 using value_type = typename decltype(m_d->buffers)::difference_type;
99 const value_type maxIndex = std::numeric_limits<value_type>::max();
100
101 if (m_d->nextBuffer <= std::numeric_limits<value_type>::max()) {
102 return std::next(begin, value_type(m_d->nextBuffer));
103 } else {
104 auto midpoint = std::next(begin, std::numeric_limits<value_type>::max());
105 return std::next(midpoint, value_type(m_d->nextBuffer - maxIndex));
106 }
107 }();
108 auto end = m_d->buffers.end();
109
110 std::rotate(begin, middle, end);
111
112 m_d->nextBuffer = m_d->buffers.size();
113
114 const size_t buffersToAdd = numBuffers - m_d->buffers.size();
115
116 addBuffersImpl(buffersToAdd, m_d->bufferSize);
117}
118
119void KisOpenGLBufferCircularStorage::addBuffersImpl(size_t buffersToAdd, int bufferSize)
120{
121 m_d->bufferSize = bufferSize;
122
123 const size_t newSize = qMax(m_d->buffers.size() + buffersToAdd, nextPowerOfTwo(m_d->buffers.size()));
124
125 if (m_d->buffers.capacity() < newSize)
126 m_d->buffers.reserve(newSize);
127
128 // overflow check for size()
129 KIS_ASSERT(m_d->buffers.size() <= std::numeric_limits<int>::max());
130
131 for (size_t i = 0; i < buffersToAdd; i++) {
132 m_d->buffers.emplace_back(m_d->type);
133
134 QOpenGLBuffer &buf = m_d->buffers.back();
135
136 buf.create();
137 buf.setUsagePattern(QOpenGLBuffer::DynamicDraw);
138 buf.bind();
139 buf.allocate(m_d->bufferSize);
140 buf.release();
141 }
142}
static bool useTextureBufferInvalidation()
static void glInvalidateBufferData(uint buffer)
#define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val)
Definition kis_assert.h:129
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128
#define KIS_ASSERT(cond)
Definition kis_assert.h:33
T nextPowerOfTwo(T v)
Definition kis_global.h:328
BufferBinder(KisOpenGLBufferCircularStorage *bufferStorage, const void **dataPtr, int dataSize)
void addBuffersImpl(size_t buffersToAdd, int bufferSize)
void allocate(int numBuffers, int bufferSize)