Skip to content

Commit 25ded30

Browse files
committed
🔧 Upload GUI only if changed
1 parent 65e45ae commit 25ded30

File tree

2 files changed

+77
-70
lines changed

2 files changed

+77
-70
lines changed

src/cs-gui/GuiItem.cpp

+69-64
Original file line numberDiff line numberDiff line change
@@ -37,38 +37,35 @@ GuiItem::GuiItem(std::string const& url, bool allowLocalFileAccess)
3737
, mIsRelPositionY(true)
3838
, mIsRelOffsetX(true)
3939
, mIsRelOffsetY(true) {
40-
setDrawCallback([this](DrawEvent const& event) { return updateTexture(event); });
4140

42-
setRequestKeyboardFocusCallback(
43-
[this](bool requested) { mIsKeyboardInputElementFocused = requested; });
41+
setDrawCallback([this](DrawEvent const& event) {
42+
mPBOsNeedUpload = mTexturePBOs.size();
4443

45-
glGenBuffers(1, &mTextureBuffer);
46-
glBindBuffer(GL_TEXTURE_BUFFER, mTextureBuffer);
47-
size_t bufferSize{4 * sizeof(uint8_t) * getWidth() * getHeight()};
44+
if (event.mResized) {
45+
mTextureSizeX = event.mWidth;
46+
mTextureSizeY = event.mHeight;
4847

49-
GLbitfield flags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT;
50-
glBufferStorage(GL_TEXTURE_BUFFER, bufferSize, nullptr, flags);
51-
mBufferData = static_cast<uint8_t*>(glMapBufferRange(GL_TEXTURE_BUFFER, 0, bufferSize, flags));
48+
recreateBuffers();
49+
}
5250

53-
glGenTextures(1, &mTexture);
54-
glBindTexture(GL_TEXTURE_2D, mTexture);
55-
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, getWidth(), getHeight());
56-
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
57-
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
58-
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
59-
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
51+
return mPixels.data();
52+
});
6053

61-
glBindBuffer(GL_TEXTURE_BUFFER, 0);
62-
glBindTexture(GL_TEXTURE_BUFFER, 0);
54+
setRequestKeyboardFocusCallback(
55+
[this](bool requested) { mIsKeyboardInputElementFocused = requested; });
56+
57+
mTextureSizeX = getWidth();
58+
mTextureSizeY = getHeight();
59+
60+
recreateBuffers();
6361
}
6462

6563
////////////////////////////////////////////////////////////////////////////////////////////////////
6664

