@@ -37,38 +37,35 @@ GuiItem::GuiItem(std::string const& url, bool allowLocalFileAccess)
37
37
, mIsRelPositionY (true )
38
38
, mIsRelOffsetX (true )
39
39
, mIsRelOffsetY (true ) {
40
- setDrawCallback ([this ](DrawEvent const & event) { return updateTexture (event); });
41
40
42
- setRequestKeyboardFocusCallback (
43
- [ this ]( bool requested) { mIsKeyboardInputElementFocused = requested; } );
41
+ setDrawCallback ([ this ](DrawEvent const & event) {
42
+ mPBOsNeedUpload = mTexturePBOs . size ( );
44
43
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 ;
48
47
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
+ }
52
50
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
+ });
60
53
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 ();
63
61
}
64
62
65
63
// //////////////////////////////////////////////////////////////////////////////////////////////////
66
64
67
65
GuiItem::~GuiItem () {
68
- glBindBuffer (GL_TEXTURE_BUFFER, mTextureBuffer );
69
- glUnmapBuffer (GL_TEXTURE_BUFFER);
70
- glDeleteBuffers (1 , &mTextureBuffer );
66
+ glDeleteBuffers (2 , &mTexturePBOs [0 ]);
71
67
glDeleteTextures (1 , &mTexture );
68
+
72
69
// seems to be necessary as OnPaint can be called by some other thread even
73
70
// if this object is already deleted
74
71
setDrawCallback ([](DrawEvent const & /* unused*/ ) { return nullptr ; });
@@ -220,46 +217,68 @@ bool GuiItem::calculateMousePosition(int areaX, int areaY, int& x, int& y) {
220
217
221
218
// //////////////////////////////////////////////////////////////////////////////////////////////////
222
219
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;
228
223
229
- glDeleteBuffers (1 , &mTextureBuffer );
230
- glGenBuffers (1 , &mTextureBuffer );
231
- glBindBuffer (GL_TEXTURE_BUFFER, mTextureBuffer );
224
+ updateSizes ();
225
+ }
232
226
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);
237
239
238
- glDeleteTextures (1 , &mTexture );
239
- glGenTextures (1 , &mTexture );
240
240
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 ;
251
250
}
252
251
253
- return mBufferData ;
252
+ return mTexture ;
254
253
}
255
254
256
255
// //////////////////////////////////////////////////////////////////////////////////////////////////
257
256
258
- void GuiItem::onAreaResize (int width, int height) {
259
- mAreaWidth = width;
260
- mAreaHeight = height;
257
+ void GuiItem::recreateBuffers () {
261
258
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 );
263
282
}
264
283
265
284
// //////////////////////////////////////////////////////////////////////////////////////////////////
@@ -306,18 +325,4 @@ void GuiItem::updateSizes() {
306
325
307
326
// //////////////////////////////////////////////////////////////////////////////////////////////////
308
327
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
-
323
328
} // namespace cs::gui
0 commit comments