Optimize the cefclient off-screen rendering example (issue #697).

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@743 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt
2012-08-16 19:21:47 +00:00
parent 606612399c
commit a2ca607a77
4 changed files with 159 additions and 349 deletions

View File

@@ -14,82 +14,21 @@
#error Platform is not supported. #error Platform is not supported.
#endif #endif
namespace { #ifndef GL_BGR
#define GL_BGR 0x80E0
#endif
#ifndef GL_BGRA
#define GL_BGRA 0x80E1
#endif
#ifndef GL_UNSIGNED_INT_8_8_8_8_REV
#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
#endif
// Convert from BGRA to RGBA format and from upper-left to lower-left origin.
void ConvertToRGBA(const unsigned char* src, unsigned char* dst,
int width, int height) {
int sp = 0, dp = (height-1) * width * 4;
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++, dp += 4, sp += 4) {
dst[dp] = src[sp+2]; // R
dst[dp+1] = src[sp+1]; // G
dst[dp+2] = src[sp]; // B
dst[dp+3] = src[sp+3]; // A
}
dp -= width * 8;
}
}
void ConvertToRGBARect(const CefRect& clipRect,
const unsigned char* src, unsigned char* dst,
int width, int height) {
int sp = 0, dp = (height-1) * width * 4;
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++, dp += 4, sp += 4) {
if ((clipRect.x <= j) && (clipRect.x + clipRect.width > j) &&
(clipRect.y <= i) && (clipRect.y + clipRect.height > i)) {
dst[dp] = src[sp+2]; // R
dst[dp+1] = src[sp+1]; // G
dst[dp+2] = src[sp]; // B
dst[dp+3] = src[sp+3]; // A
}
}
dp -= width * 8;
}
}
// Convert from BGRA to RGB format and from upper-left to lower-left origin.
void ConvertToRGB(const unsigned char* src, unsigned char* dst,
int width, int height) {
int sp = 0, dp = (height-1) * width * 3;
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++, dp += 3, sp += 4) {
dst[dp] = src[sp+2]; // R
dst[dp+1] = src[sp+1]; // G
dst[dp+2] = src[sp]; // B
}
dp -= width * 6;
}
}
void ConvertToRGBRect(const CefRect& clipRect,
const unsigned char* src, unsigned char* dst,
int width, int height) {
int sp = 0, dp = (height-1) * width * 3;
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++, dp += 3, sp += 4) {
if ((clipRect.x <= j) && (clipRect.x + clipRect.width > j) &&
(clipRect.y <= i) && (clipRect.y + clipRect.height > i)) {
dst[dp] = src[sp+2]; // R
dst[dp+1] = src[sp+1]; // G
dst[dp+2] = src[sp]; // B
}
}
dp -= width * 6;
}
}
} // namespace
ClientOSRenderer::ClientOSRenderer(bool transparent) ClientOSRenderer::ClientOSRenderer(bool transparent)
: transparent_(transparent), : transparent_(transparent),
initialized_(false), initialized_(false),
texture_id_(0), texture_id_(0),
view_buffer_(NULL),
view_buffer_size_(0),
popup_buffer_(NULL),
popup_buffer_size_(0),
view_width_(0), view_width_(0),
view_height_(0), view_height_(0),
spin_x_(0), spin_x_(0),
@@ -104,104 +43,44 @@ void ClientOSRenderer::Initialize() {
if (initialized_) if (initialized_)
return; return;
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// Necessary for non-power-of-2 textures to render correctly. // Necessary for non-power-of-2 textures to render correctly.
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
if (transparent_) { // Create the texture.
// Alpha blending style. Texture values have premultiplied alpha. glGenTextures(1, &texture_id_);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); ASSERT(texture_id_ != 0);
}
glBindTexture(GL_TEXTURE_2D, texture_id_);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
initialized_ = true; initialized_ = true;
} }
void ClientOSRenderer::Cleanup() { void ClientOSRenderer::Cleanup() {
if (view_buffer_) {
delete [] view_buffer_;
view_buffer_ = NULL;
view_buffer_size_ = 0;
}
if (popup_buffer_) {
delete [] popup_buffer_;
popup_buffer_ = NULL;
popup_buffer_size_ = 0;
}
if (texture_id_ != 0) if (texture_id_ != 0)
glDeleteTextures(1, &texture_id_); glDeleteTextures(1, &texture_id_);
} }
void ClientOSRenderer::SetSize(int width, int height) {
if (!initialized_)
Initialize();
// Match GL units to screen coordinates.
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 0, width, height, 0.1, 100.0);
if (transparent_) {
// Enable alpha blending.
glEnable(GL_BLEND);
}
// Enable 2D textures.
glEnable(GL_TEXTURE_2D);
GLuint new_texture_id = 0;
// Create a new texture.
glGenTextures(1, &new_texture_id);
ASSERT(new_texture_id != 0);
glBindTexture(GL_TEXTURE_2D, new_texture_id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// Start with all white contents.
{
int size = width * height * (transparent_?4:3);
unsigned char* buffer = new unsigned char[size];
memset(buffer, 255, size);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
transparent_?GL_RGBA:GL_RGB, GL_UNSIGNED_BYTE, buffer);
delete [] buffer;
}
if (texture_id_ != 0) {
// Draw the existing view buffer to the new texture.
DrawViewBuffer(width, height);
// Delete the old texture.
glDeleteTextures(1, &texture_id_);
}
texture_id_ = new_texture_id;
// Disable 2D textures.
glDisable(GL_TEXTURE_2D);
if (transparent_) {
// Disable alpha blending.
glDisable(GL_BLEND);
}
}
void ClientOSRenderer::Render() { void ClientOSRenderer::Render() {
if (view_width_ == 0 || view_height_ == 0)
return;
ASSERT(initialized_); ASSERT(initialized_);
struct { struct {
float tu, tv; float tu, tv;
float x, y, z; float x, y, z;
} static vertices[] = { } static vertices[] = {
{0.0f, 0.0f, -1.0f, -1.0f, 0.0f}, {0.0f, 1.0f, -1.0f, -1.0f, 0.0f},
{1.0f, 0.0f, 1.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 1.0f, -1.0f, 0.0f},
{1.0f, 1.0f, 1.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 1.0f, 1.0f, 0.0f},
{0.0f, 1.0f, -1.0f, 1.0f, 0.0f} {0.0f, 0.0f, -1.0f, 1.0f, 0.0f}
}; };
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@@ -209,6 +88,12 @@ void ClientOSRenderer::Render() {
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glLoadIdentity(); glLoadIdentity();
// Match GL units to screen coordinates.
glViewport(0, 0, view_width_, view_height_);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 0, view_width_, view_height_, 0.1, 100.0);
// Draw the background gradient. // Draw the background gradient.
glPushAttrib(GL_ALL_ATTRIB_BITS); glPushAttrib(GL_ALL_ATTRIB_BITS);
glBegin(GL_QUADS); glBegin(GL_QUADS);
@@ -222,10 +107,15 @@ void ClientOSRenderer::Render() {
glPopAttrib(); glPopAttrib();
// Rotate the view based on the mouse spin. // Rotate the view based on the mouse spin.
if (spin_x_ != 0)
glRotatef(-spin_x_, 1.0f, 0.0f, 0.0f); glRotatef(-spin_x_, 1.0f, 0.0f, 0.0f);
if (spin_y_ != 0)
glRotatef(-spin_y_, 0.0f, 1.0f, 0.0f); glRotatef(-spin_y_, 0.0f, 1.0f, 0.0f);
if (transparent_) { if (transparent_) {
// Alpha blending style. Texture values have premultiplied alpha.
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
// Enable alpha blending. // Enable alpha blending.
glEnable(GL_BLEND); glEnable(GL_BLEND);
} }
@@ -253,34 +143,26 @@ void ClientOSRenderer::Render() {
void ClientOSRenderer::OnPopupShow(CefRefPtr<CefBrowser> browser, void ClientOSRenderer::OnPopupShow(CefRefPtr<CefBrowser> browser,
bool show) { bool show) {
if (!show) { if (!show) {
// Clear the popup buffer. // Invalidate the previous popup rectangle so that it will be repainted.
browser->Invalidate(popup_rect_);
// Clear the popup rectangle.
popup_rect_.Set(0, 0, 0, 0); popup_rect_.Set(0, 0, 0, 0);
if (popup_buffer_) {
delete [] popup_buffer_;
popup_buffer_ = NULL;
popup_buffer_size_ = 0;
}
} }
} }
void ClientOSRenderer::OnPopupSize(CefRefPtr<CefBrowser> browser, void ClientOSRenderer::OnPopupSize(CefRefPtr<CefBrowser> browser,
const CefRect& rect) { const CefRect& rect) {
if (rect.width > 0) { if (rect.width > 0 && rect.height > 0)
// Update the popup rectange. It should always be inside the view.
ASSERT(rect.x + rect.width < view_width_ &&
rect.y + rect.height < view_height_);
popup_rect_ = rect; popup_rect_ = rect;
}
} }
void ClientOSRenderer::OnPaint(CefRefPtr<CefBrowser> browser, void ClientOSRenderer::OnPaint(CefRefPtr<CefBrowser> browser,
CefRenderHandler::PaintElementType type, CefRenderHandler::PaintElementType type,
const CefRenderHandler::RectList& dirtyRects, const CefRenderHandler::RectList& dirtyRects,
const void* buffer) { const void* buffer) {
ASSERT(initialized_); if (!initialized_)
Initialize();
// Retrieve the current size of the browser view.
browser->GetSize(type, view_width_, view_height_);
if (transparent_) { if (transparent_) {
// Enable alpha blending. // Enable alpha blending.
@@ -294,46 +176,59 @@ void ClientOSRenderer::OnPaint(CefRefPtr<CefBrowser> browser,
glBindTexture(GL_TEXTURE_2D, texture_id_); glBindTexture(GL_TEXTURE_2D, texture_id_);
if (type == PET_VIEW) { if (type == PET_VIEW) {
SetBufferSize(view_width_, view_height_, true); int old_width = view_width_;
int old_height = view_height_;
// Paint the view. // Retrieve the current size of the browser view.
if (transparent_) { browser->GetSize(type, view_width_, view_height_);
CefRenderHandler::RectList::const_iterator i = dirtyRects.begin();
for (; i != dirtyRects.end(); ++i) { glPixelStorei(GL_UNPACK_ROW_LENGTH, view_width_);
ConvertToRGBARect(*i, (unsigned char*)buffer, view_buffer_,
view_width_, view_height_); if (old_width != view_width_ || old_height != view_height_) {
} // Update/resize the whole texture.
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, view_width_, view_height_, 0,
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, buffer);
} else { } else {
// Update just the dirty rectangles.
CefRenderHandler::RectList::const_iterator i = dirtyRects.begin(); CefRenderHandler::RectList::const_iterator i = dirtyRects.begin();
for (; i != dirtyRects.end(); ++i) { for (; i != dirtyRects.end(); ++i) {
ConvertToRGBRect(*i, (unsigned char*)buffer, view_buffer_, const CefRect& rect = *i;
view_width_, view_height_); glPixelStorei(GL_UNPACK_SKIP_PIXELS, rect.x);
glPixelStorei(GL_UNPACK_SKIP_ROWS, rect.y);
glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x, rect.y, rect.width,
rect.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
buffer);
} }
} }
} else if (type == PET_POPUP && popup_rect_.width > 0 &&
popup_rect_.height > 0) {
int skip_pixels = 0, x = popup_rect_.x;
int skip_rows = 0, y = popup_rect_.y;
int width = popup_rect_.width;
int height = popup_rect_.height;
// Update the whole texture. This is done for simplicity instead of // Adjust the popup to fit inside the view.
// updating just the dirty region. if (x < 0) {
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, view_width_, view_height_, skip_pixels = -x;
transparent_?GL_RGBA:GL_RGB, GL_UNSIGNED_BYTE, view_buffer_); x = 0;
} }
if (y < 0) {
skip_rows = -y;
y = 0;
}
if (x + width > view_width_)
width -= x + width - view_width_;
if (y + height > view_height_)
height -= y + height - view_height_;
if (popup_rect_.width > 0) { // Update the popup rectangle.
if (type == PET_POPUP) { glPixelStorei(GL_UNPACK_ROW_LENGTH, popup_rect_.width);
// Paint the popup. glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels);
if (transparent_) glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows);
SetRGBA(buffer, popup_rect_.width, popup_rect_.height, false); glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL_BGRA,
else GL_UNSIGNED_INT_8_8_8_8_REV, buffer);
SetRGB(buffer, popup_rect_.width, popup_rect_.height, false);
}
if (popup_buffer_) {
// Update the popup region.
glTexSubImage2D(GL_TEXTURE_2D, 0, popup_rect_.x,
view_height_ - popup_rect_.y - popup_rect_.height,
popup_rect_.width, popup_rect_.height,
transparent_?GL_RGBA:GL_RGB,
GL_UNSIGNED_BYTE, popup_buffer_);
}
} }
// Disable 2D textures. // Disable 2D textures.
@@ -354,79 +249,3 @@ void ClientOSRenderer::IncrementSpin(float spinDX, float spinDY) {
spin_x_ -= spinDX; spin_x_ -= spinDX;
spin_y_ -= spinDY; spin_y_ -= spinDY;
} }
bool ClientOSRenderer::GetPixelValue(int x, int y, unsigned char& r,
unsigned char& g, unsigned char& b,
unsigned char& a) {
if (!view_buffer_)
return false;
ASSERT(x >= 0 && x < view_width_);
ASSERT(y >= 0 && y < view_height_);
int pixel_bytes = transparent_ ? 4 : 3;
int y_flipped = view_height_ - y;
int index = (view_width_ * y_flipped * pixel_bytes) + (x * pixel_bytes);
r = view_buffer_[index];
g = view_buffer_[index+1];
b = view_buffer_[index+2];
if (transparent_)
a = view_buffer_[index+3];
return true;
}
void ClientOSRenderer::SetBufferSize(int width, int height, bool view) {
int dst_size = width * height * (transparent_?4:3);
// Allocate a new buffer if necesary.
if (view) {
if (dst_size > view_buffer_size_) {
if (view_buffer_)
delete [] view_buffer_;
view_buffer_ = new unsigned char[dst_size];
view_buffer_size_ = dst_size;
}
} else {
if (dst_size > popup_buffer_size_) {
if (popup_buffer_)
delete [] popup_buffer_;
popup_buffer_ = new unsigned char[dst_size];
popup_buffer_size_ = dst_size;
}
}
}
// Set the contents of the RGBA buffer.
void ClientOSRenderer::SetRGBA(const void* src, int width, int height,
bool view) {
SetBufferSize(width, height, view);
ConvertToRGBA((unsigned char*)src, view?view_buffer_:popup_buffer_, width,
height);
}
// Set the contents of the RGB buffer.
void ClientOSRenderer::SetRGB(const void* src, int width, int height,
bool view) {
SetBufferSize(width, height, view);
ConvertToRGB((unsigned char*)src, view?view_buffer_:popup_buffer_, width,
height);
}
void ClientOSRenderer::DrawViewBuffer(int max_width, int max_height) {
if (max_width < view_width_ || max_height < view_height_) {
// The requested max size is smaller than the current view buffer.
int width = std::min(max_width, view_width_);
int height = std::min(max_height, view_height_);
glPixelStorei(GL_UNPACK_ROW_LENGTH, view_width_);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height,
transparent_?GL_RGBA:GL_RGB, GL_UNSIGNED_BYTE,
view_buffer_);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
} else {
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, view_width_, view_height_,
transparent_?GL_RGBA:GL_RGB, GL_UNSIGNED_BYTE, view_buffer_);
}
}