6765
GuiItem::~GuiItem() {
68-
glBindBuffer(GL_TEXTURE_BUFFER, mTextureBuffer);
69-
glUnmapBuffer(GL_TEXTURE_BUFFER);
70-
glDeleteBuffers(1, &mTextureBuffer);
66+
glDeleteBuffers(2, &mTexturePBOs[0]);
7167
glDeleteTextures(1, &mTexture);
68+
7269
// seems to be necessary as OnPaint can be called by some other thread even
7370
// if this object is already deleted
7471
setDrawCallback([](DrawEvent const& /*unused*/) { return nullptr; });
@@ -220,46 +217,68 @@ bool GuiItem::calculateMousePosition(int areaX, int areaY, int& x, int& y) {
220217

221218
////////////////////////////////////////////////////////////////////////////////////////////////////
222219

223-
uint8_t* GuiItem::updateTexture(DrawEvent const& event) {
224-
if (event.mResized) {
225-
glBindBuffer(GL_TEXTURE_BUFFER, mTextureBuffer);
226-
glUnmapBuffer(GL_TEXTURE_BUFFER);
227-
glBindBuffer(GL_TEXTURE_BUFFER, 0);
220+
void GuiItem::onAreaResize(int width, int height) {
221+
mAreaWidth = width;
222+
mAreaHeight = height;
228223

229-
glDeleteBuffers(1, &mTextureBuffer);
230-
glGenBuffers(1, &mTextureBuffer);
231-
glBindBuffer(GL_TEXTURE_BUFFER, mTextureBuffer);
224+
updateSizes();
225+
}
232226

233-
size_t bufferSize{4 * sizeof(uint8_t) * event.mWidth * event.mHeight};
234-
GLbitfield flags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT;
235-
glBufferStorage(GL_TEXTURE_BUFFER, bufferSize, nullptr, flags);
236-
mBufferData = static_cast<uint8_t*>(glMapBufferRange(GL_TEXTURE_BUFFER, 0, bufferSize, flags));
227+
////////////////////////////////////////////////////////////////////////////////////////////////////
228+
229+
uint32_t GuiItem::getTexture() const {
230+
231+
// Copy the pixels buffer to the texture.
232+
if (mPBOsNeedUpload > 0) {
233+
234+
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, mTexturePBOs[mCurrentPBO]);
235+
auto ptr = static_cast<uint8_t*>(glMapBufferRange(
236+
GL_PIXEL_UNPACK_BUFFER, 0, 4 * mTextureSizeX * mTextureSizeY, GL_MAP_WRITE_BIT));
237+
std::memcpy(ptr, mPixels.data(), 4 * mTextureSizeX * mTextureSizeY);
238+
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
237239

238-
glDeleteTextures(1, &mTexture);
239-
glGenTextures(1, &mTexture);
240240
glBindTexture(GL_TEXTURE_2D, mTexture);
241-
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, event.mWidth, event.mHeight);
242-
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
243-
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
244-
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
245-
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
246-
247-
glBindBuffer(GL_TEXTURE_BUFFER, 0);
248-
glBindTexture(GL_TEXTURE_BUFFER, 0);
249-
mTextureSizeX = event.mWidth;
250-
mTextureSizeY = event.mHeight;
241+
glBindBuffer(GL_PIXEL_UNPACK_BUFFER,
242+
mTexturePBOs[(mCurrentPBO + mTexturePBOs.size() - 1) % mTexturePBOs.size()]);
243+
glTexSubImage2D(
244+
GL_TEXTURE_2D, 0, 0, 0, mTextureSizeX, mTextureSizeY, GL_BGRA, GL_UNSIGNED_BYTE, 0);
245+
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
246+
glBindTexture(GL_TEXTURE_2D, 0);
247+
248+
mCurrentPBO = (mCurrentPBO + 1) % mTexturePBOs.size();
249+
mPBOsNeedUpload -= 1;
251250
}
252251

253-
return mBufferData;
252+
return mTexture;
254253
}
255254

256255
////////////////////////////////////////////////////////////////////////////////////////////////////
257256

258-
void GuiItem::onAreaResize(int width, int height) {
259-
mAreaWidth = width;
260-
mAreaHeight = height;
257+
void GuiItem::recreateBuffers() {
261258

262-
updateSizes();
259+
if (mTexture) {
260+
glDeleteTextures(1, &mTexture);
261+
glDeleteBuffers(2, &mTexturePBOs[0]);
262+
}
263+
264+
for (size_t i = 0; i < mTexturePBOs.size(); ++i) {
265+
glGenBuffers(1, &mTexturePBOs[i]);
266+
glBindBuffer(GL_TEXTURE_BUFFER, mTexturePBOs[i]);
267+
glBufferStorage(
268+
GL_TEXTURE_BUFFER, 4 * mTextureSizeX * mTextureSizeY, nullptr, GL_MAP_WRITE_BIT);
269+
}
270+
glBindBuffer(GL_TEXTURE_BUFFER, 0);
271+
272+
glGenTextures(1, &mTexture);
273+
glBindTexture(GL_TEXTURE_2D, mTexture);
274+
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, mTextureSizeX, mTextureSizeY);
275+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
276+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
277+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
278+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
279+
glBindTexture(GL_TEXTURE_2D, 0);
280+
281+
mPixels.resize(4 * mTextureSizeX * mTextureSizeY);
263282
}
264283

265284
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -306,18 +325,4 @@ void GuiItem::updateSizes() {
306325

307326
////////////////////////////////////////////////////////////////////////////////////////////////////
308327

309-
uint32_t GuiItem::getTexture() const {
310-
311-
// Copy the texture buffer to the texture.
312-
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, mTextureBuffer);
313-
glBindTexture(GL_TEXTURE_2D, mTexture);
314-
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, getWidth(), getHeight(), GL_BGRA, GL_UNSIGNED_BYTE, 0);
315-
glBindTexture(GL_TEXTURE_2D, 0);
316-
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
317-
318-
return mTexture;
319-
}
320-
321-
////////////////////////////////////////////////////////////////////////////////////////////////////
322-
323328
} // namespace cs::gui

src/cs-gui/GuiItem.hpp

+8-6
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,14 @@ class CS_GUI_EXPORT GuiItem : public WebView {
8686
uint32_t getTexture() const;
8787

8888
private:
89-
uint8_t* updateTexture(DrawEvent const& event);
90-
void updateSizes();
91-
92-
uint32_t mTextureBuffer{};
93-
uint32_t mTexture{};
94-
uint8_t* mBufferData = nullptr;
89+
void recreateBuffers();
90+
void updateSizes();
91+
92+
std::vector<uint8_t> mPixels;
93+
uint32_t mTexture = 0;
94+
std::array<uint32_t, 2> mTexturePBOs;
95+
mutable uint8_t mCurrentPBO = 0;
96+
mutable uint8_t mPBOsNeedUpload = 0;
9597

9698
// in pixels
9799
int mTextureSizeX = 0;

0 commit comments

Comments
 (0)