14
14
#include < cef3/cef/include/cef_task.h>
15
15
#include " CWebDevTools.h"
16
16
17
+ namespace
18
+ {
19
+ const int CEF_PIXEL_STRIDE = 4 ;
20
+ }
21
+
17
22
CWebView::CWebView (bool bIsLocal, CWebBrowserItem* pWebBrowserRenderItem, bool bTransparent)
18
23
{
19
24
m_bIsLocal = bIsLocal;
@@ -39,9 +44,6 @@ CWebView::~CWebView()
39
44
// Ensure that CefRefPtr::~CefRefPtr doesn't try to release it twice (it has already been released in CWebView::OnBeforeClose)
40
45
m_pWebView = nullptr ;
41
46
42
- // Make sure we don't dead lock the CEF render thread
43
- m_RenderData.cv .notify_all ();
44
-
45
47
OutputDebugLine (" CWebView::~CWebView" );
46
48
}
47
49
@@ -75,9 +77,6 @@ void CWebView::CloseBrowser()
75
77
// CefBrowserHost::CloseBrowser calls the destructor after the browser has been destroyed
76
78
m_bBeingDestroyed = true ;
77
79
78
- // Make sure we don't dead lock the CEF render thread
79
- m_RenderData.cv .notify_all ();
80
-
81
80
if (m_pWebView)
82
81
m_pWebView->GetHost ()->CloseBrowser (true );
83
82
}
@@ -182,15 +181,17 @@ void CWebView::ClearTexture()
182
181
IDirect3DSurface9* pD3DSurface = m_pWebBrowserRenderItem->m_pD3DRenderTargetSurface ;
183
182
if (!pD3DSurface)
184
183
return ;
185
-
186
- D3DLOCKED_RECT LockedRect;
184
+
187
185
D3DSURFACE_DESC SurfaceDesc;
186
+ if (FAILED (pD3DSurface->GetDesc (&SurfaceDesc)))
187
+ return ;
188
188
189
- pD3DSurface->GetDesc (&SurfaceDesc);
190
- pD3DSurface->LockRect (&LockedRect, NULL , 0 );
191
-
192
- memset (LockedRect.pBits , 0xFF , SurfaceDesc.Width * SurfaceDesc.Height * 4 );
193
- pD3DSurface->UnlockRect ();
189
+ D3DLOCKED_RECT LockedRect;
190
+ if (SUCCEEDED (pD3DSurface->LockRect (&LockedRect, NULL , D3DLOCK_DISCARD)))
191
+ {
192
+ memset (LockedRect.pBits , 0xFF , SurfaceDesc.Height * LockedRect.Pitch );
193
+ pD3DSurface->UnlockRect ();
194
+ }
194
195
}
195
196
196
197
void CWebView::UpdateTexture ()
@@ -210,61 +211,76 @@ void CWebView::UpdateTexture()
210
211
{
211
212
// Lock surface
212
213
D3DLOCKED_RECT LockedRect;
213
- pSurface->LockRect (&LockedRect, nullptr , 0 );
214
-
215
- // Dirty rect implementation, don't use this as loops are significantly slower than memcpy
216
- auto surfaceData = static_cast <byte*>(LockedRect.pBits );
217
- auto sourceData = static_cast <const byte*>(m_RenderData.buffer );
218
- auto pitch = LockedRect.Pitch ;
219
-
220
- // Update view area
221
- if (m_RenderData.changed )
214
+ if (SUCCEEDED (pSurface->LockRect (&LockedRect, nullptr , 0 )))
222
215
{
223
- // Update changed state
224
- m_RenderData.changed = false ;
225
-
226
- if (m_RenderData.dirtyRects .size () > 0 && m_RenderData.dirtyRects [0 ].width == m_RenderData.width &&
227
- m_RenderData.dirtyRects [0 ].height == m_RenderData.height )
216
+ // Dirty rect implementation, don't use this as loops are significantly slower than memcpy
217
+ const auto destData = static_cast <byte*>(LockedRect.pBits );
218
+ const auto sourceData = static_cast <const byte*>(m_RenderData.buffer );
219
+ const auto destPitch = LockedRect.Pitch ;
220
+ const auto sourcePitch = m_RenderData.width * CEF_PIXEL_STRIDE;
221
+
222
+ // Update view area
223
+ if (m_RenderData.changed )
228
224
{
229
- // Update whole texture
230
- memcpy (surfaceData, sourceData, m_RenderData.width * m_RenderData.height * 4 );
231
- }
232
- else
233
- {
234
- // Update dirty rects
235
- for (auto & rect : m_RenderData.dirtyRects )
225
+ // Update changed state
226
+ m_RenderData.changed = false ;
227
+
228
+ if (m_RenderData.dirtyRects .size () > 0 && m_RenderData.dirtyRects [0 ].width == m_RenderData.width &&
229
+ m_RenderData.dirtyRects [0 ].height == m_RenderData.height )
236
230
{
237
- for (int y = rect.y ; y < rect.y + rect.height ; ++y)
231
+ // Note that D3D texture size can be hardware dependent(especially with dynamic texture)
232
+ // When destination and source pitches differ we must copy pixels row by row
233
+ if (destPitch == sourcePitch)
234
+ memcpy (destData, sourceData, destPitch * m_RenderData.height );
235
+ else
238
236
{
239
- int index = y * pitch + rect.x * 4 ;
240
- memcpy (&surfaceData[index], &sourceData[index], rect.width * 4 );
237
+ for (int y = 0 ; y < m_RenderData.height ; ++y)
238
+ {
239
+ const int sourceIndex = y * sourcePitch;
240
+ const int destIndex = y * destPitch;
241
+
242
+ memcpy (&destData[destIndex], &sourceData[sourceIndex], std::min (sourcePitch, destPitch));
243
+ }
244
+ }
245
+ }
246
+ else
247
+ {
248
+ // Update dirty rects
249
+ for (const auto & rect : m_RenderData.dirtyRects )
250
+ {
251
+ for (int y = rect.y ; y < rect.y + rect.height ; ++y)
252
+ {
253
+ // Note that D3D texture size can be hardware dependent(especially with dynamic texture)
254
+ // We cannot be sure that source and destination pitches are the same
255
+ const int sourceIndex = y * sourcePitch + rect.x * CEF_PIXEL_STRIDE;
256
+ const int destIndex = y * destPitch + rect.x * CEF_PIXEL_STRIDE;
257
+
258
+ memcpy (&destData[destIndex], &sourceData[sourceIndex], rect.width * CEF_PIXEL_STRIDE);
259
+ }
241
260
}
242
261
}
243
262
}
244
- }
245
263
246
- // Update popup area (override certain areas of the view texture)
247
- bool popupSizeMismatches = m_RenderData.popupRect .x + m_RenderData.popupRect .width >= (int )m_pWebBrowserRenderItem->m_uiSizeX ||
248
- m_RenderData.popupRect .y + m_RenderData.popupRect .height >= (int )m_pWebBrowserRenderItem->m_uiSizeY ;
264
+ // Update popup area (override certain areas of the view texture)
265
+ const bool popupSizeMismatches = m_RenderData.popupRect .x + m_RenderData.popupRect .width >= (int )m_pWebBrowserRenderItem->m_uiSizeX ||
266
+ m_RenderData.popupRect .y + m_RenderData.popupRect .height >= (int )m_pWebBrowserRenderItem->m_uiSizeY ;
249
267
250
- if (m_RenderData.popupShown && !popupSizeMismatches)
251
- {
252
- auto popupPitch = m_RenderData.popupRect .width * 4 ;
253
- for (int y = 0 ; y < m_RenderData.popupRect .height ; ++y)
268
+ if (m_RenderData.popupShown && !popupSizeMismatches)
254
269
{
255
- int sourceIndex = y * popupPitch;
256
- int destIndex = (y + m_RenderData.popupRect .y ) * pitch + m_RenderData.popupRect .x * 4 ;
270
+ const auto popupPitch = m_RenderData.popupRect .width * CEF_PIXEL_STRIDE;
271
+ for (int y = 0 ; y < m_RenderData.popupRect .height ; ++y)
272
+ {
273
+ const int sourceIndex = y * popupPitch;
274
+ const int destIndex = (y + m_RenderData.popupRect .y ) * destPitch + m_RenderData.popupRect .x * CEF_PIXEL_STRIDE;
257
275
258
- memcpy (&surfaceData[destIndex], &m_RenderData.popupBuffer [sourceIndex], popupPitch);
276
+ memcpy (&destData[destIndex], &m_RenderData.popupBuffer [sourceIndex], popupPitch);
277
+ }
259
278
}
260
- }
261
279
262
- // Unlock surface
263
- pSurface->UnlockRect ();
280
+ // Unlock surface
281
+ pSurface->UnlockRect ();
282
+ }
264
283
}
265
-
266
- // Resume CEF render thread
267
- m_RenderData.cv .notify_all ();
268
284
}
269
285
270
286
void CWebView::ExecuteJavascript (const SString& strJavascriptCode)
@@ -431,9 +447,6 @@ void CWebView::Resize(const CVector2D& size)
431
447
// Send resize event to CEF
432
448
if (m_pWebView)
433
449
m_pWebView->GetHost ()->WasResized ();
434
-
435
- // Tell CEF to render a new frame
436
- m_RenderData.cv .notify_all ();
437
450
}
438
451
439
452
CVector2D CWebView::GetSize ()
@@ -661,7 +674,7 @@ void CWebView::OnPopupSize(CefRefPtr<CefBrowser> browser, const CefRect& rect)
661
674
m_RenderData.popupRect = rect;
662
675
663
676
// Resize buffer
664
- m_RenderData.popupBuffer .reset (new byte[rect.width * rect.height * 4 ]);
677
+ m_RenderData.popupBuffer .reset (new byte[rect.width * rect.height * CEF_PIXEL_STRIDE ]);
665
678
}
666
679
667
680
// //////////////////////////////////////////////////////////////////
@@ -677,31 +690,25 @@ void CWebView::OnPaint(CefRefPtr<CefBrowser> browser, CefRenderHandler::PaintEle
677
690
if (m_bBeingDestroyed)
678
691
return ;
679
692
693
+ std::unique_lock<std::mutex> lock (m_RenderData.dataMutex );
694
+
695
+ // Copy popup buffer
696
+ if (paintType == PET_POPUP)
680
697
{
681
- std::lock_guard<std::mutex> lock (m_RenderData.dataMutex );
682
-
683
- // Copy popup buffer
684
- if (paintType == PET_POPUP)
698
+ if (m_RenderData.popupBuffer )
685
699
{
686
- if (m_RenderData.popupBuffer )
687
- {
688
- memcpy (m_RenderData.popupBuffer .get (), buffer, width * height * 4 );
689
- }
690
-
691
- return ; // We don't have to wait as we've copied the buffer already
700
+ memcpy (m_RenderData.popupBuffer .get (), buffer, width * height * CEF_PIXEL_STRIDE);
692
701
}
693
702
694
- // Store render data
695
- m_RenderData.buffer = buffer;
696
- m_RenderData.width = width;
697
- m_RenderData.height = height;
698
- m_RenderData.dirtyRects = dirtyRects;
699
- m_RenderData.changed = true ;
703
+ return ; // We don't have to wait as we've copied the buffer already
700
704
}
701
705
702
- // Wait for the main thread to handle drawing the texture
703
- std::unique_lock<std::mutex> lock (m_RenderData.cvMutex );
704
- m_RenderData.cv .wait (lock);
706
+ // Store render data
707
+ m_RenderData.buffer = buffer;
708
+ m_RenderData.width = width;
709
+ m_RenderData.height = height;
710
+ m_RenderData.dirtyRects = dirtyRects;
711
+ m_RenderData.changed = true ;
705
712
}
706
713
707
714
// //////////////////////////////////////////////////////////////////
0 commit comments