View File

@@ -20,9 +20,6 @@ class ClientOSRenderer {
// Clean up the OpenGL environment. // Clean up the OpenGL environment.
void Cleanup(); void Cleanup();
// Set the size of the viewport.
void SetSize(int width, int height);
// Render to the screen. // Render to the screen.
void Render(); void Render();
@@ -40,29 +37,18 @@ class ClientOSRenderer {
void SetSpin(float spinX, float spinY); void SetSpin(float spinX, float spinY);
void IncrementSpin(float spinDX, float spinDY); void IncrementSpin(float spinDX, float spinDY);
// Retrieve the pixel value from the view buffer. |x| and |y| are relative to
// the upper-left corner of the view.
bool GetPixelValue(int x, int y, unsigned char& r, unsigned char& g,
unsigned char& b, unsigned char& a);
bool IsTransparent() { return transparent_; } bool IsTransparent() { return transparent_; }
private: int GetViewWidth() { return view_width_; }
void SetBufferSize(int width, int height, bool view); int GetViewHeight() { return view_height_; }
void SetRGBA(const void* src, int width, int height, bool view);
void SetRGB(const void* src, int width, int height, bool view);
void DrawViewBuffer(int max_width, int max_height);
private:
bool transparent_; bool transparent_;
bool initialized_; bool initialized_;
unsigned int texture_id_; unsigned int texture_id_;
unsigned char* view_buffer_;
int view_buffer_size_;
unsigned char* popup_buffer_;
int popup_buffer_size_;
CefRect popup_rect_;
int view_width_; int view_width_;
int view_height_; int view_height_;
CefRect popup_rect_;
float spin_x_; float spin_x_;
float spin_y_; float spin_y_;
}; };

