I had a weird issue where the buffer that CEF passed to OnPaint contained garbage / was glitched when I didn't use single-process mode.
I'm using version "cef_binary_3.3325.1756.g6d8faa4_linux64_minimal" with Ogre (if that makes a difference as it maybe fails in connecting to the opengl driver or something).
My opengl driver is "OpenGL version string: 4.6.0 NVIDIA 390.48"
It looked like this:
Also when I used the approach also used in the sample program for setting the cursor I got an X11 error:
- Code: Select all
X Error of failed request: BadCursor (invalid Cursor parameter)
Major opcode of failed request: 2 (X_ChangeWindowAttributes)
Resource id in failed request: 0x780000a
Serial number of failed request: 2083
Current serial number in output stream: 2084
Edit: I have fixed this error (BadCursor) by using "cef_get_xdisplay();" instead of the one I created my window with.
All of this gets fixed if I use "--single-process" flag OR which I think it a better fix "--disable-gpu". I'm going to force disable gpu on linux for now but I'd like to know if this is a bug in CEF (or chromium) or I did something wrong.
This is how it looks with "--disable-gpu" (and the cursor changing also works):
Here's my OnPaint method:
- Code: Select all
void View::OnPaint(CefRefPtr<CefBrowser> browser, PaintElementType type,
const RectList& dirtyRects, const void* buffer, int width, int height)
{
CEF_REQUIRE_UI_THREAD();
Engine::Get()->AssertIfNotMainThread();
if(dirtyRects.empty()) {
LOG_ERROR("View: OnPaint given empty dirtyRects list");
return;
}
// Lock us, just for fun //
// As we are always on the main thread
GUARD_LOCK();
// Calculate the size of the buffer //
size_t buffSize = width * height * CEF_BYTES_PER_PIXEL;
Ogre::TexturePtr targettexture;
switch(type) {
case PET_POPUP: {
LOG_ERROR("CEF PET_POPUP not handled");
return;
}
case PET_VIEW: {
targettexture = Texture;
break;
}
default: LOG_FATAL("Unknown paint type in View: OnPaint"); return;
}
// Make sure our texture is large enough //
if(targettexture->getWidth() != static_cast<size_t>(width) ||
targettexture->getHeight() != static_cast<size_t>(height)) {
// Free resources and then change the size //
targettexture->freeInternalResources();
targettexture->setWidth(width);
targettexture->setHeight(height);
targettexture->createInternalResources();
LOG_INFO("GuiView: recreated texture for CEF browser");
}
// Copy it to our texture //
Ogre::v1::HardwarePixelBufferSharedPtr pixelBuffer = targettexture->getBuffer();
LEVIATHAN_ASSERT(
pixelBuffer->getSizeInBytes() == buffSize, "CEF and Ogre buffer size mismatch");
// Copy the data over //
const auto firstRect = dirtyRects.front();
if(dirtyRects.size() == 1 && firstRect.x == 0 && firstRect.y == 0 &&
firstRect.width == width && firstRect.height == height) {
// Can directly copy the whole thing
pixelBuffer->lock(Ogre::v1::HardwareBuffer::HBL_DISCARD);
const Ogre::PixelBox& pixelBox = pixelBuffer->getCurrentLock();
uint8_t* destptr = static_cast<uint8_t*>(pixelBox.data);
std::memcpy(destptr, buffer, buffSize);
pixelBuffer->unlock();
} else {
// Lock buffer and get a target box for writing //
pixelBuffer->lock(Ogre::v1::HardwareBuffer::HBL_NORMAL);
const Ogre::PixelBox& pixelBox = pixelBuffer->getCurrentLock();
uint32_t* destptr = static_cast<uint32_t*>(pixelBox.data);
const uint32_t* source = static_cast<const uint32_t*>(buffer);
const size_t rowElements = pixelBox.rowPitch;
for(const auto rect : dirtyRects) {
const auto lastX = rect.x + rect.width;
const auto lastY = rect.y + rect.height;
for(int y = rect.y; y < lastY; ++y) {
for(int x = rect.x; x < lastX; ++x) {
// Safety check. Comment out when not debugging
// LEVIATHAN_ASSERT(y >= 0 && y < height, "View OnPaint y out of range");
// LEVIATHAN_ASSERT(x >= 0 && x < width, "View OnPaint x out of range");
destptr[(rowElements * y) + x] = source[(y * width) + x];
}
}
}
// std::memset(destptr, 255, pixelBuffer->getSizeInBytes());
// Unlock the buffer //
pixelBuffer->unlock();
}
// // Save render result
// Ogre::Image img;
// Texture->convertToImage(img);
// static std::atomic<int> spamnumber = 0;
// img.save("Test" + std::to_string(++spamnumber) + ".png");
}