View File

@@ -59,7 +59,8 @@ class ClientOSRHandler : public CefClient,
public CefRenderHandler { public CefRenderHandler {
public: public:
explicit ClientOSRHandler(ClientPlugin* plugin) explicit ClientOSRHandler(ClientPlugin* plugin)
: plugin_(plugin) { : plugin_(plugin),
want_pixel_value_(false) {
} }
~ClientOSRHandler() { ~ClientOSRHandler() {
} }
@@ -69,6 +70,21 @@ class ClientOSRHandler : public CefClient,
plugin_ = NULL; plugin_ = NULL;
} }
// Retrieve the pixel value at the requested coordinate the next time that
// the view is painted.
void WantPixelValue(int x, int y) {
if (!want_pixel_value_) {
want_pixel_value_ = true;
// Trigger a call to OnPaint.
if (g_offscreenBrowser.get())
g_offscreenBrowser->Invalidate(CefRect(0,0,1,1));
}
coord_x_ = x;
coord_y_ = y;
}
// CefClient methods // CefClient methods
virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() OVERRIDE { virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() OVERRIDE {
return this; return this;
@@ -275,6 +291,42 @@ class ClientOSRHandler : public CefClient,
wglMakeCurrent(plugin_->hDC, plugin_->hRC); wglMakeCurrent(plugin_->hDC, plugin_->hRC);
plugin_->renderer.OnPaint(browser, type, dirtyRects, buffer); plugin_->renderer.OnPaint(browser, type, dirtyRects, buffer);
plugin_->renderer.Render();
SwapBuffers(plugin_->hDC);
if (type == PET_VIEW && want_pixel_value_) {
// Retrieve the pixel value at the requested coordinate.
int width = plugin_->renderer.GetViewWidth();
int height = plugin_->renderer.GetViewHeight();
if(coord_x_ >= 0 && coord_x_ < width &&
coord_y_ >= 0 && coord_y_ < height) {
bool transparent = plugin_->renderer.IsTransparent();
int index = (width * coord_y_ * 4) + (coord_x_ * 4);
const unsigned char *pBuf = static_cast<const unsigned char*>(buffer);
unsigned char r, g, b, a;
b = pBuf[index];
g = pBuf[index+1];
r = pBuf[index+2];
if (transparent)
a = pBuf[index+3];
std::stringstream ss;
ss << coord_x_ << "," << coord_y_ << " = R:" << static_cast<int>(r)
<< " G:" << static_cast<int>(g) << " B:" << static_cast<int>(b);
if (transparent)
ss << " A:" << static_cast<int>(a);
std::string js =
"document.getElementById('pixel').innerText = '" + ss.str() + "';";
AppGetBrowser()->GetMainFrame()->ExecuteJavaScript(js, "", 0);
}
want_pixel_value_ = false;
}
} }
virtual void OnCursorChange(CefRefPtr<CefBrowser> browser, virtual void OnCursorChange(CefRefPtr<CefBrowser> browser,
@@ -303,6 +355,11 @@ class ClientOSRHandler : public CefClient,
ClientPlugin* plugin_; ClientPlugin* plugin_;
// Used for retrieving the pixel value.
bool want_pixel_value_;
int coord_x_;
int coord_y_;
// Include the default reference counting implementation. // Include the default reference counting implementation.
IMPLEMENT_REFCOUNTING(ClientOSRPlugin); IMPLEMENT_REFCOUNTING(ClientOSRPlugin);
}; };
@@ -349,23 +406,10 @@ void DisableGL(ClientPlugin* plugin) {
// Size the GL view. // Size the GL view.
void SizeGL(ClientPlugin* plugin, int width, int height) { void SizeGL(ClientPlugin* plugin, int width, int height) {
wglMakeCurrent(plugin->hDC, plugin->hRC);
plugin->renderer.SetSize(width, height);
if (g_offscreenBrowser.get()) if (g_offscreenBrowser.get())
g_offscreenBrowser->SetSize(PET_VIEW, width, height); g_offscreenBrowser->SetSize(PET_VIEW, width, height);
} }
// Render the view contents.
void RenderGL(ClientPlugin* plugin) {
wglMakeCurrent(plugin->hDC, plugin->hRC);
plugin->renderer.Render();
SwapBuffers(plugin->hDC);
}
NPError NPP_NewImpl(NPMIMEType plugin_type, NPP instance, uint16 mode, NPError NPP_NewImpl(NPMIMEType plugin_type, NPP instance, uint16 mode,
int16 argc, char* argn[], char* argv[], int16 argc, char* argn[], char* argv[],
NPSavedData* saved) { NPSavedData* saved) {
@@ -472,24 +516,12 @@ LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT message, WPARAM wParam,
reinterpret_cast<ClientPlugin*>(GetWindowLongPtr(hWnd, GWLP_USERDATA)); reinterpret_cast<ClientPlugin*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
switch (message) { switch (message) {
case WM_CREATE:
// Start the timer that's used for redrawing.
SetTimer(hWnd, 1, 20, NULL);
return 0;
case WM_DESTROY: case WM_DESTROY:
// Stop the timer that's used for redrawing.
KillTimer(hWnd, 1);
// Explicitly close the offscreen browser and release the reference. // Explicitly close the offscreen browser and release the reference.
g_offscreenBrowser->CloseBrowser(); g_offscreenBrowser->CloseBrowser();
g_offscreenBrowser = NULL; g_offscreenBrowser = NULL;
return 0; return 0;
case WM_TIMER:
RenderGL(plugin);
break;
case WM_LBUTTONDOWN: case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN: case WM_RBUTTONDOWN:
SetCapture(hWnd); SetCapture(hWnd);
@@ -503,18 +535,9 @@ LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT message, WPARAM wParam,
// Retrieve the pixel value. // Retrieve the pixel value.
int x = LOWORD(lParam); int x = LOWORD(lParam);
int y = HIWORD(lParam); int y = HIWORD(lParam);
unsigned char r, g, b, a; CefRefPtr<ClientOSRHandler> handler =
if (plugin->renderer.GetPixelValue(x, y, r, g, b, a)) { static_cast<ClientOSRHandler*>(g_offscreenBrowser->GetClient().get());
std::stringstream ss; handler->WantPixelValue(x, y);
ss << x << "," << y << " = R:" << static_cast<int>(r) << " G:" <<
static_cast<int>(g) << " B:" << static_cast<int>(b);
if (plugin->renderer.IsTransparent())
ss << " A:" << static_cast<int>(a);
std::string js =
"document.getElementById('pixel').innerText = '" + ss.str() + "';";
AppGetBrowser()->GetMainFrame()->ExecuteJavaScript(js, "", 0);
}
} else { } else {
if (g_offscreenBrowser.get()) { if (g_offscreenBrowser.get()) {
g_offscreenBrowser->SendMouseClickEvent(LOWORD(lParam), HIWORD(lParam), g_offscreenBrowser->SendMouseClickEvent(LOWORD(lParam), HIWORD(lParam),

View File

@@ -254,18 +254,13 @@ class ClientOSRHandler : public CefClient,
if (!view_) if (!view_)
return; return;
[[view_ openGLContext] makeCurrentContext]; NSOpenGLContext* context = [view_ openGLContext];
[context makeCurrentContext];
view_->renderer_->OnPaint(browser, type, dirtyRects, buffer); view_->renderer_->OnPaint(browser, type, dirtyRects, buffer);
view_->renderer_->Render();
// Notify the view to redraw the invalidated regions. [context flushBuffer];
{
RectList::const_iterator i = dirtyRects.begin();
for (; i != dirtyRects.end(); ++i) {
NSRect rect = {{i->x, i->y}, {i->width, i->height}};
[view_ setNeedsDisplayInRect:rect];
}
}
} }
virtual void OnCursorChange(CefRefPtr<CefBrowser> browser, virtual void OnCursorChange(CefRefPtr<CefBrowser> browser,
@@ -329,25 +324,12 @@ class ClientOSRHandler : public CefClient,
[super dealloc]; [super dealloc];
} }
- (void)drawRect: (NSRect)bounds {
NSOpenGLContext* context = [self openGLContext];
[context makeCurrentContext];
renderer_->Render();
[context flushBuffer];
}
- (void)setFrame:(NSRect)frameRect { - (void)setFrame:(NSRect)frameRect {
[super setFrame:frameRect]; [super setFrame:frameRect];
int width = frameRect.size.width; int width = frameRect.size.width;
int height = frameRect.size.height; int height = frameRect.size.height;
[[self openGLContext] makeCurrentContext];
renderer_->SetSize(width, height);
if (browser_) if (browser_)
browser_->SetSize(PET_VIEW, width, height); browser_->SetSize(PET_VIEW, width, height);
} }